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(&param, 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, &param) == 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