2015-10-05 18:28:25

by Jakub Pawlowski

[permalink] [raw]
Subject: [PATCH v4 1/5] emulator: add support for checking le scan state

---
emulator/btdev.c | 5 +++++
emulator/btdev.h | 2 ++
emulator/hciemu.c | 8 ++++++++
emulator/hciemu.h | 2 ++
4 files changed, 17 insertions(+)

diff --git a/emulator/btdev.c b/emulator/btdev.c
index e8cead8..aee7a48 100644
--- a/emulator/btdev.c
+++ b/emulator/btdev.c
@@ -675,6 +675,11 @@ uint8_t *btdev_get_features(struct btdev *btdev)
return btdev->features;
}

+bool btdev_is_le_scan_enabled(struct btdev *btdev)
+{
+ return btdev->le_scan_enable;
+}
+
static bool use_ssp(struct btdev *btdev1, struct btdev *btdev2)
{
if (btdev1->auth_enable || btdev2->auth_enable)
diff --git a/emulator/btdev.h b/emulator/btdev.h
index 4b724a7..8b116e4 100644
--- a/emulator/btdev.h
+++ b/emulator/btdev.h
@@ -80,6 +80,8 @@ void btdev_destroy(struct btdev *btdev);
const uint8_t *btdev_get_bdaddr(struct btdev *btdev);
uint8_t *btdev_get_features(struct btdev *btdev);

+bool btdev_is_le_scan_enabled(struct btdev *btdev);
+
void btdev_set_command_handler(struct btdev *btdev, btdev_command_func handler,
void *user_data);

diff --git a/emulator/hciemu.c b/emulator/hciemu.c
index 4881a24..725fbd4 100644
--- a/emulator/hciemu.c
+++ b/emulator/hciemu.c
@@ -427,6 +427,14 @@ const uint8_t *hciemu_get_client_bdaddr(struct hciemu *hciemu)
return btdev_get_bdaddr(hciemu->client_dev);
}

