Merge "read report array out of boundary for BLE HID device."
diff --git a/bta/dm/bta_dm_act.c b/bta/dm/bta_dm_act.c
index 46d73b3..f7422f7 100755
--- a/bta/dm/bta_dm_act.c
+++ b/bta/dm/bta_dm_act.c
@@ -5017,6 +5017,7 @@
                         p_data->ble_set_adv_params.p_dir_bda,
                         BTA_DM_BLE_ADV_CHNL_MAP);
 }
+
 /*******************************************************************************
 **
 ** Function         bta_dm_ble_set_adv_config
@@ -5032,6 +5033,34 @@
                         (tBTM_BLE_ADV_DATA *)p_data->ble_set_adv_data.p_adv_cfg);
 }
 
+/*******************************************************************************
+**
+** Function         bta_dm_ble_set_scan_rsp
+**
+** Description      This function set the customized ADV scan resp. configuration
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_dm_ble_set_scan_rsp (tBTA_DM_MSG *p_data)
+{
+    BTM_BleWriteScanRsp(p_data->ble_set_adv_data.data_mask,
+                        (tBTM_BLE_ADV_DATA *)p_data->ble_set_adv_data.p_adv_cfg);
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_ble_broadcast
+**
+** Description      Starts or stops LE broadcasts
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_dm_ble_broadcast (tBTA_DM_MSG *p_data)
+{
+    BTM_BleBroadcast(p_data->ble_observe.start);
+}
 
 #if ((defined BTA_GATT_INCLUDED) &&  (BTA_GATT_INCLUDED == TRUE))
 #ifndef BTA_DM_GATT_CLOSE_DELAY_TOUT
diff --git a/bta/dm/bta_dm_api.c b/bta/dm/bta_dm_api.c
index 941213a..e37548e 100644
--- a/bta/dm/bta_dm_api.c
+++ b/bta/dm/bta_dm_api.c
@@ -1510,6 +1510,60 @@
         bta_sys_sendmsg(p_msg);
     }
 }
+
+/*******************************************************************************
+**
+** Function         BTA_DmBleSetScanRsp
+**
+** Description      This function is called to override the BTA scan response.
+**
+** Parameters       Pointer to User defined ADV data structure
+**
+** Returns          None
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmBleSetScanRsp (tBTA_BLE_AD_MASK data_mask, tBTA_BLE_ADV_DATA *p_adv_cfg)
+{
+    tBTA_DM_API_SET_ADV_CONFIG  *p_msg;
+
+    if ((p_msg = (tBTA_DM_API_SET_ADV_CONFIG *) GKI_getbuf(sizeof(tBTA_DM_API_SET_ADV_CONFIG))) != NULL)
+    {
+        p_msg->hdr.event = BTA_DM_API_BLE_SET_SCAN_RSP_EVT;
+		p_msg->data_mask = data_mask;
+        p_msg->p_adv_cfg = p_adv_cfg;
+
+        bta_sys_sendmsg(p_msg);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_DmBleBroadcast
+**
+** Description      This function starts or stops LE broadcasting.
+**
+** Parameters       start: start or stop broadcast.
+**
+** Returns          None
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmBleBroadcast (BOOLEAN start)
+{
+    tBTA_DM_API_BLE_OBSERVE   *p_msg;
+
+    APPL_TRACE_API1("BTA_DmBleBroadcast: start = %d ", start);
+
+    if ((p_msg = (tBTA_DM_API_BLE_OBSERVE *) GKI_getbuf(sizeof(tBTA_DM_API_BLE_OBSERVE))) != NULL)
+    {
+        memset(p_msg, 0, sizeof(tBTA_DM_API_BLE_OBSERVE));
+
+        p_msg->hdr.event = BTA_DM_API_BLE_BROADCAST_EVT;
+        p_msg->start = start;
+
+        bta_sys_sendmsg(p_msg);
+    }
+}
+
 #endif
 /*******************************************************************************
 **
diff --git a/bta/dm/bta_dm_int.h b/bta/dm/bta_dm_int.h
index d87dbf3..dd3e16c 100644
--- a/bta/dm/bta_dm_int.h
+++ b/bta/dm/bta_dm_int.h
@@ -101,6 +101,8 @@
     BTA_DM_API_BLE_OBSERVE_EVT,
     BTA_DM_API_BLE_ADV_PARAM_EVT,
     BTA_DM_API_BLE_SET_ADV_CONFIG_EVT,
+    BTA_DM_API_BLE_SET_SCAN_RSP_EVT,
+    BTA_DM_API_BLE_BROADCAST_EVT,
 #endif
 
 #if ( BTM_EIR_SERVER_INCLUDED == TRUE )&&( BTA_EIR_CANNED_UUID_LIST != TRUE )&&(BTA_EIR_SERVER_NUM_CUSTOM_UUID > 0)
@@ -996,6 +998,8 @@
 extern void bta_dm_ble_observe (tBTA_DM_MSG *p_data);
 extern void bta_dm_ble_set_adv_params (tBTA_DM_MSG *p_data);
 extern void bta_dm_ble_set_adv_config (tBTA_DM_MSG *p_data);
+extern void bta_dm_ble_set_scan_rsp (tBTA_DM_MSG *p_data);
+extern void bta_dm_ble_broadcast (tBTA_DM_MSG *p_data);
 
 #endif
 extern void bta_dm_set_encryption(tBTA_DM_MSG *p_data);
diff --git a/bta/dm/bta_dm_main.c b/bta/dm/bta_dm_main.c
index 50f871f..0f6b91a 100644
--- a/bta/dm/bta_dm_main.c
+++ b/bta/dm/bta_dm_main.c
@@ -98,6 +98,8 @@
     bta_dm_ble_observe,
     bta_dm_ble_set_adv_params,     /* BTA_DM_API_BLE_SCAN_PARAM_EVT */
     bta_dm_ble_set_adv_config,     /* BTA_DM_API_BLE_SET_ADV_CONFIG_EVT */
