summaryrefslogtreecommitdiff
path: root/emulator/le.c
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2014-12-14 04:54:41 +0100
committerMarcel Holtmann <marcel@holtmann.org>2014-12-14 04:59:15 +0100
commit8470d254636888f0b1fee893b1c5192b240e5c95 (patch)
tree2c6734121511037bd2e9dcd0a1b8ce9872ff2c85 /emulator/le.c
parentd6c1d96051c5efda7996f95892704ce63e0d4bee (diff)
downloadbluez-8470d254636888f0b1fee893b1c5192b240e5c95.tar.gz
emulator: Add support for LE scan parameters and LE scan enable commands
Diffstat (limited to 'emulator/le.c')
-rw-r--r--emulator/le.c127
1 files changed, 125 insertions, 2 deletions
diff --git a/emulator/le.c b/emulator/le.c
index a39cdde5f..c0dd83d75 100644
--- a/emulator/le.c
+++ b/emulator/le.c
@@ -87,6 +87,14 @@ struct bt_le {
uint8_t le_scan_rsp_data[31];
uint8_t le_adv_enable;
+ uint8_t le_scan_type;
+ uint16_t le_scan_interval;
+ uint16_t le_scan_window;
+ uint8_t le_scan_own_addr_type;
+ uint8_t le_scan_filter_policy;
+ uint8_t le_scan_enable;
+ uint8_t le_scan_filter_dup;
+
uint8_t le_white_list_size;
uint8_t le_states[8];
@@ -136,8 +144,8 @@ static void reset_defaults(struct bt_le *hci)
hci->commands[25] |= 0x80; /* LE Set Advertising Data */
hci->commands[26] |= 0x01; /* LE Set Scan Response Data */
hci->commands[26] |= 0x02; /* LE Set Advertise Enable */
- //hci->commands[26] |= 0x04; /* LE Set Scan Parameters */
- //hci->commands[26] |= 0x08; /* LE Set Scan Enable */
+ hci->commands[26] |= 0x04; /* LE Set Scan Parameters */
+ hci->commands[26] |= 0x08; /* LE Set Scan Enable */
//hci->commands[26] |= 0x10; /* LE Create Connection */
//hci->commands[26] |= 0x20; /* LE Create Connection Cancel */
hci->commands[26] |= 0x40; /* LE Read White List Size */
@@ -227,6 +235,14 @@ static void reset_defaults(struct bt_le *hci)
hci->le_adv_enable = 0x00;
+ hci->le_scan_type = 0x00; /* Passive Scanning */
+ hci->le_scan_interval = 0x0010; /* 10 ms */
+ hci->le_scan_window = 0x0010; /* 10 ms */
+ hci->le_scan_own_addr_type = 0x00; /* Public Device Address */
+ hci->le_scan_filter_policy = 0x00;
+ hci->le_scan_enable = 0x00;
+ hci->le_scan_filter_dup = 0x00;
+
hci->le_white_list_size = WHITE_LIST_SIZE;
memset(hci->le_states, 0, sizeof(hci->le_states));
@@ -662,6 +678,109 @@ static void cmd_le_set_adv_enable(struct bt_le *hci,
&status, sizeof(status));
}
+static void cmd_le_set_scan_parameters(struct bt_le *hci,
+ const void *data, uint8_t size)
+{
+ const struct bt_hci_cmd_le_set_scan_parameters *cmd = data;
+ uint16_t interval, window;
+ uint8_t status;
+
+ if (hci->le_scan_enable == 0x01) {
+ cmd_status(hci, BT_HCI_ERR_COMMAND_DISALLOWED,
+ BT_HCI_CMD_LE_SET_SCAN_PARAMETERS);
+ return;
+ }
+
+ interval = le16_to_cpu(cmd->interval);
+ window = le16_to_cpu(cmd->window);
+
+ /* Valid range for scan type is 0x00 to 0x01 */
+ if (cmd->type > 0x01) {
+ cmd_status(hci, BT_HCI_ERR_INVALID_PARAMETERS,
+ BT_HCI_CMD_LE_SET_SCAN_PARAMETERS);
+ return;
+ }
+
+ /* Valid range for scan interval is 0x0004 to 0x4000 */
+ if (interval < 0x0004 || interval > 0x4000) {
+ cmd_status(hci, BT_HCI_ERR_INVALID_PARAMETERS,
+ BT_HCI_CMD_LE_SET_SCAN_PARAMETERS);
+ return;
+ }
+
+ /* Valid range for scan window is 0x0004 to 0x4000 */
+ if (window < 0x0004 || window > 0x4000) {
+ cmd_status(hci, BT_HCI_ERR_INVALID_PARAMETERS,
+ BT_HCI_CMD_LE_SET_SCAN_PARAMETERS);
+ return;
+ }
+
+ /* Scan window shall be less or equal than scan interval */
+ if (window > interval) {
+ cmd_status(hci, BT_HCI_ERR_INVALID_PARAMETERS,
+ BT_HCI_CMD_LE_SET_SCAN_PARAMETERS);
+ return;
+ }
+
+ /* Valid range for own address type is 0x00 to 0x01 */
+ if (cmd->own_addr_type > 0x01) {
+ cmd_status(hci, BT_HCI_ERR_INVALID_PARAMETERS,
+ BT_HCI_CMD_LE_SET_SCAN_PARAMETERS);
+ return;
+ }
+
+ /* Valid range for scanning filter policy is 0x00 to 0x03 */
+ if (cmd->filter_policy > 0x03) {
+ cmd_status(hci, BT_HCI_ERR_INVALID_PARAMETERS,
+ BT_HCI_CMD_LE_SET_SCAN_PARAMETERS);
+ return;
+ }
+
+ hci->le_scan_type = cmd->type;
+ hci->le_scan_interval = interval;
+ hci->le_scan_window = window;
+ hci->le_scan_own_addr_type = cmd->own_addr_type;
+ hci->le_scan_filter_policy = cmd->filter_policy;
+
+ status = BT_HCI_ERR_SUCCESS;
+ cmd_complete(hci, BT_HCI_CMD_LE_SET_SCAN_PARAMETERS,
+ &status, sizeof(status));
+}
+
+static void cmd_le_set_scan_enable(struct bt_le *hci,
+ const void *data, uint8_t size)
+{
+ const struct bt_hci_cmd_le_set_scan_enable *cmd = data;
+ uint8_t status;
+
+ /* Valid range for scan enable is 0x00 to 0x01 */
+ if (cmd->enable > 0x01) {
+ cmd_status(hci, BT_HCI_ERR_INVALID_PARAMETERS,
+ BT_HCI_CMD_LE_SET_SCAN_ENABLE);
+ return;
+ }
+
+ /* Valid range for filter duplicates is 0x00 to 0x01 */
+ if (cmd->filter_dup > 0x01) {
+ cmd_status(hci, BT_HCI_ERR_INVALID_PARAMETERS,
+ BT_HCI_CMD_LE_SET_SCAN_ENABLE);
+ return;
+ }
+
+ if (cmd->enable == hci->le_scan_enable) {
+ cmd_status(hci, BT_HCI_ERR_COMMAND_DISALLOWED,
+ BT_HCI_CMD_LE_SET_SCAN_ENABLE);
+ return;
+ }
+
+ hci->le_scan_enable = cmd->enable;
+ hci->le_scan_filter_dup = cmd->filter_dup;
+
+ status = BT_HCI_ERR_SUCCESS;
+ cmd_complete(hci, BT_HCI_CMD_LE_SET_SCAN_ENABLE,
+ &status, sizeof(status));
+}
+
static void cmd_le_read_white_list_size(struct bt_le *hci,
const void *data, uint8_t size)
{
@@ -1054,6 +1173,10 @@ static const struct {
cmd_le_set_scan_rsp_data, 32, true },
{ BT_HCI_CMD_LE_SET_ADV_ENABLE,
cmd_le_set_adv_enable, 1, true },
+ { BT_HCI_CMD_LE_SET_SCAN_PARAMETERS,
+ cmd_le_set_scan_parameters, 7, true },
+ { BT_HCI_CMD_LE_SET_SCAN_ENABLE,
+ cmd_le_set_scan_enable, 2, true },
{ BT_HCI_CMD_LE_READ_WHITE_LIST_SIZE,
cmd_le_read_white_list_size, 0, true },