OSDN Git Service

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