2018-04-12 11:20:51

by Jaganath K

[permalink] [raw]
Subject: [PATCH v1 00/10] Extedned Adv, Scan, Connection and PHY support

This patch set adds new mgmt APIs for Get / Set PHY contiguration,
Set PHY in Advertising, added mgmt-tester for the new commands,
and also added btmgmt and monitor changes for the new commands
and events

Jaganath Kanakkassery (10):
doc/mgmt-api: Add support for Set Phy Configuration command
doc/mgmt-api: Add advertising phys support to flags
monitor: Add support PHY management commands and event
btmgmt: Add PHY configuration get/set commands
monitor: Add support for Secondary PHY flags in Add Advertising
btmgmt: Add support for setting PHY in add-adv
mgmt-tester: Add extended advertising test cases
mgmt-tester: Add PHY Configuration test cases
mgmt-tester: Add tests for extended scanning and device found
mgmt-tester: Add support ext create connection and enh conn complete

doc/mgmt-api.txt | 106 +++
emulator/btdev.c | 459 ++++++++++-
emulator/btdev.h | 1 +
emulator/bthost.c | 99 +++
emulator/bthost.h | 7 +
emulator/hciemu.c | 3 +
emulator/hciemu.h | 1 +
lib/mgmt.h | 36 +
monitor/bt.h | 1 +
monitor/packet.c | 68 ++
tools/btmgmt.c | 145 +++-
tools/mgmt-tester.c | 2253 ++++++++++++++++++++++++++++++++++++++++++++++++---
12 files changed, 3074 insertions(+), 105 deletions(-)
mode change 100644 => 100755 tools/btmgmt.c

--
2.7.4



2018-04-12 11:21:01

by Jaganath K

[permalink] [raw]
Subject: [PATCH v1 10/10] mgmt-tester: Add support ext create connection and enh conn complete

---
emulator/btdev.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++--
emulator/bthost.c | 55 ++++++++++++++++++++++++++++++++++
emulator/bthost.h | 3 ++
tools/mgmt-tester.c | 49 +++++++++++++++++++++++++-----
4 files changed, 184 insertions(+), 9 deletions(-)

diff --git a/emulator/btdev.c b/emulator/btdev.c
index c3d2b8a..72c35da 100644
--- a/emulator/btdev.c
+++ b/emulator/btdev.c
@@ -636,7 +636,8 @@ struct btdev *btdev_create(enum btdev_type type, uint16_t id)

memset(btdev, 0, sizeof(*btdev));

