summaryrefslogtreecommitdiff
path: root/emulator/le.c
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2015-07-14 22:44:47 +0200
committerMarcel Holtmann <marcel@holtmann.org>2015-07-14 23:09:34 +0200
commit81596d12b173a4d53e8fcf04a775ce3c6573d5e9 (patch)
treec4ebf47e7d85cb73196efb6e3553d3a6466f5df0 /emulator/le.c
parent8a4b1bd1bb7e34322d42c86a02734a5d09ad8be1 (diff)
downloadbluez-81596d12b173a4d53e8fcf04a775ce3c6573d5e9.tar.gz
emulator: Add support for scan window and scan interval handling
Diffstat (limited to 'emulator/le.c')
-rw-r--r--emulator/le.c73
1 files changed, 72 insertions, 1 deletions
diff --git a/emulator/le.c b/emulator/le.c
index a0d902bef..6ffa0d4a1 100644
--- a/emulator/le.c
+++ b/emulator/le.c
@@ -69,6 +69,8 @@ struct bt_le {
struct bt_phy *phy;
struct bt_crypto *crypto;
int adv_timeout_id;
+ int scan_timeout_id;
+ bool scan_window_active;
uint8_t event_mask[16];
uint16_t manufacturer;
@@ -504,6 +506,60 @@ static bool stop_adv(struct bt_le *hci)
return true;
}
+static void scan_timeout_callback(int id, void *user_data)
+{
+ struct bt_le *hci = user_data;
+ unsigned int msec;
+
+ if (hci->le_scan_window == hci->le_scan_interval ||
+ !hci->scan_window_active) {
+ msec = (hci->le_scan_window * 625) / 1000;
+ hci->scan_window_active = true;
+ } else {
+ msec = ((hci->le_scan_interval -
+ hci->le_scan_window) * 625) / 1000;
+ hci->scan_window_active = false;
+ }
+
+ if (mainloop_modify_timeout(id, msec) < 0) {
+ fprintf(stderr, "Setting scanning timeout failed\n");
+ hci->le_scan_enable = 0x00;
+ hci->scan_window_active = false;
+ }
+}
+
+static bool start_scan(struct bt_le *hci)
+{
+ unsigned int msec;
+
+ if (hci->scan_timeout_id >= 0)
+ return false;
+
+ msec = (hci->le_scan_window * 625) / 1000;
+
+ hci->scan_timeout_id = mainloop_add_timeout(msec, scan_timeout_callback,
+ hci, NULL);
+ if (hci->scan_timeout_id < 0)
+ return false;
+
+ hci->scan_window_active = true;
+
+ return true;
+}
+
+static bool stop_scan(struct bt_le *hci)
+{
+ if (hci->scan_timeout_id < 0)
+ return false;
+
+ mainloop_remove_timeout(hci->scan_timeout_id);
+ hci->scan_timeout_id = -1;
+
+ hci->scan_window_active = false;
+
+ return true;
+}
+
static void cmd_complete(struct bt_le *hci, uint16_t opcode,
const void *data, uint8_t len)
{
@@ -577,6 +633,7 @@ static void cmd_reset(struct bt_le *hci, const void *data, uint8_t size)
uint8_t status;
stop_adv(hci);
+ stop_scan(hci);
reset_defaults(hci);
status = BT_HCI_ERR_SUCCESS;
@@ -982,6 +1039,7 @@ static void cmd_le_set_scan_enable(struct bt_le *hci,
{
const struct bt_hci_cmd_le_set_scan_enable *cmd = data;
uint8_t status;
+ bool result;
/* Valid range for scan enable is 0x00 to 0x01 */
if (cmd->enable > 0x01) {
@@ -1005,6 +1063,17 @@ static void cmd_le_set_scan_enable(struct bt_le *hci,
clear_scan_cache(hci);
+ if (cmd->enable == 0x01)
+ result = start_scan(hci);
+ else
+ result = stop_scan(hci);
+
+ if (!result) {
+ cmd_status(hci, BT_HCI_ERR_UNSPECIFIED_ERROR,
+ BT_HCI_CMD_LE_SET_SCAN_ENABLE);
+ return;
+ }
+
hci->le_scan_enable = cmd->enable;
hci->le_scan_filter_dup = cmd->filter_dup;
@@ -1721,7 +1790,7 @@ static void phy_recv_callback(uint16_t type, const void *data,
if (!(hci->le_event_mask[0] & 0x02))
return;
- if (hci->le_scan_enable == 0x01) {
+ if (hci->scan_window_active) {
const struct bt_phy_pkt_adv *pkt = data;
uint8_t buf[100];
struct bt_hci_evt_le_adv_report *evt = (void *) buf;
@@ -1785,6 +1854,8 @@ struct bt_le *bt_le_new(void)
return NULL;
hci->adv_timeout_id = -1;
+ hci->scan_timeout_id = -1;
+ hci->scan_window_active = false;
reset_defaults(hci);