Diff between 8a4b1bd1bb7e34322d42c86a02734a5d09ad8be1 and 81596d12b173a4d53e8fcf04a775ce3c6573d5e9

Changed Files

File Additions Deletions Status
emulator/le.c +72 -1 modified

Full Patch

diff --git a/emulator/le.c b/emulator/le.c
index a0d902b..6ffa0d4 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);