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_connect(const void *test_data) { struct test_data *data = tester_get_data(); const struct l2cap_data *l2data = data->test_data; GIOChannel *io; int sk; 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); else bthost_add_l2cap_server(bthost, l2data->server_psm, client_l2cap_connect_cb, data); } if (l2data->direct_advertising) hciemu_add_master_post_command_hook(data->hciemu, direct_adv_cmd_complete, NULL); 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) { close(sk); tester_test_failed(); return; } 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, l2cap_connect_cb, NULL); g_io_channel_unref(io); tester_print("Connect in progress"); }
static void test_le_generate_dhkey_status(const void *data, uint8_t size, void *user_data) { uint8_t status = *((uint8_t *) data); if (status) { tester_warn("Failed to send DHKey gen cmd (0x%02x)", status); tester_test_failed(); return; } }
static void test_le_read_local_pk_status(const void *data, uint8_t size, void *user_data) { uint8_t status = *((uint8_t *) data); if (status) { tester_warn("Failed to send Read Local PK256 cmd (0x%02x)", status); tester_test_failed(); return; } }
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_command(uint16_t opcode) { struct user_data *user = tester_get_data(); if (!bt_hci_send(user->hci_ut, opcode, NULL, 0, test_command_complete, NULL, NULL)) { tester_warn("Failed to send HCI command 0x%04x", opcode); tester_test_failed(); return; } }
static void test_inquiry_status(const void *data, uint8_t size, void *user_data) { uint8_t status = *((uint8_t *) data); if (status) { tester_warn("HCI inquiry command failed (0x%02x)", status); tester_test_failed(); return; } }
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(); }
static void test_create_connection_status(const void *data, uint8_t size, void *user_data) { uint8_t status = *((uint8_t *) data); if (status) { tester_warn("HCI create connection command failed (0x%02x)", status); tester_test_failed(); return; } }
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_get_master_le_scan_enable(data->hciemu)) { tester_print("Delayed check whether scann is off failed"); tester_test_failed(); return FALSE; } 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_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 void test_server(const void *test_data) { struct test_data *data = tester_get_data(); const struct rfcomm_server_data *server_data = data->test_data; const uint8_t *master_addr; struct bthost *bthost; GIOChannel *io; int sk; master_addr = hciemu_get_master_bdaddr(data->hciemu); sk = create_rfcomm_sock((bdaddr_t *) master_addr, server_data->server_channel); if (sk < 0) { tester_test_failed(); return; } if (listen(sk, 5) < 0) { tester_warn("listening on socket failed: %s (%u)", strerror(errno), errno); tester_test_failed(); close(sk); return; } 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_IN, rfcomm_listen_cb, NULL); g_io_channel_unref(io); tester_print("Listening for connections"); bthost = hciemu_client_get_host(data->hciemu); bthost_set_connect_cb(bthost, client_new_conn, data); bthost_hci_connect(bthost, master_addr, BDADDR_BREDR); }
static gboolean server_received_data(GIOChannel *io, GIOCondition cond, gpointer user_data) { struct test_data *data = tester_get_data(); const struct l2cap_data *l2data = data->test_data; char buf[1024]; int sk; sk = g_io_channel_unix_get_fd(io); if (read(sk, buf, l2data->data_len) != l2data->data_len) { tester_warn("Unable to read %u bytes", l2data->data_len); tester_test_failed(); return FALSE; } if (memcmp(buf, l2data->read_data, l2data->data_len)) tester_test_failed(); else tester_test_passed(); return FALSE; }
static void test_connect_transp(const void *test_data) { struct test_data *data = tester_get_data(); const struct sco_client_data *scodata = data->test_data; int sk, err; struct bt_voice voice; sk = create_sco_sock(data); if (sk < 0) { tester_test_failed(); return; } memset(&voice, 0, sizeof(voice)); voice.setting = BT_VOICE_TRANSPARENT; err = setsockopt(sk, SOL_BLUETOOTH, BT_VOICE, &voice, sizeof(voice)); if (err < 0) { tester_warn("Can't set socket option : %s (%d)", strerror(errno), errno); tester_test_failed(); goto end; } err = connect_sco_sock(data, sk); tester_warn("Connect returned %s (%d), expected %s (%d)", strerror(-err), -err, strerror(scodata->expect_err), scodata->expect_err); if (-err != scodata->expect_err) tester_test_failed(); else tester_test_passed(); end: close(sk); }
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_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 client_received_data(GIOChannel *io, GIOCondition cond, gpointer user_data) { struct test_data *data = tester_get_data(); const struct rfcomm_client_data *client_data = data->test_data; int sk; ssize_t ret; char buf[248]; sk = g_io_channel_unix_get_fd(io); ret = read(sk, buf, client_data->data_len); if (client_data->data_len != ret) { tester_test_failed(); return false; } if (memcmp(client_data->read_data, buf, client_data->data_len)) tester_test_failed(); else tester_test_passed(); return false; }
static void bthost_send_rsp(const void *buf, uint16_t len, void *user_data) { struct test_data *data = tester_get_data(); const struct l2cap_data *l2data = data->test_data; struct bthost *bthost; if (l2data->expect_cmd_len && len != l2data->expect_cmd_len) { tester_test_failed(); return; } if (l2data->expect_cmd && memcmp(buf, l2data->expect_cmd, l2data->expect_cmd_len)) { tester_test_failed(); return; } if (!l2data->send_cmd) return; bthost = hciemu_client_get_host(data->hciemu); bthost_send_cid(bthost, data->handle, data->dcid, l2data->send_cmd, l2data->send_cmd_len); }
static gboolean server_received_data(GIOChannel *io, GIOCondition cond, gpointer user_data) { struct test_data *data = tester_get_data(); const struct rfcomm_server_data *server_data = data->test_data; char buf[1024]; ssize_t ret; int sk; sk = g_io_channel_unix_get_fd(io); ret = read(sk, buf, server_data->data_len); if (ret != server_data->data_len) { tester_test_failed(); return false; } if (memcmp(buf, server_data->read_data, server_data->data_len)) tester_test_failed(); else tester_test_passed(); 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_get_master_le_scan_enable(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 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 void test_le_encrypt_complete(const void *data, uint8_t size, void *user_data) { const struct bt_hci_rsp_le_encrypt *rsp = data; uint8_t sample[16] = { 0x7d, 0xf7, 0x6b, 0x0c, 0x1a, 0xb8, 0x99, 0xb3, 0x3e, 0x42, 0xf0, 0x47, 0xb9, 0x1b, 0x54, 0x6f }; uint8_t enc_data[16]; if (rsp->status) { tester_warn("Failed HCI LE Encrypt (0x%02x)", rsp->status); tester_test_failed(); return; } swap_buf(rsp->data, enc_data, 16); util_hexdump('>', enc_data, 16, test_debug, NULL); if (!memcmp(sample, enc_data, 16)) tester_test_passed(); else tester_test_failed(); }
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; } len = sizeof(voice); memset(&voice, 0, len); 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(const void *test_data) { struct user_data *user = tester_get_data(); bt_hci_register(user->hci_ut, BT_HCI_EVT_LE_META_EVENT, test_le_read_local_pk_complete, (void *)test_data, NULL); if (!bt_hci_send(user->hci_ut, BT_HCI_CMD_LE_READ_LOCAL_PK256, NULL, 0, test_le_read_local_pk_status, NULL, NULL)) { tester_warn("Failed to send HCI LE Read Local PK256 command"); tester_test_failed(); return; } }
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 void test_read_local_extended_features(const void *test_data) { struct user_data *user = tester_get_data(); struct bt_hci_cmd_read_local_ext_features cmd; cmd.page = 0x00; if (!bt_hci_send(user->hci_ut, BT_HCI_CMD_READ_LOCAL_EXT_FEATURES, &cmd, sizeof(cmd), test_local_extended_features_complete, NULL, NULL)) { tester_warn("Failed to send HCI extended features command"); tester_test_failed(); return; } }
static void teardown_connection(const void *test_data) { struct user_data *user = tester_get_data(); struct bt_hci_cmd_disconnect cmd; cmd.handle = cpu_to_le16(user->handle_ut); cmd.reason = 0x13; if (!bt_hci_send(user->hci_ut, BT_HCI_CMD_DISCONNECT, &cmd, sizeof(cmd), teardown_disconnect_status, NULL, NULL)) { tester_warn("Failed to send HCI disconnect command"); tester_test_failed(); return; } }