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