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