+    bta_dm_ble_set_scan_rsp,       /* BTA_DM_API_BLE_SET_SCAN_RSP_EVT */
+    bta_dm_ble_broadcast,          /* BTA_DM_API_BLE_BROADCAST_EVT */
 #endif
 
 #if ( BTM_EIR_SERVER_INCLUDED == TRUE )&&( BTA_EIR_CANNED_UUID_LIST != TRUE )&&(BTA_EIR_SERVER_NUM_CUSTOM_UUID > 0)
diff --git a/bta/hh/bta_hh_int.h b/bta/hh/bta_hh_int.h
index ed93dd5..1ac40da 100644
--- a/bta/hh/bta_hh_int.h
+++ b/bta/hh/bta_hh_int.h
@@ -203,7 +203,7 @@
 }tBTA_HH_LE_RPT;
 
 #ifndef BTA_HH_LE_RPT_MAX
-#define BTA_HH_LE_RPT_MAX       10
+#define BTA_HH_LE_RPT_MAX       20
 #endif
 
 typedef struct
diff --git a/bta/hh/bta_hh_le.c b/bta/hh/bta_hh_le.c
index d968861..dbbfb32 100644
--- a/bta/hh/bta_hh_le.c
+++ b/bta/hh/bta_hh_le.c
@@ -38,7 +38,7 @@
 
 #define BTA_HH_LE_RPT_TYPE_VALID(x)     ((x) <= BTA_LE_HID_RPT_FEATURE && (x)>=BTA_LE_HID_RPT_INPUT)
 
-#define BTA_HH_LE_RPT_INST_ID_MAP(s,c)  (UINT8)(((s)<<4)||(c))
+#define BTA_HH_LE_RPT_INST_ID_MAP(s,c)  (UINT8)(((s)<<4)|(c))
 #define BTA_HH_LE_RPT_GET_SRVC_INST_ID(x)  (UINT8)(x  >> 4)
 #define BTA_HH_LE_RPT_GET_RPT_INST_ID(x)  (UINT8)(x & 0x0f)
 
@@ -1088,7 +1088,7 @@
                                           p_char_id->char_id.inst_id,
                                           prop) == NULL)
         {
-            APPL_TRACE_ERROR0("Add report entry failed !!!")
+            APPL_TRACE_ERROR0("Add report entry failed !!!");
             break;
         }
 
@@ -1129,7 +1129,7 @@
                                       prop) == NULL)
 
     {
-        APPL_TRACE_ERROR0("Add report entry failed !!!")
+        APPL_TRACE_ERROR0("Add report entry failed !!!");
     }
 
     return;
diff --git a/bta/include/bta_api.h b/bta/include/bta_api.h
index e52e699..4345fbf 100644
--- a/bta/include/bta_api.h
+++ b/bta/include/bta_api.h
@@ -1884,7 +1884,7 @@
 *******************************************************************************/
 BTA_API extern void BTA_DmSetAfhChannelAssessment (BOOLEAN enable_or_disable);
 
-#if BLE_INCLUDE == TRUE
+#if BLE_INCLUDED == TRUE
 // btla-specific --
 /*******************************************************************************
 **
@@ -1927,6 +1927,34 @@
 *******************************************************************************/
 BTA_API extern void BTA_DmBleSetAdvConfig (tBTA_BLE_AD_MASK data_mask,
                                            tBTA_BLE_ADV_DATA *p_adv_cfg);
