Patch set contains few fixes which are noticed while writing
tests and success test cases for hidhost.
Ravi kumar Veeramally (11):
android/hidhost: Fix connection state notification on profile
unregister
android/hidhost: Fix miscalculation of get report event struct length
android/hidhost: Remove unnecessary check
android/tester: Add HIDhost Connect test
android/tester: Add HIDhost Disconnect test
android/tester: Add HIDhost VirtualUnplug test
android/tester: Add HIDhost GetProtocol test
android/tester: Add HIDhost SetProtocol test
android/tester: Add HIDhost GetReport test
android/tester: Add HIDhost SetReport test
android/tester: Add HIDhost SendData test
android/android-tester.c | 517 ++++++++++++++++++++++++++++++++++++++++++++++-
android/hal-hidhost.c | 3 +-
android/hidhost.c | 14 +-
3 files changed, 511 insertions(+), 23 deletions(-)
--
1.8.3.2
Hi Szymon,
On 01/20/2014 05:30 PM, Szymon Janc wrote:
> android/android-tester.c | 517 ++++++++++++++++++++++++++++++++++++++++++++++-
> android/hal-hidhost.c | 3 +-
> android/hidhost.c | 14 +-
> 3 files changed, 511 insertions(+), 23 deletions(-)
>
>
> I've applied all patches except 2 and 9, thanks.
> Please see comments for 02/11.
>
Ok, I will check what went wrong.
Thanks,
Ravi.
Hi Ravi,
On Friday 17 of January 2014 01:25:40 Ravi kumar Veeramally wrote:
> Patch set contains few fixes which are noticed while writing
> tests and success test cases for hidhost.
>
> Ravi kumar Veeramally (11):
> android/hidhost: Fix connection state notification on profile
> unregister
> android/hidhost: Fix miscalculation of get report event struct length
> android/hidhost: Remove unnecessary check
> android/tester: Add HIDhost Connect test
> android/tester: Add HIDhost Disconnect test
> android/tester: Add HIDhost VirtualUnplug test
> android/tester: Add HIDhost GetProtocol test
> android/tester: Add HIDhost SetProtocol test
> android/tester: Add HIDhost GetReport test
> android/tester: Add HIDhost SetReport test
> android/tester: Add HIDhost SendData test
>
> android/android-tester.c | 517 ++++++++++++++++++++++++++++++++++++++++++++++-
> android/hal-hidhost.c | 3 +-
> android/hidhost.c | 14 +-
> 3 files changed, 511 insertions(+), 23 deletions(-)
>
>
I've applied all patches except 2 and 9, thanks.
Please see comments for 02/11.
--
Best regards,
Szymon Janc
Hi Ravi,
On Friday 17 of January 2014 01:25:42 Ravi kumar Veeramally wrote:
> ---
> android/hal-hidhost.c | 3 ++-
> android/hidhost.c | 3 ++-
> 2 files changed, 4 insertions(+), 2 deletions(-)
>
> diff --git a/android/hal-hidhost.c b/android/hal-hidhost.c
> index fd3ad2d..5445d08 100644
> --- a/android/hal-hidhost.c
> +++ b/android/hal-hidhost.c
> @@ -73,7 +73,8 @@ static void handle_get_report(void *buf, uint16_t len)
> {
> struct hal_ev_hidhost_get_report *ev = buf;
>
> - if (len != sizeof(*ev) + ev->len) {
> + if (len != sizeof(*ev) + sizeof(struct hal_ev_hidhost_get_report)
> + + ev->len) {
I don't understand this change. We have header and data len. There should be
no need for any extra calculations.
> error("invalid get report event, aborting");
> exit(EXIT_FAILURE);
> }
> diff --git a/android/hidhost.c b/android/hidhost.c
> index c004063..8a2668c 100644
> --- a/android/hidhost.c
> +++ b/android/hidhost.c
> @@ -371,13 +371,14 @@ static void bt_hid_notify_get_report(struct hid_device *dev, uint8_t *buf,
> ba2str(&dev->dst, address);
> DBG("device %s", address);
>
> - ev_len = sizeof(*ev) + sizeof(struct hal_ev_hidhost_get_report) + 1;
> + ev_len = sizeof(*ev) + sizeof(struct hal_ev_hidhost_get_report);
I don't understand why there is double sizeof() in first place.(*ev is same type)
>
> if (!((buf[0] == (HID_MSG_DATA | HID_DATA_TYPE_INPUT)) ||
> (buf[0] == (HID_MSG_DATA | HID_DATA_TYPE_OUTPUT)) ||
> (buf[0] == (HID_MSG_DATA | HID_DATA_TYPE_FEATURE)))) {
> ev = g_malloc0(ev_len);
> ev->status = buf[0];
> + ev->len = 0;
> bdaddr2android(&dev->dst, ev->bdaddr);
> goto send;
> }
I have a feeling that there is something wrong with ev_len calculations in
bt_hid_notify_get_report(). I'd rather prefer to have this function properly
fixed (and possibly refactored on how it handles ev data allocation).
--
Best regards,
Szymon Janc
---
android/android-tester.c | 29 +++++++++++++++++++++++++++++
1 file changed, 29 insertions(+)
diff --git a/android/android-tester.c b/android/android-tester.c
index f8d539d..c79ea16 100644
--- a/android/android-tester.c
+++ b/android/android-tester.c
@@ -3204,6 +3204,10 @@ static void setup_hidhost_interface(const void *test_data)
#define HID_GET_OUTPUT_REPORT 0x4a
#define HID_GET_FEATURE_REPORT 0x4b
+#define HID_SET_INPUT_REPORT 0x51
+#define HID_SET_OUTPUT_REPORT 0x52
+#define HID_SET_FEATURE_REPORT 0x53
+
static void hid_prepare_reply_protocol_mode(const void *data, uint16_t len)
{
struct test_data *t_data = tester_get_data();
@@ -3268,6 +3272,12 @@ static void hid_ctrl_cid_hook_cb(const void *data, uint16_t len,
case HID_GET_FEATURE_REPORT:
hid_prepare_reply_report(data, len);
break;
+ /* HID device doesnot reply for this commads, so reaching pdu's
+ * to hid device means assuming test passed */
+ case HID_SET_INPUT_REPORT:
+ case HID_SET_OUTPUT_REPORT:
+ case HID_SET_FEATURE_REPORT:
+ tester_test_passed();
}
}
@@ -3525,6 +3535,21 @@ static void test_hidhost_get_report(const void *test_data)
tester_test_failed();
}
+static void test_hidhost_set_report(const void *test_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;
+ char *buf = "010101";
+
+ data->cb_count = 0;
+ bdaddr2android((const bdaddr_t *) hid_addr, &bdaddr);
+ bt_status = data->if_hid->set_report(&bdaddr, BTHH_INPUT_REPORT, buf);
+ if (bt_status != BT_STATUS_SUCCESS)
+ tester_test_failed();
+}
+
#define test_bredrle(name, data, test_setup, test, test_teardown) \
do { \
struct test_data *user; \
@@ -3894,5 +3919,9 @@ int main(int argc, char *argv[])
&hidhost_test_get_report, setup_hidhost_connect,
test_hidhost_get_report, teardown);
+ test_bredrle("HIDHost SetReport Success",
+ NULL, setup_hidhost_connect,
+ test_hidhost_set_report, teardown);
+
return tester_run();
}
--
1.8.3.2
---
android/android-tester.c | 28 ++++++++++++++++++++++++++++
1 file changed, 28 insertions(+)
diff --git a/android/android-tester.c b/android/android-tester.c
index c79ea16..2ef44ef 100644
--- a/android/android-tester.c
+++ b/android/android-tester.c
@@ -3208,6 +3208,8 @@ static void setup_hidhost_interface(const void *test_data)
#define HID_SET_OUTPUT_REPORT 0x52
#define HID_SET_FEATURE_REPORT 0x53
+#define HID_SEND_DATA 0xa2
+
static void hid_prepare_reply_protocol_mode(const void *data, uint16_t len)
{
struct test_data *t_data = tester_get_data();
@@ -3242,6 +3244,12 @@ static void hid_prepare_reply_report(const void *data, uint16_t len)
static void hid_intr_cid_hook_cb(const void *data, uint16_t len,
void *user_data)
{
+ uint8_t header = ((uint8_t *) data)[0];
+
+ switch (header) {
+ case HID_SEND_DATA:
+ tester_test_passed();
+ }
}
static void hid_intr_connect_cb(uint16_t handle, uint16_t cid, void *user_data)
@@ -3277,6 +3285,7 @@ static void hid_ctrl_cid_hook_cb(const void *data, uint16_t len,
case HID_SET_INPUT_REPORT:
case HID_SET_OUTPUT_REPORT:
case HID_SET_FEATURE_REPORT:
+ case HID_SEND_DATA:
tester_test_passed();
}
}
@@ -3550,6 +3559,21 @@ static void test_hidhost_set_report(const void *test_data)
tester_test_failed();
}
+static void test_hidhost_send_data(const void *test_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;
+ char *buf = "fe0201";
+
+ data->cb_count = 0;
+ bdaddr2android((const bdaddr_t *) hid_addr, &bdaddr);
+ bt_status = data->if_hid->send_data(&bdaddr, buf);
+ if (bt_status != BT_STATUS_SUCCESS)
+ tester_test_failed();
+}
+
#define test_bredrle(name, data, test_setup, test, test_teardown) \
do { \
struct test_data *user; \
@@ -3923,5 +3947,9 @@ int main(int argc, char *argv[])
NULL, setup_hidhost_connect,
test_hidhost_set_report, teardown);
+ test_bredrle("HIDHost SendData Success",
+ NULL, setup_hidhost_connect,
+ test_hidhost_send_data, teardown);
+
return tester_run();
}
--
1.8.3.2
---
android/android-tester.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 64 insertions(+)
diff --git a/android/android-tester.c b/android/android-tester.c
index da1fc28..f8d539d 100644
--- a/android/android-tester.c
+++ b/android/android-tester.c
@@ -3200,6 +3200,10 @@ static void setup_hidhost_interface(const void *test_data)
#define HID_SET_REPORT_PROTOCOL 0x70
#define HID_SET_BOOT_PROTOCOL 0x71
+#define HID_GET_INPUT_REPORT 0x49
+#define HID_GET_OUTPUT_REPORT 0x4a
+#define HID_GET_FEATURE_REPORT 0x4b
+
static void hid_prepare_reply_protocol_mode(const void *data, uint16_t len)
{
struct test_data *t_data = tester_get_data();
@@ -3215,6 +3219,22 @@ static void hid_prepare_reply_protocol_mode(const void *data, uint16_t len)
(void *)pdu, pdu_len);
}
+static void hid_prepare_reply_report(const void *data, uint16_t len)
+{
+ struct test_data *t_data = tester_get_data();
+ struct bthost *bthost = hciemu_client_get_host(t_data->hciemu);
+ uint8_t pdu[3] = { 0, 0, 0 };
+ uint16_t pdu_len = 0;
+
+ pdu_len = 3;
+ pdu[0] = 0xa2;
+ pdu[1] = 0x01;
+ pdu[2] = 0x00;
+
+ bthost_send_cid(bthost, t_data->ctrl_handle, t_data->ctrl_cid,
+ (void *)pdu, pdu_len);
+}
+
static void hid_intr_cid_hook_cb(const void *data, uint16_t len,
void *user_data)
{
@@ -3243,6 +3263,11 @@ static void hid_ctrl_cid_hook_cb(const void *data, uint16_t len,
case HID_SET_BOOT_PROTOCOL:
hid_prepare_reply_protocol_mode(data, len);
break;
+ case HID_GET_INPUT_REPORT:
+ case HID_GET_OUTPUT_REPORT:
+ case HID_GET_FEATURE_REPORT:
+ hid_prepare_reply_report(data, len);
+ break;
}
}
@@ -3465,6 +3490,41 @@ static void test_hidhost_set_protocol(const void *test_data)
tester_test_failed();
}
+static void hid_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;
+
+ if (data->cb_count == test->expected_cb_count &&
+ status == test->expected_status &&
+ size == test->expected_report_size)
+ tester_test_passed();
+ else
+ tester_test_failed();
+}
+
+static const struct hidhost_generic_data hidhost_test_get_report = {
+ .expected_hal_cb.get_report_cb = hid_get_report_cb,
+ .expected_cb_count = 1,
+ .expected_status = BTHH_OK,
+ .expected_report_size = 2,
+};
+
+static void test_hidhost_get_report(const void *test_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;
+
+ data->cb_count = 0;
+ bdaddr2android((const bdaddr_t *) hid_addr, &bdaddr);
+ bt_status = data->if_hid->get_report(&bdaddr, BTHH_INPUT_REPORT, 1, 20);
+ if (bt_status != BT_STATUS_SUCCESS)
+ tester_test_failed();
+}
+
#define test_bredrle(name, data, test_setup, test, test_teardown) \
do { \
struct test_data *user; \
@@ -3830,5 +3890,9 @@ int main(int argc, char *argv[])
&hidhost_test_get_protocol, setup_hidhost_connect,
test_hidhost_set_protocol, teardown);
+ test_bredrle("HIDHost GetReport Success",
+ &hidhost_test_get_report, setup_hidhost_connect,
+ test_hidhost_get_report, teardown);
+
return tester_run();
}
--
1.8.3.2
---
android/android-tester.c | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)
diff --git a/android/android-tester.c b/android/android-tester.c
index 56be850..da1fc28 100644
--- a/android/android-tester.c
+++ b/android/android-tester.c
@@ -3197,6 +3197,8 @@ static void setup_hidhost_interface(const void *test_data)
#define HID_GET_REPORT_PROTOCOL 0x60
#define HID_GET_BOOT_PROTOCOL 0x61
+#define HID_SET_REPORT_PROTOCOL 0x70
+#define HID_SET_BOOT_PROTOCOL 0x71
static void hid_prepare_reply_protocol_mode(const void *data, uint16_t len)
{
@@ -3237,6 +3239,8 @@ static void hid_ctrl_cid_hook_cb(const void *data, uint16_t len,
switch (header) {
case HID_GET_REPORT_PROTOCOL:
case HID_GET_BOOT_PROTOCOL:
+ case HID_SET_REPORT_PROTOCOL:
+ case HID_SET_BOOT_PROTOCOL:
hid_prepare_reply_protocol_mode(data, len);
break;
}
@@ -3447,6 +3451,20 @@ static void test_hidhost_get_protocol(const void *test_data)
tester_test_failed();
}
+static void test_hidhost_set_protocol(const void *test_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;
+
+ data->cb_count = 0;
+ bdaddr2android((const bdaddr_t *) hid_addr, &bdaddr);
+ bt_status = data->if_hid->set_protocol(&bdaddr, BTHH_REPORT_MODE);
+ if (bt_status != BT_STATUS_SUCCESS)
+ tester_test_failed();
+}
+
#define test_bredrle(name, data, test_setup, test, test_teardown) \
do { \
struct test_data *user; \
@@ -3808,5 +3826,9 @@ int main(int argc, char *argv[])
&hidhost_test_get_protocol, setup_hidhost_connect,
test_hidhost_get_protocol, teardown);
+ test_bredrle("HIDHost SetProtocol Success",
+ &hidhost_test_get_protocol, setup_hidhost_connect,
+ test_hidhost_set_protocol, teardown);
+
return tester_run();
}
--
1.8.3.2
---
android/android-tester.c | 101 ++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 99 insertions(+), 2 deletions(-)
diff --git a/android/android-tester.c b/android/android-tester.c
index 2adbba1..56be850 100644
--- a/android/android-tester.c
+++ b/android/android-tester.c
@@ -3195,6 +3195,64 @@ static void setup_hidhost_interface(const void *test_data)
tester_setup_complete();
}
+#define HID_GET_REPORT_PROTOCOL 0x60
+#define HID_GET_BOOT_PROTOCOL 0x61
+
+static void hid_prepare_reply_protocol_mode(const void *data, uint16_t len)
+{
+ struct test_data *t_data = tester_get_data();
+ struct bthost *bthost = hciemu_client_get_host(t_data->hciemu);
+ uint8_t pdu[2] = { 0, 0 };
+ uint16_t pdu_len = 0;
+
+ pdu_len = 2;
+ pdu[0] = 0xa0;
+ pdu[1] = 0x00;
+
+ bthost_send_cid(bthost, t_data->ctrl_handle, t_data->ctrl_cid,
+ (void *)pdu, pdu_len);
+}
+
+static void hid_intr_cid_hook_cb(const void *data, uint16_t len,
+ void *user_data)
+{
+}
+
+static void hid_intr_connect_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->intr_handle = handle;
+ data->intr_cid = cid;
+
+ bthost_add_cid_hook(bthost, handle, cid, hid_intr_cid_hook_cb, NULL);
+}
+
+static void hid_ctrl_cid_hook_cb(const void *data, uint16_t len,
+ void *user_data)
+{
+ uint8_t header = ((uint8_t *) data)[0];
+
+ switch (header) {
+ case HID_GET_REPORT_PROTOCOL:
+ case HID_GET_BOOT_PROTOCOL:
+ hid_prepare_reply_protocol_mode(data, len);
+ break;
+ }
+}
+
+static void hid_ctrl_connect_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->ctrl_handle = handle;
+ data->ctrl_cid = cid;
+
+ bthost_add_cid_hook(bthost, handle, cid, hid_ctrl_cid_hook_cb, NULL);
+}
+
static void hid_sdp_cid_hook_cb(const void *data, uint16_t len, void *user_data)
{
struct test_data *t_data = tester_get_data();
@@ -3308,9 +3366,9 @@ static void setup_hidhost_connect(const void *test_data)
/* 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);
+ bthost_add_l2cap_server(bthost, 17, hid_ctrl_connect_cb, NULL);
/* Emulate Interrupt Channel (PSM = 19) */
- bthost_add_l2cap_server(bthost, 19, NULL, NULL);
+ bthost_add_l2cap_server(bthost, 19, hid_intr_connect_cb, NULL);
bthost_set_cmd_complete_cb(bthost, emu_powered_complete, data);
bthost_write_scan_enable(bthost, 0x03);
@@ -3354,6 +3412,41 @@ static void test_hidhost_virtual_unplug(const void *test_data)
tester_test_failed();
}
+static void hid_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;
+
+ if (data->cb_count == test->expected_cb_count &&
+ status == test->expected_status &&
+ mode == test->expected_protocol_mode)
+ tester_test_passed();
+ else
+ tester_test_failed();
+}
+
+static const struct hidhost_generic_data hidhost_test_get_protocol = {
+ .expected_hal_cb.protocol_mode_cb = hid_protocol_mode_cb,
+ .expected_cb_count = 1,
+ .expected_protocol_mode = BTHH_BOOT_MODE,
+ .expected_status = BTHH_OK,
+};
+
+static void test_hidhost_get_protocol(const void *test_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;
+
+ data->cb_count = 0;
+ bdaddr2android((const bdaddr_t *) hid_addr, &bdaddr);
+ bt_status = data->if_hid->get_protocol(&bdaddr, BTHH_REPORT_MODE);
+ if (bt_status != BT_STATUS_SUCCESS)
+ tester_test_failed();
+}
+
#define test_bredrle(name, data, test_setup, test, test_teardown) \
do { \
struct test_data *user; \
@@ -3711,5 +3804,9 @@ int main(int argc, char *argv[])
&hidhost_test_disconnect, setup_hidhost_connect,
test_hidhost_virtual_unplug, teardown);
+ test_bredrle("HIDHost GetProtocol Success",
+ &hidhost_test_get_protocol, setup_hidhost_connect,
+ test_hidhost_get_protocol, teardown);
+
return tester_run();
}
--
1.8.3.2
---
android/android-tester.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/android/android-tester.c b/android/android-tester.c
index 8edabb1..2adbba1 100644
--- a/android/android-tester.c
+++ b/android/android-tester.c
@@ -3340,6 +3340,20 @@ static void test_hidhost_disconnect(const void *test_data)
tester_test_failed();
}
+static void test_hidhost_virtual_unplug(const void *test_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;
+
+ data->cb_count = 0;
+ bdaddr2android((const bdaddr_t *) hid_addr, &bdaddr);
+ bt_status = data->if_hid->virtual_unplug(&bdaddr);
+ if (bt_status != BT_STATUS_SUCCESS)
+ tester_test_failed();
+}
+
#define test_bredrle(name, data, test_setup, test, test_teardown) \
do { \
struct test_data *user; \
@@ -3693,5 +3707,9 @@ int main(int argc, char *argv[])
&hidhost_test_disconnect, setup_hidhost_connect,
test_hidhost_disconnect, teardown);
+ test_bredrle("HIDHost VirtualUnplug Success",
+ &hidhost_test_disconnect, setup_hidhost_connect,
+ test_hidhost_virtual_unplug, teardown);
+
return tester_run();
}
--
1.8.3.2
---
android/android-tester.c | 28 ++++++++++++++++++++++++++++
1 file changed, 28 insertions(+)
diff --git a/android/android-tester.c b/android/android-tester.c
index 0888a68..8edabb1 100644
--- a/android/android-tester.c
+++ b/android/android-tester.c
@@ -3316,6 +3316,30 @@ static void setup_hidhost_connect(const void *test_data)
bthost_write_scan_enable(bthost, 0x03);
}
+static void hid_discon_cb(bt_bdaddr_t *bd_addr, bthh_connection_state_t state)
+{
+ if (state == BTHH_CONN_STATE_DISCONNECTED)
+ tester_test_passed();
+}
+
+static const struct hidhost_generic_data hidhost_test_disconnect = {
+ .expected_hal_cb.connection_state_cb = hid_discon_cb,
+};
+
+static void test_hidhost_disconnect(const void *test_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;
+
+ data->cb_count = 0;
+ bdaddr2android((const bdaddr_t *) hid_addr, &bdaddr);
+ bt_status = data->if_hid->disconnect(&bdaddr);
+ if (bt_status != BT_STATUS_SUCCESS)
+ tester_test_failed();
+}
+
#define test_bredrle(name, data, test_setup, test, test_teardown) \
do { \
struct test_data *user; \
@@ -3665,5 +3689,9 @@ int main(int argc, char *argv[])
NULL, setup_hidhost_connect,
test_dummy, teardown);
+ test_bredrle("HIDHost Disconnect Success",
+ &hidhost_test_disconnect, setup_hidhost_connect,
+ test_hidhost_disconnect, teardown);
+
return tester_run();
}
--
1.8.3.2
Emulated HID SDP and L2CAP Control and Interrupt channels.
---
android/android-tester.c | 231 +++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 221 insertions(+), 10 deletions(-)
diff --git a/android/android-tester.c b/android/android-tester.c
index 6f0e962..0888a68 100644
--- a/android/android-tester.c
+++ b/android/android-tester.c
@@ -69,6 +69,16 @@ struct socket_data {
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"
@@ -97,6 +107,14 @@ struct test_data {
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];
@@ -1933,15 +1951,6 @@ static bt_callbacks_t bt_callbacks = {
.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)
{
@@ -3076,7 +3085,80 @@ clean:
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;
@@ -3105,10 +3187,135 @@ static void setup_hidhost_interface(const void *test_data)
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; \
@@ -3454,5 +3661,9 @@ int main(int argc, char *argv[])
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();
}
--
1.8.3.2
---
android/hal-hidhost.c | 3 ++-
android/hidhost.c | 3 ++-
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/android/hal-hidhost.c b/android/hal-hidhost.c
index fd3ad2d..5445d08 100644
--- a/android/hal-hidhost.c
+++ b/android/hal-hidhost.c
@@ -73,7 +73,8 @@ static void handle_get_report(void *buf, uint16_t len)
{
struct hal_ev_hidhost_get_report *ev = buf;
- if (len != sizeof(*ev) + ev->len) {
+ if (len != sizeof(*ev) + sizeof(struct hal_ev_hidhost_get_report)
+ + ev->len) {
error("invalid get report event, aborting");
exit(EXIT_FAILURE);
}
diff --git a/android/hidhost.c b/android/hidhost.c
index c004063..8a2668c 100644
--- a/android/hidhost.c
+++ b/android/hidhost.c
@@ -371,13 +371,14 @@ static void bt_hid_notify_get_report(struct hid_device *dev, uint8_t *buf,
ba2str(&dev->dst, address);
DBG("device %s", address);
- ev_len = sizeof(*ev) + sizeof(struct hal_ev_hidhost_get_report) + 1;
+ ev_len = sizeof(*ev) + sizeof(struct hal_ev_hidhost_get_report);
if (!((buf[0] == (HID_MSG_DATA | HID_DATA_TYPE_INPUT)) ||
(buf[0] == (HID_MSG_DATA | HID_DATA_TYPE_OUTPUT)) ||
(buf[0] == (HID_MSG_DATA | HID_DATA_TYPE_FEATURE)))) {
ev = g_malloc0(ev_len);
ev->status = buf[0];
+ ev->len = 0;
bdaddr2android(&dev->dst, ev->bdaddr);
goto send;
}
--
1.8.3.2
HID device will return unsupported or invalid response for unsupported
or invalid get/set protocol request. Need not to check prior to that.
---
android/hidhost.c | 10 ----------
1 file changed, 10 deletions(-)
diff --git a/android/hidhost.c b/android/hidhost.c
index 8a2668c..968b6f2 100644
--- a/android/hidhost.c
+++ b/android/hidhost.c
@@ -900,11 +900,6 @@ static void bt_hid_get_protocol(const void *buf, uint16_t len)
dev = l->data;
- if (dev->boot_dev) {
- status = HAL_STATUS_UNSUPPORTED;
- goto failed;
- }
-
hdr = HID_MSG_GET_PROTOCOL | cmd->mode;
fd = g_io_channel_unix_get_fd(dev->ctrl_io);
@@ -955,11 +950,6 @@ static void bt_hid_set_protocol(const void *buf, uint16_t len)
dev = l->data;
- if (dev->boot_dev) {
- status = HAL_STATUS_UNSUPPORTED;
- goto failed;
- }
-
hdr = HID_MSG_SET_PROTOCOL | cmd->mode;
fd = g_io_channel_unix_get_fd(dev->ctrl_io);
--
1.8.3.2
Issue found while writing end2end tests. Usually profile unregister is
called when final cleanup of bluetoothd. Freeing connected hid devices
through g_slist_foreach is a asynchronous call. Profile is cleaned up
and and ipc also complete cleanup. But free_hid_devices tries to notify
hal which doesn't exist that time. So behaviour is unexpected.
---
android/hidhost.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/android/hidhost.c b/android/hidhost.c
index aed9899..c004063 100644
--- a/android/hidhost.c
+++ b/android/hidhost.c
@@ -1328,7 +1328,6 @@ static void free_hid_devices(gpointer data, gpointer user_data)
{
struct hid_device *dev = data;
- bt_hid_notify_state(dev, HAL_HIDHOST_STATE_DISCONNECTED);
hid_device_free(dev);
}
--
1.8.3.2