1 /******************************************************************************
3 * Copyright (C) 1999-2012 Broadcom Corporation
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:
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 ******************************************************************************/
19 /******************************************************************************
21 * this file contains GATT interface functions
23 ******************************************************************************/
24 #include "bt_target.h"
27 #if defined(BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE)
29 #include "bt_common.h"
38 /*******************************************************************************
40 ** Function GATT_SetTraceLevel
42 ** Description This function sets the trace level. If called with
43 ** a value of 0xFF, it simply returns the current trace level.
46 ** level: The level to set the GATT tracing to:
47 ** 0xff-returns the current setting.
48 ** 0-turns off tracing.
55 ** Returns The new or current trace level
57 *******************************************************************************/
58 UINT8 GATT_SetTraceLevel (UINT8 new_level)
60 if (new_level != 0xFF)
61 gatt_cb.trace_level = new_level;
63 return(gatt_cb.trace_level);
66 /*****************************************************************************
70 ******************************************************************************/
71 /*******************************************************************************
73 ** Function GATTS_AddHandleRange
75 ** Description This function add the allocated handles range for the specifed
76 ** application UUID, service UUID and service instance
78 ** Parameter p_hndl_range: pointer to allocated handles information
80 ** Returns TRUE if handle range is added sucessfully; otherwise FALSE.
82 *******************************************************************************/
84 BOOLEAN GATTS_AddHandleRange(tGATTS_HNDL_RANGE *p_hndl_range)
86 tGATT_HDL_LIST_ELEM *p_buf;
87 BOOLEAN status= FALSE;
89 if ((p_buf = gatt_alloc_hdl_buffer()) != NULL)
91 p_buf->asgn_range = *p_hndl_range;
92 status = gatt_add_an_item_to_list(&gatt_cb.hdl_list_info, p_buf);
98 /*******************************************************************************
100 ** Function GATTS_NVRegister
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.
106 ** Parameter p_cb_info : callback informaiton
108 ** Returns TRUE if registered OK, else FALSE
110 *******************************************************************************/
111 BOOLEAN GATTS_NVRegister (tGATT_APPL_INFO *p_cb_info)
113 BOOLEAN status= FALSE;
116 gatt_cb.cb_info = *p_cb_info;
124 /*******************************************************************************
126 ** Function GATTS_CreateService
128 ** Description This function is called to reserve a block of handles for a service.
130 ** *** It should be called only once per service instance ***
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.
138 ** Returns service handle if sucessful, otherwise 0.
140 *******************************************************************************/
141 UINT16 GATTS_CreateService (tGATT_IF gatt_if, tBT_UUID *p_svc_uuid,
142 UINT16 svc_inst, UINT16 num_handles, BOOLEAN is_pri)
145 tGATT_HDL_LIST_INFO *p_list_info= &gatt_cb.hdl_list_info;
146 tGATT_HDL_LIST_ELEM *p_list=NULL;
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;
154 GATT_TRACE_API ("GATTS_CreateService" );
158 GATT_TRACE_ERROR ("Inavlid gatt_if=%d", gatt_if);
162 p_app_uuid128 = &p_reg->app_uuid128;
164 if ((p_list = gatt_find_hdl_buffer_by_app_id(p_app_uuid128, p_svc_uuid, svc_inst)) != NULL)
166 s_hdl = p_list->asgn_range.s_handle;
167 GATT_TRACE_DEBUG ("Service already been created!!");
171 if ( (p_svc_uuid->len == LEN_UUID_16) && (p_svc_uuid->uu.uuid16 == UUID_SERVCLASS_GATT_SERVER))
173 s_hdl= gatt_cb.hdl_cfg.gatt_start_hdl;
175 else if ((p_svc_uuid->len == LEN_UUID_16) && (p_svc_uuid->uu.uuid16 == UUID_SERVCLASS_GAP_SERVER))
177 s_hdl= gatt_cb.hdl_cfg.gap_start_hdl;
181 p_list = p_list_info->p_first;
185 s_hdl = p_list->asgn_range.e_handle + 1;
188 if (s_hdl < gatt_cb.hdl_cfg.app_start_hdl)
191 s_hdl= gatt_cb.hdl_cfg.app_start_hdl;
196 /* check for space */
197 if (num_handles > (0xFFFF - s_hdl + 1))
199 GATT_TRACE_ERROR ("GATTS_ReserveHandles: no handles, s_hdl: %u needed: %u", s_hdl, num_handles);
203 if ( (p_list = gatt_alloc_hdl_buffer()) == NULL)
206 GATT_TRACE_ERROR ("GATTS_ReserveHandles: no free handle blocks");
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;
217 gatt_add_an_item_to_list(p_list_info, p_list);
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)
227 GATT_TRACE_ERROR ("gatt_add_pending_new_srv_start: no free blocks");
231 gatt_remove_an_item_from_list(p_list_info, p_list);
232 gatt_free_hdl_buffer(p_list);
237 GATT_TRACE_DEBUG ("Add a new srv chg item");
241 if (!gatts_init_service_db(&p_list->svc_db, p_svc_uuid, is_pri, s_hdl , num_handles))
243 GATT_TRACE_ERROR ("GATTS_ReserveHandles: service DB initialization failed");
246 gatt_remove_an_item_from_list(p_list_info, p_list);
247 gatt_free_hdl_buffer(p_list);
251 osi_freebuf(fixed_queue_try_remove_from_queue(gatt_cb.pending_new_srv_start_q, p_buf));
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);
264 /*******************************************************************************
266 ** Function GATTS_AddIncludeService
268 ** Description This function is called to add an included service.
270 ** Parameter service_handle : To which service this included service is added to.
271 ** include_svc_handle : included service handle.
273 ** Returns included service attribute handle. If 0, add included service
276 *******************************************************************************/
277 UINT16 GATTS_AddIncludeService (UINT16 service_handle, UINT16 include_svc_handle)
280 tGATT_HDL_LIST_ELEM *p_decl, *p_incl_decl;
282 if ((p_decl = gatt_find_hdl_buffer_by_handle(service_handle)) == NULL)
284 GATT_TRACE_DEBUG("Service not created");
287 if ((p_incl_decl = gatt_find_hdl_buffer_by_handle(include_svc_handle)) == NULL)
289 GATT_TRACE_DEBUG("Included Service not created");
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);
298 /*******************************************************************************
300 ** Function GATTS_AddCharacteristic
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
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
312 ** Returns Characteristic value declaration attribute handle. 0 if failed.
314 *******************************************************************************/
315 UINT16 GATTS_AddCharacteristic (UINT16 service_handle, tBT_UUID *p_char_uuid,
316 tGATT_PERM perm,tGATT_CHAR_PROP property)
318 tGATT_HDL_LIST_ELEM *p_decl;
320 if ((p_decl = gatt_find_hdl_buffer_by_handle(service_handle)) == NULL)
322 GATT_TRACE_DEBUG("Service not created");
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)) )
329 GATT_TRACE_DEBUG("Invalid configuration property=0x%x perm=0x%x ", property, perm);
333 return gatts_add_characteristic(&p_decl->svc_db,
338 /*******************************************************************************
340 ** Function GATTS_AddCharDescriptor
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.
347 ** Parameter service_handle : To which service this characteristic descriptor
349 ** perm : Characteristic value declaration attribute
351 ** p_descr_uuid : Characteristic descriptor UUID
353 ** Returns Characteristic descriptor attribute handle. 0 if add
354 ** characteristic descriptor failed.
356 *******************************************************************************/
357 UINT16 GATTS_AddCharDescriptor (UINT16 service_handle,
359 tBT_UUID * p_descr_uuid)
361 tGATT_HDL_LIST_ELEM *p_decl;
363 if ((p_decl = gatt_find_hdl_buffer_by_handle(service_handle)) == NULL)
365 GATT_TRACE_DEBUG("Service not created");
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))
372 GATT_TRACE_DEBUG("Illegal parameter");
376 return gatts_add_char_descr(&p_decl->svc_db,
381 /*******************************************************************************
383 ** Function GATTS_DeleteService
385 ** Description This function is called to delete a service.
387 ** Parameter gatt_if : application interface
388 ** p_svc_uuid : service UUID
389 ** svc_inst : instance of the service inside the application
391 ** Returns TRUE if operation succeed, FALSE if handle block was not found.
393 *******************************************************************************/
394 BOOLEAN GATTS_DeleteService (tGATT_IF gatt_if, tBT_UUID *p_svc_uuid, UINT16 svc_inst)
397 tGATT_HDL_LIST_INFO *p_list_info= &gatt_cb.hdl_list_info;
398 tGATT_HDL_LIST_ELEM *p_list=NULL;
400 tGATTS_PENDING_NEW_SRV_START *p_buf;
401 tGATT_REG *p_reg = gatt_get_regcb(gatt_if);
402 tBT_UUID *p_app_uuid128;
404 GATT_TRACE_DEBUG ("GATTS_DeleteService");
408 GATT_TRACE_ERROR ("Applicaiton not foud");
411 p_app_uuid128 = &p_reg->app_uuid128;
413 if ((p_list = gatt_find_hdl_buffer_by_app_id(p_app_uuid128, p_svc_uuid, svc_inst)) == NULL)
415 GATT_TRACE_ERROR ("No Service found");
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)
423 GATT_TRACE_DEBUG ("Delete a new service changed item - the service has not yet started");
424 osi_freebuf(fixed_queue_try_remove_from_queue(gatt_cb.pending_new_srv_start_q, p_buf));
431 if ((i_sreg = gatt_sr_find_i_rcb_by_app_id (p_app_uuid128,
433 svc_inst)) != GATT_MAX_SR_PROFILES)
435 GATTS_StopService(gatt_cb.sr_reg[i_sreg].s_hdl);
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 );
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);
445 gatt_remove_an_item_from_list(p_list_info, p_list);
446 gatt_free_hdl_buffer(p_list);
451 /*******************************************************************************
453 ** Function GATTS_StartService
455 ** Description This function is called to start a service with GATT
457 ** Parameter gatt_if : service handle.
458 ** p_cback : application service callback functions.
459 ** sup_transport : supported transport(s) for this primary service
461 ** return GATT_SUCCESS if sucessfully started; otherwise error code.
463 *******************************************************************************/
464 tGATT_STATUS GATTS_StartService (tGATT_IF gatt_if, UINT16 service_handle,
465 tGATT_TRANSPORT sup_transport)
467 tGATT_SR_REG *p_sreg;
468 tGATT_HDL_LIST_ELEM *p_list=NULL;
471 tGATT_REG *p_reg = gatt_get_regcb(gatt_if);
473 tGATTS_PENDING_NEW_SRV_START *p_buf;
475 GATT_TRACE_API ("GATTS_StartService");
480 GATT_TRACE_ERROR ("Applicaiton not found ");
481 return GATT_NOT_FOUND;
484 if ((p_list = gatt_find_hdl_buffer_by_handle(service_handle)) == NULL)
487 GATT_TRACE_ERROR ("no service found");
488 return GATT_NOT_FOUND;
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)
495 GATT_TRACE_ERROR ("Duplicate Service start - Service already started");
496 return GATT_SERVICE_STARTED;
499 /*this is a new application servoce start */
500 if ((i_sreg = gatt_sr_alloc_rcb(p_list)) == GATT_MAX_SR_PROFILES)
502 GATT_TRACE_ERROR ("GATTS_StartService: no free server registration block");
503 return GATT_NO_RESOURCES;
506 p_sreg = &gatt_cb.sr_reg[i_sreg];
507 p_sreg->gatt_if = gatt_if;
509 switch (sup_transport)
511 case GATT_TRANSPORT_BR_EDR:
512 case GATT_TRANSPORT_LE_BR_EDR:
513 if (p_sreg->type == GATT_UUID_PRI_SERVICE)
515 p_uuid = gatts_get_service_uuid (p_sreg->p_db);
517 p_sreg->sdp_handle = gatt_add_sdp_record(p_uuid, p_sreg->s_hdl, p_sreg->e_hdl);
524 gatts_update_srv_list_elem(i_sreg, p_sreg->s_hdl,
525 p_list->asgn_range.is_primary);
527 gatt_add_a_srv_to_list(&gatt_cb.srv_list_info, &gatt_cb.srv_list[i_sreg]);
529 GATT_TRACE_DEBUG ("allocated i_sreg=%d ",i_sreg);
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,
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)
542 /* remove the new service element after the srv changed processing is completed*/
544 osi_freebuf(fixed_queue_try_remove_from_queue(gatt_cb.pending_new_srv_start_q, p_buf));
549 /*******************************************************************************
551 ** Function GATTS_StopService
553 ** Description This function is called to stop a service
555 ** Parameter service_handle : this is the start handle of a service
559 *******************************************************************************/
560 void GATTS_StopService (UINT16 service_handle)
562 UINT8 ii = gatt_sr_find_i_rcb_by_handle(service_handle);
564 GATT_TRACE_API("GATTS_StopService %u", service_handle);
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) )
569 if (gatt_cb.sr_reg[ii].sdp_handle)
571 SDP_DeleteRecord(gatt_cb.sr_reg[ii].sdp_handle);
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));
579 GATT_TRACE_ERROR("GATTS_StopService service_handle: %u is not in use", service_handle);
582 /*******************************************************************************
584 ** Function GATTs_HandleValueIndication
586 ** Description This function sends a handle value indication to a client.
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.
593 ** Returns GATT_SUCCESS if sucessfully sent or queued; otherwise error code.
595 *******************************************************************************/
596 tGATT_STATUS GATTS_HandleValueIndication (UINT16 conn_id, UINT16 attr_handle, UINT16 val_len, UINT8 *p_val)
598 tGATT_STATUS cmd_status = GATT_NO_RESOURCES;
600 tGATT_VALUE indication;
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);
609 GATT_TRACE_API ("GATTS_HandleValueIndication");
610 if ( (p_reg == NULL) || (p_tcb == NULL))
612 GATT_TRACE_ERROR ("GATTS_HandleValueIndication Unknown conn_id: %u ", conn_id);
613 return(tGATT_STATUS) GATT_INVALID_CONN_ID;
616 if (! GATT_HANDLE_IS_VALID (attr_handle))
617 return GATT_ILLEGAL_PARAMETER;
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;
625 if (GATT_HANDLE_IS_VALID(p_tcb->indicate_handle))
627 GATT_TRACE_DEBUG ("Add a pending indication");
628 if ((p_buf = gatt_add_pending_ind(p_tcb, &indication)) !=NULL)
630 cmd_status = GATT_SUCCESS;
634 cmd_status = GATT_NO_RESOURCES;
640 if ( (p_msg = attp_build_sr_msg (p_tcb, GATT_HANDLE_VALUE_IND, (tGATT_SR_MSG *)&indication)) != NULL)
642 cmd_status = attp_send_sr_msg (p_tcb, p_msg);
644 if (cmd_status == GATT_SUCCESS || cmd_status == GATT_CONGESTED)
646 p_tcb->indicate_handle = indication.handle;
647 gatt_start_conf_timer(p_tcb);
654 /*******************************************************************************
656 ** Function GATTS_HandleValueNotification
658 ** Description This function sends a handle value notification to a client.
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.
665 ** Returns GATT_SUCCESS if sucessfully sent; otherwise error code.
667 *******************************************************************************/
668 tGATT_STATUS GATTS_HandleValueNotification (UINT16 conn_id, UINT16 attr_handle,
669 UINT16 val_len, UINT8 *p_val)
671 tGATT_STATUS cmd_sent = GATT_ILLEGAL_PARAMETER;
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);
679 GATT_TRACE_API ("GATTS_HandleValueNotification");
681 if ( (p_reg == NULL) || (p_tcb == NULL))
683 GATT_TRACE_ERROR ("GATTS_HandleValueNotification Unknown conn_id: %u ", conn_id);
684 return(tGATT_STATUS) GATT_INVALID_CONN_ID;
687 if (GATT_HANDLE_IS_VALID (attr_handle))
689 notif.handle = attr_handle;
691 memcpy (notif.value, p_val, val_len);
692 notif.auth_req = GATT_AUTH_REQ_NONE;;
694 if ((p_buf = attp_build_sr_msg (p_tcb, GATT_HANDLE_VALUE_NOTIF, (tGATT_SR_MSG *)¬if))
697 cmd_sent = attp_send_sr_msg (p_tcb, p_buf);
700 cmd_sent = GATT_NO_RESOURCES;
705 /*******************************************************************************
707 ** Function GATTS_SendRsp
709 ** Description This function sends the server response to client.
711 ** Parameter conn_id: connection identifier.
712 ** trans_id: transaction id
713 ** status: response status
714 ** p_msg: pointer to message parameters structure.
716 ** Returns GATT_SUCCESS if sucessfully sent; otherwise error code.
718 *******************************************************************************/
719 tGATT_STATUS GATTS_SendRsp (UINT16 conn_id, UINT32 trans_id,
720 tGATT_STATUS status, tGATTS_RSP *p_msg)
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);
728 GATT_TRACE_API ("GATTS_SendRsp: conn_id: %u trans_id: %u Status: 0x%04x",
729 conn_id, trans_id, status);
731 if ( (p_reg == NULL) || (p_tcb == NULL))
733 GATT_TRACE_ERROR ("GATTS_SendRsp Unknown conn_id: %u ", conn_id);
734 return(tGATT_STATUS) GATT_INVALID_CONN_ID;
737 if (p_tcb->sr_cmd.trans_id != trans_id)
739 GATT_TRACE_ERROR ("GATTS_SendRsp conn_id: %u waiting for op_code = %02x",
740 conn_id, p_tcb->sr_cmd.op_code);
742 return(GATT_WRONG_STATE);
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);
750 /*******************************************************************************/
751 /* GATT Profile Srvr Functions */
752 /*******************************************************************************/
754 /*******************************************************************************/
756 /* GATT CLIENT APIs */
758 /*******************************************************************************/
761 /*******************************************************************************
763 ** Function GATTC_ConfigureMTU
765 ** Description This function is called to configure the ATT MTU size.
767 ** Parameters conn_id: connection identifier.
768 ** mtu - attribute MTU size..
770 ** Returns GATT_SUCCESS if command started successfully.
772 *******************************************************************************/
773 tGATT_STATUS GATTC_ConfigureMTU (UINT16 conn_id, UINT16 mtu)
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);
783 GATT_TRACE_API ("GATTC_ConfigureMTU conn_id=%d mtu=%d", conn_id, mtu );
785 /* Validate that the link is BLE, not BR/EDR */
786 if (p_tcb->transport != BT_TRANSPORT_LE)
791 if ( (p_tcb == NULL) || (p_reg==NULL) || (mtu < GATT_DEF_BLE_MTU_SIZE) || (mtu > GATT_MAX_MTU_SIZE))
793 return GATT_ILLEGAL_PARAMETER;
796 if (gatt_is_clcb_allocated(conn_id))
798 GATT_TRACE_ERROR("GATTC_ConfigureMTU GATT_BUSY conn_id = %d", conn_id);
802 if ((p_clcb = gatt_clcb_alloc(conn_id)) != NULL)
804 p_clcb->p_tcb->payload_size = mtu;
805 p_clcb->operation = GATTC_OPTYPE_CONFIG;
807 ret = attp_send_cl_msg (p_clcb->p_tcb, p_clcb->clcb_idx, GATT_REQ_MTU, (tGATT_CL_MSG *)&mtu);
813 /*******************************************************************************
815 ** Function GATTC_Discover
817 ** Description This function is called to do a discovery procedure on ATT server.
819 ** Parameters conn_id: connection identifier.
820 ** disc_type:discovery type.
821 ** p_param: parameters of discovery requirement.
823 ** Returns GATT_SUCCESS if command received/sent successfully.
825 *******************************************************************************/
826 tGATT_STATUS GATTC_Discover (UINT16 conn_id, tGATT_DISC_TYPE disc_type,
827 tGATT_DISC_PARAM *p_param)
829 tGATT_STATUS status = GATT_SUCCESS;
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);
837 GATT_TRACE_API ("GATTC_Discover conn_id=%d disc_type=%d",conn_id, disc_type);
839 if ( (p_tcb == NULL) || (p_reg==NULL) ||(p_param == NULL) ||
840 (disc_type >= GATT_DISC_MAX))
842 GATT_TRACE_ERROR("GATTC_Discover Illegal param: disc_type %d conn_id = %d", disc_type, conn_id);
843 return GATT_ILLEGAL_PARAMETER;
847 if (gatt_is_clcb_allocated(conn_id))
849 GATT_TRACE_ERROR("GATTC_Discover GATT_BUSY conn_id = %d", conn_id);
854 if ((p_clcb = gatt_clcb_alloc(conn_id)) != NULL )
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))
862 gatt_clcb_dealloc(p_clcb);
863 return GATT_ILLEGAL_PARAMETER;
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;
872 gatt_act_discovery(p_clcb);
876 status = GATT_NO_RESOURCES;
881 /*******************************************************************************
883 ** Function GATTC_Read
885 ** Description This function is called to read the value of an attribute from
888 ** Parameters conn_id: connection identifier.
889 ** type - attribute read type.
890 ** p_read - read operation parameters.
892 ** Returns GATT_SUCCESS if command started successfully.
894 *******************************************************************************/
895 tGATT_STATUS GATTC_Read (UINT16 conn_id, tGATT_READ_TYPE type, tGATT_READ_PARAM *p_read)
897 tGATT_STATUS status = GATT_SUCCESS;
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);
906 GATT_TRACE_API ("GATTC_Read conn_id=%d type=%d", conn_id, type);
908 if ( (p_tcb == NULL) || (p_reg==NULL) || (p_read == NULL) || ((type >= GATT_READ_MAX) || (type == 0)))
910 GATT_TRACE_ERROR("GATT_Read Illegal param: conn_id %d, type 0%d,", conn_id, type);
911 return GATT_ILLEGAL_PARAMETER;
914 if (gatt_is_clcb_allocated(conn_id))
916 GATT_TRACE_ERROR("GATTC_Read GATT_BUSY conn_id = %d", conn_id);
920 if ( (p_clcb = gatt_clcb_alloc(conn_id)) != NULL )
922 p_clcb->operation = GATTC_OPTYPE_READ;
923 p_clcb->op_subtype = type;
924 p_clcb->auth_req = p_read->by_handle.auth_req;
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));
935 case GATT_READ_MULTIPLE:
936 p_clcb->s_handle = 0;
937 /* copy multiple handles in CB */
938 p_read_multi = (tGATT_READ_MULTI *)osi_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;
946 if (type == GATT_READ_PARTIAL)
948 p_clcb->counter = p_read->partial.offset;
955 /* start security check */
956 if (gatt_security_check_start(p_clcb) == FALSE)
958 status = GATT_NO_RESOURCES;
959 gatt_clcb_dealloc(p_clcb);
964 status = GATT_NO_RESOURCES;
969 /*******************************************************************************
971 ** Function GATTC_Write
973 ** Description This function is called to write the value of an attribute to
976 ** Parameters conn_id: connection identifier.
977 ** type - attribute write type.
978 ** p_write - write operation parameters.
980 ** Returns GATT_SUCCESS if command started successfully.
982 *******************************************************************************/
983 tGATT_STATUS GATTC_Write (UINT16 conn_id, tGATT_WRITE_TYPE type, tGATT_VALUE *p_write)
985 tGATT_STATUS status = GATT_SUCCESS;
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);
993 if ( (p_tcb == NULL) || (p_reg==NULL) || (p_write == NULL) ||
994 ((type != GATT_WRITE) && (type != GATT_WRITE_PREPARE) && (type != GATT_WRITE_NO_RSP)) )
996 GATT_TRACE_ERROR("GATT_Write Illegal param: conn_id %d, type 0%d,", conn_id, type);
997 return GATT_ILLEGAL_PARAMETER;
1000 if (gatt_is_clcb_allocated(conn_id))
1002 GATT_TRACE_ERROR("GATTC_Write GATT_BUSY conn_id = %d", conn_id);
1006 if ((p_clcb = gatt_clcb_alloc(conn_id)) != NULL )
1008 p_clcb->operation = GATTC_OPTYPE_WRITE;
1009 p_clcb->op_subtype = type;
1010 p_clcb->auth_req = p_write->auth_req;
1012 if (( p_clcb->p_attr_buf = (UINT8 *)osi_getbuf((UINT16)sizeof(tGATT_VALUE))) != NULL)
1014 memcpy(p_clcb->p_attr_buf, (void *)p_write, sizeof(tGATT_VALUE));
1016 p = (tGATT_VALUE *)p_clcb->p_attr_buf;
1017 if (type == GATT_WRITE_PREPARE)
1019 p_clcb->start_offset = p_write->offset;
1023 if (gatt_security_check_start(p_clcb) == FALSE)
1025 status = GATT_NO_RESOURCES;
1030 status = GATT_NO_RESOURCES;
1033 if (status == GATT_NO_RESOURCES)
1034 gatt_clcb_dealloc(p_clcb);
1038 status = GATT_NO_RESOURCES;
1044 /*******************************************************************************
1046 ** Function GATTC_ExecuteWrite
1048 ** Description This function is called to send an Execute write request to
1051 ** Parameters conn_id: connection identifier.
1052 ** is_execute - to execute or cancel the prepare write requet(s)
1054 ** Returns GATT_SUCCESS if command started successfully.
1056 *******************************************************************************/
1057 tGATT_STATUS GATTC_ExecuteWrite (UINT16 conn_id, BOOLEAN is_execute)
1059 tGATT_STATUS status = GATT_SUCCESS;
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);
1067 GATT_TRACE_API ("GATTC_ExecuteWrite conn_id=%d is_execute=%d", conn_id, is_execute);
1069 if ( (p_tcb == NULL) || (p_reg==NULL) )
1071 GATT_TRACE_ERROR("GATTC_ExecuteWrite Illegal param: conn_id %d", conn_id);
1072 return GATT_ILLEGAL_PARAMETER;
1075 if (gatt_is_clcb_allocated(conn_id))
1077 GATT_TRACE_ERROR("GATTC_Write GATT_BUSY conn_id = %d", conn_id);
1081 if ((p_clcb = gatt_clcb_alloc(conn_id)) != NULL)
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);
1089 GATT_TRACE_ERROR("Unable to allocate client CB for conn_id %d ", conn_id);
1090 status = GATT_NO_RESOURCES;
1095 /*******************************************************************************
1097 ** Function GATTC_SendHandleValueConfirm
1099 ** Description This function is called to send a handle value confirmation
1100 ** as response to a handle value notification from server.
1102 ** Parameters conn_id: connection identifier.
1103 ** handle: the handle of the attribute confirmation.
1105 ** Returns GATT_SUCCESS if command started successfully.
1107 *******************************************************************************/
1108 tGATT_STATUS GATTC_SendHandleValueConfirm (UINT16 conn_id, UINT16 handle)
1110 tGATT_STATUS ret = GATT_ILLEGAL_PARAMETER;
1111 tGATT_TCB *p_tcb=gatt_get_tcb_by_idx(GATT_GET_TCB_IDX(conn_id));
1113 GATT_TRACE_API ("GATTC_SendHandleValueConfirm conn_id=%d handle=0x%x", conn_id, handle);
1117 if (p_tcb->ind_count > 0 )
1119 btu_stop_timer (&p_tcb->ind_ack_timer_ent);
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);
1125 p_tcb->ind_count = 0;
1130 GATT_TRACE_DEBUG ("GATTC_SendHandleValueConfirm - conn_id: %u - ignored not waiting for indicaiton ack", conn_id);
1136 GATT_TRACE_ERROR ("GATTC_SendHandleValueConfirm - Unknown conn_id: %u", conn_id);
1142 /*******************************************************************************/
1146 /*******************************************************************************/
1147 /*******************************************************************************
1149 ** Function GATT_SetIdleTimeout
1151 ** Description This function (common to both client and server) sets the idle
1152 ** timeout for a tansport connection
1154 ** Parameter bd_addr: target device bd address.
1155 ** idle_tout: timeout value in seconds.
1159 *******************************************************************************/
1160 void GATT_SetIdleTimeout (BD_ADDR bd_addr, UINT16 idle_tout, tBT_TRANSPORT transport)
1163 BOOLEAN status = FALSE;
1165 if ((p_tcb = gatt_find_tcb_by_addr (bd_addr, transport)) != NULL)
1167 if (p_tcb->att_lcid == L2CAP_ATT_CID)
1169 status = L2CA_SetFixedChannelTout (bd_addr, L2CAP_ATT_CID, idle_tout);
1171 if (idle_tout == GATT_LINK_IDLE_TIMEOUT_WHEN_NO_APP)
1172 L2CA_SetIdleTimeoutByBdAddr(p_tcb->peer_bda,
1173 GATT_LINK_IDLE_TIMEOUT_WHEN_NO_APP, BT_TRANSPORT_LE);
1177 status = L2CA_SetIdleTimeout (p_tcb->att_lcid, idle_tout, FALSE);
1181 GATT_TRACE_API ("GATT_SetIdleTimeout idle_tout=%d status=%d(1-OK 0-not performed)",
1186 /*******************************************************************************
1188 ** Function GATT_Register
1190 ** Description This function is called to register an application
1193 ** Parameter p_app_uuid128: Application UUID
1194 ** p_cb_info: callback functions.
1196 ** Returns 0 for error, otherwise the index of the client registered with GATT
1198 *******************************************************************************/
1199 tGATT_IF GATT_Register (tBT_UUID *p_app_uuid128, tGATT_CBACK *p_cb_info)
1205 GATT_TRACE_API ("GATT_Register");
1206 gatt_dbg_display_uuid(*p_app_uuid128);
1208 for (i_gatt_if = 0, p_reg = gatt_cb.cl_rcb; i_gatt_if < GATT_MAX_APPS; i_gatt_if++, p_reg++)
1210 if (p_reg->in_use && !memcmp(p_app_uuid128->uu.uuid128, p_reg->app_uuid128.uu.uuid128, LEN_UUID_128))
1212 GATT_TRACE_ERROR("application already registered.");
1217 for (i_gatt_if = 0, p_reg = gatt_cb.cl_rcb; i_gatt_if < GATT_MAX_APPS; i_gatt_if++, p_reg++)
1221 memset(p_reg, 0 , sizeof(tGATT_REG));
1222 i_gatt_if++; /* one based number */
1223 p_reg->app_uuid128 = *p_app_uuid128;
1225 p_reg->gatt_if = (tGATT_IF)i_gatt_if;
1226 p_reg->app_cb = *p_cb_info;
1227 p_reg->in_use = TRUE;
1232 GATT_TRACE_API ("allocated gatt_if=%d", gatt_if);
1237 /*******************************************************************************
1239 ** Function GATT_Deregister
1241 ** Description This function deregistered the application from GATT.
1243 ** Parameters gatt_if: applicaiton interface.
1247 *******************************************************************************/
1248 void GATT_Deregister (tGATT_IF gatt_if)
1250 tGATT_REG *p_reg = gatt_get_regcb(gatt_if);
1254 tGATT_SR_REG *p_sreg;
1256 GATT_TRACE_API ("GATT_Deregister gatt_if=%d", gatt_if);
1257 /* Index 0 is GAP and is never deregistered */
1258 if ( (gatt_if == 0) || (p_reg == NULL) )
1260 GATT_TRACE_ERROR ("GATT_Deregister with invalid gatt_if: %u", gatt_if);
1264 /* stop all services */
1265 /* todo an applcaiton can not be deregistered if its services is also used by other application
1266 deregisteration need to bed performed in an orderly fashion
1269 for (ii = 0, p_sreg = gatt_cb.sr_reg; ii < GATT_MAX_SR_PROFILES; ii++, p_sreg++)
1271 if (p_sreg->in_use && (p_sreg->gatt_if == gatt_if))
1273 GATTS_StopService(p_sreg->s_hdl);
1277 /* free all services db buffers if owned by this application */
1278 gatt_free_srvc_db_buffer_app_id(&p_reg->app_uuid128);
1280 /* When an application deregisters, check remove the link associated with the app */
1282 for (i=0, p_tcb = gatt_cb.tcb; i < GATT_MAX_PHY_CHANNEL; i++, p_tcb++)
1286 if (gatt_get_ch_state(p_tcb) != GATT_CH_CLOSE)
1288 gatt_update_app_use_link_flag(gatt_if, p_tcb, FALSE, FALSE);
1289 if (!gatt_num_apps_hold_link(p_tcb))
1291 /* this will disconnect the link or cancel the pending connect request at lower layer*/
1292 gatt_disconnect(p_tcb);
1296 for (j = 0, p_clcb= &gatt_cb.clcb[j]; j < GATT_CL_MAX_LCB; j++, p_clcb++)
1298 if (p_clcb->in_use &&
1299 (p_clcb->p_reg->gatt_if == gatt_if) &&
1300 (p_clcb->p_tcb->tcb_idx == p_tcb->tcb_idx))
1302 btu_stop_timer(&p_clcb->rsp_timer_ent);
1303 gatt_clcb_dealloc (p_clcb);
1310 gatt_deregister_bgdev_list(gatt_if);
1311 /* update the listen mode */
1312 #if (defined(BLE_PERIPHERAL_MODE_SUPPORT) && (BLE_PERIPHERAL_MODE_SUPPORT == TRUE))
1313 GATT_Listen(gatt_if, FALSE, NULL);
1316 memset (p_reg, 0, sizeof(tGATT_REG));
1320 /*******************************************************************************
1322 ** Function GATT_StartIf
1324 ** Description This function is called after registration to start receiving
1325 ** callbacks for registered interface. Function may call back
1326 ** with connection status and queued notifications
1328 ** Parameter gatt_if: applicaiton interface.
1332 *******************************************************************************/
1333 void GATT_StartIf (tGATT_IF gatt_if)
1338 UINT8 start_idx, found_idx;
1340 tGATT_TRANSPORT transport ;
1342 GATT_TRACE_API ("GATT_StartIf gatt_if=%d", gatt_if);
1343 if ((p_reg = gatt_get_regcb(gatt_if)) != NULL)
1346 while (gatt_find_the_connected_bda(start_idx, bda, &found_idx, &transport))
1348 p_tcb = gatt_find_tcb_by_addr(bda, transport);
1349 if (p_reg->app_cb.p_conn_cb && p_tcb)
1351 conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, gatt_if);
1352 (*p_reg->app_cb.p_conn_cb)(gatt_if, bda, conn_id, TRUE, 0, transport);
1354 start_idx = ++found_idx;
1360 /*******************************************************************************
1362 ** Function GATT_Connect
1364 ** Description This function initiate a connecttion to a remote device on GATT
1367 ** Parameters gatt_if: applicaiton interface
1368 ** bd_addr: peer device address.
1369 ** is_direct: is a direct conenection or a background auto connection
1371 ** Returns TRUE if connection started; FALSE if connection start failure.
1373 *******************************************************************************/
1374 BOOLEAN GATT_Connect (tGATT_IF gatt_if, BD_ADDR bd_addr, BOOLEAN is_direct, tBT_TRANSPORT transport)
1377 BOOLEAN status = FALSE;
1379 GATT_TRACE_API ("GATT_Connect gatt_if=%d", gatt_if);
1381 /* Make sure app is registered */
1382 if ((p_reg = gatt_get_regcb(gatt_if)) == NULL)
1384 GATT_TRACE_ERROR("GATT_Connect - gatt_if =%d is not registered", gatt_if);
1389 status = gatt_act_connect (p_reg, bd_addr, transport);
1392 if (transport == BT_TRANSPORT_LE)
1393 status = gatt_update_auto_connect_dev(gatt_if,TRUE, bd_addr, TRUE);
1396 GATT_TRACE_ERROR("Unsupported transport for background connection");
1404 /*******************************************************************************
1406 ** Function GATT_CancelConnect
1408 ** Description This function terminate the connection initaition to a remote
1409 ** device on GATT channel.
1411 ** Parameters gatt_if: client interface. If 0 used as unconditionally disconnect,
1412 ** typically used for direct connection cancellation.
1413 ** bd_addr: peer device address.
1415 ** Returns TRUE if connection started; FALSE if connection start failure.
1417 *******************************************************************************/
1418 BOOLEAN GATT_CancelConnect (tGATT_IF gatt_if, BD_ADDR bd_addr, BOOLEAN is_direct){
1421 BOOLEAN status = TRUE;
1422 tGATT_IF temp_gatt_if;
1423 UINT8 start_idx, found_idx;
1425 GATT_TRACE_API ("GATT_CancelConnect gatt_if=%d", gatt_if);
1427 if ((gatt_if != 0) && ((p_reg = gatt_get_regcb(gatt_if)) == NULL))
1429 GATT_TRACE_ERROR("GATT_CancelConnect - gatt_if =%d is not registered", gatt_if);
1437 GATT_TRACE_DEBUG("GATT_CancelConnect - unconditional");
1439 /* only LE connection can be cancelled */
1440 p_tcb = gatt_find_tcb_by_addr(bd_addr, BT_TRANSPORT_LE);
1441 if (p_tcb && gatt_num_apps_hold_link(p_tcb))
1443 while (status && gatt_find_app_hold_link(p_tcb, start_idx, &found_idx, &temp_gatt_if))
1445 status = gatt_cancel_open(temp_gatt_if, bd_addr);
1446 start_idx = ++found_idx;
1451 GATT_TRACE_ERROR("GATT_CancelConnect - no app found");
1457 status = gatt_cancel_open(gatt_if, bd_addr);
1464 if (gatt_get_num_apps_for_bg_dev(bd_addr))
1466 while (gatt_find_app_for_bg_dev(bd_addr, &temp_gatt_if))
1467 gatt_remove_bg_dev_for_app(temp_gatt_if, bd_addr);
1471 GATT_TRACE_ERROR("GATT_CancelConnect -no app associated with the bg device for unconditional removal");
1477 status = gatt_remove_bg_dev_for_app(gatt_if, bd_addr);
1484 /*******************************************************************************
1486 ** Function GATT_Disconnect
1488 ** Description This function disconnect the GATT channel for this registered
1491 ** Parameters conn_id: connection identifier.
1493 ** Returns GATT_SUCCESS if disconnected.
1495 *******************************************************************************/
1496 tGATT_STATUS GATT_Disconnect (UINT16 conn_id)
1498 tGATT_STATUS ret = GATT_ILLEGAL_PARAMETER;
1499 tGATT_TCB *p_tcb=NULL;
1500 tGATT_IF gatt_if=GATT_GET_GATT_IF(conn_id);
1501 UINT8 tcb_idx = GATT_GET_TCB_IDX(conn_id);
1503 GATT_TRACE_API ("GATT_Disconnect conn_id=%d ", conn_id);
1505 p_tcb = gatt_get_tcb_by_idx(tcb_idx);
1509 gatt_update_app_use_link_flag(gatt_if, p_tcb, FALSE, FALSE);
1510 if (!gatt_num_apps_hold_link(p_tcb))
1512 gatt_disconnect(p_tcb);
1520 /*******************************************************************************
1522 ** Function GATT_GetConnectionInfor
1524 ** Description This function use conn_id to find its associated BD address and applciation
1527 ** Parameters conn_id: connection id (input)
1528 ** p_gatt_if: applicaiton interface (output)
1529 ** bd_addr: peer device address. (output)
1531 ** Returns TRUE the ligical link information is found for conn_id
1533 *******************************************************************************/
1534 BOOLEAN GATT_GetConnectionInfor(UINT16 conn_id, tGATT_IF *p_gatt_if, BD_ADDR bd_addr,
1535 tBT_TRANSPORT *p_transport)
1538 tGATT_IF gatt_if = GATT_GET_GATT_IF(conn_id);
1539 tGATT_REG *p_reg = gatt_get_regcb(gatt_if);
1540 UINT8 tcb_idx = GATT_GET_TCB_IDX(conn_id);
1541 tGATT_TCB *p_tcb= gatt_get_tcb_by_idx(tcb_idx);
1542 BOOLEAN status=FALSE;
1544 GATT_TRACE_API ("GATT_GetConnectionInfor conn_id=%d", conn_id);
1546 if (p_tcb && p_reg )
1548 memcpy(bd_addr, p_tcb->peer_bda, BD_ADDR_LEN);
1549 *p_gatt_if = gatt_if;
1550 *p_transport = p_tcb->transport;
1557 /*******************************************************************************
1559 ** Function GATT_GetConnIdIfConnected
1561 ** Description This function find the conn_id if the logical link for BD address
1562 ** and applciation interface is connected
1564 ** Parameters gatt_if: applicaiton interface (input)
1565 ** bd_addr: peer device address. (input)
1566 ** p_conn_id: connection id (output)
1567 ** transport: transport option
1569 ** Returns TRUE the logical link is connected
1571 *******************************************************************************/
1572 BOOLEAN GATT_GetConnIdIfConnected(tGATT_IF gatt_if, BD_ADDR bd_addr, UINT16 *p_conn_id,
1573 tBT_TRANSPORT transport)
1575 tGATT_REG *p_reg = gatt_get_regcb(gatt_if);
1576 tGATT_TCB *p_tcb= gatt_find_tcb_by_addr(bd_addr, transport);
1577 BOOLEAN status=FALSE;
1579 if (p_reg && p_tcb && (gatt_get_ch_state(p_tcb) == GATT_CH_OPEN) )
1581 *p_conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, gatt_if);
1585 GATT_TRACE_API ("GATT_GetConnIdIfConnected status=%d", status);
1590 /*******************************************************************************
1592 ** Function GATT_Listen
1594 ** Description This function start or stop LE advertisement and listen for
1597 ** Parameters gatt_if: applicaiton interface
1598 ** p_bd_addr: listen for specific address connection, or NULL for
1599 ** listen to all device connection.
1600 ** start: start or stop listening.
1602 ** Returns TRUE if advertisement is started; FALSE if adv start failure.
1604 *******************************************************************************/
1605 BOOLEAN GATT_Listen (tGATT_IF gatt_if, BOOLEAN start, BD_ADDR_PTR bd_addr)
1609 GATT_TRACE_API ("GATT_Listen gatt_if=%d", gatt_if);
1611 /* Make sure app is registered */
1612 if ((p_reg = gatt_get_regcb(gatt_if)) == NULL)
1614 GATT_TRACE_ERROR("GATT_Listen - gatt_if =%d is not registered", gatt_if);
1618 if (bd_addr != NULL)
1620 gatt_update_auto_connect_dev(gatt_if,start, bd_addr, FALSE);
1624 p_reg->listening = start ? GATT_LISTEN_TO_ALL : GATT_LISTEN_TO_NONE;
1627 return gatt_update_listen_mode();