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