• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  *
3  *  Copyright (C) 1999-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 GATT interface functions
22  *
23  ******************************************************************************/
24 #include "bt_target.h"
25 
26 
27 #if defined(BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE)
28 
29 #include "gki.h"
30 #include <stdio.h>
31 #include <string.h>
32 #include "gatt_api.h"
33 #include "gatt_int.h"
34 #include "l2c_api.h"
35 #include "btm_int.h"
36 
37 
38 /*******************************************************************************
39 **
40 ** Function         GATT_SetTraceLevel
41 **
42 ** Description      This function sets the trace level.  If called with
43 **                  a value of 0xFF, it simply returns the current trace level.
44 **
45 **                  Input Parameters:
46 **                      level:  The level to set the GATT tracing to:
47 **                      0xff-returns the current setting.
48 **                      0-turns off tracing.
49 **                      >= 1-Errors.
50 **                      >= 2-Warnings.
51 **                      >= 3-APIs.
52 **                      >= 4-Events.
53 **                      >= 5-Debug.
54 **
55 ** Returns          The new or current trace level
56 **
57 *******************************************************************************/
GATT_SetTraceLevel(UINT8 new_level)58 UINT8 GATT_SetTraceLevel (UINT8 new_level)
59 {
60     if (new_level != 0xFF)
61         gatt_cb.trace_level = new_level;
62 
63     return(gatt_cb.trace_level);
64 }
65 
66 /*****************************************************************************
67 **
68 **                  GATT SERVER API
69 **
70 ******************************************************************************/
71 /*******************************************************************************
72 **
73 ** Function         GATTS_AddHandleRange
74 **
75 ** Description      This function add the allocated handles range for the specifed
76 **                  application UUID, service UUID and service instance
77 **
78 ** Parameter        p_hndl_range:   pointer to allocated handles information
79 **
80 ** Returns          TRUE if handle range is added sucessfully; otherwise FALSE.
81 **
82 *******************************************************************************/
83 
GATTS_AddHandleRange(tGATTS_HNDL_RANGE * p_hndl_range)84 BOOLEAN GATTS_AddHandleRange(tGATTS_HNDL_RANGE *p_hndl_range)
85 {
86     tGATT_HDL_LIST_ELEM *p_buf;
87     BOOLEAN status= FALSE;
88 
89     if ((p_buf = gatt_alloc_hdl_buffer()) != NULL)
90     {
91         p_buf->asgn_range = *p_hndl_range;
92         status  = gatt_add_an_item_to_list(&gatt_cb.hdl_list_info, p_buf);
93     }
94     return status;
95 }
96 
97 
98 /*******************************************************************************
99 **
100 ** Function         GATTS_NVRegister
101 **
102 ** Description      Application manager calls this function to register for
103 **                  NV save callback function.  There can be one and only one
104 **                  NV save callback function.
105 **
106 ** Parameter        p_cb_info : callback informaiton
107 **
108 ** Returns          TRUE if registered OK, else FALSE
109 **
110 *******************************************************************************/
GATTS_NVRegister(tGATT_APPL_INFO * p_cb_info)111 BOOLEAN  GATTS_NVRegister (tGATT_APPL_INFO *p_cb_info)
112 {
113     BOOLEAN status= FALSE;
114     if (p_cb_info)
115     {
116         gatt_cb.cb_info = *p_cb_info;
117         status = TRUE;
118         gatt_init_srv_chg();
119     }
120 
121     return status;
122 }
123 
124 /*******************************************************************************
125 **
126 ** Function         GATTS_CreateService
127 **
128 ** Description      This function is called to reserve a block of handles for a service.
129 **
130 **                  *** It should be called only once per service instance  ***
131 **
132 ** Parameter        gatt_if       : application if
133 **                  p_svc_uuid    : service UUID
134 **                  svc_inst      : instance of the service inside the application
135 **                  num_handles   : number of handles needed by the service.
136 **                  is_pri        : is a primary service or not.
137 **
138 ** Returns          service handle if sucessful, otherwise 0.
139 **
140 *******************************************************************************/
GATTS_CreateService(tGATT_IF gatt_if,tBT_UUID * p_svc_uuid,UINT16 svc_inst,UINT16 num_handles,BOOLEAN is_pri)141 UINT16 GATTS_CreateService (tGATT_IF gatt_if, tBT_UUID *p_svc_uuid,
142                             UINT16 svc_inst, UINT16 num_handles, BOOLEAN is_pri)
143 {
144 
145     tGATT_HDL_LIST_INFO     *p_list_info= &gatt_cb.hdl_list_info;
146     tGATT_HDL_LIST_ELEM     *p_list=NULL;
147     UINT16                  s_hdl=0;
148     BOOLEAN                 save_hdl=FALSE;
149     tGATTS_PENDING_NEW_SRV_START      *p_buf=NULL;
150     tGATT_REG              *p_reg = gatt_get_regcb(gatt_if);
151     tBT_UUID     *p_app_uuid128;
152 
153 
154     GATT_TRACE_API0 ("GATTS_CreateService" );
155 
156     if (p_reg == NULL)
157     {
158         GATT_TRACE_ERROR1 ("Inavlid gatt_if=%d", gatt_if);
159         return(0);
160     }
161 
162     p_app_uuid128 = &p_reg->app_uuid128;
163 
164     if ((p_list = gatt_find_hdl_buffer_by_app_id(p_app_uuid128, p_svc_uuid, svc_inst)) != NULL)
165     {
166         s_hdl = p_list->asgn_range.s_handle;
167         GATT_TRACE_DEBUG0 ("Service already been created!!");
168     }
169     else
170     {
171         if ( (p_svc_uuid->len == LEN_UUID_16) && (p_svc_uuid->uu.uuid16 == UUID_SERVCLASS_GATT_SERVER))
172         {
173             s_hdl=  gatt_cb.hdl_cfg.gatt_start_hdl;
174         }
175         else if ((p_svc_uuid->len == LEN_UUID_16) && (p_svc_uuid->uu.uuid16 == UUID_SERVCLASS_GAP_SERVER))
176         {
177             s_hdl= gatt_cb.hdl_cfg.gap_start_hdl;
178         }
179         else
180         {
181             p_list = p_list_info->p_first;
182 
183             if (p_list)
184             {
185                 s_hdl = p_list->asgn_range.e_handle + 1;
186             }
187 
188             if (s_hdl < gatt_cb.hdl_cfg.app_start_hdl)
189             {
190 
191                 s_hdl= gatt_cb.hdl_cfg.app_start_hdl;
192             }
193             save_hdl = TRUE;
194         }
195 
196         /* check for space */
197         if (num_handles > (0xFFFF - s_hdl + 1))
198         {
199             GATT_TRACE_ERROR2 ("GATTS_ReserveHandles: no handles, s_hdl: %u  needed: %u", s_hdl, num_handles);
200             return(0);
201         }
202 
203         if ( (p_list = gatt_alloc_hdl_buffer()) == NULL)
204         {
205             /* No free entry */
206             GATT_TRACE_ERROR0 ("GATTS_ReserveHandles: no free handle blocks");
207             return(0);
208         }
209 
210         p_list->asgn_range.app_uuid128 = *p_app_uuid128;
211         p_list->asgn_range.svc_uuid    = *p_svc_uuid;
212         p_list->asgn_range.svc_inst    = svc_inst;
213         p_list->asgn_range.s_handle    = s_hdl;
214         p_list->asgn_range.e_handle    = s_hdl+num_handles-1;
215         p_list->asgn_range.is_primary  = is_pri;
216 
217         gatt_add_an_item_to_list(p_list_info, p_list);
218 
219         if (save_hdl)
220         {
221             if (gatt_cb.cb_info.p_nv_save_callback)
222                 (*gatt_cb.cb_info.p_nv_save_callback)(TRUE, &p_list->asgn_range);
223             /* add a pending new  service change item to the list */
224             if ( (p_buf = gatt_add_pending_new_srv_start(&p_list->asgn_range)) == NULL)
225             {
226                 /* No free entry */
227                 GATT_TRACE_ERROR0 ("gatt_add_pending_new_srv_start: no free blocks");
228 
229                 if (p_list)
230                 {
231                     gatt_remove_an_item_from_list(p_list_info, p_list);
232                     gatt_free_hdl_buffer(p_list);
233                 }
234                 return(0);
235             }
236 
237             GATT_TRACE_DEBUG0 ("Add a new srv chg item");
238         }
239     }
240 
241     if (!gatts_init_service_db(&p_list->svc_db, *p_svc_uuid, is_pri, s_hdl , num_handles))
242     {
243         GATT_TRACE_ERROR0 ("GATTS_ReserveHandles: service DB initialization failed");
244         if (p_list)
245         {
246             gatt_remove_an_item_from_list(p_list_info, p_list);
247             gatt_free_hdl_buffer(p_list);
248         }
249 
250         if (p_buf)
251             GKI_freebuf (GKI_remove_from_queue (&gatt_cb.pending_new_srv_start_q, p_buf));
252         return(0);
253     }
254 
255     GATT_TRACE_DEBUG6 ("GATTS_CreateService(success): handles needed:%u s_hdl=%u e_hdl=%u %s[%x] is_primary=%d",
256                        num_handles, p_list->asgn_range.s_handle , p_list->asgn_range.e_handle,
257                        ((p_list->asgn_range.svc_uuid.len == 2) ? "uuid16": "uuid128" ),
258                        p_list->asgn_range.svc_uuid.uu.uuid16,
259                        p_list->asgn_range.is_primary);
260 
261     return(s_hdl);
262 }
263 
264 /*******************************************************************************
265 **
266 ** Function         GATTS_AddIncludeService
267 **
268 ** Description      This function is called to add an included service.
269 **
270 ** Parameter        service_handle : To which service this included service is added to.
271 **                  include_svc_handle    : included service handle.
272 **
273 ** Returns          included service attribute handle. If 0, add included service
274 **                  fail.
275 **
276 *******************************************************************************/
GATTS_AddIncludeService(UINT16 service_handle,UINT16 include_svc_handle)277 UINT16 GATTS_AddIncludeService (UINT16 service_handle, UINT16 include_svc_handle)
278 
279 {
280     tGATT_HDL_LIST_ELEM  *p_decl, *p_incl_decl;
281 
282     if ((p_decl = gatt_find_hdl_buffer_by_handle(service_handle)) == NULL)
283     {
284         GATT_TRACE_DEBUG0("Service not created");
285         return 0;
286     }
287     if ((p_incl_decl = gatt_find_hdl_buffer_by_handle(include_svc_handle)) == NULL)
288     {
289         GATT_TRACE_DEBUG0("Included Service not created");
290         return 0;
291     }
292 
293     return gatts_add_included_service(&p_decl->svc_db,
294                                       p_incl_decl->asgn_range.s_handle,
295                                       p_incl_decl->asgn_range.e_handle,
296                                       p_incl_decl->asgn_range.svc_uuid);
297 }
298 /*******************************************************************************
299 **
300 ** Function         GATTS_AddCharacteristic
301 **
302 ** Description      This function is called to add a characteristic into a service.
303 **                  It will add a characteristic declaration and characteristic
304 **                  value declaration into the service database identified by the
305 **                  service handle.
306 **
307 ** Parameter        service_handle : To which service this included service is added to.
308 **                  char_uuid : Characteristic UUID.
309 **                  perm      : Characteristic value declaration attribute permission.
310 **                  property  : Characteristic Properties
311 **
312 ** Returns          Characteristic value declaration attribute handle. 0 if failed.
313 **
314 *******************************************************************************/
GATTS_AddCharacteristic(UINT16 service_handle,tBT_UUID * p_char_uuid,tGATT_PERM perm,tGATT_CHAR_PROP property)315 UINT16 GATTS_AddCharacteristic (UINT16 service_handle, tBT_UUID *p_char_uuid,
316                                 tGATT_PERM perm,tGATT_CHAR_PROP property)
317 {
318     tGATT_HDL_LIST_ELEM  *p_decl;
319 
320     if ((p_decl = gatt_find_hdl_buffer_by_handle(service_handle)) == NULL)
321     {
322         GATT_TRACE_DEBUG0("Service not created");
323         return 0;
324     }
325     /* data validity checking */
326     if (  ((property & GATT_CHAR_PROP_BIT_AUTH) && !(perm & GATT_WRITE_SIGNED_PERM)) ||
327           ((perm & GATT_WRITE_SIGNED_PERM) && !(property & GATT_CHAR_PROP_BIT_AUTH)) )
328     {
329         GATT_TRACE_DEBUG2("Invalid configuration property=0x%x perm=0x%x ", property, perm);
330         return 0;
331     }
332 
333     return gatts_add_characteristic(&p_decl->svc_db,
334                                     perm,
335                                     property,
336                                     p_char_uuid);
337 }
338 /*******************************************************************************
339 **
340 ** Function         GATTS_AddCharDescriptor
341 **
342 ** Description      This function is called to add a characteristic descriptor
343 **                  into a service database. Add descriptor should follow add char
344 **                  to which it belongs, and next add char should be done only
345 **                  after all add descriptors for the previous char.
346 **
347 ** Parameter        service_handle  : To which service this characteristic descriptor
348 **                                    is added to.
349 **                  perm            : Characteristic value declaration attribute
350 **                                    permission.
351 **                  p_descr_uuid    : Characteristic descriptor UUID
352 **
353 ** Returns         Characteristic descriptor attribute handle. 0 if add
354 **                 characteristic descriptor failed.
355 **
356 *******************************************************************************/
GATTS_AddCharDescriptor(UINT16 service_handle,tGATT_PERM perm,tBT_UUID * p_descr_uuid)357 UINT16 GATTS_AddCharDescriptor (UINT16 service_handle,
358                                  tGATT_PERM perm,
359                                  tBT_UUID  * p_descr_uuid)
360 {
361     tGATT_HDL_LIST_ELEM  *p_decl;
362 
363     if ((p_decl = gatt_find_hdl_buffer_by_handle(service_handle)) == NULL)
364     {
365         GATT_TRACE_DEBUG0("Service not created");
366         return 0;
367     }
368     if (p_descr_uuid == NULL ||
369         (p_descr_uuid->len != LEN_UUID_128 && p_descr_uuid->len !=  LEN_UUID_16))
370     {
371         GATT_TRACE_DEBUG0("Illegal parameter");
372         return 0;
373     }
374 
375     return gatts_add_char_descr(&p_decl->svc_db,
376                                 perm,
377                                 p_descr_uuid);
378 
379 }
380 /*******************************************************************************
381 **
382 ** Function         GATTS_DeleteService
383 **
384 ** Description      This function is called to delete a service.
385 **
386 ** Parameter        gatt_if       : application interface
387 **                  p_svc_uuid    : service UUID
388 **                  svc_inst      : instance of the service inside the application
389 **
390 ** Returns          TRUE if operation succeed, FALSE if handle block was not found.
391 **
392 *******************************************************************************/
GATTS_DeleteService(tGATT_IF gatt_if,tBT_UUID * p_svc_uuid,UINT16 svc_inst)393 BOOLEAN GATTS_DeleteService (tGATT_IF gatt_if, tBT_UUID *p_svc_uuid, UINT16 svc_inst)
394 {
395 
396     tGATT_HDL_LIST_INFO             *p_list_info= &gatt_cb.hdl_list_info;
397     tGATT_HDL_LIST_ELEM             *p_list=NULL;
398     UINT8                           i_sreg;
399     tGATTS_PENDING_NEW_SRV_START    *p_buf;
400     tGATT_REG       *p_reg = gatt_get_regcb(gatt_if);
401     tBT_UUID *p_app_uuid128;
402 
403     GATT_TRACE_DEBUG0 ("GATTS_DeleteService");
404 
405     if (p_reg == NULL)
406     {
407         GATT_TRACE_ERROR0 ("Applicaiton not foud");
408         return(FALSE);
409     }
410     p_app_uuid128 = &p_reg->app_uuid128;
411 
412     if ((p_list = gatt_find_hdl_buffer_by_app_id(p_app_uuid128, p_svc_uuid, svc_inst)) == NULL)
413     {
414         GATT_TRACE_ERROR0 ("No Service found");
415         return(FALSE);
416     }
417 
418     if ( (p_buf = gatt_sr_is_new_srv_chg(&p_list->asgn_range.app_uuid128,
419                                          &p_list->asgn_range.svc_uuid,
420                                          p_list->asgn_range.svc_inst)) != NULL)
421     {
422         GATT_TRACE_DEBUG0 ("Delete a new service changed item - the service has not yet started");
423         GKI_freebuf (GKI_remove_from_queue (&gatt_cb.pending_new_srv_start_q, p_buf));
424     }
425     else
426     {
427         gatt_proc_srv_chg();
428     }
429 
430     if ((i_sreg = gatt_sr_find_i_rcb_by_app_id (p_app_uuid128,
431                                                 p_svc_uuid,
432                                                 svc_inst)) != GATT_MAX_SR_PROFILES)
433     {
434         GATTS_StopService(gatt_cb.sr_reg[i_sreg].s_hdl);
435     }
436 
437     GATT_TRACE_DEBUG2 ("released handles s_hdl=%u e_hdl=%u",
438                        p_list->asgn_range.s_handle , p_list->asgn_range.e_handle  );
439 
440     if ( (p_list->asgn_range.s_handle >= gatt_cb.hdl_cfg.app_start_hdl)
441          && gatt_cb.cb_info.p_nv_save_callback)
442         (*gatt_cb.cb_info.p_nv_save_callback)(FALSE, &p_list->asgn_range);
443 
444     gatt_remove_an_item_from_list(p_list_info, p_list);
445     gatt_free_hdl_buffer(p_list);
446 
447     return(TRUE);
448 }
449 
450 /*******************************************************************************
451 **
452 ** Function         GATTS_StartService
453 **
454 ** Description      This function is called to start a service with GATT
455 **
456 ** Parameter        gatt_if : service handle.
457 **                  p_cback       : application service callback functions.
458 **                  sup_transport : supported transport(s) for this primary service
459 **
460 ** return           GATT_SUCCESS if sucessfully started; otherwise error code.
461 **
462 *******************************************************************************/
GATTS_StartService(tGATT_IF gatt_if,UINT16 service_handle,tGATT_TRANSPORT sup_transport)463 tGATT_STATUS GATTS_StartService (tGATT_IF gatt_if, UINT16 service_handle,
464                                  tGATT_TRANSPORT sup_transport)
465 {
466     tGATT_SR_REG            *p_sreg;
467     tGATT_HDL_LIST_ELEM      *p_list=NULL;
468     UINT8                    i_sreg;
469     tBT_UUID                *p_uuid;
470     tGATT_REG              *p_reg = gatt_get_regcb(gatt_if);
471 
472     tGATTS_PENDING_NEW_SRV_START *p_buf;
473 
474     GATT_TRACE_API0 ("GATTS_StartService");
475 
476     if (p_reg == NULL)
477     {
478         /* Not found  */
479         GATT_TRACE_ERROR0 ("Applicaiton not found ");
480         return GATT_NOT_FOUND;
481     }
482 
483     if ((p_list = gatt_find_hdl_buffer_by_handle(service_handle)) == NULL)
484     {
485         /* Not found  */
486         GATT_TRACE_ERROR0 ("no service found");
487         return GATT_NOT_FOUND;
488     }
489 
490     if (gatt_sr_find_i_rcb_by_app_id (&p_list->asgn_range.app_uuid128,
491                                       &p_list->asgn_range.svc_uuid,
492                                       p_list->asgn_range.svc_inst) != GATT_MAX_SR_PROFILES)
493     {
494         GATT_TRACE_ERROR0 ("Duplicate Service start - Service already started");
495         return GATT_SERVICE_STARTED;
496     }
497 
498     /*this is a new application servoce start */
499     if ((i_sreg = gatt_sr_alloc_rcb(p_list)) ==  GATT_MAX_SR_PROFILES)
500     {
501         GATT_TRACE_ERROR0 ("GATTS_StartService: no free server registration block");
502         return GATT_NO_RESOURCES;
503     }
504 
505     p_sreg = &gatt_cb.sr_reg[i_sreg];
506     p_sreg->gatt_if = gatt_if;
507 
508     switch (sup_transport)
509     {
510         case GATT_TRANSPORT_BR_EDR:
511         case GATT_TRANSPORT_LE_BR_EDR:
512             if (p_sreg->type == GATT_UUID_PRI_SERVICE)
513             {
514                 p_uuid = gatts_get_service_uuid (p_sreg->p_db);
515 
516                 p_sreg->sdp_handle = gatt_add_sdp_record(p_uuid, p_sreg->s_hdl, p_sreg->e_hdl);
517             }
518             break;
519         default:
520             break;
521     }
522 
523     gatts_update_srv_list_elem(i_sreg, p_sreg->s_hdl,
524                                p_list->asgn_range.is_primary);
525 
526     gatt_add_a_srv_to_list(&gatt_cb.srv_list_info, &gatt_cb.srv_list[i_sreg]);
527 
528     GATT_TRACE_DEBUG1 ("allocated i_sreg=%d ",i_sreg);
529 
530     GATT_TRACE_DEBUG5 ("s_hdl=%d e_hdl=%d type=0x%x svc_inst=%d sdp_hdl=0x%x",
531                        p_sreg->s_hdl,p_sreg->e_hdl,
532                        p_sreg->type,  p_sreg->service_instance,
533                        p_sreg->sdp_handle);
534 
535 
536     if ( (p_buf = gatt_sr_is_new_srv_chg(&p_list->asgn_range.app_uuid128,
537                                          &p_list->asgn_range.svc_uuid,
538                                          p_list->asgn_range.svc_inst)) != NULL)
539     {
540         gatt_proc_srv_chg();
541         /* remove the new service element after the srv changed processing is completed*/
542 
543         GKI_freebuf (GKI_remove_from_queue (&gatt_cb.pending_new_srv_start_q, p_buf));
544     }
545     return GATT_SUCCESS;
546 }
547 
548 /*******************************************************************************
549 **
550 ** Function         GATTS_StopService
551 **
552 ** Description      This function is called to stop a service
553 **
554 ** Parameter         service_handle : this is the start handle of a service
555 **
556 ** Returns          None.
557 **
558 *******************************************************************************/
GATTS_StopService(UINT16 service_handle)559 void GATTS_StopService (UINT16 service_handle)
560 {
561     UINT8           ii = gatt_sr_find_i_rcb_by_handle(service_handle);
562 
563     GATT_TRACE_API1("GATTS_StopService %u", service_handle);
564 
565     /* Index 0 is reserved for GATT, and is never stopped */
566     if ( (ii > 0) && (ii < GATT_MAX_SR_PROFILES) && (gatt_cb.sr_reg[ii].in_use) )
567     {
568         if (gatt_cb.sr_reg[ii].sdp_handle)
569         {
570             SDP_DeleteRecord(gatt_cb.sr_reg[ii].sdp_handle);
571         }
572         gatt_remove_a_srv_from_list(&gatt_cb.srv_list_info, &gatt_cb.srv_list[ii]);
573         gatt_cb.srv_list[ii].in_use = FALSE;
574         memset (&gatt_cb.sr_reg[ii], 0, sizeof(tGATT_SR_REG));
575     }
576     else
577     {
578         GATT_TRACE_ERROR1("GATTS_StopService service_handle: %u is not in use", service_handle);
579     }
580 }
581 /*******************************************************************************
582 **
583 ** Function         GATTs_HandleValueIndication
584 **
585 ** Description      This function sends a handle value indication to a client.
586 **
587 ** Parameter        conn_id: connection identifier.
588 **                  attr_handle: Attribute handle of this handle value indication.
589 **                  val_len: Length of the indicated attribute value.
590 **                  p_val: Pointer to the indicated attribute value data.
591 **
592 ** Returns          GATT_SUCCESS if sucessfully sent or queued; otherwise error code.
593 **
594 *******************************************************************************/
GATTS_HandleValueIndication(UINT16 conn_id,UINT16 attr_handle,UINT16 val_len,UINT8 * p_val)595 tGATT_STATUS GATTS_HandleValueIndication (UINT16 conn_id,  UINT16 attr_handle, UINT16 val_len, UINT8 *p_val)
596 {
597     tGATT_STATUS    cmd_status = GATT_ILLEGAL_PARAMETER;
598 
599     tGATT_VALUE      indication;
600     BT_HDR          *p_msg;
601     tGATT_VALUE     *p_buf;
602     tGATT_IF         gatt_if = GATT_GET_GATT_IF(conn_id);
603     UINT8           tcb_idx = GATT_GET_TCB_IDX(conn_id);
604     tGATT_REG       *p_reg = gatt_get_regcb(gatt_if);
605     tGATT_TCB       *p_tcb = gatt_get_tcb_by_idx(tcb_idx);
606 
607 
608     GATT_TRACE_API0 ("GATTS_HandleValueIndication");
609     if ( (p_reg == NULL) || (p_tcb == NULL))
610     {
611         GATT_TRACE_ERROR1 ("GATTS_HandleValueIndication Unknown  conn_id: %u ", conn_id);
612         return(tGATT_STATUS) GATT_INVALID_CONN_ID;
613     }
614     indication.conn_id  = conn_id;
615     indication.handle   = attr_handle;
616     indication.len      = val_len;
617     memcpy (indication.value, p_val, val_len);
618     indication.auth_req = GATT_AUTH_REQ_NONE;
619 
620     if (GATT_HANDLE_IS_VALID (attr_handle)  )
621     {
622         if (GATT_HANDLE_IS_VALID(p_tcb->indicate_handle))
623         {
624             GATT_TRACE_DEBUG0 ("Add a pending indication");
625             if ((p_buf = gatt_add_pending_ind(p_tcb, &indication)) !=NULL)
626             {
627                 cmd_status = GATT_SUCCESS;
628             }
629             else
630             {
631                 cmd_status = GATT_NO_RESOURCES;
632             }
633         }
634         else
635         {
636 
637             if ( (p_msg = attp_build_sr_msg (p_tcb, GATT_HANDLE_VALUE_IND, (tGATT_SR_MSG *)&indication)) != NULL)
638             {
639                 cmd_status = attp_send_sr_msg (p_tcb, p_msg);
640 
641                 if (cmd_status == GATT_SUCCESS)
642                 {
643                     p_tcb->indicate_handle = indication.handle;
644                     gatt_start_conf_timer(p_tcb);
645                 }
646             }
647         }
648     }
649     return cmd_status;
650 }
651 
652 /*******************************************************************************
653 **
654 ** Function         GATTS_HandleValueNotification
655 **
656 ** Description      This function sends a handle value notification to a client.
657 **
658 ** Parameter        conn_id: connection identifier.
659 **                  attr_handle: Attribute handle of this handle value indication.
660 **                  val_len: Length of the indicated attribute value.
661 **                  p_val: Pointer to the indicated attribute value data.
662 **
663 ** Returns          GATT_SUCCESS if sucessfully sent; otherwise error code.
664 **
665 *******************************************************************************/
GATTS_HandleValueNotification(UINT16 conn_id,UINT16 attr_handle,UINT16 val_len,UINT8 * p_val)666 tGATT_STATUS GATTS_HandleValueNotification (UINT16 conn_id, UINT16 attr_handle,
667                                             UINT16 val_len, UINT8 *p_val)
668 {
669     tGATT_STATUS    cmd_sent = GATT_ILLEGAL_PARAMETER;
670     BT_HDR          *p_buf;
671     tGATT_VALUE     notif;
672     tGATT_IF         gatt_if = GATT_GET_GATT_IF(conn_id);
673     UINT8           tcb_idx = GATT_GET_TCB_IDX(conn_id);
674     tGATT_REG       *p_reg = gatt_get_regcb(gatt_if);
675     tGATT_TCB       *p_tcb = gatt_get_tcb_by_idx(tcb_idx);
676 
677     GATT_TRACE_API0 ("GATTS_HandleValueNotification");
678 
679     if ( (p_reg == NULL) || (p_tcb == NULL))
680     {
681         GATT_TRACE_ERROR1 ("GATTS_HandleValueNotification Unknown  conn_id: %u ", conn_id);
682         return(tGATT_STATUS) GATT_INVALID_CONN_ID;
683     }
684 
685     if (GATT_HANDLE_IS_VALID (attr_handle))
686     {
687         notif.handle    = attr_handle;
688         notif.len       = val_len;
689         memcpy (notif.value, p_val, val_len);
690         notif.auth_req = GATT_AUTH_REQ_NONE;;
691 
692         p_buf = attp_build_sr_msg (p_tcb, GATT_HANDLE_VALUE_NOTIF, (tGATT_SR_MSG *)&notif);
693         cmd_sent = attp_send_sr_msg (p_tcb, p_buf);
694     }
695     return cmd_sent;
696 }
697 
698 /*******************************************************************************
699 **
700 ** Function         GATTS_SendRsp
701 **
702 ** Description      This function sends the server response to client.
703 **
704 ** Parameter        conn_id: connection identifier.
705 **                  trans_id: transaction id
706 **                  status: response status
707 **                  p_msg: pointer to message parameters structure.
708 **
709 ** Returns          GATT_SUCCESS if sucessfully sent; otherwise error code.
710 **
711 *******************************************************************************/
GATTS_SendRsp(UINT16 conn_id,UINT32 trans_id,tGATT_STATUS status,tGATTS_RSP * p_msg)712 tGATT_STATUS GATTS_SendRsp (UINT16 conn_id,  UINT32 trans_id,
713                             tGATT_STATUS status, tGATTS_RSP *p_msg)
714 {
715     tGATT_STATUS cmd_sent = GATT_ILLEGAL_PARAMETER;
716     tGATT_IF         gatt_if = GATT_GET_GATT_IF(conn_id);
717     UINT8           tcb_idx = GATT_GET_TCB_IDX(conn_id);
718     tGATT_REG       *p_reg = gatt_get_regcb(gatt_if);
719     tGATT_TCB       *p_tcb = gatt_get_tcb_by_idx(tcb_idx);
720 
721     GATT_TRACE_API3 ("GATTS_SendRsp: conn_id: %u  trans_id: %u  Status: 0x%04x",
722                      conn_id, trans_id, status);
723 
724     if ( (p_reg == NULL) || (p_tcb == NULL))
725     {
726         GATT_TRACE_ERROR1 ("GATTS_SendRsp Unknown  conn_id: %u ", conn_id);
727         return(tGATT_STATUS) GATT_INVALID_CONN_ID;
728     }
729 
730     if (p_tcb->sr_cmd.trans_id != trans_id)
731     {
732         GATT_TRACE_ERROR2 ("GATTS_SendRsp conn_id: %u  waiting for op_code = %02x",
733                            conn_id, p_tcb->sr_cmd.op_code);
734 
735         return(GATT_WRONG_STATE);
736     }
737     /* Process App response */
738     cmd_sent = gatt_sr_process_app_rsp (p_tcb,  gatt_if, trans_id, p_tcb->sr_cmd.op_code, status, p_msg);
739 
740     return cmd_sent;
741 }
742 
743 /*******************************************************************************/
744 /* GATT Profile Srvr Functions */
745 /*******************************************************************************/
746 
747 /*******************************************************************************/
748 /*                                                                             */
749 /*                   GATT CLIENT APIs                                          */
750 /*                                                                             */
751 /*******************************************************************************/
752 
753 
754 /*******************************************************************************
755 **
756 ** Function         GATTC_ConfigureMTU
757 **
758 ** Description      This function is called to configure the ATT MTU size.
759 **
760 ** Parameters       conn_id: connection identifier.
761 **                  mtu    - attribute MTU size..
762 **
763 ** Returns          GATT_SUCCESS if command started successfully.
764 **
765 *******************************************************************************/
GATTC_ConfigureMTU(UINT16 conn_id,UINT16 mtu)766 tGATT_STATUS GATTC_ConfigureMTU (UINT16 conn_id, UINT16 mtu)
767 {
768     UINT8           ret = GATT_NO_RESOURCES;
769     tGATT_IF        gatt_if=GATT_GET_GATT_IF(conn_id);
770     UINT8           tcb_idx = GATT_GET_TCB_IDX(conn_id);
771     tGATT_TCB       *p_tcb = gatt_get_tcb_by_idx(tcb_idx);
772     tGATT_REG       *p_reg = gatt_get_regcb(gatt_if);
773 
774     tGATT_CLCB    *p_clcb;
775 
776     GATT_TRACE_API2 ("GATTC_ConfigureMTU conn_id=%d mtu=%d", conn_id, mtu );
777 
778     // Validate that the link is BLE, not BR/EDR
779     // ????
780 
781     if ( (p_tcb == NULL) || (p_reg==NULL) || (mtu < GATT_DEF_BLE_MTU_SIZE) || (mtu > GATT_MAX_MTU_SIZE))
782     {
783         return GATT_ILLEGAL_PARAMETER;
784     }
785 
786     if (gatt_is_clcb_allocated(conn_id))
787     {
788         GATT_TRACE_ERROR1("GATTC_ConfigureMTU GATT_BUSY conn_id = %d", conn_id);
789         return GATT_BUSY;
790     }
791 
792     if ((p_clcb = gatt_clcb_alloc(conn_id)) != NULL)
793     {
794         p_clcb->p_tcb->payload_size = mtu;
795         p_clcb->operation = GATTC_OPTYPE_CONFIG;
796 
797         ret = attp_send_cl_msg (p_clcb->p_tcb, p_clcb->clcb_idx, GATT_REQ_MTU, (tGATT_CL_MSG *)&mtu);
798     }
799 
800     return ret;
801 }
802 
803 /*******************************************************************************
804 **
805 ** Function         GATTC_Discover
806 **
807 ** Description      This function is called to do a discovery procedure on ATT server.
808 **
809 ** Parameters       conn_id: connection identifier.
810 **                  disc_type:discovery type.
811 **                  p_param: parameters of discovery requirement.
812 **
813 ** Returns          GATT_SUCCESS if command received/sent successfully.
814 **
815 *******************************************************************************/
GATTC_Discover(UINT16 conn_id,tGATT_DISC_TYPE disc_type,tGATT_DISC_PARAM * p_param)816 tGATT_STATUS GATTC_Discover (UINT16 conn_id, tGATT_DISC_TYPE disc_type,
817                              tGATT_DISC_PARAM *p_param)
818 {
819     tGATT_STATUS    status = GATT_SUCCESS;
820     tGATT_CLCB      *p_clcb;
821     tGATT_IF        gatt_if=GATT_GET_GATT_IF(conn_id);
822     UINT8           tcb_idx = GATT_GET_TCB_IDX(conn_id);
823     tGATT_TCB       *p_tcb = gatt_get_tcb_by_idx(tcb_idx);
824     tGATT_REG       *p_reg = gatt_get_regcb(gatt_if);
825 
826 
827     GATT_TRACE_API2 ("GATTC_Discover conn_id=%d disc_type=%d",conn_id, disc_type);
828 
829     if ( (p_tcb == NULL) || (p_reg==NULL) ||(p_param == NULL) ||
830          (disc_type >= GATT_DISC_MAX))
831     {
832         GATT_TRACE_ERROR2("GATTC_Discover Illegal param: disc_type %d conn_id = %d", disc_type, conn_id);
833         return GATT_ILLEGAL_PARAMETER;
834     }
835 
836 
837     if (gatt_is_clcb_allocated(conn_id))
838     {
839         GATT_TRACE_ERROR1("GATTC_Discover GATT_BUSY conn_id = %d", conn_id);
840         return GATT_BUSY;
841     }
842 
843 
844     if ((p_clcb = gatt_clcb_alloc(conn_id)) != NULL )
845     {
846         if (!GATT_HANDLE_IS_VALID(p_param->s_handle) ||
847             !GATT_HANDLE_IS_VALID(p_param->e_handle) ||
848             /* search by type does not have a valid UUID param */
849             (disc_type == GATT_DISC_SRVC_BY_UUID &&
850              p_param->service.len == 0))
851         {
852             gatt_clcb_dealloc(p_clcb);
853             return GATT_ILLEGAL_PARAMETER;
854         }
855 
856         p_clcb->operation  = GATTC_OPTYPE_DISCOVERY;
857         p_clcb->op_subtype = disc_type;
858         p_clcb->s_handle   = p_param->s_handle;
859         p_clcb->e_handle   = p_param->e_handle;
860         p_clcb->uuid       = p_param->service;
861 
862         gatt_act_discovery(p_clcb);
863     }
864     else
865     {
866         status = GATT_NO_RESOURCES;
867     }
868     return status;
869 }
870 
871 /*******************************************************************************
872 **
873 ** Function         GATTC_Read
874 **
875 ** Description      This function is called to read the value of an attribute from
876 **                  the server.
877 **
878 ** Parameters       conn_id: connection identifier.
879 **                  type    - attribute read type.
880 **                  p_read  - read operation parameters.
881 **
882 ** Returns          GATT_SUCCESS if command started successfully.
883 **
884 *******************************************************************************/
GATTC_Read(UINT16 conn_id,tGATT_READ_TYPE type,tGATT_READ_PARAM * p_read)885 tGATT_STATUS GATTC_Read (UINT16 conn_id, tGATT_READ_TYPE type, tGATT_READ_PARAM *p_read)
886 {
887     tGATT_STATUS status = GATT_SUCCESS;
888     tGATT_CLCB          *p_clcb;
889     tGATT_READ_MULTI    *p_read_multi;
890     tGATT_IF            gatt_if=GATT_GET_GATT_IF(conn_id);
891     UINT8               tcb_idx = GATT_GET_TCB_IDX(conn_id);
892     tGATT_TCB           *p_tcb = gatt_get_tcb_by_idx(tcb_idx);
893     tGATT_REG           *p_reg = gatt_get_regcb(gatt_if);
894 
895 
896     GATT_TRACE_API2 ("GATTC_Read conn_id=%d type=%d", conn_id, type);
897 
898     if ( (p_tcb == NULL) || (p_reg==NULL) || (p_read == NULL) || ((type >= GATT_READ_MAX) || (type == 0)))
899     {
900         GATT_TRACE_ERROR2("GATT_Read Illegal param: conn_id %d, type 0%d,", conn_id, type);
901         return GATT_ILLEGAL_PARAMETER;
902     }
903 
904     if (gatt_is_clcb_allocated(conn_id))
905     {
906         GATT_TRACE_ERROR1("GATTC_Read GATT_BUSY conn_id = %d", conn_id);
907         return GATT_BUSY;
908     }
909 
910     if ( (p_clcb = gatt_clcb_alloc(conn_id)) != NULL  )
911     {
912         p_clcb->operation = GATTC_OPTYPE_READ;
913         p_clcb->op_subtype = type;
914         p_clcb->auth_req = p_read->by_handle.auth_req;
915         p_clcb->counter = 0;
916 
917         switch (type)
918         {
919             case GATT_READ_BY_TYPE:
920             case GATT_READ_CHAR_VALUE:
921                 p_clcb->s_handle = p_read->service.s_handle;
922                 p_clcb->e_handle = p_read->service.e_handle;
923                 memcpy(&p_clcb->uuid, &p_read->service.uuid, sizeof(tBT_UUID));
924                 break;
925             case GATT_READ_MULTIPLE:
926                 p_clcb->s_handle = 0;
927                 /* copy multiple handles in CB */
928                 p_read_multi = (tGATT_READ_MULTI *)GKI_getbuf(sizeof(tGATT_READ_MULTI));
929                 p_clcb->p_attr_buf = (UINT8*)p_read_multi;
930                 memcpy (p_read_multi, &p_read->read_multiple, sizeof(tGATT_READ_MULTI));
931             case GATT_READ_BY_HANDLE:
932             case GATT_READ_PARTIAL:
933                 memset(&p_clcb->uuid, 0, sizeof(tBT_UUID));
934                 p_clcb->s_handle = p_read->by_handle.handle;
935 
936                 if (type == GATT_READ_PARTIAL)
937                 {
938                     p_clcb->counter = p_read->partial.offset;
939                 }
940 
941                 break;
942             default:
943                 break;
944         }
945         /* start security check */
946         if (gatt_security_check_start(p_clcb) == FALSE)
947         {
948             status = GATT_NO_RESOURCES;
949             gatt_clcb_dealloc(p_clcb);
950         }
951     }
952     else
953     {
954         status = GATT_NO_RESOURCES;
955     }
956     return status;
957 }
958 
959 /*******************************************************************************
960 **
961 ** Function         GATTC_Write
962 **
963 ** Description      This function is called to write the value of an attribute to
964 **                  the server.
965 **
966 ** Parameters       conn_id: connection identifier.
967 **                  type    - attribute write type.
968 **                  p_write  - write operation parameters.
969 **
970 ** Returns          GATT_SUCCESS if command started successfully.
971 **
972 *******************************************************************************/
GATTC_Write(UINT16 conn_id,tGATT_WRITE_TYPE type,tGATT_VALUE * p_write)973 tGATT_STATUS GATTC_Write (UINT16 conn_id, tGATT_WRITE_TYPE type, tGATT_VALUE *p_write)
974 {
975     tGATT_STATUS status = GATT_SUCCESS;
976     tGATT_CLCB      *p_clcb;
977     tGATT_VALUE     *p;
978     tGATT_IF        gatt_if=GATT_GET_GATT_IF(conn_id);
979     UINT8           tcb_idx = GATT_GET_TCB_IDX(conn_id);
980     tGATT_TCB       *p_tcb = gatt_get_tcb_by_idx(tcb_idx);
981     tGATT_REG       *p_reg = gatt_get_regcb(gatt_if);
982 
983     if ( (p_tcb == NULL) || (p_reg==NULL) || (p_write == NULL) ||
984          ((type != GATT_WRITE) && (type != GATT_WRITE_PREPARE) && (type != GATT_WRITE_NO_RSP)) )
985     {
986         GATT_TRACE_ERROR2("GATT_Write Illegal param: conn_id %d, type 0%d,", conn_id, type);
987         return GATT_ILLEGAL_PARAMETER;
988     }
989 
990     if (gatt_is_clcb_allocated(conn_id))
991     {
992         GATT_TRACE_ERROR1("GATTC_Write GATT_BUSY conn_id = %d", conn_id);
993         return GATT_BUSY;
994     }
995 
996     if ((p_clcb = gatt_clcb_alloc(conn_id)) != NULL )
997     {
998         p_clcb->operation  = GATTC_OPTYPE_WRITE;
999         p_clcb->op_subtype = type;
1000         p_clcb->auth_req = p_write->auth_req;
1001 
1002         if (( p_clcb->p_attr_buf = (UINT8 *)GKI_getbuf((UINT16)sizeof(tGATT_VALUE))) != NULL)
1003         {
1004             memcpy(p_clcb->p_attr_buf, (void *)p_write, sizeof(tGATT_VALUE));
1005 
1006             p =  (tGATT_VALUE *)p_clcb->p_attr_buf;
1007             if (type == GATT_WRITE_PREPARE)
1008             {
1009                 p_clcb->start_offset = p_write->offset;
1010                 p->offset = 0;
1011             }
1012 
1013             if (gatt_security_check_start(p_clcb) == FALSE)
1014             {
1015                 status = GATT_NO_RESOURCES;
1016             }
1017         }
1018         else
1019         {
1020             status = GATT_NO_RESOURCES;
1021         }
1022 
1023         if (status == GATT_NO_RESOURCES)
1024             gatt_clcb_dealloc(p_clcb);
1025     }
1026     else
1027     {
1028         status = GATT_NO_RESOURCES;
1029     }
1030     return status;
1031 }
1032 
1033 
1034 /*******************************************************************************
1035 **
1036 ** Function         GATTC_ExecuteWrite
1037 **
1038 ** Description      This function is called to send an Execute write request to
1039 **                  the server.
1040 **
1041 ** Parameters       conn_id: connection identifier.
1042 **                  is_execute - to execute or cancel the prepare write requet(s)
1043 **
1044 ** Returns          GATT_SUCCESS if command started successfully.
1045 **
1046 *******************************************************************************/
GATTC_ExecuteWrite(UINT16 conn_id,BOOLEAN is_execute)1047 tGATT_STATUS GATTC_ExecuteWrite (UINT16 conn_id, BOOLEAN is_execute)
1048 {
1049     tGATT_STATUS status = GATT_SUCCESS;
1050     tGATT_CLCB      *p_clcb;
1051     tGATT_EXEC_FLAG flag;
1052     tGATT_IF        gatt_if=GATT_GET_GATT_IF(conn_id);
1053     UINT8           tcb_idx = GATT_GET_TCB_IDX(conn_id);
1054     tGATT_TCB       *p_tcb = gatt_get_tcb_by_idx(tcb_idx);
1055     tGATT_REG       *p_reg = gatt_get_regcb(gatt_if);
1056 
1057     GATT_TRACE_API2 ("GATTC_ExecuteWrite conn_id=%d is_execute=%d", conn_id, is_execute);
1058 
1059     if ( (p_tcb == NULL) || (p_reg==NULL) )
1060     {
1061         GATT_TRACE_ERROR1("GATTC_ExecuteWrite Illegal param: conn_id %d", conn_id);
1062         return GATT_ILLEGAL_PARAMETER;
1063     }
1064 
1065     if (gatt_is_clcb_allocated(conn_id))
1066     {
1067         GATT_TRACE_ERROR1("GATTC_Write GATT_BUSY conn_id = %d", conn_id);
1068         return GATT_BUSY;
1069     }
1070 
1071     if ((p_clcb = gatt_clcb_alloc(conn_id)) != NULL)
1072     {
1073         p_clcb->operation  = GATTC_OPTYPE_EXE_WRITE;
1074         flag = is_execute ? GATT_PREP_WRITE_EXEC : GATT_PREP_WRITE_CANCEL;
1075         gatt_send_queue_write_cancel (p_clcb->p_tcb, p_clcb, flag);
1076     }
1077     else
1078     {
1079         GATT_TRACE_ERROR1("Unable to allocate client CB for conn_id %d ", conn_id);
1080         status = GATT_NO_RESOURCES;
1081     }
1082     return status;
1083 }
1084 
1085 /*******************************************************************************
1086 **
1087 ** Function         GATTC_SendHandleValueConfirm
1088 **
1089 ** Description      This function is called to send a handle value confirmation
1090 **                  as response to a handle value notification from server.
1091 **
1092 ** Parameters       conn_id: connection identifier.
1093 **                  handle: the handle of the attribute confirmation.
1094 **
1095 ** Returns          GATT_SUCCESS if command started successfully.
1096 **
1097 *******************************************************************************/
GATTC_SendHandleValueConfirm(UINT16 conn_id,UINT16 handle)1098 tGATT_STATUS GATTC_SendHandleValueConfirm (UINT16 conn_id, UINT16 handle)
1099 {
1100     tGATT_STATUS    ret = GATT_ILLEGAL_PARAMETER;
1101     tGATT_TCB     *p_tcb=gatt_get_tcb_by_idx(GATT_GET_TCB_IDX(conn_id));
1102 
1103     GATT_TRACE_API2 ("GATTC_SendHandleValueConfirm conn_id=%d handle=0x%x", conn_id, handle);
1104 
1105     if (p_tcb)
1106     {
1107         if (p_tcb->ind_count > 0 )
1108         {
1109             btu_stop_timer (&p_tcb->ind_ack_timer_ent);
1110 
1111             GATT_TRACE_DEBUG1 ("notif_count=%d ", p_tcb->ind_count);
1112             /* send confirmation now */
1113             ret = attp_send_cl_msg(p_tcb, 0, GATT_HANDLE_VALUE_CONF, (tGATT_CL_MSG *)&handle);
1114 
1115             p_tcb->ind_count = 0;
1116 
1117         }
1118         else
1119         {
1120             GATT_TRACE_DEBUG1 ("GATTC_SendHandleValueConfirm - conn_id: %u - ignored not waiting for indicaiton ack", conn_id);
1121             ret = GATT_SUCCESS;
1122         }
1123     }
1124     else
1125     {
1126         GATT_TRACE_ERROR1 ("GATTC_SendHandleValueConfirm - Unknown conn_id: %u", conn_id);
1127     }
1128     return ret;
1129 }
1130 
1131 
1132 /*******************************************************************************/
1133 /*                                                                             */
1134 /*                   GATT  APIs                                                */
1135 /*                                                                             */
1136 /*******************************************************************************/
1137 /*******************************************************************************
1138 **
1139 ** Function         GATT_SetIdleTimeout
1140 **
1141 ** Description      This function (common to both client and server) sets the idle
1142 **                  timeout for a tansport connection
1143 **
1144 ** Parameter        bd_addr:   target device bd address.
1145 **                  idle_tout: timeout value in seconds.
1146 **
1147 ** Returns          void
1148 **
1149 *******************************************************************************/
GATT_SetIdleTimeout(BD_ADDR bd_addr,UINT16 idle_tout)1150 void GATT_SetIdleTimeout (BD_ADDR bd_addr, UINT16 idle_tout)
1151 {
1152     tGATT_TCB       *p_tcb;
1153     BOOLEAN         status = FALSE;
1154 
1155     if ((p_tcb = gatt_find_tcb_by_addr (bd_addr)) != NULL)
1156     {
1157         if (p_tcb->att_lcid == L2CAP_ATT_CID)
1158         {
1159             status = L2CA_SetFixedChannelTout (bd_addr, L2CAP_ATT_CID, idle_tout);
1160         }
1161         else
1162         {
1163             status = L2CA_SetIdleTimeout (p_tcb->att_lcid, idle_tout, FALSE);
1164         }
1165     }
1166 
1167     GATT_TRACE_API2 ("GATT_SetIdleTimeout idle_tout=%d status=%d(1-OK 0-not performed)",
1168                     idle_tout, status);
1169 }
1170 
1171 
1172 /*******************************************************************************
1173 **
1174 ** Function         GATT_Register
1175 **
1176 ** Description      This function is called to register an  application
1177 **                  with GATT
1178 **
1179 ** Parameter        p_app_uuid128: Application UUID
1180 **                  p_cb_info: callback functions.
1181 **
1182 ** Returns          0 for error, otherwise the index of the client registered with GATT
1183 **
1184 *******************************************************************************/
GATT_Register(tBT_UUID * p_app_uuid128,tGATT_CBACK * p_cb_info)1185 tGATT_IF GATT_Register (tBT_UUID *p_app_uuid128, tGATT_CBACK *p_cb_info)
1186 {
1187     tGATT_REG    *p_reg;
1188     UINT8        i_gatt_if=0;
1189     tGATT_IF     gatt_if=0;
1190 
1191     GATT_TRACE_API0 ("GATT_Register");
1192     gatt_dbg_display_uuid(*p_app_uuid128);
1193 
1194     for (i_gatt_if = 0, p_reg = gatt_cb.cl_rcb; i_gatt_if < GATT_MAX_APPS; i_gatt_if++, p_reg++)
1195     {
1196         if (p_reg->in_use  && !memcmp(p_app_uuid128->uu.uuid128, p_reg->app_uuid128.uu.uuid128, LEN_UUID_128))
1197         {
1198             GATT_TRACE_ERROR0("application already registered.");
1199             return 0;
1200         }
1201     }
1202 
1203     for (i_gatt_if = 0, p_reg = gatt_cb.cl_rcb; i_gatt_if < GATT_MAX_APPS; i_gatt_if++, p_reg++)
1204     {
1205         if (!p_reg->in_use)
1206         {
1207             memset(p_reg, 0 , sizeof(tGATT_REG));
1208             i_gatt_if++;              /* one based number */
1209             p_reg->app_uuid128 =  *p_app_uuid128;
1210             gatt_if            =
1211             p_reg->gatt_if     = (tGATT_IF)i_gatt_if;
1212             p_reg->app_cb      = *p_cb_info;
1213             p_reg->in_use      = TRUE;
1214 
1215             break;
1216         }
1217     }
1218     GATT_TRACE_API1 ("allocated gatt_if=%d", gatt_if);
1219     return gatt_if;
1220 }
1221 
1222 
1223 /*******************************************************************************
1224 **
1225 ** Function         GATT_Deregister
1226 **
1227 ** Description      This function deregistered the application from GATT.
1228 **
1229 ** Parameters       gatt_if: applicaiton interface.
1230 **
1231 ** Returns          None.
1232 **
1233 *******************************************************************************/
GATT_Deregister(tGATT_IF gatt_if)1234 void GATT_Deregister (tGATT_IF gatt_if)
1235 {
1236     tGATT_REG       *p_reg = gatt_get_regcb(gatt_if);
1237     tGATT_TCB       *p_tcb;
1238     tGATT_CLCB       *p_clcb;
1239     UINT8           i, ii, j;
1240     tGATT_SR_REG    *p_sreg;
1241 
1242     GATT_TRACE_API1 ("GATT_Deregister gatt_if=%d", gatt_if);
1243     /* Index 0 is GAP and is never deregistered */
1244     if ( (gatt_if == 0) || (p_reg == NULL) )
1245     {
1246         GATT_TRACE_ERROR1 ("GATT_Deregister with invalid gatt_if: %u", gatt_if);
1247         return;
1248     }
1249 
1250     /* stop all services  */
1251     /* todo an applcaiton can not be deregistered if its services is also used by other application
1252       deregisteration need to bed performed in an orderly fashion
1253       no check for now */
1254 
1255     for (ii = 0, p_sreg = gatt_cb.sr_reg; ii < GATT_MAX_SR_PROFILES; ii++, p_sreg++)
1256     {
1257         if (p_sreg->in_use && (p_sreg->gatt_if == gatt_if))
1258         {
1259             GATTS_StopService(p_sreg->s_hdl);
1260         }
1261     }
1262 
1263     /* free all services db buffers if owned by this application */
1264     gatt_free_srvc_db_buffer_app_id(&p_reg->app_uuid128);
1265 
1266     /* When an application deregisters, check remove the link associated with the app */
1267 
1268     for (i=0, p_tcb = gatt_cb.tcb; i < GATT_MAX_PHY_CHANNEL; i++, p_tcb++)
1269     {
1270         if (p_tcb->in_use)
1271         {
1272             if (gatt_get_ch_state(p_tcb) != GATT_CH_CLOSE)
1273             {
1274                 gatt_update_app_use_link_flag(gatt_if, p_tcb,  FALSE, FALSE);
1275                 if (!gatt_num_apps_hold_link(p_tcb))
1276                 {
1277                     /* this will disconnect the link or cancel the pending connect request at lower layer*/
1278                     gatt_disconnect(p_tcb->peer_bda);
1279                 }
1280             }
1281 
1282             for (j = 0, p_clcb= &gatt_cb.clcb[j]; j < GATT_CL_MAX_LCB; j++, p_clcb++)
1283             {
1284                 if (p_clcb->in_use &&
1285                     (p_clcb->p_reg->gatt_if == gatt_if) &&
1286                     (p_clcb->p_tcb->tcb_idx == p_tcb->tcb_idx))
1287                 {
1288                     gatt_clcb_dealloc (p_clcb);
1289                     break;
1290                 }
1291             }
1292         }
1293     }
1294 
1295     gatt_deregister_bgdev_list(gatt_if);
1296     /* update the listen mode */
1297 #ifdef BLE_PERIPHERAL_MODE_SUPPORT
1298     GATT_Listen(gatt_if, FALSE, NULL);
1299 #endif
1300 
1301     memset (p_reg, 0, sizeof(tGATT_REG));
1302 }
1303 
1304 
1305 /*******************************************************************************
1306 **
1307 ** Function         GATT_StartIf
1308 **
1309 ** Description      This function is called after registration to start receiving
1310 **                  callbacks for registered interface.  Function may call back
1311 **                  with connection status and queued notifications
1312 **
1313 ** Parameter        gatt_if: applicaiton interface.
1314 **
1315 ** Returns          0 for error, otherwise the index of the client registered with GATT
1316 **
1317 *******************************************************************************/
GATT_StartIf(tGATT_IF gatt_if)1318 void GATT_StartIf (tGATT_IF gatt_if)
1319 {
1320     tGATT_REG   *p_reg;
1321     tGATT_TCB   *p_tcb;
1322     BD_ADDR     bda;
1323     UINT8       start_idx, found_idx;
1324     UINT16      conn_id;
1325 
1326     GATT_TRACE_API1 ("GATT_StartIf gatt_if=%d", gatt_if);
1327     if ((p_reg = gatt_get_regcb(gatt_if)) != NULL)
1328     {
1329         p_reg = &gatt_cb.cl_rcb[gatt_if - 1];
1330         start_idx = 0;
1331         while (gatt_find_the_connected_bda(start_idx, bda, &found_idx))
1332         {
1333             p_tcb = gatt_find_tcb_by_addr(bda);
1334             if (p_reg->app_cb.p_conn_cb && p_tcb)
1335             {
1336                 conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, gatt_if);
1337                 (*p_reg->app_cb.p_conn_cb)(gatt_if, bda, conn_id, TRUE, 0);
1338             }
1339             start_idx = ++found_idx;
1340         }
1341     }
1342 }
1343 
1344 
1345 /*******************************************************************************
1346 **
1347 ** Function         GATT_Connect
1348 **
1349 ** Description      This function initiate a connecttion to a remote device on GATT
1350 **                  channel.
1351 **
1352 ** Parameters       gatt_if: applicaiton interface
1353 **                  bd_addr: peer device address.
1354 **                  is_direct: is a direct conenection or a background auto connection
1355 **
1356 ** Returns          TRUE if connection started; FALSE if connection start failure.
1357 **
1358 *******************************************************************************/
GATT_Connect(tGATT_IF gatt_if,BD_ADDR bd_addr,BOOLEAN is_direct)1359 BOOLEAN GATT_Connect (tGATT_IF gatt_if, BD_ADDR bd_addr, BOOLEAN is_direct){
1360     tGATT_REG    *p_reg;
1361     BOOLEAN status;
1362 
1363     GATT_TRACE_API1 ("GATT_Connect gatt_if=%d", gatt_if);
1364 
1365     /* Make sure app is registered */
1366     if ((p_reg = gatt_get_regcb(gatt_if)) == NULL)
1367     {
1368         GATT_TRACE_ERROR1("GATT_Connect - gatt_if =%d is not registered", gatt_if);
1369         return(FALSE);
1370     }
1371 
1372     if (is_direct)
1373         status = gatt_act_connect (p_reg, bd_addr);
1374     else
1375         status = gatt_update_auto_connect_dev(gatt_if,TRUE, bd_addr, TRUE);
1376 
1377     return status;
1378 
1379 }
1380 
1381 /*******************************************************************************
1382 **
1383 ** Function         GATT_CancelConnect
1384 **
1385 ** Description      This function terminate the connection initaition to a remote
1386 **                  device on GATT channel.
1387 **
1388 ** Parameters       gatt_if: client interface. If 0 used as unconditionally disconnect,
1389 **                          typically used for direct connection cancellation.
1390 **                  bd_addr: peer device address.
1391 **
1392 ** Returns          TRUE if connection started; FALSE if connection start failure.
1393 **
1394 *******************************************************************************/
GATT_CancelConnect(tGATT_IF gatt_if,BD_ADDR bd_addr,BOOLEAN is_direct)1395 BOOLEAN GATT_CancelConnect (tGATT_IF gatt_if, BD_ADDR bd_addr, BOOLEAN is_direct){
1396     tGATT_REG     *p_reg;
1397     tGATT_TCB     *p_tcb;
1398     BOOLEAN       status = TRUE;
1399     tGATT_IF      temp_gatt_if;
1400     UINT8         start_idx, found_idx;
1401 
1402     GATT_TRACE_API1 ("GATT_CancelConnect gatt_if=%d", gatt_if);
1403 
1404     if ((gatt_if != 0) && ((p_reg = gatt_get_regcb(gatt_if)) == NULL))
1405     {
1406         GATT_TRACE_ERROR1("GATT_CancelConnect - gatt_if =%d is not registered", gatt_if);
1407         return(FALSE);
1408     }
1409 
1410     if (is_direct)
1411     {
1412         if (!gatt_if)
1413         {
1414             GATT_TRACE_DEBUG0("GATT_CancelConnect - unconditional");
1415             start_idx = 0;
1416             p_tcb = gatt_find_tcb_by_addr(bd_addr);
1417             if (p_tcb && gatt_num_apps_hold_link(p_tcb))
1418             {
1419                 while (status && gatt_find_app_hold_link(p_tcb, start_idx, &found_idx, &temp_gatt_if))
1420                 {
1421                     status = gatt_cancel_open(temp_gatt_if, bd_addr);
1422                     start_idx = ++found_idx;
1423                 }
1424             }
1425             else
1426             {
1427                 GATT_TRACE_ERROR0("GATT_CancelConnect - no app found");
1428                 status = FALSE;
1429             }
1430         }
1431         else
1432         {
1433             status = gatt_cancel_open(gatt_if, bd_addr);
1434         }
1435     }
1436     else
1437     {
1438         if (!gatt_if)
1439         {
1440             if (gatt_get_num_apps_for_bg_dev(bd_addr))
1441             {
1442                 while (gatt_find_app_for_bg_dev(bd_addr, &temp_gatt_if))
1443                     gatt_remove_bg_dev_for_app(temp_gatt_if, bd_addr);
1444             }
1445             else
1446             {
1447                 GATT_TRACE_ERROR0("GATT_CancelConnect -no app associated with the bg device for unconditional removal");
1448                 status = FALSE;
1449             }
1450         }
1451         else
1452         {
1453             status = gatt_remove_bg_dev_for_app(gatt_if, bd_addr);
1454         }
1455     }
1456 
1457     return status;
1458 }
1459 
1460 /*******************************************************************************
1461 **
1462 ** Function         GATT_Disconnect
1463 **
1464 ** Description      This function disconnect the GATT channel for this registered
1465 **                  application.
1466 **
1467 ** Parameters       conn_id: connection identifier.
1468 **
1469 ** Returns          GATT_SUCCESS if disconnected.
1470 **
1471 *******************************************************************************/
GATT_Disconnect(UINT16 conn_id)1472 tGATT_STATUS GATT_Disconnect (UINT16 conn_id)
1473 {
1474     tGATT_STATUS    ret = GATT_ILLEGAL_PARAMETER;
1475     tGATT_TCB       *p_tcb=NULL;
1476     tGATT_IF        gatt_if=GATT_GET_GATT_IF(conn_id);
1477     UINT8          tcb_idx = GATT_GET_TCB_IDX(conn_id);
1478 
1479     GATT_TRACE_API1 ("GATT_Disconnect conn_id=%d ", conn_id);
1480 
1481     p_tcb = gatt_get_tcb_by_idx(tcb_idx);
1482 
1483     if (p_tcb)
1484     {
1485         gatt_update_app_use_link_flag(gatt_if, p_tcb, FALSE, FALSE);
1486         if (!gatt_num_apps_hold_link(p_tcb))
1487         {
1488             gatt_disconnect(p_tcb->peer_bda);
1489         }
1490         ret = GATT_SUCCESS;
1491     }
1492     return ret;
1493 }
1494 
1495 
1496 /*******************************************************************************
1497 **
1498 ** Function         GATT_GetConnectionInfor
1499 **
1500 ** Description      This function use conn_id to find its associated BD address and applciation
1501 **                  interface
1502 **
1503 ** Parameters        conn_id: connection id  (input)
1504 **                   p_gatt_if: applicaiton interface (output)
1505 **                   bd_addr: peer device address. (output)
1506 **
1507 ** Returns          TRUE the ligical link information is found for conn_id
1508 **
1509 *******************************************************************************/
GATT_GetConnectionInfor(UINT16 conn_id,tGATT_IF * p_gatt_if,BD_ADDR bd_addr)1510 BOOLEAN GATT_GetConnectionInfor(UINT16 conn_id, tGATT_IF *p_gatt_if, BD_ADDR bd_addr)
1511 {
1512 
1513     tGATT_IF        gatt_if = GATT_GET_GATT_IF(conn_id);
1514     tGATT_REG       *p_reg = gatt_get_regcb(gatt_if);
1515     UINT8           tcb_idx = GATT_GET_TCB_IDX(conn_id);
1516     tGATT_TCB       *p_tcb= gatt_get_tcb_by_idx(tcb_idx);
1517     BOOLEAN         status=FALSE;
1518 
1519     GATT_TRACE_API1 ("GATT_GetConnectionInfor conn_id=%d", conn_id);
1520 
1521     if (p_tcb && p_reg )
1522     {
1523         memcpy(bd_addr, p_tcb->peer_bda, BD_ADDR_LEN);
1524         *p_gatt_if = gatt_if;
1525         status = TRUE;
1526     }
1527     return status;
1528 }
1529 
1530 
1531 /*******************************************************************************
1532 **
1533 ** Function         GATT_GetConnIdIfConnected
1534 **
1535 ** Description      This function find the conn_id if the logical link for BD address
1536 **                  and applciation interface is connected
1537 **
1538 ** Parameters        gatt_if: applicaiton interface (input)
1539 **                   bd_addr: peer device address. (input)
1540 **                   p_conn_id: connection id  (output)
1541 **
1542 ** Returns          TRUE the logical link is connected
1543 **
1544 *******************************************************************************/
GATT_GetConnIdIfConnected(tGATT_IF gatt_if,BD_ADDR bd_addr,UINT16 * p_conn_id)1545 BOOLEAN GATT_GetConnIdIfConnected(tGATT_IF gatt_if, BD_ADDR bd_addr, UINT16 *p_conn_id)
1546 {
1547     tGATT_REG       *p_reg = gatt_get_regcb(gatt_if);
1548     tGATT_TCB       *p_tcb= gatt_find_tcb_by_addr(bd_addr);
1549     BOOLEAN         status=FALSE;
1550 
1551     if (p_reg && p_tcb && (gatt_get_ch_state(p_tcb) == GATT_CH_OPEN) )
1552     {
1553         *p_conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, gatt_if);
1554         status = TRUE;
1555     }
1556 
1557     GATT_TRACE_API1 ("GATT_GetConnIdIfConnected status=%d", status);
1558     return status;
1559 }
1560 
1561 
1562 /*******************************************************************************
1563 **
1564 ** Function         GATT_Listen
1565 **
1566 ** Description      This function start or stop LE advertisement and listen for
1567 **                  connection.
1568 **
1569 ** Parameters       gatt_if: applicaiton interface
1570 **                  p_bd_addr: listen for specific address connection, or NULL for
1571 **                             listen to all device connection.
1572 **                  start: start or stop listening.
1573 **
1574 ** Returns          TRUE if advertisement is started; FALSE if adv start failure.
1575 **
1576 *******************************************************************************/
GATT_Listen(tGATT_IF gatt_if,BOOLEAN start,BD_ADDR_PTR bd_addr)1577 BOOLEAN GATT_Listen (tGATT_IF gatt_if, BOOLEAN start, BD_ADDR_PTR bd_addr)
1578 {
1579     tGATT_REG    *p_reg;
1580     BOOLEAN status = TRUE;
1581 
1582     GATT_TRACE_API1 ("GATT_Listen gatt_if=%d", gatt_if);
1583 
1584     /* Make sure app is registered */
1585     if ((p_reg = gatt_get_regcb(gatt_if)) == NULL)
1586     {
1587         GATT_TRACE_ERROR1("GATT_Listen - gatt_if =%d is not registered", gatt_if);
1588         return(FALSE);
1589     }
1590 
1591     if (bd_addr != NULL)
1592     {
1593         status = gatt_update_auto_connect_dev(gatt_if,start, bd_addr, FALSE);
1594     }
1595     else
1596     {
1597         p_reg->listening = start ? GATT_LISTEN_TO_ALL : GATT_LISTEN_TO_NONE;
1598     }
1599 
1600     gatt_update_listen_mode();
1601 
1602     return status;
1603 
1604 }
1605 
1606 #endif
1607 
1608