OSDN Git Service

LE Multi ADV feature
authorSatya Calloji <satyac@broadcom.com>
Wed, 30 Apr 2014 22:55:39 +0000 (15:55 -0700)
committerSatya Calloji <satyac@broadcom.com>
Fri, 16 May 2014 23:22:02 +0000 (16:22 -0700)
BTIF and stack changes for LE multi ADV feature

Change-Id: I5e009ff8cbac5fc6f92ca943c61c4faf98e4e2ce

19 files changed:
bta/dm/bta_dm_act.c
bta/dm/bta_dm_api.c
bta/dm/bta_dm_int.h
bta/dm/bta_dm_main.c
bta/include/bta_api.h
bta/include/bta_gatt_api.h
btif/include/btif_gatt_multi_adv_util.h [new file with mode: 0644]
btif/src/btif_gatt_client.c
btif/src/btif_gatt_multi_adv_util.c [new file with mode: 0644]
include/bt_target.h
main/Android.mk
stack/Android.mk
stack/btm/btm_ble.c
stack/btm/btm_ble_addr.c
stack/btm/btm_ble_gap.c
stack/btm/btm_ble_int.h
stack/btm/btm_ble_multi_adv.c [new file with mode: 0644]
stack/include/btm_ble_api.h
stack/include/hcidefs.h

index 9391d80..ab81d0d 100644 (file)
@@ -5204,8 +5204,16 @@ void bta_dm_ble_set_adv_params (tBTA_DM_MSG *p_data)
 *******************************************************************************/
 void bta_dm_ble_set_adv_config (tBTA_DM_MSG *p_data)
 {
-    BTM_BleWriteAdvData(p_data->ble_set_adv_data.data_mask,
-                        (tBTM_BLE_ADV_DATA *)p_data->ble_set_adv_data.p_adv_cfg);
+    tBTA_STATUS status = BTA_FAILURE;
+
+    if (BTM_BleWriteAdvData(p_data->ble_set_adv_data.data_mask,
+                        (tBTM_BLE_ADV_DATA *)p_data->ble_set_adv_data.p_adv_cfg) == BTM_SUCCESS)
+    {
+        status = BTA_SUCCESS;
+    }
+
+    if (p_data->ble_set_adv_data.p_adv_data_cback)
+        (*p_data->ble_set_adv_data.p_adv_data_cback)(status);
 }
 
 /*******************************************************************************
@@ -5219,8 +5227,16 @@ void bta_dm_ble_set_adv_config (tBTA_DM_MSG *p_data)
 *******************************************************************************/
 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);
+    tBTA_STATUS status = BTA_FAILURE;
+
+    if(BTM_BleWriteScanRsp(p_data->ble_set_adv_data.data_mask,
+                        (tBTM_BLE_ADV_DATA *)p_data->ble_set_adv_data.p_adv_cfg) == BTM_SUCCESS)
+    {
+        status = BTA_SUCCESS;
+    }
+
+    if (p_data->ble_set_adv_data.p_adv_data_cback)
+        (*p_data->ble_set_adv_data.p_adv_data_cback)(status);
 }
 
 /*******************************************************************************
@@ -5237,6 +5253,71 @@ void bta_dm_ble_broadcast (tBTA_DM_MSG *p_data)
     BTM_BleBroadcast(p_data->ble_observe.start);
 }
 
+/*******************************************************************************
+**
+** Function         bta_dm_ble_multi_adv_enb
+**
+** Description      This function enables a single advertising instance
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_dm_ble_multi_adv_enb(tBTA_DM_MSG *p_data)
+{
+#if BLE_MULTI_ADV_INCLUDED == TRUE
+    BTM_BleEnableAdvInstance((tBTM_BLE_ADV_PARAMS*)p_data->ble_multi_adv_enb.p_params,
+        p_data->ble_multi_adv_enb.p_cback,p_data->ble_multi_adv_enb.p_ref);
+#endif
+}
+/*******************************************************************************
+**
+** Function         bta_dm_ble_multi_adv_param_upd
+**
+** Description      This function updates multiple advertising instance parameters
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_dm_ble_multi_adv_upd_param(tBTA_DM_MSG *p_data)
+{
+#if BLE_MULTI_ADV_INCLUDED == TRUE
+    BTM_BleUpdateAdvInstParam(p_data->ble_multi_adv_param.inst_id,
+        (tBTM_BLE_ADV_PARAMS*)p_data->ble_multi_adv_param.p_params);
+#endif
+}
+/*******************************************************************************
+**
+** Function         bta_dm_ble_multi_adv_data
+**
+** Description      This function write multiple advertising instance adv data
+**                  or scan response data
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_dm_ble_multi_adv_data(tBTA_DM_MSG *p_data)
+{
+#if BLE_MULTI_ADV_INCLUDED == TRUE
+    BTM_BleCfgAdvInstData(p_data->ble_multi_adv_data.inst_id,p_data->ble_multi_adv_data.is_scan_rsp,
+        p_data->ble_multi_adv_data.data_mask,(tBTM_BLE_ADV_DATA*)p_data->ble_multi_adv_data.p_data);
+#endif
+}
+/*******************************************************************************
+**
+** Function         btm_dm_ble_multi_adv_disable
+**
+** Description      This function disable a single adv instance
+**
+** Parameters:
+**
+*******************************************************************************/
+void btm_dm_ble_multi_adv_disable(tBTA_DM_MSG *p_data)
+{
+#if BLE_MULTI_ADV_INCLUDED == TRUE
+    BTM_BleDisableAdvInstance(p_data->ble_multi_adv_disable.inst_id);
+#endif
+}
+
 #if ((defined BTA_GATT_INCLUDED) &&  (BTA_GATT_INCLUDED == TRUE))
 #ifndef BTA_DM_GATT_CLOSE_DELAY_TOUT
 #define BTA_DM_GATT_CLOSE_DELAY_TOUT    1000
index 89e2cce..288e126 100644 (file)
@@ -1515,19 +1515,26 @@ void BTA_DmSetBleAdvParams (UINT16 adv_int_min, UINT16 adv_int_max,
 **
 ** Description      This function is called to override the BTA default ADV parameters.
 **
-** Parameters       Pointer to User defined ADV data structure
+** Parameters       data_mask: adv data mask.
+**                  p_adv_cfg: Pointer to User defined ADV data structure. This
+**                             memory space can not be freed until p_adv_data_cback
+**                             is received.
+**                  p_adv_data_cback: set adv data complete callback.
 **
 ** Returns          None
 **
 *******************************************************************************/
-void BTA_DmBleSetAdvConfig (tBTA_BLE_AD_MASK data_mask, tBTA_BLE_ADV_DATA *p_adv_cfg)
+void BTA_DmBleSetAdvConfig (tBTA_BLE_AD_MASK data_mask, tBTA_BLE_ADV_DATA *p_adv_cfg,
+                            tBTA_SET_ADV_DATA_CMPL_CBACK *p_adv_data_cback)
 {
     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)
+    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_ADV_CONFIG_EVT;
         p_msg->data_mask = data_mask;
+        p_msg->p_adv_data_cback = p_adv_data_cback;
         p_msg->p_adv_cfg = p_adv_cfg;
 
         bta_sys_sendmsg(p_msg);
@@ -1545,14 +1552,17 @@ void BTA_DmBleSetAdvConfig (tBTA_BLE_AD_MASK data_mask, tBTA_BLE_ADV_DATA *p_adv
 ** Returns          None
 **
 *******************************************************************************/
-BTA_API extern void BTA_DmBleSetScanRsp (tBTA_BLE_AD_MASK data_mask, tBTA_BLE_ADV_DATA *p_adv_cfg)
+BTA_API extern void BTA_DmBleSetScanRsp (tBTA_BLE_AD_MASK data_mask, tBTA_BLE_ADV_DATA *p_adv_cfg,
+                        tBTA_SET_ADV_DATA_CMPL_CBACK *p_adv_data_cback)
 {
     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)
+    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_data_cback = p_adv_data_cback;
         p_msg->p_adv_cfg = p_adv_cfg;
 
         bta_sys_sendmsg(p_msg);
@@ -1814,6 +1824,166 @@ void BTA_DmBleConfigLocalPrivacy(BOOLEAN privacy_enable)
 }
 #endif
 
+#if BLE_INCLUDED == TRUE
+/*******************************************************************************
+**
+** Function         BTA_BleEnableAdvInstance
+**
+** Description      This function enable a Multi-ADV instance with the specififed
+**                  adv parameters
+**
+** Parameters       p_params: pointer to the adv parameter structure.
+**                  p_cback: callback function associated to this adv instance.
+**                  p_ref: reference data pointer to this adv instance.
+**
+** Returns          BTA_SUCCESS if command started sucessfully; otherwise failure.
+**
+*******************************************************************************/
+tBTA_STATUS BTA_BleEnableAdvInstance (tBTA_BLE_ADV_PARAMS *p_params,
+                                tBTA_BLE_MULTI_ADV_CBACK *p_cback,
+                                void *p_ref)
+{
+    tBTA_DM_API_BLE_MULTI_ADV_ENB    *p_msg;
+    UINT16 len = sizeof(tBTA_BLE_ADV_PARAMS) + sizeof(tBTA_DM_API_BLE_MULTI_ADV_ENB);
+
+    APPL_TRACE_API0 ("BTA_BleEnableAdvInstance");
+
+    if ((p_msg = (tBTA_DM_API_BLE_MULTI_ADV_ENB *) GKI_getbuf(len)) != NULL)
+    {
+        memset(p_msg, 0, sizeof(tBTA_DM_API_BLE_MULTI_ADV_ENB));
+
+        p_msg->hdr.event     = BTA_DM_API_BLE_MULTI_ADV_ENB_EVT;
+        p_msg->p_cback      = (void *)p_cback;
+        if (p_params != NULL)
+        {
+            p_msg->p_params =  (void *)(p_msg + 1);
+            memcpy(p_msg->p_params, p_params, sizeof(tBTA_BLE_ADV_PARAMS));
+        }
+        p_msg->p_ref        = p_ref;
+
+        bta_sys_sendmsg(p_msg);
+
+        return BTA_SUCCESS;
+    }
+    return BTA_FAILURE;
+}
+
+/*******************************************************************************
+**
+** Function         BTA_BleUpdateAdvInstParam
+**
+** Description      This function update a Multi-ADV instance with the specififed
+**                  adv parameters.
+**
+** Parameters       inst_id: Adv instance to update the parameter.
+**                  p_params: pointer to the adv parameter structure.
+**
+** Returns          BTA_SUCCESS if command started sucessfully; otherwise failure.
+**
+*******************************************************************************/
+tBTA_STATUS BTA_BleUpdateAdvInstParam (UINT8 inst_id, tBTA_BLE_ADV_PARAMS *p_params)
+{
+    tBTA_DM_API_BLE_MULTI_ADV_PARAM    *p_msg;
+    UINT16      len = sizeof(tBTA_BLE_ADV_PARAMS) + sizeof(tBTA_DM_API_BLE_MULTI_ADV_PARAM);
+
+    APPL_TRACE_API0 ("BTA_BleUpdateAdvInstParam");
+    if (inst_id <= BTM_BLE_MULTI_ADV_MAX && inst_id != BTA_BLE_MULTI_ADV_ILLEGAL)
+    {
+        if ((p_msg = (tBTA_DM_API_BLE_MULTI_ADV_PARAM *) GKI_getbuf(len)) != NULL)
+        {
+             memset(p_msg, 0, sizeof(tBTA_DM_API_BLE_MULTI_ADV_PARAM));
+
+             p_msg->hdr.event     = BTA_DM_API_BLE_MULTI_ADV_PARAM_UPD_EVT;
+             p_msg->inst_id        = inst_id;
+             p_msg->p_params =  (void *)(p_msg + 1);
+             memcpy(p_msg->p_params, p_params, sizeof(tBTA_BLE_ADV_PARAMS));
+
+             bta_sys_sendmsg(p_msg);
+
+             return BTA_SUCCESS;
+        }
+    }
+    return BTA_FAILURE;
+}
+
+/*******************************************************************************
+**
+** Function         BTA_BleCfgAdvInstData
+**
+** Description      This function configure a Multi-ADV instance with the specififed
+**                  adv data or scan response data.
+**
+** Parameter        inst_id: Adv instance to configure the adv data or scan response.
+**                  is_scan_rsp: is the data scan response or adv data.
+**                  data_mask: adv data type as bit mask.
+**                  p_data: pointer to the ADV data structure tBTA_BLE_ADV_DATA. This
+**                  memory space can not be freed until BTA_BLE_MULTI_ADV_DATA_EVT
+**                  is sent to application.
+**
+** Returns          BTA_SUCCESS if command started sucessfully; otherwise failure.
+**
+*******************************************************************************/
+tBTA_STATUS BTA_BleCfgAdvInstData (UINT8 inst_id, BOOLEAN is_scan_rsp,
+                            tBTA_BLE_AD_MASK data_mask,
+                            tBTA_BLE_ADV_DATA *p_data)
+{
+    tBTA_DM_API_BLE_MULTI_ADV_DATA    *p_msg;
+    UINT16      len =  sizeof(tBTA_DM_API_BLE_MULTI_ADV_DATA) ;
+
+    APPL_TRACE_API0 ("BTA_BleCfgAdvInstData");
+
+    if (inst_id <= BTM_BLE_MULTI_ADV_MAX && inst_id != BTA_BLE_MULTI_ADV_ILLEGAL)
+    {
+    if ((p_msg = (tBTA_DM_API_BLE_MULTI_ADV_DATA *) GKI_getbuf(len)) != NULL)
+    {
+            memset(p_msg, 0, len);
+
+            p_msg->hdr.event     = BTA_DM_API_BLE_MULTI_ADV_DATA_EVT;
+            p_msg->inst_id      = inst_id;
+            p_msg->is_scan_rsp  = is_scan_rsp;
+            p_msg->data_mask     = data_mask;
+            p_msg->p_data        = p_data;
+
+            bta_sys_sendmsg(p_msg);
+
+            return BTA_SUCCESS;
+        }
+    }
+    return BTA_FAILURE;
+}
+
+/*******************************************************************************
+**
+** Function         BTA_BleDisableAdvInstance
+**
+** Description      This function disable a Multi-ADV instance.
+**
+** Parameter        inst_id: instance ID to disable.
+**
+** Returns          BTA_SUCCESS if command started sucessfully; otherwise failure.
+**
+*******************************************************************************/
+tBTA_STATUS BTA_BleDisableAdvInstance (UINT8  inst_id)
+{
+    tBTA_DM_API_BLE_MULTI_ADV_DISABLE    *p_msg;
+
+    APPL_TRACE_API1 ("BTA_BleDisableAdvInstance: %d", inst_id);
+
+    if (inst_id <= BTM_BLE_MULTI_ADV_MAX && inst_id != BTA_BLE_MULTI_ADV_ILLEGAL)
+    {
+        if ((p_msg = (tBTA_DM_API_BLE_MULTI_ADV_DISABLE *)
+            GKI_getbuf(sizeof(tBTA_DM_API_BLE_MULTI_ADV_DISABLE))) != NULL)
+        {
+            memset(p_msg, 0, sizeof(tBTA_DM_API_BLE_MULTI_ADV_DISABLE));
+            p_msg->hdr.event    = BTA_DM_API_BLE_MULTI_ADV_DISABLE_EVT;
+            p_msg->inst_id      = inst_id;
+            bta_sys_sendmsg(p_msg);
+            return BTA_SUCCESS;
+        }
+    }
+    return BTA_FAILURE;
+}
+
 /*******************************************************************************
 **
 ** Function         BTA_DmBleUpdateConnectionParams
@@ -1832,7 +2002,6 @@ void BTA_DmBleConfigLocalPrivacy(BOOLEAN privacy_enable)
 void BTA_DmBleUpdateConnectionParams(BD_ADDR bd_addr, UINT16 min_int, UINT16 max_int,
                                     UINT16 latency, UINT16 timeout)
 {
-#if BLE_INCLUDED == TRUE
     tBTA_DM_API_UPDATE_CONN_PARAM *p_msg;
 
     if ((p_msg = (tBTA_DM_API_UPDATE_CONN_PARAM *) GKI_getbuf(sizeof(tBTA_DM_API_UPDATE_CONN_PARAM))) != NULL)
@@ -1848,8 +2017,8 @@ void BTA_DmBleUpdateConnectionParams(BD_ADDR bd_addr, UINT16 min_int, UINT16 max
 
         bta_sys_sendmsg(p_msg);
     }
-#endif
 }
+#endif
 
 /*******************************************************************************
 **
@@ -1946,8 +2115,6 @@ void BTA_DmCloseACL(BD_ADDR bd_addr, BOOLEAN remove_dev, tBTA_TRANSPORT transpor
 BTA_API extern void BTA_DmBleObserve(BOOLEAN start, UINT8 duration,
                                      tBTA_DM_SEARCH_CBACK *p_results_cb)
 {
-#if BLE_INCLUDED == TRUE
-
     tBTA_DM_API_BLE_OBSERVE   *p_msg;
 
     APPL_TRACE_API1("BTA_DmBleObserve:start = %d ", start);
@@ -1963,6 +2130,5 @@ BTA_API extern void BTA_DmBleObserve(BOOLEAN start, UINT8 duration,
 
         bta_sys_sendmsg(p_msg);
     }
-#endif
 }
 #endif
index 03cb45f..78eb833 100644 (file)
@@ -100,6 +100,11 @@ enum
     BTA_DM_API_BLE_SCAN_PARAM_EVT,
     BTA_DM_API_BLE_OBSERVE_EVT,
     BTA_DM_API_UPDATE_CONN_PARAM_EVT,
+
+#if BLE_PRIVACY_SPT == TRUE
+    BTA_DM_API_LOCAL_PRIVACY_EVT,
+#endif
+
     BTA_DM_API_BLE_ADV_PARAM_EVT,
     BTA_DM_API_BLE_SET_ADV_CONFIG_EVT,
     BTA_DM_API_BLE_SET_SCAN_RSP_EVT,
@@ -109,6 +114,10 @@ enum
     BTA_DM_API_CFG_FILTER_COND_EVT,
     BTA_DM_API_ENABLE_SCAN_FILTER_EVT,
 #endif
+    BTA_DM_API_BLE_MULTI_ADV_ENB_EVT,
+    BTA_DM_API_BLE_MULTI_ADV_PARAM_UPD_EVT,
+    BTA_DM_API_BLE_MULTI_ADV_DATA_EVT,
+    BTA_DM_API_BLE_MULTI_ADV_DISABLE_EVT,
 #endif
 
 #if ( BTM_EIR_SERVER_INCLUDED == TRUE )&&( BTA_EIR_CANNED_UUID_LIST != TRUE )&&(BTA_EIR_SERVER_NUM_CUSTOM_UUID > 0)
@@ -540,11 +549,51 @@ typedef struct
 typedef struct
 {
     BT_HDR                  hdr;
+    BOOLEAN                 enable;
+
+}tBTA_DM_API_BLE_FEATURE;
+
+/* multi adv data structure */
+typedef struct
+{
+    BT_HDR                      hdr;
+    void                        *p_cback;
+    void                        *p_ref;
+    tBTA_BLE_ADV_PARAMS         *p_params;
+}tBTA_DM_API_BLE_MULTI_ADV_ENB;
+
+typedef struct
+{
+    BT_HDR                      hdr;
+    UINT8                        inst_id;
+    tBTA_BLE_ADV_PARAMS         *p_params;
+}tBTA_DM_API_BLE_MULTI_ADV_PARAM;
+
+typedef struct
+{
+    BT_HDR                  hdr;
+    UINT8                   inst_id;
+    BOOLEAN                 is_scan_rsp;
+    tBTA_BLE_AD_MASK        data_mask;
+    tBTA_BLE_ADV_DATA      *p_data;
+}tBTA_DM_API_BLE_MULTI_ADV_DATA;
+
+typedef struct
+{
+    BT_HDR                  hdr;
+    UINT8                   inst_id;
+}tBTA_DM_API_BLE_MULTI_ADV_DISABLE;
+
+
+typedef struct
+{
+    BT_HDR                  hdr;
     UINT16                  data_mask;
     tBTA_BLE_ADV_DATA       *p_adv_cfg;
+    tBTA_SET_ADV_DATA_CMPL_CBACK    *p_adv_data_cback;
 }tBTA_DM_API_SET_ADV_CONFIG;
 
-#endif
+#endif /* BLE_INCLUDED */
 
 typedef struct
 {
@@ -689,6 +738,10 @@ typedef union
     tBTA_DM_API_CFG_FILTER_COND         ble_cfg_filter_cond;
 #endif
     tBTA_DM_API_UPDATE_CONN_PARAM       ble_update_conn_params;
+    tBTA_DM_API_BLE_MULTI_ADV_ENB       ble_multi_adv_enb;
+    tBTA_DM_API_BLE_MULTI_ADV_PARAM     ble_multi_adv_param;
+    tBTA_DM_API_BLE_MULTI_ADV_DATA      ble_multi_adv_data;
+    tBTA_DM_API_BLE_MULTI_ADV_DISABLE   ble_multi_adv_disable;
 #endif
 
     tBTA_DM_API_SET_AFH_CHANNEL_ASSESSMENT set_afh_channel_assessment;
@@ -1057,6 +1110,10 @@ extern void bta_dm_ble_broadcast (tBTA_DM_MSG *p_data);
 extern void bta_dm_enable_scan_filter (tBTA_DM_MSG *p_data);
 extern void bta_dm_cfg_filter_cond (tBTA_DM_MSG *p_data);
 #endif
+extern void btm_dm_ble_multi_adv_disable(tBTA_DM_MSG *p_data);
+extern void bta_dm_ble_multi_adv_data(tBTA_DM_MSG *p_data);
+extern void bta_dm_ble_multi_adv_upd_param(tBTA_DM_MSG *p_data);
+extern void bta_dm_ble_multi_adv_enb(tBTA_DM_MSG *p_data);
 
 #endif
 extern void bta_dm_set_encryption(tBTA_DM_MSG *p_data);
index 8f8c750..c68dac5 100644 (file)
@@ -108,6 +108,10 @@ const tBTA_DM_ACTION bta_dm_action[] =
     bta_dm_cfg_filter_cond,         /* BTA_DM_API_CFG_FILTER_COND_EVT */
     bta_dm_enable_scan_filter,      /* BTA_DM_API_ENABLE_SCAN_FILTER_EVT */
 #endif
+    bta_dm_ble_multi_adv_enb,           /*  BTA_DM_API_BLE_MULTI_ADV_ENB_EVT*/
+    bta_dm_ble_multi_adv_upd_param,     /*  BTA_DM_API_BLE_MULTI_ADV_PARAM_UPD_EVT */
+    bta_dm_ble_multi_adv_data,          /*  BTA_DM_API_BLE_MULTI_ADV_DATA_EVT */
+    btm_dm_ble_multi_adv_disable,       /*  BTA_DM_API_BLE_MULTI_ADV_DISABLE_EVT */
 #endif
 
 #if ( BTM_EIR_SERVER_INCLUDED == TRUE )&&( BTA_EIR_CANNED_UUID_LIST != TRUE )&&(BTA_EIR_SERVER_NUM_CUSTOM_UUID > 0)
index b8fcddc..2ad6a98 100644 (file)
@@ -336,8 +336,9 @@ typedef struct
 #define BTA_DM_BLE_AD_BIT_SERVICE_128SOL  BTM_BLE_AD_BIT_SERVICE_128SOL
 #define BTA_DM_BLE_AD_BIT_PUBLIC_ADDR     BTM_BLE_AD_BIT_PUBLIC_ADDR
 #define BTA_DM_BLE_AD_BIT_RANDOM_ADDR     BTM_BLE_AD_BIT_RANDOM_ADDR
+#define BTA_DM_BLE_AD_BIT_SERVICE_128     BTM_BLE_AD_BIT_SERVICE_128      /*128-bit Service UUIDs*/
 
-typedef  UINT16  tBTA_BLE_AD_MASK;
+typedef  tBTM_BLE_AD_MASK  tBTA_BLE_AD_MASK;
 
 /* slave preferred connection interval range */
 typedef struct
@@ -378,15 +379,68 @@ typedef struct
 
 typedef struct
 {
-    tBTA_BLE_MANU                      manu;                   /* manufactuer data */
-    tBTA_BLE_INT_RANGE         int_range;      /* slave prefered conn interval range */
-    tBTA_BLE_SERVICE           services;       /* services */
-       UINT16                                  appearance;             /* appearance data */
-    UINT8                                      flag;
-    tBTA_BLE_PROPRIETARY    *p_proprietary;
+    tBT_UUID    service_uuid;
+    UINT8       len;
+    UINT8      *p_val;
+}tBTA_BLE_SERVICE_DATA;
+
+typedef tBTM_BLE_128SERVICE tBTA_BLE_128SERVICE;
+typedef tBTM_BLE_32SERVICE  tBTA_BLE_32SERVICE;
 
+typedef struct
+{
+    tBTA_BLE_INT_RANGE      int_range;          /* slave prefered conn interval range */
+    tBTA_BLE_MANU           *p_manu;            /* manufacturer data */
+    tBTA_BLE_SERVICE        *p_services;        /* 16 bits services */
+    tBTA_BLE_128SERVICE     *p_services_128b;   /* 128 bits service */
+    tBTA_BLE_32SERVICE      *p_service_32b;     /* 32 bits Service UUID */
+    tBTA_BLE_SERVICE        *p_sol_services;    /* 16 bits services Solicitation UUIDs */
+    tBTA_BLE_32SERVICE      *p_sol_service_32b; /* List of 32 bit Service Solicitation UUIDs */
+    tBTA_BLE_128SERVICE     *p_sol_service_128b;/* List of 128 bit Service Solicitation UUIDs */
+    tBTA_BLE_PROPRIETARY    *p_proprietary;     /* proprietary data */
+    tBTA_BLE_SERVICE_DATA   *p_service_data;    /* service data */
+    UINT16                  appearance;         /* appearance data */
+    UINT8                   flag;
+    UINT8                   tx_power;
 }tBTA_BLE_ADV_DATA;
 
+typedef void (tBTA_SET_ADV_DATA_CMPL_CBACK) (tBTA_STATUS status);
+
+/* advertising channel map */
+#define BTA_BLE_ADV_CHNL_37 BTM_BLE_ADV_CHNL_37
+#define BTA_BLE_ADV_CHNL_38 BTM_BLE_ADV_CHNL_38
+#define BTA_BLE_ADV_CHNL_39 BTM_BLE_ADV_CHNL_39
+typedef tBTM_BLE_ADV_CHNL_MAP tBTA_BLE_ADV_CHNL_MAP; /* use as a bit mask */
+
+/* advertising filter policy */
+typedef tBTM_BLE_AFP   tBTA_BLE_AFP;
+
+/* adv event type */
+#define BTA_BLE_CONNECT_EVT         BTM_BLE_CONNECT_EVT     /* Connectable undirected advertising */
+#define BTA_BLE_CONNECT_DIR_EVT     BTM_BLE_CONNECT_DIR_EVT /* Connectable directed advertising */
+#define BTA_BLE_DISCOVER_EVT        BTM_BLE_DISCOVER_EVT    /* Scannable undirected advertising */
+#define BTA_BLE_NON_CONNECT_EVT     BTM_BLE_NON_CONNECT_EVT /* Non connectable undirected advertising */
+typedef UINT8 tBTA_BLE_ADV_EVT;
+
+/* adv tx power level */
+#define BTA_BLE_ADV_TX_POWER_MIN        0           /* minimum tx power */
+#define BTA_BLE_ADV_TX_POWER_LOW        1           /* low tx power     */
+#define BTA_BLE_ADV_TX_POWER_MID        2           /* middle tx power  */
+#define BTA_BLE_ADV_TX_POWER_UPPER      3           /* upper tx power   */
+#define BTA_BLE_ADV_TX_POWER_MAX        4           /* maximum tx power */
+typedef UINT8 tBTA_BLE_ADV_TX_POWER;
+
+/* advertising instance parameters */
+typedef struct
+{
+    UINT16                  adv_int_min;            /* minimum adv interval */
+    UINT16                  adv_int_max;            /* maximum adv interval */
+    tBTA_BLE_ADV_EVT        adv_type;               /* adv event type */
+    tBTA_BLE_ADV_CHNL_MAP   channel_map;            /* adv channel map */
+    tBTA_BLE_AFP            adv_filter_policy;      /* advertising filter policy */
+    tBTA_BLE_ADV_TX_POWER   tx_power;               /* adv tx power */
+}tBTA_BLE_ADV_PARAMS;
+
 /* These are the fields returned in each device adv packet.  It
 ** is returned in the results callback if registered.
 */
@@ -843,6 +897,21 @@ typedef union
 /* Security callback */
 typedef void (tBTA_DM_SEC_CBACK)(tBTA_DM_SEC_EVT event, tBTA_DM_SEC *p_data);
 
+#define BTA_BLE_MULTI_ADV_MAX BTM_BLE_MULTI_ADV_MAX
+#define BTA_BLE_MULTI_ADV_ILLEGAL 0
+
+/* multi adv callback event */
+#define BTA_BLE_MULTI_ADV_ENB_EVT           1
+#define BTA_BLE_MULTI_ADV_DISABLE_EVT       2
+#define BTA_BLE_MULTI_ADV_PARAM_EVT         3
+#define BTA_BLE_MULTI_ADV_DATA_EVT          4
+
+typedef UINT8 tBTA_BLE_MULTI_ADV_EVT;
+
+/* multi adv callback */
+typedef void (tBTA_BLE_MULTI_ADV_CBACK)(tBTA_BLE_MULTI_ADV_EVT event,
+                                        UINT8 inst_id, void *p_ref, tBTA_STATUS status);
+
 /* Vendor Specific Command Callback */
 typedef tBTM_VSC_CMPL_CB        tBTA_VENDOR_CMPL_CBACK;
 
@@ -1999,7 +2068,8 @@ BTA_API extern void BTA_DmBleEnableRemotePrivacy(BD_ADDR bd_addr, BOOLEAN privac
 **
 *******************************************************************************/
 BTA_API extern void BTA_DmBleSetAdvConfig (tBTA_BLE_AD_MASK data_mask,
-                                           tBTA_BLE_ADV_DATA *p_adv_cfg);
+                                           tBTA_BLE_ADV_DATA *p_adv_cfg,
+                                           tBTA_SET_ADV_DATA_CMPL_CBACK *p_adv_data_cback);
 
 /*******************************************************************************
 **
@@ -2013,7 +2083,8 @@ BTA_API extern void BTA_DmBleSetAdvConfig (tBTA_BLE_AD_MASK data_mask,
 **
 *******************************************************************************/
 BTA_API extern void BTA_DmBleSetScanRsp (tBTA_BLE_AD_MASK data_mask,
-                                         tBTA_BLE_ADV_DATA *p_adv_cfg);
+                                         tBTA_BLE_ADV_DATA *p_adv_cfg,
+                                         tBTA_SET_ADV_DATA_CMPL_CBACK *p_adv_data_cback);
 
 /*******************************************************************************
 **
@@ -2028,6 +2099,66 @@ BTA_API extern void BTA_DmBleSetScanRsp (tBTA_BLE_AD_MASK data_mask,
 *******************************************************************************/
 BTA_API extern void BTA_DmBleBroadcast (BOOLEAN start);
 
+
+/*******************************************************************************
+**
+** Function         BTA_BleEnableAdvInstance
+**
+** Description      This function enables the Multi ADV instance feature
+**
+** Parameters       p_params Pointer to ADV param user defined structure
+**                  p_cback  Pointer to Multi ADV callback structure
+**                  p_ref - Reference pointer
+**
+** Returns          None
+**
+*******************************************************************************/
+BTA_API extern tBTA_STATUS BTA_BleEnableAdvInstance (tBTA_BLE_ADV_PARAMS *p_params,
+                                tBTA_BLE_MULTI_ADV_CBACK *p_cback,void *p_ref);
+
+/*******************************************************************************
+**
+** Function         BTA_BleUpdateAdvInstParam
+**
+** Description      This function updates the Multi ADV instance params
+**
+** Parameters       inst_id Instance ID
+**                  p_params Pointer to ADV param user defined structure
+**
+** Returns          None
+**
+*******************************************************************************/
+BTA_API extern tBTA_STATUS BTA_BleUpdateAdvInstParam (UINT8 inst_id,
+                                tBTA_BLE_ADV_PARAMS *p_params);
+
+/*******************************************************************************
+**
+** Function         BTA_BleCfgAdvInstData
+**
+** Description      This function is called to configure the ADV instance data
+**
+** Parameters       inst_id - Instance ID
+**                  is_scan_rsp - Boolean value Scan response
+**                  Pointer to User defined ADV data structure
+** Returns          None
+**
+*******************************************************************************/
+BTA_API extern tBTA_STATUS BTA_BleCfgAdvInstData (UINT8 inst_id, BOOLEAN is_scan_rsp,
+                                tBTA_BLE_AD_MASK data_mask, tBTA_BLE_ADV_DATA *p_data);
+
+/*******************************************************************************
+**
+** Function         BTA_BleDisableAdvInstance
+**
+** Description      This function is called to disable the ADV instance
+**
+** Parameters       inst_id - Instance ID to be disabled
+**
+** Returns          None
+**
+*******************************************************************************/
+BTA_API extern tBTA_STATUS BTA_BleDisableAdvInstance(UINT8 inst_id);
+
 /*******************************************************************************
 **
 ** Function         BTA_DmBleUpdateConnectionParams
index 3fec4a0..80af960 100644 (file)
@@ -128,6 +128,11 @@ typedef UINT8 tBTA_GATT_STATUS;
 #define BTA_GATTC_LISTEN_EVT        16  /* listen event */
 #define BTA_GATTC_ENC_CMPL_CB_EVT   17  /* encryption complete callback event */
 #define BTA_GATTC_CFG_MTU_EVT       18  /* configure MTU complete event */
+#define BTA_GATTC_ADV_DATA_EVT      19  /* ADV data event */
+#define BTA_GATTC_MULT_ADV_ENB_EVT  20  /* Enable Multi ADV event */
+#define BTA_GATTC_MULT_ADV_UPD_EVT  21  /* Update parameter event */
+#define BTA_GATTC_MULT_ADV_DATA_EVT 22  /* Multi ADV data event */
+#define BTA_GATTC_MULT_ADV_DIS_EVT  23  /* Disable Multi ADV event */
 
 typedef UINT8 tBTA_GATTC_EVT;
 
diff --git a/btif/include/btif_gatt_multi_adv_util.h b/btif/include/btif_gatt_multi_adv_util.h
new file mode 100644 (file)
index 0000000..2fef449
--- /dev/null
@@ -0,0 +1,87 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2014  Broadcom Corporation
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at:
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ ******************************************************************************/
+
+
+#ifndef BTIF_GATT_MULTI_ADV_UTIL_H
+#define BTIF_GATT_MULTI_ADV_UTIL_H
+
+#include <hardware/bluetooth.h>
+#include "bta_api.h"
+
+#define CLNT_IF_IDX 0
+#define INST_ID_IDX 1
+#define INVALID_ADV_INST -1
+#define STD_ADV_INSTID 0
+#define ADV_FLAGS 0x02
+
+typedef struct
+{
+    int client_if;
+    BOOLEAN set_scan_rsp;
+    BOOLEAN include_name;
+    BOOLEAN include_txpower;
+    int min_interval;
+    int max_interval;
+    int appearance;
+    uint16_t manufacturer_len;
+    uint8_t* p_manufacturer_data;
+    uint16_t service_data_len;
+    uint8_t* p_service_data;
+    uint16_t service_uuid_len;
+    uint8_t* p_service_uuid;
+} btif_adv_data_t;
+
+typedef struct
+{
+    UINT8 inst_id;
+    BOOLEAN is_scan_rsp;
+    UINT8 client_if;
+    UINT16 service_uuid_len;
+    tBTA_BLE_AD_MASK mask;
+    tBTA_BLE_ADV_DATA data;
+    tBTA_BLE_ADV_PARAMS param;
+}btgatt_multi_adv_inst_cb;
+
+typedef struct
+{
+    INT8 clntif_map[BTM_BLE_MULTI_ADV_MAX][INST_ID_IDX+1];
+    // Includes the stored data for standard LE instance
+    btgatt_multi_adv_inst_cb inst_cb[BTM_BLE_MULTI_ADV_MAX+1];
+} btgatt_multi_adv_common_data;
+
+extern btgatt_multi_adv_common_data *btif_obtain_multi_adv_data_cb();
+extern void btif_gattc_init_multi_adv_cb(void);
+extern void btif_gattc_destroy_multi_adv_cb();
+extern int btif_multi_adv_add_instid_map(int client_if, int inst_id,
+        BOOLEAN gen_temp_instid);
+extern int btif_multi_adv_instid_for_clientif(int client_if);
+extern int btif_gattc_obtain_idx_for_datacb(int value, int arrindex);
+extern void btif_gattc_clear_clientif(int client_if);
+extern void btif_gattc_cleanup_inst_cb(int inst_id);
+extern void btif_gattc_cleanup_multi_inst_cb(btgatt_multi_adv_inst_cb *p_inst_cb);
+extern BOOLEAN btif_gattc_copy_datacb(int arrindex, btif_adv_data_t *p_adv_data,
+                                            BOOLEAN bInstData);
+extern void btif_gattc_adv_data_packager(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 service_data_len, char* service_data, uint16_t service_uuid_len,
+                char* service_uuid, btif_adv_data_t *p_multi_adv_inst);
+
+#endif
+
+
index 32f2e3f..2202e99 100644 (file)
@@ -38,7 +38,7 @@
 
 #if (defined(BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
 
-#include "gki.h"
+#include "btif_gatt_multi_adv_util.h"
 #include <hardware/bt_gatt.h>
 #include "bta_api.h"
 #include "bta_gatt_api.h"
@@ -58,8 +58,6 @@
 **  Constants & Macros
 ********************************************************************************/
 
-#define ADV_FLAGS 0x02
-
 #define CHECK_BTGATT_INIT() if (bt_gatt_callbacks == NULL)\
     {\
         ALOGW("%s: BTGATT not initialized", __FUNCTION__);\
@@ -99,6 +97,10 @@ typedef enum {
     BTIF_GATTC_SCAN_FILTER_CONFIG,
     BTIF_GATTC_SCAN_FILTER_CLEAR,
     BTIF_GATTC_SET_SCAN_PARAMS,
+    BTIF_GATTC_ADV_INSTANCE_ENABLE,
+    BTIF_GATTC_ADV_INSTANCE_UPDATE,
+    BTIF_GATTC_ADV_INSTANCE_SET_DATA,
+    BTIF_GATTC_ADV_INSTANCE_DISABLE
 } btif_gattc_event_t;
 
 #define BTIF_GATT_MAX_OBSERVED_DEV 40
@@ -113,14 +115,8 @@ typedef enum {
 
 typedef struct
 {
-    tBTA_BLE_AD_MASK mask;
-    tBTA_BLE_ADV_DATA data;
-} btgatt_adv_data;
-
-typedef struct
-{
     uint8_t     value[BTGATT_MAX_ATTR_LEN];
-    btgatt_adv_data adv_data;
+    uint8_t     inst_id;
     bt_bdaddr_t bd_addr;
     btgatt_srvc_id_t srvc_id;
     btgatt_srvc_id_t incl_srvc_id;
@@ -258,7 +254,6 @@ static void btif_gattc_init_dev_cb(void)
 {
     memset(p_dev_cb, 0, sizeof(btif_gattc_dev_cb_t));
 }
-
 static void btif_gattc_add_remote_bdaddr (BD_ADDR p_bda, uint8_t addr_type)
 {
     BOOLEAN found=FALSE;
@@ -562,6 +557,57 @@ static void btif_gattc_upstreams_evt(uint16_t event, char* p_param)
             break;
         }
 
+        case BTA_GATTC_MULT_ADV_ENB_EVT:
+        {
+            btif_gattc_cb_t *p_btif_cb = (btif_gattc_cb_t*)p_param;
+            btif_multi_adv_add_instid_map(p_btif_cb->client_if,
+                p_btif_cb->inst_id,false);
+            HAL_CBACK(bt_gatt_callbacks, client->multi_adv_enable_cb
+                    , p_btif_cb->client_if
+                    , p_btif_cb->status
+                );
+            break;
+        }
+
+        case BTA_GATTC_MULT_ADV_UPD_EVT:
+        {
+            btif_gattc_cb_t *p_btif_cb = (btif_gattc_cb_t*)p_param;
+            HAL_CBACK(bt_gatt_callbacks, client->multi_adv_update_cb
+                , p_btif_cb->client_if
+                , p_btif_cb->status
+            );
+            break;
+        }
+
+        case BTA_GATTC_MULT_ADV_DATA_EVT:
+         {
+            btif_gattc_cb_t *p_btif_cb = (btif_gattc_cb_t*)p_param;
+            btif_gattc_cleanup_inst_cb(p_btif_cb->inst_id);
+            HAL_CBACK(bt_gatt_callbacks, client->multi_adv_data_cb
+                , p_btif_cb->client_if
+                , p_btif_cb->status
+            );
+            break;
+        }
+
+        case BTA_GATTC_MULT_ADV_DIS_EVT:
+        {
+            btif_gattc_cb_t *p_btif_cb = (btif_gattc_cb_t*)p_param;
+            btif_gattc_clear_clientif(p_btif_cb->client_if);
+            HAL_CBACK(bt_gatt_callbacks, client->multi_adv_disable_cb
+                , p_btif_cb->client_if
+                , p_btif_cb->status
+            );
+            break;
+        }
+
+        case BTA_GATTC_ADV_DATA_EVT:
+        {
+            btif_gattc_cleanup_inst_cb(STD_ADV_INSTID);
+            /* No HAL callback available */
+            break;
+        }
+
         default:
             ALOGE("%s: Unhandled event (%d)!", __FUNCTION__, event);
             break;
@@ -577,6 +623,66 @@ static void bta_gattc_cback(tBTA_GATTC_EVT event, tBTA_GATTC *p_data)
     ASSERTC(status == BT_STATUS_SUCCESS, "Context transfer failed!", status);
 }
 
+static void bta_gattc_multi_adv_cback(tBTA_BLE_MULTI_ADV_EVT event, UINT8 inst_id,
+                                    void *p_ref, tBTA_STATUS call_status)
+{
+    btif_gattc_cb_t btif_cb;
+    tBTA_GATTC_EVT upevt;
+    uint8_t client_if = 0;
+
+    if(NULL == p_ref)
+    {
+        BTIF_TRACE_ERROR1("%s Invalid p_ref received",__FUNCTION__);
+        return;
+    }
+
+    client_if = *(UINT8 *)p_ref;
+    BTIF_TRACE_DEBUG4("%s -Inst ID %d, Status:%x, client_if:%d",__FUNCTION__,inst_id, call_status,
+                       client_if);
+
+    btif_cb.status = call_status;
+    btif_cb.client_if = client_if;
+    btif_cb.inst_id = inst_id;
+
+    switch(event)
+    {
+        case BTA_BLE_MULTI_ADV_ENB_EVT:
+        {
+            upevt = BTA_GATTC_MULT_ADV_ENB_EVT;
+            break;
+        }
+
+        case BTA_BLE_MULTI_ADV_DISABLE_EVT:
+            upevt = BTA_GATTC_MULT_ADV_DIS_EVT;
+            break;
+
+        case BTA_BLE_MULTI_ADV_PARAM_EVT:
+            upevt = BTA_GATTC_MULT_ADV_UPD_EVT;
+            break;
+
+        case BTA_BLE_MULTI_ADV_DATA_EVT:
+            upevt = BTA_GATTC_MULT_ADV_DATA_EVT;
+            break;
+
+        default:
+            return;
+    }
+
+    bt_status_t status = btif_transfer_context(btif_gattc_upstreams_evt, (uint16_t) upevt,
+                        (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
+    ASSERTC(status == BT_STATUS_SUCCESS, "Context transfer failed!", status);
+}
+
+static void bta_gattc_set_adv_data_cback(tBTA_STATUS call_status)
+{
+    UNUSED(call_status);
+    btif_gattc_cb_t btif_cb;
+    btif_cb.status = call_status;
+    btif_cb.action = 0;
+    btif_transfer_context(btif_gattc_upstreams_evt, BTA_GATTC_ADV_DATA_EVT,
+                          (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
+}
+
 static void bta_scan_results_cb (tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARCH *p_data)
 {
     btif_gattc_cb_t btif_cb;
@@ -654,8 +760,24 @@ static void btgattc_handle_event(uint16_t event, char* p_param)
     tBTA_GATTC_INCL_SVC_ID     out_incl_svc_id;
     tBTA_GATT_UNFMT            descr_val;
 
-    btif_gattc_cb_t* p_cb = (btif_gattc_cb_t*)p_param;
-    if (!p_cb) return;
+    btif_gattc_cb_t* p_cb = NULL;
+    btif_adv_data_t *p_adv_data = NULL;
+    btgatt_multi_adv_inst_cb *p_inst_cb = NULL;
+
+    if(BTIF_GATTC_ADV_INSTANCE_ENABLE == event || BTIF_GATTC_ADV_INSTANCE_DISABLE == event ||
+        BTIF_GATTC_ADV_INSTANCE_UPDATE == event)
+    {
+        p_inst_cb = (btgatt_multi_adv_inst_cb*)p_param;
+    }
+    else
+    {
+        if(BTIF_GATTC_ADV_INSTANCE_SET_DATA == event || BTIF_GATTC_SET_ADV_DATA == event)
+            p_adv_data = (btif_adv_data_t*)p_param;
+        else
+            p_cb = (btif_gattc_cb_t*)p_param;
+    }
+
+    if (!p_cb && !p_adv_data && !p_inst_cb) return;
 
     ALOGD("%s: Event %d", __FUNCTION__, event);
 
@@ -663,10 +785,12 @@ static void btgattc_handle_event(uint16_t event, char* p_param)
     {
         case BTIF_GATTC_REGISTER_APP:
             btif_to_bta_uuid(&uuid, &p_cb->uuid);
+            btif_gattc_init_multi_adv_cb();
             BTA_GATTC_AppRegister(&uuid, bta_gattc_cback);
             break;
 
         case BTIF_GATTC_UNREGISTER_APP:
+            btif_gattc_destroy_multi_adv_cb();
             BTA_GATTC_AppDeregister(p_cb->client_if);
             break;
 
@@ -1026,39 +1150,106 @@ static void btgattc_handle_event(uint16_t event, char* p_param)
 
         case BTIF_GATTC_SET_ADV_DATA:
         {
-            if (p_cb->start == 0)
-                BTA_DmBleSetAdvConfig(p_cb->adv_data.mask, &p_cb->adv_data.data);
+            int cbindex = CLNT_IF_IDX;
+            if(cbindex >= 0 && NULL != p_adv_data)
+            {
+                btgatt_multi_adv_common_data *p_multi_adv_data_cb = btif_obtain_multi_adv_data_cb();
+                if(!btif_gattc_copy_datacb(cbindex, p_adv_data, false))
+                    return;
+
+                if (!p_adv_data->set_scan_rsp)
+                {
+                    BTA_DmBleSetAdvConfig(p_multi_adv_data_cb->inst_cb[cbindex].mask,
+                        &p_multi_adv_data_cb->inst_cb[cbindex].data, bta_gattc_set_adv_data_cback);
+                }
+                else
+                {
+                    BTA_DmBleSetScanRsp(p_multi_adv_data_cb->inst_cb[cbindex].mask,
+                        &p_multi_adv_data_cb->inst_cb[cbindex].data, bta_gattc_set_adv_data_cback);
+                }
+                break;
+            }
+        }
+
+        case BTIF_GATTC_ADV_INSTANCE_ENABLE:
+        {
+            if(NULL == p_inst_cb)
+               return;
+
+            int arrindex = btif_multi_adv_add_instid_map(p_inst_cb->client_if,INVALID_ADV_INST,
+                                                        true);
+            int cbindex = btif_gattc_obtain_idx_for_datacb(p_inst_cb->client_if, CLNT_IF_IDX);
+            if(cbindex >= 0 && arrindex >= 0)
+            {
+                btgatt_multi_adv_common_data *p_multi_adv_data_cb = btif_obtain_multi_adv_data_cb();
+                memcpy(&p_multi_adv_data_cb->inst_cb[cbindex].param,
+                       &p_inst_cb->param, sizeof(tBTA_BLE_ADV_PARAMS));
+
+                BTA_BleEnableAdvInstance(&(p_multi_adv_data_cb->inst_cb[cbindex].param),
+                    bta_gattc_multi_adv_cback,
+                    &(p_multi_adv_data_cb->clntif_map[arrindex][CLNT_IF_IDX]));
+            }
             else
-                BTA_DmBleSetScanRsp(p_cb->adv_data.mask, &p_cb->adv_data.data);
+                BTIF_TRACE_ERROR1("%s invalid index in BTIF_GATTC_ENABLE_ADV",__FUNCTION__);
+            break;
+        }
 
-            // Cleanup ...
+        case BTIF_GATTC_ADV_INSTANCE_UPDATE:
+        {
+            if(NULL == p_inst_cb)
+               return;
 
-            // ... manufacturer data
-            if (p_cb->adv_data.data.manu.p_val != NULL)
-                GKI_freebuf(p_cb->adv_data.data.manu.p_val);
+            int inst_id = btif_multi_adv_instid_for_clientif(p_inst_cb->client_if);
+            int cbindex = btif_gattc_obtain_idx_for_datacb(p_inst_cb->client_if, CLNT_IF_IDX);
+            if(inst_id >= 0 && cbindex >= 0 && NULL != p_inst_cb)
+            {
+                btgatt_multi_adv_common_data *p_multi_adv_data_cb = btif_obtain_multi_adv_data_cb();
+                memcpy(&p_multi_adv_data_cb->inst_cb[cbindex].param, &p_inst_cb->param,
+                        sizeof(tBTA_BLE_ADV_PARAMS));
+                BTA_BleUpdateAdvInstParam((UINT8)inst_id,
+                    &(p_multi_adv_data_cb->inst_cb[cbindex].param));
+            }
+            else
+                BTIF_TRACE_ERROR1("%s invalid index in BTIF_GATTC_UPDATE_ADV", __FUNCTION__);
+            break;
+        }
+
+        case BTIF_GATTC_ADV_INSTANCE_SET_DATA:
+        {
+            if(NULL == p_adv_data)
+               return;
 
-            // ... service data
-            if (p_cb->adv_data.data.p_proprietary != NULL)
+            int cbindex = btif_gattc_obtain_idx_for_datacb(p_adv_data->client_if, CLNT_IF_IDX);
+            int inst_id = btif_multi_adv_instid_for_clientif(p_adv_data->client_if);
+            if(inst_id < 0 || cbindex < 0)
             {
-                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);
+               BTIF_TRACE_ERROR1("%s invalid index in BTIF_GATTC_SETADV_INST_DATA", __FUNCTION__);
+               return;
             }
 
-            // ... service list
-            if (p_cb->adv_data.data.services.p_uuid != NULL)
-                GKI_freebuf(p_cb->adv_data.data.services.p_uuid);
+            if(!btif_gattc_copy_datacb(cbindex, p_adv_data, true))
+                return;
+
+            btgatt_multi_adv_common_data *p_multi_adv_data_cb = btif_obtain_multi_adv_data_cb();
+            BTA_BleCfgAdvInstData((UINT8)inst_id, p_multi_adv_data_cb->inst_cb[cbindex].is_scan_rsp,
+                      p_multi_adv_data_cb->inst_cb[cbindex].mask,
+                      &p_multi_adv_data_cb->inst_cb[cbindex].data);
+            break;
+        }
+
+        case BTIF_GATTC_ADV_INSTANCE_DISABLE:
+        {
+            if(NULL == p_inst_cb)
+               return;
 
+            int inst_id = btif_multi_adv_instid_for_clientif(p_inst_cb->client_if);
+            if(inst_id >=0)
+                BTA_BleDisableAdvInstance((UINT8)inst_id);
+            else
+                BTIF_TRACE_ERROR1("%s invalid instance ID in BTIF_GATTC_DISABLE_ADV",__FUNCTION__);
             break;
         }
+
         case BTIF_GATTC_CONFIGURE_MTU:
             BTA_GATTC_ConfigureMTU(p_cb->conn_id, p_cb->len);
             break;
@@ -1144,161 +1335,28 @@ static bt_status_t btif_gattc_set_adv_data(int client_if, bool set_scan_rsp, boo
                 uint16_t service_uuid_len, char* service_uuid)
 {
     CHECK_BTGATT_INIT();
-    btif_gattc_cb_t btif_cb;
-    memset(&btif_cb, 0, sizeof(btif_gattc_cb_t));
-    memset(&btif_cb.adv_data, 0, sizeof(btgatt_adv_data));
-
-    btif_cb.client_if = (uint8_t) client_if;
-    btif_cb.start = set_scan_rsp ? 1 : 0;
-
-    if (!set_scan_rsp)
-    {
-        btif_cb.adv_data.mask = BTM_BLE_AD_BIT_FLAGS;
-        btif_cb.adv_data.data.flag = ADV_FLAGS;
-    }
-
-    if (include_name)
-        btif_cb.adv_data.mask |= BTM_BLE_AD_BIT_DEV_NAME;
-
-    if (include_txpower)
-        btif_cb.adv_data.mask |= BTM_BLE_AD_BIT_TX_PWR;
-
-    if (min_interval > 0 && max_interval > 0 && max_interval > min_interval)
-    {
-        btif_cb.adv_data.mask |= BTM_BLE_AD_BIT_INT_RANGE;
-        btif_cb.adv_data.data.int_range.low = min_interval;
-        btif_cb.adv_data.data.int_range.hi = max_interval;
-    }
-
-    if (appearance != 0)
-    {
-        btif_cb.adv_data.mask |= BTM_BLE_AD_BIT_APPEARANCE;
-        btif_cb.adv_data.data.appearance = appearance;
-    }
-
-    if (manufacturer_len > 0 && manufacturer_data != NULL)
-    {
-        btif_cb.adv_data.data.manu.p_val = GKI_getbuf(manufacturer_len);
-        if (btif_cb.adv_data.data.manu.p_val != NULL)
-        {
-            btif_cb.adv_data.mask |= BTM_BLE_AD_BIT_MANU;
-            btif_cb.adv_data.data.manu.len = manufacturer_len;
-            memcpy(btif_cb.adv_data.data.manu.p_val, manufacturer_data, manufacturer_len);
-        }
-    }
-
-    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);
+    bt_status_t status =0;
 
-                        } else {
-                            GKI_freebuf(p_elem_service_128);
-                            p_elem_service_128 = NULL;
-                        }
-                    }
-                }
+    btif_adv_data_t adv_data;
 
-                service_uuid += LEN_UUID_128;
-                service_uuid_len -= LEN_UUID_128;
-            }
-        }
-    }
+    btif_gattc_adv_data_packager(client_if, set_scan_rsp, include_name,
+        include_txpower, min_interval, max_interval, appearance, manufacturer_len,
+        manufacturer_data, service_data_len, service_data, service_uuid_len, service_uuid,
+        &adv_data);
 
-    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;
+    status = btif_transfer_context(btgattc_handle_event, BTIF_GATTC_SET_ADV_DATA,
+                       (char*) &adv_data, sizeof(btif_adv_data_t), NULL);
 
-            if (p_elem_service_128 != NULL)
-                ++p_prop->num_elem;
+    if (NULL != adv_data.p_service_data)
+        GKI_freebuf(adv_data.p_service_data);
 
-            if (p_elem_service_data != NULL)
-                ++p_prop->num_elem;
+    if (NULL != adv_data.p_service_uuid)
+        GKI_freebuf(adv_data.p_service_uuid);
 
-            p_prop->p_elem = GKI_getbuf(sizeof(tBTA_BLE_PROP_ELEM) * p_prop->num_elem);
-            p_elem = p_prop->p_elem;
+    if (NULL != adv_data.p_manufacturer_data)
+        GKI_freebuf(adv_data.p_manufacturer_data);
 
-            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);
-            }
-        }
-    }
-
-#if (defined(BLE_PERIPHERAL_ADV_NAME) && (BLE_PERIPHERAL_ADV_NAME == TRUE))
-    btif_cb.adv_data.mask |= BTM_BLE_AD_BIT_DEV_NAME;
-#endif
-
-    return btif_transfer_context(btgattc_handle_event, BTIF_GATTC_SET_ADV_DATA,
-                                 (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
+    return status;
 }
 
 static bt_status_t btif_gattc_refresh( int client_if, const bt_bdaddr_t *bd_addr )
@@ -1568,6 +1626,84 @@ static int btif_gattc_get_device_type( const bt_bdaddr_t *bd_addr )
     return 0;
 }
 