- if (type == BTDEV_TYPE_BREDRLE || type == BTDEV_TYPE_LE) {
+ if (type == BTDEV_TYPE_BREDRLE || type == BTDEV_TYPE_LE
+ || BTDEV_TYPE_BREDRLE50) {
btdev->crypto = bt_crypto_new();
if (!btdev->crypto) {
free(btdev);
@@ -1220,6 +1221,53 @@ static void le_conn_complete(struct btdev *btdev,
send_event(btdev, BT_HCI_EVT_LE_META_EVENT, buf, sizeof(buf));
}

+static void le_ext_conn_complete(struct btdev *btdev,
+ const struct bt_hci_cmd_le_ext_create_conn *leecc,
+ uint8_t status)
+{
+ char buf[1 + sizeof(struct bt_hci_evt_le_enhanced_conn_complete)];
+ struct bt_hci_evt_le_enhanced_conn_complete *cc = (void *) &buf[1];
+ struct bt_hci_le_ext_create_conn *lecc = (void *)leecc->data;
+
+ memset(buf, 0, sizeof(buf));
+
+ buf[0] = BT_HCI_EVT_LE_ENHANCED_CONN_COMPLETE;
+
+ if (!status) {
+ struct btdev *remote;
+
+ remote = find_btdev_by_bdaddr_type(leecc->peer_addr,
+ leecc->peer_addr_type);
+
+ btdev->conn = remote;
+ btdev->le_adv_enable = 0;
+ remote->conn = btdev;
+ remote->le_adv_enable = 0;
+
+ cc->status = status;
+ cc->peer_addr_type = btdev->le_scan_own_addr_type;
+ if (cc->peer_addr_type == 0x01)
+ memcpy(cc->peer_addr, btdev->random_addr, 6);
+ else
+ memcpy(cc->peer_addr, btdev->bdaddr, 6);
+
+ cc->role = 0x01;
+ cc->handle = cpu_to_le16(42);
+ cc->interval = lecc->max_interval;
+ cc->latency = lecc->latency;
+ cc->supv_timeout = lecc->supv_timeout;
+
+ send_event(remote, BT_HCI_EVT_LE_META_EVENT, buf, sizeof(buf));
+ }
+
+ cc->status = status;
+ cc->peer_addr_type = leecc->peer_addr_type;
+ memcpy(cc->peer_addr, leecc->peer_addr, 6);
+ cc->role = 0x00;
+
+ send_event(btdev, BT_HCI_EVT_LE_META_EVENT, buf, sizeof(buf));
+}
+
static const uint8_t *scan_addr(const struct btdev *btdev)
{
if (btdev->le_scan_own_addr_type == 0x01)
@@ -1268,6 +1316,14 @@ static bool adv_connectable(struct btdev *btdev)
return btdev->le_adv_type != 0x03;
}

+static bool ext_adv_connectable(struct btdev *btdev)
+{
+ if (!btdev->le_adv_enable)
+ return false;
+
+ return btdev->le_ext_adv_type & 0x01;
+}
+
static void le_conn_request(struct btdev *btdev,
const struct bt_hci_cmd_le_create_conn *lecc)
{
@@ -1282,6 +1338,20 @@ static void le_conn_request(struct btdev *btdev,
BT_HCI_ERR_CONN_FAILED_TO_ESTABLISH);
}

+static void le_ext_conn_request(struct btdev *btdev,
+ const struct bt_hci_cmd_le_ext_create_conn *leecc)
+{
+ struct btdev *remote = find_btdev_by_bdaddr_type(leecc->peer_addr,
+ leecc->peer_addr_type);
+
+ if (remote && ext_adv_connectable(remote) && ext_adv_match(btdev, remote) &&
+ remote->le_adv_own_addr == leecc->peer_addr_type)
+ le_ext_conn_complete(btdev, leecc, 0);
+ else
+ le_ext_conn_complete(btdev, leecc,
+ BT_HCI_ERR_CONN_FAILED_TO_ESTABLISH);
+}
+
static void conn_request(struct btdev *btdev, const uint8_t *bdaddr)
{
struct btdev *remote = find_btdev_by_bdaddr(bdaddr);
@@ -3593,7 +3663,12 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode,
}
cmd_complete(btdev, opcode, &status, sizeof(status));
break;
+ case BT_HCI_CMD_LE_EXT_CREATE_CONN:
+ if (btdev->type != BTDEV_TYPE_BREDRLE50)
+ goto unsupported;

+ cmd_status(btdev, BT_HCI_ERR_SUCCESS, opcode);
+ break;
default:
goto unsupported;
}
@@ -3632,6 +3707,7 @@ static void default_cmd_completion(struct btdev *btdev, uint16_t opcode,
const struct bt_hci_cmd_le_conn_param_req_neg_reply *lcprnr;
const struct bt_hci_cmd_le_set_scan_enable *lsse;
const struct bt_hci_cmd_le_set_ext_scan_enable *lsese;
+ const struct bt_hci_cmd_le_ext_create_conn *leecc;

switch (opcode) {
case BT_HCI_CMD_INQUIRY:
@@ -3834,7 +3910,13 @@ static void default_cmd_completion(struct btdev *btdev, uint16_t opcode,
if (btdev->le_scan_enable && lsese->enable)
le_set_ext_scan_enable_complete(btdev);
break;
-
+ case BT_HCI_CMD_LE_EXT_CREATE_CONN:
+ if (btdev->type != BTDEV_TYPE_BREDRLE50)
+ return;
+ leecc = data;
+ btdev->le_scan_own_addr_type = leecc->own_addr_type;
+ le_ext_conn_request(btdev, leecc);
+ break;
}
}

diff --git a/emulator/bthost.c b/emulator/bthost.c
index 45b9bd6..d37957f 100644
--- a/emulator/bthost.c
+++ b/emulator/bthost.c
@@ -1167,6 +1167,26 @@ static void evt_le_conn_complete(struct bthost *bthost, const void *data,
init_conn(bthost, le16_to_cpu(ev->handle), ev->peer_addr, addr_type);
}

+static void evt_le_ext_conn_complete(struct bthost *bthost, const void *data,
+ uint8_t len)
+{
+ const struct bt_hci_evt_le_enhanced_conn_complete *ev = data;
+ uint8_t addr_type;
+
+ if (len < sizeof(*ev))
+ return;
+
+ if (ev->status)
+ return;
+
+ if (ev->peer_addr_type == 0x00)
+ addr_type = BDADDR_LE_PUBLIC;
+ else
+ addr_type = BDADDR_LE_RANDOM;
+
+ init_conn(bthost, le16_to_cpu(ev->handle), ev->peer_addr, addr_type);
+}
+
static void evt_le_conn_update_complete(struct bthost *bthost, const void *data,
uint8_t len)
{
@@ -1246,6 +1266,9 @@ static void evt_le_meta_event(struct bthost *bthost, const void *data,
case BT_HCI_EVT_LE_LONG_TERM_KEY_REQUEST:
evt_le_ltk_request(bthost, evt_data, len - 1);
break;
+ case BT_HCI_EVT_LE_ENHANCED_CONN_COMPLETE:
+ evt_le_ext_conn_complete(bthost, evt_data, len - 1);
+ break;
default:
printf("Unsupported LE Meta event 0x%2.2x\n", *event);
break;
@@ -2275,6 +2298,38 @@ void bthost_hci_connect(struct bthost *bthost, const uint8_t *bdaddr,
}
}

+void bthost_hci_ext_connect(struct bthost *bthost, const uint8_t *bdaddr,
+ uint8_t addr_type)
+{
+ struct bt_hci_cmd_le_ext_create_conn *cc;
+ struct bt_hci_le_ext_create_conn *cp;
+ uint8_t buf[sizeof(*cc) + sizeof(*cp)];
+
+ cc = (void *)buf;
+ cp = (void *)cc->data;
+
+ bthost->conn_init = true;
+
+ memset(cc, 0, sizeof(*cc));
+ memset(cp, 0, sizeof(*cp));
+
+ memcpy(cc->peer_addr, bdaddr, sizeof(cc->peer_addr));
+
+ if (addr_type == BDADDR_LE_RANDOM)
+ cc->peer_addr_type = 0x01;
+
+ cc->phys = 0x01;
+
+ cp->scan_interval = cpu_to_le16(0x0060);
+ cp->scan_window = cpu_to_le16(0x0030);
+ cp->min_interval = cpu_to_le16(0x0028);
+ cp->max_interval = cpu_to_le16(0x0038);
+ cp->supv_timeout = cpu_to_le16(0x002a);
+
+ send_command(bthost, BT_HCI_CMD_LE_EXT_CREATE_CONN,
+ buf, sizeof(buf));
+}
+
void bthost_hci_disconnect(struct bthost *bthost, uint16_t handle,
uint8_t reason)
{
diff --git a/emulator/bthost.h b/emulator/bthost.h
index 752c14b..b5f3696 100644
--- a/emulator/bthost.h
+++ b/emulator/bthost.h
@@ -56,6 +56,9 @@ void bthost_set_connect_cb(struct bthost *bthost, bthost_new_conn_cb cb,
void bthost_hci_connect(struct bthost *bthost, const uint8_t *bdaddr,
uint8_t addr_type);

+void bthost_hci_ext_connect(struct bthost *bthost, const uint8_t *bdaddr,
+ uint8_t addr_type);
+
void bthost_hci_disconnect(struct bthost *bthost, uint16_t handle,
uint8_t reason);

diff --git a/tools/mgmt-tester.c b/tools/mgmt-tester.c
index e5076b5..1523ca8 100644
--- a/tools/mgmt-tester.c
+++ b/tools/mgmt-tester.c
@@ -5292,6 +5292,7 @@ static void client_cmd_complete(uint16_t opcode, uint8_t status,
switch (opcode) {
case BT_HCI_CMD_WRITE_SCAN_ENABLE:
case BT_HCI_CMD_LE_SET_ADV_ENABLE:
+ case BT_HCI_CMD_LE_SET_EXT_ADV_ENABLE:
tester_print("Client set connectable: %s (0x%02x)",
mgmt_errstr(status), status);
if (!status && test->client_enable_ssp) {
@@ -5321,9 +5322,14 @@ static void setup_bthost(void)

bthost = hciemu_client_get_host(data->hciemu);
bthost_set_cmd_complete_cb(bthost, client_cmd_complete, data);
- if (data->hciemu_type == HCIEMU_TYPE_LE || test->client_enable_adv)
- bthost_set_adv_enable(bthost, 0x01);
- else
+
+ if (data->hciemu_type == HCIEMU_TYPE_LE ||
+ test->client_enable_adv) {
+ if (data->hciemu_type == HCIEMU_TYPE_BREDRLE50)
+ bthost_set_ext_adv_enable(bthost, 0x01);
+ else
+ bthost_set_adv_enable(bthost, 0x01);
+ } else
bthost_write_scan_enable(bthost, 0x03);
}

@@ -8866,9 +8872,15 @@ static void le_connected_event(uint16_t index, uint16_t length,
tester_print("Device connected");

test_add_condition(data);
- hciemu_add_hook(data->hciemu, HCIEMU_HOOK_POST_CMD,
- BT_HCI_CMD_LE_SET_ADV_ENABLE,
- test_adv_enable_hook, data);
+
+ if (data->hciemu_type == HCIEMU_TYPE_BREDRLE50)
+ hciemu_add_hook(data->hciemu, HCIEMU_HOOK_POST_CMD,
+ BT_HCI_CMD_LE_SET_EXT_ADV_ENABLE,
+ test_adv_enable_hook, data);
+ else
+ hciemu_add_hook(data->hciemu, HCIEMU_HOOK_POST_CMD,
+ BT_HCI_CMD_LE_SET_ADV_ENABLE,
+ test_adv_enable_hook, data);

/* Make sure we get not disconnected during the testaces */
mgmt_register(data->mgmt_alt, MGMT_EV_DEVICE_DISCONNECTED,
@@ -8908,7 +8920,10 @@ static void add_device_callback(uint8_t status, uint16_t len, const void *param,
}

bthost = hciemu_client_get_host(data->hciemu);
- bthost_hci_connect(bthost, master_bdaddr, BDADDR_LE_PUBLIC);
+ if (data->hciemu_type == HCIEMU_TYPE_BREDRLE50)
+ bthost_hci_ext_connect(bthost, master_bdaddr, BDADDR_LE_PUBLIC);
+ else
+ bthost_hci_connect(bthost, master_bdaddr, BDADDR_LE_PUBLIC);
}

static void test_connected_and_advertising(const void *test_data)
@@ -10382,5 +10397,25 @@ int main(int argc, char *argv[])
&device_found_invalid_field,
NULL, test_device_found);

+ test_bredrle50_full("Ext Adv. connectable & connected (slave) - Success",
+ &conn_slave_adv_conneactable_test,
+ setup_advertise_while_connected,
+ test_connected_and_advertising, 10);
+
+ test_bredrle50_full("Ext Adv. non-connectable & connected (slave) - Success",
+ &conn_slave_adv_non_conneactable_test,
+ setup_advertise_while_connected,
+ test_connected_and_advertising, 10);
+
+ test_bredrle50_full("Ext Adv. connectable & connected (master) - Success",
+ &conn_master_adv_conneactable_test,
+ setup_advertise_while_connected,
+ test_connected_and_advertising, 10);
+
+ test_bredrle50_full("Ext Adv. non-connectable & connected (master) - Success",
+ &conn_master_adv_non_conneactable_test,
+ setup_advertise_while_connected,
+ test_connected_and_advertising, 10);
+
return tester_run();
}
--
2.7.4


2018-04-12 11:21:00

by Jaganath K

[permalink] [raw]
Subject: [PATCH v1 09/10] mgmt-tester: Add tests for extended scanning and device found

---
emulator/btdev.c | 86 ++++++++++++++++++
emulator/bthost.c | 44 ++++++++++
emulator/bthost.h | 4 +
tools/mgmt-tester.c | 244 ++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 378 insertions(+)

diff --git a/emulator/btdev.c b/emulator/btdev.c
index 36aa696..c3d2b8a 100644
--- a/emulator/btdev.c
+++ b/emulator/btdev.c
@@ -2073,6 +2073,44 @@ static void le_set_scan_enable_complete(struct btdev *btdev)
}
}

+static void le_set_ext_scan_enable_complete(struct btdev *btdev)
+{
+ int i;
+
+ for (i = 0; i < MAX_BTDEV_ENTRIES; i++) {
+ uint16_t report_type;
+
+ if (!btdev_list[i] || btdev_list[i] == btdev)
+ continue;
+
+ if (!btdev_list[i]->le_adv_enable)
+ continue;
+
+ if (!ext_adv_match(btdev, btdev_list[i]))
+ continue;
+
+ report_type = get_ext_adv_report_type(btdev_list[i]->le_ext_adv_type);
+ le_send_ext_adv_report(btdev, btdev_list[i], report_type, false);
+
+ if (btdev->le_scan_type != 0x01)
+ continue;
+
+ /* if scannable bit is set the send scan response */
+ if (btdev_list[i]->le_ext_adv_type & 0x02) {
+ if (btdev_list[i]->le_ext_adv_type == 0x13)
+ report_type = 0x1b;
+ else if (btdev_list[i]->le_ext_adv_type == 0x12)
+ report_type = 0x1a;
+ else if (!(btdev_list[i]->le_ext_adv_type & 0x10))
+ report_type &= 0x08;
+ else
+ continue;
+
+ le_send_ext_adv_report(btdev, btdev_list[i], report_type, true);
+ }
+ }
+}
+
static void le_read_remote_features_complete(struct btdev *btdev)
{
char buf[1 + sizeof(struct bt_hci_evt_le_remote_features_complete)];
@@ -2245,6 +2283,9 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode,
const struct bt_hci_cmd_le_set_ext_adv_data *lsead;
const struct bt_hci_cmd_le_set_ext_scan_rsp_data *lsesrd;
const struct bt_hci_cmd_le_set_default_phy *phys;
+ const struct bt_hci_cmd_le_set_ext_scan_params *lsesp;
+ const struct bt_hci_le_scan_phy *lsp;
+ const struct bt_hci_cmd_le_set_ext_scan_enable *lsese;
struct bt_hci_rsp_read_default_link_policy rdlp;
struct bt_hci_rsp_read_stored_link_key rslk;
struct bt_hci_rsp_write_stored_link_key wslk;
@@ -3516,6 +3557,42 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode,
status = BT_HCI_ERR_SUCCESS;
cmd_complete(btdev, opcode, &status, sizeof(status));
break;
+ case BT_HCI_CMD_LE_SET_EXT_SCAN_PARAMS:
+ if (btdev->type != BTDEV_TYPE_BREDRLE50)
+ goto unsupported;
+
+ lsesp = data;
+ lsp = (void *)lsesp->data;
+
+ if (btdev->le_scan_enable)
+ status = BT_HCI_ERR_COMMAND_DISALLOWED;
+ else if (lsesp->num_phys == 0)
+ status = BT_HCI_ERR_INVALID_PARAMETERS;
+ else {
+ status = BT_HCI_ERR_SUCCESS;
+ /* Currently we dont support multiple types in single command
+ * So just take the first one will do.
+ */
+ btdev->le_scan_type = lsp->type;
+ btdev->le_scan_own_addr_type = lsesp->own_addr_type;
+ }
+
+ cmd_complete(btdev, opcode, &status, sizeof(status));
+ break;
+ case BT_HCI_CMD_LE_SET_EXT_SCAN_ENABLE:
+ if (btdev->type != BTDEV_TYPE_BREDRLE50)
+ goto unsupported;
+
+ lsese = data;
+ if (btdev->le_scan_enable == lsese->enable)
+ status = BT_HCI_ERR_COMMAND_DISALLOWED;
+ else {
+ btdev->le_scan_enable = lsese->enable;
+ btdev->le_filter_dup = lsese->filter_dup;
+ status = BT_HCI_ERR_SUCCESS;
+ }
+ cmd_complete(btdev, opcode, &status, sizeof(status));
+ break;

default:
goto unsupported;
@@ -3554,6 +3631,7 @@ static void default_cmd_completion(struct btdev *btdev, uint16_t opcode,
const struct bt_hci_cmd_le_conn_param_req_reply *lcprr;
const struct bt_hci_cmd_le_conn_param_req_neg_reply *lcprnr;
const struct bt_hci_cmd_le_set_scan_enable *lsse;
+ const struct bt_hci_cmd_le_set_ext_scan_enable *lsese;

switch (opcode) {
case BT_HCI_CMD_INQUIRY:
@@ -3748,6 +3826,14 @@ static void default_cmd_completion(struct btdev *btdev, uint16_t opcode,
lsse = data;
if (btdev->le_scan_enable && lsse->enable)
le_set_scan_enable_complete(btdev);
+ break;
+ case BT_HCI_CMD_LE_SET_EXT_SCAN_ENABLE:
+ if (btdev->type != BTDEV_TYPE_BREDRLE50)
+ return;
+ lsese = data;
+ if (btdev->le_scan_enable && lsese->enable)
+ le_set_ext_scan_enable_complete(btdev);
+ break;

}
}
diff --git a/emulator/bthost.c b/emulator/bthost.c
index 2bcdc31..45b9bd6 100644
--- a/emulator/bthost.c
+++ b/emulator/bthost.c
@@ -839,6 +839,12 @@ static void evt_cmd_complete(struct bthost *bthost, const void *data,
break;
case BT_HCI_CMD_LE_SET_ADV_DATA:
break;
+ case BT_HCI_CMD_LE_SET_EXT_ADV_PARAMS:
+ break;
+ case BT_HCI_CMD_LE_SET_EXT_ADV_DATA:
+ break;
+ case BT_HCI_CMD_LE_SET_EXT_ADV_ENABLE:
+ break;
default:
printf("Unhandled cmd_complete opcode 0x%04x\n", opcode);
break;
@@ -2301,6 +2307,29 @@ void bthost_set_adv_data(struct bthost *bthost, const uint8_t *data,
sizeof(adv_cp));
}

+void bthost_set_ext_adv_data(struct bthost *bthost, const uint8_t *data,
+ uint8_t len)
+{
+ struct bt_hci_cmd_le_set_ext_adv_data *adv_cp;
+ uint8_t buf[sizeof(*adv_cp) + 31];
+
+ adv_cp = (void *)buf;
+
+ memset(adv_cp, 0, sizeof(*adv_cp));
+ memset(adv_cp->data, 0, 31);
+
+ adv_cp->operation = 0x03;
+ adv_cp->fragment_preference = 0x01;
+
+ if (len) {
+ adv_cp->data_len = len;
+ memcpy(adv_cp->data, data, len);
+ }
+
+ send_command(bthost, BT_HCI_CMD_LE_SET_EXT_ADV_DATA, buf,
+ sizeof(buf));
+}
+
void bthost_set_adv_enable(struct bthost *bthost, uint8_t enable)
{
struct bt_hci_cmd_le_set_adv_parameters cp;
@@ -2312,6 +2341,21 @@ void bthost_set_adv_enable(struct bthost *bthost, uint8_t enable)
send_command(bthost, BT_HCI_CMD_LE_SET_ADV_ENABLE, &enable, 1);
}

+void bthost_set_ext_adv_enable(struct bthost *bthost, uint8_t enable)
+{
+ struct bt_hci_cmd_le_set_ext_adv_params cp;
+ struct bt_hci_cmd_le_set_ext_adv_enable cp_enable;
+
+ memset(&cp, 0, sizeof(cp));
+ cp.evt_properties = cpu_to_le16(0x0013);
+ send_command(bthost, BT_HCI_CMD_LE_SET_EXT_ADV_PARAMS,
+ &cp, sizeof(cp));
+
+ cp_enable.enable = enable;
+ send_command(bthost, BT_HCI_CMD_LE_SET_EXT_ADV_ENABLE, &cp_enable,
+ sizeof(cp_enable));
+}
+
void bthost_write_ssp_mode(struct bthost *bthost, uint8_t mode)
{
send_command(bthost, BT_HCI_CMD_WRITE_SIMPLE_PAIRING_MODE, &mode, 1);
diff --git a/emulator/bthost.h b/emulator/bthost.h
index 553865a..752c14b 100644
--- a/emulator/bthost.h
+++ b/emulator/bthost.h
@@ -83,6 +83,10 @@ void bthost_set_adv_data(struct bthost *bthost, const uint8_t *data,
uint8_t len);
void bthost_set_adv_enable(struct bthost *bthost, uint8_t enable);

+void bthost_set_ext_adv_data(struct bthost *bthost, const uint8_t *data,
+ uint8_t len);
+void bthost_set_ext_adv_enable(struct bthost *bthost, uint8_t enable);
+
void bthost_write_ssp_mode(struct bthost *bthost, uint8_t mode);

void bthost_write_le_host_supported(struct bthost *bthost, uint8_t mode);
diff --git a/tools/mgmt-tester.c b/tools/mgmt-tester.c
index 7485318..e5076b5 100644
--- a/tools/mgmt-tester.c
+++ b/tools/mgmt-tester.c
@@ -8374,6 +8374,205 @@ static const struct generic_data set_phy_invalid_param = {
.expect_status = MGMT_STATUS_INVALID_PARAMS,
};

+static const char start_discovery_valid_ext_scan_enable[] = {
+ 0x01,
+ 0x01,
+ 0x00, 0x00,
+ 0x00, 0x00
+};
+
+static const struct generic_data start_discovery_bredrle_ext_scan_enable = {
+ .setup_settings = settings_powered_le,
+ .send_opcode = MGMT_OP_START_DISCOVERY,
+ .send_param = start_discovery_bredrle_param,
+ .send_len = sizeof(start_discovery_bredrle_param),
+ .expect_status = MGMT_STATUS_SUCCESS,
+ .expect_param = start_discovery_bredrle_param,
+ .expect_len = sizeof(start_discovery_bredrle_param),
+ .expect_hci_command = BT_HCI_CMD_LE_SET_EXT_SCAN_ENABLE,
+ .expect_hci_param = start_discovery_valid_ext_scan_enable,
+ .expect_hci_len = sizeof(start_discovery_valid_ext_scan_enable),
+ .expect_alt_ev = MGMT_EV_DISCOVERING,
+ .expect_alt_ev_param = start_discovery_evt,
+ .expect_alt_ev_len = sizeof(start_discovery_evt),
+};
+
+static const struct generic_data start_discovery_le_ext_scan_enable = {
+ .setup_settings = settings_powered_le,
+ .send_opcode = MGMT_OP_START_DISCOVERY,
+ .send_param = start_discovery_le_param,
+ .send_len = sizeof(start_discovery_le_param),
+ .expect_status = MGMT_STATUS_SUCCESS,
+ .expect_param = start_discovery_le_param,
+ .expect_len = sizeof(start_discovery_le_param),
+ .expect_hci_command = BT_HCI_CMD_LE_SET_EXT_SCAN_ENABLE,
+ .expect_hci_param = start_discovery_valid_ext_scan_enable,
+ .expect_hci_len = sizeof(start_discovery_valid_ext_scan_enable),
+ .expect_alt_ev = MGMT_EV_DISCOVERING,
+ .expect_alt_ev_param = start_discovery_le_evt,
+ .expect_alt_ev_len = sizeof(start_discovery_le_evt),
+};
+
+static const char start_discovery_valid_ext_scan_param[] = {
+ 0x01, /* Own Addr type*/
+ 0x00, /* Scan filter policy*/
+ 0x01, /*Phys - 1m */
+ 0x01, /* Type */
+ 0x12, 0x00, /* Interval */
+ 0x12, 0x00, /* Window */
+};
+
+static const struct generic_data start_discovery_le_ext_scan_param = {
+ .setup_settings = settings_powered_le,
+ .send_opcode = MGMT_OP_START_DISCOVERY,
+ .send_param = start_discovery_le_param,
+ .send_len = sizeof(start_discovery_le_param),
+ .expect_status = MGMT_STATUS_SUCCESS,
+ .expect_param = start_discovery_le_param,
+ .expect_len = sizeof(start_discovery_le_param),
+ .expect_hci_command = BT_HCI_CMD_LE_SET_EXT_SCAN_PARAMS,
+ .expect_hci_param = start_discovery_valid_ext_scan_param,
+ .expect_hci_len = sizeof(start_discovery_valid_ext_scan_param),
+ .expect_alt_ev = MGMT_EV_DISCOVERING,
+ .expect_alt_ev_param = start_discovery_le_evt,
+ .expect_alt_ev_len = sizeof(start_discovery_le_evt),
+};
+
+static const char stop_discovery_valid_ext_scan_disable[] = {
+ 0x00,
+ 0x00,
+ 0x00, 0x00,
+ 0x00, 0x00
+};
+
+static const struct generic_data stop_discovery_le_ext_scan_disable = {
+ .setup_settings = settings_powered_le,
+ .setup_send_opcode = MGMT_OP_START_DISCOVERY,
+ .setup_send_param = start_discovery_bredrle_param,
+ .setup_send_len = sizeof(start_discovery_bredrle_param),
+ .send_opcode = MGMT_OP_STOP_DISCOVERY,
+ .send_param = stop_discovery_bredrle_param,
+ .send_len = sizeof(stop_discovery_bredrle_param),
+ .expect_status = MGMT_STATUS_SUCCESS,
+ .expect_param = stop_discovery_bredrle_param,
+ .expect_len = sizeof(stop_discovery_bredrle_param),
+ .expect_hci_command = BT_HCI_CMD_LE_SET_EXT_SCAN_ENABLE,
+ .expect_hci_param = stop_discovery_valid_ext_scan_disable,
+ .expect_hci_len = sizeof(stop_discovery_valid_ext_scan_disable),
+ .expect_alt_ev = MGMT_EV_DISCOVERING,
+ .expect_alt_ev_param = stop_discovery_evt,
+ .expect_alt_ev_len = sizeof(stop_discovery_evt),
+};
+
+static const struct generic_data start_discovery_le_2m_scan_param = {
+ .setup_settings = settings_powered_le,
+ .setup_send_opcode = MGMT_OP_SET_PHY_CONFIGURATION,
+ .setup_send_param = set_phy_2m_param,
+ .setup_send_len = sizeof(set_phy_2m_param),
+ .send_opcode = MGMT_OP_START_DISCOVERY,
+ .send_param = start_discovery_bredrle_param,
+ .send_len = sizeof(start_discovery_bredrle_param),
+ .expect_status = MGMT_STATUS_SUCCESS,
+ .expect_param = start_discovery_bredrle_param,
+ .expect_len = sizeof(start_discovery_bredrle_param),
+ .expect_hci_command = BT_HCI_CMD_LE_SET_EXT_SCAN_PARAMS,
+ .expect_hci_param = start_discovery_valid_ext_scan_param,
+ .expect_hci_len = sizeof(start_discovery_valid_ext_scan_param),
+ .expect_alt_ev = MGMT_EV_DISCOVERING,
+ .expect_alt_ev_param = start_discovery_evt,
+ .expect_alt_ev_len = sizeof(start_discovery_evt),
+};
+
+static const char start_discovery_valid_coded_scan_param[] = {
+ 0x01, /* Own Addr type*/
+ 0x00, /* Scan filter policy*/
+ 0x04, /*Phys - coded */
+ 0x01, /* Type */
+ 0x12, 0x00, /* Interval */
+ 0x12, 0x00, /* Window */
+};
+
+static const struct generic_data start_discovery_le_coded_scan_param = {
+ .setup_settings = settings_powered_le,
+ .setup_send_opcode = MGMT_OP_SET_PHY_CONFIGURATION,
+ .setup_send_param = set_phy_coded_param,
+ .setup_send_len = sizeof(set_phy_coded_param),
+ .send_opcode = MGMT_OP_START_DISCOVERY,
+ .send_param = start_discovery_bredrle_param,
+ .send_len = sizeof(start_discovery_bredrle_param),
+ .expect_status = MGMT_STATUS_SUCCESS,
+ .expect_param = start_discovery_bredrle_param,
+ .expect_len = sizeof(start_discovery_bredrle_param),
+ .expect_hci_command = BT_HCI_CMD_LE_SET_EXT_SCAN_PARAMS,
+ .expect_hci_param = start_discovery_valid_coded_scan_param,
+ .expect_hci_len = sizeof(start_discovery_valid_coded_scan_param),
+ .expect_alt_ev = MGMT_EV_DISCOVERING,
+ .expect_alt_ev_param = start_discovery_evt,
+ .expect_alt_ev_len = sizeof(start_discovery_evt),
+};
+
+static const char set_phy_1m_2m_coded_param[] = { 0x3f, 0x00 };
+
+static const char start_discovery_valid_1m_2m_coded_scan_param[] = {
+ 0x01, /* Own Addr type*/
+ 0x00, /* Scan filter policy*/
+ 0x05, /*Phys - 1m, coded */
+ 0x01, /* Type */
+ 0x12, 0x00, /* Interval */
+ 0x12, 0x00, /* Window */
+ 0x01, /* Type */
+ 0x12, 0x00, /* Interval */
+ 0x12, 0x00, /* Window */
+};
+
+static const struct generic_data start_discovery_le_1m_coded_scan_param = {
+ .setup_settings = settings_powered_le,
+ .setup_send_opcode = MGMT_OP_SET_PHY_CONFIGURATION,
+ .setup_send_param = set_phy_1m_2m_coded_param,
+ .setup_send_len = sizeof(set_phy_1m_2m_coded_param),
+ .send_opcode = MGMT_OP_START_DISCOVERY,
+ .send_param = start_discovery_bredrle_param,
+ .send_len = sizeof(start_discovery_bredrle_param),
+ .expect_status = MGMT_STATUS_SUCCESS,
+ .expect_param = start_discovery_bredrle_param,
+ .expect_len = sizeof(start_discovery_bredrle_param),
+ .expect_hci_command = BT_HCI_CMD_LE_SET_EXT_SCAN_PARAMS,
+ .expect_hci_param = start_discovery_valid_1m_2m_coded_scan_param,
+ .expect_hci_len = sizeof(start_discovery_valid_1m_2m_coded_scan_param),
+ .expect_alt_ev = MGMT_EV_DISCOVERING,
+ .expect_alt_ev_param = start_discovery_evt,
+ .expect_alt_ev_len = sizeof(start_discovery_evt),
+};
+
+static void set_phy_callback(uint8_t status, uint16_t length,
+ const void *param, void *user_data)
+{
+ if (status != MGMT_STATUS_SUCCESS) {
+ tester_setup_failed();
+ return;
+ }
+
+ tester_print("Set PHY Success");
+
+ tester_setup_complete();
+}
+
+static void setup_phy_configuration(const void *test_data)
+{
+ struct test_data *data = tester_get_data();
+ const struct generic_data *test = data->test_data;
+ const void *send_param = test->setup_send_param;
+ uint16_t send_len = test->setup_send_len;
+ unsigned int id;
+
+ id = mgmt_register(data->mgmt, MGMT_EV_DISCOVERING, data->mgmt_index,
+ discovering_event, NULL, NULL);
+ data->mgmt_discov_ev_id = id;
+
+ mgmt_send(data->mgmt, test->setup_send_opcode, data->mgmt_index,
+ send_len, send_param, set_phy_callback,
+ NULL, NULL);
+}

static bool power_off(uint16_t index)
{
@@ -8501,6 +8700,12 @@ static void trigger_device_found(void *user_data)
test->adv_data_len);

bthost_set_adv_enable(bthost, 0x01);
+ } else if (data->hciemu_type == HCIEMU_TYPE_BREDRLE50) {
+ if (test->set_adv)
+ bthost_set_ext_adv_data(bthost, test->adv_data,
+ test->adv_data_len);
+
+ bthost_set_ext_adv_enable(bthost, 0x01);
}

if (data->hciemu_type != HCIEMU_TYPE_LE)
@@ -10138,5 +10343,44 @@ int main(int argc, char *argv[])
test_bredrle50("Set PHY Invalid Param", &set_phy_invalid_param,
NULL, test_command_generic);

+ test_bredrle50("Start Discovery BREDR LE - (Ext Scan Enable)",
+ &start_discovery_bredrle_ext_scan_enable,
+ NULL,
+ test_command_generic);
+
+ test_bredrle50("Start Discovery LE - (Ext Scan Enable)",
+ &start_discovery_le_ext_scan_enable,
+ NULL,
+ test_command_generic);
+
+ test_bredrle50("Start Discovery LE - (Ext Scan Param)",
+ &start_discovery_le_ext_scan_param,
+ NULL,
+ test_command_generic);
+
+ test_bredrle50("Stop Discovery - (Ext Scan Disable)",
+ &stop_discovery_le_ext_scan_disable,
+ setup_start_discovery, test_command_generic);
+
+ test_bredrle50("Start Discovery - (2m, Scan Param)",
+ &start_discovery_le_2m_scan_param,
+ setup_phy_configuration, test_command_generic);
+
+ test_bredrle50("Start Discovery - (coded, Scan Param)",
+ &start_discovery_le_coded_scan_param,
+ setup_phy_configuration, test_command_generic);
+
+ test_bredrle50("Start Discovery - (1m, 2m, coded, Scan Param)",
+ &start_discovery_le_1m_coded_scan_param,
+ setup_phy_configuration, test_command_generic);
+
+ test_bredrle50("Ext Device Found - Advertising data - Zero padded",
+ &device_found_gtag,
+ NULL, test_device_found);
+
+ test_bredrle50("Ext Device Found - Advertising data - Invalid field",
+ &device_found_invalid_field,
+ NULL, test_device_found);
+
return tester_run();
}
--
2.7.4


2018-04-12 11:20:59

by Jaganath K

[permalink] [raw]
Subject: [PATCH v1 08/10] mgmt-tester: Add PHY Configuration test cases

---
emulator/btdev.c | 16 ++++-
tools/mgmt-tester.c | 180 ++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 195 insertions(+), 1 deletion(-)

diff --git a/emulator/btdev.c b/emulator/btdev.c
index ad4f873..36aa696 100644
--- a/emulator/btdev.c
+++ b/emulator/btdev.c
@@ -2244,6 +2244,7 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode,
const struct bt_hci_cmd_le_set_ext_adv_enable *lseae;
const struct bt_hci_cmd_le_set_ext_adv_data *lsead;
const struct bt_hci_cmd_le_set_ext_scan_rsp_data *lsesrd;
+ const struct bt_hci_cmd_le_set_default_phy *phys;
struct bt_hci_rsp_read_default_link_policy rdlp;
struct bt_hci_rsp_read_stored_link_key rslk;
struct bt_hci_rsp_write_stored_link_key wslk;
@@ -3501,7 +3502,20 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode,
status = BT_HCI_ERR_SUCCESS;
cmd_complete(btdev, opcode, &status, sizeof(status));
break;
-
+ case BT_HCI_CMD_LE_SET_DEFAULT_PHY:
+ if (btdev->type == BTDEV_TYPE_BREDR)
+ goto unsupported;
+ phys = data;
+ if (phys->all_phys > 0x03 ||
+ (!(phys->all_phys & 0x01) &&
+ (!phys->tx_phys || phys->tx_phys > 0x07)) ||
+ (!(phys->all_phys & 0x02) &&
+ (!phys->rx_phys || phys->rx_phys > 0x07)))
+ status = BT_HCI_ERR_INVALID_PARAMETERS;
+ else
+ status = BT_HCI_ERR_SUCCESS;
+ cmd_complete(btdev, opcode, &status, sizeof(status));
+ break;

default:
goto unsupported;
diff --git a/tools/mgmt-tester.c b/tools/mgmt-tester.c
index 660a3b4..7485318 100644
--- a/tools/mgmt-tester.c
+++ b/tools/mgmt-tester.c
@@ -8216,6 +8216,165 @@ static const struct generic_data add_ext_advertising_conn_off_1m = {
.expect_hci_len = sizeof(set_connectable_off_ext_1m_adv_param),
};

+static const uint8_t get_phy_param[] = {
+ 0x3f, 0x00, /* 1mtx 1mrx 2mtx 2mrx codedtx codedrx*/
+ 0x03, 0x00, /* 1mtx 1mtx */
+};
+
+static const struct generic_data get_phy_success = {
+ .setup_settings = settings_powered_le,
+ .send_opcode = MGMT_OP_GET_PHY_CONFIGURATION,
+ .expect_status = MGMT_STATUS_SUCCESS,
+ .expect_param = get_phy_param,
+ .expect_len = sizeof(get_phy_param),
+};
+
+static const uint8_t set_phy_2m_param[] = {
+ 0x0c, 0x00, /* 2mtx 2mrx */
+};
+
+static const uint8_t set_default_phy_2m_param[] = {
+ 0x00, /* preference is there for tx and rx */
+ 0x02, /* 2mtx */
+ 0x02, /* 2mrx */
+};
+
+static const struct generic_data set_phy_2m_success = {
+ .setup_settings = settings_powered_le,
+ .send_opcode = MGMT_OP_SET_PHY_CONFIGURATION,
+ .send_param = set_phy_2m_param,
+ .send_len = sizeof(set_phy_2m_param),
+ .expect_status = MGMT_STATUS_SUCCESS,
+ .expect_hci_command = BT_HCI_CMD_LE_SET_DEFAULT_PHY,
+ .expect_hci_param = set_default_phy_2m_param,
+ .expect_hci_len = sizeof(set_default_phy_2m_param),
+ .expect_alt_ev = MGMT_EV_PHY_CONFIGURATION_CHANGED,
+ .expect_alt_ev_param = set_phy_2m_param,
+ .expect_alt_ev_len = sizeof(set_phy_2m_param),
+ .expect_settings_set = MGMT_SETTING_PHY_CONFIGURATION,
+};
+
+static const uint8_t set_phy_coded_param[] = {
+ 0x30, 0x00, /* codedtx codedrx */
+};
+
+static const uint8_t set_default_phy_coded_param[] = {
+ 0x00, /* preference is there for tx and rx */
+ 0x04, /* codedtx */
+ 0x04, /* codedrx */
+};
+
+static const struct generic_data set_phy_coded_success = {
+ .setup_settings = settings_powered_le,
+ .send_opcode = MGMT_OP_SET_PHY_CONFIGURATION,
+ .send_param = set_phy_coded_param,
+ .send_len = sizeof(set_phy_coded_param),
+ .expect_status = MGMT_STATUS_SUCCESS,
+ .expect_hci_command = BT_HCI_CMD_LE_SET_DEFAULT_PHY,
+ .expect_hci_param = set_default_phy_coded_param,
+ .expect_hci_len = sizeof(set_default_phy_coded_param),
+ .expect_alt_ev = MGMT_EV_PHY_CONFIGURATION_CHANGED,
+ .expect_alt_ev_param = set_phy_coded_param,
+ .expect_alt_ev_len = sizeof(set_phy_coded_param),
+ .expect_settings_set = MGMT_SETTING_PHY_CONFIGURATION,
+};
+
+static const uint8_t set_phy_all_param[] = {
+ 0x3f, 0x00, /* 1m 2m coded both tx rx */
+};
+
+static const uint8_t set_default_phy_all_param[] = {
+ 0x00, /* preference is there for tx and rx */
+ 0x07, /* 1m 2m coded tx */
+ 0x07, /* 1m 2m coded rx */
+};
+
+static const struct generic_data set_phy_all_success = {
+ .setup_settings = settings_powered_le,
+ .send_opcode = MGMT_OP_SET_PHY_CONFIGURATION,
+ .send_param = set_phy_all_param,
+ .send_len = sizeof(set_phy_all_param),
+ .expect_status = MGMT_STATUS_SUCCESS,
+ .expect_hci_command = BT_HCI_CMD_LE_SET_DEFAULT_PHY,
+ .expect_hci_param = set_default_phy_all_param,
+ .expect_hci_len = sizeof(set_default_phy_all_param),
+ .expect_alt_ev = MGMT_EV_PHY_CONFIGURATION_CHANGED,
+ .expect_alt_ev_param = set_phy_all_param,
+ .expect_alt_ev_len = sizeof(set_phy_all_param),
+ .expect_settings_set = MGMT_SETTING_PHY_CONFIGURATION,
+};
+
+static const uint8_t set_phy_2m_tx_param[] = {
+ 0x04, 0x00, /* only 2m tx */
+};
+
+static const uint8_t set_default_phy_2m_tx_param[] = {
+ 0x02, /* no preference for rx */
+ 0x02, /* 2m tx */
+ 0x00,
+};
+
+static const uint8_t set_phy_2m_tx_evt_param[] = {
+ 0x04, 0x00, /* 2m tx */
+};
+
+static const struct generic_data set_phy_2m_tx_success = {
+ .setup_settings = settings_powered_le,
+ .send_opcode = MGMT_OP_SET_PHY_CONFIGURATION,
+ .send_param = set_phy_2m_tx_param,
+ .send_len = sizeof(set_phy_2m_tx_param),
+ .expect_status = MGMT_STATUS_SUCCESS,
+ .expect_hci_command = BT_HCI_CMD_LE_SET_DEFAULT_PHY,
+ .expect_hci_param = set_default_phy_2m_tx_param,
+ .expect_hci_len = sizeof(set_default_phy_2m_tx_param),
+ .expect_alt_ev = MGMT_EV_PHY_CONFIGURATION_CHANGED,
+ .expect_alt_ev_param = set_phy_2m_tx_evt_param,
+ .expect_alt_ev_len = sizeof(set_phy_2m_tx_evt_param),
+ .expect_settings_set = MGMT_SETTING_PHY_CONFIGURATION,
+};
+
+static const uint8_t set_phy_2m_rx_param[] = {
+ 0x08, 0x00, /* only 2m rx */
+};
+
+static const uint8_t set_default_phy_2m_rx_param[] = {
+ 0x01, /* no preference for tx */
+ 0x00,
+ 0x02, /* 2m rx */
+};
+
+static const uint8_t set_phy_2m_rx_evt_param[] = {
+ 0x08, 0x00, /* 2m rx */
+};
+
+static const struct generic_data set_phy_2m_rx_success = {
+ .setup_settings = settings_powered_le,
+ .send_opcode = MGMT_OP_SET_PHY_CONFIGURATION,
+ .send_param = set_phy_2m_rx_param,
+ .send_len = sizeof(set_phy_2m_rx_param),
+ .expect_status = MGMT_STATUS_SUCCESS,
+ .expect_hci_command = BT_HCI_CMD_LE_SET_DEFAULT_PHY,
+ .expect_hci_param = set_default_phy_2m_rx_param,
+ .expect_hci_len = sizeof(set_default_phy_2m_rx_param),
+ .expect_alt_ev = MGMT_EV_PHY_CONFIGURATION_CHANGED,
+ .expect_alt_ev_param = set_phy_2m_rx_evt_param,
+ .expect_alt_ev_len = sizeof(set_phy_2m_rx_evt_param),
+ .expect_settings_set = MGMT_SETTING_PHY_CONFIGURATION,
+};
+
+static const uint8_t set_phy_param_invalid[] = {
+ 0x7f, 0x00, /* Invalid phy*/
+};
+
+static const struct generic_data set_phy_invalid_param = {
+ .setup_settings = settings_powered_le,
+ .send_opcode = MGMT_OP_SET_PHY_CONFIGURATION,
+ .send_param = set_phy_param_invalid,
+ .send_len = sizeof(set_phy_param_invalid),
+ .expect_status = MGMT_STATUS_INVALID_PARAMS,
+};
+
+
static bool power_off(uint16_t index)
{
int sk, err;
@@ -9958,5 +10117,26 @@ int main(int argc, char *argv[])
setup_add_advertising_duration,
test_command_generic, 3);

+ test_bredrle50("Get PHY Success", &get_phy_success,
+ NULL, test_command_generic);
+
+ test_bredrle50("Set PHY 2m Success", &set_phy_2m_success,
+ NULL, test_command_generic);
+
+ test_bredrle50("Set PHY coded Succcess", &set_phy_coded_success,
+ NULL, test_command_generic);
+
+ test_bredrle50("Set PHY 1m 2m coded Succcess", &set_phy_all_success,
+ NULL, test_command_generic);
+
+ test_bredrle50("Set PHY 2m tx success", &set_phy_2m_tx_success,
+ NULL, test_command_generic);
+
+ test_bredrle50("Set PHY 2m rx success", &set_phy_2m_rx_success,
+ NULL, test_command_generic);
+
+ test_bredrle50("Set PHY Invalid Param", &set_phy_invalid_param,
+ NULL, test_command_generic);
+
return tester_run();
}
--
2.7.4


2018-04-12 11:20:58

by Jaganath K

[permalink] [raw]
Subject: [PATCH v1 07/10] mgmt-tester: Add extended advertising test cases

---
emulator/btdev.c | 274 +++++++-
emulator/btdev.h | 1 +
emulator/hciemu.c | 3 +
emulator/hciemu.h | 1 +
monitor/bt.h | 1 +
tools/mgmt-tester.c | 1788 ++++++++++++++++++++++++++++++++++++++++++++++++---
6 files changed, 1969 insertions(+), 99 deletions(-)

diff --git a/emulator/btdev.c b/emulator/btdev.c
index 69d84a5..ad4f873 100644
--- a/emulator/btdev.c
+++ b/emulator/btdev.c
@@ -145,6 +145,9 @@ struct btdev {
uint16_t sync_train_interval;
uint32_t sync_train_timeout;
uint8_t sync_train_service_data;
+
+ uint16_t le_ext_adv_type;
+ uint8_t le_adv_primary_phy;
};

struct inquiry_data {
@@ -469,6 +472,34 @@ static void set_bredrle_commands(struct btdev *btdev)
btdev->commands[32] |= 0x40; /* Read Local OOB Extended Data */
}

+static void set_bredrle50_commands(struct btdev *btdev)
+{
+ set_bredrle_commands(btdev);
+
+ btdev->commands[36] |= 0x02; /* LE Set Advertising Set Random Address */
+ btdev->commands[36] |= 0x04; /* LE Set Extended Advertising Parameters */
+ btdev->commands[36] |= 0x08; /* LE Set Extended Advertising Data */
+ btdev->commands[36] |= 0x10; /* LE Set Extended Scan Response Data */
+ btdev->commands[36] |= 0x20; /* LE Set Extended Advertising Enable */
+ btdev->commands[36] |= 0x40; /* LE Read Maximum Advertising Data Length */
+ btdev->commands[36] |= 0x80; /* LE Read Number of Supported Advertising Sets */
+ btdev->commands[37] |= 0x01; /* LE Remove Advertising Set */
+ btdev->commands[37] |= 0x02; /* LE Clear Advertising Sets */
+ btdev->commands[37] |= 0x04; /* LE Set Periodic Advertising Parameters */
+ btdev->commands[37] |= 0x08; /* LE Set Periodic Advertising Data */
+ btdev->commands[37] |= 0x10; /* LE Set Periodic Advertising Enable */
+ btdev->commands[37] |= 0x20; /* LE Set Extended Scan Parameters */
+ btdev->commands[37] |= 0x40; /* LE Set Extended Scan Enable */
+ btdev->commands[37] |= 0x80; /* LE Extended Create Connection */
+ btdev->commands[38] |= 0x01; /* LE Periodic Advertising Create Sync */
+ btdev->commands[38] |= 0x02; /* LE Periodic Advertising Create Sync Cancel */
+ btdev->commands[38] |= 0x04; /* LE Periodic Advertising Terminate Sync */
+ btdev->commands[38] |= 0x08; /* LE Add Device To Periodic Advertiser List */
+ btdev->commands[38] |= 0x10; /* LE Remove Device From Periodic Advertiser List */
+ btdev->commands[38] |= 0x20; /* LE Clear Periodic Advertiser List */
+ btdev->commands[38] |= 0x40; /* LE Read Periodic Advertiser List Size */
+}
+
static void set_amp_commands(struct btdev *btdev)
{
set_common_commands_all(btdev);
@@ -570,6 +601,15 @@ static void set_le_features(struct btdev *btdev)
btdev->le_features[0] |= 0x08; /* Slave-initiated Features Exchange */
}

+static void set_bredrle50_features(struct btdev *btdev)
+{
+ set_bredrle_features(btdev);
+
+ btdev->le_features[1] |= 0x01; /* LE 2M PHY */
+ btdev->le_features[1] |= 0x08; /* LE Coded PHY */
+ btdev->le_features[1] |= 0x10; /* LE EXT ADV */
+}
+
static void set_le_states(struct btdev *btdev)
{
/* Set all 41 bits as per Bluetooth 5.0 specification */
@@ -637,6 +677,12 @@ struct btdev *btdev_create(enum btdev_type type, uint16_t id)
set_bredr20_features(btdev);
set_bredr20_commands(btdev);
break;
+ case BTDEV_TYPE_BREDRLE50:
+ btdev->version = 0x05;
+ set_bredrle50_features(btdev);
+ set_bredrle50_commands(btdev);
+ set_le_states(btdev);
+ break;
}

btdev->page_scan_interval = 0x0800;
@@ -1202,6 +1248,18 @@ static bool adv_match(struct btdev *scan, struct btdev *adv)
return !memcmp(scan_addr(scan), adv->le_adv_direct_addr, 6);
}

+static bool ext_adv_match(struct btdev *scan, struct btdev *adv)
+{
+ /* Match everything if this is not directed advertising */
+ if (!(adv->le_ext_adv_type & 0x04))
+ return true;
+
+ if (scan->le_scan_own_addr_type != adv->le_adv_direct_addr_type)
+ return false;
+
+ return !memcmp(scan_addr(scan), adv->le_adv_direct_addr, 6);
+}
+
static bool adv_connectable(struct btdev *btdev)
{
if (!btdev->le_adv_enable)
@@ -1851,6 +1909,47 @@ static void le_send_adv_report(struct btdev *btdev, const struct btdev *remote,
1 + 10 + meta_event.lar.data_len + 1);
}

+static void le_send_ext_adv_report(struct btdev *btdev,
+ const struct btdev *remote,
+ uint16_t type, bool is_scan_rsp)
+{
+ struct __packed {
+ uint8_t subevent;
+ uint8_t num_reports;
+ union {
+ struct bt_hci_le_ext_adv_report lear;
+ uint8_t raw[24 + 31];
+ };
+ } meta_event;
+
+ meta_event.subevent = BT_HCI_EVT_LE_EXT_ADV_REPORT;
+
+ memset(&meta_event.lear, 0, sizeof(meta_event.lear));
+ meta_event.num_reports = 1;
+ meta_event.lear.event_type = cpu_to_le16(type);
+ meta_event.lear.addr_type = remote->le_adv_own_addr;
+ memcpy(meta_event.lear.addr, adv_addr(remote), 6);
+ meta_event.lear.rssi = 127;
+ meta_event.lear.tx_power = 127;
+ /* Right now we dont care about phy in adv report */
+ meta_event.lear.primary_phy = 0x01;
+ meta_event.lear.secondary_phy = 0x01;
+
+ /* Scan or advertising response */
+ if (is_scan_rsp) {
+ meta_event.lear.data_len = remote->le_scan_data_len;
+ memcpy(meta_event.lear.data, remote->le_scan_data,
+ meta_event.lear.data_len);
+ } else {
+ meta_event.lear.data_len = remote->le_adv_data_len;
+ memcpy(meta_event.lear.data, remote->le_adv_data,
+ meta_event.lear.data_len);
+ }
+
+ send_event(btdev, BT_HCI_EVT_LE_META_EVENT, &meta_event,
+ 1 + 1 + 24 + meta_event.lear.data_len);
+}
+
static uint8_t get_adv_report_type(uint8_t adv_type)
{
/*
@@ -1863,6 +1962,22 @@ static uint8_t get_adv_report_type(uint8_t adv_type)
return adv_type;
}

+static uint8_t get_ext_adv_report_type(uint8_t ext_adv_type)
+{
+ /* If legacy bit is not set then just reset high duty cycle directed bit */
+ if (!(ext_adv_type & 0x10))
+ return (ext_adv_type & 0xf7);
+
+ /*
+ * Connectable low duty cycle directed advertising creates a
+ * connectable directed advertising report type.
+ */
+ if (ext_adv_type == 0x001d)
+ return 0x0015;
+
+ return ext_adv_type;
+}
+
static void le_set_adv_enable_complete(struct btdev *btdev)
{
uint8_t report_type;
@@ -1891,6 +2006,44 @@ static void le_set_adv_enable_complete(struct btdev *btdev)
}
}

+static void le_set_ext_adv_enable_complete(struct btdev *btdev)
+{
+ uint16_t report_type;
+ int i;
+
+ report_type = get_ext_adv_report_type(btdev->le_ext_adv_type);
+
+ for (i = 0; i < MAX_BTDEV_ENTRIES; i++) {
+ if (!btdev_list[i] || btdev_list[i] == btdev)
+ continue;
+
+ if (!btdev_list[i]->le_scan_enable)
+ continue;
+
+ if (!ext_adv_match(btdev_list[i], btdev))
+ continue;
+
+ le_send_ext_adv_report(btdev_list[i], btdev, report_type, false);
+
+ if (btdev_list[i]->le_scan_type != 0x01)
+ continue;
+
+ /* if scannable bit is set the send scan response */
+ if (btdev->le_ext_adv_type & 0x02) {
+ if (btdev->le_ext_adv_type == 0x13)
+ report_type = 0x1b;
+ else if (btdev->le_ext_adv_type == 0x12)
+ report_type = 0x1a;
+ else if (!(btdev->le_ext_adv_type & 0x10))
+ report_type &= 0x08;
+ else
+ continue;
+
+ le_send_ext_adv_report(btdev_list[i], btdev, report_type, true);
+ }
+ }
+}
+
static void le_set_scan_enable_complete(struct btdev *btdev)
{
int i;
@@ -2086,6 +2239,11 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode,
const struct bt_hci_cmd_read_local_amp_assoc *rlaa_cmd;
const struct bt_hci_cmd_read_rssi *rrssi;
const struct bt_hci_cmd_read_tx_power *rtxp;
+ const struct bt_hci_cmd_le_set_adv_set_rand_addr *lsasra;
+ const struct bt_hci_cmd_le_set_ext_adv_params *lseap;
+ const struct bt_hci_cmd_le_set_ext_adv_enable *lseae;
+ const struct bt_hci_cmd_le_set_ext_adv_data *lsead;
+ const struct bt_hci_cmd_le_set_ext_scan_rsp_data *lsesrd;
struct bt_hci_rsp_read_default_link_policy rdlp;
struct bt_hci_rsp_read_stored_link_key rslk;
struct bt_hci_rsp_write_stored_link_key wslk;
@@ -2145,6 +2303,8 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode,
struct bt_hci_rsp_read_tx_power rtxp_rsp;
struct bt_hci_evt_le_read_local_pk256_complete pk_evt;
struct bt_hci_evt_le_generate_dhkey_complete dh_evt;
+ struct bt_hci_rsp_le_read_num_supported_adv_sets rlrnsas;
+ struct bt_hci_rsp_le_set_ext_adv_params rlseap;
uint8_t status, page;

switch (opcode) {
@@ -2679,7 +2839,8 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode,
break;

case BT_HCI_CMD_READ_LE_HOST_SUPPORTED:
- if (btdev->type != BTDEV_TYPE_BREDRLE)
+ if (btdev->type != BTDEV_TYPE_BREDRLE &&
+ btdev->type != BTDEV_TYPE_BREDRLE50)
goto unsupported;
rlhs.status = BT_HCI_ERR_SUCCESS;
rlhs.supported = btdev->le_supported;
@@ -2688,7 +2849,8 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode,
break;

case BT_HCI_CMD_WRITE_LE_HOST_SUPPORTED:
- if (btdev->type != BTDEV_TYPE_BREDRLE)
+ if (btdev->type != BTDEV_TYPE_BREDRLE &&
+ btdev->type != BTDEV_TYPE_BREDRLE50)
goto unsupported;
wlhs = data;
btdev->le_supported = wlhs->supported;
@@ -2698,7 +2860,8 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode,
break;

case BT_HCI_CMD_READ_SECURE_CONN_SUPPORT:
- if (btdev->type != BTDEV_TYPE_BREDRLE)
+ if (btdev->type != BTDEV_TYPE_BREDRLE &&
+ btdev->type != BTDEV_TYPE_BREDRLE50)
goto unsupported;
rscs.status = BT_HCI_ERR_SUCCESS;
rscs.support = btdev->secure_conn_support;
@@ -2706,7 +2869,8 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode,
break;

case BT_HCI_CMD_WRITE_SECURE_CONN_SUPPORT:
- if (btdev->type != BTDEV_TYPE_BREDRLE)
+ if (btdev->type != BTDEV_TYPE_BREDRLE &&
+ btdev->type != BTDEV_TYPE_BREDRLE50)
goto unsupported;
wscs = data;
btdev->secure_conn_support = wscs->support;
@@ -2715,14 +2879,16 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode,
break;

case BT_HCI_CMD_READ_LOCAL_OOB_EXT_DATA:
- if (btdev->type != BTDEV_TYPE_BREDRLE)
+ if (btdev->type != BTDEV_TYPE_BREDRLE &&
+ btdev->type != BTDEV_TYPE_BREDRLE50)
goto unsupported;
rloed.status = BT_HCI_ERR_SUCCESS;
cmd_complete(btdev, opcode, &rloed, sizeof(rloed));
break;

case BT_HCI_CMD_READ_SYNC_TRAIN_PARAMS:
- if (btdev->type != BTDEV_TYPE_BREDRLE)
+ if (btdev->type != BTDEV_TYPE_BREDRLE &&
+ btdev->type != BTDEV_TYPE_BREDRLE50)
goto unsupported;
rstp.status = BT_HCI_ERR_SUCCESS;
rstp.interval = cpu_to_le16(btdev->sync_train_interval);
@@ -2872,7 +3038,8 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode,

case BT_HCI_CMD_READ_ENCRYPT_KEY_SIZE:
if (btdev->type != BTDEV_TYPE_BREDRLE &&
- btdev->type != BTDEV_TYPE_BREDR)
+ btdev->type != BTDEV_TYPE_BREDR &&
+ btdev->type != BTDEV_TYPE_BREDRLE50)
goto unsupported;
reks = data;
read_enc_key_size_complete(btdev, le16_to_cpu(reks->handle));
@@ -2918,7 +3085,8 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode,
break;

case BT_HCI_CMD_SET_EVENT_MASK_PAGE2:
- if (btdev->type != BTDEV_TYPE_BREDRLE)
+ if (btdev->type != BTDEV_TYPE_BREDRLE &&
+ btdev->type != BTDEV_TYPE_BREDRLE50)
goto unsupported;
semp2 = data;
memcpy(btdev->event_mask_page2, semp2->mask, 8);
@@ -3245,6 +3413,96 @@ static void default_cmd(struct btdev *btdev, uint16_t opcode,
lcprnr_rsp.status = BT_HCI_ERR_SUCCESS;
cmd_complete(btdev, opcode, &lcprnr_rsp, sizeof(lcprnr_rsp));
break;
+ case BT_HCI_CMD_LE_READ_NUM_SUPPORTED_ADV_SETS:
+ if (btdev->type != BTDEV_TYPE_BREDRLE50)
+ goto unsupported;
+
+ rlrnsas.status = BT_HCI_ERR_SUCCESS;
+ /* Support one set as of now */
+ rlrnsas.num_of_sets = 1;
+ cmd_complete(btdev, opcode, &rlrnsas, sizeof(rlrnsas));
+ break;
+ case BT_HCI_CMD_LE_SET_ADV_SET_RAND_ADDR:
+ if (btdev->type != BTDEV_TYPE_BREDRLE50)
+ goto unsupported;
+
+ lsasra = data;
+ memcpy(btdev->random_addr, lsasra->bdaddr, 6);
+ status = BT_HCI_ERR_SUCCESS;
+ cmd_complete(btdev, opcode, &status, sizeof(status));
+ break;
+ case BT_HCI_CMD_LE_SET_EXT_ADV_PARAMS:
+ if (btdev->type != BTDEV_TYPE_BREDRLE50)
+ goto unsupported;
+
+ if (btdev->le_adv_enable) {
+ status = BT_HCI_ERR_COMMAND_DISALLOWED;
+ cmd_complete(btdev, opcode, &status, sizeof(status));
+ break;
+ }
+
+ lseap = data;
+ btdev->le_ext_adv_type = le16_to_cpu(lseap->evt_properties);
+ btdev->le_adv_primary_phy = lseap->primary_phy;
+ btdev->le_adv_own_addr = lseap->own_addr_type;
+ btdev->le_adv_direct_addr_type = lseap->peer_addr_type;
+ memcpy(btdev->le_adv_direct_addr, lseap->peer_addr, 6);
+
+ rlseap.status = BT_HCI_ERR_SUCCESS;
+ rlseap.tx_power = 0;
+ cmd_complete(btdev, opcode, &rlseap, sizeof(rlseap));
+ break;
+ case BT_HCI_CMD_LE_SET_EXT_ADV_ENABLE:
+ if (btdev->type != BTDEV_TYPE_BREDRLE50)
+ goto unsupported;
+
+ lseae = data;
+ if (btdev->le_adv_enable == lseae->enable)
+ status = BT_HCI_ERR_COMMAND_DISALLOWED;
+ else {
+ btdev->le_adv_enable = lseae->enable;
+ status = BT_HCI_ERR_SUCCESS;
+ }
+ cmd_complete(btdev, opcode, &status, sizeof(status));
+ if (status == BT_HCI_ERR_SUCCESS && btdev->le_adv_enable)
+ le_set_ext_adv_enable_complete(btdev);
+ break;
+ case BT_HCI_CMD_LE_SET_EXT_ADV_DATA:
+ if (btdev->type != BTDEV_TYPE_BREDRLE50)
+ goto unsupported;
+
+ lsead = data;
+ btdev->le_adv_data_len = lsead->data_len;
+ memcpy(btdev->le_adv_data, lsead->data, 31);
+ status = BT_HCI_ERR_SUCCESS;
+ cmd_complete(btdev, opcode, &status, sizeof(status));
+ break;
+ case BT_HCI_CMD_LE_SET_EXT_SCAN_RSP_DATA:
+ if (btdev->type != BTDEV_TYPE_BREDRLE50)
+ goto unsupported;
+
+ lsesrd = data;
+ btdev->le_scan_data_len = lsesrd->data_len;
+ memcpy(btdev->le_scan_data, lsesrd->data, 31);
+ status = BT_HCI_ERR_SUCCESS;
+ cmd_complete(btdev, opcode, &status, sizeof(status));
+ break;
+ case BT_HCI_CMD_LE_REMOVE_ADV_SET:
+ if (btdev->type != BTDEV_TYPE_BREDRLE50)
+ goto unsupported;
+
+ status = BT_HCI_ERR_SUCCESS;
+ cmd_complete(btdev, opcode, &status, sizeof(status));
+ break;
+ case BT_HCI_CMD_LE_CLEAR_ADV_SETS:
+ if (btdev->type != BTDEV_TYPE_BREDRLE50)
+ goto unsupported;
+
+ status = BT_HCI_ERR_SUCCESS;
+ cmd_complete(btdev, opcode, &status, sizeof(status));
+ break;
+
+
default:
goto unsupported;
}
diff --git a/emulator/btdev.h b/emulator/btdev.h
index ba06a10..362d1e7 100644
--- a/emulator/btdev.h
+++ b/emulator/btdev.h
@@ -63,6 +63,7 @@ enum btdev_type {
BTDEV_TYPE_LE,
BTDEV_TYPE_AMP,
BTDEV_TYPE_BREDR20,
+ BTDEV_TYPE_BREDRLE50,
};

enum btdev_hook_type {
diff --git a/emulator/hciemu.c b/emulator/hciemu.c
index 1787a6c..bc36773 100644
--- a/emulator/hciemu.c
+++ b/emulator/hciemu.c
@@ -331,6 +331,9 @@ struct hciemu *hciemu_new(enum hciemu_type type)
case HCIEMU_TYPE_LEGACY:
hciemu->btdev_type = BTDEV_TYPE_BREDR20;
break;
+ case HCIEMU_TYPE_BREDRLE50:
+ hciemu->btdev_type = BTDEV_TYPE_BREDRLE50;
+ break;
default:
return NULL;
}
diff --git a/emulator/hciemu.h b/emulator/hciemu.h
index 5c0c4c3..e37c069 100644
--- a/emulator/hciemu.h
+++ b/emulator/hciemu.h
@@ -31,6 +31,7 @@ enum hciemu_type {
HCIEMU_TYPE_BREDR,
HCIEMU_TYPE_LE,
HCIEMU_TYPE_LEGACY,
+ HCIEMU_TYPE_BREDRLE50,
};

enum hciemu_hook_type {
diff --git a/monitor/bt.h b/monitor/bt.h
index 595b6a7..ec62864 100644
--- a/monitor/bt.h
+++ b/monitor/bt.h
@@ -3010,6 +3010,7 @@ struct bt_hci_le_ext_adv_report {
uint8_t direct_addr_type;
uint8_t direct_addr[6];
uint8_t data_len;
+ uint8_t data[0];
} __attribute__ ((packed));

#define BT_HCI_EVT_LE_ADV_SET_TERM 0x12
diff --git a/tools/mgmt-tester.c b/tools/mgmt-tester.c
index bc71791..660a3b4 100644
--- a/tools/mgmt-tester.c
+++ b/tools/mgmt-tester.c
@@ -462,6 +462,25 @@ static void test_condition_complete(struct test_data *data)
#define test_le(name, data, setup, func) \
test_le_full(name, data, setup, func, 2)

+#define test_bredrle50_full(name, data, setup, func, timeout) \
+ do { \
+ struct test_data *user; \
+ user = new0(struct test_data, 1); \
+ user->hciemu_type = HCIEMU_TYPE_BREDRLE50; \
+ user->test_setup = setup; \
+ user->test_data = data; \
+ user->expected_version = 0x05; \
+ user->expected_manufacturer = 0x003f; \
+ user->expected_supported_settings = 0x0001bfff; \
+ user->initial_settings = 0x00000080; \
+ tester_add_full(name, data, \
+ test_pre_setup, test_setup, func, NULL, \
+ test_post_teardown, timeout, user, free); \
+ } while (0)
+
+#define test_bredrle50(name, data, setup, func) \
+ test_bredrle50_full(name, data, setup, func, 2)
+
static void controller_setup(const void *test_data)
{
tester_test_passed();
@@ -6852,120 +6871,1465 @@ static const struct generic_data set_appearance_success = {
.expect_len = 0,
};

-static bool power_off(uint16_t index)
-{
- int sk, err;
-
- sk = hci_open_dev(index);
- if (sk < 0)
- return false;
+static const uint8_t read_adv_features_rsp_3[] = {
+ 0xff, 0x03, 0x00, 0x00, /* supported flags */
+ 0x1f, /* max_adv_data_len */
+ 0x1f, /* max_scan_rsp_len */
+ 0x05, /* max_instances */
+ 0x00, /* num_instances */
+};

- err = ioctl(sk, HCIDEVDOWN, index);
+static const struct generic_data read_adv_features_success_3 = {
+ .send_opcode = MGMT_OP_READ_ADV_FEATURES,
+ .expect_param = read_adv_features_rsp_3,
+ .expect_len = sizeof(read_adv_features_rsp_3),
+ .expect_status = MGMT_STATUS_SUCCESS,
+};

- hci_close_dev(sk);
+/* add advertising with multiple phy flags */
+static const uint8_t add_ext_advertising_invalid_param_1[] = {
+ 0x01, /* adv instance */
+ 0x80, 0x01, 0x00, 0x00, /* flags: 1m and 2m*/
+ 0x00, 0x00, 0x00, 0x00, 0x09, 0x00,
+ 0x03, 0x02, 0x0d, 0x18, 0x04, 0xff, 0x01, 0x02, 0x03,
+};

- if (err < 0)
- return false;
+static const struct generic_data add_ext_advertising_fail_1 = {
+ .setup_settings = settings_powered_le,
+ .send_opcode = MGMT_OP_ADD_ADVERTISING,
+ .send_param = add_ext_advertising_invalid_param_1,
+ .send_len = sizeof(add_ext_advertising_invalid_param_1),
+ .expect_status = MGMT_STATUS_INVALID_PARAMS,
+};

- return true;
-}
+/* add advertising with multiple phy flags */
+static const uint8_t add_ext_advertising_invalid_param_2[] = {
+ 0x01, /* adv instance */
+ 0x00, 0x03, 0x00, 0x00, /* flags: 2m and coded*/
+ 0x00, 0x00, 0x00, 0x00, 0x09, 0x00,
+ 0x03, 0x02, 0x0d, 0x18, 0x04, 0xff, 0x01, 0x02, 0x03,
+};

-static void test_command_generic(const void *test_data)
-{
- struct test_data *data = tester_get_data();
- const struct generic_data *test = data->test_data;
- const void *send_param = test->send_param;
- uint16_t send_len = test->send_len;
- unsigned int id;
- uint16_t index;
+static const struct generic_data add_ext_advertising_fail_2 = {
+ .setup_settings = settings_powered_le,
+ .send_opcode = MGMT_OP_ADD_ADVERTISING,
+ .send_param = add_ext_advertising_invalid_param_2,
+ .send_len = sizeof(add_ext_advertising_invalid_param_2),
+ .expect_status = MGMT_STATUS_INVALID_PARAMS,
+};

- index = test->send_index_none ? MGMT_INDEX_NONE : data->mgmt_index;
+/* add advertising with multiple phy flags */
+static const uint8_t add_ext_advertising_invalid_param_3[] = {
+ 0x01, /* adv instance */
+ 0x80, 0x02, 0x00, 0x00, /* flags: 1m and coded*/
+ 0x00, 0x00, 0x00, 0x00, 0x09, 0x00,
+ 0x03, 0x02, 0x0d, 0x18, 0x04, 0xff, 0x01, 0x02, 0x03,
+};

- if (test->expect_settings_set || test->expect_settings_unset) {
- tester_print("Registering new settings notification");
+static const struct generic_data add_ext_advertising_fail_3 = {
+ .setup_settings = settings_powered_le,
+ .send_opcode = MGMT_OP_ADD_ADVERTISING,
+ .send_param = add_ext_advertising_invalid_param_3,
+ .send_len = sizeof(add_ext_advertising_invalid_param_3),
+ .expect_status = MGMT_STATUS_INVALID_PARAMS,
+};

- id = mgmt_register(data->mgmt, MGMT_EV_NEW_SETTINGS, index,
- command_generic_new_settings, NULL, NULL);
- data->mgmt_settings_id = id;
+/* add advertising with multiple phy flags */
+static const uint8_t add_ext_advertising_invalid_param_4[] = {
+ 0x01, /* adv instance */
+ 0x80, 0x03, 0x00, 0x00, /* flags: 1m, 2m and coded*/
+ 0x00, 0x00, 0x00, 0x00, 0x09, 0x00,
+ 0x03, 0x02, 0x0d, 0x18, 0x04, 0xff, 0x01, 0x02, 0x03,
+};

- id = mgmt_register(data->mgmt_alt, MGMT_EV_NEW_SETTINGS, index,
- command_generic_new_settings_alt, NULL, NULL);
- data->mgmt_alt_settings_id = id;
- test_add_condition(data);
- }
+static const struct generic_data add_ext_advertising_fail_4 = {
+ .setup_settings = settings_powered_le,
+ .send_opcode = MGMT_OP_ADD_ADVERTISING,
+ .send_param = add_ext_advertising_invalid_param_4,
+ .send_len = sizeof(add_ext_advertising_invalid_param_4),
+ .expect_status = MGMT_STATUS_INVALID_PARAMS,
+};

- if (test->expect_alt_ev) {
- tester_print("Registering %s notification",
- mgmt_evstr(test->expect_alt_ev));
- id = mgmt_register(data->mgmt_alt, test->expect_alt_ev, index,
- command_generic_event_alt, NULL, NULL);
- data->mgmt_alt_ev_id = id;
- test_add_condition(data);
- }
+static const uint8_t set_ext_adv_data_uuid[] = {
+ /* handle */
+ 0x00,
+ /* complete data */
+ 0x03,
+ /* controller should not fragment */
+ 0x01,
+ /* adv data len */
+ 0x09,
+ /* advertise heart rate monitor and manufacturer specific data */
+ 0x03, 0x02, 0x0d, 0x18, 0x04, 0xff, 0x01, 0x02, 0x03,
+ /* padding */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00
+};

- if (test->expect_hci_command) {
- tester_print("Registering HCI command callback");
- hciemu_add_master_post_command_hook(data->hciemu,
- command_hci_callback, data);
- test_add_condition(data);
- }
+static const struct generic_data add_ext_advertising_success_1 = {
+ .setup_settings = settings_powered_le,
+ .send_opcode = MGMT_OP_ADD_ADVERTISING,
+ .send_param = add_advertising_param_uuid,
+ .send_len = sizeof(add_advertising_param_uuid),
+ .expect_param = advertising_instance1_param,
+ .expect_len = sizeof(advertising_instance1_param),
+ .expect_status = MGMT_STATUS_SUCCESS,
+ .expect_alt_ev = MGMT_EV_ADVERTISING_ADDED,
+ .expect_alt_ev_param = advertising_instance1_param,
+ .expect_alt_ev_len = sizeof(advertising_instance1_param),
+ .expect_hci_command = BT_HCI_CMD_LE_SET_EXT_ADV_DATA,
+ .expect_hci_param = set_ext_adv_data_uuid,
+ .expect_hci_len = sizeof(set_ext_adv_data_uuid),
+};

- if (test->send_opcode == 0x0000) {
- tester_print("Executing no-op test");
- return;
- }
+static const char set_powered_ext_adv_instance_settings_param[] = {
+ 0x81, 0x02, 0x00, 0x00,
+};

- tester_print("Sending %s (0x%04x)", mgmt_opstr(test->send_opcode),
- test->send_opcode);
+static const uint8_t set_ext_adv_data_test1[] = {
+ 0x00, /* handle */
+ 0x03, /* complete data */
+ 0x01, /* controller should not fragment */
+ 0x07, /* adv data len */
+ 0x06, /* AD len */
+ 0x08, /* AD type: shortened local name */
+ 0x74, 0x65, 0x73, 0x74, 0x31, /* "test1" */
+ /* padding */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+};

- if (test->send_func)
- send_param = test->send_func(&send_len);
+static const struct generic_data add_ext_advertising_success_pwron_data = {
+ .send_opcode = MGMT_OP_SET_POWERED,
+ .send_param = set_powered_on_param,
+ .send_len = sizeof(set_powered_on_param),
+ .expect_status = MGMT_STATUS_SUCCESS,
+ .expect_param = set_powered_adv_instance_settings_param,
+ .expect_len = sizeof(set_powered_adv_instance_settings_param),
+ .expect_hci_command = BT_HCI_CMD_LE_SET_EXT_ADV_DATA,
+ .expect_hci_param = set_ext_adv_data_test1,
+ .expect_hci_len = sizeof(set_ext_adv_data_test1),
+};

- if (test->force_power_off) {
- mgmt_send_nowait(data->mgmt, test->send_opcode, index,
- send_len, send_param,
- command_generic_callback, NULL, NULL);
- power_off(data->mgmt_index);
- } else {
- mgmt_send(data->mgmt, test->send_opcode, index, send_len,
- send_param, command_generic_callback,
- NULL, NULL);
- }
+static const char set_ext_adv_on_set_adv_enable_param[] = {
+ 0x01, /* Enable */
+ 0x01, /* No of sets */
+ 0x00, /* Handle */
+ 0x00, 0x00, /* Duration */
+ 0x00, /* Max events */
+};

- test_add_condition(data);
-}
+static const struct generic_data add_ext_advertising_success_pwron_enabled = {
+ .send_opcode = MGMT_OP_SET_POWERED,
+ .send_param = set_powered_on_param,
+ .send_len = sizeof(set_powered_on_param),
+ .expect_status = MGMT_STATUS_SUCCESS,
+ .expect_param = set_powered_adv_instance_settings_param,
+ .expect_len = sizeof(set_powered_adv_instance_settings_param),
+ .expect_hci_command = BT_HCI_CMD_LE_SET_EXT_ADV_ENABLE,
+ .expect_hci_param = set_ext_adv_on_set_adv_enable_param,
+ .expect_hci_len = sizeof(set_ext_adv_on_set_adv_enable_param),
+};

-static void check_scan(void *user_data)
-{
- struct test_data *data = tester_get_data();
+static const uint8_t set_ext_adv_data_txpwr[] = {
+ 0x00, /* handle */
+ 0x03, /* complete data */
+ 0x01, /* controller should not fragment */
+ 0x03, /* adv data len */
+ 0x02, /* AD len */
+ 0x0a, /* AD type: tx power */
+ 0x00, /* tx power */
+ /* padding */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};

- if (hciemu_get_master_le_scan_enable(data->hciemu)) {
- tester_warn("LE scan still enabled");
- tester_test_failed();
- return;
- }
+static const struct generic_data add_ext_advertising_success_4 = {
+ .send_opcode = MGMT_OP_SET_ADVERTISING,
+ .send_param = set_adv_on_param,
+ .send_len = sizeof(set_adv_on_param),
+ .expect_status = MGMT_STATUS_SUCCESS,
+ .expect_param = set_adv_settings_param_2,
+ .expect_len = sizeof(set_adv_settings_param_2),
+ .expect_hci_command = BT_HCI_CMD_LE_SET_EXT_ADV_DATA,
+ .expect_hci_param = set_ext_adv_data_txpwr,
+ .expect_hci_len = sizeof(set_ext_adv_data_txpwr),
+};

- if (hciemu_get_master_scan_enable(data->hciemu)) {
- tester_warn("BR/EDR scan still enabled");
- tester_test_failed();
- return;
- }
+static const struct generic_data add_ext_advertising_success_5 = {
+ .send_opcode = MGMT_OP_SET_ADVERTISING,
+ .send_param = set_adv_off_param,
+ .send_len = sizeof(set_adv_off_param),
+ .expect_status = MGMT_STATUS_SUCCESS,
+ .expect_param = set_powered_adv_instance_settings_param,
+ .expect_len = sizeof(set_powered_adv_instance_settings_param),
+ .expect_hci_command = BT_HCI_CMD_LE_SET_EXT_ADV_DATA,
+ .expect_hci_param = set_ext_adv_data_test1,
+ .expect_hci_len = sizeof(set_ext_adv_data_test1),
+};

- test_condition_complete(data);
-}
+static const struct generic_data add_ext_advertising_success_6 = {
+ .setup_settings = settings_powered_le,
+ .send_opcode = MGMT_OP_ADD_ADVERTISING,
+ .send_param = add_advertising_param_scanrsp,
+ .send_len = sizeof(add_advertising_param_scanrsp),
+ .expect_param = advertising_instance1_param,
+ .expect_len = sizeof(advertising_instance1_param),
+ .expect_status = MGMT_STATUS_SUCCESS,
+ .expect_alt_ev = MGMT_EV_ADVERTISING_ADDED,
+ .expect_alt_ev_param = advertising_instance1_param,
+ .expect_alt_ev_len = sizeof(advertising_instance1_param),
+ .expect_hci_command = BT_HCI_CMD_LE_SET_EXT_ADV_DATA,
+ .expect_hci_param = set_ext_adv_data_uuid,
+ .expect_hci_len = sizeof(set_ext_adv_data_uuid),
+};

-static void test_remove_device(const void *test_data)
-{
- struct test_data *data = tester_get_data();
+static const uint8_t set_ext_scan_rsp_uuid[] = {
+ 0x00, /* handle */
+ 0x03, /* complete data */
+ 0x01, /* controller should not fragment */
+ 0x0a, /* scan rsp data len */
+ 0x03, /* AD len */
+ 0x19, /* AD type: external appearance */
+ 0x40, 0x03, /* some custom appearance */
+ 0x05, /* AD len */
+ 0x03, /* AD type: all 16 bit service class UUIDs */
+ 0x0d, 0x18, 0x0f, 0x18, /* heart rate monitor, battery service */
+ /* padding */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00,
+};

- test_command_generic(test_data);
- tester_wait(1, check_scan, NULL);
- test_add_condition(data);
-}
+static const struct generic_data add_ext_advertising_success_7 = {
+ .setup_settings = settings_powered_le,
+ .send_opcode = MGMT_OP_ADD_ADVERTISING,
+ .send_param = add_advertising_param_scanrsp,
+ .send_len = sizeof(add_advertising_param_scanrsp),
+ .expect_param = advertising_instance1_param,
+ .expect_len = sizeof(advertising_instance1_param),
+ .expect_status = MGMT_STATUS_SUCCESS,
+ .expect_alt_ev = MGMT_EV_ADVERTISING_ADDED,
+ .expect_alt_ev_param = advertising_instance1_param,
+ .expect_alt_ev_len = sizeof(advertising_instance1_param),
+ .expect_hci_command = BT_HCI_CMD_LE_SET_EXT_SCAN_RSP_DATA,
+ .expect_hci_param = set_ext_scan_rsp_uuid,
+ .expect_hci_len = sizeof(set_ext_scan_rsp_uuid),
+};
+
+static uint8_t set_connectable_on_ext_adv_param[] = {
+ 0x00, /* Handle */
+ 0x13, 0x00, /* Event type */
+ 0x00, 0x08, 0x00, /* min_interval */
+ 0x00, 0x08, 0x00, /* max_interval */
+ 0x07, /* channel_map */
+ 0x00, /* own_addr_type */
+ 0x00, /* peer_addr_type */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* peer_addr */
+ 0x00, /* filter_policy */
+ 127, /* Tx power */
+ 0x01, /* Primary PHY */
+ 0x00, /* primary adv max skip */
+ 0x01, /* Secondary PHY */
+ 0x00, /* adv sid*/
+ 0x00, /* Scan req notification */
+};
+
+static const struct generic_data add_ext_advertising_success_8 = {
+ .setup_settings = settings_powered_le,
+ .send_opcode = MGMT_OP_ADD_ADVERTISING,
+ .send_param = add_advertising_param_connectable,
+ .send_len = sizeof(add_advertising_param_connectable),
+ .expect_param = advertising_instance1_param,
+ .expect_len = sizeof(advertising_instance1_param),
+ .expect_status = MGMT_STATUS_SUCCESS,
+ .expect_hci_command = BT_HCI_CMD_LE_SET_EXT_ADV_PARAMS,
+ .expect_hci_param = set_connectable_on_ext_adv_param,
+ .expect_hci_len = sizeof(set_connectable_on_ext_adv_param),
+};

-static void trigger_device_found(void *user_data)
-{
- struct test_data *data = tester_get_data();
+static const uint8_t set_ext_adv_data_general_discov[] = {
+ 0x00, /* handle */
+ 0x03, /* complete data */
+ 0x01, /* controller should not fragment */
+ 0x0c, /* adv data len */
+ 0x02, /* AD len */
+ 0x01, /* AD type: flags */
+ 0x02, /* general discoverable */
+ 0x03, /* AD len */
+ 0x02, /* AD type: some 16bit service class UUIDs */
+ 0x0d, 0x18, /* heart rate monitor */
+ 0x04, /* AD len */
+ 0xff, /* AD type: manufacturer specific data */
+ 0x01, 0x02, 0x03, /* custom advertising data */
+ /* padding */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+static const uint8_t set_ext_adv_data_limited_discov[] = {
+ 0x00, /* handle */
+ 0x03, /* complete data */
+ 0x01, /* controller should not fragment */
+ 0x0c, /* adv data len */
+ 0x02, /* AD len */
+ 0x01, /* AD type: flags */
+ 0x01, /* limited discoverable */
+ /* rest: same as before */
+ 0x03, 0x02, 0x0d, 0x18, 0x04, 0xff, 0x01, 0x02, 0x03,
+ /* padding */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+static const uint8_t set_ext_adv_data_uuid_txpwr[] = {
+ 0x00, /* handle */
+ 0x03, /* complete data */
+ 0x01, /* controller should not fragment */
+ 0x0c, /* adv data len */
+ 0x03, /* AD len */
+ 0x02, /* AD type: some 16bit service class UUIDs */
+ 0x0d, 0x18, /* heart rate monitor */
+ 0x04, /* AD len */
+ 0xff, /* AD type: manufacturer specific data */
+ 0x01, 0x02, 0x03, /* custom advertising data */
+ 0x02, /* AD len */
+ 0x0a, /* AD type: tx power */
+ 0x00, /* tx power */
+ /* padding */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+static const struct generic_data add_ext_advertising_success_9 = {
+ .setup_settings = settings_powered_le,
+ .send_opcode = MGMT_OP_ADD_ADVERTISING,
+ .send_param = add_advertising_param_general_discov,
+ .send_len = sizeof(add_advertising_param_general_discov),
+ .expect_param = advertising_instance1_param,
+ .expect_len = sizeof(advertising_instance1_param),
+ .expect_status = MGMT_STATUS_SUCCESS,
+ .expect_hci_command = BT_HCI_CMD_LE_SET_EXT_ADV_DATA,
+ .expect_hci_param = set_ext_adv_data_general_discov,
+ .expect_hci_len = sizeof(set_ext_adv_data_general_discov),
+};
+
+static const struct generic_data add_ext_advertising_success_10 = {
+ .setup_settings = settings_powered_le,
+ .send_opcode = MGMT_OP_ADD_ADVERTISING,
+ .send_param = add_advertising_param_limited_discov,
+ .send_len = sizeof(add_advertising_param_limited_discov),
+ .expect_param = advertising_instance1_param,
+ .expect_len = sizeof(advertising_instance1_param),
+ .expect_status = MGMT_STATUS_SUCCESS,
+ .expect_hci_command = BT_HCI_CMD_LE_SET_EXT_ADV_DATA,
+ .expect_hci_param = set_ext_adv_data_limited_discov,
+ .expect_hci_len = sizeof(set_ext_adv_data_limited_discov),
+};
+
+static const struct generic_data add_ext_advertising_success_11 = {
+ .setup_settings = settings_powered_le_discoverable,
+ .send_opcode = MGMT_OP_ADD_ADVERTISING,
+ .send_param = add_advertising_param_managed,
+ .send_len = sizeof(add_advertising_param_managed),
+ .expect_param = advertising_instance1_param,
+ .expect_len = sizeof(advertising_instance1_param),
+ .expect_status = MGMT_STATUS_SUCCESS,
+ .expect_hci_command = BT_HCI_CMD_LE_SET_EXT_ADV_DATA,
+ .expect_hci_param = set_ext_adv_data_general_discov,
+ .expect_hci_len = sizeof(set_ext_adv_data_general_discov),
+};
+
+static const struct generic_data add_ext_advertising_success_12 = {
+ .setup_settings = settings_powered_le_discoverable,
+ .send_opcode = MGMT_OP_ADD_ADVERTISING,
+ .send_param = add_advertising_param_txpwr,
+ .send_len = sizeof(add_advertising_param_txpwr),
+ .expect_param = advertising_instance1_param,
+ .expect_len = sizeof(advertising_instance1_param),
+ .expect_status = MGMT_STATUS_SUCCESS,
+ .expect_hci_command = BT_HCI_CMD_LE_SET_EXT_ADV_DATA,
+ .expect_hci_param = set_ext_adv_data_uuid_txpwr,
+ .expect_hci_len = sizeof(set_ext_adv_data_uuid_txpwr),
+};
+
+static uint8_t set_connectable_off_scan_ext_adv_param[] = {
+ 0x00, /* Handle */
+ 0x12, 0x00, /* Event type */
+ 0x00, 0x08, 0x00, /* min_interval */
+ 0x00, 0x08, 0x00, /* max_interval */
+ 0x07, /* channel_map */
+ 0x01, /* own_addr_type */
+ 0x00, /* peer_addr_type */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* peer_addr */
+ 0x00, /* filter_policy */
+ 127, /* Tx power */
+ 0x01, /* Primary PHY */
+ 0x00, /* primary adv max skip */
+ 0x01, /* Secondary PHY */
+ 0x00, /* adv sid*/
+ 0x00, /* Scan req notification */
+};
+
+static const struct generic_data add_ext_advertising_success_13 = {
+ .setup_settings = settings_powered_le,
+ .send_opcode = MGMT_OP_ADD_ADVERTISING,
+ .send_param = add_advertising_param_scanrsp,
+ .send_len = sizeof(add_advertising_param_scanrsp),
+ .expect_param = advertising_instance1_param,
+ .expect_len = sizeof(advertising_instance1_param),
+ .expect_status = MGMT_STATUS_SUCCESS,
+ .expect_hci_command = BT_HCI_CMD_LE_SET_EXT_ADV_PARAMS,
+ .expect_hci_param = set_connectable_off_scan_ext_adv_param,
+ .expect_hci_len = sizeof(set_connectable_off_scan_ext_adv_param),
+};
+
+static uint8_t set_connectable_off_ext_adv_param[] = {
+ 0x00, /* Handle */
+ 0x10, 0x00, /* Event type */
+ 0x00, 0x08, 0x00, /* min_interval */
+ 0x00, 0x08, 0x00, /* max_interval */
+ 0x07, /* channel_map */
+ 0x01, /* own_addr_type */
+ 0x00, /* peer_addr_type */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* peer_addr */
+ 0x00, /* filter_policy */
+ 127, /* Tx power */
+ 0x01, /* Primary PHY */
+ 0x00, /* primary adv max skip */
+ 0x01, /* Secondary PHY */
+ 0x00, /* adv sid*/
+ 0x00, /* Scan req notification */
+};
+
+static const struct generic_data add_ext_advertising_success_14 = {
+ .setup_settings = settings_powered_le,
+ .send_opcode = MGMT_OP_ADD_ADVERTISING,
+ .send_param = add_advertising_param_uuid,
+ .send_len = sizeof(add_advertising_param_uuid),
+ .expect_param = advertising_instance1_param,
+ .expect_len = sizeof(advertising_instance1_param),
+ .expect_status = MGMT_STATUS_SUCCESS,
+ .expect_hci_command = BT_HCI_CMD_LE_SET_EXT_ADV_PARAMS,
+ .expect_hci_param = set_connectable_off_ext_adv_param,
+ .expect_hci_len = sizeof(set_connectable_off_ext_adv_param),
+};
+
+static const struct generic_data add_ext_advertising_success_15 = {
+ .setup_settings = settings_powered_le_connectable,
+ .send_opcode = MGMT_OP_ADD_ADVERTISING,
+ .send_param = add_advertising_param_uuid,
+ .send_len = sizeof(add_advertising_param_uuid),
+ .expect_param = advertising_instance1_param,
+ .expect_len = sizeof(advertising_instance1_param),
+ .expect_status = MGMT_STATUS_SUCCESS,
+ .expect_hci_command = BT_HCI_CMD_LE_SET_EXT_ADV_PARAMS,
+ .expect_hci_param = set_connectable_on_ext_adv_param,
+ .expect_hci_len = sizeof(set_connectable_on_ext_adv_param),
+};
+
+static const struct generic_data add_ext_advertising_success_16 = {
+ .send_opcode = MGMT_OP_SET_CONNECTABLE,
+ .send_param = set_connectable_on_param,
+ .send_len = sizeof(set_connectable_on_param),
+ .expect_status = MGMT_STATUS_SUCCESS,
+ .expect_param = set_connectable_settings_param_3,
+ .expect_len = sizeof(set_connectable_settings_param_3),
+ .expect_hci_command = BT_HCI_CMD_LE_SET_EXT_ADV_PARAMS,
+ .expect_hci_param = set_connectable_on_ext_adv_param,
+ .expect_hci_len = sizeof(set_connectable_on_ext_adv_param),
+};
+
+static const struct generic_data add_ext_advertising_success_17 = {
+ .send_opcode = MGMT_OP_SET_CONNECTABLE,
+ .send_param = set_connectable_off_param,
+ .send_len = sizeof(set_connectable_off_param),
+ .expect_status = MGMT_STATUS_SUCCESS,
+ .expect_param = set_le_settings_param_2,
+ .expect_len = sizeof(set_le_settings_param_2),
+ .expect_hci_command = BT_HCI_CMD_LE_SET_EXT_ADV_PARAMS,
+ .expect_hci_param = set_connectable_off_ext_adv_param,
+ .expect_hci_len = sizeof(set_connectable_off_ext_adv_param),
+};
+
+static const struct generic_data add_ext_advertising_power_off = {
+ .send_opcode = MGMT_OP_SET_POWERED,
+ .send_param = set_powered_off_param,
+ .send_len = sizeof(set_powered_off_param),
+ .expect_status = MGMT_STATUS_SUCCESS,
+ .expect_param = set_powered_off_le_settings_param,
+ .expect_len = sizeof(set_powered_off_le_settings_param),
+ .expect_alt_ev = MGMT_EV_ADVERTISING_REMOVED,
+ .expect_alt_ev_param = advertising_instance1_param,
+ .expect_alt_ev_len = sizeof(advertising_instance1_param),
+};
+
+static const struct generic_data add_ext_advertising_le_off = {
+ .send_opcode = MGMT_OP_SET_LE,
+ .send_param = set_le_off_param,
+ .send_len = sizeof(set_le_off_param),
+ .expect_status = MGMT_STATUS_SUCCESS,
+ .expect_param = set_le_settings_param_off,
+ .expect_len = sizeof(set_le_settings_param_off),
+ .expect_alt_ev = MGMT_EV_ADVERTISING_REMOVED,
+ .expect_alt_ev_param = advertising_instance1_param,
+ .expect_alt_ev_len = sizeof(advertising_instance1_param),
+};
+
+static const struct generic_data add_ext_advertising_success_18 = {
+ .send_opcode = MGMT_OP_ADD_ADVERTISING,
+ .send_param = add_advertising_param_uuid,
+ .send_len = sizeof(add_advertising_param_uuid),
+ .expect_param = advertising_instance1_param,
+ .expect_len = sizeof(advertising_instance1_param),
+ .expect_status = MGMT_STATUS_SUCCESS,
+ .expect_hci_command = BT_HCI_CMD_LE_SET_EXT_ADV_DATA,
+ .expect_hci_param = set_ext_adv_data_uuid,
+ .expect_hci_len = sizeof(set_ext_adv_data_uuid),
+};
+
+static const char set_ext_adv_disable_param[] = {
+ 0x00, 0x00,
+};
+
+static const struct generic_data add_ext_advertising_timeout_expired = {
+ .expect_alt_ev = MGMT_EV_ADVERTISING_REMOVED,
+ .expect_alt_ev_param = advertising_instance1_param,
+ .expect_alt_ev_len = sizeof(advertising_instance1_param),
+ .expect_hci_command = BT_HCI_CMD_LE_SET_EXT_ADV_ENABLE,
+ .expect_hci_param = set_ext_adv_disable_param,
+ .expect_hci_len = sizeof(set_ext_adv_disable_param),
+};
+
+static const struct generic_data remove_ext_advertising_fail_1 = {
+ .send_opcode = MGMT_OP_REMOVE_ADVERTISING,
+ .send_param = remove_advertising_param_1,
+ .send_len = sizeof(remove_advertising_param_1),
+ .expect_status = MGMT_STATUS_INVALID_PARAMS,
+};
+
+static const struct generic_data remove_ext_advertising_success_1 = {
+ .send_opcode = MGMT_OP_REMOVE_ADVERTISING,
+ .send_param = remove_advertising_param_1,
+ .send_len = sizeof(remove_advertising_param_1),
+ .expect_status = MGMT_STATUS_SUCCESS,
+ .expect_param = remove_advertising_param_1,
+ .expect_len = sizeof(remove_advertising_param_1),
+ .expect_alt_ev = MGMT_EV_ADVERTISING_REMOVED,
+ .expect_alt_ev_param = advertising_instance1_param,
+ .expect_alt_ev_len = sizeof(advertising_instance1_param),
+ .expect_hci_command = BT_HCI_CMD_LE_SET_EXT_ADV_ENABLE,
+ .expect_hci_param = set_ext_adv_disable_param,
+ .expect_hci_len = sizeof(set_ext_adv_disable_param),
+};
+
+static const struct generic_data remove_ext_advertising_success_2 = {
+ .send_opcode = MGMT_OP_REMOVE_ADVERTISING,
+ .send_param = remove_advertising_param_2,
+ .send_len = sizeof(remove_advertising_param_2),
+ .expect_status = MGMT_STATUS_SUCCESS,
+ .expect_param = remove_advertising_param_2,
+ .expect_len = sizeof(remove_advertising_param_2),
+ .expect_alt_ev = MGMT_EV_ADVERTISING_REMOVED,
+ .expect_alt_ev_param = advertising_instance1_param,
+ .expect_alt_ev_len = sizeof(advertising_instance1_param),
+ .expect_hci_command = BT_HCI_CMD_LE_SET_EXT_ADV_ENABLE,
+ .expect_hci_param = set_ext_adv_disable_param,
+ .expect_hci_len = sizeof(set_ext_adv_disable_param),
+};
+
+static const uint8_t set_ext_adv_data_test2[] = {
+ 0x00, /* handle */
+ 0x03, /* complete data */
+ 0x01, /* controller should not fragment */
+ 0x07, /* adv data len */
+ 0x06, /* AD len */
+ 0x08, /* AD type: shortened local name */
+ 0x74, 0x65, 0x73, 0x74, 0x32, /* "test2" */
+ /* padding */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+};
+
+static const struct generic_data multi_ext_advertising_switch = {
+ .expect_alt_ev = MGMT_EV_ADVERTISING_REMOVED,
+ .expect_alt_ev_param = advertising_instance1_param,
+ .expect_alt_ev_len = sizeof(advertising_instance1_param),
+ .expect_hci_command = BT_HCI_CMD_LE_SET_EXT_ADV_DATA,
+ .expect_hci_param = set_ext_adv_data_test2,
+ .expect_hci_len = sizeof(set_ext_adv_data_test2),
+};
+
+static const struct generic_data multi_ext_advertising_add_second = {
+ .send_opcode = MGMT_OP_ADD_ADVERTISING,
+ .send_param = add_advertising_param_test2,
+ .send_len = sizeof(add_advertising_param_test2),
+ .expect_param = advertising_instance2_param,
+ .expect_len = sizeof(advertising_instance2_param),
+ .expect_status = MGMT_STATUS_SUCCESS,
+ .expect_alt_ev = MGMT_EV_ADVERTISING_ADDED,
+ .expect_alt_ev_param = advertising_instance2_param,
+ .expect_alt_ev_len = sizeof(advertising_instance2_param),
+ .expect_hci_command = BT_HCI_CMD_LE_SET_EXT_ADV_DATA,
+ .expect_hci_param = set_ext_adv_data_test2,
+ .expect_hci_len = sizeof(set_ext_adv_data_test2),
+};
+
+static const uint8_t add_ext_advertising_param_empty[] = {
+ 0x01, /* adv instance */
+ 0x00, 0x00, 0x00, 0x00, /* flags: none */
+ 0x00, 0x00, /* duration: default */
+ 0x00, 0x00, /* timeout: none */
+ 0x00, /* adv data len */
+ 0x00, /* scan rsp len */
+};
+
+static const struct generic_data add_ext_advertising_empty_scrsp = {
+ .setup_settings = settings_powered_le,
+ .setup_send_opcode = MGMT_OP_SET_LOCAL_NAME,
+ .setup_send_param = set_local_name_param,
+ .setup_send_len = sizeof(set_local_name_param),
+ .send_opcode = MGMT_OP_ADD_ADVERTISING,
+ .send_param = add_advertising_param_empty,
+ .send_len = sizeof(add_advertising_param_empty),
+ .expect_status = MGMT_STATUS_SUCCESS,
+ .expect_param = advertising_instance1_param,
+ .expect_len = sizeof(advertising_instance1_param),
+};
+
+static const uint8_t add_ext_advertising_param_scrsp_data_only_ok[] = {
+ 0x01, /* adv instance */
+ 0x00, 0x00, 0x00, 0x00, /* flags: none */
+ 0x00, 0x00, /* duration: default */
+ 0x00, 0x00, /* timeout: none */
+ 0x00, /* adv data len */
+ 0x1f, /* scan rsp len */
+ /* adv data: */
+ /* scan rsp data: */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00,
+};
+
+static const struct generic_data add_ext_advertising_scrsp_data_only_ok = {
+ .setup_settings = settings_powered_le,
+ .send_opcode = MGMT_OP_ADD_ADVERTISING,
+ .send_param = add_advertising_param_scrsp_data_only_ok,
+ .send_len = sizeof(add_advertising_param_scrsp_data_only_ok),
+ .expect_status = MGMT_STATUS_SUCCESS,
+ .expect_param = advertising_instance1_param,
+ .expect_len = sizeof(advertising_instance1_param),
+};
+
+static const uint8_t add_ext_advertising_param_scrsp_data_only_too_long[] = {
+ 0x01, /* adv instance */
+ 0x00, 0x00, 0x00, 0x00, /* flags: none */
+ 0x00, 0x00, /* duration: default */
+ 0x00, 0x00, /* timeout: none */
+ 0x00, /* adv data len */
+ 0x20, /* scan rsp len */
+ /* adv data: */
+ /* scan rsp data: */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00,
+};
+
+static const struct generic_data add_ext_advertising_scrsp_data_only_too_long = {
+ .setup_settings = settings_powered_le,
+ .send_opcode = MGMT_OP_ADD_ADVERTISING,
+ .send_param = add_advertising_param_scrsp_data_only_too_long,
+ .send_len = sizeof(add_advertising_param_scrsp_data_only_too_long),
+ .expect_status = MGMT_STATUS_INVALID_PARAMS,
+ .expect_param = NULL,
+ .expect_len = 0,
+};
+
+static const uint8_t add_ext_advertising_param_scrsp_appear_data_ok[] = {
+ 0x01, /* adv instance */
+ 0x20, 0x00, 0x00, 0x00, /* flags: appearance */
+ 0x00, 0x00, /* duration: default */
+ 0x00, 0x00, /* timeout: none */
+ 0x00, /* adv data len */
+ 0x1b, /* scan rsp len */
+ /* adv data: */
+ /* scan rsp data: */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+static const struct generic_data add_ext_advertising_scrsp_appear_data_ok = {
+ .setup_settings = settings_powered_le,
+ .setup_send_opcode = MGMT_OP_SET_APPEARANCE,
+ .setup_send_param = set_appearance_param,
+ .setup_send_len = sizeof(set_appearance_param),
+ .send_opcode = MGMT_OP_ADD_ADVERTISING,
+ .send_param = add_advertising_param_scrsp_appear_data_ok,
+ .send_len = sizeof(add_advertising_param_scrsp_appear_data_ok),
+ .expect_status = MGMT_STATUS_SUCCESS,
+ .expect_param = advertising_instance1_param,
+ .expect_len = sizeof(advertising_instance1_param),
+};
+
+static const uint8_t add_ext_advertising_param_scrsp_appear_data_too_long[] = {
+ 0x01, /* adv instance */
+ 0x20, 0x00, 0x00, 0x00, /* flags: appearance */
+ 0x00, 0x00, /* duration: default */
+ 0x00, 0x00, /* timeout: none */
+ 0x00, /* adv data len */
+ 0x1c, /* scan rsp len */
+ /* adv data: */
+ /* scan rsp data: */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+static const struct generic_data add_ext_advertising_scrsp_appear_data_too_long = {
+ .setup_settings = settings_powered_le,
+ .setup_send_opcode = MGMT_OP_SET_APPEARANCE,
+ .setup_send_param = set_appearance_param,
+ .setup_send_len = sizeof(set_appearance_param),
+ .send_opcode = MGMT_OP_ADD_ADVERTISING,
+ .send_param = add_advertising_param_scrsp_appear_data_too_long,
+ .send_len = sizeof(add_advertising_param_scrsp_appear_data_too_long),
+ .expect_status = MGMT_STATUS_INVALID_PARAMS,
+ .expect_param = NULL,
+ .expect_len = 0,
+};
+
+static const uint8_t add_ext_advertising_param_scrsp_appear_null[] = {
+ 0x01, /* adv instance */
+ 0x20, 0x00, 0x00, 0x00, /* flags: appearance */
+ 0x00, 0x00, /* duration: default */
+ 0x00, 0x00, /* timeout: none */
+ 0x00, /* adv data len */
+ 0x01, /* scan rsp len */
+ /* adv data: */
+ /* scan rsp data: */
+ 0x00,
+};
+
+static const struct generic_data add_ext_advertising_scrsp_appear_null = {
+ .setup_settings = settings_powered_le,
+ .send_opcode = MGMT_OP_ADD_ADVERTISING,
+ .send_param = add_advertising_param_scrsp_appear_null,
+ .send_len = sizeof(add_advertising_param_scrsp_appear_null),
+ .expect_status = MGMT_STATUS_SUCCESS,
+ .expect_param = advertising_instance1_param,
+ .expect_len = sizeof(advertising_instance1_param),
+};
+
+static const uint8_t add_ext_advertising_empty_param[] = {
+ 0x01, /* adv instance */
+ 0x40, 0x00, 0x00, 0x00, /* flags: local name*/
+ 0x00, 0x00, /* duration: default */
+ 0x00, 0x00, /* timeout: none */
+ 0x00, /* adv data len */
+ 0x01, /* scan rsp len */
+ /* scan rsp data: */
+ 0x00,
+};
+
+static const uint8_t ext_scan_rsp_data_empty[] = {
+ 0x00, /* handle */
+ 0x03, /* complete data */
+ 0x01, /* controller should not fragment */
+ 0x01, /* scan rsp data len */
+ 0x00, /* scan rsp data */
+ /* placeholder data */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+static const struct generic_data add_ext_advertising_no_name_set = {
+ .setup_settings = settings_powered_le,
+ .send_opcode = MGMT_OP_ADD_ADVERTISING,
+ .send_param = add_advertising_empty_param,
+ .send_len = sizeof(add_advertising_empty_param),
+ .expect_status = MGMT_STATUS_SUCCESS,
+ .expect_param = advertising_instance1_param,
+ .expect_len = sizeof(advertising_instance1_param),
+ .expect_hci_command = BT_HCI_CMD_LE_SET_EXT_SCAN_RSP_DATA,
+ .expect_hci_param = ext_scan_rsp_data_empty,
+ .expect_hci_len = sizeof(ext_scan_rsp_data_empty),
+};
+
+static const uint8_t add_ext_advertising_param_name[] = {
+ 0x01, /* adv instance */
+ 0x40, 0x00, 0x00, 0x00, /* flags: Add local name to scan_rsp */
+ 0x00, 0x00, /* duration: default */
+ 0x00, 0x00, /* timeout: none */
+ 0x00, /* adv data len */
+ 0x00, /* scan rsp len */
+};
+
+static const uint8_t set_ext_scan_rsp_data_name_fits_in_scrsp[] = {
+ 0x00, /* handle */
+ 0x03, /* complete data */
+ 0x01, /* controller should not fragment */
+ 0x0c, /* Scan rsp data len */
+ 0x0b, /* Local name data len */
+ 0x09, /* Complete name */
+ 0x54, 0x65, 0x73, 0x74, 0x20, 0x6e, 0x61, 0x6d, 0x65, /* "Test name" */
+ /* padding */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+static const struct generic_data add_ext_advertising_name_fits_in_scrsp = {
+ .setup_settings = settings_powered_le,
+ .setup_send_opcode = MGMT_OP_SET_LOCAL_NAME,
+ .setup_send_param = &set_local_name_cp,
+ .setup_send_len = sizeof(set_local_name_cp),
+ .send_opcode = MGMT_OP_ADD_ADVERTISING,
+ .send_param = add_advertising_param_name,
+ .send_len = sizeof(add_advertising_param_name),
+ .expect_status = MGMT_STATUS_SUCCESS,
+ .expect_param = advertising_instance1_param,
+ .expect_len = sizeof(advertising_instance1_param),
+ .expect_hci_command = BT_HCI_CMD_LE_SET_EXT_SCAN_RSP_DATA,
+ .expect_hci_param = set_ext_scan_rsp_data_name_fits_in_scrsp,
+ .expect_hci_len = sizeof(set_ext_scan_rsp_data_name_fits_in_scrsp),
+};
+
+static const uint8_t set_ext_scan_rsp_data_shortened_name_fits[] = {
+ 0x00, /* handle */
+ 0x03, /* complete data */
+ 0x01, /* controller should not fragment */
+ 0x0d, /* Scan rsp data len */
+ 0x0c, /* Local name data len */
+ 0x08, /* Short name */
+ 0x54, 0x65, 0x73, 0x74, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x31,
+ /* "Test name1" */
+ /* padding */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+static const struct generic_data add_ext_advertising_shortened_name_in_scrsp = {
+ .setup_settings = settings_powered_le,
+ .setup_send_opcode = MGMT_OP_SET_LOCAL_NAME,
+ .setup_send_param = &set_local_name_longer_cp,
+ .setup_send_len = sizeof(set_local_name_longer_cp),
+ .send_opcode = MGMT_OP_ADD_ADVERTISING,
+ .send_param = add_advertising_param_name,
+ .send_len = sizeof(add_advertising_param_name),
+ .expect_status = MGMT_STATUS_SUCCESS,
+ .expect_param = advertising_instance1_param,
+ .expect_len = sizeof(advertising_instance1_param),
+ .expect_hci_command = BT_HCI_CMD_LE_SET_EXT_SCAN_RSP_DATA,
+ .expect_hci_param = set_ext_scan_rsp_data_shortened_name_fits,
+ .expect_hci_len = sizeof(set_ext_scan_rsp_data_shortened_name_fits),
+};
+
+static const uint8_t set_ext_scan_rsp_data_short_name_fits[] = {
+ 0x00, /* handle */
+ 0x03, /* complete data */
+ 0x01, /* controller should not fragment */
+ 0x07, /* Scan rsp data len */
+ 0x06, /* Local name data len */
+ 0x08, /* Short name */
+ 0x54, 0x65, 0x73, 0x74,
+ /* "Test*/
+ /* padding */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+static const uint8_t add_ext_advertising_param_name_data_ok[] = {
+ 0x01, /* adv instance */
+ 0x40, 0x00, 0x00, 0x00, /* flags: local name */
+ 0x00, 0x00, /* duration: default */
+ 0x00, 0x00, /* timeout: none */
+ 0x00, /* adv data len */
+ 0x12, /* scan rsp len */
+ /* adv data: */
+ /* scan rsp data: */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+static const uint8_t set_ext_scan_rsp_data_param_name_data_ok[] = {
+ 0x00, /* handle */
+ 0x03, /* complete data */
+ 0x01, /* controller should not fragment */
+ 0x1e, /* Scan rsp data len */
+ /* scan rsp data */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x0b, /* Local name data len */
+ 0x09, /* Complete name */
+ 0x54, 0x65, 0x73, 0x74, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x00,
+ /* "Test name" */
+ /* padding */
+ 0x00,
+};
+
+static const struct generic_data add_ext_advertising_name_data_ok = {
+ .setup_settings = settings_powered_le,
+ .setup_send_opcode = MGMT_OP_SET_LOCAL_NAME,
+ .setup_send_param = &set_local_name_cp,
+ .setup_send_len = sizeof(set_local_name_cp),
+ .send_opcode = MGMT_OP_ADD_ADVERTISING,
+ .send_param = add_advertising_param_name_data_ok,
+ .send_len = sizeof(add_advertising_param_name_data_ok),
+ .expect_status = MGMT_STATUS_SUCCESS,
+ .expect_param = advertising_instance1_param,
+ .expect_len = sizeof(advertising_instance1_param),
+ .expect_hci_command = BT_HCI_CMD_LE_SET_EXT_SCAN_RSP_DATA,
+ .expect_hci_param = set_ext_scan_rsp_data_param_name_data_ok,
+ .expect_hci_len = sizeof(set_ext_scan_rsp_data_param_name_data_ok),
+};
+
+static const uint8_t add_ext_advertising_param_name_data_inv[] = {
+ 0x01, /* adv instance */
+ 0x40, 0x00, 0x00, 0x00, /* flags: local name */
+ 0x00, 0x00, /* duration: default */
+ 0x00, 0x00, /* timeout: none */
+ 0x00, /* adv data len */
+ 0x14, /* scan rsp len */
+ /* adv data: */
+ /* scan rsp data: */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const struct generic_data add_ext_advertising_name_data_inv = {
+ .setup_settings = settings_powered_le,
+ .setup_send_opcode = MGMT_OP_SET_LOCAL_NAME,
+ .setup_send_param = &set_local_name_cp,
+ .setup_send_len = sizeof(set_local_name_cp),
+ .send_opcode = MGMT_OP_ADD_ADVERTISING,
+ .send_param = add_advertising_param_name_data_inv,
+ .send_len = sizeof(add_advertising_param_name_data_inv),
+ .expect_status = MGMT_STATUS_INVALID_PARAMS,
+ .expect_param = NULL,
+ .expect_len = 0,
+};
+
+static const uint8_t add_ext_advertising_param_name_data_appear[] = {
+ 0x01, /* adv instance */
+ 0x60, 0x00, 0x00, 0x00, /* flags: local name + appearance */
+ 0x00, 0x00, /* duration: default */
+ 0x00, 0x00, /* timeout: none */
+ 0x00, /* adv data len */
+ 0x0e, /* scan rsp len */
+ /* adv data: */
+ /* scan rsp data: */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+};
+
+static const struct setup_mgmt_cmd add_ext_advertising_mgmt_cmd_arr[] = {
+ {
+ .send_opcode = MGMT_OP_SET_APPEARANCE,
+ .send_param = set_appearance_param,
+ .send_len = sizeof(set_appearance_param),
+ },
+ {
+ .send_opcode = MGMT_OP_SET_LOCAL_NAME,
+ .send_param = &set_local_name_cp,
+ .send_len = sizeof(set_local_name_cp),
+ },
+ { /* last element should always have opcode 0x00 */
+ .send_opcode = 0x00,
+ .send_param = NULL,
+ .send_len = 0,
+ }
+};
+
+static const uint8_t set_ext_scan_rsp_data_name_data_appear[] = {
+ 0x00, /* handle */
+ 0x03, /* complete data */
+ 0x01, /* controller should not fragment */
+ 0x1e, /* Scan rsp data len */
+ 0x03, /* appearance len */
+ 0x19, /* EIR_APPEARANCE */
+ 0x54, 0x65, /* appearance value */
+ /* scan rsp data */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x0b, /* Local name data len */
+ 0x09, /* Complete name */
+ 0x54, 0x65, 0x73, 0x74, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x00,
+ /* "Test name" */
+ /* padding */
+ 0x00,
+};
+
+static const struct generic_data add_ext_advertising_name_data_appear = {
+ .setup_settings = settings_powered_le,
+ .setup_mgmt_cmd_arr = add_advertising_mgmt_cmd_arr,
+ .send_opcode = MGMT_OP_ADD_ADVERTISING,
+ .send_param = add_advertising_param_name_data_appear,
+ .send_len = sizeof(add_advertising_param_name_data_appear),
+ .expect_status = MGMT_STATUS_SUCCESS,
+ .expect_param = advertising_instance1_param,
+ .expect_len = sizeof(advertising_instance1_param),
+ .expect_hci_command = BT_HCI_CMD_LE_SET_EXT_SCAN_RSP_DATA,
+ .expect_hci_param = set_ext_scan_rsp_data_name_data_appear,
+ .expect_hci_len = sizeof(set_ext_scan_rsp_data_name_data_appear),
+};
+
+/* simple add advertising command */
+static const uint8_t add_advertising_1m_param_uuid[] = {
+ 0x01, /* adv instance */
+ 0x80, 0x00, 0x00, 0x00, /* flags: 1m */
+ 0x00, 0x00, /* duration: default */
+ 0x00, 0x00, /* timeout: none */
+ 0x09, /* adv data len */
+ 0x00, /* scan rsp len */
+ /* adv data: */
+ 0x03, /* AD len */
+ 0x02, /* AD type: some 16 bit service class UUIDs */
+ 0x0d, 0x18, /* heart rate monitor */
+ 0x04, /* AD len */
+ 0xff, /* AD type: manufacturer specific data */
+ 0x01, 0x02, 0x03, /* custom advertising data */
+};
+
+static uint8_t set_connectable_off_ext_1m_adv_param[] = {
+ 0x00, /* Handle */
+ 0x00, 0x00, /* Event type */
+ 0x00, 0x08, 0x00, /* min_interval */
+ 0x00, 0x08, 0x00, /* max_interval */
+ 0x07, /* channel_map */
+ 0x01, /* own_addr_type */
+ 0x00, /* peer_addr_type */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* peer_addr */
+ 0x00, /* filter_policy */
+ 127, /* Tx power */
+ 0x01, /* Primary PHY */
+ 0x00, /* primary adv max skip */
+ 0x01, /* Secondary PHY */
+ 0x00, /* adv sid*/
+ 0x00, /* Scan req notification */
+};
+
+static const struct generic_data add_ext_advertising_success_1m = {
+ .setup_settings = settings_powered_le,
+ .send_opcode = MGMT_OP_ADD_ADVERTISING,
+ .send_param = add_advertising_1m_param_uuid,
+ .send_len = sizeof(add_advertising_1m_param_uuid),
+ .expect_param = advertising_instance1_param,
+ .expect_len = sizeof(advertising_instance1_param),
+ .expect_status = MGMT_STATUS_SUCCESS,
+ .expect_hci_command = BT_HCI_CMD_LE_SET_EXT_ADV_PARAMS,
+ .expect_hci_param = set_connectable_off_ext_1m_adv_param,
+ .expect_hci_len = sizeof(set_connectable_off_ext_1m_adv_param),
+};
+
+/* simple add advertising command */
+static const uint8_t add_advertising_2m_param_uuid[] = {
+ 0x01, /* adv instance */
+ 0x00, 0x01, 0x00, 0x00, /* flags: 2m */
+ 0x00, 0x00, /* duration: default */
+ 0x00, 0x00, /* timeout: none */
+ 0x09, /* adv data len */
+ 0x00, /* scan rsp len */
+ /* adv data: */
+ 0x03, /* AD len */
+ 0x02, /* AD type: some 16 bit service class UUIDs */
+ 0x0d, 0x18, /* heart rate monitor */
+ 0x04, /* AD len */
+ 0xff, /* AD type: manufacturer specific data */
+ 0x01, 0x02, 0x03, /* custom advertising data */
+};
+
+static uint8_t set_connectable_off_ext_2m_adv_param[] = {
+ 0x00, /* Handle */
+ 0x00, 0x00, /* Event type */
+ 0x00, 0x08, 0x00, /* min_interval */
+ 0x00, 0x08, 0x00, /* max_interval */
+ 0x07, /* channel_map */
+ 0x01, /* own_addr_type */
+ 0x00, /* peer_addr_type */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* peer_addr */
+ 0x00, /* filter_policy */
+ 127, /* Tx power */
+ 0x01, /* Primary PHY */
+ 0x00, /* primary adv max skip */
+ 0x02, /* Secondary PHY */
+ 0x00, /* adv sid*/
+ 0x00, /* Scan req notification */
+};
+
+static const struct generic_data add_ext_advertising_success_2m = {
+ .setup_settings = settings_powered_le,
+ .send_opcode = MGMT_OP_ADD_ADVERTISING,
+ .send_param = add_advertising_2m_param_uuid,
+ .send_len = sizeof(add_advertising_2m_param_uuid),
+ .expect_param = advertising_instance1_param,
+ .expect_len = sizeof(advertising_instance1_param),
+ .expect_status = MGMT_STATUS_SUCCESS,
+ .expect_hci_command = BT_HCI_CMD_LE_SET_EXT_ADV_PARAMS,
+ .expect_hci_param = set_connectable_off_ext_2m_adv_param,
+ .expect_hci_len = sizeof(set_connectable_off_ext_2m_adv_param),
+};
+
+/* simple add advertising command */
+static const uint8_t add_advertising_coded_param_uuid[] = {
+ 0x01, /* adv instance */
+ 0x00, 0x02, 0x00, 0x00, /* flags: coded */
+ 0x00, 0x00, /* duration: default */
+ 0x00, 0x00, /* timeout: none */
+ 0x09, /* adv data len */
+ 0x00, /* scan rsp len */
+ /* adv data: */
+ 0x03, /* AD len */
+ 0x02, /* AD type: some 16 bit service class UUIDs */
+ 0x0d, 0x18, /* heart rate monitor */
+ 0x04, /* AD len */
+ 0xff, /* AD type: manufacturer specific data */
+ 0x01, 0x02, 0x03, /* custom advertising data */
+};
+
+static uint8_t set_connectable_off_ext_coded_adv_param[] = {
+ 0x00, /* Handle */
+ 0x00, 0x00, /* Event type */
+ 0x00, 0x08, 0x00, /* min_interval */
+ 0x00, 0x08, 0x00, /* max_interval */
+ 0x07, /* channel_map */
+ 0x01, /* own_addr_type */
+ 0x00, /* peer_addr_type */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* peer_addr */
+ 0x00, /* filter_policy */
+ 127, /* Tx power */
+ 0x03, /* Primary PHY */
+ 0x00, /* primary adv max skip */
+ 0x03, /* Secondary PHY */
+ 0x00, /* adv sid*/
+ 0x00, /* Scan req notification */
+};
+
+static const struct generic_data add_ext_advertising_success_coded = {
+ .setup_settings = settings_powered_le,
+ .send_opcode = MGMT_OP_ADD_ADVERTISING,
+ .send_param = add_advertising_coded_param_uuid,
+ .send_len = sizeof(add_advertising_coded_param_uuid),
+ .expect_param = advertising_instance1_param,
+ .expect_len = sizeof(advertising_instance1_param),
+ .expect_status = MGMT_STATUS_SUCCESS,
+ .expect_hci_command = BT_HCI_CMD_LE_SET_EXT_ADV_PARAMS,
+ .expect_hci_param = set_connectable_off_ext_coded_adv_param,
+ .expect_hci_len = sizeof(set_connectable_off_ext_coded_adv_param),
+};
+
+/* add advertising with scan response data */
+static const uint8_t add_advertising_param_scanrsp_1m[] = {
+ 0x01, /* Instance */
+ 0x80, 0x00, 0x00, 0x00, /* Flags: 1m*/
+ 0x00, 0x00, /* Duration */
+ 0x00, 0x00, /* Timeout */
+ 0x09, /* Adv data len */
+ 0x0a, /* scan rsp len */
+ /* adv data: same as before */
+ 0x03, 0x02, 0x0d, 0x18, 0x04, 0xff, 0x01, 0x02, 0x03,
+ /* scan rsp data: */
+ 0x03, /* AD len */
+ 0x19, /* AD type: external appearance */
+ 0x40, 0x03, /* some custom appearance */
+ 0x05, /* AD len */
+ 0x03, /* AD type: all 16 bit service class UUIDs */
+ 0x0d, 0x18, /* heart rate monitor */
+ 0x0f, 0x18, /* battery service */
+};
+
+static uint8_t set_connectable_off_scan_ext_pdu_adv_param[] = {
+ 0x00, /* Handle */
+ 0x02, 0x00, /* Event type */
+ 0x00, 0x08, 0x00, /* min_interval */
+ 0x00, 0x08, 0x00, /* max_interval */
+ 0x07, /* channel_map */
+ 0x01, /* own_addr_type */
+ 0x00, /* peer_addr_type */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* peer_addr */
+ 0x00, /* filter_policy */
+ 127, /* Tx power */
+ 0x01, /* Primary PHY */
+ 0x00, /* primary adv max skip */
+ 0x01, /* Secondary PHY */
+ 0x00, /* adv sid*/
+ 0x00, /* Scan req notification */
+};
+
+static const struct generic_data add_ext_advertising_success_scannable = {
+ .setup_settings = settings_powered_le,
+ .send_opcode = MGMT_OP_ADD_ADVERTISING,
+ .send_param = add_advertising_param_scanrsp_1m,
+ .send_len = sizeof(add_advertising_param_scanrsp_1m),
+ .expect_param = advertising_instance1_param,
+ .expect_len = sizeof(advertising_instance1_param),
+ .expect_status = MGMT_STATUS_SUCCESS,
+ .expect_hci_command = BT_HCI_CMD_LE_SET_EXT_ADV_PARAMS,
+ .expect_hci_param = set_connectable_off_scan_ext_pdu_adv_param,
+ .expect_hci_len = sizeof(set_connectable_off_scan_ext_pdu_adv_param),
+};
+
+static uint8_t set_connectable_on_ext_pdu_adv_param[] = {
+ 0x00, /* Handle */
+ 0x01, 0x00, /* Event type */
+ 0x00, 0x08, 0x00, /* min_interval */
+ 0x00, 0x08, 0x00, /* max_interval */
+ 0x07, /* channel_map */
+ 0x00, /* own_addr_type */
+ 0x00, /* peer_addr_type */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* peer_addr */
+ 0x00, /* filter_policy */
+ 127, /* Tx power */
+ 0x01, /* Primary PHY */
+ 0x00, /* primary adv max skip */
+ 0x01, /* Secondary PHY */
+ 0x00, /* adv sid*/
+ 0x00, /* Scan req notification */
+};
+
+static const struct generic_data add_ext_advertising_success_connectable = {
+ .setup_settings = settings_powered_le_connectable,
+ .send_opcode = MGMT_OP_ADD_ADVERTISING,
+ .send_param = add_advertising_1m_param_uuid,
+ .send_len = sizeof(add_advertising_1m_param_uuid),
+ .expect_param = advertising_instance1_param,
+ .expect_len = sizeof(advertising_instance1_param),
+ .expect_status = MGMT_STATUS_SUCCESS,
+ .expect_hci_command = BT_HCI_CMD_LE_SET_EXT_ADV_PARAMS,
+ .expect_hci_param = set_connectable_on_ext_pdu_adv_param,
+ .expect_hci_len = sizeof(set_connectable_on_ext_pdu_adv_param),
+};
+
+static const struct generic_data add_ext_advertising_success_conn_scan = {
+ .setup_settings = settings_powered_le_connectable,
+ .send_opcode = MGMT_OP_ADD_ADVERTISING,
+ .send_param = add_advertising_param_scanrsp_1m,
+ .send_len = sizeof(add_advertising_param_scanrsp_1m),
+ .expect_param = advertising_instance1_param,
+ .expect_len = sizeof(advertising_instance1_param),
+ .expect_status = MGMT_STATUS_SUCCESS,
+ .expect_hci_command = BT_HCI_CMD_LE_SET_EXT_ADV_PARAMS,
+ .expect_hci_param = set_connectable_on_ext_pdu_adv_param,
+ .expect_hci_len = sizeof(set_connectable_on_ext_pdu_adv_param),
+};
+
+static void setup_add_adv_param_1m(struct mgmt_cp_add_advertising *cp,
+ uint8_t instance)
+{
+ memset(cp, 0, sizeof(*cp));
+ cp->instance = instance;
+ cp->flags = cpu_to_le32(MGMT_ADV_FLAG_SEC_1M);
+ cp->adv_data_len = TESTER_ADD_ADV_DATA_LEN;
+ cp->data[0] = TESTER_ADD_ADV_DATA_LEN - 1; /* AD len */
+ cp->data[1] = 0x08; /* AD type: shortened local name */
+ cp->data[2] = 't'; /* adv data ... */
+ cp->data[3] = 'e';
+ cp->data[4] = 's';
+ cp->data[5] = 't';
+ cp->data[6] = '0' + instance;
+}
+
+static void setup_add_advertising_1m(const void *test_data)
+{
+ struct test_data *data = tester_get_data();
+ struct mgmt_cp_add_advertising *cp;
+ unsigned char adv_param[sizeof(*cp) + TESTER_ADD_ADV_DATA_LEN];
+ unsigned char param[] = { 0x01 };
+
+ tester_print("Adding advertising instance while powered");
+
+ cp = (struct mgmt_cp_add_advertising *) adv_param;
+ setup_add_adv_param_1m(cp, 1);
+
+ mgmt_send(data->mgmt, MGMT_OP_SET_LE, data->mgmt_index,
+ sizeof(param), &param,
+ NULL, NULL, NULL);
+
+ mgmt_send(data->mgmt, MGMT_OP_SET_POWERED, data->mgmt_index,
+ sizeof(param), &param,
+ NULL, NULL, NULL);
+
+ mgmt_send(data->mgmt, MGMT_OP_ADD_ADVERTISING, data->mgmt_index,
+ sizeof(adv_param), adv_param,
+ setup_add_advertising_callback,
+ NULL, NULL);
+}
+
+static const struct generic_data add_ext_advertising_conn_on_1m = {
+ .send_opcode = MGMT_OP_SET_CONNECTABLE,
+ .send_param = set_connectable_on_param,
+ .send_len = sizeof(set_connectable_on_param),
+ .expect_status = MGMT_STATUS_SUCCESS,
+ .expect_param = set_connectable_settings_param_3,
+ .expect_len = sizeof(set_connectable_settings_param_3),
+ .expect_hci_command = BT_HCI_CMD_LE_SET_EXT_ADV_PARAMS,
+ .expect_hci_param = set_connectable_on_ext_pdu_adv_param,
+ .expect_hci_len = sizeof(set_connectable_on_ext_pdu_adv_param),
+};
+
+static void setup_add_advertising_connectable_1m(const void *test_data)
+{
+ struct test_data *data = tester_get_data();
+ struct mgmt_cp_add_advertising *cp;
+ unsigned char adv_param[sizeof(*cp) + TESTER_ADD_ADV_DATA_LEN];
+ unsigned char param[] = { 0x01 };
+
+ tester_print("Adding advertising instance while connectable");
+
+ cp = (struct mgmt_cp_add_advertising *) adv_param;
+ setup_add_adv_param_1m(cp, 1);
+
+ mgmt_send(data->mgmt, MGMT_OP_SET_LE, data->mgmt_index,
+ sizeof(param), &param,
+ NULL, NULL, NULL);
+
+ mgmt_send(data->mgmt, MGMT_OP_SET_POWERED, data->mgmt_index,
+ sizeof(param), &param,
+ NULL, NULL, NULL);
+
+ mgmt_send(data->mgmt, MGMT_OP_SET_CONNECTABLE, data->mgmt_index,
+ sizeof(param), &param,
+ NULL, NULL, NULL);
+
+ mgmt_send(data->mgmt, MGMT_OP_ADD_ADVERTISING, data->mgmt_index,
+ sizeof(adv_param), adv_param,
+ setup_add_advertising_callback,
+ NULL, NULL);
+}
+
+static const struct generic_data add_ext_advertising_conn_off_1m = {
+ .send_opcode = MGMT_OP_SET_CONNECTABLE,
+ .send_param = set_connectable_off_param,
+ .send_len = sizeof(set_connectable_off_param),
+ .expect_status = MGMT_STATUS_SUCCESS,
+ .expect_param = set_le_settings_param_2,
+ .expect_len = sizeof(set_le_settings_param_2),
+ .expect_hci_command = BT_HCI_CMD_LE_SET_EXT_ADV_PARAMS,
+ .expect_hci_param = set_connectable_off_ext_1m_adv_param,
+ .expect_hci_len = sizeof(set_connectable_off_ext_1m_adv_param),
+};
+
+static bool power_off(uint16_t index)
+{
+ int sk, err;
+
+ sk = hci_open_dev(index);
+ if (sk < 0)
+ return false;
+
+ err = ioctl(sk, HCIDEVDOWN, index);
+
+ hci_close_dev(sk);
+
+ if (err < 0)
+ return false;
+
+ return true;
+}
+
+static void test_command_generic(const void *test_data)
+{
+ struct test_data *data = tester_get_data();
+ const struct generic_data *test = data->test_data;
+ const void *send_param = test->send_param;
+ uint16_t send_len = test->send_len;
+ unsigned int id;
+ uint16_t index;
+
+ index = test->send_index_none ? MGMT_INDEX_NONE : data->mgmt_index;
+
+ if (test->expect_settings_set || test->expect_settings_unset) {
+ tester_print("Registering new settings notification");
+
+ id = mgmt_register(data->mgmt, MGMT_EV_NEW_SETTINGS, index,
+ command_generic_new_settings, NULL, NULL);
+ data->mgmt_settings_id = id;
+
+ id = mgmt_register(data->mgmt_alt, MGMT_EV_NEW_SETTINGS, index,
+ command_generic_new_settings_alt, NULL, NULL);
+ data->mgmt_alt_settings_id = id;
+ test_add_condition(data);
+ }
+
+ if (test->expect_alt_ev) {
+ tester_print("Registering %s notification",
+ mgmt_evstr(test->expect_alt_ev));
+ id = mgmt_register(data->mgmt_alt, test->expect_alt_ev, index,
+ command_generic_event_alt, NULL, NULL);
+ data->mgmt_alt_ev_id = id;
+ test_add_condition(data);
+ }
+
+ if (test->expect_hci_command) {
+ tester_print("Registering HCI command callback");
+ hciemu_add_master_post_command_hook(data->hciemu,
+ command_hci_callback, data);
+ test_add_condition(data);
+ }
+
+ if (test->send_opcode == 0x0000) {
+ tester_print("Executing no-op test");
+ return;
+ }
+
+ tester_print("Sending %s (0x%04x)", mgmt_opstr(test->send_opcode),
+ test->send_opcode);
+
+ if (test->send_func)
+ send_param = test->send_func(&send_len);
+
+ if (test->force_power_off) {
+ mgmt_send_nowait(data->mgmt, test->send_opcode, index,
+ send_len, send_param,
+ command_generic_callback, NULL, NULL);
+ power_off(data->mgmt_index);
+ } else {
+ mgmt_send(data->mgmt, test->send_opcode, index, send_len,
+ send_param, command_generic_callback,
+ NULL, NULL);
+ }
+
+ test_add_condition(data);
+}
+
+static void check_scan(void *user_data)
+{
+ struct test_data *data = tester_get_data();
+
+ if (hciemu_get_master_le_scan_enable(data->hciemu)) {
+ tester_warn("LE scan still enabled");
+ tester_test_failed();
+ return;
+ }
+
+ if (hciemu_get_master_scan_enable(data->hciemu)) {
+ tester_warn("BR/EDR scan still enabled");
+ tester_test_failed();
+ return;
+ }
+
+ test_condition_complete(data);
+}
+
+static void test_remove_device(const void *test_data)
+{
+ struct test_data *data = tester_get_data();
+
+ test_command_generic(test_data);
+ tester_wait(1, check_scan, NULL);
+ test_add_condition(data);
+}
+
+static void trigger_device_found(void *user_data)
+{
+ struct test_data *data = tester_get_data();
const struct generic_data *test = data->test_data;
struct bthost *bthost;

@@ -8352,5 +9716,247 @@ int main(int argc, char *argv[])
&device_found_invalid_field,
NULL, test_device_found);

+ test_bredrle50("Read Ext Advertising Features - Success 3 (PHY flags)",
+ &read_adv_features_success_3,
+ NULL, test_command_generic);
+
+ test_bredrle50("Add Ext Advertising - Invalid Params 1 (Multiple Phys)",
+ &add_ext_advertising_fail_1,
+ NULL, test_command_generic);
+
+ test_bredrle50("Add Ext Advertising - Invalid Params 2 (Multiple PHYs)",
+ &add_ext_advertising_fail_2,
+ NULL, test_command_generic);
+
+ test_bredrle50("Add Ext Advertising - Invalid Params 3 (Multiple PHYs)",
+ &add_ext_advertising_fail_3,
+ NULL, test_command_generic);
+
+ test_bredrle50("Add Ext Advertising - Invalid Params 4 (Multiple PHYs)",
+ &add_ext_advertising_fail_4,
+ NULL, test_command_generic);
+
+ test_bredrle50("Add Ext Advertising - Success 1 (Powered, Add Adv Inst)",
+ &add_ext_advertising_success_1,
+ NULL, test_command_generic);
+
+
+ test_bredrle50("Add Ext Advertising - Success 2 (!Powered, Add Adv Inst)",
+ &add_ext_advertising_success_pwron_data,
+ setup_add_advertising_not_powered,
+ test_command_generic);
+
+ test_bredrle50("Add Ext Advertising - Success 3 (!Powered, Adv Enable)",
+ &add_ext_advertising_success_pwron_enabled,
+ setup_add_advertising_not_powered,
+ test_command_generic);
+
+ test_bredrle50("Add Ext Advertising - Success 4 (Set Adv on override)",
+ &add_ext_advertising_success_4,
+ setup_add_advertising,
+ test_command_generic);
+
+ test_bredrle50("Add Ext Advertising - Success 5 (Set Adv off override)",
+ &add_ext_advertising_success_5,
+ setup_set_and_add_advertising,
+ test_command_generic);
+
+ test_bredrle50("Add Ext Advertising - Success 6 (Scan Rsp Dta, Adv ok)",
+ &add_ext_advertising_success_6,
+ NULL, test_command_generic);
+
+ test_bredrle50("Add Ext Advertising - Success 7 (Scan Rsp Dta, Scan ok) ",
+ &add_ext_advertising_success_7,
+ NULL, test_command_generic);
+ test_bredrle50("Add Ext Advertising - Success 8 (Connectable Flag)",
+ &add_ext_advertising_success_8,
+ NULL, test_command_generic);
+
+ test_bredrle50("Add Ext Advertising - Success 9 (General Discov Flag)",
+ &add_ext_advertising_success_9,
+ NULL, test_command_generic);
+
+ test_bredrle50("Add Ext Advertising - Success 10 (Limited Discov Flag)",
+ &add_ext_advertising_success_10,
+ NULL, test_command_generic);
+
+ test_bredrle50("Add Ext Advertising - Success 11 (Managed Flags)",
+ &add_ext_advertising_success_11,
+ NULL, test_command_generic);
+
+ test_bredrle50("Add Ext Advertising - Success 12 (TX Power Flag)",
+ &add_ext_advertising_success_12,
+ NULL, test_command_generic);
+
+ test_bredrle50("Add Ext Advertising - Success 13 (ADV_SCAN_IND)",
+ &add_ext_advertising_success_13,
+ NULL, test_command_generic);
+
+ test_bredrle50("Add Ext Advertising - Success 14 (ADV_NONCONN_IND)",
+ &add_ext_advertising_success_14,
+ NULL, test_command_generic);
+
+ test_bredrle50("Add Ext Advertising - Success 15 (ADV_IND)",
+ &add_ext_advertising_success_15,
+ NULL, test_command_generic);
+
+ test_bredrle50("Add Ext Advertising - Success 16 (Connectable -> on)",
+ &add_ext_advertising_success_16,
+ setup_add_advertising,
+ test_command_generic);
+
+ test_bredrle50("Add Ext Advertising - Success 17 (Connectable -> off)",
+ &add_ext_advertising_success_17,
+ setup_add_advertising_connectable,
+ test_command_generic);
+
+ /* Changing an advertising instance while it is still being
+ * advertised will immediately update the advertised data if
+ * there is no other instance to switch to.
+ */
+ test_bredrle50("Add Ext Advertising - Success 20 (Add Adv override)",
+ &add_ext_advertising_success_18,
+ setup_add_advertising,
+ test_command_generic);
+
+ /* An instance should be removed when its timeout has been reached.
+ * Advertising will also be disabled if this was the last instance.
+ */
+ test_bredrle50_full("Add Ext Advertising - Success 21 (Timeout expires)",
+ &add_ext_advertising_timeout_expired,
+ setup_add_advertising_timeout,
+ test_command_generic, 3);
+
+ /* LE off will clear (remove) all instances. */
+ test_bredrle50("Add Ext Advertising - Success 22 (LE -> off, Remove)",
+ &add_ext_advertising_le_off,
+ setup_add_advertising,
+ test_command_generic);
+
+ test_bredrle50("Add Ext Advertising - Success (Empty ScRsp)",
+ &add_ext_advertising_empty_scrsp,
+ setup_command_generic,
+ test_command_generic);
+
+ test_bredrle50("Add Ext Advertising - Success (ScRsp only)",
+ &add_ext_advertising_scrsp_data_only_ok,
+ NULL, test_command_generic);
+
+ test_bredrle50("Add Ext Advertising - Invalid Params (ScRsp too long)",
+ &add_ext_advertising_scrsp_data_only_too_long,
+ NULL, test_command_generic);
+
+ test_bredrle50("Add Ext Advertising - Success (ScRsp appear)",
+ &add_ext_advertising_scrsp_appear_data_ok,
+ setup_command_generic, test_command_generic);
+
+ test_bredrle50("Add Ext Advertising - Invalid Params (ScRsp appear long)",
+ &add_ext_advertising_scrsp_appear_data_too_long,
+ setup_command_generic, test_command_generic);
+
+ test_bredrle50("Add Ext Advertising - Success (Appear is null)",
+ &add_ext_advertising_scrsp_appear_null,
+ NULL, test_command_generic);
+
+ test_bredrle50("Add Ext Advertising - Success (Name is null)",
+ &add_ext_advertising_no_name_set,
+ NULL, test_command_generic);
+
+ test_bredrle50("Add Ext Advertising - Success (Complete name)",
+ &add_ext_advertising_name_fits_in_scrsp,
+ setup_command_generic,
+ test_command_generic);
+
+ test_bredrle50("Add Ext Advertising - Success (Shortened name)",
+ &add_ext_advertising_shortened_name_in_scrsp,
+ setup_command_generic,
+ test_command_generic);
+
+ test_bredrle50("Add Ext Advertising - Success (Short name)",
+ &add_ext_advertising_shortened_name_in_scrsp,
+ setup_command_generic,
+ test_command_generic);
+
+ test_bredrle50("Add Ext Advertising - Success (Name + data)",
+ &add_ext_advertising_name_data_ok,
+ setup_command_generic,
+ test_command_generic);
+
+ test_bredrle50("Add Ext Advertising - Invalid Params (Name + data)",
+ &add_ext_advertising_name_data_inv,
+ setup_command_generic,
+ test_command_generic);
+
+ test_bredrle50("Add Ext Advertising - Success (Name+data+appear)",
+ &add_ext_advertising_name_data_appear,
+ setup_command_generic,
+ test_command_generic);
+
+ test_bredrle50("Add Ext Advertising - Success (PHY -> 1M)",
+ &add_ext_advertising_success_1m,
+ NULL, test_command_generic);
+
+ test_bredrle50("Add Ext Advertising - Success (PHY -> 2M)",
+ &add_ext_advertising_success_2m,
+ NULL, test_command_generic);
+
+ test_bredrle50("Add Ext Advertising - Success (PHY -> Coded)",
+ &add_ext_advertising_success_coded,
+ NULL, test_command_generic);
+
+ test_bredrle50("Add Ext Advertising - Success (Ext Pdu Scannable)",
+ &add_ext_advertising_success_scannable,
+ NULL, test_command_generic);
+
+ test_bredrle50("Add Ext Advertising - Success (Ext Pdu Connectable)",
+ &add_ext_advertising_success_connectable,
+ NULL, test_command_generic);
+
+ /* In Ext pdu it shall not be both scannable and connectable */
+ test_bredrle50("Add Ext Advertising - Success (Ext Pdu Conn Scan)",
+ &add_ext_advertising_success_conn_scan,
+ NULL, test_command_generic);
+
+ test_bredrle50("Add Ext Advertising - Success (1m Connectable -> on)",
+ &add_ext_advertising_conn_on_1m,
+ setup_add_advertising_1m,
+ test_command_generic);
+
+ test_bredrle50("Add Ext Advertising - Success (1m Connectable -> off)",
+ &add_ext_advertising_conn_off_1m,
+ setup_add_advertising_connectable_1m,
+ test_command_generic);
+
+ test_bredrle50("Remove Ext Advertising - Invalid Params 1",
+ &remove_ext_advertising_fail_1,
+ NULL, test_command_generic);
+
+ test_bredrle50("Remove Ext Advertising - Success 1",
+ &remove_ext_advertising_success_1,
+ setup_add_advertising,
+ test_command_generic);
+
+ test_bredrle50("Remove Ext Advertising - Success 2",
+ &remove_ext_advertising_success_2,
+ setup_add_advertising,
+ test_command_generic);
+
+ /* When advertising two instances, the instances should be
+ * advertised in a round-robin fashion.
+ */
+ test_bredrle50("Multi Ext Advertising - Success 1 (Instance Switch)",
+ &multi_ext_advertising_switch,
+ setup_multi_adv,
+ test_command_generic);
+
+ /* Adding a new instance when one is already being advertised
+ * will switch to the new instance after the first has reached
+ * its duration. A long timeout has been set to
+ */
+ test_bredrle50_full("Multi Ext Advertising - Success 2 (Add Second Inst)",
+ &multi_ext_advertising_add_second,
+ setup_add_advertising_duration,
+ test_command_generic, 3);
+
return tester_run();
}
--
2.7.4


2018-04-12 11:20:57

by Jaganath K

[permalink] [raw]
Subject: [PATCH v1 06/10] btmgmt: Add support for setting PHY in add-adv

---
lib/mgmt.h | 3 +++
tools/btmgmt.c | 17 ++++++++++++++++-
2 files changed, 19 insertions(+), 1 deletion(-)

diff --git a/lib/mgmt.h b/lib/mgmt.h
index 7a25e17..ec6a380 100644
--- a/lib/mgmt.h
+++ b/lib/mgmt.h
@@ -506,6 +506,9 @@ struct mgmt_rp_add_advertising {
#define MGMT_ADV_FLAG_TX_POWER (1 << 4)
#define MGMT_ADV_FLAG_APPEARANCE (1 << 5)
#define MGMT_ADV_FLAG_LOCAL_NAME (1 << 6)
+#define MGMT_ADV_FLAG_SEC_1M (1 << 7)
+#define MGMT_ADV_FLAG_SEC_2M (1 << 8)
+#define MGMT_ADV_FLAG_SEC_CODED (1 << 9)

#define MGMT_OP_REMOVE_ADVERTISING 0x003F
struct mgmt_cp_remove_advertising {
diff --git a/tools/btmgmt.c b/tools/btmgmt.c
index 750bb44..5f1f587 100755
--- a/tools/btmgmt.c
+++ b/tools/btmgmt.c
@@ -3629,6 +3629,9 @@ static const char *adv_flags_str[] = {
"tx-power",
"scan-rsp-appearance",
"scan-rsp-local-name",
+ "Secondary-channel-1M",
+ "Secondary-channel-2M",
+ "Secondary-channel-CODED",
};

static const char *adv_flags2str(uint32_t flags)
@@ -3846,6 +3849,7 @@ static void add_adv_usage(void)
"\t -s, --scan-rsp <data> Scan Response Data bytes\n"
"\t -t, --timeout <timeout> Timeout in seconds\n"
"\t -D, --duration <duration> Duration in seconds\n"
+ "\t -P, --phy <phy> Phy type, Specify 1M/2M/CODED\n"
"\t -c, --connectable \"connectable\" flag\n"
"\t -g, --general-discov \"general-discoverable\" flag\n"
"\t -l, --limited-discov \"limited-discoverable\" flag\n"
@@ -3864,6 +3868,7 @@ static struct option add_adv_options[] = {
{ "scan-rsp", 1, 0, 's' },
{ "timeout", 1, 0, 't' },
{ "duration", 1, 0, 'D' },
+ { "phy", 1, 0, 'P' },
{ "connectable", 0, 0, 'c' },
{ "general-discov", 0, 0, 'g' },
{ "limited-discov", 0, 0, 'l' },
@@ -3932,7 +3937,7 @@ static void cmd_add_adv(int argc, char **argv)
uint32_t flags = 0;
uint16_t index;

- while ((opt = getopt_long(argc, argv, "+u:d:s:t:D:cglmphna",
+ while ((opt = getopt_long(argc, argv, "+u:d:s:t:D:P:cglmphna",
add_adv_options, NULL)) != -1) {
switch (opt) {
case 'u':
@@ -4017,6 +4022,16 @@ static void cmd_add_adv(int argc, char **argv)
case 'a':
flags |= MGMT_ADV_FLAG_APPEARANCE;
break;
+ case 'P':
+ if (strcasecmp(optarg, "1M") == 0)
+ flags |= MGMT_ADV_FLAG_SEC_1M;
+ else if (strcasecmp(optarg, "2M") == 0)
+ flags |= MGMT_ADV_FLAG_SEC_2M;
+ else if (strcasecmp(optarg, "CODED") == 0)
+ flags |= MGMT_ADV_FLAG_SEC_CODED;
+ else
+ goto done;
+ break;
case 'h':
success = true;
/* fall through */
--
2.7.4


2018-04-12 11:20:56

by Jaganath K

[permalink] [raw]
Subject: [PATCH v1 05/10] monitor: Add support for Secondary PHY flags in Add Advertising

---
monitor/packet.c | 3 +++
1 file changed, 3 insertions(+)

diff --git a/monitor/packet.c b/monitor/packet.c
index e3b5ab7..2a22e7d 100644
--- a/monitor/packet.c
+++ b/monitor/packet.c
@@ -10741,6 +10741,9 @@ static const struct {
{ 4, "Add TX Power field to Advertising Data" },
{ 5, "Add Appearance field to Scan Response" },
{ 6, "Add Local Name in Scan Response" },
+ { 7, "Advertise in 1M on Secondary channel" },
+ { 8, "Advertise in 2M on Secondary channel" },
+ { 9, "Advertise in CODED on Secondary channel" },
{ }
};

--
2.7.4


2018-04-12 11:20:55

by Jaganath K

[permalink] [raw]
Subject: [PATCH v1 04/10] btmgmt: Add PHY configuration get/set commands

---
lib/mgmt.h | 33 +++++++++++++++
tools/btmgmt.c | 128 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 161 insertions(+)
mode change 100644 => 100755 tools/btmgmt.c

diff --git a/lib/mgmt.h b/lib/mgmt.h
index 798a05e..7a25e17 100644
--- a/lib/mgmt.h
+++ b/lib/mgmt.h
@@ -101,6 +101,7 @@ struct mgmt_rp_read_index_list {
#define MGMT_SETTING_PRIVACY 0x00002000
#define MGMT_SETTING_CONFIGURATION 0x00004000
#define MGMT_SETTING_STATIC_ADDRESS 0x00008000
+#define MGMT_SETTING_PHY_CONFIGURATION 0x00010000

#define MGMT_OP_READ_INFO 0x0004
struct mgmt_rp_read_info {
@@ -546,6 +547,30 @@ struct mgmt_cp_set_appearance {
uint16_t appearance;
} __packed;

+#define MGMT_OP_GET_PHY_CONFIGURATION 0x0044
+struct mgmt_rp_get_phy_confguration {
+ uint16_t supported_phys;
+ uint16_t selected_phys;
+} __packed;
+
+#define MGMT_PHY_LE_1M_TX 0x0001
+#define MGMT_PHY_LE_1M_RX 0x0002
+#define MGMT_PHY_LE_2M_TX 0x0004
+#define MGMT_PHY_LE_2M_RX 0x0008
+#define MGMT_PHY_LE_CODED_TX 0x0010
+#define MGMT_PHY_LE_CODED_RX 0x0020
+
+#define MGMT_PHY_LE_TX_MASK (MGMT_PHY_LE_1M_TX | MGMT_PHY_LE_2M_TX | \
+ MGMT_PHY_LE_CODED_TX)
+#define MGMT_PHY_LE_RX_MASK (MGMT_PHY_LE_1M_RX | MGMT_PHY_LE_2M_RX | \
+ MGMT_PHY_LE_CODED_RX)
+
+#define MGMT_OP_SET_PHY_CONFIGURATION 0x0045
+struct mgmt_cp_set_phy_confguration {
+ uint16_t default_phys;
+} __packed;
+
+
#define MGMT_EV_CMD_COMPLETE 0x0001
struct mgmt_ev_cmd_complete {
uint16_t opcode;
@@ -764,6 +789,11 @@ struct mgmt_ev_ext_info_changed {
uint8_t eir[0];
} __packed;

+#define MGMT_EV_PHY_CONFIGURATION_CHANGED 0x0026
+struct mgmt_ev_phy_configuration_changed {
+ uint16_t selected_phys;
+} __packed;
+
static const char *mgmt_op[] = {
"<0x0000>",
"Read Version",
@@ -833,6 +863,8 @@ static const char *mgmt_op[] = {
"Start Limited Discovery",
"Read Extended Controller Information",
"Set Appearance",
+ "Get PHY Configuration",
+ "Set PHY Configuration",
};

static const char *mgmt_ev[] = {
@@ -874,6 +906,7 @@ static const char *mgmt_ev[] = {
"Advertising Added",
"Advertising Removed",
"Extended Controller Information Changed",
+ "PHY Configuration Changed",
};

static const char *mgmt_status[] = {
diff --git a/tools/btmgmt.c b/tools/btmgmt.c
old mode 100644
new mode 100755
index f60bb8b..750bb44
--- a/tools/btmgmt.c
+++ b/tools/btmgmt.c
@@ -4165,6 +4165,132 @@ static void cmd_appearance(int argc, char **argv)
}
}

+static const char *phys_str[] = {
+ "1MTX",
+ "1MRX",
+ "2MTX",
+ "2MRX",
+ "CODEDTX",
+ "CODEDRX",
+};
+
+static const char *phys2str(uint16_t phys)
+{
+ static char str[256];
+ unsigned i;
+ int off;
+
+ off = 0;
+ str[0] = '\0';
+
+ for (i = 0; i < NELEM(phys_str); i++) {
+ if ((phys & (1 << i)) != 0)
+ off += snprintf(str + off, sizeof(str) - off, "%s ",
+ phys_str[i]);
+ }
+
+ return str;
+}
+
+static void get_phy_rsp(uint8_t status, uint16_t len, const void *param,
+ void *user_data)
+{
+ const struct mgmt_rp_get_phy_confguration *rp = param;
+ uint16_t supported_flags, selected_phys;
+
+ if (status != 0) {
+ error("Get PHY Configuration failed with status 0x%02x (%s)",
+ status, mgmt_errstr(status));
+ return bt_shell_noninteractive_quit(EXIT_FAILURE);
+ }
+
+ if (len < sizeof(*rp)) {
+ error("Too small get-phy reply (%u bytes)", len);
+ return bt_shell_noninteractive_quit(EXIT_FAILURE);
+ }
+
+ supported_flags = get_le16(&rp->supported_phys);
+ selected_phys = get_le16(&rp->selected_phys);
+
+ print("Supported phys: %s", phys2str(supported_flags));
+ print("Selected phys: %s", phys2str(selected_phys));
+
+ bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static void get_phy()
+{
+ uint16_t index;
+
+ index = mgmt_index;
+ if (index == MGMT_INDEX_NONE)
+ index = 0;
+
+ if (mgmt_send(mgmt, MGMT_OP_GET_PHY_CONFIGURATION, index, 0, NULL,
+ get_phy_rsp, NULL, NULL) == 0) {
+ error("Unable to send Get PHY cmd");
+ return bt_shell_noninteractive_quit(EXIT_FAILURE);
+ }
+}
+
+static void set_phy_rsp(uint8_t status, uint16_t len, const void *param,
+ void *user_data)
+{
+ if (status != 0) {
+ error("Could not set PHY Configuration with status 0x%02x (%s)",
+ status, mgmt_errstr(status));
+ return bt_shell_noninteractive_quit(EXIT_FAILURE);
+ }
+
+ print("PHY Configuration successfully set");
+
+ bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static void cmd_phy(int argc, char **argv)
+{
+ struct mgmt_cp_set_phy_confguration cp;
+ int i;
+ uint16_t phys = 0;
+ uint16_t index;
+
+ if (argc < 2)
+ return get_phy();
+
+ for (i = 1; i < argc; i++) {
+ if (strcasecmp(argv[i], "1MTX") == 0)
+ phys |= MGMT_PHY_LE_1M_TX;
+
+ if (strcasecmp(argv[i], "1MRX") == 0)
+ phys |= MGMT_PHY_LE_1M_RX;
+
+ if (strcasecmp(argv[i], "2MTX") == 0)
+ phys |= MGMT_PHY_LE_2M_TX;
+
+ if (strcasecmp(argv[i], "2MRX") == 0)
+ phys |= MGMT_PHY_LE_2M_RX;
+
+ if (strcasecmp(argv[i], "CODEDTX") == 0)
+ phys |= MGMT_PHY_LE_CODED_TX;
+
+ if (strcasecmp(argv[i], "CODEDRX") == 0)
+ phys |= MGMT_PHY_LE_CODED_RX;
+ }
+
+ cp.default_phys = cpu_to_le16(phys);
+
+ index = mgmt_index;
+ if (index == MGMT_INDEX_NONE)
+ index = 0;
+
+ if (mgmt_send(mgmt, MGMT_OP_SET_PHY_CONFIGURATION, index, sizeof(cp),
+ &cp, set_phy_rsp, NULL, NULL) == 0) {
+ error("Unable to send %s cmd",
+ mgmt_opstr(MGMT_OP_GET_PHY_CONFIGURATION));
+ return bt_shell_noninteractive_quit(EXIT_FAILURE);
+ }
+}
+
static void register_mgmt_callbacks(struct mgmt *mgmt, uint16_t index)
{
mgmt_register(mgmt, MGMT_EV_CONTROLLER_ERROR, index, controller_error,
@@ -4360,6 +4486,8 @@ static const struct bt_shell_menu main_menu = {
cmd_clr_adv, "Clear advertising instances" },
{ "appearance", "<appearance>",
cmd_appearance, "Set appearance" },
+ { "phy", "[phys]",
+ cmd_phy, "Get/Set PHY Configuration" },
{} },
};

--
2.7.4


2018-04-12 11:20:54

by Jaganath K

[permalink] [raw]
Subject: [PATCH v1 03/10] monitor: Add support PHY management commands and event

---
monitor/packet.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 65 insertions(+)

diff --git a/monitor/packet.c b/monitor/packet.c
index b800a2d..e3b5ab7 100644
--- a/monitor/packet.c
+++ b/monitor/packet.c
@@ -97,6 +97,7 @@
#define COLOR_UNKNOWN_ADDRESS_TYPE COLOR_WHITE_BG
#define COLOR_UNKNOWN_DEVICE_FLAG COLOR_WHITE_BG
#define COLOR_UNKNOWN_ADV_FLAG COLOR_WHITE_BG
+#define COLOR_UNKNOWN_PHY COLOR_WHITE_BG

#define COLOR_PHY_PACKET COLOR_BLUE

@@ -10611,6 +10612,7 @@ static const struct {
{ 13, "Privacy" },
{ 14, "Controller Configuration"},
{ 15, "Static Address" },
+ { 16, "PHY Configuration" },
{ }
};

@@ -11905,6 +11907,54 @@ static void mgmt_set_apperance_cmd(const void *data, uint16_t size)
print_appearance(appearance);
}

+static const struct {
+ uint8_t bit;
+ const char *str;
+} mgmt_phy_table[] = {
+ { 0, "1MTX" },
+ { 1, "1MRX" },
+ { 2, "2MTX" },
+ { 3, "2MRX" },
+ { 4, "CODEDTX" },
+ { 5, "CODEDRX" },
+ { }
+};
+
+static void mgmt_print_phys(const char *label, uint16_t phys)
+{
+ uint16_t mask = phys;
+ int i;
+
+ print_field("%s: 0x%4.4x", label, phys);
+
+ for (i = 0; mgmt_phy_table[i].str; i++) {
+ if (phys & (1 << mgmt_phy_table[i].bit)) {
+ print_field(" %s", mgmt_phy_table[i].str);
+ mask &= ~(1 << mgmt_phy_table[i].bit);
+ }
+ }
+
+ if (mask)
+ print_text(COLOR_UNKNOWN_PHY, " Unknown PHYs"
+ " (0x%8.8x)", mask);
+}
+
+static void mgmt_get_phy_rsp(const void *data, uint16_t size)
+{
+ uint16_t supported_phys = get_le16(data);
+ uint16_t selected_phys = get_le16(data + 2);
+
+ mgmt_print_phys("Supported PHYs", supported_phys);
+ mgmt_print_phys("Selected PHYs", selected_phys);
+}
+
+static void mgmt_set_phy_cmd(const void *data, uint16_t size)
+{
+ uint16_t default_phys = get_le16(data);
+
+ mgmt_print_phys("Default PHYs", default_phys);
+}
+
struct mgmt_data {
uint16_t opcode;
const char *str;
@@ -12118,6 +12168,12 @@ static const struct mgmt_data mgmt_command_table[] = {
{ 0x0043, "Set Appearance",
mgmt_set_apperance_cmd, 2, true,
mgmt_null_rsp, 0, true },
+ { 0x0044, "Get PHY Configuration",
+ mgmt_null_cmd, 0, true,
+ mgmt_get_phy_rsp, 4, true },
+ { 0x0045, "Set PHY Configuration",
+ mgmt_set_phy_cmd, 2, true,
+ mgmt_null_rsp, 0, true },
{ }
};

@@ -12496,6 +12552,13 @@ static void mgmt_ext_controller_info_changed_evt(const void *data, uint16_t size
print_eir(data + 2, size - 2, false);
}

+static void mgmt_phy_changed_evt(const void *data, uint16_t size)
+{
+ uint16_t selected_phys = get_le16(data);
+
+ mgmt_print_phys("Selected PHYs", selected_phys);
+}
+
static const struct mgmt_data mgmt_event_table[] = {
{ 0x0001, "Command Complete",
mgmt_command_complete_evt, 3, false },
@@ -12571,6 +12634,8 @@ static const struct mgmt_data mgmt_event_table[] = {
mgmt_advertising_removed_evt, 1, true },
{ 0x0025, "Extended Controller Information Changed",
mgmt_ext_controller_info_changed_evt, 2, false },
+ { 0x0026, "PHY Configuration Changed",
+ mgmt_phy_changed_evt, 2, true },
{ }
};

--
2.7.4


2018-04-12 11:20:53

by Jaganath K

[permalink] [raw]
Subject: [PATCH v1 02/10] doc/mgmt-api: Add advertising phys support to flags

---
doc/mgmt-api.txt | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)

diff --git a/doc/mgmt-api.txt b/doc/mgmt-api.txt
index caba22d..87982e0 100644
--- a/doc/mgmt-api.txt
+++ b/doc/mgmt-api.txt
@@ -2504,6 +2504,9 @@ Read Advertising Features Command
4 Add TX Power field to Adv_Data
5 Add Appearance field to Scan_Rsp
6 Add Local Name in Scan_Rsp
+ 7 Secondary Channel with LE 1M
+ 8 Secondary Channel with LE 2M
+ 9 Secondary Channel with LE Coded

The Flags bit 0 indicates support for connectable advertising
and for switching to connectable advertising independent of the
@@ -2553,6 +2556,15 @@ Read Advertising Features Command
space is limited a short version or no name information. The
Local Name will be added at the end of the scan response data.

+ The Flags bit 7 indicates support for advertising in secondary
+ channel in LE 1M PHY.
+
+ The Flags bit 8 indicates support for advertising in secondary
+ channel in LE 2M PHY. Primary channel would be on 1M.
+
+ The Flags bit 9 indicates support for advertising in secondary
+ channel in LE CODED PHY.
+
The valid range for Instance identifiers is 1-254. The value 0
is reserved for internal use and the value 255 is reserved for
future extensions. However the Max_Instances value for indicating
@@ -2613,6 +2625,9 @@ Add Advertising Command
4 Add TX Power field to Adv_Data
5 Add Appearance field to Scan_Rsp
6 Add Local Name in Scan_Rsp
+ 7 Secondary Channel with LE 1M
+ 8 Secondary Channel with LE 2M
+ 9 Secondary Channel with LE Coded

When the connectable flag is set, then the controller will use
undirected connectable advertising. The value of the connectable
@@ -2640,6 +2655,16 @@ Add Advertising Command
supported to provide less air traffic for devices implementing
broadcaster role.

+ Secondary channel flags can be used to advertise in secondary
+ channel with the corresponding PHYs. These flag bits are mutually
+ exclusive and setting multiple will result in Invalid Parameter
+ error. Choosing either LE 1M or LE 2M will result in using
+ extended advertising on the primary channel with LE 1M and the
+ respectively LE 1M or LE 2M on the secondary channel. Choosing
+ LE Coded will result in using extended advertising on the primary
+ and secondary channels with LE Coded. Choosing none of these flags
+ will result in legacy advertising.
+
The Duration parameter configures the length of an Instance. The
value is in seconds.

--
2.7.4


2018-04-12 11:20:52

by Jaganath K

[permalink] [raw]
Subject: [PATCH v1 01/10] doc/mgmt-api: Add support for Set Phy Configuration command

This also adds PHY Configuration Changed Event.
---
doc/mgmt-api.txt | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 81 insertions(+)

diff --git a/doc/mgmt-api.txt b/doc/mgmt-api.txt
index 8e7de14..caba22d 100644
--- a/doc/mgmt-api.txt
+++ b/doc/mgmt-api.txt
@@ -2917,6 +2917,72 @@ Set Appearance Command
Invalid Index


+Get PHY Configuration Command
+==========================
+
+ Command Code: 0x0043
+ Controller Index: <controller id>
+ Command Parameters:
+ Return Parameters: Supported_phys (2 Octet)
+ Selected_phys (2 Octet)
+
+ This command is used to retrieve the supported PHYs and currently
+ selected PHYs.
+
+ Supported_phys and Selected_phys is a bitmask with the following bits.
+ 0 LE 1M TX
+ 1 LE 1M RX
+ 2 LE 2M TX
+ 3 LE 2M RX
+ 4 LE CODED TX
+ 5 LE CODED RX
+
+ LE 1M TX and LE 1M RX would be supported by default.
+
+ This command is only available for LE capable controllers.
+ It will return Not Supported otherwise.
+
+ Possible errors: Not Supported
+ Invalid Index
+
+Set PHY Configuration Command
+=============================
+
+ Command Code: 0x0044
+ Controller Index: <controller id>
+ Command Parameters: Default_phys (2 Octet)
+ Return Parameters:
+
+ This command is used to set the default phy to the controller.
+
+ This will be stored and used for all the subsequent scanning
+ and connection initiation.
+
+ The list of supported PHYs can be retrieved via the
+ Get PHY Configuration command. Selecting unsupported PHYs will
+ result in an Invalid Parameters error.
+
+ This can be called at any point to change the preferred PHYs.
+
+ Default_phys is a bitmask with the following bits.
+ 0 LE 1M TX
+ 1 LE 1M RX
+ 2 LE 2M TX
+ 3 LE 2M RX
+ 4 LE CODED TX
+ 5 LE CODED RX
+
+ This command generates a Command Complete event on success
+ or a Command Status event on failure.
+
+ This command is only available for LE capable controllers.
+ It will return Not Supported otherwise.
+
+ Possible errors: Not Supported
+ Invalid Parameters
+ Invalid Index
+
+
Command Complete Event
======================

@@ -3782,3 +3848,18 @@ Extended Controller Information Changed Event

The event will only be sent to management sockets other than the
one through which the change was triggered.
+
+PHY Configuration Changed Event
+===============================
+
+ Event Code: 0x0026
+ Controller Index: <controller id>
+ Event Parameters: Selected_phys (2 Octets)
+
+ This event indicates that default PHYs have been updated.
+
+ This event will only be used after Set PHY Configuration
+ command has been used at least once.
+
+ The event will only be sent to management sockets other than the
+ one through which the change was triggered.
--
2.7.4


2018-06-21 14:29:56

by Marcel Holtmann

[permalink] [raw]
Subject: Re: [PATCH v1 03/10] monitor: Add support PHY management commands and event

Hi Jaganath,

> ---
> monitor/packet.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 65 insertions(+)
>
> diff --git a/monitor/packet.c b/monitor/packet.c
> index b800a2d..e3b5ab7 100644
> --- a/monitor/packet.c
> +++ b/monitor/packet.c
> @@ -97,6 +97,7 @@
> #define COLOR_UNKNOWN_ADDRESS_TYPE COLOR_WHITE_BG
> #define COLOR_UNKNOWN_DEVICE_FLAG COLOR_WHITE_BG
> #define COLOR_UNKNOWN_ADV_FLAG COLOR_WHITE_BG
> +#define COLOR_UNKNOWN_PHY COLOR_WHITE_BG
>
> #define COLOR_PHY_PACKET COLOR_BLUE
>
> @@ -10611,6 +10612,7 @@ static const struct {
> { 13, "Privacy" },
> { 14, "Controller Configuration"},
> { 15, "Static Address" },
> + { 16, "PHY Configuration" },
> { }
> };
>
> @@ -11905,6 +11907,54 @@ static void mgmt_set_apperance_cmd(const void *data, uint16_t size)
> print_appearance(appearance);
> }
>
> +static const struct {
> + uint8_t bit;
> + const char *str;
> +} mgmt_phy_table[] = {
> + { 0, "1MTX" },
> + { 1, "1MRX" },
> + { 2, "2MTX" },
> + { 3, "2MRX" },
> + { 4, "CODEDTX" },
> + { 5, "CODEDRX" },
> + { }
> +};

this is unreadable. Use full strings like “LE 1M TX” etc.

Regards

Marcel