static int connect_sco_sock(struct test_data *data, int sk) { const uint8_t *client_bdaddr; struct sockaddr_sco addr; int err; client_bdaddr = hciemu_get_client_bdaddr(data->hciemu); if (!client_bdaddr) { tester_warn("No client bdaddr"); return -ENODEV; } memset(&addr, 0, sizeof(addr)); addr.sco_family = AF_BLUETOOTH; bacpy(&addr.sco_bdaddr, (void *) client_bdaddr); err = connect(sk, (struct sockaddr *) &addr, sizeof(addr)); if (err < 0 && !(errno == EAGAIN || errno == EINPROGRESS)) { err = -errno; tester_warn("Can't connect socket: %s (%d)", strerror(errno), errno); return err; } return 0; }
static void init_bdaddr(struct test_data *data) { const uint8_t *master_bdaddr, *client_bdaddr; master_bdaddr = hciemu_get_master_bdaddr(data->hciemu); if (!master_bdaddr) { tester_warn("No master bdaddr"); tester_test_failed(); return; } client_bdaddr = hciemu_get_client_bdaddr(data->hciemu); if (!client_bdaddr) { tester_warn("No client bdaddr"); tester_test_failed(); return; } data->ia_type = LE_PUBLIC_ADDRESS; data->ra_type = LE_PUBLIC_ADDRESS; if (data->out) { memcpy(data->ia, client_bdaddr, sizeof(data->ia)); memcpy(data->ra, master_bdaddr, sizeof(data->ra)); } else { memcpy(data->ia, master_bdaddr, sizeof(data->ia)); memcpy(data->ra, client_bdaddr, sizeof(data->ra)); } }
static int connect_l2cap_sock(struct test_data *data, int sk, uint16_t psm, uint16_t cid) { const uint8_t *client_bdaddr; struct sockaddr_l2 addr; int err; client_bdaddr = hciemu_get_client_bdaddr(data->hciemu); if (!client_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); addr.l2_psm = htobs(psm); addr.l2_cid = htobs(cid); 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; tester_warn("Can't connect socket: %s (%d)", strerror(errno), errno); return err; } return 0; }
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_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; test_scan_enable_counter = 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); 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 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 test_connect(const void *test_data) { struct test_data *data = tester_get_data(); struct bthost *bthost = hciemu_client_get_host(data->hciemu); const struct rfcomm_client_data *client_data = data->test_data; const uint8_t *client_addr, *master_addr; GIOChannel *io; int sk; bthost_add_l2cap_server(bthost, 0x0003, NULL, NULL); bthost_add_rfcomm_server(bthost, client_data->server_channel, rfcomm_connect_cb, NULL); master_addr = hciemu_get_master_bdaddr(data->hciemu); client_addr = hciemu_get_client_bdaddr(data->hciemu); sk = create_rfcomm_sock((bdaddr_t *) master_addr, 0); if (connect_rfcomm_sock(sk, (const bdaddr_t *) client_addr, client_data->client_channel) < 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, rc_connect_cb, NULL); g_io_channel_unref(io); tester_print("Connect in progress %d", sk); }
static void avrcp_disconnect_action(void) { struct test_data *data = tester_get_data(); const uint8_t *addr = hciemu_get_client_bdaddr(data->hciemu); struct step *step = g_new0(struct step, 1); bt_bdaddr_t bdaddr; bdaddr2android((const bdaddr_t *) addr, &bdaddr); step->action_status = data->if_a2dp->disconnect(&bdaddr); schedule_action_verification(step); }
static void hidhost_set_report_action(void) { struct test_data *data = tester_get_data(); const uint8_t *hid_addr = hciemu_get_client_bdaddr(data->hciemu); struct step *step = g_new0(struct step, 1); char *buf = "fe0201"; bt_bdaddr_t bdaddr; bdaddr2android((const bdaddr_t *) hid_addr, &bdaddr); step->action_status = data->if_hid->send_data(&bdaddr, buf); schedule_action_verification(step); }
static void hidhost_virtual_unplug_action(void) { struct test_data *data = tester_get_data(); const uint8_t *hid_addr = hciemu_get_client_bdaddr(data->hciemu); struct step *step = g_new0(struct step, 1); bt_bdaddr_t bdaddr; bdaddr2android((const bdaddr_t *) hid_addr, &bdaddr); step->action_status = data->if_hid->virtual_unplug(&bdaddr); schedule_action_verification(step); }
static void hidhost_set_protocol_action(void) { struct test_data *data = tester_get_data(); const uint8_t *hid_addr = hciemu_get_client_bdaddr(data->hciemu); struct step *step = g_new0(struct step, 1); bt_bdaddr_t bdaddr; bdaddr2android((const bdaddr_t *) hid_addr, &bdaddr); step->action_status = data->if_hid->set_protocol(&bdaddr, BTHH_REPORT_MODE); schedule_action_verification(step); }
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 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); }