+
+/*******************************************************************************
+**
+** Function         BTA_DmBleSetScanRsp
+**
+** Description      This function is called to override the BTA scan response.
+**
+** Parameters       Pointer to User defined ADV data structure
+**
+** Returns          None
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmBleSetScanRsp (tBTA_BLE_AD_MASK data_mask,
+                                         tBTA_BLE_ADV_DATA *p_adv_cfg);
+
+/*******************************************************************************
+**
+** Function         BTA_DmBleBroadcast
+**
+** Description      This function starts or stops LE broadcasting.
+**
+** Parameters       start: start or stop broadcast.
+**
+** Returns          None
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmBleBroadcast (BOOLEAN start);
+
 #endif
 
 #ifdef __cplusplus
diff --git a/btif/src/btif_gatt_client.c b/btif/src/btif_gatt_client.c
index ce51ce2..64cd976 100644
--- a/btif/src/btif_gatt_client.c
+++ b/btif/src/btif_gatt_client.c
@@ -104,8 +104,8 @@
 
 typedef struct
 {
-    tBTM_BLE_AD_MASK mask;
-    tBTM_BLE_ADV_DATA data;
+    tBTA_BLE_AD_MASK mask;
+    tBTA_BLE_ADV_DATA data;
 } btgatt_adv_data;
 
 typedef struct
@@ -819,17 +819,46 @@
             break;
 
         case BTIF_GATTC_LISTEN:
+#ifdef BLE_PERIPHERAL_MODE_SUPPORT
             BTA_GATTC_Listen(p_cb->client_if, p_cb->start, NULL);
+#else
+            BTA_DmBleBroadcast(p_cb->start);
+#endif
             break;
 
         case BTIF_GATTC_SET_ADV_DATA:
         {
             if (p_cb->start == 0)
-                BTM_BleWriteAdvData(p_cb->adv_data.mask, &p_cb->adv_data.data);
+                BTA_DmBleSetAdvConfig(p_cb->adv_data.mask, &p_cb->adv_data.data);
             else
-                BTM_BleWriteScanRsp(p_cb->adv_data.mask, &p_cb->adv_data.data);
+                BTA_DmBleSetScanRsp(p_cb->adv_data.mask, &p_cb->adv_data.data);
+
+            // Cleanup ...
+
+            // ... manufacturer data
             if (p_cb->adv_data.data.manu.p_val != NULL)
                 GKI_freebuf(p_cb->adv_data.data.manu.p_val);
+
+            // ... service data
+            if (p_cb->adv_data.data.p_proprietary != NULL)
+            {
+                int i = 0;
+                tBTA_BLE_PROP_ELEM *p_elem = p_cb->adv_data.data.p_proprietary->p_elem;
+                while (i++ != p_cb->adv_data.data.p_proprietary->num_elem && p_elem)
+                {
+                    if (p_elem->p_val != NULL)
+                        GKI_freebuf(p_elem->p_val);
+                    ++p_elem;
+                }
+                if (p_cb->adv_data.data.p_proprietary->p_elem != NULL)
+                    GKI_freebuf(p_cb->adv_data.data.p_proprietary->p_elem);
+                GKI_freebuf(p_cb->adv_data.data.p_proprietary);
+            }
+
+            // ... service list
+            if (p_cb->adv_data.data.services.p_uuid != NULL)
+                GKI_freebuf(p_cb->adv_data.data.services.p_uuid);
+
             break;
         }
 
@@ -904,7 +933,9 @@
 
 static bt_status_t btif_gattc_set_adv_data(int client_if, bool set_scan_rsp, bool include_name,
                 bool include_txpower, int min_interval, int max_interval, int appearance,
-                uint16_t manufacturer_len, char* manufacturer_data)
+                uint16_t manufacturer_len, char* manufacturer_data,
+                uint16_t service_data_len, char* service_data,
+                uint16_t service_uuid_len, char* service_uuid)
 {
     CHECK_BTGATT_INIT();
     btif_gattc_cb_t btif_cb;
@@ -950,6 +981,112 @@
         }
     }
 
+    tBTA_BLE_PROP_ELEM *p_elem_service_data = NULL;
+    tBTA_BLE_PROP_ELEM *p_elem_service_128 = NULL;
+
+    if (service_data_len > 0 && service_data != NULL)
+    {
+        p_elem_service_data = GKI_getbuf(sizeof(tBTA_BLE_PROP_ELEM));
+        if (p_elem_service_data != NULL)
+        {
+            p_elem_service_data->p_val = GKI_getbuf(service_data_len);
+            if (p_elem_service_data->p_val != NULL)
+            {
+                p_elem_service_data->adv_type = BTM_BLE_AD_TYPE_SERVICE_DATA;
+                p_elem_service_data->len = service_data_len;
+                memcpy(p_elem_service_data->p_val, service_data, service_data_len);
+
+            } else {
+                GKI_freebuf(p_elem_service_data);
+                p_elem_service_data = NULL;
+            }
+        }
+    }
+
+    if (service_uuid_len > 0 && service_uuid != NULL)
+    {
+        btif_cb.adv_data.data.services.list_cmpl = FALSE;
+        btif_cb.adv_data.data.services.num_service = 0;
+
+        btif_cb.adv_data.data.services.p_uuid =
+            GKI_getbuf(service_uuid_len / LEN_UUID_128 * LEN_UUID_16);
+        if (btif_cb.adv_data.data.services.p_uuid != NULL)
+        {
+            UINT16 *p_uuid_out = btif_cb.adv_data.data.services.p_uuid;
+            while (service_uuid_len >= LEN_UUID_128)
+            {
+                bt_uuid_t uuid;
+                memset(&uuid, 0, sizeof(bt_uuid_t));
+                memcpy(&uuid.uu, service_uuid, LEN_UUID_128);
+
+                tBT_UUID bt_uuid;
+                memset(&bt_uuid, 0, sizeof(tBT_UUID));
+                btif_to_bta_uuid(&bt_uuid, &uuid);
+
+                if (bt_uuid.len == LEN_UUID_16)
+                {
+                    btif_cb.adv_data.mask |= BTM_BLE_AD_BIT_SERVICE;
+                    ++btif_cb.adv_data.data.services.num_service;
+                    *p_uuid_out++ = bt_uuid.uu.uuid16;
+
+                } else if (bt_uuid.len == LEN_UUID_128 && p_elem_service_128 == NULL) {
+                    /* Currently, only one 128-bit UUID is supported */
+                    p_elem_service_128 = GKI_getbuf(sizeof(tBTA_BLE_PROP_ELEM));
+                    if (p_elem_service_128 != NULL)
+                    {
+                        p_elem_service_128->p_val = GKI_getbuf(LEN_UUID_128);
+                        if (p_elem_service_128->p_val != NULL)
+                        {
+                            p_elem_service_128->adv_type = BTM_BLE_AD_TYPE_128SRV_PART;
+                            p_elem_service_128->len = LEN_UUID_128;
+                            memcpy(p_elem_service_128->p_val, bt_uuid.uu.uuid128, LEN_UUID_128);
+
+                        } else {
+                            GKI_freebuf(p_elem_service_128);
+                            p_elem_service_128 = NULL;
+                        }
+                    }
+                }
+
+                service_uuid += LEN_UUID_128;
+                service_uuid_len -= LEN_UUID_128;
+            }
+        }
+    }
+
+    if (p_elem_service_data != NULL || p_elem_service_128 != NULL)
+    {
+        btif_cb.adv_data.data.p_proprietary = GKI_getbuf(sizeof(tBTA_BLE_PROPRIETARY));
+        if (btif_cb.adv_data.data.p_proprietary != NULL)
+        {
+            tBTA_BLE_PROPRIETARY *p_prop = btif_cb.adv_data.data.p_proprietary;
+            tBTA_BLE_PROP_ELEM *p_elem = NULL;
+            p_prop->num_elem = 0;
+            btif_cb.adv_data.mask |= BTM_BLE_AD_BIT_PROPRIETARY;
+
+            if (p_elem_service_128 != NULL)
+                ++p_prop->num_elem;
+
+            if (p_elem_service_data != NULL)
+                ++p_prop->num_elem;
+
+            p_prop->p_elem = GKI_getbuf(sizeof(tBTA_BLE_PROP_ELEM) * p_prop->num_elem);
+            p_elem = p_prop->p_elem;
+
+            if (p_elem_service_128 != NULL)
+            {
+                memcpy(p_elem++, p_elem_service_128, sizeof(tBTA_BLE_PROP_ELEM));
+                GKI_freebuf(p_elem_service_128);
+            }
+
+            if (p_elem_service_data != NULL)
+            {
+                memcpy(p_elem++, p_elem_service_data, sizeof(tBTA_BLE_PROP_ELEM));
+                GKI_freebuf(p_elem_service_data);
+            }
+        }
+    }
+
     return btif_transfer_context(btgattc_handle_event, BTIF_GATTC_SET_ADV_DATA,
                                  (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
 }
diff --git a/stack/gatt/gatt_api.c b/stack/gatt/gatt_api.c
index a96c58a..b53b7c5 100644
--- a/stack/gatt/gatt_api.c
+++ b/stack/gatt/gatt_api.c
@@ -1294,7 +1294,9 @@
 
     gatt_deregister_bgdev_list(gatt_if);
     /* update the listen mode */
+#ifdef BLE_PERIPHERAL_MODE_SUPPORT
     GATT_Listen(gatt_if, FALSE, NULL);
+#endif
 
     memset (p_reg, 0, sizeof(tGATT_REG));
 }