LE: Add support for the HID-over-GATT profile (1/3)
bug:8330048
Change-Id: I5727161b0a87700487bee96cdffa8fd169034204
diff --git a/stack/Android.mk b/stack/Android.mk
index f677ad2..10e9bef 100755
--- a/stack/Android.mk
+++ b/stack/Android.mk
@@ -18,6 +18,7 @@
$(LOCAL_PATH)/hid \
$(LOCAL_PATH)/sdp \
$(LOCAL_PATH)/smp \
+ $(LOCAL_PATH)/srvc \
$(LOCAL_PATH)/../include \
$(LOCAL_PATH)/../gki/common \
$(LOCAL_PATH)/../gki/ulinux \
@@ -83,10 +84,6 @@
./mcap/mca_csm.c \
./mcap/mca_cact.c \
./mcap/mca_api.c \
- ./gap/gap_ble.c \
- ./gap/gap_api.c \
- ./gap/gap_utils.c \
- ./gap/gap_conn.c \
./gatt/gatt_sr.c \
./gatt/gatt_cl.c \
./gatt/gatt_api.c \
@@ -103,12 +100,12 @@
./avct/avct_lcb_act.c \
./smp/smp_main.c \
./smp/smp_l2c.c \
- ./smp/aes.c \
./smp/smp_cmac.c \
./smp/smp_utils.c \
./smp/smp_act.c \
./smp/smp_keys.c \
./smp/smp_api.c \
+ ./smp/aes.c \
./avdt/avdt_ccb.c \
./avdt/avdt_scb_act.c \
./avdt/avdt_msg.c \
@@ -124,6 +121,12 @@
./sdp/sdp_api.c \
./sdp/sdp_discovery.c \
./pan/pan_main.c \
+ ./srvc/srvc_battery.c \
+ ./srvc/srvc_battery_int.h \
+ ./srvc/srvc_dis.c \
+ ./srvc/srvc_dis_int.h \
+ ./srvc/srvc_eng.c \
+ ./srvc/srvc_eng_int.h \
./pan/pan_api.c \
./pan/pan_utils.c \
./btu/btu_hcif.c \
@@ -136,7 +139,11 @@
./l2cap/l2c_utils.c \
./l2cap/l2c_csm.c \
./l2cap/l2c_link.c \
- ./l2cap/l2c_ble.c
+ ./l2cap/l2c_ble.c \
+ ./gap/gap_api.c \
+ ./gap/gap_ble.c \
+ ./gap/gap_conn.c \
+ ./gap/gap_utils.c
LOCAL_MODULE := libbt-brcm_stack
LOCAL_MODULE_TAGS := optional
diff --git a/stack/hid/hidh_api.c b/stack/hid/hidh_api.c
index 4f048fc..1868671 100644
--- a/stack/hid/hidh_api.c
+++ b/stack/hid/hidh_api.c
@@ -33,6 +33,7 @@
#include "hidh_int.h"
#include "btm_api.h"
#include "btu.h"
+#include "btm_int.h"
#if HID_DYNAMIC_MEMORY == FALSE
tHID_HOST_CTB hh_cb;
@@ -336,7 +337,6 @@
{
int i;
/* Find an entry for this device in hh_cb.devices array */
-
if( !hh_cb.reg_flag )
return (HID_ERR_NOT_REGISTERED);
@@ -367,7 +367,8 @@
hh_cb.devices[i].conn_tries = 0 ;
}
- hh_cb.devices[i].attr_mask = attr_mask;
+ if (attr_mask != HID_ATTR_MASK_IGNORE)
+ hh_cb.devices[i].attr_mask = attr_mask;
*handle = i;
@@ -500,42 +501,42 @@
tHID_STATUS HID_HostSetSecurityLevel( char serv_name[], UINT8 sec_lvl )
{
- if (!BTM_SetSecurityLevel (FALSE, serv_name, BTM_SEC_SERVICE_HID_SEC_CTRL,
+ if (!BTM_SetSecurityLevel (FALSE, serv_name, BTM_SEC_SERVICE_HIDH_SEC_CTRL,
sec_lvl, HID_PSM_CONTROL, BTM_SEC_PROTO_HID, HID_SEC_CHN))
{
HIDH_TRACE_ERROR0 ("Security Registration 1 failed");
return (HID_ERR_NO_RESOURCES);
}
- if (!BTM_SetSecurityLevel (TRUE, serv_name, BTM_SEC_SERVICE_HID_SEC_CTRL,
+ if (!BTM_SetSecurityLevel (TRUE, serv_name, BTM_SEC_SERVICE_HIDH_SEC_CTRL,
sec_lvl, HID_PSM_CONTROL, BTM_SEC_PROTO_HID, HID_SEC_CHN))
{
HIDH_TRACE_ERROR0 ("Security Registration 2 failed");
return (HID_ERR_NO_RESOURCES);
}
- if (!BTM_SetSecurityLevel (FALSE, serv_name, BTM_SEC_SERVICE_HID_NOSEC_CTRL,
+ if (!BTM_SetSecurityLevel (FALSE, serv_name, BTM_SEC_SERVICE_HIDH_NOSEC_CTRL,
BTM_SEC_NONE, HID_PSM_CONTROL, BTM_SEC_PROTO_HID, HID_NOSEC_CHN))
{
HIDH_TRACE_ERROR0 ("Security Registration 3 failed");
return (HID_ERR_NO_RESOURCES);
}
- if (!BTM_SetSecurityLevel (TRUE, serv_name, BTM_SEC_SERVICE_HID_NOSEC_CTRL,
+ if (!BTM_SetSecurityLevel (TRUE, serv_name, BTM_SEC_SERVICE_HIDH_NOSEC_CTRL,
BTM_SEC_NONE, HID_PSM_CONTROL, BTM_SEC_PROTO_HID, HID_NOSEC_CHN))
{
HIDH_TRACE_ERROR0 ("Security Registration 4 failed");
return (HID_ERR_NO_RESOURCES);
}
- if (!BTM_SetSecurityLevel (TRUE, serv_name, BTM_SEC_SERVICE_HID_INTR,
+ if (!BTM_SetSecurityLevel (TRUE, serv_name, BTM_SEC_SERVICE_HIDH_INTR,
BTM_SEC_NONE, HID_PSM_INTERRUPT, BTM_SEC_PROTO_HID, 0))
{
HIDH_TRACE_ERROR0 ("Security Registration 5 failed");
return (HID_ERR_NO_RESOURCES);
}
- if (!BTM_SetSecurityLevel (FALSE, serv_name, BTM_SEC_SERVICE_HID_INTR,
+ if (!BTM_SetSecurityLevel (FALSE, serv_name, BTM_SEC_SERVICE_HIDH_INTR,
BTM_SEC_NONE, HID_PSM_INTERRUPT, BTM_SEC_PROTO_HID, 0))
{
HIDH_TRACE_ERROR0 ("Security Registration 6 failed");
@@ -544,3 +545,55 @@
return( HID_SUCCESS );
}
+
+/******************************************************************************
+**
+** Function hid_known_hid_device
+**
+** Description check if this device is of type HID Device
+**
+** Returns TRUE if device is HID Device else FALSE
+**
+*******************************************************************************/
+BOOLEAN hid_known_hid_device (BD_ADDR bd_addr)
+{
+ UINT8 i;
+ tBTM_INQ_INFO *p_inq_info = BTM_InqDbRead(bd_addr);
+
+ if ( !hh_cb.reg_flag )
+ return FALSE;
+
+ /* First check for class of device , if Inq DB has information about this device*/
+ if (p_inq_info != NULL)
+ {
+ /* Check if remote major device class is of type BTM_COD_MAJOR_PERIPHERAL */
+ if ((p_inq_info->results.dev_class[1] & BTM_COD_MAJOR_CLASS_MASK)
+ == BTM_COD_MAJOR_PERIPHERAL )
+ {
+ HIDH_TRACE_DEBUG0("hid_known_hid_device:dev found in InqDB & COD matches HID dev");
+ return TRUE;
+ }
+ }
+ else
+ {
+ /* Look for this device in security device DB */
+ tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (bd_addr);
+ if ((p_dev_rec != NULL) &&
+ ((p_dev_rec->dev_class[1] & BTM_COD_MAJOR_CLASS_MASK) == BTM_COD_MAJOR_PERIPHERAL ))
+ {
+ HIDH_TRACE_DEBUG0("hid_known_hid_device:dev found in SecDevDB & COD matches HID dev");
+ return TRUE;
+ }
+ }
+
+ /* Find an entry for this device in hh_cb.devices array */
+ for ( i=0; i<HID_HOST_MAX_DEVICES; i++)
+ {
+ if ((hh_cb.devices[i].in_use) &&
+ (memcmp(bd_addr, hh_cb.devices[i].addr, BD_ADDR_LEN) == 0))
+ return TRUE;
+ }
+ /* Check if this device is marked as HID Device in IOP Dev */
+ HIDH_TRACE_DEBUG0("hid_known_hid_device:remote is not HID device");
+ return FALSE;
+}
diff --git a/stack/hid/hidh_conn.c b/stack/hid/hidh_conn.c
index 2fe1f3d..d9345a0 100644
--- a/stack/hid/hidh_conn.c
+++ b/stack/hid/hidh_conn.c
@@ -129,7 +129,7 @@
{
tHID_CONN *p_hcon = &hh_cb.devices[dhandle].conn;
- HIDH_TRACE_EVENT0 ("HID - disconnect");
+ HIDH_TRACE_EVENT0 ("HID-Host disconnect");
if ((p_hcon->ctrl_cid != 0) || (p_hcon->intr_cid != 0))
{
@@ -201,18 +201,13 @@
{
tHID_CONN *p_hcon;
BOOLEAN bAccept = TRUE;
- int i;
+ UINT8 i = HID_HOST_MAX_DEVICES;
tHID_HOST_DEV_CTB *p_dev;
- HIDH_TRACE_EVENT2 ("HID - Rcvd L2CAP conn ind, PSM: 0x%04x CID 0x%x", psm, l2cap_cid);
+ HIDH_TRACE_EVENT2 ("HID-Host Rcvd L2CAP conn ind, PSM: 0x%04x CID 0x%x", psm, l2cap_cid);
- for( i=0; i < HID_HOST_MAX_DEVICES; i++ )
- {
- if( hh_cb.devices[i].in_use && (!memcmp(bd_addr, hh_cb.devices[i].addr, sizeof(BD_ADDR))) )
- break;
- }
-
- if (i >= HID_HOST_MAX_DEVICES)
+ /* always add incoming connection device into HID database by default */
+ if (HID_HostAddDev(bd_addr, HID_SEC_REQUIRED, &i) != HID_SUCCESS)
{
L2CA_ConnectRsp (bd_addr, l2cap_id, l2cap_cid, L2CAP_CONN_SECURITY_BLOCK, 0);
return;
@@ -226,12 +221,13 @@
{
if (p_hcon->ctrl_cid == 0)
{
- HIDH_TRACE_WARNING0 ("HID - Rcvd INTR L2CAP conn ind, but no CTL channel");
+ HIDH_TRACE_WARNING0 ("HID-Host Rcvd INTR L2CAP conn ind, but no CTL channel");
bAccept = FALSE;
}
if (p_hcon->conn_state != HID_CONN_STATE_CONNECTING_INTR)
{
- HIDH_TRACE_WARNING1 ("HID - Rcvd INTR L2CAP conn ind, wrong state: %d", p_hcon->conn_state);
+ HIDH_TRACE_WARNING1 ("HID-Host Rcvd INTR L2CAP conn ind, wrong state: %d",
+ p_hcon->conn_state);
bAccept = FALSE;
}
}
@@ -243,7 +239,8 @@
#else
if (p_hcon->conn_state != HID_CONN_STATE_UNUSED)
{
- HIDH_TRACE_WARNING1 ("HID - Rcvd CTL L2CAP conn ind, wrong state: %d", p_hcon->conn_state);
+ HIDH_TRACE_WARNING1 ("HID-Host - Rcvd CTL L2CAP conn ind, wrong state: %d",
+ p_hcon->conn_state);
bAccept = FALSE;
}
#endif
@@ -284,7 +281,8 @@
/* Send a Configuration Request. */
L2CA_ConfigReq (l2cap_cid, &hh_cb.l2cap_cfg);
- HIDH_TRACE_EVENT2 ("HID - Rcvd L2CAP conn ind, sent config req, PSM: 0x%04x CID 0x%x", psm, l2cap_cid);
+ HIDH_TRACE_EVENT2 ("HID-Host Rcvd L2CAP conn ind, sent config req, PSM: 0x%04x CID 0x%x",
+ psm, l2cap_cid);
}
/*******************************************************************************
@@ -300,7 +298,8 @@
{
hidh_conn_initiate( (UINT8) p_tle->param ) ;
hh_cb.devices[p_tle->param].conn_tries++;
- hh_cb.callback( (UINT8) p_tle->param, HID_HDEV_EVT_RETRYING, hh_cb.devices[p_tle->param].conn_tries, NULL ) ;
+ hh_cb.callback( (UINT8) p_tle->param, hh_cb.devices[p_tle->param].addr,
+ HID_HDEV_EVT_RETRYING, hh_cb.devices[p_tle->param].conn_tries, NULL ) ;
}
/*******************************************************************************
@@ -325,16 +324,16 @@
dhandle = ((UINT32)p_dev - (UINT32)&(hh_cb.devices[0]))/ sizeof(tHID_HOST_DEV_CTB);
if( res == BTM_SUCCESS && p_dev->conn.conn_state == HID_CONN_STATE_SECURITY )
{
- HIDH_TRACE_EVENT0 ("HID - Originator security pass.");
+ HIDH_TRACE_EVENT0 ("HID-Host Originator security pass.");
p_dev->conn.disc_reason = HID_SUCCESS; /* Authentication passed. Reset disc_reason (from HID_ERR_AUTH_FAILED) */
/* Check if L2CAP started the connection process for interrupt channel */
if ((p_dev->conn.intr_cid = L2CA_ConnectReq (HID_PSM_INTERRUPT, hh_cb.devices[dhandle].addr)) == 0)
{
- HIDH_TRACE_WARNING0 ("HID - INTR Originate failed");
+ HIDH_TRACE_WARNING0 ("HID-Host INTR Originate failed");
reason = HID_L2CAP_REQ_FAIL ;
hidh_conn_disconnect (dhandle);
- hh_cb.callback( dhandle, HID_HDEV_EVT_CLOSE, reason, NULL ) ;
+ hh_cb.callback( dhandle, hh_cb.devices[dhandle].addr, HID_HDEV_EVT_CLOSE, reason, NULL ) ;
return;
}
else
@@ -394,7 +393,7 @@
|| ((l2cap_cid == p_hcon->ctrl_cid) && (p_hcon->conn_state != HID_CONN_STATE_CONNECTING_CTRL))
|| ((l2cap_cid == p_hcon->intr_cid) && (p_hcon->conn_state != HID_CONN_STATE_CONNECTING_INTR)))
{
- HIDH_TRACE_WARNING1 ("HID - Rcvd unexpected conn cnf, CID 0x%x ", l2cap_cid);
+ HIDH_TRACE_WARNING1 ("HID-Host Rcvd unexpected conn cnf, CID 0x%x ", l2cap_cid);
return;
}
@@ -418,7 +417,7 @@
#endif
{
reason = HID_L2CAP_CONN_FAIL | (UINT32) result ;
- hh_cb.callback( dhandle, HID_HDEV_EVT_CLOSE, reason, NULL ) ;
+ hh_cb.callback( dhandle, hh_cb.devices[dhandle].addr, HID_HDEV_EVT_CLOSE, reason, NULL ) ;
}
return;
}
@@ -442,7 +441,7 @@
/* Send a Configuration Request. */
L2CA_ConfigReq (l2cap_cid, &hh_cb.l2cap_cfg);
- HIDH_TRACE_EVENT1 ("HID - got CTRL conn cnf, sent cfg req, CID: 0x%x", l2cap_cid);
+ HIDH_TRACE_EVENT1 ("HID-Host got CTRL conn cnf, sent cfg req, CID: 0x%x", l2cap_cid);
return;
}
@@ -471,11 +470,11 @@
if (p_hcon == NULL)
{
- HIDH_TRACE_WARNING1 ("HID - Rcvd L2CAP cfg ind, unknown CID: 0x%x", l2cap_cid);
+ HIDH_TRACE_WARNING1 ("HID-Host Rcvd L2CAP cfg ind, unknown CID: 0x%x", l2cap_cid);
return;
}
- HIDH_TRACE_EVENT1 ("HID - Rcvd cfg ind, sent cfg cfm, CID: 0x%x", l2cap_cid);
+ HIDH_TRACE_EVENT1 ("HID-Host Rcvd cfg ind, sent cfg cfm, CID: 0x%x", l2cap_cid);
/* Remember the remote MTU size */
if ((!p_cfg->mtu_present) || (p_cfg->mtu > HID_HOST_MTU))
@@ -502,7 +501,7 @@
p_hcon->conn_state = HID_CONN_STATE_CONNECTED;
hh_cb.devices[dhandle].state = HID_DEV_CONNECTED;
- hh_cb.callback( dhandle, HID_HDEV_EVT_OPEN, 0, NULL ) ;
+ hh_cb.callback( dhandle, hh_cb.devices[dhandle].addr, HID_HDEV_EVT_OPEN, 0, NULL ) ;
}
}
@@ -523,7 +522,7 @@
tHID_CONN *p_hcon = NULL;
UINT32 reason;
- HIDH_TRACE_EVENT2 ("HID - Rcvd cfg cfm, CID: 0x%x Result: %d", l2cap_cid, p_cfg->result);
+ HIDH_TRACE_EVENT2 ("HID-Host Rcvd cfg cfm, CID: 0x%x Result: %d", l2cap_cid, p_cfg->result);
/* Find CCB based on CID */
if( (dhandle = find_conn_by_cid(l2cap_cid)) < HID_HOST_MAX_DEVICES )
@@ -531,7 +530,7 @@
if (p_hcon == NULL)
{
- HIDH_TRACE_WARNING1 ("HID - Rcvd L2CAP cfg ind, unknown CID: 0x%x", l2cap_cid);
+ HIDH_TRACE_WARNING1 ("HID-Host Rcvd L2CAP cfg ind, unknown CID: 0x%x", l2cap_cid);
return;
}
@@ -540,7 +539,7 @@
{
hidh_conn_disconnect (dhandle);
reason = HID_L2CAP_CFG_FAIL | (UINT32) p_cfg->result ;
- hh_cb.callback( dhandle, HID_HDEV_EVT_CLOSE, reason, NULL ) ;
+ hh_cb.callback( dhandle, hh_cb.devices[dhandle].addr, HID_HDEV_EVT_CLOSE, reason, NULL ) ;
return;
}
@@ -556,7 +555,7 @@
p_hcon->conn_state = HID_CONN_STATE_CONNECTED;
hh_cb.devices[dhandle].state = HID_DEV_CONNECTED;
- hh_cb.callback( dhandle, HID_HDEV_EVT_OPEN, 0, NULL ) ;
+ hh_cb.callback( dhandle, hh_cb.devices[dhandle].addr, HID_HDEV_EVT_OPEN, 0, NULL ) ;
}
}
@@ -584,14 +583,14 @@
if (p_hcon == NULL)
{
- HIDH_TRACE_WARNING1 ("HID - Rcvd L2CAP disc, unknown CID: 0x%x", l2cap_cid);
+ HIDH_TRACE_WARNING1 ("HID-Host Rcvd L2CAP disc, unknown CID: 0x%x", l2cap_cid);
return;
}
if (ack_needed)
L2CA_DisconnectRsp (l2cap_cid);
- HIDH_TRACE_EVENT1 ("HID - Rcvd L2CAP disc, CID: 0x%x", l2cap_cid);
+ HIDH_TRACE_EVENT1 ("HID-Host Rcvd L2CAP disc, CID: 0x%x", l2cap_cid);
p_hcon->conn_state = HID_CONN_STATE_DISCONNECTING;
@@ -636,7 +635,7 @@
hid_close_evt_reason = HID_ERR_AUTH_FAILED;
}
- hh_cb.callback( dhandle, HID_HDEV_EVT_CLOSE, hid_close_evt_reason, NULL ) ;
+ hh_cb.callback( dhandle, hh_cb.devices[dhandle].addr, HID_HDEV_EVT_CLOSE, hid_close_evt_reason, NULL ) ;
}
}
}
@@ -662,11 +661,11 @@
if (p_hcon == NULL)
{
- HIDH_TRACE_WARNING1 ("HID - Rcvd L2CAP disc cfm, unknown CID: 0x%x", l2cap_cid);
+ HIDH_TRACE_WARNING1 ("HID-Host Rcvd L2CAP disc cfm, unknown CID: 0x%x", l2cap_cid);
return;
}
- HIDH_TRACE_EVENT1 ("HID - Rcvd L2CAP disc cfm, CID: 0x%x", l2cap_cid);
+ HIDH_TRACE_EVENT1 ("HID-Host Rcvd L2CAP disc cfm, CID: 0x%x", l2cap_cid);
if (l2cap_cid == p_hcon->ctrl_cid)
p_hcon->ctrl_cid = 0;
@@ -677,7 +676,7 @@
{
hh_cb.devices[dhandle].state = HID_DEV_NO_CONN;
p_hcon->conn_state = HID_CONN_STATE_UNUSED;
- hh_cb.callback( dhandle, HID_HDEV_EVT_CLOSE, p_hcon->disc_reason, NULL ) ;
+ hh_cb.callback( dhandle, hh_cb.devices[dhandle].addr, HID_HDEV_EVT_CLOSE, p_hcon->disc_reason, NULL ) ;
}
}
@@ -702,11 +701,11 @@
if (p_hcon == NULL)
{
- HIDH_TRACE_WARNING1 ("HID - Rcvd L2CAP congestion status, unknown CID: 0x%x", l2cap_cid);
+ HIDH_TRACE_WARNING1 ("HID-Host Rcvd L2CAP congestion status, unknown CID: 0x%x", l2cap_cid);
return;
}
- HIDH_TRACE_EVENT2 ("HID - Rcvd L2CAP congestion status, CID: 0x%x Cong: %d", l2cap_cid, congested);
+ HIDH_TRACE_EVENT2 ("HID-Host Rcvd L2CAP congestion status, CID: 0x%x Cong: %d", l2cap_cid, congested);
if (congested)
p_hcon->conn_flags |= HID_CONN_FLAGS_CONGESTED;
@@ -740,7 +739,7 @@
UINT8 dhandle;
tHID_CONN *p_hcon = NULL;
- HIDH_TRACE_DEBUG1 ("HID - hidh_l2cif_data_ind [l2cap_cid=0x%04x]", l2cap_cid);
+ HIDH_TRACE_DEBUG1 ("HID-Host hidh_l2cif_data_ind [l2cap_cid=0x%04x]", l2cap_cid);
/* Find CCB based on CID */
if ((dhandle = find_conn_by_cid(l2cap_cid)) < HID_HOST_MAX_DEVICES)
@@ -748,7 +747,7 @@
if (p_hcon == NULL)
{
- HIDH_TRACE_WARNING1 ("HID - Rcvd L2CAP data, unknown CID: 0x%x", l2cap_cid);
+ HIDH_TRACE_WARNING1 ("HID-Host Rcvd L2CAP data, unknown CID: 0x%x", l2cap_cid);
GKI_freebuf (p_msg);
return;
}
@@ -766,7 +765,7 @@
switch (ttype)
{
case HID_TRANS_HANDSHAKE:
- hh_cb.callback(dhandle, HID_HDEV_EVT_HANDSHAKE, param, NULL);
+ hh_cb.callback(dhandle, hh_cb.devices[dhandle].addr, HID_HDEV_EVT_HANDSHAKE, param, NULL);
GKI_freebuf (p_msg);
break;
@@ -776,7 +775,7 @@
case HID_PAR_CONTROL_VIRTUAL_CABLE_UNPLUG:
hidh_conn_disconnect( dhandle ) ;
/* Device is unplugging from us. Tell USB */
- hh_cb.callback(dhandle, HID_HDEV_EVT_VC_UNPLUG, 0, NULL);
+ hh_cb.callback(dhandle, hh_cb.devices[dhandle].addr, HID_HDEV_EVT_VC_UNPLUG, 0, NULL);
break;
default:
@@ -789,13 +788,13 @@
case HID_TRANS_DATA:
evt = (hh_cb.devices[dhandle].conn.intr_cid == l2cap_cid) ?
HID_HDEV_EVT_INTR_DATA : HID_HDEV_EVT_CTRL_DATA;
- hh_cb.callback(dhandle, evt, rep_type, p_msg);
+ hh_cb.callback(dhandle, hh_cb.devices[dhandle].addr, evt, rep_type, p_msg);
break;
case HID_TRANS_DATAC:
evt = (hh_cb.devices[dhandle].conn.intr_cid == l2cap_cid) ?
HID_HDEV_EVT_INTR_DATC : HID_HDEV_EVT_CTRL_DATC;
- hh_cb.callback(dhandle, evt, rep_type, p_msg);
+ hh_cb.callback(dhandle, hh_cb.devices[dhandle].addr, evt, rep_type, p_msg);
break;
default:
@@ -949,7 +948,7 @@
*******************************************************************************/
tHID_STATUS hidh_conn_initiate (UINT8 dhandle)
{
- UINT8 service_id = BTM_SEC_SERVICE_HID_NOSEC_CTRL;
+ UINT8 service_id = BTM_SEC_SERVICE_HIDH_NOSEC_CTRL;
UINT32 mx_chan_id = HID_NOSEC_CHN;
tHID_HOST_DEV_CTB *p_dev = &hh_cb.devices[dhandle];
@@ -966,7 +965,7 @@
if(p_dev->attr_mask & HID_SEC_REQUIRED)
{
- service_id = BTM_SEC_SERVICE_HID_SEC_CTRL;
+ service_id = BTM_SEC_SERVICE_HIDH_SEC_CTRL;
mx_chan_id = HID_SEC_CHN;
}
BTM_SetOutService (p_dev->addr, service_id, mx_chan_id);
@@ -974,8 +973,9 @@
/* Check if L2CAP started the connection process */
if ((p_dev->conn.ctrl_cid = L2CA_ConnectReq (HID_PSM_CONTROL, p_dev->addr)) == 0)
{
- HIDH_TRACE_WARNING0 ("HID - Originate failed");
- hh_cb.callback( dhandle, HID_HDEV_EVT_CLOSE, HID_ERR_L2CAP_FAILED, NULL ) ;
+ HIDH_TRACE_WARNING0 ("HID-Host Originate failed");
+ hh_cb.callback( dhandle, hh_cb.devices[dhandle].addr, HID_HDEV_EVT_CLOSE,
+ HID_ERR_L2CAP_FAILED, NULL ) ;
}
else
{
diff --git a/stack/include/btm_api.h b/stack/include/btm_api.h
index 3a7ed1d..2181f31 100644
--- a/stack/include/btm_api.h
+++ b/stack/include/btm_api.h
@@ -1185,9 +1185,9 @@
#define BTM_SEC_SERVICE_TE_PHONE_ACCESS 30
#define BTM_SEC_SERVICE_ME_PHONE_ACCESS 31
-#define BTM_SEC_SERVICE_HID_SEC_CTRL 32
-#define BTM_SEC_SERVICE_HID_NOSEC_CTRL 33
-#define BTM_SEC_SERVICE_HID_INTR 34
+#define BTM_SEC_SERVICE_HIDH_SEC_CTRL 32
+#define BTM_SEC_SERVICE_HIDH_NOSEC_CTRL 33
+#define BTM_SEC_SERVICE_HIDH_INTR 34
#define BTM_SEC_SERVICE_BIP 35
#define BTM_SEC_SERVICE_BIP_REF 36
#define BTM_SEC_SERVICE_AVDTP 37
@@ -1272,9 +1272,9 @@
#define BTM_SEC_TRUST_ME_PHONE_ACCESS (1 << BTM_SEC_SERVICE_ME_PHONE_ACCESS)
/* 0..31 bits of mask[1] (Most Significant Word) */
-#define BTM_SEC_TRUST_HID_CTRL (1 << (BTM_SEC_SERVICE_HID_SEC_CTRL - 32))
-#define BTM_SEC_TRUST_HID_NOSEC_CTRL (1 << (BTM_SEC_SERVICE_HID_NOSEC_CTRL - 32))
-#define BTM_SEC_TRUST_HID_INTR (1 << (BTM_SEC_SERVICE_HID_INTR - 32))
+#define BTM_SEC_TRUST_HIDH_CTRL (1 << (BTM_SEC_SERVICE_HIDH_SEC_CTRL - 32))
+#define BTM_SEC_TRUST_HIDH_NOSEC_CTRL (1 << (BTM_SEC_SERVICE_HIDH_NOSEC_CTRL - 32))
+#define BTM_SEC_TRUST_HIDH_INTR (1 << (BTM_SEC_SERVICE_HIDH_INTR - 32))
#define BTM_SEC_TRUST_BIP (1 << (BTM_SEC_SERVICE_BIP - 32))
#define BTM_SEC_TRUST_BIP_REF (1 << (BTM_SEC_SERVICE_BIP_REF - 32))
#define BTM_SEC_TRUST_AVDTP (1 << (BTM_SEC_SERVICE_AVDTP - 32))
diff --git a/stack/include/gattdefs.h b/stack/include/gattdefs.h
index e2150f2..38e18f3 100644
--- a/stack/include/gattdefs.h
+++ b/stack/include/gattdefs.h
@@ -57,4 +57,69 @@
#define GATT_UUID_GATT_SRV_CHGD 0x2A05
/* Attribute Protocol Test */
+/* Link Loss Service */
+#define GATT_UUID_ALERT_LEVEL 0x2A06 /* Alert Level */
+#define GATT_UUID_TX_POWER_LEVEL 0x2A07 /* TX power level */
+
+/* Time Profile */
+/* Current Time Service */
+#define GATT_UUID_CURRENT_TIME 0x2A2B /* Current Time */
+#define GATT_UUID_LOCAL_TIME_INFO 0x2A0F /* Local time info */
+#define GATT_UUID_REF_TIME_INFO 0x2A14 /* reference time information */
+
+/* NwA Profile */
+#define GATT_UUID_NW_STATUS 0x2A18 /* network availability status */
+#define GATT_UUID_NW_TRIGGER 0x2A1A /* Network availability trigger */
+
+/* phone alert */
+#define GATT_UUID_ALERT_STATUS 0x2A40 /* alert status */
+#define GATT_UUID_RINGER_CP 0x2A42 /* ringer control point */
+#define GATT_UUID_RINGER_SETTING 0x2A41 /* ringer setting */
+
+/* Glucose Service */
+#define GATT_UUID_GM_MEASUREMENT 0x2A18
+#define GATT_UUID_GM_CONTEXT 0x2A34
+#define GATT_UUID_GM_CONTROL_POINT 0x2A52
+#define GATT_UUID_GM_FEATURE 0x2A51
+
+/* device infor characteristic */
+#define GATT_UUID_SYSTEM_ID 0x2A23
+#define GATT_UUID_MODEL_NUMBER_STR 0x2A24
+#define GATT_UUID_SERIAL_NUMBER_STR 0x2A25
+#define GATT_UUID_FW_VERSION_STR 0x2A26
+#define GATT_UUID_HW_VERSION_STR 0x2A27
+#define GATT_UUID_SW_VERSION_STR 0x2A28
+#define GATT_UUID_MANU_NAME 0x2A29
+#define GATT_UUID_IEEE_DATA 0x2A2A
+#define GATT_UUID_PNP_ID 0x2A50
+
+/* HID characteristics */
+#define GATT_UUID_HID_INFORMATION 0x2A4A
+#define GATT_UUID_HID_REPORT_MAP 0x2A4B
+#define GATT_UUID_HID_CONTROL_POINT 0x2A4C
+#define GATT_UUID_HID_REPORT 0x2A4D
+#define GATT_UUID_HID_PROTO_MODE 0x2A4E
+#define GATT_UUID_HID_BT_KB_INPUT 0x2A22
+#define GATT_UUID_HID_BT_KB_OUTPUT 0x2A32
+#define GATT_UUID_HID_BT_MOUSE_INPUT 0x2A33
+
+/* Battery Service char */
+#define GATT_UUID_BATTERY_LEVEL 0x2A19
+
+#define GATT_UUID_SC_CONTROL_POINT 0x2A55
+#define GATT_UUID_SENSOR_LOCATION 0x2A5D
+
+/* RUNNERS SPEED AND CADENCE SERVICE */
+#define GATT_UUID_RSC_MEASUREMENT 0x2A53
+#define GATT_UUID_RSC_FEATURE 0x2A54
+
+/* CYCLING SPEED AND CADENCE SERVICE */
+#define GATT_UUID_CSC_MEASUREMENT 0x2A5B
+#define GATT_UUID_CSC_FEATURE 0x2A5C
+
+
+/* Scan Parameter charatceristics */
+#define GATT_UUID_SCAN_INT_WINDOW 0x2A4F
+#define GATT_UUID_SCAN_REFRESH 0x2A31
+
#endif
diff --git a/stack/include/hiddefs.h b/stack/include/hiddefs.h
index e29a4c4..bf5d021 100644
--- a/stack/include/hiddefs.h
+++ b/stack/include/hiddefs.h
@@ -49,6 +49,7 @@
HID_ERR_L2CAP_FAILED,
HID_ERR_AUTH_FAILED,
HID_ERR_SDP_BUSY,
+ HID_ERR_GATT,
HID_ERR_INVALID = 0xFF
};
diff --git a/stack/include/hidh_api.h b/stack/include/hidh_api.h
index 4662630..27e8ac5 100644
--- a/stack/include/hidh_api.h
+++ b/stack/include/hidh_api.h
@@ -42,6 +42,7 @@
#define HID_SSR_MIN_TOUT 0x0100
#define HID_SEC_REQUIRED 0x8000
+#define HID_ATTR_MASK_IGNORE 0
/*****************************************************************************
@@ -76,6 +77,7 @@
HID_HDEV_EVT_VC_UNPLUG
};
typedef void (tHID_HOST_DEV_CALLBACK) (UINT8 dev_handle,
+ BD_ADDR addr,
UINT8 event, /* Event from HID-DEVICE. */
UINT32 data, /* Integer data corresponding to the event.*/
BT_HDR *p_buf ); /* Pointer data corresponding to the event. */
@@ -205,6 +207,18 @@
/*******************************************************************************
**
+** Function hid_known_hid_device
+**
+** Description This function checks if this device is of type HID Device
+**
+** Returns TRUE if device exists else FALSE
+**
+*******************************************************************************/
+BOOLEAN hid_known_hid_device (BD_ADDR bd_addr);
+
+
+/*******************************************************************************
+**
** Function HID_HostSetTraceLevel
**
** Description This function sets the trace level for HID Host. If called with
diff --git a/stack/include/srvc_api.h b/stack/include/srvc_api.h
new file mode 100644
index 0000000..b67a14f
--- /dev/null
+++ b/stack/include/srvc_api.h
@@ -0,0 +1,210 @@
+/****************************************************************************
+**
+** Name: srvc_api.h
+** Function this file contains the definitions for the DIS API
+**
+**
+** Copyright (c) 1999-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+******************************************************************************/
+#ifndef SRVC_DIS_API_H
+#define SRVC_DIS_API_H
+
+#include "bt_target.h"
+#include "gatt_api.h"
+#include "gattdefs.h"
+
+#define DIS_SUCCESS GATT_SUCCESS
+#define DIS_ILLEGAL_PARAM GATT_ILLEGAL_PARAMETER
+#define DIS_NO_RESOURCES GATT_NO_RESOURCES
+typedef UINT8 tDIS_STATUS;
+
+
+/*****************************************************************************
+** Data structure for DIS
+*****************************************************************************/
+
+#define DIS_ATTR_SYS_ID_BIT 0x0001
+#define DIS_ATTR_MODEL_NUM_BIT 0x0002
+#define DIS_ATTR_SERIAL_NUM_BIT 0x0004
+#define DIS_ATTR_FW_NUM_BIT 0x0008
+#define DIS_ATTR_HW_NUM_BIT 0x0010
+#define DIS_ATTR_SW_NUM_BIT 0x0020
+#define DIS_ATTR_MANU_NAME_BIT 0x0040
+#define DIS_ATTR_IEEE_DATA_BIT 0x0080
+#define DIS_ATTR_PNP_ID_BIT 0x0100
+typedef UINT16 tDIS_ATTR_MASK;
+
+#define DIS_ATTR_ALL_MASK 0xffff
+
+typedef tDIS_ATTR_MASK tDIS_ATTR_BIT ;
+
+typedef struct
+{
+ UINT16 len;
+ UINT8 *p_data;
+}tDIS_STRING;
+
+typedef struct
+{
+ UINT16 vendor_id;
+ UINT16 product_id;
+ UINT16 product_version;
+ UINT8 vendor_id_src;
+
+}tDIS_PNP_ID;
+
+typedef union
+{
+ UINT64 system_id;
+ tDIS_PNP_ID pnp_id;
+ tDIS_STRING data_str;
+}tDIS_ATTR;
+
+#define DIS_MAX_STRING_DATA 7
+
+typedef struct
+{
+ UINT16 attr_mask;
+ UINT64 system_id;
+ tDIS_PNP_ID pnp_id;
+ UINT8 *data_string[DIS_MAX_STRING_DATA];
+}tDIS_VALUE;
+
+
+typedef void (tDIS_READ_CBACK)(BD_ADDR addr, tDIS_VALUE *p_dis_value);
+
+/*****************************************************************************
+** Data structure used by Battery Service
+*****************************************************************************/
+typedef struct
+{
+ BD_ADDR remote_bda;
+ BOOLEAN need_rsp;
+ UINT16 clt_cfg;
+}tBA_WRITE_DATA;
+
+#define BA_READ_CLT_CFG_REQ 1
+#define BA_READ_PRE_FMT_REQ 2
+#define BA_READ_RPT_REF_REQ 3
+#define BA_READ_LEVEL_REQ 4
+#define BA_WRITE_CLT_CFG_REQ 5
+
+typedef void (tBA_CBACK)(UINT8 app_id, UINT8 event, tBA_WRITE_DATA *p_data);
+
+#define BA_LEVEL_NOTIFY 0x01
+#define BA_LEVEL_PRE_FMT 0x02
+#define BA_LEVEL_RPT_REF 0x04
+typedef UINT8 tBA_LEVEL_DESCR;
+
+typedef struct
+{
+ BOOLEAN is_pri;
+ tBA_LEVEL_DESCR ba_level_descr;
+ tGATT_TRANSPORT transport;
+ tBA_CBACK *p_cback;
+
+}tBA_REG_INFO;
+
+typedef union
+{
+ UINT8 ba_level;
+ UINT16 clt_cfg;
+ tGATT_CHAR_RPT_REF rpt_ref;
+ tGATT_CHAR_PRES pres_fmt;
+}tBA_RSP_DATA;
+
+/*****************************************************************************
+** External Function Declarations
+*****************************************************************************/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/*****************************************************************************
+** Service Engine API
+*****************************************************************************/
+/*******************************************************************************
+**
+** Function srvc_eng_init
+**
+** Description Initializa the GATT Service engine, register a GATT application
+** as for a central service management.
+**
+*******************************************************************************/
+ GATT_API extern tGATT_STATUS srvc_eng_init (void);
+
+
+/*****************************************************************************
+** DIS Server Function
+*****************************************************************************/
+
+/*******************************************************************************
+**
+** Function DIS_SrInit
+**
+** Description Initializa the Device Information Service Server.
+**
+*******************************************************************************/
+ GATT_API extern tDIS_STATUS DIS_SrInit (tDIS_ATTR_MASK dis_attr_mask);
+/*******************************************************************************
+**
+** Function DIS_SrUpdate
+**
+** Description Update the DIS server attribute values
+**
+*******************************************************************************/
+ GATT_API extern tDIS_STATUS DIS_SrUpdate(tDIS_ATTR_BIT dis_attr_bit, tDIS_ATTR *p_info);
+/*****************************************************************************
+** DIS Client Function
+*****************************************************************************/
+/*******************************************************************************
+**
+** Function DIS_ReadDISInfo
+**
+** Description Read remote device DIS information.
+**
+** Returns void
+**
+*******************************************************************************/
+ GATT_API extern BOOLEAN DIS_ReadDISInfo(BD_ADDR peer_bda, tDIS_READ_CBACK *p_cback);
+
+/*******************************************************************************
+** BATTERY SERVICE API
+*******************************************************************************/
+/*******************************************************************************
+**
+** Function Battery_Instantiate
+**
+** Description Instantiate a Battery service
+**
+*******************************************************************************/
+ GATT_API extern UINT16 Battery_Instantiate (UINT8 app_id, tBA_REG_INFO *p_reg_info);
+
+/*******************************************************************************
+**
+** Function Battery_Rsp
+**
+** Description Respond to a battery service request
+**
+*******************************************************************************/
+ GATT_API extern void Battery_Rsp (UINT8 app_id, tGATT_STATUS st, UINT8 event, tBA_RSP_DATA *p_rsp);
+/*******************************************************************************
+**
+** Function Battery_Notify
+**
+** Description Send battery level notification
+**
+*******************************************************************************/
+ GATT_API extern void Battery_Notify (UINT8 app_id, BD_ADDR remote_bda, UINT8 battery_level);
+
+
+#ifdef __cplusplus
+
+}
+#endif
+
+#endif
+
+
diff --git a/stack/srvc/srvc_battery.c b/stack/srvc/srvc_battery.c
new file mode 100644
index 0000000..25db24c
--- /dev/null
+++ b/stack/srvc/srvc_battery.c
@@ -0,0 +1,394 @@
+/*****************************************************************************
+**
+** Name: srvc_battery.c
+**
+** Description: this file contains the main Battery Service over GATT
+** server and handling functions.
+**
+** Copyright (c) 2008-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+******************************************************************************/
+
+#include "bt_target.h"
+
+#include "gatt_api.h"
+#include "gatt_int.h"
+#include "srvc_eng_int.h"
+#include "srvc_battery_int.h"
+
+#if BLE_INCLUDED == TRUE
+
+#define BA_MAX_CHAR_NUM 1
+#define BA_MAX_ATTR_NUM (BA_MAX_CHAR_NUM * 5 + 1) /* max 3 descriptors, 1 desclration and 1 value */
+
+#ifndef BATTER_LEVEL_PROP
+#define BATTER_LEVEL_PROP (GATT_CHAR_PROP_BIT_READ|GATT_CHAR_PROP_BIT_NOTIFY)
+#endif
+
+
+#ifndef BATTER_LEVEL_PERM
+#define BATTER_LEVEL_PERM (GATT_PERM_READ)
+#endif
+
+tBATTERY_CB battery_cb;
+
+
+/*******************************************************************************
+** battery_valid_handle_range
+**
+** validate a handle to be a DIS attribute handle or not.
+*******************************************************************************/
+BOOLEAN battery_valid_handle_range(UINT16 handle)
+{
+ UINT8 i = 0;
+ tBA_INST *p_inst = &battery_cb.battery_inst[0];
+
+ for (;i < BA_MAX_INT_NUM; i ++, p_inst++)
+ {
+ if (handle == p_inst->ba_level_hdl ||
+ handle == p_inst->clt_cfg_hdl ||
+ handle == p_inst->rpt_ref_hdl ||
+ handle == p_inst->pres_fmt_hdl )
+ {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+/*******************************************************************************
+** battery_s_write_attr_value
+**
+** Process write DIS attribute request.
+*******************************************************************************/
+UINT8 battery_s_write_attr_value(UINT8 clcb_idx, tGATT_WRITE_REQ * p_value,
+ tGATT_STATUS *p_status)
+{
+ UINT8 *p = p_value->value, i;
+ UINT16 handle = p_value->handle;
+ tBA_INST *p_inst = &battery_cb.battery_inst[0];
+ tGATT_STATUS st = GATT_NOT_FOUND;
+ tBA_WRITE_DATA cfg;
+ UINT8 act = SRVC_ACT_RSP;
+
+ for (i = 0; i < BA_MAX_INT_NUM; i ++, p_inst ++)
+ {
+ /* read battery level */
+ if (handle == p_inst->clt_cfg_hdl)
+ {
+ memcpy(cfg.remote_bda, srvc_eng_cb.clcb[clcb_idx].bda, BD_ADDR_LEN);
+ STREAM_TO_UINT16(cfg.clt_cfg, p);
+
+ if (p_inst->p_cback)
+ {
+ p_inst->pending_clcb_idx = clcb_idx;
+ p_inst->pending_evt = BA_WRITE_CLT_CFG_REQ;
+ p_inst->pending_handle = handle;
+ cfg.need_rsp = p_value->need_rsp;
+ act = SRVC_ACT_PENDING;
+
+ (* p_inst->p_cback)(p_inst->app_id, BA_WRITE_CLT_CFG_REQ, &cfg);
+ }
+ }
+ else /* all other handle is not writable */
+ {
+ st = GATT_WRITE_NOT_PERMIT;
+ break;
+ }
+ }
+ *p_status = st;
+
+ return act;
+}
+/*******************************************************************************
+** BA Attributes Database Server Request callback
+*******************************************************************************/
+UINT8 battery_s_read_attr_value (UINT8 clcb_idx, UINT16 handle, tGATT_VALUE *p_value, BOOLEAN is_long, tGATT_STATUS* p_status)
+{
+ UINT8 i;
+ tBA_INST *p_inst = &battery_cb.battery_inst[0];
+ tGATT_STATUS st = GATT_NOT_FOUND;
+ UINT8 act = SRVC_ACT_RSP;
+
+ for (i = 0; i < BA_MAX_INT_NUM; i ++, p_inst ++)
+ {
+ /* read battery level */
+ if (handle == p_inst->ba_level_hdl ||
+ handle == p_inst->clt_cfg_hdl ||
+ handle == p_inst->rpt_ref_hdl ||
+ handle == p_inst->pres_fmt_hdl)
+ {
+ if (is_long)
+ st = GATT_NOT_LONG;
+
+ if (p_inst->p_cback)
+ {
+ if (handle == p_inst->ba_level_hdl) p_inst->pending_evt = BA_READ_LEVEL_REQ;
+ if (handle == p_inst->clt_cfg_hdl) p_inst->pending_evt = BA_READ_CLT_CFG_REQ;
+ if (handle == p_inst->pres_fmt_hdl) p_inst->pending_evt = BA_READ_PRE_FMT_REQ;
+ if (handle == p_inst->rpt_ref_hdl) p_inst->pending_evt = BA_READ_RPT_REF_REQ ;
+
+ p_inst->pending_clcb_idx = clcb_idx;
+ p_inst->pending_handle = handle;
+ act = SRVC_ACT_PENDING;
+
+ (* p_inst->p_cback)(p_inst->app_id, p_inst->pending_evt, NULL);
+ }
+ else /* application is not registered */
+ st = GATT_ERR_UNLIKELY;
+ break;
+ }
+ /* else attribute not found */
+ }
+
+
+ *p_status = st;
+ return act;
+}
+
+
+/*******************************************************************************
+**
+** Function battery_gatt_c_read_ba_req
+**
+** Description Read remote device BA level attribute request.
+**
+** Returns void
+**
+*******************************************************************************/
+BOOLEAN battery_gatt_c_read_ba_req(UINT16 conn_id)
+{
+ return TRUE;
+}
+
+/*******************************************************************************
+**
+** Function battery_c_cmpl_cback
+**
+** Description Client operation complete callback.
+**
+** Returns void
+**
+*******************************************************************************/
+void battery_c_cmpl_cback (tSRVC_CLCB *p_clcb, tGATTC_OPTYPE op,
+ tGATT_STATUS status, tGATT_CL_COMPLETE *p_data)
+{
+}
+
+
+/*******************************************************************************
+**
+** Function Battery_Instantiate
+**
+** Description Instantiate a Battery service
+**
+*******************************************************************************/
+UINT16 Battery_Instantiate (UINT8 app_id, tBA_REG_INFO *p_reg_info)
+{
+ tBT_UUID uuid = {LEN_UUID_16, {UUID_SERVCLASS_BATTERY}};
+ UINT16 srvc_hdl;
+ tGATT_STATUS status = GATT_ERROR;
+ tBA_INST *p_inst;
+ tGATT_CHAR_PROP prop = GATT_CHAR_PROP_BIT_READ;
+
+ if (battery_cb.inst_id == BA_MAX_INT_NUM)
+ {
+ GATT_TRACE_ERROR0("MAX battery service has been reached");
+ return 0;
+ }
+
+ p_inst = &battery_cb.battery_inst[battery_cb.inst_id];
+
+ srvc_hdl = GATTS_CreateService (srvc_eng_cb.gatt_if ,
+ &uuid,
+ battery_cb.inst_id ,
+ BA_MAX_ATTR_NUM,
+ p_reg_info->is_pri);
+
+ if (srvc_hdl == 0)
+ {
+ GATT_TRACE_ERROR0("Can not create service, Battery_Instantiate() failed!");
+ return 0;
+ }
+
+ battery_cb.inst_id ++;
+
+ p_inst->app_id = app_id;
+ p_inst->p_cback = p_reg_info->p_cback;
+
+ /* add battery level
+ */
+ uuid.uu.uuid16 = GATT_UUID_BATTERY_LEVEL;
+
+ if (p_reg_info->ba_level_descr & BA_LEVEL_NOTIFY)
+ prop |= GATT_CHAR_PROP_BIT_NOTIFY;
+
+ if ((p_inst->ba_level_hdl = GATTS_AddCharacteristic(srvc_hdl,
+ &uuid,
+ BATTER_LEVEL_PERM,
+ prop)) == 0)
+ {
+ GATT_TRACE_ERROR0("Can not add Battery Level, Battery_Instantiate() failed!");
+ status = GATT_ERROR;
+ }
+ else
+ {
+ if (p_reg_info->ba_level_descr & BA_LEVEL_NOTIFY)
+ {
+ uuid.uu.uuid16 = GATT_UUID_CHAR_CLIENT_CONFIG;
+ p_inst->clt_cfg_hdl = GATTS_AddCharDescriptor(srvc_hdl,
+ (GATT_PERM_READ|GATT_PERM_WRITE),
+ &uuid);
+ if (p_inst->clt_cfg_hdl == 0)
+ {
+ GATT_TRACE_ERROR0("Add battery level client notification FAILED!");
+ }
+ }
+ /* need presentation format descriptor? */
+ if (p_reg_info->ba_level_descr & BA_LEVEL_PRE_FMT)
+ {
+ uuid.uu.uuid16 = GATT_UUID_CHAR_PRESENT_FORMAT;
+ if ( (p_inst->pres_fmt_hdl = GATTS_AddCharDescriptor(srvc_hdl,
+ GATT_PERM_READ,
+ &uuid))
+ == 0)
+ {
+ GATT_TRACE_ERROR0("Add battery level presentation format descriptor FAILED!");
+ }
+
+ }
+ /* need presentation format descriptor? */
+ if (p_reg_info->ba_level_descr & BA_LEVEL_RPT_REF)
+ {
+ uuid.uu.uuid16 = GATT_UUID_RPT_REF_DESCR;
+ if ( (p_inst->rpt_ref_hdl = GATTS_AddCharDescriptor(srvc_hdl,
+ GATT_PERM_READ,
+ &uuid))
+ == 0)
+ {
+ GATT_TRACE_ERROR0("Add battery level report reference descriptor FAILED!");
+ }
+
+ }
+ /* start service
+ */
+ status = GATTS_StartService (srvc_eng_cb.gatt_if, srvc_hdl, p_reg_info->transport);
+ }
+
+ if (status != GATT_SUCCESS)
+ {
+ battery_cb.inst_id --;
+ uuid.uu.uuid16 = UUID_SERVCLASS_BATTERY;
+ GATTS_DeleteService(srvc_eng_cb.gatt_if, &uuid, battery_cb.inst_id);
+ srvc_hdl = 0;
+ }
+
+ return srvc_hdl;
+}
+/*******************************************************************************
+**
+** Function Battery_Rsp
+**
+** Description Respond to a battery service request
+**
+*******************************************************************************/
+void Battery_Rsp (UINT8 app_id, tGATT_STATUS st, UINT8 event, tBA_RSP_DATA *p_rsp)
+{
+ tBA_INST *p_inst = &battery_cb.battery_inst[0];
+ tGATTS_RSP rsp;
+ UINT8 *pp;
+
+ UINT8 i = 0;
+ while (i < BA_MAX_INT_NUM)
+ {
+ if (p_inst->app_id == app_id && p_inst->ba_level_hdl != 0)
+ break;
+ i ++;
+ }
+
+ if (i == BA_MAX_INT_NUM)
+ return;
+
+ memset(&rsp, 0, sizeof(tGATTS_RSP));
+
+ if (p_inst->pending_evt == event)
+ {
+ switch (event)
+ {
+ case BA_READ_CLT_CFG_REQ:
+ rsp.attr_value.handle = p_inst->pending_handle;
+ rsp.attr_value.len = 2;
+ pp = rsp.attr_value.value;
+ UINT16_TO_STREAM(pp, p_rsp->clt_cfg);
+ srvc_sr_rsp(p_inst->pending_clcb_idx, st, &rsp);
+ break;
+
+ case BA_READ_LEVEL_REQ:
+ rsp.attr_value.handle = p_inst->pending_handle;
+ rsp.attr_value.len = 1;
+ pp = rsp.attr_value.value;
+ UINT8_TO_STREAM(pp, p_rsp->ba_level);
+ srvc_sr_rsp(p_inst->pending_clcb_idx, st, &rsp);
+ break;
+
+ case BA_WRITE_CLT_CFG_REQ:
+ srvc_sr_rsp(p_inst->pending_clcb_idx, st, NULL);
+ break;
+
+ case BA_READ_RPT_REF_REQ:
+ rsp.attr_value.handle = p_inst->pending_handle;
+ rsp.attr_value.len = 2;
+ pp = rsp.attr_value.value;
+ UINT8_TO_STREAM(pp, p_rsp->rpt_ref.rpt_id);
+ UINT8_TO_STREAM(pp, p_rsp->rpt_ref.rpt_type);
+ srvc_sr_rsp(p_inst->pending_clcb_idx, st, &rsp);
+ break;
+
+ default:
+ break;
+ }
+ p_inst->pending_clcb_idx = 0;
+ p_inst->pending_evt = 0;
+ p_inst->pending_handle = 0;
+ }
+ return;
+}
+/*******************************************************************************
+**
+** Function Battery_Notify
+**
+** Description Send battery level notification
+**
+*******************************************************************************/
+void Battery_Notify (UINT8 app_id, BD_ADDR remote_bda, UINT8 battery_level)
+{
+ tBA_INST *p_inst = &battery_cb.battery_inst[0];
+ UINT8 i = 0;
+
+ while (i < BA_MAX_INT_NUM)
+ {
+ if (p_inst->app_id == app_id && p_inst->ba_level_hdl != 0)
+ break;
+ i ++;
+ }
+
+ if (i == BA_MAX_INT_NUM || p_inst->clt_cfg_hdl == 0)
+ return;
+
+ srvc_sr_notify(remote_bda, p_inst->ba_level_hdl, 1, &battery_level);
+
+}
+/*******************************************************************************
+**
+** Function Battery_ReadBatteryLevel
+**
+** Description Read remote device Battery Level information.
+**
+** Returns void
+**
+*******************************************************************************/
+BOOLEAN Battery_ReadBatteryLevel(BD_ADDR peer_bda)
+{
+ /* to be implemented */
+ return TRUE;
+}
+#endif /* BLE_INCLUDED */
diff --git a/stack/srvc/srvc_battery_int.h b/stack/srvc/srvc_battery_int.h
new file mode 100644
index 0000000..97c808a
--- /dev/null
+++ b/stack/srvc/srvc_battery_int.h
@@ -0,0 +1,75 @@
+/*****************************************************************************
+**
+** Name: srvc_battery_int.h
+**
+** Description: this file contains the Battery service internal interface
+** definitions.
+**
+**
+** Copyright (c) 1999-2008, Broadcom Corp., All Rights Reserved.
+** WIDCOMM Bluetooth Core. Proprietary and confidential.
+******************************************************************************/
+
+#ifndef SRVC_BATTERY_INT_H
+#define SRVC_BATTERY_INT_H
+
+#include "bt_target.h"
+#include "srvc_api.h"
+#include "gatt_api.h"
+
+#ifndef BA_MAX_INT_NUM
+#define BA_MAX_INT_NUM 4
+#endif
+
+#define BATTERY_LEVEL_SIZE 1
+
+
+typedef struct
+{
+ UINT8 app_id;
+ UINT16 ba_level_hdl;
+ UINT16 clt_cfg_hdl;
+ UINT16 rpt_ref_hdl;
+ UINT16 pres_fmt_hdl;
+
+ tBA_CBACK *p_cback;
+
+ UINT16 pending_handle;
+ UINT8 pending_clcb_idx;
+ UINT8 pending_evt;
+
+}tBA_INST;
+
+typedef struct
+{
+ tBA_INST battery_inst[BA_MAX_INT_NUM];
+ UINT8 inst_id;
+ BOOLEAN enabled;
+
+}tBATTERY_CB;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Global GATT data */
+#if GATT_DYNAMIC_MEMORY == FALSE
+GATT_API extern tBATTERY_CB battery_cb;
+#else
+GATT_API extern tBATTERY_CB *battery_cb_ptr;
+#define battery_cb (*battery_cb_ptr)
+#endif
+
+
+extern BOOLEAN battery_valid_handle_range(UINT16 handle);
+
+extern UINT8 battery_s_write_attr_value(UINT8 clcb_idx, tGATT_WRITE_REQ * p_value,
+ tGATT_STATUS *p_status);
+extern UINT8 battery_s_read_attr_value (UINT8 clcb_idx, UINT16 handle, tGATT_VALUE *p_value, BOOLEAN is_long, tGATT_STATUS* p_status);
+
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/stack/srvc/srvc_dis.c b/stack/srvc/srvc_dis.c
new file mode 100644
index 0000000..505d791
--- /dev/null
+++ b/stack/srvc/srvc_dis.c
@@ -0,0 +1,451 @@
+/*****************************************************************************
+**
+** Name: srvc_dis.c
+**
+** Description: this file contains the main Device Information Service over GATT
+** server/client and request handling functions.
+**
+** Copyright (c) 2008-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+******************************************************************************/
+
+#include "bt_target.h"
+
+#include "gatt_api.h"
+#include "gatt_int.h"
+#include "srvc_eng_int.h"
+#include "srvc_dis_int.h"
+
+#if BLE_INCLUDED == TRUE
+
+#define DIS_UUID_TO_ATTR_MASK(x) (UINT16)(1 << ((x) - GATT_UUID_SYSTEM_ID))
+
+#define DIS_MAX_NUM_INC_SVR 0
+#define DIS_MAX_CHAR_NUM 9
+#define DIS_MAX_ATTR_NUM (DIS_MAX_CHAR_NUM * 2 + DIS_MAX_NUM_INC_SVR + 1)
+
+#ifndef DIS_ATTR_DB_SIZE
+#define DIS_ATTR_DB_SIZE GATT_DB_MEM_SIZE(DIS_MAX_NUM_INC_SVR, DIS_MAX_CHAR_NUM, 0)
+#endif
+
+#define UINT64_TO_STREAM(p, u64) {*(p)++ = (UINT8)(u64); *(p)++ = (UINT8)((u64) >> 8);*(p)++ = (UINT8)((u64) >> 16); *(p)++ = (UINT8)((u64) >> 24); \
+ *(p)++ = (UINT8)((u64) >> 32); *(p)++ = (UINT8)((u64) >> 40);*(p)++ = (UINT8)((u64) >> 48); *(p)++ = (UINT8)((u64) >> 56);}
+
+#define STREAM_TO_UINT64(u64, p) {u64 = (((UINT64)(*(p))) + ((((UINT64)(*((p) + 1)))) << 8) + ((((UINT64)(*((p) + 2)))) << 16) + ((((UINT64)(*((p) + 3)))) << 24) \
+ + ((((UINT64)(*((p) + 4)))) << 32) + ((((UINT64)(*((p) + 5)))) << 40) + ((((UINT64)(*((p) + 6)))) << 48) + ((((UINT64)(*((p) + 7)))) << 56)); (p) += 8;}
+
+
+
+static const UINT16 dis_attr_uuid[DIS_MAX_CHAR_NUM] =
+{
+ GATT_UUID_SYSTEM_ID,
+ GATT_UUID_MODEL_NUMBER_STR,
+ GATT_UUID_SERIAL_NUMBER_STR,
+ GATT_UUID_FW_VERSION_STR,
+ GATT_UUID_HW_VERSION_STR,
+ GATT_UUID_SW_VERSION_STR,
+ GATT_UUID_MANU_NAME,
+ GATT_UUID_IEEE_DATA,
+ GATT_UUID_PNP_ID
+};
+
+tDIS_CB dis_cb;
+/*******************************************************************************
+** dis_valid_handle_range
+**
+** validate a handle to be a DIS attribute handle or not.
+*******************************************************************************/
+BOOLEAN dis_valid_handle_range(UINT16 handle)
+{
+ if (handle >= dis_cb.service_handle && handle <= dis_cb.max_handle)
+ return TRUE;
+ else
+ return FALSE;
+}
+/*******************************************************************************
+** dis_write_attr_value
+**
+** Process write DIS attribute request.
+*******************************************************************************/
+UINT8 dis_write_attr_value(tGATT_WRITE_REQ * p_data, tGATT_STATUS *p_status)
+{
+ *p_status = GATT_WRITE_NOT_PERMIT;
+ return SRVC_ACT_RSP;
+}
+/*******************************************************************************
+** DIS Attributes Database Server Request callback
+*******************************************************************************/
+UINT8 dis_read_attr_value (UINT8 clcb_idx, UINT16 handle, tGATT_VALUE *p_value,
+ BOOLEAN is_long, tGATT_STATUS *p_status)
+{
+ tDIS_DB_ENTRY *p_db_attr = dis_cb.dis_attr;
+ UINT8 *p = p_value->value, i, *pp;
+ UINT16 offset = p_value->offset;
+ UINT8 act = SRVC_ACT_RSP;
+ tGATT_STATUS st = GATT_NOT_FOUND;
+
+ for (i = 0; i < DIS_MAX_CHAR_NUM; i ++, p_db_attr ++)
+ {
+ if (handle == p_db_attr->handle)
+ {
+ if ((p_db_attr->uuid == GATT_UUID_PNP_ID || p_db_attr->uuid == GATT_UUID_SYSTEM_ID)&&
+ is_long == TRUE)
+ {
+ st = GATT_NOT_LONG;
+ break;
+ }
+ st = GATT_SUCCESS;
+
+ switch (p_db_attr->uuid)
+ {
+ case GATT_UUID_MANU_NAME:
+ case GATT_UUID_MODEL_NUMBER_STR:
+ case GATT_UUID_SERIAL_NUMBER_STR:
+ case GATT_UUID_FW_VERSION_STR:
+ case GATT_UUID_HW_VERSION_STR:
+ case GATT_UUID_SW_VERSION_STR:
+ case GATT_UUID_IEEE_DATA:
+ pp = dis_cb.dis_value.data_string[p_db_attr->uuid - GATT_UUID_MODEL_NUMBER_STR];
+ if (pp != NULL)
+ {
+ if (strlen ((char *)pp) > GATT_MAX_ATTR_LEN)
+ p_value->len = GATT_MAX_ATTR_LEN;
+ else
+ p_value->len = (UINT16)strlen ((char *)pp);
+ }
+ else
+ p_value->len = 0;
+
+ if (offset > p_value->len)
+ {
+ st = GATT_INVALID_OFFSET;
+ break;
+ }
+ else
+ {
+ p_value->len -= offset;
+ pp += offset;
+ ARRAY_TO_STREAM(p, pp, p_value->len);
+ GATT_TRACE_EVENT1("GATT_UUID_MANU_NAME len=0x%04x", p_value->len);
+ }
+ break;
+
+
+ case GATT_UUID_SYSTEM_ID:
+ UINT64_TO_STREAM(p, dis_cb.dis_value.system_id); /* int_min */
+ p_value->len = DIS_SYSTEM_ID_SIZE;
+ break;
+
+ case GATT_UUID_PNP_ID:
+ UINT8_TO_STREAM(p, dis_cb.dis_value.pnp_id.vendor_id_src);
+ UINT16_TO_STREAM(p, dis_cb.dis_value.pnp_id.vendor_id);
+ UINT16_TO_STREAM(p, dis_cb.dis_value.pnp_id.product_id);
+ UINT16_TO_STREAM(p, dis_cb.dis_value.pnp_id.product_version);
+ p_value->len = DIS_PNP_ID_SIZE;
+ break;
+
+ }
+ break;
+ }
+ }
+ *p_status = st;
+ return act;
+}
+
+/*******************************************************************************
+**
+** Function dis_gatt_c_read_dis_value_cmpl
+**
+** Description Client read DIS database complete callback.
+**
+** Returns void
+**
+*******************************************************************************/
+void dis_gatt_c_read_dis_value_cmpl(UINT16 conn_id)
+{
+ tSRVC_CLCB *p_clcb = srvc_eng_find_clcb_by_conn_id(conn_id);
+
+ dis_cb.dis_read_uuid_idx = 0xff;
+
+ srvc_eng_release_channel(conn_id);
+
+ if (dis_cb.p_read_dis_cback && p_clcb)
+ {
+ GATT_TRACE_ERROR1("dis_gatt_c_read_dis_value_cmpl: attr_mask = 0x%04x", p_clcb->dis_value.attr_mask);
+ GATT_TRACE_EVENT0("calling p_read_dis_cbackd");
+
+ (*dis_cb.p_read_dis_cback)(p_clcb->bda, &p_clcb->dis_value);
+ dis_cb.p_read_dis_cback=NULL;
+ }
+
+}
+
+/*******************************************************************************
+**
+** Function dis_gatt_c_read_dis_req
+**
+** Description Read remote device DIS attribute request.
+**
+** Returns void
+**
+*******************************************************************************/
+BOOLEAN dis_gatt_c_read_dis_req(UINT16 conn_id)
+{
+ tGATT_READ_PARAM param;
+
+ memset(¶m, 0, sizeof(tGATT_READ_PARAM));
+
+ param.service.uuid.len = LEN_UUID_16;
+ param.service.s_handle = 1;
+ param.service.e_handle = 0xFFFF;
+ param.service.auth_req = 0;
+
+ while (dis_cb.dis_read_uuid_idx < DIS_MAX_CHAR_NUM)
+ {
+ param.service.uuid.uu.uuid16 = dis_attr_uuid[dis_cb.dis_read_uuid_idx];
+
+ if (GATTC_Read(conn_id, GATT_READ_BY_TYPE, ¶m) == GATT_SUCCESS)
+ {
+ return(TRUE);
+ }
+ else
+ {
+ GATT_TRACE_ERROR1 ("Read DISInfo: 0x%04x GATT_Read Failed", param.service.uuid.uu.uuid16);
+ dis_cb.dis_read_uuid_idx ++;
+ }
+ }
+
+ dis_gatt_c_read_dis_value_cmpl(conn_id);
+
+ return(FALSE);
+}
+
+/*******************************************************************************
+**
+** Function dis_c_cmpl_cback
+**
+** Description Client operation complete callback.
+**
+** Returns void
+**
+*******************************************************************************/
+void dis_c_cmpl_cback (tSRVC_CLCB *p_clcb, tGATTC_OPTYPE op,
+ tGATT_STATUS status, tGATT_CL_COMPLETE *p_data)
+{
+ UINT16 read_type = dis_attr_uuid[dis_cb.dis_read_uuid_idx];
+ UINT8 *pp = NULL, *p_str;
+ UINT16 conn_id = p_clcb->conn_id;
+
+ GATT_TRACE_EVENT3 ("dis_c_cmpl_cback() - op_code: 0x%02x status: 0x%02x \
+ read_type: 0x%04x", op, status, read_type);
+
+ if (op != GATTC_OPTYPE_READ)
+ return;
+
+ if (p_data != NULL && status == GATT_SUCCESS)
+ {
+ pp = p_data->att_value.value;
+
+ switch (read_type)
+ {
+ case GATT_UUID_SYSTEM_ID:
+ GATT_TRACE_EVENT0 ("DIS_ATTR_SYS_ID_BIT");
+ if (p_data->att_value.len == DIS_SYSTEM_ID_SIZE)
+ {
+ p_clcb->dis_value.attr_mask |= DIS_ATTR_SYS_ID_BIT;
+ /* save system ID*/
+ STREAM_TO_UINT64 (p_clcb->dis_value.system_id, pp);
+ }
+ break;
+
+ case GATT_UUID_PNP_ID:
+ if (p_data->att_value.len == DIS_PNP_ID_SIZE)
+ {
+ p_clcb->dis_value.attr_mask |= DIS_ATTR_PNP_ID_BIT;
+ STREAM_TO_UINT8 (p_clcb->dis_value.pnp_id.vendor_id_src, pp);
+ STREAM_TO_UINT16 (p_clcb->dis_value.pnp_id.vendor_id, pp);
+ STREAM_TO_UINT16 (p_clcb->dis_value.pnp_id.product_id, pp);
+ STREAM_TO_UINT16 (p_clcb->dis_value.pnp_id.product_version, pp);
+ }
+ break;
+
+ case GATT_UUID_MODEL_NUMBER_STR:
+ case GATT_UUID_SERIAL_NUMBER_STR:
+ case GATT_UUID_FW_VERSION_STR:
+ case GATT_UUID_HW_VERSION_STR:
+ case GATT_UUID_SW_VERSION_STR:
+ case GATT_UUID_MANU_NAME:
+ case GATT_UUID_IEEE_DATA:
+ p_str = p_clcb->dis_value.data_string[read_type - GATT_UUID_MODEL_NUMBER_STR];
+ if (p_str != NULL)
+ GKI_freebuf(p_str);
+ if ((p_str = (UINT8 *)GKI_getbuf((UINT16)(p_data->att_value.len + 1))) != NULL)
+ {
+ memset(p_str, 0, p_data->att_value.len + 1);
+ p_clcb->dis_value.attr_mask |= DIS_UUID_TO_ATTR_MASK (read_type);
+ memcpy(p_str, p_data->att_value.value, p_data->att_value.len);
+ }
+ break;
+
+ default:
+ break;
+
+ break;
+ }/* end switch */
+ }/* end if */
+
+ dis_cb.dis_read_uuid_idx ++;
+
+ dis_gatt_c_read_dis_req(conn_id);
+}
+
+
+/*******************************************************************************
+**
+** Function DIS_SrInit
+**
+** Description Initializa the Device Information Service Server.
+**
+*******************************************************************************/
+tDIS_STATUS DIS_SrInit (tDIS_ATTR_MASK dis_attr_mask)
+{
+ tBT_UUID uuid = {LEN_UUID_16, {UUID_SERVCLASS_DEVICE_INFO}};
+ UINT16 i = 0;
+ tGATT_STATUS status;
+ tDIS_DB_ENTRY *p_db_attr = &dis_cb.dis_attr[0];
+
+ if (dis_cb.enabled)
+ {
+ GATT_TRACE_ERROR0("DIS already initalized");
+ return DIS_SUCCESS;
+ }
+
+ memset(&dis_cb, 0, sizeof(tDIS_CB));
+
+ dis_cb.service_handle = GATTS_CreateService (srvc_eng_cb.gatt_if , &uuid, 0, DIS_MAX_ATTR_NUM, TRUE);
+
+ if (dis_cb.service_handle == 0)
+ {
+ GATT_TRACE_ERROR0("Can not create service, DIS_Init failed!");
+ return GATT_ERROR;
+ }
+ dis_cb.max_handle = dis_cb.service_handle + DIS_MAX_ATTR_NUM;
+
+ while (dis_attr_mask != 0 && i < DIS_MAX_CHAR_NUM)
+ {
+ /* add Manufacturer name
+ */
+ uuid.uu.uuid16 = p_db_attr->uuid = dis_attr_uuid[i];
+ p_db_attr->handle = GATTS_AddCharacteristic(dis_cb.service_handle, &uuid, GATT_PERM_READ, GATT_CHAR_PROP_BIT_READ);
+ GATT_TRACE_DEBUG2 ("DIS_SrInit: handle of new attribute 0x%04 = x%d", uuid.uu.uuid16, p_db_attr->handle );
+ p_db_attr ++;
+ i ++;
+ dis_attr_mask >>= 1;
+ }
+
+ /* start service
+ */
+ status = GATTS_StartService (srvc_eng_cb.gatt_if, dis_cb.service_handle, GATT_TRANSPORT_LE_BR_EDR);
+
+ dis_cb.enabled = TRUE;
+
+ return (tDIS_STATUS) status;
+}
+/*******************************************************************************
+**
+** Function DIS_SrUpdate
+**
+** Description Update the DIS server attribute values
+**
+*******************************************************************************/
+tDIS_STATUS DIS_SrUpdate(tDIS_ATTR_BIT dis_attr_bit, tDIS_ATTR *p_info)
+{
+ UINT8 i = 1;
+ tDIS_STATUS st = DIS_SUCCESS;
+
+ if (dis_attr_bit & DIS_ATTR_SYS_ID_BIT)
+ {
+ dis_cb.dis_value.system_id = p_info->system_id;
+ }
+ else if (dis_attr_bit & DIS_ATTR_PNP_ID_BIT)
+ {
+ dis_cb.dis_value.pnp_id.vendor_id = p_info->pnp_id.vendor_id;
+ dis_cb.dis_value.pnp_id.vendor_id_src = p_info->pnp_id.vendor_id_src;
+ dis_cb.dis_value.pnp_id.product_id = p_info->pnp_id.product_id;
+ dis_cb.dis_value.pnp_id.product_version = p_info->pnp_id.product_version;
+ }
+ else
+ {
+ st = DIS_ILLEGAL_PARAM;
+
+ while (dis_attr_bit && i < (DIS_MAX_CHAR_NUM -1 ))
+ {
+ if (dis_attr_bit & (UINT16)(1 << i))
+ {
+ if (dis_cb.dis_value.data_string[i - 1] != NULL)
+ GKI_freebuf(dis_cb.dis_value.data_string[i]);
+/* coverity[OVERRUN-STATIC] False-positive : when i = 8, (1 << i) == DIS_ATTR_PNP_ID_BIT, and it will never come down here
+CID 49902: Out-of-bounds read (OVERRUN_STATIC)
+Overrunning static array "dis_cb.dis_value.data_string", with 7 elements, at position 7 with index variable "i".
+*/
+ if ((dis_cb.dis_value.data_string[i - 1] = (UINT8 *)GKI_getbuf((UINT16)(p_info->data_str.len + 1))) != NULL)
+ {
+ memset(dis_cb.dis_value.data_string[i - 1], 0, p_info->data_str.len + 1); /* make sure null terminate */
+ memcpy(dis_cb.dis_value.data_string[i - 1], p_info->data_str.p_data, p_info->data_str.len);
+ st = DIS_SUCCESS;
+ }
+ else
+ st = DIS_NO_RESOURCES;
+
+ break;
+ }
+ i ++;
+ }
+ }
+ return st;
+}
+/*******************************************************************************
+**
+** Function DIS_ReadDISInfo
+**
+** Description Read remote device DIS information.
+**
+** Returns void
+**
+*******************************************************************************/
+BOOLEAN DIS_ReadDISInfo(BD_ADDR peer_bda, tDIS_READ_CBACK *p_cback)
+{
+ UINT16 conn_id;
+
+ /* For now we only handle one at a time */
+ if (dis_cb.dis_read_uuid_idx != 0xff)
+ return(FALSE);
+
+ if (p_cback == NULL)
+ return(FALSE);
+
+ dis_cb.p_read_dis_cback = p_cback;
+ /* Mark currently active operation */
+ dis_cb.dis_read_uuid_idx = 0;
+
+ GATT_TRACE_EVENT3 ("DIS_ReadDISInfo() - BDA: %08x%04x cl_read_uuid: 0x%04x",
+ (peer_bda[0]<<24)+(peer_bda[1]<<16)+(peer_bda[2]<<8)+peer_bda[3],
+ (peer_bda[4]<<8)+peer_bda[5], dis_attr_uuid[dis_cb.dis_read_uuid_idx]);
+
+
+ GATT_GetConnIdIfConnected(srvc_eng_cb.gatt_if, peer_bda, &conn_id);
+
+ /* need to enhance it as multiple service is needed */
+ srvc_eng_request_channel(peer_bda, SRVC_ID_DIS);
+
+ if (conn_id == GATT_INVALID_CONN_ID)
+ {
+ return GATT_Connect(srvc_eng_cb.gatt_if, peer_bda, TRUE);
+ }
+
+ return dis_gatt_c_read_dis_req(conn_id);
+
+}
+#endif /* BLE_INCLUDED */
+
+
diff --git a/stack/srvc/srvc_dis_int.h b/stack/srvc/srvc_dis_int.h
new file mode 100644
index 0000000..ede7a85
--- /dev/null
+++ b/stack/srvc/srvc_dis_int.h
@@ -0,0 +1,76 @@
+/*****************************************************************************
+**
+** Name: srvc_dis_int.h
+**
+** Description: this file contains the GAP internal interface
+** definitions.
+**
+**
+** Copyright (c) 1999-2008, Broadcom Corp., All Rights Reserved.
+** WIDCOMM Bluetooth Core. Proprietary and confidential.
+******************************************************************************/
+
+#ifndef SRVC_DIS_INT_H
+#define SRVC_DIS_INT_H
+
+#include "bt_target.h"
+#include "srvc_api.h"
+#include "gatt_api.h"
+
+#define DIS_MAX_CHAR_NUM 9
+
+
+typedef struct
+{
+ UINT16 uuid;
+ UINT16 handle;
+}tDIS_DB_ENTRY;
+
+#define DIS_SYSTEM_ID_SIZE 8
+#define DIS_PNP_ID_SIZE 7
+
+
+
+typedef struct
+{
+ tDIS_DB_ENTRY dis_attr[DIS_MAX_CHAR_NUM];
+ tDIS_VALUE dis_value;
+
+ tDIS_READ_CBACK *p_read_dis_cback;
+
+ UINT16 service_handle;
+ UINT16 max_handle;
+
+ BOOLEAN enabled;
+
+ UINT8 dis_read_uuid_idx;
+}tDIS_CB;
+
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Global GATT data */
+#if GATT_DYNAMIC_MEMORY == FALSE
+GATT_API extern tDIS_CB dis_cb;
+#else
+GATT_API extern tDIS_CB *dis_cb_ptr;
+#define dis_cb (*dis_cb_ptr)
+#endif
+
+
+extern BOOLEAN dis_valid_handle_range(UINT16 handle);
+extern UINT8 dis_read_attr_value (UINT8 clcb_idx, UINT16 handle, tGATT_VALUE *p_value,
+ BOOLEAN is_long, tGATT_STATUS *p_status);
+extern UINT8 dis_write_attr_value(tGATT_WRITE_REQ * p_data, tGATT_STATUS *p_status);
+
+extern void dis_c_cmpl_cback (tSRVC_CLCB *p_clcb, tGATTC_OPTYPE op,
+ tGATT_STATUS status, tGATT_CL_COMPLETE *p_data);
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/stack/srvc/srvc_eng.c b/stack/srvc/srvc_eng.c
new file mode 100644
index 0000000..c4f5527
--- /dev/null
+++ b/stack/srvc/srvc_eng.c
@@ -0,0 +1,456 @@
+/*****************************************************************************
+**
+** Name: srvc_eng.c
+**
+** Description: this file contains the main Device Information Service over GATT
+** server/client and request handling functions.
+**
+** Copyright (c) 2008-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+******************************************************************************/
+
+#include "bt_target.h"
+
+#include "gatt_api.h"
+#include "gatt_int.h"
+#include "srvc_eng_int.h"
+
+#if BLE_INCLUDED == TRUE
+
+//#if DIS_INCLUDED == TRUE
+#include "srvc_dis_int.h"
+//#endif
+#include "srvc_battery_int.h"
+
+static void srvc_eng_s_request_cback (UINT16 conn_id, UINT32 trans_id, UINT8 op_code, tGATTS_DATA *p_data);
+static void srvc_eng_connect_cback (tGATT_IF gatt_if, BD_ADDR bda, UINT16 conn_id, BOOLEAN connected, tGATT_DISCONN_REASON reason);
+static void srvc_eng_c_cmpl_cback (UINT16 conn_id, tGATTC_OPTYPE op, tGATT_STATUS status, tGATT_CL_COMPLETE *p_data);
+
+static tGATT_CBACK srvc_gatt_cback =
+{
+ srvc_eng_connect_cback,
+ srvc_eng_c_cmpl_cback,
+ NULL,
+ NULL,
+ srvc_eng_s_request_cback
+} ;
+/* type for action functions */
+typedef void (*tSRVC_ENG_C_CMPL_ACTION)(tSRVC_CLCB *p_clcb, tGATTC_OPTYPE op,
+ tGATT_STATUS status, tGATT_CL_COMPLETE *p_data);
+
+const tSRVC_ENG_C_CMPL_ACTION srvc_eng_c_cmpl_act[SRVC_ID_MAX] =
+{
+ dis_c_cmpl_cback,
+};
+
+tSRVC_ENG_CB srvc_eng_cb;
+
+/*******************************************************************************
+**
+** Function srvc_eng_find_conn_id_by_bd_addr
+**
+** Description The function searches all LCB with macthing bd address
+**
+** Returns total number of clcb found.
+**
+*******************************************************************************/
+UINT16 srvc_eng_find_conn_id_by_bd_addr(BD_ADDR bda)
+{
+ UINT8 i_clcb;
+ tSRVC_CLCB *p_clcb = NULL;
+
+ for (i_clcb = 0, p_clcb= srvc_eng_cb.clcb; i_clcb < SRVC_MAX_APPS; i_clcb++, p_clcb++)
+ {
+ if (p_clcb->in_use && p_clcb->connected && !memcmp(p_clcb->bda, bda, BD_ADDR_LEN))
+ {
+ return p_clcb->conn_id;
+ }
+ }
+
+ return GATT_INVALID_CONN_ID;
+}
+
+/*******************************************************************************
+**
+** Function srvc_eng_find_clcb_by_bd_addr
+**
+** Description The function searches all LCBs with macthing bd address.
+**
+** Returns Pointer to the found link conenction control block.
+**
+*******************************************************************************/
+tSRVC_CLCB *srvc_eng_find_clcb_by_bd_addr(BD_ADDR bda)
+{
+ UINT8 i_clcb;
+ tSRVC_CLCB *p_clcb = NULL;
+
+ for (i_clcb = 0, p_clcb= srvc_eng_cb.clcb; i_clcb < SRVC_MAX_APPS; i_clcb++, p_clcb++)
+ {
+ if (p_clcb->in_use && p_clcb->connected && !memcmp(p_clcb->bda, bda, BD_ADDR_LEN))
+ {
+ return p_clcb;
+ }
+ }
+
+ return NULL;
+}
+/*******************************************************************************
+**
+** Function srvc_eng_find_clcb_by_conn_id
+**
+** Description The function searches all LCBs with macthing connection ID.
+**
+** Returns Pointer to the found link conenction control block.
+**
+*******************************************************************************/
+tSRVC_CLCB *srvc_eng_find_clcb_by_conn_id(UINT16 conn_id)
+{
+ UINT8 i_clcb;
+ tSRVC_CLCB *p_clcb = NULL;
+
+ for (i_clcb = 0, p_clcb= srvc_eng_cb.clcb; i_clcb < SRVC_MAX_APPS; i_clcb++, p_clcb++)
+ {
+ if (p_clcb->in_use && p_clcb->connected && p_clcb->conn_id == conn_id)
+ {
+ return p_clcb;
+ }
+ }
+
+ return NULL;
+}
+/*******************************************************************************
+**
+** Function srvc_eng_find_clcb_by_conn_id
+**
+** Description The function searches all LCBs with macthing connection ID.
+**
+** Returns Pointer to the found link conenction control block.
+**
+*******************************************************************************/
+UINT8 srvc_eng_find_clcb_idx_by_conn_id(UINT16 conn_id)
+{
+ UINT8 i_clcb;
+ tSRVC_CLCB *p_clcb = NULL;
+
+ for (i_clcb = 0, p_clcb= srvc_eng_cb.clcb; i_clcb < SRVC_MAX_APPS; i_clcb++, p_clcb++)
+ {
+ if (p_clcb->in_use && p_clcb->connected && p_clcb->conn_id == conn_id)
+ {
+ return i_clcb;
+ }
+ }
+
+ return SRVC_MAX_APPS;
+}
+/*******************************************************************************
+**
+** Function srvc_eng_clcb_alloc
+**
+** Description The function allocates a GATT profile connection link control block
+**
+** Returns NULL if not found. Otherwise pointer to the connection link block.
+**
+*******************************************************************************/
+tSRVC_CLCB *srvc_eng_clcb_alloc (UINT16 conn_id, BD_ADDR bda)
+{
+ UINT8 i_clcb = 0;
+ tSRVC_CLCB *p_clcb = NULL;
+
+ for (i_clcb = 0, p_clcb= srvc_eng_cb.clcb; i_clcb < SRVC_MAX_APPS; i_clcb++, p_clcb++)
+ {
+ if (!p_clcb->in_use)
+ {
+ p_clcb->in_use = TRUE;
+ p_clcb->conn_id = conn_id;
+ p_clcb->connected = TRUE;
+ memcpy (p_clcb->bda, bda, BD_ADDR_LEN);
+ break;
+ }
+ }
+ return p_clcb;
+}
+/*******************************************************************************
+**
+** Function srvc_eng_clcb_dealloc
+**
+** Description The function deallocates a GATT profile connection link control block
+**
+** Returns NTrue the deallocation is successful
+**
+*******************************************************************************/
+BOOLEAN srvc_eng_clcb_dealloc (UINT16 conn_id)
+{
+ UINT8 i_clcb = 0;
+ tSRVC_CLCB *p_clcb = NULL;
+
+ for (i_clcb = 0, p_clcb= srvc_eng_cb.clcb; i_clcb < SRVC_MAX_APPS; i_clcb++, p_clcb++)
+ {
+ if (p_clcb->in_use && p_clcb->connected && (p_clcb->conn_id == conn_id))
+ {
+ memset(p_clcb, 0, sizeof(tSRVC_CLCB));
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+/*******************************************************************************
+** Service Engine Server Attributes Database Read/Read Blob Request process
+*******************************************************************************/
+UINT8 srvc_eng_process_read_req (UINT8 clcb_idx, tGATT_READ_REQ *p_data, tGATTS_RSP *p_rsp, tGATT_STATUS *p_status)
+{
+ tGATT_STATUS status = GATT_NOT_FOUND;
+ UINT8 act = SRVC_ACT_RSP;
+
+ if (p_data->is_long)
+ p_rsp->attr_value.offset = p_data->offset;
+
+ p_rsp->attr_value.handle = p_data->handle;
+
+ if (dis_valid_handle_range(p_data->handle))
+ act = dis_read_attr_value(clcb_idx, p_data->handle, &p_rsp->attr_value, p_data->is_long, p_status);
+
+ else if (battery_valid_handle_range(p_data->handle))
+ act = battery_s_read_attr_value(clcb_idx, p_data->handle, &p_rsp->attr_value, p_data->is_long, p_status);
+
+ else
+ *p_status = status;
+ return act;
+}
+/*******************************************************************************
+** Service Engine Server Attributes Database write Request process
+*******************************************************************************/
+UINT8 srvc_eng_process_write_req (UINT8 clcb_idx, tGATT_WRITE_REQ *p_data, tGATTS_RSP *p_rsp, tGATT_STATUS *p_status)
+{
+ UINT8 act = SRVC_ACT_RSP;
+
+ if (dis_valid_handle_range(p_data->handle))
+ {
+ act = dis_write_attr_value(p_data, p_status);
+ }
+ else if (battery_valid_handle_range(p_data->handle))
+ {
+ act = battery_s_write_attr_value(clcb_idx, p_data, p_status);
+ }
+ else
+ *p_status = GATT_NOT_FOUND;
+
+ return act;
+}
+
+/*******************************************************************************
+**
+** Function srvc_eng_s_request_cback
+**
+** Description GATT DIS attribute access request callback.
+**
+** Returns void.
+**
+*******************************************************************************/
+static void srvc_eng_s_request_cback (UINT16 conn_id, UINT32 trans_id, tGATTS_REQ_TYPE type,
+ tGATTS_DATA *p_data)
+{
+ UINT8 status = GATT_INVALID_PDU;
+ tGATTS_RSP rsp_msg ;
+ UINT8 act = SRVC_ACT_IGNORE;
+ UINT8 clcb_idx = srvc_eng_find_clcb_idx_by_conn_id(conn_id);
+
+ GATT_TRACE_EVENT1("srvc_eng_s_request_cback : recv type (0x%02x)", type);
+
+ memset(&rsp_msg, 0, sizeof(tGATTS_RSP));
+
+ srvc_eng_cb.clcb[clcb_idx].trans_id = trans_id;
+
+ switch (type)
+ {
+ case GATTS_REQ_TYPE_READ:
+ act = srvc_eng_process_read_req(clcb_idx, &p_data->read_req, &rsp_msg, &status);
+ break;
+
+ case GATTS_REQ_TYPE_WRITE:
+ act = srvc_eng_process_write_req(clcb_idx, &p_data->write_req, &rsp_msg, &status);
+ if (!p_data->write_req.need_rsp)
+ act = SRVC_ACT_IGNORE;
+ break;
+
+ case GATTS_REQ_TYPE_WRITE_EXEC:
+ GATT_TRACE_EVENT0("Ignore GATT_REQ_EXEC_WRITE/WRITE_CMD" );
+ break;
+
+ case GATTS_REQ_TYPE_MTU:
+ GATT_TRACE_EVENT1("Get MTU exchange new mtu size: %d", p_data->mtu);
+ break;
+
+ default:
+ GATT_TRACE_EVENT1("Unknown/unexpected LE GAP ATT request: 0x%02x", type);
+ break;
+ }
+
+ srvc_eng_cb.clcb[clcb_idx].trans_id = 0;
+
+ if (act == SRVC_ACT_RSP)
+ GATTS_SendRsp (conn_id, trans_id, status, &rsp_msg);
+
+
+}
+
+
+/*******************************************************************************
+**
+** Function srvc_eng_c_cmpl_cback
+**
+** Description Client operation complete callback.
+**
+** Returns void
+**
+*******************************************************************************/
+static void srvc_eng_c_cmpl_cback (UINT16 conn_id, tGATTC_OPTYPE op, tGATT_STATUS status,
+ tGATT_CL_COMPLETE *p_data)
+{
+ tSRVC_CLCB *p_clcb = srvc_eng_find_clcb_by_conn_id(conn_id);
+
+ GATT_TRACE_EVENT2 ("srvc_eng_c_cmpl_cback() - op_code: 0x%02x status: 0x%02x ", op, status);
+
+ if (p_clcb == NULL)
+ {
+ GATT_TRACE_ERROR0("srvc_eng_c_cmpl_cback received for unknown connection");
+ return;
+ }
+
+ if (p_clcb->cur_srvc_id != SRVC_ID_NONE &&
+ p_clcb->cur_srvc_id <= SRVC_ID_MAX)
+ srvc_eng_c_cmpl_act[p_clcb->cur_srvc_id - 1](p_clcb, op, status, p_data);
+}
+
+
+/*******************************************************************************
+**
+** Function srvc_eng_connect_cback
+**
+** Description Gatt profile connection callback.
+**
+** Returns void
+**
+*******************************************************************************/
+static void srvc_eng_connect_cback (tGATT_IF gatt_if, BD_ADDR bda, UINT16 conn_id,
+ BOOLEAN connected, tGATT_DISCONN_REASON reason)
+{
+ GATT_TRACE_EVENT5 ("srvc_eng_connect_cback: from %08x%04x connected:%d conn_id=%d reason = 0x%04x",
+ (bda[0]<<24)+(bda[1]<<16)+(bda[2]<<8)+bda[3],
+ (bda[4]<<8)+bda[5], connected, conn_id, reason);
+
+ if (connected)
+ {
+ if (srvc_eng_clcb_alloc(conn_id, bda) == NULL)
+ {
+ GATT_TRACE_ERROR0 ("srvc_eng_connect_cback: no_resource");
+ return;
+ }
+ }
+ else
+ {
+ srvc_eng_clcb_dealloc(conn_id);
+ }
+
+}
+/*******************************************************************************
+**
+** Function srvc_eng_c_cmpl_cback
+**
+** Description Client operation complete callback.
+**
+** Returns void
+**
+*******************************************************************************/
+BOOLEAN srvc_eng_request_channel (BD_ADDR remote_bda, UINT8 srvc_id )
+{
+ BOOLEAN set = TRUE;
+ tSRVC_CLCB *p_clcb = srvc_eng_find_clcb_by_bd_addr(remote_bda);
+
+ if (p_clcb == NULL)
+ p_clcb = srvc_eng_clcb_alloc(0, remote_bda);
+
+ if (p_clcb && p_clcb->cur_srvc_id == SRVC_ID_NONE)
+ p_clcb->cur_srvc_id = srvc_id;
+ else
+ set = FALSE;
+
+ return set;
+}
+/*******************************************************************************
+**
+** Function srvc_eng_release_channel
+**
+** Description Client operation complete callback.
+**
+** Returns void
+**
+*******************************************************************************/
+void srvc_eng_release_channel (UINT16 conn_id)
+{
+ tSRVC_CLCB *p_clcb = srvc_eng_find_clcb_by_conn_id(conn_id);
+
+ p_clcb->cur_srvc_id = SRVC_ID_NONE;
+
+ /* check pending request */
+ //if (p_clcb->pend_req == NULL)
+ GATT_Disconnect(p_clcb->conn_id);
+}
+/*******************************************************************************
+**
+** Function srvc_eng_init
+**
+** Description Initializa the GATT Service engine.
+**
+*******************************************************************************/
+tGATT_STATUS srvc_eng_init (void)
+{
+ tBT_UUID app_uuid = {LEN_UUID_16, {UUID_SERVCLASS_DEVICE_INFO}};
+
+ if (srvc_eng_cb.enabled)
+ {
+ GATT_TRACE_ERROR0("DIS already initalized");
+ }
+ else
+ {
+ memset(&srvc_eng_cb, 0, sizeof(tDIS_CB));
+
+ /* Create a GATT profile service */
+ srvc_eng_cb.gatt_if = GATT_Register(&app_uuid, &srvc_gatt_cback);
+ GATT_StartIf(srvc_eng_cb.gatt_if);
+
+ GATT_TRACE_DEBUG1 ("Srvc_Init: gatt_if=%d ", srvc_eng_cb.gatt_if);
+
+ srvc_eng_cb.enabled = TRUE;
+//#if DIS_INCLUDED == TRUE
+ dis_cb.dis_read_uuid_idx = 0xff;
+//#endif
+ }
+ return GATT_SUCCESS;
+}
+
+void srvc_sr_rsp(UINT8 clcb_idx, tGATT_STATUS st, tGATTS_RSP *p_rsp)
+{
+ if (srvc_eng_cb.clcb[clcb_idx].trans_id != 0)
+ {
+ GATTS_SendRsp(srvc_eng_cb.clcb[clcb_idx].conn_id,
+ srvc_eng_cb.clcb[clcb_idx].trans_id,
+ st,
+ p_rsp);
+
+ srvc_eng_cb.clcb[clcb_idx].trans_id = 0;
+ }
+}
+void srvc_sr_notify(BD_ADDR remote_bda, UINT16 handle, UINT16 len, UINT8 *p_value)
+{
+ UINT16 conn_id = srvc_eng_find_conn_id_by_bd_addr(remote_bda);
+
+ if (conn_id != GATT_INVALID_CONN_ID)
+ {
+ GATTS_HandleValueNotification( conn_id, handle, len, p_value);
+ }
+}
+
+#endif
+
+
+
diff --git a/stack/srvc/srvc_eng_int.h b/stack/srvc/srvc_eng_int.h
new file mode 100644
index 0000000..40aae81
--- /dev/null
+++ b/stack/srvc/srvc_eng_int.h
@@ -0,0 +1,82 @@
+/*****************************************************************************
+**
+** Name: srvc_eng_int.h
+**
+** Description: this file contains the Service Engine internal interface
+** definitions.
+**
+**
+** Copyright (c) 1999-2008, Broadcom Corp., All Rights Reserved.
+** Broadcom Corp. Bluetooth Core. Proprietary and confidential.
+******************************************************************************/
+
+#ifndef SRVC_ENG_INT_H
+#define SRVC_ENG_INT_H
+
+#include "bt_target.h"
+#include "gatt_api.h"
+#include "srvc_api.h"
+
+#define SRVC_MAX_APPS GATT_CL_MAX_LCB
+
+#define SRVC_ID_NONE 0
+#define SRVC_ID_DIS 1
+#define SRVC_ID_MAX SRVC_ID_DIS
+
+#define SRVC_ACT_IGNORE 0
+#define SRVC_ACT_RSP 1
+#define SRVC_ACT_PENDING 2
+
+typedef struct
+{
+ BOOLEAN in_use;
+ UINT16 conn_id;
+ BOOLEAN connected;
+ BD_ADDR bda;
+ UINT32 trans_id;
+ UINT8 cur_srvc_id;
+
+ tDIS_VALUE dis_value;
+
+}tSRVC_CLCB;
+
+
+/* service engine control block */
+typedef struct
+{
+ tSRVC_CLCB clcb[SRVC_MAX_APPS]; /* connection link*/
+ tGATT_IF gatt_if;
+ BOOLEAN enabled;
+
+}tSRVC_ENG_CB;
+
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Global GATT data */
+#if GATT_DYNAMIC_MEMORY == FALSE
+GATT_API extern tSRVC_ENG_CB srvc_eng_cb;
+#else
+GATT_API extern tSRVC_ENG_CB srvc_eng_cb_ptr;
+#define srvc_eng_cb (*srvc_eng_cb_ptr)
+
+#endif
+
+extern tSRVC_CLCB *srvc_eng_find_clcb_by_conn_id(UINT16 conn_id);
+extern tSRVC_CLCB *srvc_eng_find_clcb_by_bd_addr(BD_ADDR bda);
+extern UINT16 srvc_eng_find_conn_id_by_bd_addr(BD_ADDR bda);
+
+
+extern void srvc_eng_release_channel (UINT16 conn_id) ;
+extern BOOLEAN srvc_eng_request_channel (BD_ADDR remote_bda, UINT8 srvc_id );
+extern void srvc_sr_rsp(UINT8 clcb_idx, tGATT_STATUS st, tGATTS_RSP *p_rsp);
+extern void srvc_sr_notify(BD_ADDR remote_bda, UINT16 handle, UINT16 len, UINT8 *p_value);
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif