diff --git a/android/android-tester.c b/android/android-tester.c
index b05fde0..cc43ce4 100644
--- a/android/android-tester.c
+++ b/android/android-tester.c
bool test_channel;
};
+struct hidhost_generic_data {
+ bthh_status_t expected_status;
+ int expected_conn_state;
+ int expected_cb_count;
+ bthh_protocol_mode_t expected_protocol_mode;
+ int expected_report;
+ bthh_callbacks_t expected_hal_cb;
+ int expected_report_size;
+};
+
#define WAIT_FOR_SIGNAL_TIME 2 /* in seconds */
#define EMULATOR_SIGNAL "emulator_started"
int cb_count;
GSList *expected_properties_list;
+
+ /* hidhost */
+ uint16_t sdp_handle;
+ uint16_t sdp_cid;
+ uint16_t ctrl_handle;
+ uint16_t ctrl_cid;
+ uint16_t intr_handle;
+ uint16_t intr_cid;
};
static char exec_dir[PATH_MAX + 1];
.le_test_mode_cb = NULL
};
-static bthh_callbacks_t bthh_callbacks = {
- .size = sizeof(bthh_callbacks),
- .connection_state_cb = NULL,
- .hid_info_cb = NULL,
- .protocol_mode_cb = NULL,
- .idle_time_cb = NULL,
- .get_report_cb = NULL,
- .virtual_unplug_cb = NULL
-};
static void setup(struct test_data *data)
{
close(sock_fd);
}
-static void setup_hidhost_interface(const void *test_data)
+static void hidhost_connection_state_cb(bt_bdaddr_t *bd_addr,
+ bthh_connection_state_t state)
+{
+ struct test_data *data = tester_get_data();
+ const struct hidhost_generic_data *test = data->test_data;
+
+ data->cb_count++;
+
+ if (state == BTHH_CONN_STATE_CONNECTED)
+ tester_setup_complete();
+
+ if (test && test->expected_hal_cb.connection_state_cb)
+ test->expected_hal_cb.connection_state_cb(bd_addr, state);
+}
+
+static void hidhost_virual_unplug_cb(bt_bdaddr_t *bd_addr, bthh_status_t status)
+{
+ struct test_data *data = tester_get_data();
+ const struct hidhost_generic_data *test = data->test_data;
+
+ data->cb_count++;
+
+ if (test && test->expected_hal_cb.virtual_unplug_cb)
+ test->expected_hal_cb.virtual_unplug_cb(bd_addr, status);
+}
+
+static void hidhost_hid_info_cb(bt_bdaddr_t *bd_addr, bthh_hid_info_t hid)
+{
+ struct test_data *data = tester_get_data();
+ const struct hidhost_generic_data *test = data->test_data;
+
+ data->cb_count++;
+
+ if (test && test->expected_hal_cb.hid_info_cb)
+ test->expected_hal_cb.hid_info_cb(bd_addr, hid);
+}
+
+static void hidhost_protocol_mode_cb(bt_bdaddr_t *bd_addr,
+ bthh_status_t status,
+ bthh_protocol_mode_t mode)
+{
+ struct test_data *data = tester_get_data();
+ const struct hidhost_generic_data *test = data->test_data;
+
+ data->cb_count++;
+
+ if (test && test->expected_hal_cb.protocol_mode_cb)
+ test->expected_hal_cb.protocol_mode_cb(bd_addr, status, mode);
+}
+
+static void hidhost_get_report_cb(bt_bdaddr_t *bd_addr, bthh_status_t status,
+ uint8_t *report, int size)
+{
+ struct test_data *data = tester_get_data();
+ const struct hidhost_generic_data *test = data->test_data;
+
+ data->cb_count++;
+
+ if (test && test->expected_hal_cb.get_report_cb)
+ test->expected_hal_cb.get_report_cb(bd_addr, status, report,
+ size);
+}
+
+static bthh_callbacks_t bthh_callbacks = {
+ .size = sizeof(bthh_callbacks),
+ .connection_state_cb = hidhost_connection_state_cb,
+ .hid_info_cb = hidhost_hid_info_cb,
+ .protocol_mode_cb = hidhost_protocol_mode_cb,
+ .idle_time_cb = NULL,
+ .get_report_cb = hidhost_get_report_cb,
+ .virtual_unplug_cb = hidhost_virual_unplug_cb
+};
+
+static void setup_hidhost(const void *test_data)
{
struct test_data *data = tester_get_data();
bt_status_t status;
tester_setup_failed();
return;
}
+}
+static void setup_hidhost_interface(const void *test_data)
+{
+ setup_hidhost(test_data);
tester_setup_complete();
}
+static void hid_sdp_cid_hook_cb(const void *data, uint16_t len, void *user_data)
+{
+ struct test_data *t_data = tester_get_data();
+ struct bthost *bthost = hciemu_client_get_host(t_data->hciemu);
+ uint8_t pdu[] = { 0x07, /* PDU id */
+ 0x00, 0x00, /* Transaction id */
+ 0x01, 0x71, /* Response length */
+ 0x01, 0x6E, /* Attributes length */
+ 0x36, 0x01, 0x6b, 0x36, 0x01, 0x68, 0x09, 0x00,
+ 0x00, 0x0a, 0x00, 0x01, 0x00, 0x00, 0x09, 0x00,
+ 0x01, 0x35, 0x03, 0x19, 0x11, 0x24, 0x09, 0x00,
+ 0x04, 0x35, 0x0d, 0x35, 0x06, 0x19, 0x01, 0x00,
+ 0x09, 0x00, 0x11, 0x35, 0x03, 0x19, 0x00, 0x11,
+ 0x09, 0x00, 0x05, 0x35, 0x03, 0x19, 0x10, 0x02,
+ 0x09, 0x00, 0x06, 0x35, 0x09, 0x09, 0x65, 0x6e,
+ 0x09, 0x00, 0x6a, 0x09, 0x01, 0x00, 0x09, 0x00,
+ 0x09, 0x35, 0x08, 0x35, 0x06, 0x19, 0x11, 0x24,
+ 0x09, 0x01, 0x00, 0x09, 0x00, 0x0d, 0x35, 0x0f,
+ 0x35, 0x0d, 0x35, 0x06, 0x19, 0x01, 0x00, 0x09,
+ 0x00, 0x13, 0x35, 0x03, 0x19, 0x00, 0x11, 0x09,
+ 0x01, 0x00, 0x25, 0x1e, 0x4c, 0x6f, 0x67, 0x69,
+ 0x74, 0x65, 0x63, 0x68, 0x20, 0x42, 0x6c, 0x75,
+ 0x65, 0x74, 0x6f, 0x6f, 0x74, 0x68, 0x20, 0x4d,
+ 0x6f, 0x75, 0x73, 0x65, 0x20, 0x4d, 0x35, 0x35,
+ 0x35, 0x62, 0x09, 0x01, 0x01, 0x25, 0x0f, 0x42,
+ 0x6c, 0x75, 0x65, 0x74, 0x6f, 0x6f, 0x74, 0x68,
+ 0x20, 0x4d, 0x6f, 0x75, 0x73, 0x65, 0x09, 0x01,
+ 0x02, 0x25, 0x08, 0x4c, 0x6f, 0x67, 0x69, 0x74,
+ 0x65, 0x63, 0x68, 0x09, 0x02, 0x00, 0x09, 0x01,
+ 0x00, 0x09, 0x02, 0x01, 0x09, 0x01, 0x11, 0x09,
+ 0x02, 0x02, 0x08, 0x80, 0x09, 0x02, 0x03, 0x08,
+ 0x21, 0x09, 0x02, 0x04, 0x28, 0x01, 0x09, 0x02,
+ 0x05, 0x28, 0x01, 0x09, 0x02, 0x06, 0x35, 0x74,
+ 0x35, 0x72, 0x08, 0x22, 0x25, 0x6e, 0x05, 0x01,
+ 0x09, 0x02, 0xa1, 0x01, 0x85, 0x02, 0x09, 0x01,
+ 0xa1, 0x00, 0x05, 0x09, 0x19, 0x01, 0x29, 0x08,
+ 0x15, 0x00, 0x25, 0x01, 0x75, 0x01, 0x95, 0x08,
+ 0x81, 0x02, 0x05, 0x01, 0x09, 0x30, 0x09, 0x31,
+ 0x16, 0x01, 0xf8, 0x26, 0xff, 0x07, 0x75, 0x0c,
+ 0x95, 0x02, 0x81, 0x06, 0x09, 0x38, 0x15, 0x81,
+ 0x25, 0x7f, 0x75, 0x08, 0x95, 0x01, 0x81, 0x06,
+ 0x05, 0x0c, 0x0a, 0x38, 0x02, 0x81, 0x06, 0x05,
+ 0x09, 0x19, 0x09, 0x29, 0x10, 0x15, 0x00, 0x25,
+ 0x01, 0x95, 0x08, 0x75, 0x01, 0x81, 0x02, 0xc0,
+ 0xc0, 0x06, 0x00, 0xff, 0x09, 0x01, 0xa1, 0x01,
+ 0x85, 0x10, 0x75, 0x08, 0x95, 0x06, 0x15, 0x00,
+ 0x26, 0xff, 0x00, 0x09, 0x01, 0x81, 0x00, 0x09,
+ 0x01, 0x91, 0x00, 0xc0, 0x09, 0x02, 0x07, 0x35,
+ 0x08, 0x35, 0x06, 0x09, 0x04, 0x09, 0x09, 0x01,
+ 0x00, 0x09, 0x02, 0x08, 0x28, 0x00, 0x09, 0x02,
+ 0x09, 0x28, 0x01, 0x09, 0x02, 0x0a, 0x28, 0x01,
+ 0x09, 0x02, 0x0b, 0x09, 0x01, 0x00, 0x09, 0x02,
+ 0x0c, 0x09, 0x0c, 0x80, 0x09, 0x02, 0x0d, 0x28,
+ 0x00, 0x09, 0x02, 0x0e, 0x28, 0x01,
+ 0x00 /* no continuation */};
+
+ bthost_send_cid(bthost, t_data->sdp_handle, t_data->sdp_cid,
+ (void *)pdu, sizeof(pdu));
+}
+
+static void hid_sdp_search_cb(uint16_t handle, uint16_t cid, void *user_data)
+{
+ struct test_data *data = tester_get_data();
+ struct bthost *bthost = hciemu_client_get_host(data->hciemu);
+
+ data->sdp_handle = handle;
+ data->sdp_cid = cid;
+
+ bthost_add_cid_hook(bthost, handle, cid, hid_sdp_cid_hook_cb, NULL);
+}
+
+static void emu_powered_complete(uint16_t opcode, uint8_t status,
+ const void *param, uint8_t len,
+ void *user_data)
+{
+ struct test_data *data = tester_get_data();
+ const uint8_t *hid_addr = hciemu_get_client_bdaddr(data->hciemu);
+ bt_bdaddr_t bdaddr;
+ bt_status_t bt_status;
+
+ switch (opcode) {
+ case BT_HCI_CMD_WRITE_SCAN_ENABLE:
+ case BT_HCI_CMD_LE_SET_ADV_ENABLE:
+ break;
+ default:
+ return;
+ }
+
+ if (status) {
+ tester_setup_failed();
+ return;
+ }
+
+ data->cb_count = 0;
+ bdaddr2android((const bdaddr_t *) hid_addr, &bdaddr);
+ bt_status = data->if_hid->connect(&bdaddr);
+ if (bt_status != BT_STATUS_SUCCESS)
+ tester_setup_failed();
+
+}
+
+static void setup_hidhost_connect(const void *test_data)
+{
+ struct test_data *data = tester_get_data();
+ struct bthost *bthost;
+
+ setup_hidhost(test_data);
+
+ bthost = hciemu_client_get_host(data->hciemu);
+
+ /* Emulate SDP (PSM = 1) */
+ bthost_add_l2cap_server(bthost, 1, hid_sdp_search_cb, NULL);
+ /* Emulate Control Channel (PSM = 17) */
+ bthost_add_l2cap_server(bthost, 17, NULL, NULL);
+ /* Emulate Interrupt Channel (PSM = 19) */
+ bthost_add_l2cap_server(bthost, 19, NULL, NULL);
+
+ bthost_set_cmd_complete_cb(bthost, emu_powered_complete, data);
+ bthost_write_scan_enable(bthost, 0x03);
+}
+
#define test_bredrle(name, data, test_setup, test, test_teardown) \
do { \
struct test_data *user; \
test_bredrle("HIDHost Init", NULL, setup_hidhost_interface,
test_dummy, teardown);
+ test_bredrle("HIDHost Connect Success",
+ NULL, setup_hidhost_connect,
+ test_dummy, teardown);
+
return tester_run();
}