summaryrefslogtreecommitdiffstats
path: root/stack/btm/btm_ble_gap.c
diff options
context:
space:
mode:
Diffstat (limited to 'stack/btm/btm_ble_gap.c')
-rw-r--r--stack/btm/btm_ble_gap.c1132
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 */