1 /******************************************************************************
2  *
3  *  Copyright (C) 2003-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 GATT client utility function.
22  *
23  ******************************************************************************/
24 
25 #include "bt_target.h"
26 
27 #if defined(BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE)
28 
29 #include <string.h>
30 
31 #include "btcore/include/bdaddr.h"
32 #include "btif/include/btif_util.h"
33 #include "gki.h"
34 #include "utl.h"
35 #include "bta_sys.h"
36 #include "bta_gattc_int.h"
37 #include "l2c_api.h"
38 
39 #define LOG_TAG "bt_bta_gattc"
40 /*****************************************************************************
41 **  Constants
42 *****************************************************************************/
43 
44 
45 static const UINT8  base_uuid[LEN_UUID_128] = {0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x00, 0x00, 0x80,
46     0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
47 
48 static const BD_ADDR dummy_bda = {0,0,0,0,0,0};
49 
50 /*******************************************************************************
51 **
52 ** Function         bta_gatt_convert_uuid16_to_uuid128
53 **
54 ** Description      Convert a 16 bits UUID to be an standard 128 bits one.
55 **
56 ** Returns          TRUE if two uuid match; FALSE otherwise.
57 **
58 *******************************************************************************/
bta_gatt_convert_uuid16_to_uuid128(UINT8 uuid_128[LEN_UUID_128],UINT16 uuid_16)59 void bta_gatt_convert_uuid16_to_uuid128(UINT8 uuid_128[LEN_UUID_128], UINT16 uuid_16)
60 {
61     UINT8   *p = &uuid_128[LEN_UUID_128 - 4];
62 
63     memcpy (uuid_128, base_uuid, LEN_UUID_128);
64 
65     UINT16_TO_STREAM(p, uuid_16);
66 }
67 /*******************************************************************************
68 **
69 ** Function         bta_gattc_uuid_compare
70 **
71 ** Description      Compare two UUID to see if they are the same.
72 **
73 ** Returns          TRUE if two uuid match; FALSE otherwise.
74 **
75 *******************************************************************************/
bta_gattc_uuid_compare(tBT_UUID * p_src,tBT_UUID * p_tar,BOOLEAN is_precise)76 BOOLEAN bta_gattc_uuid_compare (tBT_UUID *p_src, tBT_UUID *p_tar, BOOLEAN is_precise)
77 {
78     UINT8  su[LEN_UUID_128], tu[LEN_UUID_128];
79     UINT8  *ps, *pt;
80 
81     /* any of the UUID is unspecified */
82     if (p_src == 0 || p_tar == 0)
83     {
84         if (is_precise)
85             return FALSE;
86         else
87             return TRUE;
88     }
89 
90     /* If both are 16-bit, we can do a simple compare */
91     if (p_src->len == 2 && p_tar->len == 2)
92     {
93         return p_src->uu.uuid16 == p_tar->uu.uuid16;
94     }
95 
96     /* One or both of the UUIDs is 128-bit */
97     if (p_src->len == LEN_UUID_16)
98     {
99         /* convert a 16 bits UUID to 128 bits value */
100         bta_gatt_convert_uuid16_to_uuid128(su, p_src->uu.uuid16);
101         ps = su;
102     }
103     else
104         ps = p_src->uu.uuid128;
105 
106     if (p_tar->len == LEN_UUID_16)
107     {
108         /* convert a 16 bits UUID to 128 bits value */
109         bta_gatt_convert_uuid16_to_uuid128(tu, p_tar->uu.uuid16);
110         pt = tu;
111     }
112     else
113         pt = p_tar->uu.uuid128;
114 
115     return(memcmp(ps, pt, LEN_UUID_128) == 0);
116 }
117 
118 /*******************************************************************************
119 **
120 ** Function         bta_gattc_cl_get_regcb
121 **
122 ** Description      get registration control block by client interface.
123 **
124 ** Returns          pointer to the regcb
125 **
126 *******************************************************************************/
bta_gattc_cl_get_regcb(UINT8 client_if)127 tBTA_GATTC_RCB * bta_gattc_cl_get_regcb(UINT8 client_if)
128 {
129     UINT8   i = 0;
130     tBTA_GATTC_RCB  *p_clrcb = &bta_gattc_cb.cl_rcb[0];
131 
132     for (i = 0; i < BTA_GATTC_CL_MAX; i ++, p_clrcb ++)
133     {
134         if (p_clrcb->in_use &&
135             p_clrcb->client_if == client_if)
136             return p_clrcb;
137     }
138     return NULL;
139 }
140 /*******************************************************************************
141 **
142 ** Function         bta_gattc_num_reg_app
143 **
144 ** Description      find the number of registered application.
145 **
146 ** Returns          pointer to the regcb
147 **
148 *******************************************************************************/
bta_gattc_num_reg_app(void)149 UINT8 bta_gattc_num_reg_app(void)
150 {
151     UINT8   i = 0, j = 0;
152 
153     for (i = 0; i < BTA_GATTC_CL_MAX; i ++)
154     {
155         if (bta_gattc_cb.cl_rcb[i].in_use)
156             j ++;
157     }
158     return j;
159 }
160 /*******************************************************************************
161 **
162 ** Function         bta_gattc_find_clcb_by_cif
163 **
164 ** Description      get clcb by client interface and remote bd adddress
165 **
166 ** Returns          pointer to the clcb
167 **
168 *******************************************************************************/
bta_gattc_find_clcb_by_cif(UINT8 client_if,BD_ADDR remote_bda,tBTA_TRANSPORT transport)169 tBTA_GATTC_CLCB * bta_gattc_find_clcb_by_cif (UINT8 client_if, BD_ADDR remote_bda,
170                                               tBTA_TRANSPORT transport)
171 {
172     tBTA_GATTC_CLCB *p_clcb = &bta_gattc_cb.clcb[0];
173     UINT8   i;
174 
175     for (i = 0; i < BTA_GATTC_CLCB_MAX; i ++, p_clcb ++)
176     {
177         if (p_clcb->in_use &&
178             p_clcb->p_rcb->client_if == client_if &&
179             p_clcb->transport == transport &&
180             bdcmp(p_clcb->bda, remote_bda) == 0)
181             return p_clcb;
182     }
183     return NULL;
184 }
185 /*******************************************************************************
186 **
187 ** Function         bta_gattc_find_clcb_by_conn_id
188 **
189 ** Description      get clcb by connection ID
190 **
191 ** Returns          pointer to the clcb
192 **
193 *******************************************************************************/
bta_gattc_find_clcb_by_conn_id(UINT16 conn_id)194 tBTA_GATTC_CLCB * bta_gattc_find_clcb_by_conn_id (UINT16 conn_id)
195 {
196     tBTA_GATTC_CLCB *p_clcb = &bta_gattc_cb.clcb[0];
197     UINT8 i;
198 
199     for (i = 0; i < BTA_GATTC_CLCB_MAX; i ++, p_clcb ++)
200     {
201         if (p_clcb->in_use &&
202             p_clcb->bta_conn_id == conn_id)
203             return p_clcb;
204     }
205     return NULL;
206 }
207 
208 /*******************************************************************************
209 **
210 ** Function         bta_gattc_clcb_alloc
211 **
212 ** Description      allocate CLCB
213 **
214 ** Returns          pointer to the clcb
215 **
216 *******************************************************************************/
bta_gattc_clcb_alloc(tBTA_GATTC_IF client_if,BD_ADDR remote_bda,tBTA_TRANSPORT transport)217 tBTA_GATTC_CLCB * bta_gattc_clcb_alloc(tBTA_GATTC_IF client_if, BD_ADDR remote_bda,
218                                        tBTA_TRANSPORT transport)
219 {
220     UINT8               i_clcb = 0;
221     tBTA_GATTC_CLCB     *p_clcb = NULL;
222 
223     for (i_clcb = 0; i_clcb < BTA_GATTC_CLCB_MAX; i_clcb++)
224     {
225         if (!bta_gattc_cb.clcb[i_clcb].in_use)
226         {
227 #if BTA_GATT_DEBUG == TRUE
228             APPL_TRACE_DEBUG("bta_gattc_clcb_alloc: found clcb[%d] available",i_clcb);
229 #endif
230             p_clcb                  = &bta_gattc_cb.clcb[i_clcb];
231             p_clcb->in_use          = TRUE;
232             p_clcb->status          = BTA_GATT_OK;
233             p_clcb->transport       = transport;
234             bdcpy(p_clcb->bda, remote_bda);
235 
236             p_clcb->p_rcb = bta_gattc_cl_get_regcb(client_if);
237 
238             if ((p_clcb->p_srcb = bta_gattc_find_srcb(remote_bda)) == NULL)
239                 p_clcb->p_srcb      = bta_gattc_srcb_alloc(remote_bda);
240 
241             if (p_clcb->p_rcb != NULL && p_clcb->p_srcb != NULL)
242             {
243                 p_clcb->p_srcb->num_clcb ++;
244                 p_clcb->p_rcb->num_clcb ++;
245             }
246             else
247             {
248                 /* release this clcb if clcb or srcb allocation failed */
249                 p_clcb->in_use = FALSE;
250                 p_clcb = NULL;
251             }
252             break;
253         }
254     }
255     return p_clcb;
256 }
257 /*******************************************************************************
258 **
259 ** Function         bta_gattc_find_alloc_clcb
260 **
261 ** Description      find or allocate CLCB if not found.
262 **
263 ** Returns          pointer to the clcb
264 **
265 *******************************************************************************/
bta_gattc_find_alloc_clcb(tBTA_GATTC_IF client_if,BD_ADDR remote_bda,tBTA_TRANSPORT transport)266 tBTA_GATTC_CLCB *bta_gattc_find_alloc_clcb(tBTA_GATTC_IF client_if, BD_ADDR remote_bda,
267                                            tBTA_TRANSPORT transport)
268 {
269     tBTA_GATTC_CLCB *p_clcb ;
270 
271     if ((p_clcb = bta_gattc_find_clcb_by_cif(client_if, remote_bda, transport)) == NULL)
272     {
273         p_clcb = bta_gattc_clcb_alloc(client_if, remote_bda, transport);
274     }
275     return p_clcb;
276 }
277 
278 /*******************************************************************************
279 **
280 ** Function         bta_gattc_clcb_dealloc
281 **
282 ** Description      Deallocte a clcb
283 **
284 ** Returns          pointer to the clcb
285 **
286 *******************************************************************************/
bta_gattc_clcb_dealloc(tBTA_GATTC_CLCB * p_clcb)287 void bta_gattc_clcb_dealloc(tBTA_GATTC_CLCB *p_clcb)
288 {
289     tBTA_GATTC_SERV     *p_srcb = NULL;
290 
291     if (p_clcb)
292     {
293         p_srcb = p_clcb->p_srcb;
294         if (p_srcb->num_clcb)
295             p_srcb->num_clcb --;
296 
297         if (p_clcb->p_rcb->num_clcb)
298             p_clcb->p_rcb->num_clcb --;
299 
300         /* if the srcb is no longer needed, reset the state */
301         if ( p_srcb->num_clcb == 0)
302         {
303             p_srcb->connected = FALSE;
304             p_srcb->state = BTA_GATTC_SERV_IDLE;
305             p_srcb->mtu = 0;
306         }
307 
308         utl_freebuf((void **)&p_clcb->p_q_cmd);
309 
310         memset(p_clcb, 0, sizeof(tBTA_GATTC_CLCB));
311     }
312     else
313     {
314         APPL_TRACE_ERROR("bta_gattc_clcb_dealloc p_clcb=NULL");
315     }
316 }
317 
318 /*******************************************************************************
319 **
320 ** Function         bta_gattc_find_srcb
321 **
322 ** Description      find server cache by remote bd address currently in use
323 **
324 ** Returns          pointer to the server cache.
325 **
326 *******************************************************************************/
bta_gattc_find_srcb(BD_ADDR bda)327 tBTA_GATTC_SERV * bta_gattc_find_srcb(BD_ADDR bda)
328 {
329     tBTA_GATTC_SERV *p_srcb = &bta_gattc_cb.known_server[0];
330     UINT8   i;
331 
332     for (i = 0; i < BTA_GATTC_KNOWN_SR_MAX; i ++, p_srcb ++)
333     {
334         if (p_srcb->in_use && bdcmp(p_srcb->server_bda, bda) == 0)
335             return p_srcb;
336     }
337     return NULL;
338 }
339 
340 /*******************************************************************************
341 **
342 ** Function         bta_gattc_find_srvr_cache
343 **
344 ** Description      find server cache by remote bd address
345 **
346 ** Returns          pointer to the server cache.
347 **
348 *******************************************************************************/
bta_gattc_find_srvr_cache(BD_ADDR bda)349 tBTA_GATTC_SERV * bta_gattc_find_srvr_cache(BD_ADDR bda)
350 {
351     tBTA_GATTC_SERV *p_srcb = &bta_gattc_cb.known_server[0];
352     UINT8   i;
353 
354     for (i = 0; i < BTA_GATTC_KNOWN_SR_MAX; i ++, p_srcb ++)
355     {
356         if (bdcmp(p_srcb->server_bda, bda) == 0)
357             return p_srcb;
358     }
359     return NULL;
360 }
361 /*******************************************************************************
362 **
363 ** Function         bta_gattc_find_scb_by_cid
364 **
365 ** Description      find server control block by connection ID
366 **
367 ** Returns          pointer to the server cache.
368 **
369 *******************************************************************************/
bta_gattc_find_scb_by_cid(UINT16 conn_id)370 tBTA_GATTC_SERV * bta_gattc_find_scb_by_cid (UINT16 conn_id)
371 {
372     tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
373 
374     if (p_clcb)
375         return p_clcb->p_srcb;
376     else
377         return NULL;
378 }
379 /*******************************************************************************
380 **
381 ** Function         bta_gattc_srcb_alloc
382 **
383 ** Description      allocate server cache control block
384 **
385 ** Returns          pointer to the server cache.
386 **
387 *******************************************************************************/
bta_gattc_srcb_alloc(BD_ADDR bda)388 tBTA_GATTC_SERV * bta_gattc_srcb_alloc(BD_ADDR bda)
389 {
390     tBTA_GATTC_SERV *p_tcb = &bta_gattc_cb.known_server[0],
391                              *p_recycle = NULL;
392     BOOLEAN         found = FALSE;
393     UINT8           i;
394 
395     for (i = 0; i < BTA_GATTC_KNOWN_SR_MAX; i ++, p_tcb ++)
396     {
397         if (!p_tcb->in_use)
398         {
399             found = TRUE;
400             break;
401         }
402         else if (!p_tcb->connected)
403         {
404             p_recycle = p_tcb;
405         }
406     }
407 
408     /* if not found, try to recycle one known device */
409     if (!found && !p_recycle)
410         p_tcb = NULL;
411     else if (!found && p_recycle)
412         p_tcb = p_recycle;
413 
414     if (p_tcb != NULL)
415     {
416         while (!GKI_queue_is_empty(&p_tcb->cache_buffer))
417             GKI_freebuf (GKI_dequeue (&p_tcb->cache_buffer));
418 
419         utl_freebuf((void **)&p_tcb->p_srvc_list);
420         memset(p_tcb, 0 , sizeof(tBTA_GATTC_SERV));
421 
422         p_tcb->in_use = TRUE;
423         bdcpy(p_tcb->server_bda, bda);
424     }
425     return p_tcb;
426 }
427 /*******************************************************************************
428 **
429 ** Function         bta_gattc_enqueue
430 **
431 ** Description      enqueue a client request in clcb.
432 **
433 ** Returns          success or failure.
434 **
435 *******************************************************************************/
bta_gattc_enqueue(tBTA_GATTC_CLCB * p_clcb,tBTA_GATTC_DATA * p_data)436 BOOLEAN bta_gattc_enqueue(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
437 {
438 
439  if (p_clcb->p_q_cmd == NULL)
440  {
441      p_clcb->p_q_cmd = p_data;
442  }
443  else
444  {
445      APPL_TRACE_ERROR("already has a pending command!!");
446      /* skip the callback now. ----- need to send callback ? */
447  }
448  return (p_clcb->p_q_cmd != NULL) ? TRUE : FALSE;
449 
450 }
451 
452 /*******************************************************************************
453 **
454 ** Function         bta_gattc_pack_attr_uuid
455 **
456 ** Description      pack UUID into a stream.
457 **
458 ** Returns
459 **
460 *******************************************************************************/
bta_gattc_pack_attr_uuid(tBTA_GATTC_CACHE_ATTR * p_attr,tBT_UUID * p_uuid)461 void bta_gattc_pack_attr_uuid(tBTA_GATTC_CACHE_ATTR   *p_attr, tBT_UUID *p_uuid)
462 {
463     UINT8 *pp = (UINT8 *)p_attr->p_uuid;
464 
465     memset(p_uuid, 0, sizeof(tBT_UUID));
466 
467     p_uuid->len = p_attr->uuid_len;
468 
469     if (p_attr->uuid_len == LEN_UUID_16)
470     {
471         STREAM_TO_UINT16(p_uuid->uu.uuid16, pp);
472     }
473     else
474     {
475         memcpy(p_uuid->uu.uuid128, pp, LEN_UUID_128);
476     }
477 
478     return;
479 }
480 /*******************************************************************************
481 **
482 ** Function         bta_gattc_cpygattid
483 **
484 ** Description      copy two tBTA_GATT_ID value
485 **
486 ** Returns
487 **
488 *******************************************************************************/
bta_gattc_cpygattid(tBTA_GATT_ID * p_des,tBTA_GATT_ID * p_src)489 void bta_gattc_cpygattid(tBTA_GATT_ID *p_des, tBTA_GATT_ID *p_src)
490 {
491     memset ((void *)p_des, 0, sizeof(tBTA_GATT_ID));
492 
493     p_des->inst_id = p_src->inst_id;
494 
495     p_des->uuid.len = p_src->uuid.len;
496 
497     if (p_des->uuid.len == LEN_UUID_16)
498     {
499         p_des->uuid.uu.uuid16 = p_src->uuid.uu.uuid16;
500     }
501     else if (p_des->uuid.len == LEN_UUID_128)
502     {
503         memcpy(p_des->uuid.uu.uuid128, p_src->uuid.uu.uuid128, LEN_UUID_128);
504     }
505 }
506 /*******************************************************************************
507 **
508 ** Function         bta_gattc_gattid_compare
509 **
510 ** Description      compare two tBTA_GATT_ID type of pointer
511 **
512 ** Returns
513 **
514 *******************************************************************************/
bta_gattc_gattid_compare(tBTA_GATT_ID * p_src,tBTA_GATT_ID * p_tar)515 BOOLEAN bta_gattc_gattid_compare(tBTA_GATT_ID *p_src, tBTA_GATT_ID *p_tar)
516 {
517     if (p_src->inst_id == p_tar->inst_id &&
518         bta_gattc_uuid_compare (&p_src->uuid, &p_tar->uuid, TRUE ))
519         return TRUE;
520     else
521         return FALSE;
522 
523 }
524 /*******************************************************************************
525 **
526 ** Function         bta_gattc_srvcid_compare
527 **
528 ** Description      compare two tBTA_GATT_SRVC_ID type of pointer
529 **
530 ** Returns
531 **
532 *******************************************************************************/
bta_gattc_srvcid_compare(tBTA_GATT_SRVC_ID * p_src,tBTA_GATT_SRVC_ID * p_tar)533 BOOLEAN bta_gattc_srvcid_compare(tBTA_GATT_SRVC_ID *p_src, tBTA_GATT_SRVC_ID *p_tar)
534 {
535     if (p_src->is_primary == p_tar->is_primary &&
536         bta_gattc_gattid_compare (&p_src->id, &p_tar->id))
537         return TRUE;
538     else
539         return FALSE;
540 }
541 /*******************************************************************************
542 **
543 ** Function         bta_gattc_charid_compare
544 **
545 ** Description      compare two tBTA_GATTC_CHAR_ID type of pointer
546 **
547 ** Returns
548 **
549 *******************************************************************************/
bta_gattc_charid_compare(tBTA_GATTC_CHAR_ID * p_src,tBTA_GATTC_CHAR_ID * p_tar)550 BOOLEAN bta_gattc_charid_compare(tBTA_GATTC_CHAR_ID *p_src, tBTA_GATTC_CHAR_ID *p_tar)
551 {
552     if (bta_gattc_gattid_compare (&p_src->char_id, &p_tar->char_id) &&
553         bta_gattc_srvcid_compare (&p_src->srvc_id, &p_tar->srvc_id))
554         return TRUE;
555     else
556         return FALSE;
557 }
558 
559 /*******************************************************************************
560 **
561 ** Function         bta_gattc_check_notif_registry
562 **
563 ** Description      check if the service notificaition has been registered.
564 **
565 ** Returns
566 **
567 *******************************************************************************/
bta_gattc_check_notif_registry(tBTA_GATTC_RCB * p_clreg,tBTA_GATTC_SERV * p_srcb,tBTA_GATTC_NOTIFY * p_notify)568 BOOLEAN bta_gattc_check_notif_registry(tBTA_GATTC_RCB  *p_clreg, tBTA_GATTC_SERV *p_srcb,
569                                        tBTA_GATTC_NOTIFY  *p_notify)
570 {
571     UINT8           i;
572 
573     for (i = 0 ; i < BTA_GATTC_NOTIF_REG_MAX; i ++)
574     {
575         if (p_clreg->notif_reg[i].in_use &&
576             bdcmp(p_clreg->notif_reg[i].remote_bda, p_srcb->server_bda) == 0 &&
577             bta_gattc_charid_compare (&p_clreg->notif_reg[i].char_id, &p_notify->char_id))
578         {
579             APPL_TRACE_DEBUG("Notification registered!");
580             return TRUE;
581         }
582     }
583     return FALSE;
584 
585 }
586 /*******************************************************************************
587 **
588 ** Function         bta_gattc_clear_notif_registration
589 **
590 ** Description      clear up the notification registration information by BD_ADDR.
591 **
592 ** Returns          None.
593 **
594 *******************************************************************************/
bta_gattc_clear_notif_registration(UINT16 conn_id)595 void bta_gattc_clear_notif_registration(UINT16 conn_id)
596 {
597     BD_ADDR             remote_bda;
598     tBTA_GATTC_IF       gatt_if;
599     tBTA_GATTC_RCB      *p_clrcb ;
600     UINT8       i;
601     tGATT_TRANSPORT     transport;
602 
603     if (GATT_GetConnectionInfor(conn_id, &gatt_if, remote_bda, &transport))
604     {
605         if ((p_clrcb = bta_gattc_cl_get_regcb(gatt_if)) != NULL)
606         {
607             for (i = 0 ; i < BTA_GATTC_NOTIF_REG_MAX; i ++)
608             {
609                 if (p_clrcb->notif_reg[i].in_use &&
610                     !bdcmp(p_clrcb->notif_reg[i].remote_bda, remote_bda))
611                     memset(&p_clrcb->notif_reg[i], 0, sizeof(tBTA_GATTC_NOTIF_REG));
612             }
613         }
614     }
615     else
616     {
617         APPL_TRACE_ERROR("can not clear indication/notif registration for unknown app");
618     }
619     return;
620 }
621 
622 /*******************************************************************************
623 **
624 ** Function         bta_gattc_pack_cb_data
625 **
626 ** Description      pack the data from read response into callback data structure.
627 **
628 ** Returns
629 **
630 *******************************************************************************/
bta_gattc_pack_read_cb_data(tBTA_GATTC_SERV * p_srcb,tBT_UUID * p_descr_uuid,tGATT_VALUE * p_attr,tBTA_GATT_READ_VAL * p_value)631 tBTA_GATT_STATUS bta_gattc_pack_read_cb_data(tBTA_GATTC_SERV *p_srcb,
632                                              tBT_UUID *p_descr_uuid,
633                                              tGATT_VALUE *p_attr,
634                                              tBTA_GATT_READ_VAL *p_value)
635 {
636     UINT8                   i = 0, *pp = p_attr->value;
637     tBT_UUID                uuid = {LEN_UUID_16, {GATT_UUID_CHAR_AGG_FORMAT}};
638     UINT16                  handle;
639     tBTA_GATT_STATUS        status = BTA_GATT_OK;
640 
641     /* GATT_UUID_CHAR_AGG_FORMAT */
642     if (bta_gattc_uuid_compare (&uuid, p_descr_uuid, TRUE))
643     {
644         while (p_attr->len >= 2 && i < BTA_GATTC_MULTI_MAX)
645         {
646             STREAM_TO_UINT16(handle, pp);
647 
648             if (bta_gattc_handle2id(p_srcb,
649                                     handle,
650                                     &p_value->aggre_value.pre_format[i].char_id.srvc_id,
651                                     &p_value->aggre_value.pre_format[i].char_id.char_id,
652                                     &p_value->aggre_value.pre_format[i].descr_id) == FALSE)
653             {
654                 status = BTA_GATT_INTERNAL_ERROR;
655                 APPL_TRACE_ERROR("can not map to GATT ID. handle = 0x%04x", handle);
656                 break;
657             }
658             i ++;
659             p_attr->len -= 2;
660         }
661         p_value->aggre_value.num_pres_fmt = i;
662     }
663     else
664     {
665         /* all others, take as raw format */
666         p_value->unformat.len = p_attr->len;
667         p_value->unformat.p_value = p_attr->value;
668     }
669     return status;
670 }
671 /*******************************************************************************
672 **
673 ** Function         bta_gattc_mark_bg_conn
674 **
675 ** Description      mark background connection status when a bg connection is initiated
676 **                  or terminated.
677 **
678 ** Returns          TRUE if success; FALSE otherwise.
679 **
680 *******************************************************************************/
bta_gattc_mark_bg_conn(tBTA_GATTC_IF client_if,BD_ADDR_PTR remote_bda_ptr,BOOLEAN add,BOOLEAN is_listen)681 BOOLEAN bta_gattc_mark_bg_conn (tBTA_GATTC_IF client_if,  BD_ADDR_PTR remote_bda_ptr,
682                                 BOOLEAN add, BOOLEAN is_listen)
683 {
684     tBTA_GATTC_BG_TCK   *p_bg_tck = &bta_gattc_cb.bg_track[0];
685     UINT8   i = 0;
686     tBTA_GATTC_CIF_MASK  *p_cif_mask;
687 
688     for (i = 0; i < BTA_GATTC_KNOWN_SR_MAX; i ++, p_bg_tck ++)
689     {
690         if (p_bg_tck->in_use &&
691             ((remote_bda_ptr != NULL && bdcmp(p_bg_tck->remote_bda, remote_bda_ptr) == 0) ||
692             (remote_bda_ptr == NULL && bdcmp(p_bg_tck->remote_bda, dummy_bda) == 0)))
693         {
694              p_cif_mask = is_listen ? &p_bg_tck->cif_adv_mask : &p_bg_tck->cif_mask;
695 
696             if (add)
697                 /* mask on the cif bit */
698                 *p_cif_mask |= (1 <<(client_if - 1));
699             else
700             {
701                 if (client_if != 0)
702                     *p_cif_mask &= (~(1 <<(client_if - 1)));
703                 else
704                     *p_cif_mask = 0;
705             }
706             /* no BG connection for this device, make it available */
707             if (p_bg_tck->cif_mask == 0 && p_bg_tck->cif_adv_mask == 0)
708             {
709                 memset(p_bg_tck, 0, sizeof(tBTA_GATTC_BG_TCK));
710             }
711             return TRUE;
712         }
713     }
714     if (!add)
715     {
716         if (remote_bda_ptr)
717         {
718             bdstr_t bdstr = {0};
719             APPL_TRACE_ERROR("%s unable to find the bg connection mask for: %s", __func__,
720                 bdaddr_to_string((bt_bdaddr_t *)remote_bda_ptr, bdstr, sizeof(bdstr)));
721         }
722         return FALSE;
723     }
724     else /* adding a new device mask */
725     {
726         for (i = 0, p_bg_tck = &bta_gattc_cb.bg_track[0];
727              i < BTA_GATTC_KNOWN_SR_MAX; i ++, p_bg_tck ++)
728         {
729             if (!p_bg_tck->in_use)
730             {
731                 p_bg_tck->in_use = TRUE;
732                 if (remote_bda_ptr)
733                     bdcpy(p_bg_tck->remote_bda, remote_bda_ptr);
734                 else
735                     bdcpy(p_bg_tck->remote_bda, dummy_bda);
736 
737                 p_cif_mask = is_listen ? &p_bg_tck->cif_adv_mask : &p_bg_tck->cif_mask;
738 
739                 *p_cif_mask = (1 <<(client_if - 1));
740                 return TRUE;
741             }
742         }
743         APPL_TRACE_ERROR("no available space to mark the bg connection status");
744         return FALSE;
745     }
746 }
747 /*******************************************************************************
748 **
749 ** Function         bta_gattc_check_bg_conn
750 **
751 ** Description      check if this is a background connection background connection.
752 **
753 ** Returns          TRUE if success; FALSE otherwise.
754 **
755 *******************************************************************************/
bta_gattc_check_bg_conn(tBTA_GATTC_IF client_if,BD_ADDR remote_bda,UINT8 role)756 BOOLEAN bta_gattc_check_bg_conn (tBTA_GATTC_IF client_if,  BD_ADDR remote_bda, UINT8 role)
757 {
758     tBTA_GATTC_BG_TCK   *p_bg_tck = &bta_gattc_cb.bg_track[0];
759     UINT8       i = 0;
760     BOOLEAN     is_bg_conn = FALSE;
761 
762     for (i = 0; i < BTA_GATTC_KNOWN_SR_MAX && !is_bg_conn; i ++, p_bg_tck ++)
763     {
764         if (p_bg_tck->in_use &&
765             (bdcmp(p_bg_tck->remote_bda, remote_bda) == 0 ||
766              bdcmp(p_bg_tck->remote_bda, dummy_bda) == 0))
767         {
768             if (((p_bg_tck->cif_mask &(1 <<(client_if - 1))) != 0) &&
769                 role == HCI_ROLE_MASTER)
770                 is_bg_conn = TRUE;
771 
772             if (((p_bg_tck->cif_adv_mask &(1 <<(client_if - 1))) != 0) &&
773                 role == HCI_ROLE_SLAVE)
774                 is_bg_conn = TRUE;
775         }
776     }
777     return is_bg_conn;
778 }
779 /*******************************************************************************
780 **
781 ** Function         bta_gattc_send_open_cback
782 **
783 ** Description      send open callback
784 **
785 ** Returns
786 **
787 *******************************************************************************/
bta_gattc_send_open_cback(tBTA_GATTC_RCB * p_clreg,tBTA_GATT_STATUS status,BD_ADDR remote_bda,UINT16 conn_id,tBTA_TRANSPORT transport,UINT16 mtu)788 void bta_gattc_send_open_cback( tBTA_GATTC_RCB *p_clreg, tBTA_GATT_STATUS status,
789                                 BD_ADDR remote_bda, UINT16 conn_id,
790                                 tBTA_TRANSPORT transport, UINT16 mtu)
791 {
792     tBTA_GATTC      cb_data;
793 
794     if (p_clreg->p_cback)
795     {
796         memset(&cb_data, 0, sizeof(tBTA_GATTC));
797 
798         cb_data.open.status = status;
799         cb_data.open.client_if = p_clreg->client_if;
800         cb_data.open.conn_id = conn_id;
801         cb_data.open.mtu = mtu;
802         cb_data.open.transport = transport;
803         bdcpy(cb_data.open.remote_bda, remote_bda);
804 
805         (*p_clreg->p_cback)(BTA_GATTC_OPEN_EVT, &cb_data);
806     }
807 }
808 /*******************************************************************************
809 **
810 ** Function         bta_gattc_conn_alloc
811 **
812 ** Description      allocate connection tracking spot
813 **
814 ** Returns          pointer to the clcb
815 **
816 *******************************************************************************/
bta_gattc_conn_alloc(BD_ADDR remote_bda)817 tBTA_GATTC_CONN * bta_gattc_conn_alloc(BD_ADDR remote_bda)
818 {
819     UINT8               i_conn = 0;
820     tBTA_GATTC_CONN     *p_conn = &bta_gattc_cb.conn_track[0];
821 
822     for (i_conn = 0; i_conn < BTA_GATTC_CONN_MAX; i_conn++, p_conn ++)
823     {
824         if (!p_conn->in_use)
825         {
826 #if BTA_GATT_DEBUG == TRUE
827             APPL_TRACE_DEBUG("bta_gattc_conn_alloc: found conn_track[%d] available",i_conn);
828 #endif
829             p_conn->in_use          = TRUE;
830             bdcpy(p_conn->remote_bda, remote_bda);
831             return p_conn;
832         }
833     }
834     return NULL;
835 }
836 
837 /*******************************************************************************
838 **
839 ** Function         bta_gattc_conn_find
840 **
841 ** Description      allocate connection tracking spot
842 **
843 ** Returns          pointer to the clcb
844 **
845 *******************************************************************************/
bta_gattc_conn_find(BD_ADDR remote_bda)846 tBTA_GATTC_CONN * bta_gattc_conn_find(BD_ADDR remote_bda)
847 {
848     UINT8               i_conn = 0;
849     tBTA_GATTC_CONN     *p_conn = &bta_gattc_cb.conn_track[0];
850 
851     for (i_conn = 0; i_conn < BTA_GATTC_CONN_MAX; i_conn++, p_conn ++)
852     {
853         if (p_conn->in_use && bdcmp(remote_bda, p_conn->remote_bda) == 0)
854         {
855 #if BTA_GATT_DEBUG == TRUE
856             APPL_TRACE_DEBUG("bta_gattc_conn_find: found conn_track[%d] matched",i_conn);
857 #endif
858             return p_conn;
859         }
860     }
861     return NULL;
862 }
863 
864 
865 /*******************************************************************************
866 **
867 ** Function         bta_gattc_conn_find_alloc
868 **
869 ** Description      find or allocate connection tracking spot
870 **
871 ** Returns          pointer to the clcb
872 **
873 *******************************************************************************/
bta_gattc_conn_find_alloc(BD_ADDR remote_bda)874 tBTA_GATTC_CONN * bta_gattc_conn_find_alloc(BD_ADDR remote_bda)
875 {
876     tBTA_GATTC_CONN     *p_conn = bta_gattc_conn_find (remote_bda);
877 
878     if (p_conn == NULL)
879     {
880         p_conn = bta_gattc_conn_alloc(remote_bda);
881     }
882     return p_conn;
883 }
884 
885 /*******************************************************************************
886 **
887 ** Function         bta_gattc_conn_dealloc
888 **
889 ** Description      de-allocate connection tracking spot
890 **
891 ** Returns          pointer to the clcb
892 **
893 *******************************************************************************/
bta_gattc_conn_dealloc(BD_ADDR remote_bda)894 BOOLEAN bta_gattc_conn_dealloc(BD_ADDR remote_bda)
895 {
896     tBTA_GATTC_CONN     *p_conn = bta_gattc_conn_find (remote_bda);
897 
898     if (p_conn != NULL)
899     {
900         p_conn->in_use = FALSE;
901         memset(p_conn->remote_bda, 0, BD_ADDR_LEN);
902         return TRUE;
903     }
904     return FALSE;
905 }
906 
907 /*******************************************************************************
908 **
909 ** Function         bta_gattc_find_int_conn_clcb
910 **
911 ** Description      try to locate a clcb when an internal connecion event arrives.
912 **
913 ** Returns          pointer to the clcb
914 **
915 *******************************************************************************/
bta_gattc_find_int_conn_clcb(tBTA_GATTC_DATA * p_msg)916 tBTA_GATTC_CLCB * bta_gattc_find_int_conn_clcb(tBTA_GATTC_DATA *p_msg)
917 {
918     tBTA_GATTC_CLCB *p_clcb = NULL;
919 
920     if (p_msg->int_conn.role == HCI_ROLE_SLAVE)
921         bta_gattc_conn_find_alloc(p_msg->int_conn.remote_bda);
922 
923     /* try to locate a logic channel */
924     if ((p_clcb = bta_gattc_find_clcb_by_cif(p_msg->int_conn.client_if,
925                                              p_msg->int_conn.remote_bda,
926                                              p_msg->int_conn.transport)) == NULL)
927     {
928         /* for a background connection or listening connection */
929         if (/*p_msg->int_conn.role == HCI_ROLE_SLAVE ||  */
930             bta_gattc_check_bg_conn(p_msg->int_conn.client_if,
931                                     p_msg->int_conn.remote_bda,
932                                     p_msg->int_conn.role))
933         {
934             /* allocate a new channel */
935             p_clcb = bta_gattc_clcb_alloc(p_msg->int_conn.client_if,
936                                           p_msg->int_conn.remote_bda,
937                                           p_msg->int_conn.transport);
938         }
939     }
940     return p_clcb;
941 }
942 
943 /*******************************************************************************
944 **
945 ** Function         bta_gattc_find_int_disconn_clcb
946 **
947 ** Description      try to locate a clcb when an internal disconnect callback arrives.
948 **
949 ** Returns          pointer to the clcb
950 **
951 *******************************************************************************/
bta_gattc_find_int_disconn_clcb(tBTA_GATTC_DATA * p_msg)952 tBTA_GATTC_CLCB * bta_gattc_find_int_disconn_clcb(tBTA_GATTC_DATA *p_msg)
953 {
954     tBTA_GATTC_CLCB         *p_clcb = NULL;
955 
956     bta_gattc_conn_dealloc(p_msg->int_conn.remote_bda);
957     if ((p_clcb = bta_gattc_find_clcb_by_conn_id(p_msg->int_conn.hdr.layer_specific)) == NULL)
958     {
959         /* connection attempt failed, send connection callback event */
960         p_clcb = bta_gattc_find_clcb_by_cif(p_msg->int_conn.client_if,
961                                             p_msg->int_conn.remote_bda,
962                                             p_msg->int_conn.transport);
963     }
964     if (p_clcb == NULL)
965     {
966         APPL_TRACE_DEBUG(" disconnection ID: [%d] not used by BTA",
967             p_msg->int_conn.hdr.layer_specific);
968     }
969     return p_clcb;
970 }
971 
972 #endif /* BTA_GATT_INCLUDED */
973