• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  *
3  *  Copyright (C) 2008-2012 Broadcom Corporation
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at:
8  *
9  *  http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  ******************************************************************************/
18 
19 /******************************************************************************
20  *
21  *  this file contains the main GATT server attributes access request
22  *  handling functions.
23  *
24  ******************************************************************************/
25 
26 #include "bt_target.h"
27 
28 #include "gatt_api.h"
29 #include "gatt_int.h"
30 
31 #if BLE_INCLUDED == TRUE
32 
33 #define GATTP_MAX_NUM_INC_SVR       0
34 #define GATTP_MAX_CHAR_NUM          2
35 #define GATTP_MAX_ATTR_NUM          (GATTP_MAX_CHAR_NUM * 2 + GATTP_MAX_NUM_INC_SVR + 1)
36 #define GATTP_MAX_CHAR_VALUE_SIZE   50
37 
38 #ifndef GATTP_ATTR_DB_SIZE
39 #define GATTP_ATTR_DB_SIZE      GATT_DB_MEM_SIZE(GATTP_MAX_NUM_INC_SVR, GATTP_MAX_CHAR_NUM, GATTP_MAX_CHAR_VALUE_SIZE)
40 #endif
41 
42 static void gatt_profile_request_cback (UINT16 conn_id, UINT32 trans_id, UINT8 op_code, tGATTS_DATA *p_data);
43 static void gatt_profile_connect_cback (tGATT_IF gatt_if, BD_ADDR bda, UINT16 conn_id, BOOLEAN connected, tGATT_DISCONN_REASON reason);
44 
45 static tGATT_CBACK gatt_profile_cback =
46 {
47     gatt_profile_connect_cback,
48     NULL,
49     NULL,
50     NULL,
51     gatt_profile_request_cback,
52     NULL
53 } ;
54 
55 /*******************************************************************************
56 **
57 ** Function         gatt_profile_find_conn_id_by_bd_addr
58 **
59 ** Description      The function searches all LCB with macthing bd address
60 **
61 ** Returns          total number of clcb found.
62 **
63 *******************************************************************************/
gatt_profile_find_conn_id_by_bd_addr(BD_ADDR bda)64 UINT16 gatt_profile_find_conn_id_by_bd_addr(BD_ADDR bda)
65 {
66     UINT8 i_clcb;
67     tGATT_PROFILE_CLCB    *p_clcb = NULL;
68 
69     for (i_clcb = 0, p_clcb= gatt_cb.profile_clcb; i_clcb < GATT_MAX_APPS; i_clcb++, p_clcb++)
70     {
71         if (p_clcb->in_use && p_clcb->connected && !memcmp(p_clcb->bda, bda, BD_ADDR_LEN))
72         {
73             return p_clcb->conn_id;
74         }
75     }
76 
77     return GATT_INVALID_CONN_ID;
78 }
79 
80 /*******************************************************************************
81 **
82 ** Function         gatt_profile_find_clcb_by_bd_addr
83 **
84 ** Description      The function searches all LCBs with macthing bd address.
85 **
86 ** Returns          Pointer to the found link conenction control block.
87 **
88 *******************************************************************************/
gatt_profile_find_clcb_by_bd_addr(BD_ADDR bda)89 tGATT_PROFILE_CLCB *gatt_profile_find_clcb_by_bd_addr(BD_ADDR bda)
90 {
91     UINT8 i_clcb;
92     tGATT_PROFILE_CLCB    *p_clcb = NULL;
93 
94     for (i_clcb = 0, p_clcb= gatt_cb.profile_clcb; i_clcb < GATT_MAX_APPS; i_clcb++, p_clcb++)
95     {
96         if (p_clcb->in_use && p_clcb->connected && !memcmp(p_clcb->bda, bda, BD_ADDR_LEN))
97         {
98             return p_clcb;
99         }
100     }
101 
102     return p_clcb;
103 }
104 
105 /*******************************************************************************
106 **
107 ** Function         gatt_profile_clcb_alloc
108 **
109 ** Description      The function allocates a GATT profile  connection link control block
110 **
111 ** Returns           NULL if not found. Otherwise pointer to the connection link block.
112 **
113 *******************************************************************************/
gatt_profile_clcb_alloc(UINT16 conn_id,BD_ADDR bda)114 tGATT_PROFILE_CLCB *gatt_profile_clcb_alloc (UINT16 conn_id, BD_ADDR bda)
115 {
116     UINT8                   i_clcb = 0;
117     tGATT_PROFILE_CLCB      *p_clcb = NULL;
118 
119     for (i_clcb = 0, p_clcb= gatt_cb.profile_clcb; i_clcb < GATT_MAX_APPS; i_clcb++, p_clcb++)
120     {
121         if (!p_clcb->in_use)
122         {
123             p_clcb->in_use      = TRUE;
124             p_clcb->conn_id     = conn_id;
125             p_clcb->connected   = TRUE;
126             memcpy (p_clcb->bda, bda, BD_ADDR_LEN);
127             break;
128         }
129     }
130     return p_clcb;
131 }
132 /*******************************************************************************
133 **
134 ** Function         gatt_profile_clcb_dealloc
135 **
136 ** Description      The function deallocates a GATT profile  connection link control block
137 **
138 ** Returns           NTrue the deallocation is successful
139 **
140 *******************************************************************************/
gatt_profile_clcb_dealloc(UINT16 conn_id)141 BOOLEAN gatt_profile_clcb_dealloc (UINT16 conn_id)
142 {
143     UINT8                   i_clcb = 0;
144     tGATT_PROFILE_CLCB      *p_clcb = NULL;
145 
146     for (i_clcb = 0, p_clcb= gatt_cb.profile_clcb; i_clcb < GATT_MAX_APPS; i_clcb++, p_clcb++)
147     {
148         if (p_clcb->in_use && p_clcb->connected && (p_clcb->conn_id == conn_id))
149         {
150             memset(p_clcb, 0, sizeof(tGATT_PROFILE_CLCB));
151             return TRUE;
152         }
153     }
154     return FALSE;
155 }
156 
157 
158 /*******************************************************************************
159 **
160 ** Function         gatt_profile_request_cback
161 **
162 ** Description      GATT profile attribute access request callback.
163 **
164 ** Returns          void.
165 **
166 *******************************************************************************/
gatt_profile_request_cback(UINT16 conn_id,UINT32 trans_id,tGATTS_REQ_TYPE type,tGATTS_DATA * p_data)167 static void gatt_profile_request_cback (UINT16 conn_id, UINT32 trans_id, tGATTS_REQ_TYPE type,
168                                         tGATTS_DATA *p_data)
169 {
170     UINT8       status = GATT_INVALID_PDU;
171     tGATTS_RSP   rsp_msg ;
172     BOOLEAN     ignore = FALSE;
173 
174     memset(&rsp_msg, 0, sizeof(tGATTS_RSP));
175 
176     switch (type)
177     {
178         case GATTS_REQ_TYPE_READ:
179             status = GATT_READ_NOT_PERMIT;
180             break;
181 
182         case GATTS_REQ_TYPE_WRITE:
183             status = GATT_WRITE_NOT_PERMIT;
184             break;
185 
186         case GATTS_REQ_TYPE_WRITE_EXEC:
187         case GATT_CMD_WRITE:
188             ignore = TRUE;
189             GATT_TRACE_EVENT0("Ignore GATT_REQ_EXEC_WRITE/WRITE_CMD" );
190             break;
191 
192         case GATTS_REQ_TYPE_MTU:
193             GATT_TRACE_EVENT1("Get MTU exchange new mtu size: %d", p_data->mtu);
194             ignore = TRUE;
195             break;
196 
197         default:
198             GATT_TRACE_EVENT1("Unknown/unexpected LE GAP ATT request: 0x%02x", type);
199             break;
200     }
201 
202     if (!ignore)
203         GATTS_SendRsp (conn_id, trans_id, status, &rsp_msg);
204 
205 }
206 
207 /*******************************************************************************
208 **
209 ** Function         gatt_profile_connect_cback
210 **
211 ** Description      Gatt profile connection callback.
212 **
213 ** Returns          void
214 **
215 *******************************************************************************/
gatt_profile_connect_cback(tGATT_IF gatt_if,BD_ADDR bda,UINT16 conn_id,BOOLEAN connected,tGATT_DISCONN_REASON reason)216 static void gatt_profile_connect_cback (tGATT_IF gatt_if, BD_ADDR bda, UINT16 conn_id,
217                                         BOOLEAN connected, tGATT_DISCONN_REASON reason)
218 {
219     GATT_TRACE_EVENT5 ("gatt_profile_connect_cback: from %08x%04x connected:%d conn_id=%d reason = 0x%04x",
220                        (bda[0]<<24)+(bda[1]<<16)+(bda[2]<<8)+bda[3],
221                        (bda[4]<<8)+bda[5], connected, conn_id, reason);
222 
223     if (connected)
224     {
225         if (gatt_profile_clcb_alloc(conn_id, bda) == NULL)
226         {
227             GATT_TRACE_ERROR0 ("gatt_profile_connect_cback: no_resource");
228             return;
229         }
230     }
231     else
232     {
233         gatt_profile_clcb_dealloc(conn_id);
234     }
235 
236 }
237 
238 /*******************************************************************************
239 **
240 ** Function         gatt_profile_db_init
241 **
242 ** Description      Initializa the GATT profile attribute database.
243 **
244 *******************************************************************************/
gatt_profile_db_init(void)245 void gatt_profile_db_init (void)
246 {
247     tBT_UUID          app_uuid = {LEN_UUID_128, {0}};
248     tBT_UUID          uuid = {LEN_UUID_16, {UUID_SERVCLASS_GATT_SERVER}};
249     UINT16            service_handle = 0;
250     tGATT_STATUS      status;
251 
252     /* Fill our internal UUID with a fixed pattern 0x81 */
253     memset (&app_uuid.uu.uuid128, 0x81, LEN_UUID_128);
254 
255 
256     /* Create a GATT profile service */
257     gatt_cb.gatt_if = GATT_Register(&app_uuid, &gatt_profile_cback);
258     GATT_StartIf(gatt_cb.gatt_if);
259 
260     service_handle = GATTS_CreateService (gatt_cb.gatt_if , &uuid, 0, GATTP_MAX_ATTR_NUM, TRUE);
261     /* add Service Changed characteristic
262     */
263     uuid.uu.uuid16 = gatt_cb.gattp_attr.uuid = GATT_UUID_GATT_SRV_CHGD;
264     gatt_cb.gattp_attr.service_change = 0;
265     gatt_cb.gattp_attr.handle   =
266     gatt_cb.handle_of_h_r       = GATTS_AddCharacteristic(service_handle, &uuid, 0, GATT_CHAR_PROP_BIT_INDICATE);
267 
268     GATT_TRACE_DEBUG1 ("gatt_profile_db_init:  handle of service changed%d",
269                        gatt_cb.handle_of_h_r  );
270 
271     /* start service
272     */
273     status = GATTS_StartService (gatt_cb.gatt_if, service_handle, GATTP_TRANSPORT_SUPPORTED );
274 
275     GATT_TRACE_DEBUG2 ("gatt_profile_db_init:  gatt_if=%d   start status%d",
276                        gatt_cb.gatt_if,  status);
277 }
278 
279 #endif  /* BLE_INCLUDED */
280