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