static void client_l2cap_rsp(uint8_t code, const void *data, uint16_t len, void *user_data) { struct test_data *test_data = user_data; const struct l2cap_data *l2data = test_data->test_data; tester_print("Client received response code 0x%02x", code); if (code != l2data->expect_cmd_code) { tester_warn("Unexpected L2CAP response code (expected 0x%02x)", l2data->expect_cmd_code); goto failed; } if (code == BT_L2CAP_PDU_CONN_RSP) { const struct bt_l2cap_pdu_conn_rsp *rsp = data; if (len == sizeof(rsp) && !rsp->result && !rsp->status) return; test_data->dcid = rsp->dcid; test_data->scid = rsp->scid; if (l2data->data_len) return; } if (!l2data->expect_cmd) { tester_test_passed(); return; } if (l2data->expect_cmd_len != len) { tester_warn("Unexpected L2CAP response length (%u != %u)", len, l2data->expect_cmd_len); goto failed; } if (memcmp(l2data->expect_cmd, data, len) != 0) { tester_warn("Unexpected L2CAP response"); goto failed; } tester_test_passed(); return; failed: tester_test_failed(); }
static gboolean rc_connect_cb(GIOChannel *io, GIOCondition cond, gpointer user_data) { struct test_data *data = tester_get_data(); const struct rfcomm_client_data *client_data = data->test_data; socklen_t len = sizeof(int); int sk, err, 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 (client_data->expected_connect_err && err == client_data->expected_connect_err) { tester_test_passed(); return false; } if (client_data->send_data) { ssize_t ret; ret = write(sk, client_data->send_data, client_data->data_len); if (client_data->data_len != ret) tester_test_failed(); return false; } else if (client_data->read_data) { g_io_add_watch(io, G_IO_IN, client_received_data, NULL); bthost_send_rfcomm_data(hciemu_client_get_host(data->hciemu), data->conn_handle, client_data->client_channel, client_data->read_data, client_data->data_len); return false; } if (err < 0) tester_test_failed(); else tester_test_passed(); return false; }
static gboolean l2cap_listen_cb(GIOChannel *io, GIOCondition cond, gpointer user_data) { struct test_data *data = tester_get_data(); int sk, new_sk; data->io_id = 0; sk = g_io_channel_unix_get_fd(io); new_sk = accept(sk, NULL, NULL); if (new_sk < 0) { tester_warn("accept failed: %s (%u)", strerror(errno), errno); tester_test_failed(); return FALSE; } tester_print("Successfully connected"); close(new_sk); tester_test_passed(); return FALSE; }
static gboolean l2cap_listen_cb(GIOChannel *io, GIOCondition cond, gpointer user_data) { struct test_data *data = tester_get_data(); const struct l2cap_data *l2data = data->test_data; int sk, new_sk; data->io_id = 0; sk = g_io_channel_unix_get_fd(io); new_sk = accept(sk, NULL, NULL); if (new_sk < 0) { tester_warn("accept failed: %s (%u)", strerror(errno), errno); tester_test_failed(); return FALSE; } if (l2data->read_data) { struct bthost *bthost; GIOChannel *new_io; new_io = g_io_channel_unix_new(new_sk); g_io_channel_set_close_on_unref(new_io, TRUE); bthost = hciemu_client_get_host(data->hciemu); g_io_add_watch(new_io, G_IO_IN, server_received_data, NULL); bthost_send_cid(bthost, data->handle, data->dcid, l2data->read_data, l2data->data_len); g_io_channel_unref(new_io); return FALSE; } else if (l2data->write_data) { struct bthost *bthost; ssize_t ret; bthost = hciemu_client_get_host(data->hciemu); bthost_add_cid_hook(bthost, data->handle, data->scid, server_bthost_received_data, NULL); ret = write(new_sk, l2data->write_data, l2data->data_len); close(new_sk); if (ret != l2data->data_len) { tester_warn("Unable to write all data"); tester_test_failed(); } return FALSE; } tester_print("Successfully connected"); close(new_sk); tester_test_passed(); return FALSE; }
static void direct_adv_cmd_complete(uint16_t opcode, const void *param, uint8_t len, void *user_data) { struct test_data *data = tester_get_data(); const struct bt_hci_cmd_le_set_adv_parameters *cp; const uint8_t *expect_bdaddr; if (opcode != BT_HCI_CMD_LE_SET_ADV_PARAMETERS) return; tester_print("Received advertising parameters HCI command"); cp = param; /* Advertising as client should be direct advertising */ if (cp->type != 0x01) { tester_warn("Invalid advertising type"); tester_test_failed(); return; } expect_bdaddr = hciemu_get_client_bdaddr(data->hciemu); if (memcmp(expect_bdaddr, cp->direct_addr, 6)) { tester_warn("Invalid direct address in adv params"); tester_test_failed(); return; } tester_test_passed(); }
static void test_overwrite(const void *data) { char key[18], value[512], *str; util_create_empty(); sprintf(key, "00:00:00:00:00:00"); memset(value, 0, sizeof(value)); g_assert(textfile_put(test_pathname, key, value) == 0); snprintf(value, sizeof(value), "Test"); g_assert(textfile_put(test_pathname, key, value) == 0); g_assert(textfile_put(test_pathname, key, value) == 0); g_assert(textfile_put(test_pathname, key, value) == 0); g_assert(textfile_del(test_pathname, key) == 0); str = textfile_get(test_pathname, key); tester_debug("%s\n", str); g_assert(str == NULL); tester_test_passed(); }
static void index_removed_callback(uint16_t index, uint16_t length, const void *param, void *user_data) { struct test_data *data = tester_get_data(); tester_print("Index Removed callback"); tester_print(" Index: 0x%04x", index); if (index != data->mgmt_index) return; if (data->remove_id) { mgmt_unregister(data->mgmt, data->remove_id); data->remove_id = 0; tester_test_passed(); return; } mgmt_unregister_index(data->mgmt, data->mgmt_index); mgmt_unref(data->mgmt); data->mgmt = NULL; tester_post_teardown_complete(); }
static gboolean sco_connect_cb(GIOChannel *io, GIOCondition cond, gpointer user_data) { struct test_data *data = tester_get_data(); const struct sco_client_data *scodata = data->test_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); else tester_print("Successfully connected"); if (-err != scodata->expect_err) tester_test_failed(); else tester_test_passed(); return FALSE; }
static void test_getsockopt(const void *test_data) { int sk, err; socklen_t len; struct bt_voice voice; sk = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_SCO); if (sk < 0) { tester_warn("Can't create socket: %s (%d)", strerror(errno), errno); tester_test_failed(); return; } voice.setting = 0; len = sizeof(voice); err = getsockopt(sk, SOL_BLUETOOTH, BT_VOICE, &voice, &len); if (err < 0) { tester_warn("Can't get socket option : %s (%d)", strerror(errno), errno); tester_test_failed(); goto end; } if (voice.setting != BT_VOICE_CVSD_16BIT) { tester_warn("Invalid voice setting"); tester_test_failed(); goto end; } tester_test_passed(); end: close(sk); }
static void test_le_read_local_pk_complete(const void *data, uint8_t size, void *user_data) { const uint8_t *event = data; const struct bt_hci_evt_le_read_local_pk256_complete *evt; struct le_keys *keys = user_data; if (*event != BT_HCI_EVT_LE_READ_LOCAL_PK256_COMPLETE) { tester_warn("Failed Read Local PK256 command"); tester_test_failed(); return; } evt = (void *)(event + 1); if (evt->status) { tester_warn("HCI Read Local PK complete failed (0x%02x)", evt->status); tester_test_failed(); return; } memcpy(keys->local_pk, evt->local_pk256, 64); util_hexdump('>', evt->local_pk256, 64, test_debug, NULL); tester_test_passed(); }
static void test_getpeername_not_connected(const void *test_data) { struct test_data *data = tester_get_data(); struct sockaddr_l2 addr; socklen_t len; int sk; sk = create_l2cap_sock(data, 0, 0, 0); if (sk < 0) { tester_test_failed(); return; } len = sizeof(addr); if (getpeername(sk, (struct sockaddr *) &addr, &len) == 0) { tester_warn("getpeername succeeded on non-connected socket"); tester_test_failed(); goto done; } if (errno != ENOTCONN) { tester_warn("Unexpexted getpeername error: %s (%d)", strerror(errno), errno); tester_test_failed(); goto done; } tester_test_passed(); done: close(sk); }
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 gboolean l2cap_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); 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); else tester_print("Successfully connected"); if (l2data->read_data) { struct bthost *bthost; bthost = hciemu_client_get_host(data->hciemu); g_io_add_watch(io, G_IO_IN, client_received_data, NULL); bthost_send_cid(bthost, data->handle, data->dcid, l2data->read_data, l2data->data_len); return FALSE; } else if (l2data->write_data) { struct bthost *bthost; ssize_t ret; bthost = hciemu_client_get_host(data->hciemu); bthost_add_cid_hook(bthost, data->handle, data->dcid, bthost_received_data, NULL); ret = write(sk, l2data->write_data, l2data->data_len); if (ret != l2data->data_len) { tester_warn("Unable to write all data"); tester_test_failed(); } return FALSE; } if (-err != l2data->expect_err) tester_test_failed(); else tester_test_passed(); return FALSE; }
static void pair_device_complete(uint8_t status, uint16_t length, const void *param, void *user_data) { if (status != MGMT_STATUS_SUCCESS) { tester_warn("Pairing failed: %s", mgmt_errstr(status)); tester_test_failed(); return; } tester_print("Pairing succeedded"); tester_test_passed(); }
static void test_condition_complete(struct test_data *data) { data->unmet_conditions--; tester_print("Test condition complete, %d left", data->unmet_conditions); if (data->unmet_conditions > 0) return; tester_test_passed(); }
static void test_command_complete(const void *data, uint8_t size, void *user_data) { uint8_t status = *((uint8_t *) data); if (status) { tester_warn("HCI command failed (0x%02x)", status); tester_test_failed(); return; } tester_test_passed(); }
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); 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(); } if (l2data->close_one_socket && test_two_sockets_connect_cb_cnt == 1) { close(data->sk2); tester_test_passed(); } return FALSE; }
static void test_local_extended_features_complete(const void *data, uint8_t size, void *user_data) { const struct bt_hci_rsp_read_local_ext_features *rsp = data; if (rsp->status) { tester_warn("Failed to get HCI extended features (0x%02x)", rsp->status); tester_test_failed(); return; } tester_test_passed(); }
static void test_inquiry_complete(const void *data, uint8_t size, void *user_data) { const struct bt_hci_evt_inquiry_complete *evt = data; if (evt->status) { tester_warn("HCI inquiry complete failed (0x%02x)", evt->status); tester_test_failed(); return; } tester_test_passed(); }
static void test_open_failed(const void *test_data) { struct test_data *data = tester_get_data(); struct bt_hci *hci; hci = bt_hci_new_user_channel(data->mgmt_index); if (!hci) { tester_test_passed(); return; } bt_hci_unref(hci); tester_test_failed(); }
static void client_l2cap_rsp(uint8_t code, const void *data, uint16_t len, void *user_data) { struct test_data *test_data = user_data; const struct l2cap_server_data *l2data = test_data->test_data; tester_print("Client received response code 0x%02x", code); if (code != l2data->expect_rsp_code) { tester_warn("Unexpected L2CAP response code (expected 0x%02x)", l2data->expect_rsp_code); goto failed; } if (!l2data->expect_rsp) { tester_test_passed(); return; } if (l2data->expect_rsp_len != len) { tester_warn("Unexpected L2CAP response length (%u != %u)", len, l2data->expect_rsp_len); goto failed; } if (memcmp(l2data->expect_rsp, data, len) != 0) { tester_warn("Unexpected L2CAP response"); goto failed; } tester_test_passed(); return; failed: tester_test_failed(); }
static void server_bthost_received_data(const void *buf, uint16_t len, void *user_data) { struct test_data *data = tester_get_data(); const struct l2cap_data *l2data = data->test_data; if (len != l2data->data_len) { tester_test_failed(); return; } if (memcmp(buf, l2data->write_data, l2data->data_len)) tester_test_failed(); else tester_test_passed(); }
static void test_basic(const void *test_data) { int sk; sk = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP); if (sk < 0) { tester_warn("Can't create socket: %s (%d)", strerror(errno), errno); tester_test_failed(); return; } close(sk); tester_test_passed(); }
static gboolean rfcomm_listen_cb(GIOChannel *io, GIOCondition cond, gpointer user_data) { struct test_data *data = tester_get_data(); const struct rfcomm_server_data *server_data = data->test_data; int sk, new_sk; data->io_id = 0; sk = g_io_channel_unix_get_fd(io); new_sk = accept(sk, NULL, NULL); if (new_sk < 0) { tester_test_failed(); return false; } if (server_data->send_data) { ssize_t ret; ret = write(new_sk, server_data->send_data, server_data->data_len); if (ret != server_data->data_len) tester_test_failed(); close(new_sk); return false; } else if (server_data->read_data) { GIOChannel *new_io; new_io = g_io_channel_unix_new(new_sk); g_io_channel_set_close_on_unref(new_io, TRUE); data->io_id = g_io_add_watch(new_io, G_IO_IN, server_received_data, NULL); g_io_channel_unref(new_io); return false; } close(new_sk); tester_test_passed(); return false; }
static void server_hook_func(const void *data, uint16_t len, void *user_data) { struct test_data *test_data = tester_get_data(); const struct rfcomm_server_data *server_data = test_data->test_data; ssize_t ret; if (server_data->data_len != len) { tester_test_failed(); return; } ret = memcmp(server_data->send_data, data, len); if (ret) tester_test_failed(); else tester_test_passed(); }
static void test_reset_in_advertising_state_timeout(void *user_data) { struct user_data *user = tester_get_data(); struct bt_hci_cmd_le_set_adv_enable lsae; struct bt_hci_cmd_le_set_scan_enable lsse; lsae.enable = 0x00; bt_hci_send(user->hci_ut, BT_HCI_CMD_LE_SET_ADV_ENABLE, &lsae, sizeof(lsae), NULL, NULL, NULL); lsse.enable = 0x00; lsse.filter_dup = 0x00; bt_hci_send(user->hci_lt, BT_HCI_CMD_LE_SET_SCAN_ENABLE, &lsse, sizeof(lsse), NULL, NULL, NULL); tester_test_passed(); }
static gboolean context_quit(gpointer user_data) { struct context *context = user_data; if (context->process > 0) g_source_remove(context->process); if (context->source > 0) g_source_remove(context->source); bt_hog_unref(context->hog); g_attrib_unref(context->attrib); g_free(context); tester_test_passed(); return FALSE; }
static void test_pagesize(const void *data) { char key[18], *str; int size; size = getpagesize(); g_assert(size >= 4096); tester_debug("System uses a page size of %d bytes\n", size); util_create_pagesize(); sprintf(key, "11:11:11:11:11:11"); str = textfile_get(test_pathname, key); tester_debug("%s\n", str); g_assert(str == NULL); tester_test_passed(); }
static void test_connect_reject(const void *test_data) { struct test_data *data = tester_get_data(); const struct l2cap_data *l2data = data->test_data; int sk; sk = create_l2cap_sock(data, 0, l2data->cid, l2data->sec_level); if (sk < 0) { tester_test_failed(); return; } if (connect_l2cap_sock(data, sk, l2data->client_psm, l2data->cid) < 0) tester_test_passed(); else tester_test_failed(); close(sk); }
static void test_le_generate_dhkey_complete(const void *data, uint8_t size, void *user_data) { const uint8_t *event = data; const struct bt_hci_evt_le_generate_dhkey_complete *evt; struct le_keys *keys = user_data; uint8_t dhkey[32]; if (*event != BT_HCI_EVT_LE_GENERATE_DHKEY_COMPLETE) { tester_warn("Failed DHKey generation command"); tester_test_failed(); return; } evt = (void *)(event + 1); if (evt->status) { tester_warn("HCI Generate DHKey complete failed (0x%02x)", evt->status); tester_test_failed(); return; } util_hexdump('>', evt->dhkey, 32, test_debug, NULL); util_hexdump('S', keys->remote_sk, 32, test_debug, NULL); util_hexdump('P', keys->local_pk, 64, test_debug, NULL); /* Generate DHKey ourself with local public key and remote * private key we got when generated public / private key * pair for BT_HCI_CMD_LE_GENERATE_DHKEY argument. */ ecdh_shared_secret(keys->local_pk, keys->remote_sk, dhkey); util_hexdump('D', dhkey, 32, test_debug, NULL); if (!memcmp(dhkey, evt->dhkey, 32)) tester_test_passed(); else tester_test_failed(); }