From ffb3960bb05f9acb0717d213612403487e9ad433 Mon Sep 17 00:00:00 2001 From: Satya Calloji Date: Wed, 30 Apr 2014 15:55:39 -0700 Subject: [PATCH] LE Multi ADV feature BTIF and stack changes for LE multi ADV feature Change-Id: I5e009ff8cbac5fc6f92ca943c61c4faf98e4e2ce --- bta/dm/bta_dm_act.c | 89 +++- bta/dm/bta_dm_api.c | 186 +++++++- bta/dm/bta_dm_int.h | 59 ++- bta/dm/bta_dm_main.c | 4 + bta/include/bta_api.h | 149 ++++++- bta/include/bta_gatt_api.h | 5 + btif/include/btif_gatt_multi_adv_util.h | 87 ++++ btif/src/btif_gatt_client.c | 508 +++++++++++++-------- btif/src/btif_gatt_multi_adv_util.c | 540 ++++++++++++++++++++++ include/bt_target.h | 6 +- main/Android.mk | 1 + stack/Android.mk | 1 + stack/btm/btm_ble.c | 35 +- stack/btm/btm_ble_addr.c | 14 +- stack/btm/btm_ble_gap.c | 279 ++++++++++-- stack/btm/btm_ble_int.h | 14 +- stack/btm/btm_ble_multi_adv.c | 761 ++++++++++++++++++++++++++++++++ stack/include/btm_ble_api.h | 167 ++++++- stack/include/hcidefs.h | 18 +- 19 files changed, 2643 insertions(+), 280 deletions(-) create mode 100644 btif/include/btif_gatt_multi_adv_util.h create mode 100644 btif/src/btif_gatt_multi_adv_util.c create mode 100644 stack/btm/btm_ble_multi_adv.c diff --git a/bta/dm/bta_dm_act.c b/bta/dm/bta_dm_act.c index 9391d801c..ab81d0da7 100644 --- a/bta/dm/bta_dm_act.c +++ b/bta/dm/bta_dm_act.c @@ -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 diff --git a/bta/dm/bta_dm_api.c b/bta/dm/bta_dm_api.c index 89e2cce08..288e1262b 100644 --- a/bta/dm/bta_dm_api.c +++ b/bta/dm/bta_dm_api.c @@ -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 diff --git a/bta/dm/bta_dm_int.h b/bta/dm/bta_dm_int.h index 03cb45fdf..78eb83322 100644 --- a/bta/dm/bta_dm_int.h +++ b/bta/dm/bta_dm_int.h @@ -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); diff --git a/bta/dm/bta_dm_main.c b/bta/dm/bta_dm_main.c index 8f8c750d0..c68dac555 100644 --- a/bta/dm/bta_dm_main.c +++ b/bta/dm/bta_dm_main.c @@ -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) diff --git a/bta/include/bta_api.h b/bta/include/bta_api.h index b8fcddc15..2ad6a98a9 100644 --- a/bta/include/bta_api.h +++ b/bta/include/bta_api.h @@ -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 diff --git a/bta/include/bta_gatt_api.h b/bta/include/bta_gatt_api.h index 3fec4a078..80af960fe 100644 --- a/bta/include/bta_gatt_api.h +++ b/bta/include/bta_gatt_api.h @@ -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 index 000000000..2fef4499f --- /dev/null +++ b/btif/include/btif_gatt_multi_adv_util.h @@ -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 +#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 + + diff --git a/btif/src/btif_gatt_client.c b/btif/src/btif_gatt_client.c index 32f2e3f7f..2202e99f2 100644 --- a/btif/src/btif_gatt_client.c +++ b/btif/src/btif_gatt_client.c @@ -38,7 +38,7 @@ #if (defined(BLE_INCLUDED) && (BLE_INCLUDED == TRUE)) -#include "gki.h" +#include "btif_gatt_multi_adv_util.h" #include #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 index 000000000..0f206456a --- /dev/null +++ b/btif/src/btif_gatt_multi_adv_util.c @@ -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 +#include + +#define LOG_TAG "BtGatt.btif" +#if (BLE_INCLUDED == TRUE) + +#include "btif_gatt_multi_adv_util.h" +#include "btif_common.h" +#include +#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 diff --git a/include/bt_target.h b/include/bt_target.h index d8618016c..01dd1929e 100644 --- a/include/bt_target.h +++ b/include/bt_target.h @@ -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 diff --git a/main/Android.mk b/main/Android.mk index d170bfe8d..a2637da60 100644 --- a/main/Android.mk +++ b/main/Android.mk @@ -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 \ diff --git a/stack/Android.mk b/stack/Android.mk index ecc42ef28..6c1652468 100644 --- a/stack/Android.mk +++ b/stack/Android.mk @@ -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 \ diff --git a/stack/btm/btm_ble.c b/stack/btm/btm_ble.c index 9bd771a71..130aa1ccc 100644 --- a/stack/btm/btm_ble.c +++ b/stack/btm/btm_ble.c @@ -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 */ diff --git a/stack/btm/btm_ble_addr.c b/stack/btm/btm_ble_addr.c index 3c646e9a4..378470ea5 100644 --- a/stack/btm/btm_ble_addr.c +++ b/stack/btm/btm_ble_addr.c @@ -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); } /******************************************************************************* diff --git a/stack/btm/btm_ble_gap.c b/stack/btm/btm_ble_gap.c index f9bd1aa82..d70db7376 100644 --- a/stack/btm/btm_ble_gap.c +++ b/stack/btm/btm_ble_gap.c @@ -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. @@ -46,13 +46,17 @@ #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(); } /******************************************************************************* diff --git a/stack/btm/btm_ble_int.h b/stack/btm/btm_ble_int.h index f3cb77135..4553f4a90 100644 --- a/stack/btm/btm_ble_int.h +++ b/stack/btm/btm_ble_int.h @@ -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 index 000000000..24394dacd --- /dev/null +++ b/stack/btm/btm_ble_multi_adv.c @@ -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 +#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 + diff --git a/stack/include/btm_ble_api.h b/stack/include/btm_ble_api.h index 0bfaea96a..2bb84345c 100644 --- a/stack/include/btm_ble_api.h +++ b/stack/include/btm_ble_api.h @@ -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 diff --git a/stack/include/hcidefs.h b/stack/include/hcidefs.h index 14ae89351..4c0b604f0 100644 --- a/stack/include/hcidefs.h +++ b/stack/include/hcidefs.h @@ -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. @@ -334,6 +334,22 @@ #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 -- 2.11.0