diff options
Diffstat (limited to 'stack/btm/btm_ble_gap.c')
-rw-r--r-- | stack/btm/btm_ble_gap.c | 1132 |
1 files changed, 808 insertions, 324 deletions
diff --git a/stack/btm/btm_ble_gap.c b/stack/btm/btm_ble_gap.c index 39f344cfc..f9bd1aa82 100644 --- a/stack/btm/btm_ble_gap.c +++ b/stack/btm/btm_ble_gap.c @@ -37,6 +37,8 @@ #if (BLE_INCLUDED == TRUE) #include "gattdefs.h" +#include "btm_ble_int.h" + #define BTM_BLE_NAME_SHORT 0x01 #define BTM_BLE_NAME_CMPL 0x02 @@ -55,26 +57,156 @@ 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, tBLE_ADDR_TYPE *p_own_addr_type); -static tBTM_STATUS btm_ble_start_adv(void); -static tBTM_STATUS btm_ble_stop_adv(void); - +static void btm_ble_stop_observe(void); +#define BTM_BLE_INQ_RESULT 0x01 +#define BTM_BLE_OBS_RESULT 0x02 +#define BTM_BLE_SEL_CONN_RESULT 0x04 -/******************************************************************************* -** -** Function BTM_BleReset -** -** Description This function is called to reset ULP controller. -** -** Parameters None. -** -** Returns void -** -*******************************************************************************/ -void BTM_BleReset(void) +/* LE states combo bit to check */ +const UINT8 btm_le_state_combo_tbl[BTM_BLE_STATE_MAX][BTM_BLE_STATE_MAX][2] = { - btsnd_hcic_ble_reset(); -} + {/* single state support */ + {HCI_SUPP_LE_STATES_CONN_ADV_MASK, HCI_SUPP_LE_STATES_CONN_ADV_OFF}, /* conn_adv */ + {HCI_SUPP_LE_STATES_INIT_MASK, HCI_SUPP_LE_STATES_INIT_OFF}, /* init */ + {HCI_SUPP_LE_STATES_INIT_MASK, HCI_SUPP_LE_STATES_INIT_OFF}, /* master */ + {HCI_SUPP_LE_STATES_SLAVE_MASK, HCI_SUPP_LE_STATES_SLAVE_OFF}, /* slave */ + {0, 0}, /* todo: lo du dir adv, not covered ? */ + {HCI_SUPP_LE_STATES_HI_DUTY_DIR_ADV_MASK, HCI_SUPP_LE_STATES_HI_DUTY_DIR_ADV_OFF}, /* hi duty dir adv */ + {HCI_SUPP_LE_STATES_NON_CONN_ADV_MASK, HCI_SUPP_LE_STATES_NON_CONN_ADV_OFF}, /* non connectable adv */ + {HCI_SUPP_LE_STATES_PASS_SCAN_MASK, HCI_SUPP_LE_STATES_PASS_SCAN_OFF}, /* passive scan */ + {HCI_SUPP_LE_STATES_ACTIVE_SCAN_MASK, HCI_SUPP_LE_STATES_ACTIVE_SCAN_OFF}, /* active scan */ + {HCI_SUPP_LE_STATES_SCAN_ADV_MASK, HCI_SUPP_LE_STATESSCAN_ADV_OFF} /* scanable adv */ + }, + { /* conn_adv =0 */ + {0, 0}, /* conn_adv */ + {HCI_SUPP_LE_STATES_CONN_ADV_INIT_MASK, HCI_SUPP_LE_STATES_CONN_ADV_INIT_OFF}, /* init: 32 */ + {HCI_SUPP_LE_STATES_CONN_ADV_MASTER_MASK, HCI_SUPP_LE_STATES_CONN_ADV_MASTER_OFF}, /* master: 35 */ + {HCI_SUPP_LE_STATES_CONN_ADV_SLAVE_MASK, HCI_SUPP_LE_STATES_CONN_ADV_SLAVE_OFF}, /* slave: 38,*/ + {0, 0}, /* lo du dir adv */ + {0, 0}, /* hi duty dir adv */ + {0, 0}, /* non connectable adv */ + {HCI_SUPP_LE_STATES_CONN_ADV_PASS_SCAN_MASK, HCI_SUPP_LE_STATES_CONN_ADV_PASS_SCAN_OFF}, /* passive scan */ + {HCI_SUPP_LE_STATES_CONN_ADV_ACTIVE_SCAN_MASK, HCI_SUPP_LE_STATES_CONN_ADV_ACTIVE_SCAN_OFF}, /* active scan */ + {0, 0} /* scanable adv */ + }, + { /* init */ + {HCI_SUPP_LE_STATES_CONN_ADV_INIT_MASK, HCI_SUPP_LE_STATES_CONN_ADV_INIT_OFF}, /* conn_adv: 32 */ + {0, 0}, /* init */ + {HCI_SUPP_LE_STATES_INIT_MASTER_MASK, HCI_SUPP_LE_STATES_INIT_MASTER_OFF}, /* master 28 */ + {HCI_SUPP_LE_STATES_INIT_MASTER_SLAVE_MASK, HCI_SUPP_LE_STATES_INIT_MASTER_SLAVE_OFF}, /* slave 41 */ + {HCI_SUPP_LE_STATES_LO_DUTY_DIR_ADV_INIT_MASK, HCI_SUPP_LE_STATES_LO_DUTY_DIR_ADV_INIT_OFF} ,/* lo du dir adv 34 */ + {HCI_SUPP_LE_STATES_HI_DUTY_DIR_ADV_INIT_MASK, HCI_SUPP_LE_STATES_HI_DUTY_DIR_ADV_INIT_OFF}, /* hi duty dir adv 33 */ + {HCI_SUPP_LE_STATES_NON_CONN_INIT_MASK, HCI_SUPP_LE_STATES_NON_CONN_INIT_OFF}, /* non connectable adv */ + {HCI_SUPP_LE_STATES_PASS_SCAN_INIT_MASK, HCI_SUPP_LE_STATES_PASS_SCAN_INIT_OFF}, /* passive scan */ + {HCI_SUPP_LE_STATES_ACTIVE_SCAN_INIT_MASK, HCI_SUPP_LE_STATES_ACTIVE_SCAN_INIT_OFF}, /* active scan */ + {HCI_SUPP_LE_STATES_SCAN_ADV_INIT_MASK, HCI_SUPP_LE_STATES_SCAN_ADV_INIT_OFF} /* scanable adv */ + + }, + { /* master */ + {HCI_SUPP_LE_STATES_CONN_ADV_MASTER_MASK, HCI_SUPP_LE_STATES_CONN_ADV_MASTER_OFF}, /* conn_adv: 35 */ + {HCI_SUPP_LE_STATES_INIT_MASTER_MASK, HCI_SUPP_LE_STATES_INIT_MASTER_OFF}, /* init 28 */ + {HCI_SUPP_LE_STATES_INIT_MASTER_MASK, HCI_SUPP_LE_STATES_INIT_MASTER_OFF}, /* master 28 */ + {HCI_SUPP_LE_STATES_CONN_ADV_INIT_MASK, HCI_SUPP_LE_STATES_CONN_ADV_INIT_OFF}, /* slave: 32 */ + {HCI_SUPP_LE_STATES_LO_DUTY_DIR_ADV_MASTER_MASK, HCI_SUPP_LE_STATES_LO_DUTY_DIR_ADV_MASTER_OFF}, /* lo duty cycle adv 37 */ + {HCI_SUPP_LE_STATES_HI_DUTY_DIR_ADV_MASTER_MASK, HCI_SUPP_LE_STATES_HI_DUTY_DIR_ADV_MASTER_OFF}, /* hi duty cycle adv 36 */ + {HCI_SUPP_LE_STATES_NON_CONN_ADV_MASTER_MASK, HCI_SUPP_LE_STATES_NON_CONN_ADV_MASTER_OFF}, /* non connectable adv */ + {HCI_SUPP_LE_STATES_PASS_SCAN_MASTER_MASK, HCI_SUPP_LE_STATES_PASS_SCAN_MASTER_OFF}, /* passive scan */ + {HCI_SUPP_LE_STATES_ACTIVE_SCAN_MASTER_MASK, HCI_SUPP_LE_STATES_ACTIVE_SCAN_MASTER_OFF}, /* active scan */ + {HCI_SUPP_LE_STATES_SCAN_ADV_MASTER_MASK, HCI_SUPP_LE_STATES_SCAN_ADV_MASTER_OFF} /* scanable adv */ + + }, + { /* slave */ + {HCI_SUPP_LE_STATES_CONN_ADV_SLAVE_MASK, HCI_SUPP_LE_STATES_CONN_ADV_SLAVE_OFF}, /* conn_adv: 38,*/ + {HCI_SUPP_LE_STATES_INIT_MASTER_SLAVE_MASK, HCI_SUPP_LE_STATES_INIT_MASTER_SLAVE_OFF}, /* init 41 */ + {HCI_SUPP_LE_STATES_INIT_MASTER_SLAVE_MASK, HCI_SUPP_LE_STATES_INIT_MASTER_SLAVE_OFF}, /* master 41 */ + {HCI_SUPP_LE_STATES_CONN_ADV_SLAVE_MASK, HCI_SUPP_LE_STATES_CONN_ADV_SLAVE_OFF}, /* slave: 38,*/ + {HCI_SUPP_LE_STATES_LO_DUTY_DIR_ADV_SLAVE_MASK, HCI_SUPP_LE_STATES_LO_DUTY_DIR_ADV_SLAVE_OFF}, /* lo duty cycle adv 40 */ + {HCI_SUPP_LE_STATES_HI_DUTY_DIR_ADV_SLAVE_MASK, HCI_SUPP_LE_STATES_HI_DUTY_DIR_ADV_SLAVE_OFF}, /* hi duty cycle adv 39 */ + {HCI_SUPP_LE_STATES_NON_CONN_ADV_SLAVE_MASK, HCI_SUPP_LE_STATES_NON_CONN_ADV_SLAVE_OFF}, /* non connectable adv */ + {HCI_SUPP_LE_STATES_PASS_SCAN_SLAVE_MASK, HCI_SUPP_LE_STATES_PASS_SCAN_SLAVE_OFF}, /* passive scan */ + {HCI_SUPP_LE_STATES_ACTIVE_SCAN_SLAVE_MASK, HCI_SUPP_LE_STATES_ACTIVE_SCAN_SLAVE_OFF}, /* active scan */ + {HCI_SUPP_LE_STATES_SCAN_ADV_SLAVE_MASK, HCI_SUPP_LE_STATES_SCAN_ADV_SLAVE_OFF} /* scanable adv */ + + }, + { /* lo duty cycle adv */ + {0, 0}, /* conn_adv: 38,*/ + {HCI_SUPP_LE_STATES_LO_DUTY_DIR_ADV_INIT_MASK, HCI_SUPP_LE_STATES_LO_DUTY_DIR_ADV_INIT_OFF} ,/* init 34 */ + {HCI_SUPP_LE_STATES_LO_DUTY_DIR_ADV_MASTER_MASK, HCI_SUPP_LE_STATES_LO_DUTY_DIR_ADV_MASTER_OFF}, /* master 37 */ + {HCI_SUPP_LE_STATES_LO_DUTY_DIR_ADV_SLAVE_MASK, HCI_SUPP_LE_STATES_LO_DUTY_DIR_ADV_SLAVE_OFF}, /* slave: 40 */ + {0, 0}, /* lo duty cycle adv 40 */ + {0, 0}, /* hi duty cycle adv 39 */ + {0, 0}, /* non connectable adv */ + {0, 0}, /* TODO: passive scan, not covered? */ + {0, 0}, /* TODO: active scan, not covered? */ + {0, 0} /* scanable adv */ + }, + { /* hi duty cycle adv */ + {0, 0}, /* conn_adv: 38,*/ + {HCI_SUPP_LE_STATES_HI_DUTY_DIR_ADV_INIT_MASK, HCI_SUPP_LE_STATES_HI_DUTY_DIR_ADV_INIT_OFF}, /* init 33 */ + {HCI_SUPP_LE_STATES_HI_DUTY_DIR_ADV_MASTER_MASK, HCI_SUPP_LE_STATES_HI_DUTY_DIR_ADV_MASTER_OFF}, /* master 36 */ + {HCI_SUPP_LE_STATES_HI_DUTY_DIR_ADV_SLAVE_MASK, HCI_SUPP_LE_STATES_HI_DUTY_DIR_ADV_SLAVE_OFF}, /* slave: 39*/ + {0, 0}, /* lo duty cycle adv 40 */ + {0, 0}, /* hi duty cycle adv 39 */ + {0, 0}, /* non connectable adv */ + {HCI_SUPP_LE_STATES_HI_DUTY_DIR_ADV_PASS_SCAN_MASK, HCI_SUPP_LE_STATES_HI_DUTY_DIR_ADV_PASS_SCAN_OFF}, /* passive scan */ + {HCI_SUPP_LE_STATES_HI_DUTY_DIR_ADV_ACTIVE_SCAN_MASK, HCI_SUPP_LE_STATES_HI_DUTY_DIR_ADV_ACTIVE_SCAN_OFF}, /* active scan */ + {0, 0} /* scanable adv */ + }, + { /* non connectable adv */ + {0, 0}, /* conn_adv: */ + {HCI_SUPP_LE_STATES_NON_CONN_INIT_MASK, HCI_SUPP_LE_STATES_NON_CONN_INIT_OFF}, /* init */ + {HCI_SUPP_LE_STATES_NON_CONN_ADV_MASTER_MASK, HCI_SUPP_LE_STATES_NON_CONN_ADV_MASTER_OFF}, /* master */ + {HCI_SUPP_LE_STATES_NON_CONN_ADV_SLAVE_MASK, HCI_SUPP_LE_STATES_NON_CONN_ADV_SLAVE_OFF}, /* slave: */ + {0, 0}, /* lo duty cycle adv */ + {0, 0}, /* hi duty cycle adv */ + {0, 0}, /* non connectable adv */ + {HCI_SUPP_LE_STATES_NON_CONN_ADV_PASS_SCAN_MASK, HCI_SUPP_LE_STATES_NON_CONN_ADV_PASS_SCAN_OFF}, /* passive scan */ + {HCI_SUPP_LE_STATES_NON_CONN_ADV_ACTIVE_SCAN_MASK, HCI_SUPP_LE_STATES_NON_CONN_ADV_ACTIVE_SCAN_OFF}, /* active scan */ + {0, 0} /* scanable adv */ + }, + { /* passive scan */ + {HCI_SUPP_LE_STATES_CONN_ADV_PASS_SCAN_MASK, HCI_SUPP_LE_STATES_CONN_ADV_PASS_SCAN_OFF}, /* conn_adv: */ + {HCI_SUPP_LE_STATES_PASS_SCAN_INIT_MASK, HCI_SUPP_LE_STATES_PASS_SCAN_INIT_OFF}, /* init */ + {HCI_SUPP_LE_STATES_PASS_SCAN_MASTER_MASK, HCI_SUPP_LE_STATES_PASS_SCAN_MASTER_OFF}, /* master */ + {HCI_SUPP_LE_STATES_PASS_SCAN_SLAVE_MASK, HCI_SUPP_LE_STATES_PASS_SCAN_SLAVE_OFF}, /* slave: */ + {0, 0}, /* lo duty cycle adv */ + {HCI_SUPP_LE_STATES_HI_DUTY_DIR_ADV_PASS_SCAN_MASK, HCI_SUPP_LE_STATES_HI_DUTY_DIR_ADV_PASS_SCAN_OFF}, /* hi duty cycle adv */ + {HCI_SUPP_LE_STATES_NON_CONN_ADV_PASS_SCAN_MASK, HCI_SUPP_LE_STATES_NON_CONN_ADV_PASS_SCAN_OFF}, /* non connectable adv */ + {0, 0}, /* passive scan */ + {0, 0}, /* active scan */ + {HCI_SUPP_LE_STATES_SCAN_ADV_PASS_SCAN_MASK, HCI_SUPP_LE_STATES_SCAN_ADV_PASS_SCAN_OFF} /* scanable adv */ + }, + { /* active scan */ + {HCI_SUPP_LE_STATES_CONN_ADV_ACTIVE_SCAN_MASK, HCI_SUPP_LE_STATES_CONN_ADV_ACTIVE_SCAN_OFF}, /* conn_adv: */ + {HCI_SUPP_LE_STATES_ACTIVE_SCAN_INIT_MASK, HCI_SUPP_LE_STATES_ACTIVE_SCAN_INIT_OFF}, /* init */ + {HCI_SUPP_LE_STATES_ACTIVE_SCAN_MASTER_MASK, HCI_SUPP_LE_STATES_ACTIVE_SCAN_MASTER_OFF}, /* master */ + {HCI_SUPP_LE_STATES_ACTIVE_SCAN_SLAVE_MASK, HCI_SUPP_LE_STATES_ACTIVE_SCAN_SLAVE_OFF}, /* slave: */ + {0, 0}, /* lo duty cycle adv */ + {HCI_SUPP_LE_STATES_HI_DUTY_DIR_ADV_ACTIVE_SCAN_MASK, HCI_SUPP_LE_STATES_HI_DUTY_DIR_ADV_ACTIVE_SCAN_OFF}, /* hi duty cycle adv */ + {HCI_SUPP_LE_STATES_NON_CONN_ADV_ACTIVE_SCAN_MASK, HCI_SUPP_LE_STATES_NON_CONN_ADV_ACTIVE_SCAN_OFF}, /* non connectable adv */ + {0, 0}, /* TODO: passive scan */ + {0, 0}, /* TODO: active scan */ + {HCI_SUPP_LE_STATES_SCAN_ADV_ACTIVE_SCAN_MASK, HCI_SUPP_LE_STATES_SCAN_ADV_ACTIVE_SCAN_OFF} /* scanable adv */ + }, + { /* scanable adv */ + {0, 0}, /* conn_adv: */ + {HCI_SUPP_LE_STATES_SCAN_ADV_INIT_MASK, HCI_SUPP_LE_STATES_SCAN_ADV_INIT_OFF}, /* init */ + {HCI_SUPP_LE_STATES_SCAN_ADV_MASTER_MASK, HCI_SUPP_LE_STATES_SCAN_ADV_MASTER_OFF}, /* master */ + {HCI_SUPP_LE_STATES_SCAN_ADV_SLAVE_MASK, HCI_SUPP_LE_STATES_SCAN_ADV_SLAVE_OFF}, /* slave: */ + {0, 0}, /* lo duty cycle adv */ + {0, 0}, /* hi duty cycle adv */ + {0, 0}, /* non connectable adv */ + {HCI_SUPP_LE_STATES_SCAN_ADV_PASS_SCAN_MASK, HCI_SUPP_LE_STATES_SCAN_ADV_PASS_SCAN_OFF}, /* passive scan */ + {HCI_SUPP_LE_STATES_SCAN_ADV_ACTIVE_SCAN_MASK, HCI_SUPP_LE_STATES_SCAN_ADV_ACTIVE_SCAN_OFF}, /* active scan */ + {0, 0} /* scanable adv */ + } + +}; +/* check LE combo state supported */ +#define BTM_LE_STATES_SUPPORTED(x, y, z) ((x)[(z)] & (y)) + + /******************************************************************************* ** ** Function BTM_BleUpdateAdvWhitelist @@ -122,10 +254,13 @@ void BTM_BleUpdateAdvFilterPolicy(tBTM_BLE_AFP adv_policy) btm_ble_stop_adv (); if (p_cb->connectable_mode & BTM_BLE_CONNECTABLE) - p_cb->evt_type = btm_set_conn_mode_adv_init_addr(p_cb, p_addr_ptr, &init_addr_type, &p_cb->adv_addr_type); + p_cb->evt_type = btm_set_conn_mode_adv_init_addr(p_cb, p_addr_ptr, &init_addr_type, + &p_cb->adv_addr_type); - btsnd_hcic_ble_write_adv_params (p_cb->adv_interval_min, - p_cb->adv_interval_max, + btsnd_hcic_ble_write_adv_params ((UINT16)(p_cb->adv_interval_min ? p_cb->adv_interval_min : + BTM_BLE_GAP_ADV_SLOW_INT), + (UINT16)(p_cb->adv_interval_max ? p_cb->adv_interval_max : + BTM_BLE_GAP_ADV_SLOW_INT), p_cb->evt_type, p_cb->adv_addr_type, init_addr_type, @@ -155,7 +290,7 @@ tBTM_STATUS BTM_BleObserve(BOOLEAN start, UINT8 duration, tBTM_INQ_RESULTS_CB *p_results_cb, tBTM_CMPL_CB *p_cmpl_cb) { tBTM_BLE_INQ_CB *p_inq = &btm_cb.ble_ctr_cb.inq_var; - tBTM_STATUS status = BTM_NO_RESOURCES; + tBTM_STATUS status = BTM_WRONG_MODE; BTM_TRACE_EVENT1 ("BTM_BleObserve : scan_type:%d",btm_cb.btm_inq_vars.scan_type); @@ -165,63 +300,50 @@ tBTM_STATUS BTM_BleObserve(BOOLEAN start, UINT8 duration, if (start) { /* shared inquiry database, do not allow observe if any inquiry is active */ - if (btm_cb.btm_inq_vars.inq_active || p_inq->proc_mode != BTM_BLE_INQUIRY_NONE) + if (BTM_BLE_IS_OBS_ACTIVE(btm_cb.ble_ctr_cb.scan_activity)) { - /*check if an interleave scan is already in progress*/ - if(btm_cb.btm_inq_vars.scan_type == INQ_GENERAL - && btm_cb.btm_inq_vars.p_inq_results_cb != NULL) - { - BTM_TRACE_EVENT0 ("BTM_BleObserve general inq in progress, redirecting the results"); - btm_cb.btm_inq_vars.p_inq_ble_results_cb = p_results_cb; - btm_cb.btm_inq_vars.p_inq_ble_cmpl_cb = p_cmpl_cb; - return BTM_SUCCESS; - } - else - return BTM_BUSY; + BTM_TRACE_ERROR0("Observe Already Active"); + return status; } - btm_cb.btm_inq_vars.scan_type = INQ_LE_OBSERVE; - btm_cb.btm_inq_vars.p_inq_ble_results_cb = p_results_cb; - btm_cb.btm_inq_vars.p_inq_ble_cmpl_cb = p_cmpl_cb; - p_inq->scan_type = (p_inq->scan_type == BTM_BLE_SCAN_MODE_NONE) ? BTM_BLE_SCAN_MODE_ACTI: p_inq->scan_type; - /* allow config scanning type */ - if (btsnd_hcic_ble_set_scan_params (p_inq->scan_type, + btm_cb.ble_ctr_cb.p_obs_results_cb = p_results_cb; + btm_cb.ble_ctr_cb.p_obs_cmpl_cb = p_cmpl_cb; + status = BTM_CMD_STARTED; + + /* scan is not started */ + if (!BTM_BLE_IS_SCAN_ACTIVE(btm_cb.ble_ctr_cb.scan_activity)) + { + p_inq->scan_type = (p_inq->scan_type == BTM_BLE_SCAN_MODE_NONE) ? BTM_BLE_SCAN_MODE_ACTI: p_inq->scan_type; + /* allow config scanning type */ + btsnd_hcic_ble_set_scan_params (p_inq->scan_type, (UINT16)(!p_inq->scan_interval ? BTM_BLE_GAP_DISC_SCAN_INT : p_inq->scan_interval), (UINT16)(!p_inq->scan_window ? BTM_BLE_GAP_DISC_SCAN_WIN : p_inq->scan_window), - BLE_ADDR_PUBLIC, - BTM_BLE_DEFAULT_SFP)) /* assume observe always not using white list */ + btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type, + BTM_BLE_DEFAULT_SFP); /* assume observe always not using white list */ + + status = btm_ble_start_scan(BTM_BLE_DUPLICATE_DISABLE); + } + if (status == BTM_CMD_STARTED) { - /* start scan, disable duplicate filtering */ - if (btsnd_hcic_ble_set_scan_enable (BTM_BLE_SCAN_ENABLE, BTM_BLE_DUPLICATE_DISABLE)) - { - status = BTM_SUCCESS; - p_inq->proc_mode = BTM_BLE_OBSERVE; - btm_cb.btm_inq_vars.inq_active |= BTM_LE_OBSERVE_ACTIVE; + btm_cb.ble_ctr_cb.scan_activity |= BTM_LE_OBSERVE_ACTIVE; - if (duration != 0) - { - /* start inquiry timer */ - btu_start_timer (&p_inq->inq_timer_ent, BTU_TTYPE_BLE_INQUIRY, duration); - } - } + if (duration != 0) + /* start observer timer */ + btu_start_timer (&btm_cb.ble_ctr_cb.obs_timer_ent, BTU_TTYPE_BLE_OBSERVE, duration); } } - else/*start = 0*/ + else if (BTM_BLE_IS_OBS_ACTIVE(btm_cb.ble_ctr_cb.scan_activity)) { - if(btm_cb.btm_inq_vars.scan_type == INQ_GENERAL) - { - //Dont stop the scan. Just nullify the cbs - btm_cb.btm_inq_vars.p_inq_ble_results_cb = NULL; - btm_cb.btm_inq_vars.p_inq_ble_cmpl_cb = NULL; - } - else if (p_inq->proc_mode == BTM_BLE_OBSERVE) - { - btm_cb.btm_inq_vars.inq_active &= ~BTM_LE_OBSERVE_ACTIVE; - btm_ble_stop_scan(); - } + status = BTM_CMD_STARTED; + btm_ble_stop_observe(); + } + else + { + BTM_TRACE_ERROR0("Observe not active"); } return status; + } /******************************************************************************* @@ -255,8 +377,10 @@ tBTM_STATUS BTM_BleBroadcast(BOOLEAN start) if (start && p_cb->adv_mode == BTM_BLE_ADV_DISABLE) { /* update adv params */ - if (!btsnd_hcic_ble_write_adv_params ((UINT16)(p_cb->adv_interval_min ? p_cb->adv_interval_min : BTM_BLE_GAP_ADV_INT), - (UINT16)(p_cb->adv_interval_max ? p_cb->adv_interval_max : BTM_BLE_GAP_ADV_INT), + if (!btsnd_hcic_ble_write_adv_params ((UINT16)(p_cb->adv_interval_min ? p_cb->adv_interval_min : + BTM_BLE_GAP_ADV_INT), + (UINT16)(p_cb->adv_interval_max ? p_cb->adv_interval_max : + BTM_BLE_GAP_ADV_INT), evt_type, p_addr_cb->own_addr_type, p_cb->direct_bda.type, @@ -270,7 +394,7 @@ tBTM_STATUS BTM_BleBroadcast(BOOLEAN start) status = btm_ble_start_adv (); } - else if (!start && p_cb->adv_mode == BTM_BLE_ADV_ENABLE) + else if (!start) { status = btm_ble_stop_adv(); } @@ -278,7 +402,7 @@ tBTM_STATUS BTM_BleBroadcast(BOOLEAN start) { status = BTM_WRONG_MODE; BTM_TRACE_ERROR2("Can not %s Broadcast, device %s in Broadcast mode", - (start ? "Start" : "Stop"), (start ? "alerady" :"not")); + (start ? "Start" : "Stop"), (start ? "already" :"not")); } return status; } @@ -309,7 +433,42 @@ void BTM_RegisterScanReqEvt(tBTM_BLE_SCAN_REQ_CBACK *p_scan_req_cback) #endif } -#if BTM_BLE_PRIVACY_SPT == TRUE +#if BLE_PRIVACY_SPT == TRUE +/******************************************************************************* +** +** Function BTM_BleConfigPrivacy +** +** Description This function is called to enable or disable the privacy in +** LE channel of the local device. +** +** Parameters enable: TRUE to enable it; FALSE to disable it. +** +** Returns void +** +*******************************************************************************/ +void BTM_BleConfigPrivacy(BOOLEAN enable) +{ + tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb; + + BTM_TRACE_EVENT0 (" BTM_BleConfigPrivacy"); + + if (p_cb->privacy != enable) + { + p_cb->privacy = enable; + + if (p_cb->privacy) + { + /* generate resolvable private address */ + btm_gen_resolvable_private_addr(); + } + else /* if privacy disabled, always use public address */ + { + p_cb->addr_mgnt_cb.own_addr_type = BLE_ADDR_PUBLIC; + } + } +} + + /******************************************************************************* ** ** Function btm_ble_resolve_random_addr_on_adv @@ -486,11 +645,13 @@ static UINT8 btm_set_conn_mode_adv_init_addr(tBTM_BLE_INQ_CB *p_cb, { UINT8 evt_type; + UNUSED(p_own_addr_type); + if ( p_cb->directed_conn) { /* direct adv mode does not have privacy if privacy - is not enabled or no reconn addr config */ - *p_own_addr_type = BLE_ADDR_PUBLIC; + is not enabled or no reconn addr config */ + *p_init_addr_type = p_cb->direct_bda.type; memcpy(p_addr_ptr, p_cb->direct_bda.bda, BD_ADDR_LEN); evt_type = BTM_BLE_CONNECT_DIR_EVT; @@ -498,6 +659,16 @@ static UINT8 btm_set_conn_mode_adv_init_addr(tBTM_BLE_INQ_CB *p_cb, else /* undirect adv mode */ { evt_type = BTM_BLE_CONNECT_EVT; + +#if BLE_PRIVACY_SPT == TRUE + /* may need to reset random address if privacy is enabled */ + if (btm_cb.ble_ctr_cb.privacy && /* own addr_type is random */ + !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(); + } +#endif } return evt_type; @@ -704,7 +875,7 @@ tBTM_STATUS BTM_BleWriteAdvData(tBTM_BLE_AD_MASK data_mask, tBTM_BLE_ADV_DATA *p { tBTM_BLE_LOCAL_ADV_DATA *p_cb_data = &btm_cb.ble_ctr_cb.inq_var.adv_data; UINT8 *p; - UINT16 mask = data_mask; + tBTM_BLE_AD_MASK mask = data_mask; BTM_TRACE_EVENT0 ("BTM_BleWriteAdvData "); @@ -930,7 +1101,99 @@ static UINT8 *btm_ble_build_adv_data(tBTM_BLE_AD_MASK *p_data_mask, UINT8 **p_ds return p_flag; } +/******************************************************************************* +** +** Function btm_ble_select_adv_interval +** +** Description select adv interval based on device mode +** +** Returns void +** +*******************************************************************************/ +void btm_ble_select_adv_interval(tBTM_BLE_INQ_CB *p_cb, UINT8 evt_type, UINT16 *p_adv_int_min, UINT16 *p_adv_int_max) +{ + if (p_cb->adv_interval_min && p_cb->adv_interval_max) + { + *p_adv_int_min = p_cb->adv_interval_min; + *p_adv_int_max = p_cb->adv_interval_max; + } + else + { + switch (evt_type) + { + case BTM_BLE_CONNECT_EVT: + *p_adv_int_min = *p_adv_int_max = BTM_BLE_GAP_ADV_FAST_INT_1; + break; + + case BTM_BLE_NON_CONNECT_EVT: + case BTM_BLE_DISCOVER_EVT: + *p_adv_int_min = *p_adv_int_max = BTM_BLE_GAP_ADV_FAST_INT_2; + break; + /* connectable directed event */ + case BTM_BLE_CONNECT_DIR_EVT: + *p_adv_int_min = BTM_BLE_GAP_ADV_DIR_MIN_INT; + *p_adv_int_max = BTM_BLE_GAP_ADV_DIR_MAX_INT; + break; + + default: + *p_adv_int_min = *p_adv_int_max = BTM_BLE_GAP_ADV_SLOW_INT; + break; + } + } + return; +} +/******************************************************************************* +** +** Function btm_ble_set_adv_flag +** +** Description Set adv flag in adv data. +** +** Returns void +** +*******************************************************************************/ +void btm_ble_set_adv_flag(UINT16 connect_mode, UINT16 disc_mode) +{ + UINT8 flag = 0, old_flag = 0; + tBTM_BLE_LOCAL_ADV_DATA *p_adv_data = &btm_cb.ble_ctr_cb.inq_var.adv_data; + + if (p_adv_data->p_flags != NULL) + flag = old_flag = *(p_adv_data->p_flags); + + /* BR/EDR non-discoverable , non-connectable */ + if ((disc_mode & BTM_DISCOVERABLE_MASK) == 0 && + (connect_mode & BTM_CONNECTABLE_MASK) == 0) + flag |= BTM_BLE_BREDR_NOT_SPT; + else + flag &= ~BTM_BLE_BREDR_NOT_SPT; + + /* if local controller support, mark both controller and host support in flag */ + if (HCI_SIMUL_LE_BREDR_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_0])) + flag |= (BTM_BLE_DMT_CONTROLLER_SPT|BTM_BLE_DMT_HOST_SPT); + else + flag &= ~(BTM_BLE_DMT_CONTROLLER_SPT|BTM_BLE_DMT_HOST_SPT); + + BTM_TRACE_ERROR1("disc_mode %04x", disc_mode); + /* update discoverable flag */ + if (disc_mode & BTM_BLE_LIMITED_DISCOVERABLE) + { + flag &= ~BTM_BLE_GEN_DISC_FLAG; + flag |= BTM_BLE_LIMIT_DISC_FLAG ; + } + else if (disc_mode & BTM_BLE_GENERAL_DISCOVERABLE) + { + flag |= BTM_BLE_GEN_DISC_FLAG; + flag &= ~BTM_BLE_LIMIT_DISC_FLAG; + } + else /* remove all discoverable flags */ + { + flag &= ~(BTM_BLE_LIMIT_DISC_FLAG|BTM_BLE_GEN_DISC_FLAG); + } + if (flag != old_flag) + { + btm_ble_update_adv_flag(flag); + } +} /******************************************************************************* ** ** Function btm_ble_set_discoverability @@ -947,7 +1210,6 @@ tBTM_STATUS btm_ble_set_discoverability(UINT16 combined_mode) tBTM_LE_RANDOM_CB *p_addr_cb = &btm_cb.ble_ctr_cb.addr_mgnt_cb; tBTM_BLE_INQ_CB *p_cb = &btm_cb.ble_ctr_cb.inq_var; UINT16 mode = (combined_mode & BTM_BLE_DISCOVERABLE_MASK); - UINT8 flag = 0; UINT8 new_mode = BTM_BLE_ADV_ENABLE; UINT8 evt_type = (p_cb->connectable_mode == BTM_BLE_NON_CONNECTABLE) ? \ ((p_cb->scan_rsp) ? BTM_BLE_DISCOVER_EVT : BTM_BLE_NON_CONNECT_EVT )\ @@ -955,7 +1217,8 @@ tBTM_STATUS btm_ble_set_discoverability(UINT16 combined_mode) tBTM_STATUS status = BTM_SUCCESS; BD_ADDR p_addr_ptr= {0}; tBLE_ADDR_TYPE init_addr_type = BLE_ADDR_PUBLIC, - own_addr_type = p_addr_cb->own_addr_type;; + own_addr_type = p_addr_cb->own_addr_type; + UINT16 adv_int_min, adv_int_max; BTM_TRACE_EVENT2 ("btm_ble_set_discoverability mode=0x%0x combined_mode=0x%x", mode, combined_mode); @@ -963,56 +1226,28 @@ tBTM_STATUS btm_ble_set_discoverability(UINT16 combined_mode) if (mode > BTM_BLE_MAX_DISCOVERABLE) return(BTM_ILLEGAL_VALUE); - p_cb->br_edr_supported_flag |= (combined_mode & BTM_DISCOVERABLE_MASK); - p_cb->discoverable_mode = mode; + btm_ble_set_adv_flag (btm_cb.btm_inq_vars.connectable_mode, combined_mode); - if (!p_cb->br_edr_supported_flag) - { - flag = BTM_BLE_BREDR_NOT_SPT; - BTM_TRACE_DEBUG1("btm_ble_set_discoverability (BREDR not sup)flag=0x%x",flag); - } + evt_type = btm_set_conn_mode_adv_init_addr(p_cb, p_addr_ptr, &init_addr_type, &own_addr_type); - BTM_TRACE_DEBUG1 ("br_edr_supported=0x%x", p_cb->br_edr_supported_flag); + if (p_cb->connectable_mode == BTM_BLE_NON_CONNECTABLE && mode == BTM_BLE_NON_DISCOVERABLE) + new_mode = BTM_BLE_ADV_DISABLE; - if (mode == BTM_BLE_LIMITED_DISCOVERABLE || mode == BTM_BLE_GENERAL_DISCOVERABLE) - { - BTM_TRACE_EVENT0 ("mode == BTM_BLE_LIMITED_DISCOVERABLE "); - /* write ADV data with limited disc flag */ - if (mode == BTM_BLE_LIMITED_DISCOVERABLE) - flag |= BTM_BLE_LIMIT_DISC_FLAG ; - else - flag |= BTM_BLE_GEN_DISC_FLAG; - } - else /* non-discoverable */ - { - BTM_TRACE_EVENT0 ("mode == BTM_BLE_NON_DISCOVERABLE "); + btm_ble_select_adv_interval(p_cb, evt_type, &adv_int_min, &adv_int_max); - if (p_cb->connectable_mode == BTM_BLE_NON_CONNECTABLE) - { - p_cb->br_edr_supported_flag = 0; - - BTM_TRACE_EVENT0 ("always disable adv in non-discoverable non-connectable mode if no scan rsp "); - if (!p_cb->scan_rsp ) - new_mode = BTM_BLE_ADV_DISABLE; - - } - else - { - p_cb->evt_type = btm_set_conn_mode_adv_init_addr(p_cb, p_addr_ptr, &init_addr_type, &own_addr_type); - } - } - btm_ble_update_adv_flag(flag); + btu_stop_timer(&p_cb->fast_adv_timer); /* update adv params if start advertising */ BTM_TRACE_EVENT2 ("evt_type=0x%x p-cb->evt_type=0x%x ", evt_type, p_cb->evt_type); + if (new_mode == BTM_BLE_ADV_ENABLE && - (evt_type != p_cb->evt_type ||p_cb->adv_addr_type != own_addr_type)) + (evt_type != p_cb->evt_type ||p_cb->adv_addr_type != own_addr_type || !p_cb->fast_adv_on)) { btm_ble_stop_adv(); /* update adv params */ - if (!btsnd_hcic_ble_write_adv_params ((UINT16)(p_cb->adv_interval_min ? p_cb->adv_interval_min : BTM_BLE_GAP_ADV_INT), - (UINT16)(p_cb->adv_interval_max ? p_cb->adv_interval_max : BTM_BLE_GAP_ADV_INT), + if (!btsnd_hcic_ble_write_adv_params (adv_int_min, + adv_int_max, evt_type, own_addr_type, init_addr_type, @@ -1036,11 +1271,18 @@ tBTM_STATUS btm_ble_set_discoverability(UINT16 combined_mode) else status = btm_ble_stop_adv(); } + if (p_cb->adv_mode == BTM_BLE_ADV_ENABLE) + { + p_cb->fast_adv_on = TRUE; + /* start initial GAP mode adv timer */ + btu_start_timer (&p_cb->fast_adv_timer, BTU_TTYPE_BLE_GAP_FAST_ADV, + BTM_BLE_GAP_FAST_ADV_TOUT); + } /* set up stop advertising timer */ if (status == BTM_SUCCESS && mode == BTM_BLE_LIMITED_DISCOVERABLE) { - BTM_TRACE_EVENT1 ("start timer for limited disc mode duration=%d (30 secs)", BTM_BLE_GAP_LIM_TOUT); + BTM_TRACE_EVENT1 ("start timer for limited disc mode duration=%d (180 secs)", BTM_BLE_GAP_LIM_TOUT); /* start Tgap(lim_timeout) */ btu_start_timer (&p_cb->inq_timer_ent, BTU_TTYPE_BLE_GAP_LIM_DISC, BTM_BLE_GAP_LIM_TOUT); @@ -1064,57 +1306,39 @@ tBTM_STATUS btm_ble_set_connectability(UINT16 combined_mode) tBTM_LE_RANDOM_CB *p_addr_cb = &btm_cb.ble_ctr_cb.addr_mgnt_cb; tBTM_BLE_INQ_CB *p_cb = &btm_cb.ble_ctr_cb.inq_var; UINT16 mode = (combined_mode & BTM_BLE_CONNECTABLE_MASK); - UINT8 cur_flag = 0; - UINT8 cur_br_edr_not_sup_flag; - UINT8 new_flag; UINT8 new_mode = BTM_BLE_ADV_ENABLE; UINT8 evt_type = (p_cb->scan_rsp) ? BTM_BLE_DISCOVER_EVT: BTM_BLE_NON_CONNECT_EVT; tBTM_STATUS status = BTM_SUCCESS; BD_ADDR p_addr_ptr = {0}; tBLE_ADDR_TYPE init_addr_type = BLE_ADDR_PUBLIC, own_addr_type = p_addr_cb->own_addr_type; + UINT16 adv_int_min, adv_int_max; BTM_TRACE_EVENT2 ("btm_ble_set_connectability mode=0x%0x combined_mode=0x%x", mode, combined_mode); + /*** Check mode parameter ***/ if (mode > BTM_BLE_MAX_CONNECTABLE) return(BTM_ILLEGAL_VALUE); - if (btm_cb.ble_ctr_cb.inq_var.adv_data.p_flags) - cur_flag = *btm_cb.ble_ctr_cb.inq_var.adv_data.p_flags ; - cur_br_edr_not_sup_flag = (cur_flag & ((UINT8) BTM_BLE_BREDR_NOT_SPT)); - p_cb->br_edr_supported_flag |= ((combined_mode & BTM_CONNECTABLE_MASK) << 4); - if (p_cb->br_edr_supported_flag && cur_br_edr_not_sup_flag) - { - new_flag = cur_flag & ((UINT8) (~BTM_BLE_BREDR_NOT_SPT)); - BTM_TRACE_EVENT2 ("new flag=0x%x cur flag=0x%x",new_flag, cur_flag); - btm_ble_update_adv_flag(new_flag); - } p_cb->connectable_mode = mode; - if (mode == BTM_BLE_NON_CONNECTABLE) - { - if (p_cb->discoverable_mode == BTM_BLE_NON_DISCOVERABLE) - { - p_cb->br_edr_supported_flag = 0; - BTM_TRACE_EVENT0 ("always disable adv in non-discoverable non-connectable mode with no scan rsp"); - if(!p_cb->scan_rsp) - new_mode = BTM_BLE_ADV_DISABLE; + btm_ble_set_adv_flag (combined_mode, btm_cb.btm_inq_vars.discoverable_mode); - } - } - else /* connectable */ - { - evt_type = btm_set_conn_mode_adv_init_addr(p_cb, p_addr_ptr, &init_addr_type, &own_addr_type); - } + evt_type = btm_set_conn_mode_adv_init_addr(p_cb, p_addr_ptr, &init_addr_type, &own_addr_type); + + if (mode == BTM_BLE_NON_CONNECTABLE && p_cb->discoverable_mode == BTM_BLE_NON_DISCOVERABLE) + new_mode = BTM_BLE_ADV_DISABLE; + btm_ble_select_adv_interval(p_cb, evt_type, &adv_int_min, &adv_int_max); + + btu_stop_timer(&p_cb->fast_adv_timer); /* update adv params if needed */ - if ((p_cb->evt_type != evt_type || p_cb->adv_addr_type != p_addr_cb->own_addr_type) - && new_mode == BTM_BLE_ADV_ENABLE) + if ((p_cb->evt_type != evt_type || p_cb->adv_addr_type != p_addr_cb->own_addr_type || !p_cb->fast_adv_on)) { btm_ble_stop_adv(); - if (!btsnd_hcic_ble_write_adv_params ((UINT16)(p_cb->adv_interval_min ? p_cb->adv_interval_min : BTM_BLE_GAP_ADV_INT), - (UINT16)(p_cb->adv_interval_max ? p_cb->adv_interval_max : BTM_BLE_GAP_ADV_INT), + if (!btsnd_hcic_ble_write_adv_params (adv_int_min, + adv_int_max, evt_type, own_addr_type, init_addr_type, @@ -1132,24 +1356,22 @@ tBTM_STATUS btm_ble_set_connectability(UINT16 combined_mode) /* update advertising mode */ if (status == BTM_SUCCESS && new_mode != p_cb->adv_mode) { - if (btsnd_hcic_ble_set_adv_enable (new_mode)) - { - status = BTM_SUCCESS; - - p_cb->adv_mode = new_mode; - - if (p_cb->adv_mode == BTM_BLE_ADV_ENABLE && - p_cb->afp != AP_SCAN_CONN_ALL) - btm_cb.ble_ctr_cb.wl_state |= BTM_BLE_WL_ADV; - else - btm_cb.ble_ctr_cb.wl_state &= ~BTM_BLE_WL_ADV; - - } + if (new_mode == BTM_BLE_ADV_ENABLE) + status = btm_ble_start_adv(); + else + status = btm_ble_stop_adv(); + } + if (p_cb->adv_mode == BTM_BLE_ADV_ENABLE) + { + p_cb->fast_adv_on = TRUE; + /* start initial GAP mode adv timer */ + btu_start_timer (&p_cb->fast_adv_timer, BTU_TTYPE_BLE_GAP_FAST_ADV, + BTM_BLE_GAP_FAST_ADV_TOUT); } - return status; } + /******************************************************************************* ** ** Function btm_ble_start_inquiry @@ -1171,24 +1393,32 @@ tBTM_STATUS btm_ble_set_connectability(UINT16 combined_mode) *******************************************************************************/ tBTM_STATUS btm_ble_start_inquiry (UINT8 mode, UINT8 duration) { - tBTM_STATUS status = BTM_NO_RESOURCES; - tBTM_BLE_INQ_CB *p_inq = &btm_cb.ble_ctr_cb.inq_var; + tBTM_STATUS status = BTM_CMD_STARTED; + tBTM_BLE_CB *p_ble_cb = &btm_cb.ble_ctr_cb; + tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars; - BTM_TRACE_DEBUG2("btm_ble_start_inquiry: mode = %02x inq_active = %d", mode, btm_cb.btm_inq_vars.inq_active); + BTM_TRACE_DEBUG2("btm_ble_start_inquiry: mode = %02x inq_active = 0x%02x", mode, btm_cb.btm_inq_vars.inq_active); - if (p_inq->proc_mode != BTM_BLE_INQUIRY_NONE) + /* if selective connection is active, or inquiry is already active, reject it */ + if (BTM_BLE_IS_INQ_ACTIVE(p_ble_cb->scan_activity) || + BTM_BLE_IS_SEL_CONN_ACTIVE (p_ble_cb->scan_activity)) { - BTM_TRACE_ERROR0("LE scan is active, can not start inquiry"); + BTM_TRACE_ERROR0("LE Inquiry is active, can not start inquiry"); return(BTM_BUSY); } - btm_update_scanner_filter_policy(SP_ADV_ALL); + if (!BTM_BLE_IS_SCAN_ACTIVE(p_ble_cb->scan_activity)) + { + btm_update_scanner_filter_policy(SP_ADV_ALL); + status = btm_ble_start_scan(BTM_BLE_DUPLICATE_DISABLE); + } - /* start scan, already enable duplicate filtering */ - if (btsnd_hcic_ble_set_scan_enable (BTM_BLE_SCAN_ENABLE, BTM_BLE_DUPLICATE_DISABLE)) + if (status == BTM_CMD_STARTED) { - status = BTM_CMD_STARTED; - p_inq->proc_mode = mode; + p_inq->inq_active |= mode; + p_ble_cb->scan_activity |= mode; + + BTM_TRACE_DEBUG1("btm_ble_start_inquiry inq_active = 0x%02x", p_inq->inq_active); if (duration != 0) { @@ -1198,6 +1428,7 @@ tBTM_STATUS btm_ble_start_inquiry (UINT8 mode, UINT8 duration) } return status; + } /******************************************************************************* @@ -1508,68 +1739,54 @@ void btm_ble_cache_adv_data(tBTM_INQ_RESULTS *p_cur, UINT8 data_len, UINT8 *p, U ** Returns void ** *******************************************************************************/ -BOOLEAN btm_ble_is_discoverable(BD_ADDR bda, UINT8 evt_type, UINT8 *p) +UINT8 btm_ble_is_discoverable(BD_ADDR bda, UINT8 evt_type, UINT8 *p) { - BOOLEAN is_discoverable = FALSE; - UINT8 *p_flag, flag = 0; + UINT8 *p_flag, flag = 0, rt = 0; UINT8 data_len; tBTM_INQ_PARMS *p_cond = &btm_cb.btm_inq_vars.inqparms; + tBTM_BLE_INQ_CB *p_le_inq_cb = &btm_cb.ble_ctr_cb.inq_var; - STREAM_TO_UINT8 (data_len, p); + UNUSED(p); /* for observer, always "discoverable */ - if (btm_cb.ble_ctr_cb.inq_var.proc_mode == BTM_BLE_OBSERVE || - (btm_cb.ble_ctr_cb.inq_var.proc_mode == BTM_BLE_SELECT_SCAN && - btm_cb.ble_ctr_cb.bg_conn_type == BTM_BLE_CONN_SELECTIVE)) - return TRUE; + if (BTM_BLE_IS_OBS_ACTIVE(btm_cb.ble_ctr_cb.scan_activity)) + rt |= BTM_BLE_OBS_RESULT; + + if (BTM_BLE_IS_SEL_CONN_ACTIVE(btm_cb.ble_ctr_cb.scan_activity) && + (evt_type == BTM_BLE_CONNECT_EVT || evt_type == BTM_BLE_CONNECT_DIR_EVT)) + rt |= BTM_BLE_SEL_CONN_RESULT; /* does not match filter condition */ if (p_cond->filter_cond_type == BTM_FILTER_COND_BD_ADDR && memcmp(bda, p_cond->filter_cond.bdaddr_cond, BD_ADDR_LEN) != 0) { BTM_TRACE_DEBUG0("BD ADDR does not meet filter condition"); - return FALSE; - } - - /* scan response does not include the flag */ - if (evt_type == BTM_BLE_SCAN_RSP_EVT) - return FALSE; - - if (data_len > BTM_BLE_ADV_DATA_LEN_MAX) - { - BTM_TRACE_WARNING1("ADV data too long %d. discard", data_len); - return FALSE; + return rt; } - if (data_len != 0) + if (p_le_inq_cb->adv_len != 0) { - if ((p_flag = BTM_CheckAdvData(p, BTM_BLE_AD_TYPE_FLAG, &data_len)) != NULL) + if ((p_flag = BTM_CheckAdvData(p_le_inq_cb->adv_data_cache, + BTM_BLE_AD_TYPE_FLAG, &data_len)) != NULL) { flag = * p_flag; - if ((btm_cb.ble_ctr_cb.inq_var.proc_mode == BTM_BLE_GENERAL_INQUIRY) && + if ((btm_cb.btm_inq_vars.inq_active & BTM_BLE_GENERAL_INQUIRY) && (flag & (BTM_BLE_LIMIT_DISC_FLAG|BTM_BLE_GEN_DISC_FLAG)) != 0) { BTM_TRACE_DEBUG0("Find Generable Discoverable device"); - is_discoverable = TRUE; + rt |= BTM_BLE_INQ_RESULT; } - else if (btm_cb.ble_ctr_cb.inq_var.proc_mode == BTM_BLE_LIMITED_INQUIRY && + else if (btm_cb.btm_inq_vars.inq_active & BTM_BLE_LIMITED_INQUIRY && (flag & BTM_BLE_LIMIT_DISC_FLAG) != 0) { BTM_TRACE_DEBUG0("Find limited discoverable device"); - is_discoverable = TRUE; + rt |= BTM_BLE_INQ_RESULT; } - } } - - if (!is_discoverable) - { - BTM_TRACE_ERROR1("discoverable flag not desired: %d", flag); - } - - return is_discoverable; + return rt; } /******************************************************************************* @@ -1742,7 +1959,7 @@ void btm_ble_process_adv_pkt (UINT8 *p_data) BD_ADDR bda; UINT8 evt_type = 0, *p = p_data; UINT8 addr_type = 0; -#if (defined BTM_BLE_PRIVACY_SPT && BTM_BLE_PRIVACY_SPT == TRUE) +#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE) BOOLEAN match = FALSE; #endif @@ -1765,15 +1982,12 @@ void btm_ble_process_adv_pkt (UINT8 *p_data) /* Only process the results if the inquiry is still active */ - if ((btm_cb.btm_inq_vars.inq_active & BTM_LE_SCAN_ACTIVE_MASK) == 0 && - (btm_cb.ble_ctr_cb.bg_conn_type != BTM_BLE_CONN_SELECTIVE || - /* or selective auto connection is active */ - btm_cb.ble_ctr_cb.p_select_cback == NULL)) + if (!BTM_BLE_IS_SCAN_ACTIVE(btm_cb.ble_ctr_cb.scan_activity)) return; BTM_TRACE_DEBUG6("btm_ble_process_adv_pkt:bda= %0x:%0x:%0x:%0x:%0x:%0x", bda[0],bda[1],bda[2],bda[3],bda[4],bda[5]); -#if (defined BTM_BLE_PRIVACY_SPT && BTM_BLE_PRIVACY_SPT == TRUE) +#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE) #if SMP_INCLUDED == TRUE /* always do RRA resolution on host */ if (!match && BTM_BLE_IS_RESOLVE_BDA(bda)) @@ -1803,13 +2017,12 @@ void btm_ble_process_adv_pkt (UINT8 *p_data) static void btm_ble_process_adv_pkt_cont(BD_ADDR bda, UINT8 addr_type, UINT8 evt_type, UINT8 *p) { tINQ_DB_ENT *p_i; - BOOLEAN to_report = FALSE; - BOOLEAN to_report_LE = TRUE; //var for reporting to LE observe tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars; tBTM_INQ_RESULTS_CB *p_inq_results_cb = p_inq->p_inq_results_cb; - tBTM_INQ_RESULTS_CB *p_inq_ble_results_cb = p_inq->p_inq_ble_results_cb; + tBTM_INQ_RESULTS_CB *p_obs_results_cb = btm_cb.ble_ctr_cb.p_obs_results_cb; tBTM_BLE_INQ_CB *p_le_inq_cb = &btm_cb.ble_ctr_cb.inq_var; - BTM_TRACE_DEBUG2("btm_ble_process_adv_pkt_cont: addr_type: %d, evt_type: %d", addr_type, evt_type); + BOOLEAN update = TRUE; + UINT8 result = 0; p_i = btm_inq_db_find (bda); @@ -1817,26 +2030,23 @@ static void btm_ble_process_adv_pkt_cont(BD_ADDR bda, UINT8 addr_type, UINT8 evt if (btm_inq_find_bdaddr(bda)) { /* never been report as an LE device */ - if ((p_i && + if (p_i && (!(p_i->inq_info.results.device_type & BT_DEVICE_TYPE_BLE) || /* scan repsonse to be updated */ (!p_i->scan_rsp))) - || - btm_cb.ble_ctr_cb.inq_var.proc_mode == BTM_BLE_OBSERVE) { - BTM_TRACE_DEBUG0("update new BLE information "); - to_report = TRUE; + update = TRUE; + } + else if (BTM_BLE_IS_OBS_ACTIVE(btm_cb.ble_ctr_cb.scan_activity)) + { + update = FALSE; } else { - to_report = FALSE; + /* if yes, skip it */ + return; /* assumption: one result per event */ } } - else /* not been processed in this round */ - { - to_report = TRUE; - } - /* If existing entry, use that, else get a new one (possibly reusing the oldest) */ if (p_i == NULL) { @@ -1846,25 +2056,22 @@ static void btm_ble_process_adv_pkt_cont(BD_ADDR bda, UINT8 addr_type, UINT8 evt } else return; - - if (to_report && btm_ble_is_discoverable(bda, evt_type, p)) - { - to_report = TRUE; - } - else - { - BTM_TRACE_ERROR0("discard adv pkt"); - to_report = FALSE; - } } else if (p_i->inq_count != p_inq->inq_counter) /* first time seen in this inquiry */ { p_inq->inq_cmpl_info.num_resp++; } /* update the LE device information in inquiry database */ - to_report_LE = btm_ble_update_inq_result(p_i, addr_type, evt_type, p); - if (to_report) - to_report = to_report_LE; + if (!btm_ble_update_inq_result(p_i, addr_type, evt_type, p)) + return; + + if ((result = btm_ble_is_discoverable(bda, evt_type, p)) == 0) + { + BTM_TRACE_ERROR0("discard adv pkt"); + return; + } + if (!update) + result &= ~BTM_BLE_INQ_RESULT; #if BTM_USE_INQ_RESULTS_FILTER == TRUE /* If the number of responses found and limited, issue a cancel inquiry */ if (p_inq->inqparms.max_resps && @@ -1882,8 +2089,7 @@ static void btm_ble_process_adv_pkt_cont(BD_ADDR bda, UINT8 addr_type, UINT8 evt (p_inq->inq_active & BTM_PERIODIC_INQUIRY_ACTIVE) == 0) btsnd_hcic_inq_cancel(); - /* stop LE scan now */ - btm_ble_stop_scan(); + btm_ble_stop_inquiry(); #if BTM_BUSY_LEVEL_CHANGE_INCLUDED == TRUE btm_acl_update_busy_level (BTM_BLI_INQ_DONE_EVT); @@ -1891,28 +2097,54 @@ static void btm_ble_process_adv_pkt_cont(BD_ADDR bda, UINT8 addr_type, UINT8 evt } } #endif - - BTM_TRACE_DEBUG2("btm_ble_process_adv_pkt_cont: to_report =%d, to_report_le=%d", - to_report, to_report_LE); /* background connection in selective connection mode */ if (btm_cb.ble_ctr_cb.bg_conn_type == BTM_BLE_CONN_SELECTIVE) { - if (p_i->inq_info.results.device_type == BT_DEVICE_TYPE_BLE && - (evt_type == BTM_BLE_CONNECT_EVT || evt_type == BTM_BLE_CONNECT_DIR_EVT)) + if (result & BTM_BLE_SEL_CONN_RESULT) btm_send_sel_conn_callback(bda, evt_type, p, addr_type); else { BTM_TRACE_DEBUG0("None LE device, can not initiate selective connection"); } } - else if (to_report || to_report_LE) + else { - if(p_inq_results_cb && to_report) + if (p_inq_results_cb && (result & BTM_BLE_INQ_RESULT)) + { (p_inq_results_cb)((tBTM_INQ_RESULTS *) &p_i->inq_info.results, p_le_inq_cb->adv_data_cache); - if(p_inq_ble_results_cb && to_report_LE) - (p_inq_ble_results_cb)((tBTM_INQ_RESULTS *) &p_i->inq_info.results, - p_le_inq_cb->adv_data_cache); + } + if (p_obs_results_cb && (result & BTM_BLE_OBS_RESULT)) + { + (p_obs_results_cb)((tBTM_INQ_RESULTS *) &p_i->inq_info.results, p_le_inq_cb->adv_data_cache); + } + } +} + +/******************************************************************************* +** +** Function btm_ble_start_scan +** +** Description Start the BLE scan. +** +** Returns void +** +*******************************************************************************/ +tBTM_STATUS btm_ble_start_scan (UINT8 filter_enable) +{ + tBTM_BLE_INQ_CB *p_inq = &btm_cb.ble_ctr_cb.inq_var; + tBTM_STATUS status = BTM_CMD_STARTED; + + /* start scan, disable duplicate filtering */ + if (!btsnd_hcic_ble_set_scan_enable (BTM_BLE_SCAN_ENABLE, filter_enable)) + status = BTM_NO_RESOURCES; + else + { + if (p_inq->scan_type == BTM_BLE_SCAN_MODE_ACTI) + btm_ble_set_topology_mask(BTM_BLE_STATE_ACTIVE_SCAN_BIT); + else + btm_ble_set_topology_mask(BTM_BLE_STATE_PASSIVE_SCAN_BIT); } + return status; } /******************************************************************************* @@ -1926,44 +2158,135 @@ static void btm_ble_process_adv_pkt_cont(BD_ADDR bda, UINT8 addr_type, UINT8 evt *******************************************************************************/ void btm_ble_stop_scan(void) { - tBTM_BLE_INQ_CB *p_cb = &btm_cb.ble_ctr_cb.inq_var; - tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars; - BTM_TRACE_EVENT0 ("btm_ble_stop_scan "); - btu_stop_timer (&p_cb->inq_timer_ent); - /* Clear the inquiry callback if set */ - p_cb->scan_type = BTM_BLE_SCAN_MODE_NONE; - p_cb->proc_mode = BTM_BLE_INQUIRY_NONE; + btm_cb.ble_ctr_cb.inq_var.scan_type = BTM_BLE_SCAN_MODE_NONE; /* stop discovery now */ btsnd_hcic_ble_set_scan_enable (BTM_BLE_SCAN_DISABLE, BTM_BLE_DUPLICATE_ENABLE); + btm_update_scanner_filter_policy(SP_ADV_ALL); +} +/******************************************************************************* +** +** Function btm_ble_stop_inquiry +** +** Description Stop the BLE Inquiry. +** +** Returns void +** +*******************************************************************************/ +void btm_ble_stop_inquiry(void) +{ + tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars; + tBTM_BLE_CB *p_ble_cb = &btm_cb.ble_ctr_cb; + + btu_stop_timer (&p_ble_cb->inq_var.inq_timer_ent); + + p_ble_cb->scan_activity &= ~BTM_BLE_INQUIRY_MASK; + + /* If no more scan activity, stop LE scan now */ + if (!BTM_BLE_IS_SCAN_ACTIVE(p_ble_cb->scan_activity)) + btm_ble_stop_scan(); + /* If we have a callback registered for inquiry complete, call it */ BTM_TRACE_DEBUG2 ("BTM Inq Compl Callback: status 0x%02x, num results %d", p_inq->inq_cmpl_info.status, p_inq->inq_cmpl_info.num_resp); - btm_update_scanner_filter_policy(SP_ADV_ALL); - btm_process_inq_complete(HCI_SUCCESS, (UINT8)(p_inq->inqparms.mode & BTM_BLE_INQUIRY_MASK)); +} + +/******************************************************************************* +** +** Function btm_ble_stop_observe +** +** Description Stop the BLE Observe. +** +** Returns void +** +*******************************************************************************/ +static void btm_ble_stop_observe(void) +{ + tBTM_BLE_CB *p_ble_cb = & btm_cb.ble_ctr_cb; + tBTM_CMPL_CB *p_obs_cb = p_ble_cb->p_obs_cmpl_cb; + + btu_stop_timer (&p_ble_cb->obs_timer_ent); + p_ble_cb->scan_activity &= ~BTM_LE_OBSERVE_ACTIVE; + + p_ble_cb->p_obs_results_cb = NULL; + p_ble_cb->p_obs_cmpl_cb = NULL; + + if (!BTM_BLE_IS_SCAN_ACTIVE(p_ble_cb->scan_activity)) + btm_ble_stop_scan(); + + if (p_obs_cb) + (p_obs_cb)((tBTM_INQUIRY_CMPL *) &btm_cb.btm_inq_vars.inq_cmpl_info); +} +/******************************************************************************* +** +** Function btm_ble_adv_states_operation +** +** Description Set or clear adv states in topology mask +** +** Returns operation status. TRUE if sucessful, FALSE otherwise. +** +*******************************************************************************/ +typedef BOOLEAN (BTM_TOPOLOGY_FUNC_PTR)(tBTM_BLE_STATE_MASK); +static BOOLEAN btm_ble_adv_states_operation(BTM_TOPOLOGY_FUNC_PTR *p_handler, UINT8 adv_evt) +{ + BOOLEAN rt = FALSE; + + switch (adv_evt) + { + case BTM_BLE_CONNECT_EVT: + rt = (*p_handler)(BTM_BLE_STATE_CONN_ADV_BIT); + break; + + case BTM_BLE_NON_CONNECT_EVT: + rt = (*p_handler) (BTM_BLE_STATE_NON_CONN_ADV_BIT); + break; + case BTM_BLE_CONNECT_DIR_EVT: + rt = (*p_handler) (BTM_BLE_STATE_HI_DUTY_DIR_ADV_BIT); + break; + + case BTM_BLE_DISCOVER_EVT: + rt = (*p_handler) (BTM_BLE_STATE_SCAN_ADV_BIT); + break; + + default: + BTM_TRACE_ERROR1("unknown adv event : %d", adv_evt); + break; + } + + return rt; } + /******************************************************************************* ** ** Function btm_ble_start_adv ** -** Description Stop the BLE advertising. +** Description start the BLE advertising. ** ** Returns void ** *******************************************************************************/ -static tBTM_STATUS btm_ble_start_adv(void) +tBTM_STATUS btm_ble_start_adv(void) { tBTM_BLE_INQ_CB *p_cb = &btm_cb.ble_ctr_cb.inq_var; tBTM_STATUS rt = BTM_NO_RESOURCES; + if (!btm_ble_adv_states_operation (btm_ble_topology_check, p_cb->evt_type)) + return BTM_WRONG_MODE; + + if (p_cb->afp != AP_SCAN_CONN_ALL) + { + btm_execute_wl_dev_operation(); + btm_cb.ble_ctr_cb.wl_state |= BTM_BLE_WL_ADV; + } + if (btsnd_hcic_ble_set_adv_enable (BTM_BLE_ADV_ENABLE)) { if (p_cb->afp != AP_SCAN_CONN_ALL) @@ -1972,13 +2295,13 @@ static tBTM_STATUS btm_ble_start_adv(void) p_cb->adv_mode = BTM_BLE_ADV_ENABLE; rt = BTM_SUCCESS; - } - else - { - p_cb->adv_mode = BTM_BLE_ADV_DISABLE; - btm_cb.ble_ctr_cb.wl_state &= ~BTM_BLE_WL_ADV; - } - return rt; + } + else + { + p_cb->adv_mode = BTM_BLE_ADV_DISABLE; + btm_cb.ble_ctr_cb.wl_state &= ~BTM_BLE_WL_ADV; + } + return rt; } /******************************************************************************* ** @@ -1989,7 +2312,7 @@ static tBTM_STATUS btm_ble_start_adv(void) ** Returns void ** *******************************************************************************/ -static tBTM_STATUS btm_ble_stop_adv(void) +tBTM_STATUS btm_ble_stop_adv(void) { tBTM_BLE_INQ_CB *p_cb = &btm_cb.ble_ctr_cb.inq_var; tBTM_STATUS rt = BTM_SUCCESS; @@ -1998,18 +2321,143 @@ static tBTM_STATUS btm_ble_stop_adv(void) { if (btsnd_hcic_ble_set_adv_enable (BTM_BLE_ADV_DISABLE)) { + p_cb->fast_adv_on = FALSE; p_cb->adv_mode = BTM_BLE_ADV_DISABLE; btm_cb.ble_ctr_cb.wl_state &= ~BTM_BLE_WL_ADV; + + /* clear all adv states */ + btm_ble_clear_topology_mask (BTM_BLE_STATE_ALL_ADV_MASK); } else rt = BTM_NO_RESOURCES; } return rt; +} + + +/******************************************************************************* +** +** Function btm_ble_set_topology_mask +** +** Description set BLE topology mask +** +** Returns TRUE is request is allowed, FALSE otherwise. +** +*******************************************************************************/ +BOOLEAN btm_ble_set_topology_mask(tBTM_BLE_STATE_MASK request_state_mask) +{ + BOOLEAN rt = TRUE; + + request_state_mask &= BTM_BLE_STATE_ALL_MASK; + + btm_cb.ble_ctr_cb.cur_states |= request_state_mask; + + return rt; +} +/******************************************************************************* +** +** Function btm_ble_clear_topology_mask +** +** Description Clear BLE topology bit mask +** +** Returns TRUE is request is allowed, FALSE otherwise. +** +*******************************************************************************/ +BOOLEAN btm_ble_clear_topology_mask (tBTM_BLE_STATE_MASK request_state_mask) +{ + request_state_mask &= BTM_BLE_STATE_ALL_MASK; + + btm_cb.ble_ctr_cb.cur_states &= ~request_state_mask; + + return TRUE; +} +/******************************************************************************* +** +** Function btm_ble_update_mode_operation +** +** Description This function update the GAP role operation when a link status +** is updated. +** +** Returns void +** +*******************************************************************************/ +void btm_ble_update_mode_operation(UINT8 link_role, BD_ADDR bd_addr, BOOLEAN conn_cancel) +{ + tACL_CONN *pa = &btm_cb.acl_db[0]; + UINT16 xx; + UINT16 mask = BTM_BLE_STATE_ALL_CONN_MASK; + + UNUSED(bd_addr); + UNUSED (conn_cancel); + + if (link_role == HCI_ROLE_SLAVE) + { + btm_cb.ble_ctr_cb.inq_var.adv_mode = BTM_BLE_ADV_DISABLE; + /* clear all adv states */ + mask |= BTM_BLE_STATE_ALL_ADV_MASK; + } + + btm_ble_clear_topology_mask (mask); + + /* check the device link role maps */ + for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, pa++) + { + if (pa->in_use && pa->transport == BT_TRANSPORT_LE) + { + if (pa->link_role == HCI_ROLE_MASTER) + btm_ble_set_topology_mask (BTM_BLE_STATE_MASTER_BIT); + else + btm_ble_set_topology_mask (BTM_BLE_STATE_SLAVE_BIT); + } + } + + 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 ); + } + if (btm_ble_get_conn_st() == BLE_CONN_IDLE) + { + if (!btm_send_pending_direct_conn()) + { + btm_ble_resume_bg_conn(); + } + } } /******************************************************************************* ** +** Function btm_ble_start_slow_adv +** +** Description Restart adv with slow adv interval +** +** Returns void +** +*******************************************************************************/ +static void btm_ble_start_slow_adv (void) +{ + tBTM_BLE_INQ_CB *p_cb = &btm_cb.ble_ctr_cb.inq_var; + BD_ADDR p_addr_ptr= {0}; + + if (p_cb->adv_mode == BTM_BLE_ADV_ENABLE) + { + btm_ble_stop_adv(); + + btsnd_hcic_ble_write_adv_params (BTM_BLE_GAP_ADV_SLOW_INT, + BTM_BLE_GAP_ADV_SLOW_INT, + p_cb->evt_type, + p_cb->adv_addr_type, + btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type,/* slow adv + mode never goes into directed adv */ + p_addr_ptr, + p_cb->adv_chnl_map, + p_cb->afp); + + btm_ble_start_adv(); + } +} +/******************************************************************************* +** ** Function btm_ble_timeout ** ** Description Called when BTM BLE inquiry timer expires @@ -2019,17 +2467,23 @@ static tBTM_STATUS btm_ble_stop_adv(void) *******************************************************************************/ void btm_ble_timeout(TIMER_LIST_ENT *p_tle) { + BTM_TRACE_EVENT0 ("btm_ble_timeout"); + switch (p_tle->event) { + case BTU_TTYPE_BLE_OBSERVE: + btm_ble_stop_observe(); + break; + case BTU_TTYPE_BLE_INQUIRY: - btm_ble_stop_scan(); + btm_ble_stop_inquiry(); break; case BTU_TTYPE_BLE_GAP_LIM_DISC: /* lim_timeout expiried, limited discovery should exit now */ - btm_ble_update_adv_flag(BTM_BLE_NON_LIMIT_DISC_FLAG); + btm_cb.btm_inq_vars.discoverable_mode &= ~BTM_BLE_LIMITED_DISCOVERABLE; - btm_ble_stop_adv(); + 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: @@ -2040,6 +2494,14 @@ void btm_ble_timeout(TIMER_LIST_ENT *p_tle) } break; + case BTU_TTYPE_BLE_GAP_FAST_ADV: + /* fast adv is completed, fall back to slow adv interval */ + btm_ble_start_slow_adv(); + break; + + default: + break; + } } @@ -2058,13 +2520,13 @@ void btm_ble_timeout(TIMER_LIST_ENT *p_tle) void btm_ble_read_remote_features_complete(UINT8 *p) { tACL_CONN *p_acl_cb = &btm_cb.acl_db[0]; - UINT8 status; UINT16 handle; int xx; BTM_TRACE_EVENT0 ("btm_ble_read_remote_features_complete "); - STREAM_TO_UINT8 (status, p); + /* Skip status */ + p++; STREAM_TO_UINT16 (handle, p); /* Look up the connection by handle and copy features */ @@ -2076,6 +2538,7 @@ void btm_ble_read_remote_features_complete(UINT8 *p) break; } } + } /******************************************************************************* @@ -2120,58 +2583,6 @@ void btm_ble_dir_adv_tout(void) /******************************************************************************* ** -** Function btm_ble_update_mode_operation -** -** Description This function update the GAP role operation when a link status -** is updated. -** -** Returns void -** -*******************************************************************************/ -void btm_ble_update_mode_operation(UINT8 link_role, BD_ADDR bd_addr, BOOLEAN conn_cancel) -{ - tACL_CONN *pa = &btm_cb.acl_db[0]; - UINT16 xx; - UINT8 dev_role = link_role; - UNUSED(bd_addr); - UNUSED(conn_cancel); - - BTM_TRACE_DEBUG1("btm_ble_update_mode_operation adv_mode = %d", btm_cb.ble_ctr_cb.inq_var.adv_mode ); - - /* update periphera role operation */ - /* If we are LE connectable, check if we need to start advertising again */ - if (link_role == HCI_ROLE_UNKNOWN) - /* && btm_cb.ble_ctr_cb.inq_var.connectable_mode != BTM_BLE_NON_CONNECTABLE) */ - { - for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, pa++) - { - /* If any other LE link is up, we are still not connectable */ - if (pa->in_use && pa->is_le_link) - { - dev_role = pa->link_role; - break; - } - } - } - - if (btm_cb.ble_ctr_cb.inq_var.connectable_mode == BTM_BLE_CONNECTABLE && - (dev_role == HCI_ROLE_UNKNOWN )) /* when device has no connection, update adv here */ - /* if already in connection, no connectable adv is allowed unless scatternet is enabled */ - { - btm_ble_set_connectability ( btm_cb.ble_ctr_cb.inq_var.connectable_mode ); - } - - if (btm_ble_get_conn_st() == BLE_CONN_IDLE) - { - if (!btm_send_pending_direct_conn()) - { - btm_ble_resume_bg_conn(); - } - } -} - -/******************************************************************************* -** ** Function btm_ble_init ** ** Description Initialize the control block variable values. @@ -2186,6 +2597,7 @@ void btm_ble_init (void) BTM_TRACE_EVENT0 ("btm_ble_init "); memset(p_cb, 0, sizeof(tBTM_BLE_CB)); + p_cb->cur_states = 0; p_cb->inq_var.adv_mode = BTM_BLE_ADV_DISABLE; p_cb->inq_var.scan_type = BTM_BLE_SCAN_MODE_NONE; @@ -2201,4 +2613,76 @@ void btm_ble_init (void) p_cb->inq_var.evt_type = BTM_BLE_NON_CONNECT_EVT; } +/******************************************************************************* +** +** Function btm_ble_topology_check +** +** Description check to see requested state is supported. One state check at +** a time is supported +** +** Returns TRUE is request is allowed, FALSE otherwise. +** +*******************************************************************************/ +BOOLEAN btm_ble_topology_check(tBTM_BLE_STATE_MASK request_state_mask) +{ + BOOLEAN rt = FALSE; + UINT32 llt_mask = 0; + UINT8 *p; + + UINT8 state_offset = 0; + UINT16 cur_states = btm_cb.ble_ctr_cb.cur_states; + UINT8 mask, offset; + UINT8 request_state = 0; + + /* check only one bit is set and within valid range */ + if (request_state_mask == BTM_BLE_STATE_INVALID || + request_state_mask > BTM_BLE_STATE_SCAN_ADV_BIT || + (request_state_mask & (request_state_mask -1 )) != 0) + { + BTM_TRACE_ERROR1("illegal state requested: %d", request_state_mask); + return rt; + } + + while (request_state_mask) + { + request_state_mask >>= 1; + request_state ++; + } + + /* check if the requested state is supported or not */ + mask = btm_le_state_combo_tbl[0][request_state - 1][0]; + offset = btm_le_state_combo_tbl[0][request_state-1][1]; + + if (!BTM_LE_STATES_SUPPORTED(btm_cb.devcb.le_supported_states, mask, offset)) + { + BTM_TRACE_ERROR1("state requested not supported: %d", request_state); + return rt; + } + + rt = TRUE; + /* make sure currently active states are all supported in conjunction with the requested + state. If the bit in table is not set, the combination is not supported */ + while (cur_states != 0) + { + if (cur_states & 0x01) + { + mask = btm_le_state_combo_tbl[request_state][state_offset][0]; + offset = btm_le_state_combo_tbl[request_state][state_offset][1]; + + if (mask != 0 && offset != 0) + { + if (!BTM_LE_STATES_SUPPORTED(btm_cb.devcb.le_supported_states, mask, offset)) + { + rt = FALSE; + break; + } + } + } + cur_states >>= 1; + state_offset ++; + } + return rt; +} + + #endif /* BLE_INCLUDED */ |