+static bt_status_t btif_gattc_multi_adv_enable(int client_if, int min_interval, int max_interval,
+                                            int adv_type, int chnl_map, int tx_power)
+{
+    CHECK_BTGATT_INIT();
+    btgatt_multi_adv_inst_cb adv_cb;
+    adv_cb.client_if = (uint8_t) client_if;
+
+    adv_cb.param.adv_int_min = min_interval;
+    adv_cb.param.adv_int_max = max_interval;
+    adv_cb.param.adv_type = adv_type;
+    adv_cb.param.channel_map = chnl_map;
+    adv_cb.param.adv_filter_policy = 0;
+    adv_cb.param.tx_power = tx_power;
+    return btif_transfer_context(btgattc_handle_event, BTIF_GATTC_ADV_INSTANCE_ENABLE,
+                             (char*) &adv_cb, sizeof(btgatt_multi_adv_inst_cb), NULL);
+}
+
+static bt_status_t btif_gattc_multi_adv_update(int client_if, int min_interval, int max_interval,
+                                            int adv_type, int chnl_map,int tx_power)
+{
+    CHECK_BTGATT_INIT();
+    btgatt_multi_adv_inst_cb adv_cb;
+    adv_cb.client_if = (uint8_t) client_if;
+
+    adv_cb.param.adv_int_min = min_interval;
+    adv_cb.param.adv_int_max = max_interval;
+    adv_cb.param.adv_type = adv_type;
+    adv_cb.param.channel_map = chnl_map;
+    adv_cb.param.adv_filter_policy = 0;
+    adv_cb.param.tx_power = tx_power;
+    return btif_transfer_context(btgattc_handle_event, BTIF_GATTC_ADV_INSTANCE_UPDATE,
+                         (char*) &adv_cb, sizeof(btgatt_multi_adv_inst_cb), NULL);
+}
+
+static bt_status_t btif_gattc_multi_adv_setdata(int client_if, bool set_scan_rsp,
+                                                   bool include_name, bool incl_txpower,
+                                                   int appearance, 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();
+
+    int min_interval = 0, max_interval = 0;
+    bt_status_t status =0;
+
+    btif_adv_data_t multi_adv_data_inst;
+
+    btif_gattc_adv_data_packager(client_if, set_scan_rsp, include_name, incl_txpower,
+        min_interval, max_interval, appearance, manufacturer_len, manufacturer_data,
+        service_data_len, service_data, service_uuid_len, service_uuid, &multi_adv_data_inst);
+
+    status = btif_transfer_context(btgattc_handle_event, BTIF_GATTC_ADV_INSTANCE_SET_DATA,
+                       (char*) &multi_adv_data_inst, sizeof(btif_adv_data_t), NULL);
+
+    if (NULL != multi_adv_data_inst.p_service_data)
+        GKI_freebuf(multi_adv_data_inst.p_service_data);
+
+    if (NULL != multi_adv_data_inst.p_service_uuid)
+        GKI_freebuf(multi_adv_data_inst.p_service_uuid);
+
+    if (NULL != multi_adv_data_inst.p_manufacturer_data)
+        GKI_freebuf(multi_adv_data_inst.p_manufacturer_data);
+
+    return status;
+}
+
+static bt_status_t btif_gattc_multi_adv_disable(int client_if)
+{
+    CHECK_BTGATT_INIT();
+    btgatt_multi_adv_inst_cb adv_cb;
+    adv_cb.client_if = (uint8_t) client_if;
+
+    return btif_transfer_context(btgattc_handle_event, BTIF_GATTC_ADV_INSTANCE_DISABLE,
+                           (char*) &adv_cb, sizeof(btgatt_multi_adv_inst_cb), NULL);
+}
+
 extern bt_status_t btif_gattc_test_command_impl(int command, btgatt_test_params_t* params);
 
 static bt_status_t btif_gattc_test_command(int command, btgatt_test_params_t* params)
@@ -1603,6 +1739,10 @@ const btgatt_client_interface_t btgattClientInterface = {
     btif_gattc_set_adv_data,
     btif_gattc_configure_mtu,
     btif_gattc_set_scan_parameters,
+    btif_gattc_multi_adv_enable,
+    btif_gattc_multi_adv_update,
+    btif_gattc_multi_adv_setdata,
+    btif_gattc_multi_adv_disable,
     btif_gattc_test_command
 };
 
diff --git a/btif/src/btif_gatt_multi_adv_util.c b/btif/src/btif_gatt_multi_adv_util.c
new file mode 100644 (file)
index 0000000..0f20645
--- /dev/null
@@ -0,0 +1,540 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2014  Broadcom Corporation
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at:
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ ******************************************************************************/
+
+
+/*******************************************************************************
+ *
+ *  Filename:      btif_gatt_multi_adv_util.c
+ *
+ *  Description:   Multi ADV helper implementation
+ *
+ *******************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#define LOG_TAG "BtGatt.btif"
+#if (BLE_INCLUDED == TRUE)
+
+#include "btif_gatt_multi_adv_util.h"
+#include "btif_common.h"
+#include <hardware/bt_gatt.h>
+#include "bta_gatt_api.h"
+#include "btif_gatt_util.h"
+
+/*******************************************************************************
+**  Static variables
+********************************************************************************/
+static int multi_adv_enable_count = 0;
+static btgatt_multi_adv_common_data *p_multi_adv_com_data_cb = NULL;
+
+btgatt_multi_adv_common_data *btif_obtain_multi_adv_data_cb()
+{
+    if(p_multi_adv_com_data_cb == NULL)
+       p_multi_adv_com_data_cb = GKI_getbuf(sizeof(btgatt_multi_adv_common_data));
+    return p_multi_adv_com_data_cb;
+}
+
+void btif_gattc_init_multi_adv_cb(void)
+{
+    int i;
+    btgatt_multi_adv_common_data *p_multi_adv_data_cb = btif_obtain_multi_adv_data_cb();
+
+    if(NULL == p_multi_adv_data_cb)
+        return;
+
+    if(multi_adv_enable_count == 0)
+    {
+        memset(p_multi_adv_data_cb,0,sizeof(btgatt_multi_adv_common_data));
+
+        for (i=0; i < BTM_BLE_MULTI_ADV_MAX; i++)
+        {
+           p_multi_adv_data_cb->clntif_map[i][CLNT_IF_IDX] = INVALID_ADV_INST;
+           p_multi_adv_data_cb->clntif_map[i][INST_ID_IDX] = INVALID_ADV_INST;
+        }
+    }
+    multi_adv_enable_count++;
+}
+
+void btif_gattc_destroy_multi_adv_cb()
+{
+    if(multi_adv_enable_count > 0)
+        multi_adv_enable_count --;
+    if(multi_adv_enable_count == 0)
+    {
+        GKI_freebuf(p_multi_adv_com_data_cb);
+        p_multi_adv_com_data_cb = NULL;
+    }
+}
+
+int btif_multi_adv_add_instid_map(int client_if, int inst_id, BOOLEAN gen_temp_instid)
+{
+    int i=0;
+
+    btgatt_multi_adv_common_data *p_multi_adv_data_cb = btif_obtain_multi_adv_data_cb();
+
+    if(NULL == p_multi_adv_data_cb)
+        return INVALID_ADV_INST;
+
+    for(i=0; i < BTM_BLE_MULTI_ADV_MAX; i++)
+    {
+       if(client_if == p_multi_adv_data_cb->clntif_map[i][CLNT_IF_IDX])
+       {
+          if(!gen_temp_instid)
+          {
+             // Write the final inst_id value obtained from stack layer
+             p_multi_adv_data_cb->clntif_map[i][INST_ID_IDX] = inst_id;
+             BTIF_TRACE_DEBUG3("%s -Index: %d, Found client_if: %d", __FUNCTION__,
+                i, p_multi_adv_data_cb->clntif_map[i][CLNT_IF_IDX]);
+             break;
+          }
+          else
+          {
+              //Store the passed in inst_id value
+             if(inst_id != INVALID_ADV_INST)
+                 p_multi_adv_data_cb->clntif_map[i][INST_ID_IDX] = inst_id;
+             else
+                 p_multi_adv_data_cb->clntif_map[i][INST_ID_IDX] = (i + 1);
+             BTIF_TRACE_DEBUG3("%s - Index:%d,Found client_if: %d", __FUNCTION__,
+                i, p_multi_adv_data_cb->clntif_map[i][CLNT_IF_IDX]);
+             break;
+          }
+       }
+    }
+
+    if(i < BTM_BLE_MULTI_ADV_MAX)
+        return i;
+
+    // If client ID if is not found, then write both values
+    for(i=0; i < BTM_BLE_MULTI_ADV_MAX; i++)
+    {
+        if(INVALID_ADV_INST == p_multi_adv_data_cb->clntif_map[i][CLNT_IF_IDX])
+        {
+             p_multi_adv_data_cb->clntif_map[i][CLNT_IF_IDX] = client_if;
+             if(inst_id != INVALID_ADV_INST)
+                p_multi_adv_data_cb->clntif_map[i][INST_ID_IDX] = inst_id;
+             else
+                p_multi_adv_data_cb->clntif_map[i][INST_ID_IDX] = (i + 1);
+             BTIF_TRACE_DEBUG4("%s -Not found - Index:%d, client_if: %d, Inst ID: %d",
+                            __FUNCTION__,i,
+                            p_multi_adv_data_cb->clntif_map[i][CLNT_IF_IDX],
+                            p_multi_adv_data_cb->clntif_map[i][INST_ID_IDX]);
+             break;
+        }
+    }
+
+    if(i < BTM_BLE_MULTI_ADV_MAX)
+        return i;
+    return INVALID_ADV_INST;
+}
+
+int btif_multi_adv_instid_for_clientif(int client_if)
+{
+    int i=0, ret = INVALID_ADV_INST;
+
+    btgatt_multi_adv_common_data *p_multi_adv_data_cb = btif_obtain_multi_adv_data_cb();
+
+    if(NULL == p_multi_adv_data_cb)
+        return INVALID_ADV_INST;
+
+    // Retrieve the existing inst_id for the client_if value
+    for(i=0; i < BTM_BLE_MULTI_ADV_MAX; i++)
+    {
+       if(client_if == p_multi_adv_data_cb->clntif_map[i][CLNT_IF_IDX])
+          ret = p_multi_adv_data_cb->clntif_map[i][INST_ID_IDX];
+    }
+
+    if(ret != INVALID_ADV_INST)
+        return ret;
+
+    return INVALID_ADV_INST;
+}
+
+
+int btif_gattc_obtain_idx_for_datacb(int value, int arrindex)
+{
+    int i=0;
+
+    btgatt_multi_adv_common_data *p_multi_adv_data_cb = btif_obtain_multi_adv_data_cb();
+
+    if(NULL == p_multi_adv_data_cb)
+        return INVALID_ADV_INST;
+
+    // Retrieve the array index for the inst_id value
+    for(i=0; i < BTM_BLE_MULTI_ADV_MAX; i++)
+    {
+       if(value == p_multi_adv_data_cb->clntif_map[i][arrindex])
+           break;
+    }
+
+    if(i < BTM_BLE_MULTI_ADV_MAX)
+    {
+        BTIF_TRACE_DEBUG2("%s, %d",__FUNCTION__,i+1);
+        return (i + 1);
+    }
+
+    BTIF_TRACE_DEBUG1("%s Invalid instance",__FUNCTION__);
+    return INVALID_ADV_INST;
+}
+
+
+void btif_gattc_adv_data_packager(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 service_data_len, char* service_data, uint16_t service_uuid_len,
+                char* service_uuid, btif_adv_data_t *p_multi_adv_inst)
+{
+    memset(p_multi_adv_inst, 0 , sizeof(btif_adv_data_t));
+
+    p_multi_adv_inst->client_if = (uint8_t) client_if;
+    p_multi_adv_inst->set_scan_rsp = set_scan_rsp;
+    p_multi_adv_inst->include_name = include_name;
+    p_multi_adv_inst->include_txpower = include_txpower;
+    p_multi_adv_inst->min_interval = min_interval;
+    p_multi_adv_inst->max_interval = max_interval;
+    p_multi_adv_inst->appearance = appearance;
+    p_multi_adv_inst->manufacturer_len = manufacturer_len;
+
+    if(manufacturer_len > 0)
+    {
+        p_multi_adv_inst->p_manufacturer_data = GKI_getbuf(manufacturer_len);
+        memcpy(p_multi_adv_inst->p_manufacturer_data, manufacturer_data, manufacturer_len);
+    }
+
+    p_multi_adv_inst->service_data_len = service_data_len;
+    if(service_data_len > 0)
+    {
+        p_multi_adv_inst->p_service_data = GKI_getbuf(service_data_len);
+        memcpy(p_multi_adv_inst->p_service_data, service_data, service_data_len);
+    }
+
+    p_multi_adv_inst->service_uuid_len = service_uuid_len;
+    if(service_uuid_len > 0)
+    {
+        p_multi_adv_inst->p_service_uuid = GKI_getbuf(service_uuid_len);
+        memcpy(p_multi_adv_inst->p_service_uuid, service_uuid, service_uuid_len);
+    }
+}
+
+BOOLEAN btif_gattc_copy_datacb(int cbindex, btif_adv_data_t *p_adv_data, BOOLEAN bInstData)
+{
+    int i=0;
+    btgatt_multi_adv_common_data *p_multi_adv_data_cb = btif_obtain_multi_adv_data_cb();
+    if(NULL == p_multi_adv_data_cb || cbindex < 0)
+       return false;
+
+    BTIF_TRACE_DEBUG1("%s", __FUNCTION__);
+    memset(&p_multi_adv_data_cb->inst_cb[cbindex],0, sizeof(btgatt_multi_adv_inst_cb));
+    memset(&p_multi_adv_data_cb->inst_cb[cbindex].data, 0, sizeof(tBTA_BLE_ADV_DATA));
+
+    if (!p_adv_data->set_scan_rsp)
+    {
+         p_multi_adv_data_cb->inst_cb[cbindex].is_scan_rsp = p_adv_data->set_scan_rsp ? 1 : 0;
+         p_multi_adv_data_cb->inst_cb[cbindex].mask = BTM_BLE_AD_BIT_FLAGS;
+         p_multi_adv_data_cb->inst_cb[cbindex].data.flag = ADV_FLAGS;
+    }
+
+    if (p_adv_data->include_name)
+        p_multi_adv_data_cb->inst_cb[cbindex].mask |= BTM_BLE_AD_BIT_DEV_NAME;
+
+    if (p_adv_data->include_txpower)
+        p_multi_adv_data_cb->inst_cb[cbindex].mask |= BTM_BLE_AD_BIT_TX_PWR;
+
+    if (false == bInstData && p_adv_data->min_interval > 0 && p_adv_data->max_interval > 0 &&
+        p_adv_data->max_interval > p_adv_data->min_interval)
+    {
+        p_multi_adv_data_cb->inst_cb[cbindex].mask |= BTM_BLE_AD_BIT_INT_RANGE;
+        p_multi_adv_data_cb->inst_cb[cbindex].data.int_range.low =
+                                        p_adv_data->min_interval;
+        p_multi_adv_data_cb->inst_cb[cbindex].data.int_range.hi =
+                                        p_adv_data->max_interval;
+    }
+    else
+    if(true == bInstData)
+    {
+        if (p_multi_adv_data_cb->inst_cb[cbindex].param.adv_int_min > 0 &&
+            p_multi_adv_data_cb->inst_cb[cbindex].param.adv_int_max > 0 &&
+            p_multi_adv_data_cb->inst_cb[cbindex].param.adv_int_max >
+            p_multi_adv_data_cb->inst_cb[cbindex].param.adv_int_min)
+        {
+              p_multi_adv_data_cb->inst_cb[cbindex].data.int_range.low =
+              p_multi_adv_data_cb->inst_cb[cbindex].param.adv_int_min;
+              p_multi_adv_data_cb->inst_cb[cbindex].data.int_range.hi =
+              p_multi_adv_data_cb->inst_cb[cbindex].param.adv_int_max;
+        }
+
+        if (p_adv_data->include_txpower)
+        {
+            p_multi_adv_data_cb->inst_cb[cbindex].data.tx_power =
+                p_multi_adv_data_cb->inst_cb[cbindex].param.tx_power;
+        }
+    }
+
+    if (p_adv_data->appearance != 0)
+    {
+        p_multi_adv_data_cb->inst_cb[cbindex].mask |= BTM_BLE_AD_BIT_APPEARANCE;
+        p_multi_adv_data_cb->inst_cb[cbindex].data.appearance = p_adv_data->appearance;
+    }
+
+    if (p_adv_data->manufacturer_len > 0 && p_adv_data->p_manufacturer_data != NULL)
+    {
+         p_multi_adv_data_cb->inst_cb[cbindex].data.p_manu =
+                            GKI_getbuf(sizeof(tBTA_BLE_MANU));
+         if(p_multi_adv_data_cb->inst_cb[cbindex].data.p_manu != NULL)
+         {
+            p_multi_adv_data_cb->inst_cb[cbindex].data.p_manu->p_val =
+                            GKI_getbuf(p_adv_data->manufacturer_len);
+            if (p_multi_adv_data_cb->inst_cb[cbindex].data.p_manu->p_val != NULL)
+            {
+                 p_multi_adv_data_cb->inst_cb[cbindex].mask |= BTM_BLE_AD_BIT_MANU;
+                 p_multi_adv_data_cb->inst_cb[cbindex].data.p_manu->len =
+                                p_adv_data->manufacturer_len;
+                 memcpy(p_multi_adv_data_cb->inst_cb[cbindex].data.p_manu->p_val,
+                    p_adv_data->p_manufacturer_data, p_adv_data->manufacturer_len);
+            }
+         }
+     }
+
+     tBTA_BLE_PROP_ELEM *p_elem_service_data = NULL;
+     tBTA_BLE_PROP_ELEM *p_elem_service_128 = NULL;
+
+     if (p_adv_data->service_data_len > 0 && p_adv_data->p_service_data != NULL)
+     {
+         BTIF_TRACE_DEBUG1("%s - In service_data", __FUNCTION__);
+         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(p_adv_data->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 = p_adv_data->service_data_len;
+                 memcpy(p_elem_service_data->p_val, p_adv_data->p_service_data,
+                             p_adv_data->service_data_len);
+             } else {
+                     GKI_freebuf(p_elem_service_data);
+                     p_elem_service_data = NULL;
+               }
+             }
+         }
+
+         if (p_adv_data->service_uuid_len > 0 && p_adv_data->p_service_uuid != NULL)
+         {
+             p_multi_adv_data_cb->inst_cb[cbindex].data.p_services =
+                                            GKI_getbuf(sizeof(tBTA_BLE_SERVICE));
+             p_multi_adv_data_cb->inst_cb[cbindex].data.p_services->list_cmpl = FALSE;
+             p_multi_adv_data_cb->inst_cb[cbindex].data.p_services->num_service = 0;
+             p_multi_adv_data_cb->inst_cb[cbindex].data.p_services->p_uuid =
+                 GKI_getbuf(p_adv_data->service_uuid_len / LEN_UUID_128 * LEN_UUID_16);
+             if (p_multi_adv_data_cb->inst_cb[cbindex].data.p_services->p_uuid != NULL)
+             {
+                 UINT16 *p_uuid_out = p_multi_adv_data_cb->inst_cb[cbindex].data.p_services->p_uuid;
+                 while (p_adv_data->service_uuid_len >= LEN_UUID_128)
+                 {
+                     bt_uuid_t uuid;
+                     memset(&uuid, 0, sizeof(bt_uuid_t));
+                     memcpy(&uuid.uu, p_adv_data->p_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)
+                     {
+                         p_multi_adv_data_cb->inst_cb[cbindex].mask |= BTM_BLE_AD_BIT_SERVICE;
+                         ++p_multi_adv_data_cb->inst_cb[cbindex].data.p_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;
+                             }
+                         }
+                     }
+                     p_adv_data->p_service_uuid += LEN_UUID_128;
+                     p_adv_data->service_uuid_len -= LEN_UUID_128;
+                 }
+             }
+         }
+
+         if (p_elem_service_data != NULL || p_elem_service_128 != NULL)
+         {
+             p_multi_adv_data_cb->inst_cb[cbindex].data.p_proprietary =
+                                                GKI_getbuf(sizeof(tBTA_BLE_PROPRIETARY));
+             if (p_multi_adv_data_cb->inst_cb[cbindex].data.p_proprietary != NULL)
+             {
+                 tBTA_BLE_PROPRIETARY *p_prop = p_multi_adv_data_cb->inst_cb[cbindex].
+                            data.p_proprietary;
+                 tBTA_BLE_PROP_ELEM *p_elem = NULL;
+                 p_prop->num_elem = 0;
+                 p_multi_adv_data_cb->inst_cb[cbindex].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);
+                 }
+             }
+         }
+
+#if (defined(BLE_PERIPHERAL_ADV_NAME) && (BLE_PERIPHERAL_ADV_NAME == TRUE))
+     p_multi_adv_data_cb->inst_cb[cbindex].mask |= BTM_BLE_AD_BIT_DEV_NAME;
+#endif
+     return true;
+}
+
+void btif_gattc_clear_clientif(int client_if)
+{
+    int i=0;
+
+    btgatt_multi_adv_common_data *p_multi_adv_data_cb = btif_obtain_multi_adv_data_cb();
+
+    if(NULL == p_multi_adv_data_cb)
+        return;
+
+    // Clear both the inst_id and client_if values
+    for(i=0; i < BTM_BLE_MULTI_ADV_MAX; i++)
+    {
+       if(client_if == p_multi_adv_data_cb->clntif_map[i][CLNT_IF_IDX])
+       {
+          p_multi_adv_data_cb->clntif_map[i][INST_ID_IDX] = INVALID_ADV_INST;
+          p_multi_adv_data_cb->clntif_map[i][CLNT_IF_IDX] = INVALID_ADV_INST;
+          BTIF_TRACE_DEBUG2("Cleaning up index %d for clnt_if :%d,", i, client_if);
+          break;
+       }
+    }
+}
+
+void btif_gattc_cleanup_inst_cb(int inst_id)
+{
+    int cbindex = 0;
+    // Check for invalid instance id
+    if (inst_id < 0 || inst_id > BTM_BLE_MULTI_ADV_MAX)
+        return;
+
+    btgatt_multi_adv_common_data *p_multi_adv_data_cb = btif_obtain_multi_adv_data_cb();
+
+    if(NULL == p_multi_adv_data_cb)
+        return;
+
+    if(inst_id > 0)
+    {
+        cbindex = btif_gattc_obtain_idx_for_datacb(inst_id, INST_ID_IDX);
+        if (cbindex < 0)
+            return;
+    }
+    else
+    if(STD_ADV_INSTID == inst_id)
+      cbindex = STD_ADV_INSTID;
+
+    BTIF_TRACE_DEBUG2("Cleaning up multi_inst_cb for inst_id %d, cbindex %d", inst_id, cbindex);
+    btif_gattc_cleanup_multi_inst_cb(&p_multi_adv_data_cb->inst_cb[cbindex]);
+}
+
+void btif_gattc_cleanup_multi_inst_cb(btgatt_multi_adv_inst_cb *p_multi_inst_cb)
+{
+    // Manufacturer data cleanup
+    if (p_multi_inst_cb->data.p_manu != NULL)
+    {
+        if (p_multi_inst_cb->data.p_manu->p_val != NULL)
+           GKI_freebuf(p_multi_inst_cb->data.p_manu->p_val);
+        GKI_freebuf(p_multi_inst_cb->data.p_manu);
+    }
+
+    // Proprietary data cleanup
+    if (p_multi_inst_cb->data.p_proprietary != NULL)
+    {
+        int i = 0;
+        tBTA_BLE_PROP_ELEM *p_elem = p_multi_inst_cb->data.p_proprietary->p_elem;
+        while (i++ != p_multi_inst_cb->data.p_proprietary->num_elem
+            && p_elem)
+        {
+            if (p_elem->p_val != NULL)
+                GKI_freebuf(p_elem->p_val);
+            ++p_elem;
+        }
+
+        if (p_multi_inst_cb->data.p_proprietary->p_elem != NULL)
+            GKI_freebuf(p_multi_inst_cb->data.p_proprietary->p_elem);
+        GKI_freebuf(p_multi_inst_cb->data.p_proprietary);
+    }
+
+    // Service list cleanup
+    if (p_multi_inst_cb->data.p_services != NULL)
+    {
+        if (p_multi_inst_cb->data.p_services->p_uuid != NULL)
+           GKI_freebuf(p_multi_inst_cb->data.p_services->p_uuid);
+        GKI_freebuf(p_multi_inst_cb->data.p_services);
+    }
+
+    // Service data cleanup
+    if (p_multi_inst_cb->data.p_service_data != NULL)
+    {
+        if (p_multi_inst_cb->data.p_service_data->p_val != NULL)
+           GKI_freebuf(p_multi_inst_cb->data.p_service_data->p_val);
+        GKI_freebuf(p_multi_inst_cb->data.p_service_data);
+    }
+
+    if (p_multi_inst_cb->data.p_services_128b != NULL)
+        GKI_freebuf(p_multi_inst_cb->data.p_services_128b);
+
+    if (p_multi_inst_cb->data.p_service_32b != NULL)
+    {
+        if (p_multi_inst_cb->data.p_service_32b->p_uuid != NULL)
+           GKI_freebuf(p_multi_inst_cb->data.p_service_32b->p_uuid);
+        GKI_freebuf(p_multi_inst_cb->data.p_service_32b);
+    }
+
+    if (p_multi_inst_cb->data.p_sol_services != NULL)
+    {
+        if (p_multi_inst_cb->data.p_sol_services->p_uuid != NULL)
+           GKI_freebuf(p_multi_inst_cb->data.p_sol_services->p_uuid);
+        GKI_freebuf(p_multi_inst_cb->data.p_sol_services);
+    }
+
+    if (p_multi_inst_cb->data.p_sol_service_32b != NULL)
+    {
+        if (p_multi_inst_cb->data.p_sol_service_32b->p_uuid != NULL)
+           GKI_freebuf(p_multi_inst_cb->data.p_sol_service_32b->p_uuid);
+        GKI_freebuf(p_multi_inst_cb->data.p_sol_service_32b);
+    }
+
+    if(p_multi_inst_cb->data.p_sol_service_128b != NULL)
+        GKI_freebuf(p_multi_inst_cb->data.p_sol_service_128b);
+}
+
+#endif
index d861801..01dd192 100644 (file)
@@ -1295,7 +1295,6 @@ and USER_HW_DISABLE_API macros */
 #define BLE_ANDROID_CONTROLLER_SCAN_FILTER            TRUE
 #endif
 
-
 #ifndef LOCAL_BLE_CONTROLLER_ID
 #define LOCAL_BLE_CONTROLLER_ID         (1)
 #endif
@@ -1304,6 +1303,11 @@ and USER_HW_DISABLE_API macros */
 #define BLE_PRIVACY_SPT      TRUE
 #endif
 
+#ifndef BLE_MULTI_ADV_INCLUDED
+#define BLE_MULTI_ADV_INCLUDED  TRUE
+#endif
+
+
 /******************************************************************************
 **
 ** ATT/GATT Protocol/Profile Settings
index d170bfe..a2637da 100644 (file)
@@ -39,6 +39,7 @@ LOCAL_SRC_FILES += \
     ../btif/src/btif_sock_util.c \
     ../btif/src/btif_pan.c \
     ../btif/src/btif_gatt.c \
+    ../btif/src/btif_gatt_multi_adv_util.c \
     ../btif/src/btif_gatt_client.c \
     ../btif/src/btif_gatt_server.c \
     ../btif/src/btif_gatt_util.c \
index ecc42ef..6c16524 100644 (file)
@@ -67,6 +67,7 @@ LOCAL_SRC_FILES:= \
     ./btm/btm_main.c \
     ./btm/btm_dev.c \
     ./btm/btm_ble_gap.c \
+    ./btm/btm_ble_multi_adv.c \
     ./btm/btm_acl.c \
     ./btm/btm_sco.c \
     ./btm/btm_pm.c \
index 9bd771a..130aa1c 100644 (file)
@@ -1443,7 +1443,21 @@ UINT8 btm_ble_io_capabilities_req(tBTM_SEC_DEV_REC *p_dev_rec, tBTM_LE_IO_REQ *p
     if (callback_rc == BTM_SUCCESS)
 #endif
     {
+#if BTM_BLE_CONFORMANCE_TESTING == TRUE
+        if (btm_cb.devcb.keep_rfu_in_auth_req)
+        {
+            BTM_TRACE_DEBUG1 ("btm_ble_io_capabilities_req keep_rfu_in_auth_req = %u",
+                btm_cb.devcb.keep_rfu_in_auth_req);
+            p_data->auth_req &= BTM_LE_AUTH_REQ_MASK_KEEP_RFU;
+            btm_cb.devcb.keep_rfu_in_auth_req = FALSE;
+        }
+        else
+        {   /* default */
+            p_data->auth_req &= BTM_LE_AUTH_REQ_MASK;
+        }
+#else
         p_data->auth_req &= BTM_LE_AUTH_REQ_MASK;
+#endif
 
         BTM_TRACE_DEBUG2 ("btm_ble_io_capabilities_req 1: p_dev_rec->security_required = %d auth_req:%d",
                           p_dev_rec->security_required, p_data->auth_req);
@@ -1658,9 +1672,9 @@ void btm_ble_conn_complete(UINT8 *p, UINT16 evt_len)
     {
         role = HCI_ROLE_UNKNOWN;
 
-        if (status == HCI_ERR_DIRECTED_ADVERTISING_TIMEOUT)
+        if (status != HCI_ERR_DIRECTED_ADVERTISING_TIMEOUT)
         {
-            btm_ble_dir_adv_tout();
+            btm_ble_set_conn_st(BLE_CONN_IDLE);
         }
         /* this is to work around broadcom firmware problem to handle
          * unsolicited command complete event for HCI_LE_Create_Connection_Cancel
@@ -2302,6 +2316,23 @@ void btm_set_random_address(BD_ADDR random_bda)
 
 
 }
+
+/*******************************************************************************
+**
+** Function         btm_ble_set_keep_rfu_in_auth_req
+**
+** Description      This function indicates if RFU bits have to be kept as is
+**                  (by default they have to be set to 0 by the sender).
+**
+** Returns          void
+**
+*******************************************************************************/
+void btm_ble_set_keep_rfu_in_auth_req(BOOLEAN keep_rfu)
+{
+    BTM_TRACE_DEBUG1 ("btm_ble_set_keep_rfu_in_auth_req keep_rfus=%d", keep_rfu);
+    btm_cb.devcb.keep_rfu_in_auth_req = keep_rfu;
+}
+
 #endif /* BTM_BLE_CONFORMANCE_TESTING */
 
 #endif /* BLE_INCLUDED */
index 3c646e9..378470e 100644 (file)
@@ -33,8 +33,6 @@
 #if (defined BLE_INCLUDED && BLE_INCLUDED == TRUE)
 #include "btm_ble_int.h"
 #include "smp_api.h"
-#define BTM_BLE_PRIVATE_ADDR_INT    900           /* 15 minutes minimum for
-                                                   random address refreshing */
 
 /*******************************************************************************
 **
@@ -64,9 +62,13 @@ static void btm_gen_resolve_paddr_cmpl(tSMP_ENC *p)
 
         /* start a periodical timer to refresh random addr */
         btu_stop_timer(&p_cb->raddr_timer_ent);
+#if (BTM_BLE_CONFORMANCE_TESTING == TRUE)
+        btu_start_timer (&p_cb->raddr_timer_ent, BTU_TTYPE_BLE_RANDOM_ADDR,
+                         btm_cb.ble_ctr_cb.rpa_tout);
+#else
         btu_start_timer (&p_cb->raddr_timer_ent, BTU_TTYPE_BLE_RANDOM_ADDR,
                          BTM_BLE_PRIVATE_ADDR_INT);
-
+#endif
     }
     else
     {
@@ -84,7 +86,7 @@ static void btm_gen_resolve_paddr_cmpl(tSMP_ENC *p)
 ** Returns          void
 **
 *******************************************************************************/
-static void btm_gen_resolve_paddr_low(tBTM_RAND_ENC *p)
+void btm_gen_resolve_paddr_low(tBTM_RAND_ENC *p)
 {
 #if (BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE)
     tBTM_LE_RANDOM_CB *p_cb = &btm_cb.ble_ctr_cb.addr_mgnt_cb;
@@ -121,11 +123,11 @@ static void btm_gen_resolve_paddr_low(tBTM_RAND_ENC *p)
 ** Returns          void
 **
 *******************************************************************************/
-void btm_gen_resolvable_private_addr (void)
+void btm_gen_resolvable_private_addr (void *p_cmd_cplt_cback)
 {
     BTM_TRACE_EVENT0 ("btm_gen_resolvable_private_addr");
     /* generate 3B rand as BD LSB, SRK with it, get BD MSB */
-    if (!btsnd_hcic_ble_rand((void *)btm_gen_resolve_paddr_low))
+    if (!btsnd_hcic_ble_rand((void *)p_cmd_cplt_cback))
         btm_gen_resolve_paddr_cmpl(NULL);
 }
 /*******************************************************************************
index f9bd1aa..d70db73 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- *  Copyright (C) 2008-2012 Broadcom Corporation
+ *  Copyright (C) 2008-2014 Broadcom Corporation
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
 #define BTM_BLE_POLICY_UNKNOWN              0xff
 
 #define BTM_EXT_BLE_RMT_NAME_TIMEOUT        30
+#define MIN_ADV_LENGTH                       2
+
+extern tBTM_BLE_MULTI_ADV_CB  btm_multi_adv_cb;
 
 /*******************************************************************************
 **  Local functions
 *******************************************************************************/
 static void btm_ble_update_adv_flag(UINT8 flag);
 static void btm_ble_process_adv_pkt_cont(BD_ADDR bda, UINT8 addr_type, UINT8 evt_type, UINT8 *p);
-static UINT8 *btm_ble_build_adv_data(tBTM_BLE_AD_MASK *p_data_mask, UINT8 **p_dst, tBTM_BLE_ADV_DATA *p_data);
+UINT8 *btm_ble_build_adv_data(tBTM_BLE_AD_MASK *p_data_mask, UINT8 **p_dst,
+                              tBTM_BLE_ADV_DATA *p_data);
 static UINT8 btm_set_conn_mode_adv_init_addr(tBTM_BLE_INQ_CB *p_cb,
                                      BD_ADDR_PTR p_addr_ptr,
                                      tBLE_ADDR_TYPE *p_init_addr_type,
@@ -409,6 +413,62 @@ tBTM_STATUS BTM_BleBroadcast(BOOLEAN start)
 
 /*******************************************************************************
 **
+** Function         btm_vsc_brcm_features_complete
+**
+** Description      Command Complete callback for HCI_BLE_VENDOR_CAP_OCF
+**
+** Returns          void
+**
+*******************************************************************************/
+static void btm_ble_vendor_capability_vsc_cmpl_cback (tBTM_VSC_CMPL *p_vcs_cplt_params)
+{
+    UINT8  status = 0xFF, *p;
+    UINT8  rpa_offloading, max_irk_list_sz, filtering_support, max_filter;
+    UINT16 scan_result_storage;
+
+    /* Check status of command complete event */
+    if((p_vcs_cplt_params->opcode == HCI_BLE_VENDOR_CAP_OCF)
+        &&(p_vcs_cplt_params->param_len > 0 ))
+    {
+        p = p_vcs_cplt_params->p_param_buf;
+        STREAM_TO_UINT8  (status, p);
+    }
+
+    if(status == HCI_SUCCESS)
+    {
+        STREAM_TO_UINT8  (btm_multi_adv_cb.adv_inst_max, p);
+        STREAM_TO_UINT8  (rpa_offloading, p);
+        STREAM_TO_UINT16 (scan_result_storage, p);
+        STREAM_TO_UINT8  (max_irk_list_sz, p);
+        STREAM_TO_UINT8  (filtering_support, p);
+        STREAM_TO_UINT8  (max_filter, p);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         btm_ble_vendor_capability_init
+**
+** Description      LE Get_Vendor Capabilities
+**
+** Returns          None.
+**
+*******************************************************************************/
+void btm_ble_vendor_capability_init(void)
+{
+    if ( BTM_VendorSpecificCommand (HCI_BLE_VENDOR_CAP_OCF,
+                                    0,
+                                    NULL,
+                                    btm_ble_vendor_capability_vsc_cmpl_cback)
+                                    != BTM_CMD_STARTED)
+    {
+        BTM_TRACE_ERROR0("LE Get_Vendor Capabilities Command Failed.");
+    }
+    return ;
+}
+
+/*******************************************************************************
+**
 ** Function         BTM_RegisterScanReqEvt
 **
 ** Description      This function is called to register a scan request callback
@@ -459,7 +519,7 @@ void BTM_BleConfigPrivacy(BOOLEAN enable)
         if (p_cb->privacy)
         {
             /* generate resolvable private address */
-            btm_gen_resolvable_private_addr();
+            btm_gen_resolvable_private_addr(NULL);
         }
         else /* if privacy disabled, always use public address */
         {
@@ -666,7 +726,7 @@ static UINT8 btm_set_conn_mode_adv_init_addr(tBTM_BLE_INQ_CB *p_cb,
             !BTM_BLE_IS_RESOLVE_BDA(btm_cb.ble_ctr_cb.addr_mgnt_cb.private_addr))
         {
             /* need to generate RRA and update random addresss in controller */
-            btm_gen_resolvable_private_addr();
+            btm_gen_resolvable_private_addr((void *)btm_gen_resolve_paddr_low);
         }
 #endif
     }
@@ -890,7 +950,7 @@ tBTM_STATUS BTM_BleWriteAdvData(tBTM_BLE_AD_MASK data_mask, tBTM_BLE_ADV_DATA *p
 
     p_cb_data->p_pad = p;
 
-    if (data_mask != 0)
+    if (mask != 0)
     {
         BTM_TRACE_ERROR0("Partial data write into ADV");
     }
@@ -951,9 +1011,10 @@ UINT8 *BTM_CheckAdvData( UINT8 *p_adv, UINT8 type, UINT8 *p_length)
 **
 ** Description      This function is called build the adv data and rsp data.
 *******************************************************************************/
-static UINT8 *btm_ble_build_adv_data(tBTM_BLE_AD_MASK *p_data_mask, UINT8 **p_dst, tBTM_BLE_ADV_DATA *p_data)
+UINT8 *btm_ble_build_adv_data(tBTM_BLE_AD_MASK *p_data_mask, UINT8 **p_dst,
+                              tBTM_BLE_ADV_DATA *p_data)
 {
-    UINT16 data_mask = *p_data_mask;
+    UINT32 data_mask = *p_data_mask;
     UINT8   *p = *p_dst,
     *p_flag = NULL;
     UINT16  len = BTM_BLE_AD_DATA_LEN, cp_len = 0;
@@ -968,7 +1029,7 @@ static UINT8 *btm_ble_build_adv_data(tBTM_BLE_AD_MASK *p_data_mask, UINT8 **p_ds
         /* flags */
         if (data_mask & BTM_BLE_AD_BIT_FLAGS)
         {
-            *p++ = 2;
+            *p++ = MIN_ADV_LENGTH;
             *p++ = BTM_BLE_AD_TYPE_FLAG;
             p_flag = p;
             if (p_data)
@@ -992,13 +1053,13 @@ static UINT8 *btm_ble_build_adv_data(tBTM_BLE_AD_MASK *p_data_mask, UINT8 **p_ds
         }
         /* device name */
 #if BTM_MAX_LOC_BD_NAME_LEN > 0
-        if (len > 2 && data_mask & BTM_BLE_AD_BIT_DEV_NAME)
+        if (len > MIN_ADV_LENGTH && data_mask & BTM_BLE_AD_BIT_DEV_NAME)
         {
-            if (strlen(btm_cb.cfg.bd_name) > (UINT16)(len - 2))
+            if (strlen(btm_cb.cfg.bd_name) > (UINT16)(len - MIN_ADV_LENGTH))
             {
-                *p++ = len - 2 + 1;
+                *p++ = len - MIN_ADV_LENGTH + 1;
                 *p++ = BTM_BLE_AD_TYPE_NAME_SHORT;
-                ARRAY_TO_STREAM(p, btm_cb.cfg.bd_name, len - 2);
+                ARRAY_TO_STREAM(p, btm_cb.cfg.bd_name, len - MIN_ADV_LENGTH);
             }
             else
             {
@@ -1007,61 +1068,180 @@ static UINT8 *btm_ble_build_adv_data(tBTM_BLE_AD_MASK *p_data_mask, UINT8 **p_ds
                 *p++ = BTM_BLE_AD_TYPE_NAME_CMPL;
                 ARRAY_TO_STREAM(p, btm_cb.cfg.bd_name, cp_len);
             }
-            len -= (cp_len + 2);
+            len -= (cp_len + MIN_ADV_LENGTH);
             data_mask &= ~BTM_BLE_AD_BIT_DEV_NAME;
         }
 #endif
         /* manufacturer data */
-        if (len > 2 && data_mask & BTM_BLE_AD_BIT_MANU &&
-            p_data && p_data->manu.len != 0 && p_data->manu.p_val)
+        if (len > MIN_ADV_LENGTH && data_mask & BTM_BLE_AD_BIT_MANU &&
+            p_data && p_data->p_manu &&
+            p_data->p_manu->len != 0 && p_data->p_manu->p_val)
         {
-            if (p_data->manu.len > (len - 2))
-                cp_len = len - 2;
+            if (p_data->p_manu->len > (len - MIN_ADV_LENGTH))
+                cp_len = len - MIN_ADV_LENGTH;
             else
-                cp_len = p_data->manu.len;
+                cp_len = p_data->p_manu->len;
 
             *p++ = cp_len + 1;
             *p++ = BTM_BLE_AD_TYPE_MANU;
-            ARRAY_TO_STREAM(p, p_data->manu.p_val, cp_len);
+            ARRAY_TO_STREAM(p, p_data->p_manu->p_val, cp_len);
 
-            len -= (cp_len + 2);
+            len -= (cp_len + MIN_ADV_LENGTH);
             data_mask &= ~BTM_BLE_AD_BIT_MANU;
         }
         /* TX power */
-        if (len > 2 && data_mask & BTM_BLE_AD_BIT_TX_PWR)
+        if (len > MIN_ADV_LENGTH && data_mask & BTM_BLE_AD_BIT_TX_PWR)
         {
-            *p++ = 2;
+            *p++ = MIN_ADV_LENGTH;
             *p++ = BTM_BLE_AD_TYPE_TX_PWR;
-            *p++ = btm_cb.ble_ctr_cb.inq_var.tx_power;
+            *p++ = p_data->tx_power;
             len -= 3;
 
             data_mask &= ~BTM_BLE_AD_BIT_TX_PWR;
         }
-        /* services */
-        if (len > 2 && data_mask & BTM_BLE_AD_BIT_SERVICE &&
-            p_data && p_data->services.num_service != 0 &&
-            p_data->services.p_uuid)
+        /* 16 bits services */
+        if (len > MIN_ADV_LENGTH && data_mask & BTM_BLE_AD_BIT_SERVICE &&
+            p_data && p_data->p_services &&
+            p_data->p_services->num_service != 0 &&
+            p_data->p_services->p_uuid)
         {
-            if (p_data->services.num_service * 2 > (len - 2))
+            if (p_data->p_services->num_service * LEN_UUID_16 > (len - MIN_ADV_LENGTH))
             {
-                cp_len = (len - 2)/2;
-                *p ++ = 1 + cp_len * 2;
+                cp_len = (len - MIN_ADV_LENGTH)/LEN_UUID_16;
+                *p ++ = 1 + cp_len * LEN_UUID_16;
                 *p++ = BTM_BLE_AD_TYPE_16SRV_PART;
             }
             else
             {
-                cp_len = p_data->services.num_service;
-                *p++ = 1 + cp_len * 2;
+                cp_len = p_data->p_services->num_service;
+                *p++ = 1 + cp_len * LEN_UUID_16;
                 *p++ = BTM_BLE_AD_TYPE_16SRV_CMPL;
             }
             for (i = 0; i < cp_len; i ++)
             {
-                UINT16_TO_STREAM(p, *(p_data->services.p_uuid + i));
+                UINT16_TO_STREAM(p, *(p_data->p_services->p_uuid + i));
             }
 
-            len -= (cp_len * 2 + 2);
+            len -= (cp_len * MIN_ADV_LENGTH + MIN_ADV_LENGTH);
             data_mask &= ~BTM_BLE_AD_BIT_SERVICE;
         }
+        /* 32 bits service uuid */
+        if (len > MIN_ADV_LENGTH && data_mask & BTM_BLE_AD_BIT_SERVICE_32 &&
+            p_data && p_data->p_service_32b &&
+            p_data->p_service_32b->num_service != 0 &&
+            p_data->p_service_32b->p_uuid)
+        {
+            if ((p_data->p_service_32b->num_service * LEN_UUID_32) > (len - MIN_ADV_LENGTH))
+            {
+                cp_len = (len - MIN_ADV_LENGTH)/LEN_UUID_32;
+                *p ++ = 1 + cp_len * LEN_UUID_32;
+                *p++ = BTM_BLE_AD_TYPE_32SRV_PART;
+            }
+            else
+            {
+                cp_len = p_data->p_service_32b->num_service;
+                *p++ = 1 + cp_len * LEN_UUID_32;
+                *p++ = BTM_BLE_AD_TYPE_32SRV_CMPL;
+            }
+            for (i = 0; i < cp_len; i ++)
+            {
+                UINT32_TO_STREAM(p, *(p_data->p_service_32b->p_uuid + i));
+            }
+
+            len -= (cp_len * LEN_UUID_32 + MIN_ADV_LENGTH);
+            data_mask &= ~BTM_BLE_AD_BIT_SERVICE_32;
+        }
+        /* 128 bits services */
+        if (len >= (MAX_UUID_SIZE + 2) && data_mask & BTM_BLE_AD_BIT_SERVICE_128 &&
+            p_data && p_data->p_services_128b)
+        {
+            *p ++ = 1 + MAX_UUID_SIZE;
+            if (!p_data->p_services_128b->list_cmpl)
+                *p++ = BTM_BLE_AD_TYPE_128SRV_PART;
+            else
+                *p++ = BTM_BLE_AD_TYPE_128SRV_CMPL;
+
+            ARRAY_TO_STREAM(p, p_data->p_services_128b->uuid128, MAX_UUID_SIZE);
+
+            len -= (MAX_UUID_SIZE + MIN_ADV_LENGTH);
+            data_mask &= ~BTM_BLE_AD_BIT_SERVICE_128;
+        }
+        /* 32 bits Service Solicitation UUIDs */
+        if (len > MIN_ADV_LENGTH && data_mask & BTM_BLE_AD_BIT_SERVICE_32SOL &&
+            p_data && p_data->p_sol_service_32b &&
+            p_data->p_sol_service_32b->num_service != 0 &&
+            p_data->p_sol_service_32b->p_uuid)
+        {
+            if ((p_data->p_sol_service_32b->num_service * LEN_UUID_32) > (len - MIN_ADV_LENGTH))
+            {
+                cp_len = (len - MIN_ADV_LENGTH)/LEN_UUID_32;
+                *p ++ = 1 + cp_len * LEN_UUID_32;
+            }
+            else
+            {
+                cp_len = p_data->p_sol_service_32b->num_service;
+                *p++ = 1 + cp_len * LEN_UUID_32;
+            }
+
+            *p++ = BTM_BLE_AD_TYPE_32SOL_SRV_UUID;
+            for (i = 0; i < cp_len; i ++)
+            {
+                UINT32_TO_STREAM(p, *(p_data->p_sol_service_32b->p_uuid + i));
+            }
+
+            len -= (cp_len * LEN_UUID_32 + MIN_ADV_LENGTH);
+            data_mask &= ~BTM_BLE_AD_BIT_SERVICE_32SOL;
+        }
+        /* 128 bits Solicitation services UUID */
+        if (len >= (MAX_UUID_SIZE + MIN_ADV_LENGTH) && data_mask & BTM_BLE_AD_BIT_SERVICE_128SOL &&
+            p_data && p_data->p_sol_service_128b)
+        {
+            *p ++ = 1 + MAX_UUID_SIZE;
+            *p++ = BTM_BLE_AD_TYPE_128SOL_SRV_UUID;
+            ARRAY_TO_STREAM(p, p_data->p_sol_service_128b->uuid128, MAX_UUID_SIZE);
+            len -= (MAX_UUID_SIZE + MIN_ADV_LENGTH);
+            data_mask &= ~BTM_BLE_AD_BIT_SERVICE_128SOL;
+        }
+        /* 16bits/32bits/128bits Service Data */
+        if (len > MIN_ADV_LENGTH && data_mask & BTM_BLE_AD_BIT_SERVICE_DATA &&
+            p_data && p_data->p_service_data->len != 0 && p_data->p_service_data->p_val)
+        {
+            if (len  > (p_data->p_service_data->service_uuid.len + MIN_ADV_LENGTH))
+            {
+                if (p_data->p_service_data->len > (len - MIN_ADV_LENGTH))
+                    cp_len = len - MIN_ADV_LENGTH- p_data->p_service_data->service_uuid.len;
+                else
+                    cp_len = p_data->p_service_data->len;
+
+                *p++ = cp_len + 1 + p_data->p_service_data->service_uuid.len;
+                if (p_data->p_service_data->service_uuid.len == LEN_UUID_16)
+                {
+                    *p++ = BTM_BLE_AD_TYPE_SERVICE_DATA;
+                    UINT16_TO_STREAM(p, p_data->p_service_data->service_uuid.uu.uuid16);
+                }
+                else if (p_data->p_service_data->service_uuid.len == LEN_UUID_32)
+                {
+                    *p++ = BTM_BLE_AD_TYPE_32SERVICE_DATA;
+                    UINT32_TO_STREAM(p, p_data->p_service_data->service_uuid.uu.uuid32);
+                }
+                else
+                {
+                    *p++ = BTM_BLE_AD_TYPE_128SERVICE_DATA;
+                    ARRAY_TO_STREAM(p, p_data->p_service_data->service_uuid.uu.uuid128,
+                                    LEN_UUID_128);
+                }
+
+                ARRAY_TO_STREAM(p, p_data->p_service_data->p_val, cp_len);
+
+                len -= (cp_len + MIN_ADV_LENGTH + p_data->p_service_data->service_uuid.len);
+                data_mask &= ~BTM_BLE_AD_BIT_SERVICE_DATA;
+            }
+            else
+            {
+                BTM_TRACE_WARNING0("service data does not fit");
+            }
+        }
+
         if (len >= 6 && data_mask & BTM_BLE_AD_BIT_INT_RANGE &&
             p_data)
         {
@@ -1078,13 +1258,14 @@ static UINT8 *btm_ble_build_adv_data(tBTM_BLE_AD_MASK *p_data_mask, UINT8 **p_ds
             {
                 p_elem = p_data->p_proprietary->p_elem  + i;
 
-                if (len >= (2 + p_elem->len))/* len byte(1) + ATTR type(1) + Uuid len(2) + value length */
+                if (len >= (MIN_ADV_LENGTH + p_elem->len))/* len byte(1) + ATTR type(1) + Uuid len(2)
+                                                          + value length */
                 {
                     *p ++ = p_elem->len + 1; /* Uuid len + value length */
                     *p ++ = p_elem->adv_type;
                     ARRAY_TO_STREAM(p, p_elem->p_val, p_elem->len);
 
-                    len -= (2 + p_elem->len);
+                    len -= (MIN_ADV_LENGTH + p_elem->len);
                 }
                 else
                 {
@@ -1200,9 +1381,9 @@ void btm_ble_set_adv_flag(UINT16 connect_mode, UINT16 disc_mode)
 **
 ** Description      This function is called to set BLE discoverable mode.
 **
-** Parameters:      mode: discoverability mode.
+** Parameters:      combined_mode: discoverability mode.
 **
-** Returns          void
+** Returns          BTM_SUCCESS is status set successfully; otherwise failure.
 **
 *******************************************************************************/
 tBTM_STATUS btm_ble_set_discoverability(UINT16 combined_mode)
@@ -1296,9 +1477,9 @@ tBTM_STATUS btm_ble_set_discoverability(UINT16 combined_mode)
 **
 ** Description      This function is called to set BLE connectability mode.
 **
-** Parameters:      mode: connectability mode.
+** Parameters:      combined_mode: connectability mode.
 **
-** Returns          void
+** Returns          BTM_SUCCESS is status set successfully; otherwise failure.
 **
 *******************************************************************************/
 tBTM_STATUS btm_ble_set_connectability(UINT16 combined_mode)
@@ -2411,7 +2592,8 @@ void btm_ble_update_mode_operation(UINT8 link_role, BD_ADDR bd_addr, BOOLEAN con
         }
     }
 
-    if (btm_cb.ble_ctr_cb.inq_var.connectable_mode == BTM_BLE_CONNECTABLE)
+    if (btm_multi_adv_cb.adv_inst_max == 0 &&
+        btm_cb.ble_ctr_cb.inq_var.connectable_mode == BTM_BLE_CONNECTABLE)
     {
         btm_ble_set_connectability ( btm_cb.ble_ctr_cb.inq_var.connectable_mode );
     }
@@ -2482,15 +2664,21 @@ void btm_ble_timeout(TIMER_LIST_ENT *p_tle)
         case BTU_TTYPE_BLE_GAP_LIM_DISC:
             /* lim_timeout expiried, limited discovery should exit now */
             btm_cb.btm_inq_vars.discoverable_mode &= ~BTM_BLE_LIMITED_DISCOVERABLE;
-
             btm_ble_set_adv_flag(btm_cb.btm_inq_vars.connectable_mode, btm_cb.btm_inq_vars.discoverable_mode);
             break;
 
         case BTU_TTYPE_BLE_RANDOM_ADDR:
             if (btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type == BLE_ADDR_RANDOM)
             {
+                if ((void *)(p_tle->param) == NULL)
                 /* refresh the random addr */
-                btm_gen_resolvable_private_addr();
+                btm_gen_resolvable_private_addr((void *)btm_gen_resolve_paddr_low);
+                else
+                {
+#if BLE_MULTI_ADV_INCLUDED == TRUE
+                  btm_ble_multi_adv_configure_rpa((tBTM_BLE_MULTI_ADV_INST*)&p_tle->param);
+#endif
+                }
             }
             break;
 
@@ -2611,6 +2799,11 @@ void btm_ble_init (void)
     p_cb->scan_int = p_cb->scan_win = BTM_BLE_CONN_PARAM_UNDEF;
 
     p_cb->inq_var.evt_type = BTM_BLE_NON_CONNECT_EVT;
+#if BLE_MULTI_ADV_INCLUDED == TRUE
+    btm_ble_multi_adv_init();
+#endif
+
+    btm_ble_vendor_capability_init();
 }
 
 /*******************************************************************************
index f3cb771..4553f4a 100644 (file)
@@ -116,6 +116,9 @@ typedef struct
 
 #define BTM_BLE_VALID_PRAM(x, min, max)  (((x) >= (min) && (x) <= (max)) || ((x) == BTM_BLE_CONN_PARAM_UNDEF))
 
+#define BTM_BLE_PRIVATE_ADDR_INT    900           /* 15 minutes minimum for
+                                                   random address refreshing */
+
 typedef struct
 {
 
@@ -328,6 +331,8 @@ extern void btm_ble_conn_complete(UINT8 *p, UINT16 evt_len);
 extern void btm_read_ble_local_supported_states_complete(UINT8 *p, UINT16 evt_len);
 extern tBTM_BLE_CONN_ST btm_ble_get_conn_st(void);
 extern void btm_ble_set_conn_st(tBTM_BLE_CONN_ST new_st);
+extern UINT8 *btm_ble_build_adv_data(tBTM_BLE_AD_MASK *p_data_mask, UINT8 **p_dst,
+                                     tBTM_BLE_ADV_DATA *p_data);
 extern tBTM_STATUS btm_ble_start_adv(void);
 extern tBTM_STATUS btm_ble_stop_adv(void);
 extern tBTM_STATUS btm_ble_start_scan (UINT8 filter_enb);
@@ -383,10 +388,16 @@ extern BOOLEAN btm_send_pending_direct_conn(void);
 extern void btm_ble_enqueue_direct_conn_req(void *p_param);
 
 /* BLE address management */
-extern void btm_gen_resolvable_private_addr (void);
+extern void btm_gen_resolvable_private_addr (void *p_cmd_cplt_cback);
 extern void btm_gen_non_resolvable_private_addr (tBTM_BLE_ADDR_CBACK *p_cback, void *p);
 extern void btm_ble_resolve_random_addr(BD_ADDR random_bda, tBTM_BLE_RESOLVE_CBACK * p_cback, void *p);
 extern void btm_ble_update_reconnect_address(BD_ADDR bd_addr);
+extern void btm_gen_resolve_paddr_low(tBTM_RAND_ENC *p);
+
+extern void btm_ble_multi_adv_configure_rpa (tBTM_BLE_MULTI_ADV_INST *p_inst);
+extern void btm_ble_multi_adv_init(void);
+extern void btm_ble_multi_adv_reenable(UINT8 inst_id);
+
 extern BOOLEAN btm_ble_topology_check(tBTM_BLE_STATE_MASK request);
 extern BOOLEAN btm_ble_clear_topology_mask(tBTM_BLE_STATE_MASK request_state);
 extern BOOLEAN btm_ble_set_topology_mask(tBTM_BLE_STATE_MASK request_state);
@@ -396,6 +407,7 @@ BT_API extern void btm_ble_set_no_disc_if_pair_fail (BOOLEAN disble_disc);
 BT_API extern void btm_ble_set_test_mac_value (BOOLEAN enable, UINT8 *p_test_mac_val);
 BT_API extern void btm_ble_set_test_local_sign_cntr_value(BOOLEAN enable, UINT32 test_local_sign_cntr);
 BT_API extern void btm_set_random_address(BD_ADDR random_bda);
+BT_API extern void btm_ble_set_keep_rfu_in_auth_req(BOOLEAN keep_rfu);
 #endif
 
 
diff --git a/stack/btm/btm_ble_multi_adv.c b/stack/btm/btm_ble_multi_adv.c
new file mode 100644 (file)
index 0000000..24394da
--- /dev/null
@@ -0,0 +1,761 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2014  Broadcom Corporation
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at:
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ ******************************************************************************/
+
+#include <string.h>
+#include "bt_target.h"
+
+#if (BLE_INCLUDED == TRUE)
+#if BLE_MULTI_ADV_INCLUDED == TRUE
+#include "bt_types.h"
+#include "hcimsgs.h"
+#include "btu.h"
+#include "btm_int.h"
+#include "bt_utils.h"
+#include "hcidefs.h"
+#include "btm_ble_api.h"
+
+/* length of each multi adv sub command */
+#define BTM_BLE_MULTI_ADV_ENB_LEN                       3
+#define BTM_BLE_MULTI_ADV_SET_PARAM_LEN                 33
+#define BTM_BLE_MULTI_ADV_WRITE_DATA_LEN                (BTM_BLE_AD_DATA_LEN + 3)
+#define BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR_LEN           8
+
+#ifndef BTM_BLE_MULTI_ADV_INST_MAX
+#define BTM_BLE_MULTI_ADV_INST_MAX                      5
+#endif
+
+tBTM_BLE_MULTI_ADV_CB  btm_multi_adv_cb;
+
+static void btm_ble_multi_adv_gen_rpa_cmpl_1(tBTM_RAND_ENC *p);
+static void btm_ble_multi_adv_gen_rpa_cmpl_2(tBTM_RAND_ENC *p);
+static void btm_ble_multi_adv_gen_rpa_cmpl_3(tBTM_RAND_ENC *p);
+static void btm_ble_multi_adv_gen_rpa_cmpl_4(tBTM_RAND_ENC *p);
+
+typedef void (*tBTM_MULTI_ADV_RPA_CMPL)(tBTM_RAND_ENC *p);
+const tBTM_MULTI_ADV_RPA_CMPL btm_ble_multi_adv_rpa_cmpl [] =
+{
+    btm_ble_multi_adv_gen_rpa_cmpl_1,
+    btm_ble_multi_adv_gen_rpa_cmpl_2,
+    btm_ble_multi_adv_gen_rpa_cmpl_3,
+    btm_ble_multi_adv_gen_rpa_cmpl_4
+};
+
+#define BTM_BLE_MULTI_ADV_CB_EVT_MASK   0xF0
+#define BTM_BLE_MULTI_ADV_SUBCODE_MASK  0x0F
+
+/*******************************************************************************
+**
+** Function         btm_ble_multi_adv_enq_op_q
+**
+** Description      enqueue a multi adv operation in q to check command complete
+**                  status.
+**
+** Returns          void
+**
+*******************************************************************************/
+void btm_ble_multi_adv_enq_op_q(UINT8 opcode, UINT8 inst_id, UINT8 cb_evt)
+{
+    tBTM_BLE_MULTI_ADV_OPQ  *p_op_q = &btm_multi_adv_cb.op_q;
+
+    p_op_q->inst_id[p_op_q->next_idx] = inst_id;
+
+    p_op_q->sub_code[p_op_q->next_idx] = (opcode |(cb_evt << 4));
+
+    p_op_q->next_idx = (p_op_q->next_idx + 1) % BTM_BLE_MULTI_ADV_MAX;
+}
+
+/*******************************************************************************
+**
+** Function         btm_ble_multi_adv_deq_op_q
+**
+** Description      dequeue a multi adv operation from q when command complete
+**                  is received.
+**
+** Returns          void
+**
+*******************************************************************************/
+void btm_ble_multi_adv_deq_op_q(UINT8 *p_opcode, UINT8 *p_inst_id, UINT8 *p_cb_evt)
+{
+    tBTM_BLE_MULTI_ADV_OPQ  *p_op_q = &btm_multi_adv_cb.op_q;
+
+    *p_inst_id = p_op_q->inst_id[p_op_q->pending_idx] & 0x7F;
+    *p_cb_evt = (p_op_q->sub_code[p_op_q->pending_idx] >> 4);
+    *p_opcode = (p_op_q->sub_code[p_op_q->pending_idx] & BTM_BLE_MULTI_ADV_SUBCODE_MASK);
+
+    p_op_q->pending_idx = (p_op_q->pending_idx + 1) % BTM_BLE_MULTI_ADV_MAX;
+}
+
+/*******************************************************************************
+**
+** Function         btm_ble_multi_adv_vsc_cmpl_cback
+**
+** Description      Multi adv VSC complete callback
+**
+** Parameters
+**
+** Returns          void
+**
+*******************************************************************************/
+void btm_ble_multi_adv_vsc_cmpl_cback (tBTM_VSC_CMPL *p_params)
+{
+    UINT8  status, subcode;
+    UINT8  *p = p_params->p_param_buf, inst_id;
+    UINT16  len = p_params->param_len;
+    tBTM_BLE_MULTI_ADV_INST *p_inst ;
+    UINT8   cb_evt = 0, opcode;
+
+    if (len  < 2)
+    {
+        BTM_TRACE_ERROR0("wrong length for btm_ble_multi_adv_vsc_cmpl_cback");
+        return;
+    }
+
+    STREAM_TO_UINT8(status, p);
+    STREAM_TO_UINT8(subcode, p);
+
+    btm_ble_multi_adv_deq_op_q(&opcode, &inst_id, &cb_evt);
+
+    BTM_TRACE_DEBUG3("op_code = %02x inst_id = %d cb_evt = %02x", opcode, inst_id, cb_evt);
+
+    if (opcode != subcode || inst_id == 0)
+    {
+        BTM_TRACE_ERROR2("get unexpected VSC cmpl, expect: %d get: %d",subcode,opcode);
+        return;
+    }
+
+    p_inst = &btm_multi_adv_cb.adv_inst[inst_id - 1];
+
+    switch (subcode)
+    {
+        case BTM_BLE_MULTI_ADV_ENB:
+        BTM_TRACE_DEBUG1("BTM_BLE_MULTI_ADV_ENB status = %d", status);
+        if (status != HCI_SUCCESS)
+        {
+            btm_multi_adv_cb.adv_inst[inst_id-1].inst_id = 0;
+        }
+        break;
+
+        case BTM_BLE_MULTI_ADV_SET_PARAM:
+        {
+            BTM_TRACE_DEBUG1("BTM_BLE_MULTI_ADV_SET_PARAM status = %d", status);
+            break;
+        }
+
+        case BTM_BLE_MULTI_ADV_WRITE_ADV_DATA:
+        {
+            BTM_TRACE_DEBUG1("BTM_BLE_MULTI_ADV_WRITE_ADV_DATA status = %d", status);
+            break;
+        }
+
+        case BTM_BLE_MULTI_ADV_WRITE_SCAN_RSP_DATA:
+        {
+            BTM_TRACE_DEBUG1("BTM_BLE_MULTI_ADV_WRITE_SCAN_RSP_DATA status = %d", status);
+            break;
+        }
+
+        case BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR:
+        {
+            BTM_TRACE_DEBUG1("BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR status = %d", status);
+            break;
+        }
+
+        default:
+            break;
+    }
+
+    if (cb_evt != 0 && p_inst->p_cback != NULL)
+    {
+        (p_inst->p_cback)(cb_evt, inst_id, p_inst->p_ref, status);
+    }
+    return;
+}
+
+/*******************************************************************************
+**
+** Function         btm_ble_enable_multi_adv
+**
+** Description      This function enable the customer specific feature in controller
+**
+** Parameters       enable: enable or disable
+**                  inst_id:    adv instance ID, can not be 0
+**
+** Returns          status
+**
+*******************************************************************************/
+tBTM_STATUS btm_ble_enable_multi_adv (BOOLEAN enable, UINT8 inst_id, UINT8 cb_evt)
+{
+    UINT8           param[BTM_BLE_MULTI_ADV_ENB_LEN], *pp;
+    UINT8           enb = enable ? 1: 0;
+    tBTM_STATUS     rt;
+
+    pp = param;
+    memset(param, 0, BTM_BLE_MULTI_ADV_ENB_LEN);
+
+    UINT8_TO_STREAM (pp, BTM_BLE_MULTI_ADV_ENB);
+    UINT8_TO_STREAM (pp, enb);
+    UINT8_TO_STREAM (pp, inst_id);
+
+    BTM_TRACE_EVENT2 (" btm_ble_enable_multi_adv: enb %d, Inst ID %d",enb,inst_id);
+
+    if ((rt = BTM_VendorSpecificCommand (HCI_BLE_MULTI_ADV_OCF,
+                                    BTM_BLE_MULTI_ADV_ENB_LEN,
+                                    param,
+                                    btm_ble_multi_adv_vsc_cmpl_cback))
+                                     == BTM_CMD_STARTED)
+    {
+        btm_ble_multi_adv_enq_op_q(BTM_BLE_MULTI_ADV_ENB, inst_id, cb_evt);
+    }
+    return rt;
+}
+
+/*******************************************************************************
+**
+** Function         btm_ble_multi_adv_set_params
+**
+** Description      This function enable the customer specific feature in controller
+**
+** Parameters       advertise parameters used for this instance.
+**
+** Returns          status
+**
+*******************************************************************************/
+tBTM_STATUS btm_ble_multi_adv_set_params (tBTM_BLE_MULTI_ADV_INST *p_inst,
+                                          tBTM_BLE_ADV_PARAMS *p_params,
+                                          UINT8 cb_evt)
+{
+    UINT8           param[BTM_BLE_MULTI_ADV_SET_PARAM_LEN], *pp;
+    tBTM_STATUS     rt;
+    BD_ADDR         dummy ={0,0,0,0,0,0};
+
+    pp = param;
+    memset(param, 0, BTM_BLE_MULTI_ADV_SET_PARAM_LEN);
+
+    UINT8_TO_STREAM(pp, BTM_BLE_MULTI_ADV_SET_PARAM);
+
+    UINT16_TO_STREAM (pp, p_params->adv_int_min);
+    UINT16_TO_STREAM (pp, p_params->adv_int_max);
+    UINT8_TO_STREAM  (pp, p_params->adv_type);
+
+    if (btm_cb.ble_ctr_cb.privacy)
+    {
+        UINT8_TO_STREAM  (pp, BLE_ADDR_RANDOM);
+        BDADDR_TO_STREAM (pp, p_inst->rpa);
+    }
+    else
+    {
+        UINT8_TO_STREAM  (pp, BLE_ADDR_PUBLIC);
+        BDADDR_TO_STREAM (pp, btm_cb.devcb.local_addr);
+    }
+
+    BTM_TRACE_EVENT3 (" btm_ble_multi_adv_set_params,Min %d, Max %d,adv_type %d",
+        p_params->adv_int_min,p_params->adv_int_max,p_params->adv_type);
+
+    UINT8_TO_STREAM  (pp, 0);
+    BDADDR_TO_STREAM (pp, dummy);
+
+    if (p_params->channel_map == 0 || p_params->channel_map > BTM_BLE_DEFAULT_ADV_CHNL_MAP)
+        p_params->channel_map = BTM_BLE_DEFAULT_ADV_CHNL_MAP;
+    UINT8_TO_STREAM (pp, p_params->channel_map);
+
+    if (p_params->adv_filter_policy >= AP_SCAN_CONN_POLICY_MAX)
+        p_params->adv_filter_policy = AP_SCAN_CONN_ALL;
+    UINT8_TO_STREAM (pp, p_params->adv_filter_policy);
+
+    UINT8_TO_STREAM (pp, p_inst->inst_id);
+
+    if (p_params->tx_power > BTM_BLE_ADV_TX_POWER_MAX)
+        p_params->tx_power = BTM_BLE_ADV_TX_POWER_MAX;
+    UINT8_TO_STREAM (pp, p_params->tx_power);
+
+    BTM_TRACE_EVENT4("set_params:Chnl Map %d,adv_fltr policy %d,ID:%d, TX Power%d",
+        p_params->channel_map,p_params->adv_filter_policy,p_inst->inst_id,p_params->tx_power);
+
+    if ((rt = BTM_VendorSpecificCommand (HCI_BLE_MULTI_ADV_OCF,
+                                    BTM_BLE_MULTI_ADV_SET_PARAM_LEN,
+                                    param,
+                                    btm_ble_multi_adv_vsc_cmpl_cback))
+           == BTM_CMD_STARTED)
+    {
+        p_inst->adv_evt = p_params->adv_type;
+
+        if (btm_cb.ble_ctr_cb.privacy)
+        {
+            /* start timer */
+            p_inst->raddr_timer_ent.param = (TIMER_PARAM_TYPE) p_inst;
+            btu_start_timer (&p_inst->raddr_timer_ent, BTU_TTYPE_BLE_RANDOM_ADDR,
+                             BTM_BLE_PRIVATE_ADDR_INT);
+        }
+        btm_ble_multi_adv_enq_op_q(BTM_BLE_MULTI_ADV_SET_PARAM, p_inst->inst_id, cb_evt);
+    }
+    return rt;
+}
+
+/*******************************************************************************
+**
+** Function         btm_ble_multi_adv_write_rpa
+**
+** Description      This function write the random address for the adv instance into
+**                  controller
+**
+** Parameters
+**
+** Returns          status
+**
+*******************************************************************************/
+tBTM_STATUS btm_ble_multi_adv_write_rpa (tBTM_BLE_MULTI_ADV_INST *p_inst, BD_ADDR random_addr)
+{
+    UINT8           param[BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR_LEN], *pp = param;
+    tBTM_STATUS     rt;
+
+    BTM_TRACE_EVENT0 (" btm_ble_multi_adv_set_random_addr");
+
+    memset(param, 0, BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR_LEN);
+
+    UINT8_TO_STREAM (pp, BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR);
+    BDADDR_TO_STREAM(pp, random_addr);
+    UINT8_TO_STREAM(pp,  p_inst->inst_id);
+
+    if ((rt = BTM_VendorSpecificCommand (HCI_BLE_MULTI_ADV_OCF,
+                                    BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR_LEN,
+                                    param,
+                                    btm_ble_multi_adv_vsc_cmpl_cback)) == BTM_CMD_STARTED)
+    {
+        /* start a periodical timer to refresh random addr */
+        btu_stop_timer(&p_inst->raddr_timer_ent);
+        p_inst->raddr_timer_ent.param = (TIMER_PARAM_TYPE) p_inst;
+        btu_start_timer (&p_inst->raddr_timer_ent, BTU_TTYPE_BLE_RANDOM_ADDR,
+                         BTM_BLE_PRIVATE_ADDR_INT);
+
+        btm_ble_multi_adv_enq_op_q(BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR, p_inst->inst_id, 0);
+    }
+    return rt;
+}
+
+/*******************************************************************************
+**
+** Function         btm_ble_multi_adv_gen_rpa_cmpl
+**
+** Description      RPA generation completion callback for each adv instance. Will
+**                  continue write the new RPA into controller.
+**
+** Returns          none.
+**
+*******************************************************************************/
+void btm_ble_multi_adv_gen_rpa_cmpl(tBTM_RAND_ENC *p, tBTM_BLE_MULTI_ADV_INST *p_inst )
+{
+#if (SMP_INCLUDED == TRUE)
+    tBTM_LE_RANDOM_CB *p_cb = &btm_cb.ble_ctr_cb.addr_mgnt_cb;
+    tSMP_ENC    output;
+
+    BTM_TRACE_EVENT1 ("btm_ble_multi_adv_gen_rpa_cmpl inst_id = %d", p_inst->inst_id);
+    if (p)
+    {
+        p->param_buf[2] &= (~BLE_RESOLVE_ADDR_MASK);
+        p->param_buf[2] |= BLE_RESOLVE_ADDR_MSB;
+
+        p_inst->rpa[2] = p->param_buf[0];
+        p_inst->rpa[1] = p->param_buf[1];
+        p_inst->rpa[0] = p->param_buf[2];
+
+        if (!SMP_Encrypt(btm_cb.devcb.id_keys.irk, BT_OCTET16_LEN, p->param_buf, 3, &output))
+        {
+            BTM_TRACE_DEBUG0("generate random address failed");
+        }
+        else
+        {
+            /* set hash to be LSB of rpAddress */
+            p_inst->rpa[5] = output.param_buf[0];
+            p_inst->rpa[4] = output.param_buf[1];
+            p_inst->rpa[3] = output.param_buf[2];
+
+            if (p_inst->inst_id != 0)
+            {
+                /* set it to controller */
+                btm_ble_multi_adv_write_rpa(p_inst, p_inst->rpa);
+            }
+        }
+    }
+#endif
+}
+
+/*******************************************************************************
+**
+** Function         btm_ble_multi_adv_gen_rpa_cmpl1
+**
+** Description      RPA generation completion callback for each adv instance. Will
+**                  continue write the new RPA into controller.
+**
+** Returns          none.
+**
+*******************************************************************************/
+static void btm_ble_multi_adv_gen_rpa_cmpl_1(tBTM_RAND_ENC *p)
+{
+    btm_ble_multi_adv_gen_rpa_cmpl(p, &btm_multi_adv_cb.adv_inst[0]);
+}
+
+/*******************************************************************************
+**
+** Function         btm_ble_multi_adv_gen_rpa_cmpl2
+**
+** Description      RPA generation completion callback for each adv instance. Will
+**                  continue write the new RPA into controller.
+**
+** Returns          none.
+**
+*******************************************************************************/
+static void btm_ble_multi_adv_gen_rpa_cmpl_2(tBTM_RAND_ENC *p)
+{
+    btm_ble_multi_adv_gen_rpa_cmpl(p, &btm_multi_adv_cb.adv_inst[1]);
+}
+
+/*******************************************************************************
+**
+** Function         btm_ble_multi_adv_gen_rpa_cmpl3
+**
+** Description      RPA generation completion callback for each adv instance. Will
+**                  continue write the new RPA into controller.
+**
+** Returns          none.
+**
+*******************************************************************************/
+static void btm_ble_multi_adv_gen_rpa_cmpl_3(tBTM_RAND_ENC *p)
+{
+    btm_ble_multi_adv_gen_rpa_cmpl(p, &btm_multi_adv_cb.adv_inst[2]);
+}
+
+/*******************************************************************************
+**
+** Function         btm_ble_multi_adv_gen_rpa_cmpl4
+**
+** Description      RPA generation completion callback for each adv instance. Will
+**                  continue write the new RPA into controller.
+**
+** Returns          none.
+**
+*******************************************************************************/
+static void btm_ble_multi_adv_gen_rpa_cmpl_4(tBTM_RAND_ENC *p)
+{
+    btm_ble_multi_adv_gen_rpa_cmpl(p, &btm_multi_adv_cb.adv_inst[3]);
+}
+/*******************************************************************************
+**
+** Function         btm_ble_multi_adv_configure_rpa
+**
+** Description      This function set the random address for the adv instance
+**
+** Parameters       advertise parameters used for this instance.
+**
+** Returns          none
+**
+*******************************************************************************/
+void btm_ble_multi_adv_configure_rpa (tBTM_BLE_MULTI_ADV_INST *p_inst)
+{
+    btm_gen_resolvable_private_addr((void *)p_inst->p_rpa_cback);
+}
+
+/*******************************************************************************
+**
+** Function         btm_ble_multi_adv_reenable
+**
+** Description      This function re-enable adv instance upon a connection establishment.
+**
+** Parameters       advertise parameters used for this instance.
+**
+** Returns          none.
+**
+*******************************************************************************/
+void btm_ble_multi_adv_reenable(UINT8 inst_id)
+{
+    tBTM_BLE_MULTI_ADV_INST *p_inst = &btm_multi_adv_cb.adv_inst[inst_id - 1];
+
+    if (p_inst->inst_id != 0)
+    {
+        if (p_inst->adv_evt != BTM_BLE_CONNECT_DIR_EVT)
+            btm_ble_enable_multi_adv (TRUE, p_inst->inst_id, 0);
+        else
+          /* mark directed adv as disabled if adv has been stopped */
+        {
+            (p_inst->p_cback)(BTM_BLE_MULTI_ADV_DISABLE_EVT,p_inst->inst_id,p_inst->p_ref,0);
+             p_inst->inst_id = 0;
+        }
+     }
+}
+
+/*******************************************************************************
+**
+** Function         BTM_BleEnableAdvInstance
+**
+** Description      This function enable a Multi-ADV instance with the specified
+**                  adv parameters
+**
+** Parameters       p_params: pointer to the adv parameter structure, set as default
+**                            adv parameter when the instance is enabled.
+**                  p_cback: callback function for the adv instance.
+**                  p_ref:  reference data attach to the adv instance to be enabled.
+**
+** Returns          status
+**
+*******************************************************************************/
+tBTM_STATUS BTM_BleEnableAdvInstance (tBTM_BLE_ADV_PARAMS *p_params,
+                                      tBTM_BLE_MULTI_ADV_CBACK *p_cback,void *p_ref)
+{
+    UINT8 i;
+    tBTM_STATUS rt = BTM_NO_RESOURCES;
+    tBTM_BLE_MULTI_ADV_INST *p_inst = &btm_multi_adv_cb.adv_inst[0];
+
+    BTM_TRACE_EVENT0("BTM_BleEnableAdvInstance called");
+
+    if (btm_multi_adv_cb.adv_inst_max == 0)
+    {
+        BTM_TRACE_ERROR0("Controller does not support Multi ADV");
+        return BTM_ERR_PROCESSING;
+    }
+
+    for (i = 0; i < BTM_BLE_MULTI_ADV_MAX; i ++, p_inst++)
+    {
+        if (p_inst->inst_id == 0)
+        {
+            p_inst->inst_id = i + 1;
+
+            /* configure adv parameter */
+            if (p_params)
+                btm_ble_multi_adv_set_params(p_inst, p_params, 0);
+
+            /* enable adv */
+            BTM_TRACE_EVENT1("btm_ble_enable_multi_adv being called with inst_id:%d",
+                p_inst->inst_id);
+            if ((rt = btm_ble_enable_multi_adv (TRUE, p_inst->inst_id, BTM_BLE_MULTI_ADV_ENB_EVT))
+                == BTM_CMD_STARTED)
+            {
+                p_inst->p_cback = p_cback;
+                p_inst->p_ref   = p_ref;
+            }
+            else
+            {
+                p_inst->inst_id = 0;
+                BTM_TRACE_ERROR0("BTM_BleEnableAdvInstance failed, no resources");
+            }
+            break;
+        }
+    }
+    return rt;
+}
+
+/*******************************************************************************
+**
+** Function         BTM_BleUpdateAdvInstParam
+**
+** Description      This function update a Multi-ADV instance with the specified
+**                  adv parameters.
+**
+** Parameters       inst_id: adv instance ID
+**                  p_params: pointer to the adv parameter structure.
+**
+** Returns          status
+**
+*******************************************************************************/
+tBTM_STATUS BTM_BleUpdateAdvInstParam (UINT8 inst_id, tBTM_BLE_ADV_PARAMS *p_params)
+{
+    tBTM_STATUS rt = BTM_ILLEGAL_VALUE;
+    tBTM_BLE_MULTI_ADV_INST *p_inst = &btm_multi_adv_cb.adv_inst[inst_id - 1];
+
+    BTM_TRACE_EVENT1("BTM_BleUpdateAdvInstParam called with inst_id:%d", inst_id);
+
+    if (btm_multi_adv_cb.adv_inst_max == 0)
+    {
+        BTM_TRACE_ERROR0("Controller does not support Multi ADV");
+        return BTM_ERR_PROCESSING;
+    }
+
+    if (inst_id <= BTM_BLE_MULTI_ADV_MAX &&
+        inst_id != BTM_BLE_MULTI_ADV_DEFAULT_STD &&
+        p_params != NULL)
+    {
+        if (p_inst->inst_id == 0)
+        {
+            BTM_TRACE_DEBUG1("adv instance %d is not active", inst_id);
+            return BTM_WRONG_MODE;
+        }
+        else
+            btm_ble_enable_multi_adv(FALSE, inst_id, 0);
+
+        btm_ble_multi_adv_set_params(p_inst, p_params, 0);
+
+        rt = btm_ble_enable_multi_adv(TRUE, inst_id, BTM_BLE_MULTI_ADV_PARAM_EVT);
+    }
+    return rt;
+}
+
+/*******************************************************************************
+**
+** Function         BTM_BleCfgAdvInstData
+**
+** Description      This function configure a Multi-ADV instance with the specified
+**                  adv data or scan response data.
+**
+** Parameters       inst_id: adv instance ID
+**                  is_scan_rsp: is this scacn response, if no set as adv data.
+**                  data_mask: adv data mask.
+**                  p_data: pointer to the adv data structure.
+**
+** Returns          status
+**
+*******************************************************************************/
+tBTM_STATUS BTM_BleCfgAdvInstData (UINT8 inst_id, BOOLEAN is_scan_rsp,
+                                    tBTM_BLE_AD_MASK data_mask,
+                                    tBTM_BLE_ADV_DATA *p_data)
+{
+    UINT8       param[BTM_BLE_MULTI_ADV_WRITE_DATA_LEN], *pp = param;
+    UINT8       sub_code = (is_scan_rsp) ?
+                           BTM_BLE_MULTI_ADV_WRITE_SCAN_RSP_DATA : BTM_BLE_MULTI_ADV_WRITE_ADV_DATA;
+    UINT8       *p_len;
+    tBTM_STATUS rt;
+    UINT8 *pp_temp = (UINT8*)(param + BTM_BLE_MULTI_ADV_WRITE_DATA_LEN -1);
+
+    if (btm_multi_adv_cb.adv_inst_max == 0)
+    {
+        BTM_TRACE_ERROR0("Controller does not support Multi ADV");
+        return BTM_ERR_PROCESSING;
+    }
+
+    BTM_TRACE_EVENT1("BTM_BleCfgAdvInstData called with inst_id:%d", inst_id);
+    if (inst_id > BTM_BLE_MULTI_ADV_MAX || inst_id == BTM_BLE_MULTI_ADV_DEFAULT_STD)
+        return BTM_ILLEGAL_VALUE;
+
+    memset(param, 0, BTM_BLE_MULTI_ADV_WRITE_DATA_LEN);
+
+    UINT8_TO_STREAM(pp, sub_code);
+    p_len = pp ++;
+    btm_ble_build_adv_data(&data_mask, &pp, p_data);
+    *p_len = (UINT8)(pp - param - 2);
+    UINT8_TO_STREAM(pp_temp, inst_id);
+
+    if ((rt = BTM_VendorSpecificCommand (HCI_BLE_MULTI_ADV_OCF,
+                                    (UINT8)BTM_BLE_MULTI_ADV_WRITE_DATA_LEN,
+                                    param,
+                                    btm_ble_multi_adv_vsc_cmpl_cback))
+                                     == BTM_CMD_STARTED)
+    {
+        btm_ble_multi_adv_enq_op_q(sub_code, inst_id, BTM_BLE_MULTI_ADV_DATA_EVT);
+    }
+    return rt;
+}
+
+/*******************************************************************************
+**
+** Function         BTM_BleDisableAdvInstance
+**
+** Description      This function disables a Multi-ADV instance.
+**
+** Parameters       inst_id: adv instance ID
+**
+** Returns          status
+**
+*******************************************************************************/
+tBTM_STATUS BTM_BleDisableAdvInstance (UINT8 inst_id)
+{
+     tBTM_STATUS rt = BTM_ILLEGAL_VALUE;
+
+     BTM_TRACE_EVENT1("BTM_BleDisableAdvInstance with inst_id:%d", inst_id);
+
+     if (btm_multi_adv_cb.adv_inst_max == 0)
+     {
+         BTM_TRACE_ERROR0("Controller does not support Multi ADV");
+         return BTM_ERR_PROCESSING;
+     }
+
+     if (inst_id <= BTM_BLE_MULTI_ADV_MAX && inst_id != BTM_BLE_MULTI_ADV_DEFAULT_STD)
+     {
+         if ((rt = btm_ble_enable_multi_adv(FALSE, inst_id, BTM_BLE_MULTI_ADV_DISABLE_EVT))
+            == BTM_CMD_STARTED)
+         {
+            btu_stop_timer(&btm_multi_adv_cb.adv_inst[inst_id-1].raddr_timer_ent);
+
+            btm_multi_adv_cb.adv_inst[inst_id-1].inst_id = 0;
+         }
+     }
+    return rt;
+}
+/*******************************************************************************
+**
+** Function         btm_ble_multi_adv_vse_cback
+**
+** Description      VSE callback for multi adv events.
+**
+** Returns
+**
+*******************************************************************************/
+void btm_ble_multi_adv_vse_cback(UINT8 len, UINT8 *p)
+{
+    UINT8   sub_event;
+    UINT8   adv_inst, reason, conn_handle;
+
+    /* Check if this is a BLE RSSI vendor specific event */
+    STREAM_TO_UINT8(sub_event, p);
+    len--;
+
+    BTM_TRACE_EVENT1("btm_ble_multi_adv_vse_cback called with event:%d", sub_event);
+    if ((sub_event == HCI_VSE_SUBCODE_BLE_MULTI_ADV_ST_CHG) && (len>=4))
+    {
+        STREAM_TO_UINT8(adv_inst, p);
+        STREAM_TO_UINT8(reason, p);
+        STREAM_TO_UINT16(conn_handle, p);
+
+        if (adv_inst <= BTM_BLE_MULTI_ADV_MAX && adv_inst !=  BTM_BLE_MULTI_ADV_DEFAULT_STD)
+        {
+            BTM_TRACE_EVENT0("btm_ble_multi_adv_reenable called");
+            btm_ble_multi_adv_reenable(adv_inst);
+        }
+        /* re-enable connectibility */
+        else if (adv_inst == BTM_BLE_MULTI_ADV_DEFAULT_STD)
+        {
+            if (btm_cb.ble_ctr_cb.inq_var.connectable_mode == BTM_BLE_CONNECTABLE)
+            {
+                btm_ble_set_connectability ( btm_cb.ble_ctr_cb.inq_var.connectable_mode );
+
+            }
+        }
+
+    }
+
+}
+/*******************************************************************************
+**
+** Function         btm_ble_multi_adv_init
+**
+** Description      This function initialize the multi adv control block.
+**
+** Parameters
+**
+** Returns          status
+**
+*******************************************************************************/
+void btm_ble_multi_adv_init(void)
+{
+    UINT8 i;
+
+    memset(&btm_multi_adv_cb, 0, sizeof(tBTM_BLE_MULTI_ADV_CB));
+
+    for (i = 0; i < BTM_BLE_MULTI_ADV_MAX; i ++)
+        btm_multi_adv_cb.adv_inst[i].p_rpa_cback = btm_ble_multi_adv_rpa_cmpl[i];
+
+    BTM_RegisterForVSEvents(btm_ble_multi_adv_vse_cback, TRUE);
+}
+#endif
+#endif
+
index 0bfaea9..2bb8434 100644 (file)
@@ -26,6 +26,7 @@
 #define BTM_BLE_API_H
 
 #include "btm_api.h"
+#include "gki.h"
 
 #define CHNL_MAP_LEN    5
 typedef UINT8 tBTM_BLE_CHNL_MAP[CHNL_MAP_LEN];
@@ -184,14 +185,6 @@ typedef void (tBTM_RAND_ENC_CB) (tBTM_RAND_ENC *p1);
 #define BTM_BLE_POLICY_ALLOW_CONN           0x02    /* relevant to advertiser */
 #define BTM_BLE_POLICY_WHITE_ALL            0x03    /* relevant to both */
 
-typedef struct
-{
-    UINT8               adv_int_min;
-    UINT8               adv_int_max;
-    tBTM_BLE_CHNL_MAP   chnl_map;
-
-}tBTM_BLE_ADV_PARAMS;
-
 /* ADV data flag bit definition used for BTM_BLE_AD_TYPE_FLAG */
 #define BTM_BLE_LIMIT_DISC_FLAG         (0x01 << 0)
 #define BTM_BLE_GEN_DISC_FLAG           (0x01 << 1)
@@ -199,7 +192,6 @@ typedef struct
 /* 4.1 spec adv flag for simultaneous BR/EDR+LE connection support */
 #define BTM_BLE_DMT_CONTROLLER_SPT      (0x01 << 3)
 #define BTM_BLE_DMT_HOST_SPT            (0x01 << 4)
-
 #define BTM_BLE_NON_LIMIT_DISC_FLAG     (0x00 )         /* lowest bit unset */
 #define BTM_BLE_ADV_FLAG_MASK           (BTM_BLE_LIMIT_DISC_FLAG | BTM_BLE_BREDR_NOT_SPT | BTM_BLE_GEN_DISC_FLAG)
 #define BTM_BLE_LIMIT_DISC_MASK         (BTM_BLE_LIMIT_DISC_FLAG )
@@ -219,8 +211,8 @@ typedef struct
 #define BTM_BLE_AD_BIT_RANDOM_ADDR       (0x00000001 << 13)
 #define BTM_BLE_AD_BIT_SERVICE_32        (0x00000001 << 4)
 #define BTM_BLE_AD_BIT_SERVICE_32SOL     (0x00000001 << 14)
-
 #define BTM_BLE_AD_BIT_PROPRIETARY     (0x00000001 << 15)
+#define BTM_BLE_AD_BIT_SERVICE_128      (0x00000001 << 16)      /*128-bit Service UUIDs*/
 
 typedef  UINT32  tBTM_BLE_AD_MASK;
 
@@ -252,6 +244,14 @@ typedef  UINT32  tBTM_BLE_AD_MASK;
 #define BTM_BLE_AD_TYPE_MANU            HCI_EIR_MANUFACTURER_SPECIFIC_TYPE      /* 0xff */
 typedef UINT8   tBTM_BLE_AD_TYPE;
 
+/* adv tx power level */
+#define BTM_BLE_ADV_TX_POWER_MIN        0           /* minimum tx power */
+#define BTM_BLE_ADV_TX_POWER_LOW        1           /* low tx power     */
+#define BTM_BLE_ADV_TX_POWER_MID        2           /* middle tx power  */
+#define BTM_BLE_ADV_TX_POWER_UPPER      3           /* upper tx power   */
+#define BTM_BLE_ADV_TX_POWER_MAX        4           /* maximum tx power */
+typedef UINT8 tBTM_BLE_ADV_TX_POWER;
+
 /* slave preferred connection interval range */
 typedef struct
 {
@@ -268,7 +268,7 @@ typedef struct
     UINT16      *p_uuid;
 }tBTM_BLE_SERVICE;
 
-/* Service tag supported in the device */
+/* 32 bits Service supported in the device */
 typedef struct
 {
     UINT8       num_service;
@@ -276,6 +276,12 @@ typedef struct
     UINT32      *p_uuid;
 }tBTM_BLE_32SERVICE;
 
+/* 128 bits Service supported in the device */
+typedef struct
+{
+    BOOLEAN     list_cmpl;
+    UINT8       uuid128[MAX_UUID_SIZE];
+}tBTM_BLE_128SERVICE;
 
 typedef struct
 {
@@ -291,7 +297,6 @@ typedef struct
     UINT8      *p_val;
 }tBTM_BLE_SERVICE_DATA;
 
-
 typedef struct
 {
     UINT8       adv_type;
@@ -307,17 +312,75 @@ typedef struct
 
 typedef struct
 {
-    tBTM_BLE_SERVICE_DATA   *p_service_data;
-    tBTM_BLE_MANU           manu;           /* manufactuer data */
     tBTM_BLE_INT_RANGE      int_range;      /* slave prefered conn interval range */
-    tBTM_BLE_SERVICE        services;       /* services */
-    tBTM_BLE_32SERVICE      service_32b;     /* 32 bits Service UUID */
-    tBTM_BLE_32SERVICE      sol_service_32b;    /* List of 32 bit Service Solicitation UUIDs */
+    tBTM_BLE_MANU           *p_manu;           /* manufactuer data */
+    tBTM_BLE_SERVICE        *p_services;       /* services */
+    tBTM_BLE_128SERVICE     *p_services_128b;  /* 128 bits service */
+    tBTM_BLE_32SERVICE      *p_service_32b;     /* 32 bits Service UUID */
+    tBTM_BLE_SERVICE        *p_sol_services;    /* 16 bits services Solicitation UUIDs */
+    tBTM_BLE_32SERVICE      *p_sol_service_32b;    /* List of 32 bit Service Solicitation UUIDs */
+    tBTM_BLE_128SERVICE     *p_sol_service_128b;    /* List of 128 bit Service Solicitation UUIDs */
+    tBTM_BLE_PROPRIETARY    *p_proprietary;
+    tBTM_BLE_SERVICE_DATA   *p_service_data;    /* service data */
     UINT16                  appearance;
     UINT8                   flag;
-    tBTM_BLE_PROPRIETARY    *p_proprietary;
+    UINT8                   tx_power;
 }tBTM_BLE_ADV_DATA;
 
+#ifndef BTM_BLE_MULTI_ADV_MAX
+#define BTM_BLE_MULTI_ADV_MAX   4
+#endif
+
+#define BTM_BLE_MULTI_ADV_INVALID   0
+
+#define BTM_BLE_MULTI_ADV_ENB_EVT           1
+#define BTM_BLE_MULTI_ADV_DISABLE_EVT       2
+#define BTM_BLE_MULTI_ADV_PARAM_EVT         3
+#define BTM_BLE_MULTI_ADV_DATA_EVT          4
+typedef UINT8 tBTM_BLE_MULTI_ADV_EVT;
+
+#define BTM_BLE_MULTI_ADV_DEFAULT_STD 0
+
+typedef struct
+{
+    UINT16          adv_int_min;
+    UINT16          adv_int_max;
+    UINT8           adv_type;
+    tBTM_BLE_ADV_CHNL_MAP channel_map;
+    tBTM_BLE_AFP    adv_filter_policy;
+    tBTM_BLE_ADV_TX_POWER tx_power;
+}tBTM_BLE_ADV_PARAMS;
+
+typedef struct
+{
+    UINT8   sub_code[BTM_BLE_MULTI_ADV_MAX];
+    UINT8   inst_id[BTM_BLE_MULTI_ADV_MAX];
+    UINT8   pending_idx;
+    UINT8   next_idx;
+}tBTM_BLE_MULTI_ADV_OPQ;
+
+typedef void (tBTM_BLE_MULTI_ADV_CBACK)(tBTM_BLE_MULTI_ADV_EVT evt, UINT8 inst_id,
+                void *p_ref, tBTM_STATUS status);
+
+typedef struct
+{
+    UINT8                       inst_id;
+    UINT8                       adv_evt;
+    BD_ADDR                     rpa;
+    TIMER_LIST_ENT              raddr_timer_ent;
+    void                        *p_rpa_cback;
+    tBTM_BLE_MULTI_ADV_CBACK    *p_cback;
+    void                        *p_ref;
+}tBTM_BLE_MULTI_ADV_INST;
+
+typedef struct
+{
+    tBTM_BLE_MULTI_ADV_INST adv_inst[BTM_BLE_MULTI_ADV_MAX];
+    tBTM_BLE_MULTI_ADV_OPQ  op_q;
+    UINT8 adv_inst_max;         /* max adv instance supported in controller */
+}tBTM_BLE_MULTI_ADV_CB;
+
+
 /* These are the fields returned in each device adv packet.  It
 ** is returned in the results callback if registered.
 */
@@ -913,6 +976,74 @@ BTM_API extern BOOLEAN BTM_UseLeLink (BD_ADDR bd_addr);
 *******************************************************************************/
 BTM_API extern tBTM_STATUS BTM_BleStackEnable (BOOLEAN enable);
 
+/*******************************************************************************/
+/*                          Multi ADV API                                      */
+/*******************************************************************************
+**
+** Function         BTM_BleEnableAdvInstance
+**
+** Description      This function enable a Multi-ADV instance with the specified
+**                  adv parameters
+**
+** Parameters       p_params: pointer to the adv parameter structure, set as default
+**                            adv parameter when the instance is enabled.
+**                  p_cback: callback function for the adv instance.
+**                  p_ref:  reference data attach to the adv instance to be enabled.
+**
+** Returns          status
+**
+*******************************************************************************/
+BTM_API extern tBTM_STATUS BTM_BleEnableAdvInstance (tBTM_BLE_ADV_PARAMS *p_params,
+                                      tBTM_BLE_MULTI_ADV_CBACK *p_cback,
+                                      void *p_ref);
+
+/*******************************************************************************
+**
+** Function         BTM_BleUpdateAdvInstParam
+**
+** Description      This function update a Multi-ADV instance with the specififed
+**                  adv parameters.
+**
+** Parameters       inst_id: adv instance ID
+**                  p_params: pointer to the adv parameter structure.
+**
+** Returns          status
+**
+*******************************************************************************/
+BTM_API extern tBTM_STATUS BTM_BleUpdateAdvInstParam (UINT8 inst_id, tBTM_BLE_ADV_PARAMS *p_params);
+
+/*******************************************************************************
+**
+** Function         BTM_BleCfgAdvInstData
+**
+** Description      This function configure a Multi-ADV instance with the specified
+**                  adv data or scan response data.
+**
+** Parameters       inst_id: adv instance ID
+**                  is_scan_rsp: is this scacn response, if no set as adv data.
+**                  data_mask: adv data mask.
+**                  p_data: pointer to the adv data structure.
+**
+** Returns          status
+**
+*******************************************************************************/
+BTM_API extern tBTM_STATUS BTM_BleCfgAdvInstData (UINT8 inst_id, BOOLEAN is_scan_rsp,
+                                    tBTM_BLE_AD_MASK data_mask,
+                                    tBTM_BLE_ADV_DATA *p_data);
+
+/*******************************************************************************
+**
+** Function         BTM_BleDisableAdvInstance
+**
+** Description      This function disable a Multi-ADV instance.
+**
+** Parameters       inst_id: adv instance ID
+**
+** Returns          status
+**
+*******************************************************************************/
+BTM_API extern tBTM_STATUS BTM_BleDisableAdvInstance (UINT8 inst_id);
+
 #ifdef __cplusplus
 }
 #endif
index 14ae893..4c0b604 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- *  Copyright (C) 1999-2012 Broadcom Corporation
+ *  Copyright (C) 1999-2014 Broadcom Corporation
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
 #define HCI_BLE_TRANSMITTER_TEST        (0x001E | HCI_GRP_BLE_CMDS)
 #define HCI_BLE_TEST_END                (0x001F | HCI_GRP_BLE_CMDS)
 
+/* LE Get Vendor Capabilities Command OCF */
+#define HCI_BLE_VENDOR_CAP_OCF    (0x0153 | HCI_GRP_VENDOR_SPECIFIC)
+
+/* Multi adv OCF */
+#define HCI_BLE_MULTI_ADV_OCF     (0x0154 | HCI_GRP_VENDOR_SPECIFIC)
+
+/* subcode for multi adv feature */
+#define BTM_BLE_MULTI_ADV_SET_PARAM                     0x01
+#define BTM_BLE_MULTI_ADV_WRITE_ADV_DATA                0x02
+#define BTM_BLE_MULTI_ADV_WRITE_SCAN_RSP_DATA           0x03
+#define BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR               0x04
+#define BTM_BLE_MULTI_ADV_ENB                           0x05
+
+/* multi adv VSE subcode */
+#define HCI_VSE_SUBCODE_BLE_MULTI_ADV_ST_CHG       0x55 /* multi adv instance state change */
+
 /* LE supported states definition */
 #define HCI_LE_ADV_STATE          0x00000001
 #define HCI_LE_SCAN_STATE         0x00000002