+bool hciemu_is_master_le_scan_enabled(struct hciemu *hciemu)
+{
+ if (!hciemu || !hciemu->master_dev)
+ return NULL;
+
+ return btdev_is_le_scan_enabled(hciemu->master_dev);
+}
+
bool hciemu_add_master_post_command_hook(struct hciemu *hciemu,
hciemu_command_func_t function, void *user_data)
{
diff --git a/emulator/hciemu.h b/emulator/hciemu.h
index 41ca3fc..04bfab7 100644
--- a/emulator/hciemu.h
+++ b/emulator/hciemu.h
@@ -53,6 +53,8 @@ uint8_t *hciemu_get_features(struct hciemu *hciemu);
const uint8_t *hciemu_get_master_bdaddr(struct hciemu *hciemu);
const uint8_t *hciemu_get_client_bdaddr(struct hciemu *hciemu);

+bool hciemu_is_master_le_scan_enabled(struct hciemu *hciemu);
+
typedef void (*hciemu_command_func_t)(uint16_t opcode, const void *data,
uint8_t len, void *user_data);

--
2.5.0



2015-10-05 18:28:29

by Jakub Pawlowski

[permalink] [raw]
Subject: [PATCH v4 5/5] tools/l2cap-tester connect two sockets disconnect one test

This test open two sockets to same client, then close first one and make
sure second one connect successfully.
---
tools/l2cap-tester.c | 39 +++++++++++++++++++++++++++++++++++++--
1 file changed, 37 insertions(+), 2 deletions(-)

diff --git a/tools/l2cap-tester.c b/tools/l2cap-tester.c
index a483977..12360aa 100644
--- a/tools/l2cap-tester.c
+++ b/tools/l2cap-tester.c
@@ -90,6 +90,7 @@ struct l2cap_data {

uint8_t *client_bdaddr;
bool server_not_advertising;
+ bool close_one_socket;
};

static void mgmt_debug(const char *str, void *user_data)
@@ -472,6 +473,13 @@ static const struct l2cap_data le_client_two_sockets_same_client = {
.server_not_advertising = true,
};

+static const struct l2cap_data le_client_two_sockets_close_one = {
+ .client_psm = 0x0080,
+ .server_psm = 0x0080,
+ .server_not_advertising = true,
+ .close_one_socket = true,
+};
+
static const struct l2cap_data le_client_connect_nval_psm_test = {
.client_psm = 0x0080,
.expect_err = ECONNREFUSED,
@@ -1377,6 +1385,7 @@ static gboolean test_two_sockets_connect_cb(GIOChannel *io, GIOCondition cond,
gpointer user_data)
{
struct test_data *data = tester_get_data();
+ const struct l2cap_data *l2data = data->test_data;
int err, sk_err, sk;
socklen_t len = sizeof(sk_err);

@@ -1404,6 +1413,11 @@ static gboolean test_two_sockets_connect_cb(GIOChannel *io, GIOCondition cond,
tester_test_passed();
}

+ if (l2data->close_one_socket && test_two_sockets_connect_cb_cnt == 1) {
+ close(data->sk2);
+ tester_test_passed();
+ }
+
return FALSE;
}

@@ -1419,14 +1433,21 @@ static gboolean enable_advertising(gpointer args)
static void test_connect_two_sockets_part_2(void)
{
struct test_data *data = tester_get_data();
+ const struct l2cap_data *l2data = data->test_data;
const uint8_t *client_bdaddr;

client_bdaddr = hciemu_get_client_bdaddr(data->hciemu);
connect_socket(client_bdaddr, &data->sk2, test_two_sockets_connect_cb);

+ if (l2data->close_one_socket) {
+ tester_print("Closing first socket! %d", data->sk);
+ close(data->sk);
+ }
+
g_idle_add(enable_advertising, NULL);
}

+static uint8_t test_scan_enable_counter;
static void test_connect_two_sockets_router(uint16_t opcode, const void *param,
uint8_t length, void *user_data)
{
@@ -1435,7 +1456,11 @@ static void test_connect_two_sockets_router(uint16_t opcode, const void *param,
tester_print("HCI Command 0x%04x length %u", opcode, length);
if (opcode == BT_HCI_CMD_LE_SET_SCAN_ENABLE &&
scan_params->enable == true) {
- test_connect_two_sockets_part_2();
+ test_scan_enable_counter++;
+ if (test_scan_enable_counter == 1)
+ test_connect_two_sockets_part_2();
+ else if (test_scan_enable_counter == 2)
+ g_idle_add(enable_advertising, NULL);
}
}

@@ -1446,6 +1471,7 @@ static void test_connect_two_sockets(const void *test_data)
const uint8_t *client_bdaddr;

test_two_sockets_connect_cb_cnt = 0;
+ test_scan_enable_counter = 0;

hciemu_add_master_post_command_hook(data->hciemu,
test_connect_two_sockets_router, data);
@@ -1459,7 +1485,11 @@ static void test_connect_two_sockets(const void *test_data)
}

client_bdaddr = hciemu_get_client_bdaddr(data->hciemu);
- connect_socket(client_bdaddr, &data->sk, test_two_sockets_connect_cb);
+ if (l2data->close_one_socket)
+ connect_socket(client_bdaddr, &data->sk, NULL);
+ else
+ connect_socket(client_bdaddr, &data->sk,
+ test_two_sockets_connect_cb);
}

static gboolean l2cap_listen_cb(GIOChannel *io, GIOCondition cond,
@@ -1793,6 +1823,11 @@ int main(int argc, char *argv[])
setup_powered_client,
test_connect_two_sockets);

+ test_l2cap_le("L2CAP LE Client - Open two sockets close one",
+ &le_client_two_sockets_close_one,
+ setup_powered_client,
+ test_connect_two_sockets);
+
test_l2cap_le("L2CAP LE Client - Invalid PSM",
&le_client_connect_nval_psm_test,
setup_powered_client, test_connect);
--
2.5.0


2015-10-05 18:28:28

by Jakub Pawlowski

[permalink] [raw]
Subject: [PATCH v4 4/5] tools/l2cap-tester: Two socket connect test

This test tries to open two sockets to same address, to make sure
both would succeed.
---
tools/l2cap-tester.c | 102 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 102 insertions(+)

diff --git a/tools/l2cap-tester.c b/tools/l2cap-tester.c
index bad50ad..a483977 100644
--- a/tools/l2cap-tester.c
+++ b/tools/l2cap-tester.c
@@ -54,6 +54,7 @@ struct test_data {
uint16_t scid;
uint16_t dcid;
int sk;
+ int sk2;
};

struct l2cap_data {
@@ -465,6 +466,12 @@ static const struct l2cap_data le_client_close_socket_test_2 = {
.server_not_advertising = true,
};

+static const struct l2cap_data le_client_two_sockets_same_client = {
+ .client_psm = 0x0080,
+ .server_psm = 0x0080,
+ .server_not_advertising = true,
+};
+
static const struct l2cap_data le_client_connect_nval_psm_test = {
.client_psm = 0x0080,
.expect_err = ECONNREFUSED,
@@ -1365,6 +1372,96 @@ static void test_close_socket(const void *test_data)
connect_socket(client_bdaddr, &data->sk, NULL);
}

+static uint8_t test_two_sockets_connect_cb_cnt;
+static gboolean test_two_sockets_connect_cb(GIOChannel *io, GIOCondition cond,
+ gpointer user_data)
+{
+ struct test_data *data = tester_get_data();
+ int err, sk_err, sk;
+ socklen_t len = sizeof(sk_err);
+
+ data->io_id = 0;
+
+ sk = g_io_channel_unix_get_fd(io);
+
+ if (getsockopt(sk, SOL_SOCKET, SO_ERROR, &sk_err, &len) < 0)
+ err = -errno;
+ else
+ err = -sk_err;
+
+ if (err < 0) {
+ tester_warn("Connect failed: %s (%d)", strerror(-err), -err);
+ tester_test_failed();
+ return FALSE;
+ }
+
+ tester_print("Successfully connected");
+ test_two_sockets_connect_cb_cnt++;
+
+ if (test_two_sockets_connect_cb_cnt == 2) {
+ close(data->sk);
+ close(data->sk2);
+ tester_test_passed();
+ }
+
+ return FALSE;
+}
+
+static gboolean enable_advertising(gpointer args)
+{
+ struct test_data *data = tester_get_data();
+ struct bthost *bthost = hciemu_client_get_host(data->hciemu);
+
+ bthost_set_adv_enable(bthost, 0x01);
+ return FALSE;
+}
+
+static void test_connect_two_sockets_part_2(void)
+{
+ struct test_data *data = tester_get_data();
+ const uint8_t *client_bdaddr;
+
+ client_bdaddr = hciemu_get_client_bdaddr(data->hciemu);
+ connect_socket(client_bdaddr, &data->sk2, test_two_sockets_connect_cb);
+
+ g_idle_add(enable_advertising, NULL);
+}
+
+static void test_connect_two_sockets_router(uint16_t opcode, const void *param,
+ uint8_t length, void *user_data)
+{
+ const struct bt_hci_cmd_le_set_scan_enable *scan_params = param;
+
+ tester_print("HCI Command 0x%04x length %u", opcode, length);
+ if (opcode == BT_HCI_CMD_LE_SET_SCAN_ENABLE &&
+ scan_params->enable == true) {
+ test_connect_two_sockets_part_2();
+ }
+}
+
+static void test_connect_two_sockets(const void *test_data)
+{
+ struct test_data *data = tester_get_data();
+ const struct l2cap_data *l2data = data->test_data;
+ const uint8_t *client_bdaddr;
+
+ test_two_sockets_connect_cb_cnt = 0;
+
+ hciemu_add_master_post_command_hook(data->hciemu,
+ test_connect_two_sockets_router, data);
+
+ if (l2data->server_psm) {
+ struct bthost *bthost = hciemu_client_get_host(data->hciemu);
+
+ if (!l2data->data_len)
+ bthost_add_l2cap_server(bthost, l2data->server_psm,
+ NULL, NULL);
+ }
+
+ client_bdaddr = hciemu_get_client_bdaddr(data->hciemu);
+ connect_socket(client_bdaddr, &data->sk, test_two_sockets_connect_cb);
+}
+
static gboolean l2cap_listen_cb(GIOChannel *io, GIOCondition cond,
gpointer user_data)
{
@@ -1691,6 +1788,11 @@ int main(int argc, char *argv[])
setup_powered_client,
test_close_socket);

+ test_l2cap_le("L2CAP LE Client - Open two sockets",
+ &le_client_two_sockets_same_client,
+ setup_powered_client,
+ test_connect_two_sockets);
+
test_l2cap_le("L2CAP LE Client - Invalid PSM",
&le_client_connect_nval_psm_test,
setup_powered_client, test_connect);
--
2.5.0


2015-10-05 18:28:27

by Jakub Pawlowski

[permalink] [raw]
Subject: [PATCH v4 3/5] tools/l2cap-tester: Disconnect during connect attempt test

This patch adds test that checks folowing:
1. Try to connect to existing BLE device that is not advertising.
2. Internally in kernel this adds this device to whitelist and enable scan.
3. Make the device advertise once. That would stop the scan, and trigger
connect attempt to device.
4. Close socket. This should stop the connect attempt, by sending
BT_HCI_CMD_LE_CREATE_CONN_CANCEL.
---
tools/l2cap-tester.c | 111 ++++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 105 insertions(+), 6 deletions(-)

diff --git a/tools/l2cap-tester.c b/tools/l2cap-tester.c
index 0885209..bad50ad 100644
--- a/tools/l2cap-tester.c
+++ b/tools/l2cap-tester.c
@@ -88,6 +88,7 @@ struct l2cap_data {
uint8_t addr_type;

uint8_t *client_bdaddr;
+ bool server_not_advertising;
};

static void mgmt_debug(const char *str, void *user_data)
@@ -459,6 +460,11 @@ static const struct l2cap_data le_client_close_socket_test_1 = {
.client_bdaddr = nonexisting_bdaddr,
};

+static const struct l2cap_data le_client_close_socket_test_2 = {
+ .client_psm = 0x0080,
+ .server_not_advertising = true,
+};
+
static const struct l2cap_data le_client_connect_nval_psm_test = {
.client_psm = 0x0080,
.expect_err = ECONNREFUSED,
@@ -543,6 +549,7 @@ static void setup_powered_client_callback(uint8_t status, uint16_t length,
const void *param, void *user_data)
{
struct test_data *data = tester_get_data();
+ const struct l2cap_data *l2data = data->test_data;
struct bthost *bthost;

if (status != MGMT_STATUS_SUCCESS) {
@@ -554,10 +561,15 @@ static void setup_powered_client_callback(uint8_t status, uint16_t length,

bthost = hciemu_client_get_host(data->hciemu);
bthost_set_cmd_complete_cb(bthost, client_cmd_complete, user_data);
- if (data->hciemu_type == HCIEMU_TYPE_LE)
- bthost_set_adv_enable(bthost, 0x01);
- else
+
+ if (data->hciemu_type == HCIEMU_TYPE_LE) {
+ if (!l2data || !l2data->server_not_advertising)
+ bthost_set_adv_enable(bthost, 0x01);
+ else
+ tester_setup_complete();
+ } else {
bthost_write_scan_enable(bthost, 0x03);
+ }
}

static void setup_powered_server_callback(uint8_t status, uint16_t length,
@@ -1239,18 +1251,100 @@ static gboolean test_close_socket_1_part_2(gpointer args)
return FALSE;
}

+static gboolean test_close_socket_2_part_3(gpointer arg)
+{
+ struct test_data *data = tester_get_data();
+ int sk = data->sk;
+ int err;
+
+ /* Scan should be already over, we're trying to create connection */
+ if (hciemu_is_master_le_scan_enabled(data->hciemu)) {
+ tester_print("Error - should no longer scan");
+ tester_test_failed();
+ return FALSE;
+ }
+
+ /* Calling close() should eventually cause CMD_LE_CREATE_CONN_CANCEL */
+ err = close(sk);
+ if (err < 0) {
+ tester_print("Error when closing socket");
+ tester_test_failed();
+ return FALSE;
+ }
+
+ /* CMD_LE_CREATE_CONN_CANCEL will trigger test pass. */
+ return FALSE;
+}
+
+static bool test_close_socket_cc_hook(const void *data, uint16_t len,
+ void *user_data)
+{
+ return false;
+}
+
+static gboolean test_close_socket_2_part_2(gpointer arg)
+{
+ struct test_data *data = tester_get_data();
+ struct bthost *bthost = hciemu_client_get_host(data->hciemu);
+
+ /* Make sure CMD_LE_CREATE_CONN will not immediately result in
+ * BT_HCI_EVT_CONN_COMPLETE.
+ */
+ hciemu_add_hook(data->hciemu, HCIEMU_HOOK_PRE_EVT,
+ BT_HCI_CMD_LE_CREATE_CONN, test_close_socket_cc_hook, NULL);
+
+ /* Advertise once. After that, kernel should stop scanning, and trigger
+ * BT_HCI_CMD_LE_CREATE_CONN_CANCEL.
+ */
+ bthost_set_adv_enable(bthost, 0x01);
+ bthost_set_adv_enable(bthost, 0x00);
+ return FALSE;
+}
+
+static void test_close_socket_scan_enabled(void)
+{
+ struct test_data *data = tester_get_data();
+ const struct l2cap_data *l2data = data->test_data;
+
+ if (l2data == &le_client_close_socket_test_1)
+ g_idle_add(test_close_socket_1_part_2, NULL);
+ else if (l2data == &le_client_close_socket_test_2)
+ g_idle_add(test_close_socket_2_part_2, NULL);
+}
+
+static void test_close_socket_scan_disabled(void)
+{
+ struct test_data *data = tester_get_data();
+ const struct l2cap_data *l2data = data->test_data;
+
+ if (l2data == &le_client_close_socket_test_1)
+ g_idle_add(test_close_socket_1_part_3, NULL);
+ else if (l2data == &le_client_close_socket_test_2)
+ g_idle_add(test_close_socket_2_part_3, NULL);
+}
+
+static void test_close_socket_conn_cancel(void)
+{
+ struct test_data *data = tester_get_data();
+ const struct l2cap_data *l2data = data->test_data;
+
+ if (l2data == &le_client_close_socket_test_2)
+ tester_test_passed();
+}
+
static void test_close_socket_router(uint16_t opcode, const void *param,
uint8_t length, void *user_data)
{
/* tester_print("HCI Command 0x%04x length %u", opcode, length); */
-
if (opcode == BT_HCI_CMD_LE_SET_SCAN_ENABLE) {
const struct bt_hci_cmd_le_set_scan_enable *scan_params = param;

if (scan_params->enable == true)
- g_idle_add(test_close_socket_1_part_2, NULL);
+ test_close_socket_scan_enabled();
else
- g_idle_add(test_close_socket_1_part_3, NULL);
+ test_close_socket_scan_disabled();
+ } else if (opcode == BT_HCI_CMD_LE_CREATE_CONN_CANCEL) {
+ test_close_socket_conn_cancel();
}
}

@@ -1592,6 +1686,11 @@ int main(int argc, char *argv[])
setup_powered_client,
test_close_socket);

+ test_l2cap_le("L2CAP LE Client - Close socket 2",
+ &le_client_close_socket_test_2,
+ setup_powered_client,
+ test_close_socket);
+
test_l2cap_le("L2CAP LE Client - Invalid PSM",
&le_client_connect_nval_psm_test,
setup_powered_client, test_connect);
--
2.5.0


2015-10-05 18:28:26

by Jakub Pawlowski

[permalink] [raw]
Subject: [PATCH v4 2/5] tools/l2cap-tester: add close socket test

This patch adds test that checks folowing:
1. Try to connect to non-existing remote BLE device using socket.
2. Internally in kernel this adds this device to whitelist and enable scan.
3. At this moment test would try to close socket.
4. That should cause scan to be stopped.
---
tools/l2cap-tester.c | 183 +++++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 169 insertions(+), 14 deletions(-)

diff --git a/tools/l2cap-tester.c b/tools/l2cap-tester.c
index 2b89045..0885209 100644
--- a/tools/l2cap-tester.c
+++ b/tools/l2cap-tester.c
@@ -53,6 +53,7 @@ struct test_data {
uint16_t handle;
uint16_t scid;
uint16_t dcid;
+ int sk;
};

struct l2cap_data {
@@ -85,6 +86,8 @@ struct l2cap_data {

bool addr_type_avail;
uint8_t addr_type;
+
+ uint8_t *client_bdaddr;
};

static void mgmt_debug(const char *str, void *user_data)
@@ -450,6 +453,12 @@ static const struct l2cap_data le_client_connect_reject_test_2 = {
.addr_type = BDADDR_LE_PUBLIC,
};

+static uint8_t nonexisting_bdaddr[] = {0x00, 0xAA, 0x01, 0x02, 0x03, 0x00};
+static const struct l2cap_data le_client_close_socket_test_1 = {
+ .client_psm = 0x0080,
+ .client_bdaddr = nonexisting_bdaddr,
+};
+
static const struct l2cap_data le_client_connect_nval_psm_test = {
.client_psm = 0x0080,
.expect_err = ECONNREFUSED,
@@ -1013,33 +1022,24 @@ static int create_l2cap_sock(struct test_data *data, uint16_t psm,
return sk;
}

-static int connect_l2cap_sock(struct test_data *data, int sk, uint16_t psm,
- uint16_t cid)
+static int connect_l2cap_impl(int sk, const uint8_t *bdaddr,
+ uint8_t bdaddr_type, uint16_t psm, uint16_t cid)
{
- const struct l2cap_data *l2data = data->test_data;
- const uint8_t *client_bdaddr;
struct sockaddr_l2 addr;
int err;

- client_bdaddr = hciemu_get_client_bdaddr(data->hciemu);
- if (!client_bdaddr) {
+ if (!bdaddr) {
tester_warn("No client bdaddr");
return -ENODEV;
}

memset(&addr, 0, sizeof(addr));
addr.l2_family = AF_BLUETOOTH;
- bacpy(&addr.l2_bdaddr, (void *) client_bdaddr);
+ bacpy(&addr.l2_bdaddr, (void *) bdaddr);
+ addr.l2_bdaddr_type = bdaddr_type;
addr.l2_psm = htobs(psm);
addr.l2_cid = htobs(cid);

- if (l2data && l2data->addr_type_avail)
- addr.l2_bdaddr_type = l2data->addr_type;
- else if (data->hciemu_type == HCIEMU_TYPE_LE)
- addr.l2_bdaddr_type = BDADDR_LE_PUBLIC;
- else
- addr.l2_bdaddr_type = BDADDR_BREDR;
-
err = connect(sk, (struct sockaddr *) &addr, sizeof(addr));
if (err < 0 && !(errno == EAGAIN || errno == EINPROGRESS)) {
err = -errno;
@@ -1051,6 +1051,33 @@ static int connect_l2cap_sock(struct test_data *data, int sk, uint16_t psm,
return 0;
}

+static int connect_l2cap_sock(struct test_data *data, int sk, uint16_t psm,
+ uint16_t cid)
+{
+ const struct l2cap_data *l2data = data->test_data;
+ const uint8_t *client_bdaddr;
+ uint8_t bdaddr_type;
+
+ if (l2data->client_bdaddr != NULL)
+ client_bdaddr = l2data->client_bdaddr;
+ else
+ client_bdaddr = hciemu_get_client_bdaddr(data->hciemu);
+
+ if (!client_bdaddr) {
+ tester_warn("No client bdaddr");
+ return -ENODEV;
+ }
+
+ if (l2data && l2data->addr_type_avail)
+ bdaddr_type = l2data->addr_type;
+ else if (data->hciemu_type == HCIEMU_TYPE_LE)
+ bdaddr_type = BDADDR_LE_PUBLIC;
+ else
+ bdaddr_type = BDADDR_BREDR;
+
+ return connect_l2cap_impl(sk, client_bdaddr, bdaddr_type, psm, cid);
+}
+
static void client_l2cap_connect_cb(uint16_t handle, uint16_t cid,
void *user_data)
{
@@ -1122,6 +1149,128 @@ static void test_connect_reject(const void *test_data)
close(sk);
}

+static void connect_socket(const uint8_t *client_bdaddr, int *sk_holder,
+ GIOFunc connect_cb)
+{
+ struct test_data *data = tester_get_data();
+ const struct l2cap_data *l2data = data->test_data;
+ GIOChannel *io;
+ int sk;
+
+ sk = create_l2cap_sock(data, 0, l2data->cid, l2data->sec_level);
+ if (sk < 0) {
+ tester_print("Error in create_l2cap_sock");
+ tester_test_failed();
+ return;
+ }
+
+ *sk_holder = sk;
+
+ if (connect_l2cap_impl(sk, client_bdaddr, BDADDR_LE_PUBLIC,
+ l2data->client_psm, l2data->cid) < 0) {
+ tester_print("Error in connect_l2cap_sock");
+ close(sk);
+ tester_test_failed();
+ return;
+ }
+
+ if (connect_cb) {
+ io = g_io_channel_unix_new(sk);
+ g_io_channel_set_close_on_unref(io, TRUE);
+
+ data->io_id = g_io_add_watch(io, G_IO_OUT, connect_cb, NULL);
+
+ g_io_channel_unref(io);
+ }
+
+ tester_print("Connect in progress, sk = %d", sk);
+}
+
+static gboolean test_close_socket_1_part_3(gpointer arg)
+{
+ struct test_data *data = tester_get_data();
+
+ tester_print("Checking whether scan was properly stopped...");
+
+ if (data->sk != -1) {
+ tester_print("Error - scan was not enabled yet");
+ tester_test_failed();
+ return FALSE;
+ }
+
+ if (hciemu_is_master_le_scan_enabled(data->hciemu)) {
+ tester_print("Delayed check whether scann is off failed");
+ tester_test_failed();
+ return FALSE;
+ }
+
+ tester_test_passed();
+ return FALSE;
+}
+
+static gboolean test_close_socket_1_part_2(gpointer args)
+{
+ struct test_data *data = tester_get_data();
+ int sk = data->sk;
+
+ tester_print("Will close socket during scan phase...");
+
+ /* We tried to conect to LE device that is not advertising. It was added
+ * to kernel whitelist, and scan was started. We should be still
+ * scanning.
+ */
+ if (!hciemu_is_master_le_scan_enabled(data->hciemu)) {
+ tester_print("Error - should be still scanning");
+ tester_test_failed();
+ return FALSE;
+ }
+
+ /* Calling close() should remove device from whitelist, and stop
+ * the scan.
+ */
+ if (close(sk) < 0) {
+ tester_print("Error when closing socket");
+ tester_test_failed();
+ return FALSE;
+ }
+
+ data->sk = -1;
+ /* tester_test_passed will be called when scan is stopped. */
+ return FALSE;
+}
+
+static void test_close_socket_router(uint16_t opcode, const void *param,
+ uint8_t length, void *user_data)
+{
+ /* tester_print("HCI Command 0x%04x length %u", opcode, length); */
+
+ if (opcode == BT_HCI_CMD_LE_SET_SCAN_ENABLE) {
+ const struct bt_hci_cmd_le_set_scan_enable *scan_params = param;
+
+ if (scan_params->enable == true)
+ g_idle_add(test_close_socket_1_part_2, NULL);
+ else
+ g_idle_add(test_close_socket_1_part_3, NULL);
+ }
+}
+
+static void test_close_socket(const void *test_data)
+{
+ struct test_data *data = tester_get_data();
+ const struct l2cap_data *l2data = data->test_data;
+ const uint8_t *client_bdaddr;
+
+ hciemu_add_master_post_command_hook(data->hciemu,
+ test_close_socket_router, data);
+
+ if (l2data->client_bdaddr != NULL)
+ client_bdaddr = l2data->client_bdaddr;
+ else
+ client_bdaddr = hciemu_get_client_bdaddr(data->hciemu);
+
+ connect_socket(client_bdaddr, &data->sk, NULL);
+}
+
static gboolean l2cap_listen_cb(GIOChannel *io, GIOCondition cond,
gpointer user_data)
{
@@ -1437,6 +1586,12 @@ int main(int argc, char *argv[])
test_l2cap_bredr("L2CAP LE Client - Connection Reject",
&le_client_connect_reject_test_2,
setup_powered_client, test_connect_reject);
+
+ test_l2cap_le("L2CAP LE Client - Close socket 1",
+ &le_client_close_socket_test_1,
+ setup_powered_client,
+ test_close_socket);
+
test_l2cap_le("L2CAP LE Client - Invalid PSM",
&le_client_connect_nval_psm_test,
setup_powered_client, test_connect);
--
2.5.0


2015-11-11 06:24:19

by Jakub Pawlowski

[permalink] [raw]
Subject: Re: [PATCH v4 1/5] emulator: add support for checking le scan state

Gentle ping ?
I'll rebase and re-upload those test

On Mon, Oct 5, 2015 at 11:28 AM, Jakub Pawlowski <[email protected]> wrote:
> ---
> emulator/btdev.c | 5 +++++
> emulator/btdev.h | 2 ++
> emulator/hciemu.c | 8 ++++++++
> emulator/hciemu.h | 2 ++
> 4 files changed, 17 insertions(+)
>
> diff --git a/emulator/btdev.c b/emulator/btdev.c
> index e8cead8..aee7a48 100644
> --- a/emulator/btdev.c
> +++ b/emulator/btdev.c
> @@ -675,6 +675,11 @@ uint8_t *btdev_get_features(struct btdev *btdev)
> return btdev->features;
> }
>
> +bool btdev_is_le_scan_enabled(struct btdev *btdev)
> +{
> + return btdev->le_scan_enable;
> +}
> +
> static bool use_ssp(struct btdev *btdev1, struct btdev *btdev2)
> {
> if (btdev1->auth_enable || btdev2->auth_enable)
> diff --git a/emulator/btdev.h b/emulator/btdev.h
> index 4b724a7..8b116e4 100644
> --- a/emulator/btdev.h
> +++ b/emulator/btdev.h
> @@ -80,6 +80,8 @@ void btdev_destroy(struct btdev *btdev);
> const uint8_t *btdev_get_bdaddr(struct btdev *btdev);
> uint8_t *btdev_get_features(struct btdev *btdev);
>
> +bool btdev_is_le_scan_enabled(struct btdev *btdev);
> +
> void btdev_set_command_handler(struct btdev *btdev, btdev_command_func handler,
> void *user_data);
>
> diff --git a/emulator/hciemu.c b/emulator/hciemu.c
> index 4881a24..725fbd4 100644
> --- a/emulator/hciemu.c
> +++ b/emulator/hciemu.c
> @@ -427,6 +427,14 @@ const uint8_t *hciemu_get_client_bdaddr(struct hciemu *hciemu)
> return btdev_get_bdaddr(hciemu->client_dev);
> }
>
> +bool hciemu_is_master_le_scan_enabled(struct hciemu *hciemu)
> +{
> + if (!hciemu || !hciemu->master_dev)
> + return NULL;
> +
> + return btdev_is_le_scan_enabled(hciemu->master_dev);
> +}
> +
> bool hciemu_add_master_post_command_hook(struct hciemu *hciemu,
> hciemu_command_func_t function, void *user_data)
> {
> diff --git a/emulator/hciemu.h b/emulator/hciemu.h
> index 41ca3fc..04bfab7 100644
> --- a/emulator/hciemu.h
> +++ b/emulator/hciemu.h
> @@ -53,6 +53,8 @@ uint8_t *hciemu_get_features(struct hciemu *hciemu);
> const uint8_t *hciemu_get_master_bdaddr(struct hciemu *hciemu);
> const uint8_t *hciemu_get_client_bdaddr(struct hciemu *hciemu);
>
> +bool hciemu_is_master_le_scan_enabled(struct hciemu *hciemu);
> +
> typedef void (*hciemu_command_func_t)(uint16_t opcode, const void *data,
> uint8_t len, void *user_data);
>
> --
> 2.5.0
>