From: Archie Pusaka <apusaka@google.com>
To: linux-bluetooth <linux-bluetooth@vger.kernel.org>,
Luiz Augusto von Dentz <luiz.dentz@gmail.com>
Cc: CrosBT Upstreaming <chromeos-bluetooth-upstreaming@chromium.org>,
Archie Pusaka <apusaka@chromium.org>,
Alain Michaud <alainm@chromium.org>,
Abhishek Pandit-Subedi <abhishekpandit@chromium.org>
Subject: [Bluez PATCH v2 2/3] input/device: Implement handle for UHID_SET_REPORT
Date: Mon, 3 Aug 2020 14:52:23 +0800 [thread overview]
Message-ID: <20200803145200.Bluez.v2.2.I90a7cdf110044e880cf5610972e93a0f47d6c9fd@changeid> (raw)
In-Reply-To: <20200803145200.Bluez.v2.1.Ibf5508171632eebb66a6cd0ed2fa87bfac078f74@changeid>
From: Archie Pusaka <apusaka@chromium.org>
This patch listens to UHID_SET_REPORT event and forwards this
message to the hid device. Upon reply, we also send a report back
to the kernel as UHID_SET_REPORT_REPLY.
hidp_send_set_report no longer listen UHID_OUTPUT events, that is
handled by hidp_send_output instead.
Reviewed-by: Alain Michaud <alainm@chromium.org>
Reviewed-by: Abhishek Pandit-Subedi <abhishekpandit@chromium.org>
---
Changes in v2:
-Split into three patches, now this only handles UHID_SET_REPORT
profiles/input/device.c | 100 ++++++++++++++++++++++++++++++----------
1 file changed, 76 insertions(+), 24 deletions(-)
diff --git a/profiles/input/device.c b/profiles/input/device.c
index ac4487f63..757290080 100644
--- a/profiles/input/device.c
+++ b/profiles/input/device.c
@@ -258,6 +258,29 @@ static bool uhid_send_get_report_reply(struct input_device *idev,
return true;
}
+static bool uhid_send_set_report_reply(struct input_device *idev,
+ uint32_t id, uint16_t err)
+{
+ struct uhid_event ev;
+ int ret;
+
+ if (!idev->uhid_created)
+ return false;
+
+ memset(&ev, 0, sizeof(ev));
+ ev.type = UHID_SET_REPORT_REPLY;
+ ev.u.set_report_reply.id = id;
+ ev.u.set_report_reply.err = err;
+
+ ret = bt_uhid_send(idev->uhid, &ev);
+ if (ret < 0) {
+ error("bt_uhid_send: %s (%d)", strerror(-ret), -ret);
+ return false;
+ }
+
+ return true;
+}
+
static bool uhid_send_input_report(struct input_device *idev,
const uint8_t *data, size_t size)
{
@@ -404,6 +427,8 @@ static void hidp_recv_ctrl_handshake(struct input_device *idev, uint8_t param)
pending_req_complete = true;
} else if (pending_req_type == HIDP_TRANS_SET_REPORT) {
DBG("SET_REPORT failed (%u)", param);
+ uhid_send_set_report_reply(idev, idev->report_rsp_id,
+ EIO);
pending_req_complete = true;
} else
DBG("Spurious HIDP_HSHK_ERR");
@@ -446,7 +471,8 @@ static void hidp_recv_ctrl_data(struct input_device *idev, uint8_t param,
DBG("");
pending_req_type = idev->report_req_pending & HIDP_HEADER_TRANS_MASK;
- if (pending_req_type != HIDP_TRANS_GET_REPORT) {
+ if (pending_req_type != HIDP_TRANS_GET_REPORT &&
+ pending_req_type != HIDP_TRANS_SET_REPORT) {
DBG("Spurious DATA on control channel");
return;
}
@@ -461,8 +487,12 @@ static void hidp_recv_ctrl_data(struct input_device *idev, uint8_t param,
case HIDP_DATA_RTYPE_FEATURE:
case HIDP_DATA_RTYPE_INPUT:
case HIDP_DATA_RTYPE_OUTPUT:
- uhid_send_get_report_reply(idev, data + 1, size - 1,
+ if (pending_req_type == HIDP_TRANS_GET_REPORT)
+ uhid_send_get_report_reply(idev, data + 1, size - 1,
idev->report_rsp_id, 0);
+ else
+ uhid_send_set_report_reply(idev, idev->report_rsp_id,
+ 0);
break;
case HIDP_DATA_RTYPE_OTHER:
@@ -579,9 +609,13 @@ static gboolean hidp_report_req_timeout(gpointer data)
switch (pending_req_type) {
case HIDP_TRANS_GET_REPORT:
req_type_str = "GET_REPORT";
+ uhid_send_get_report_reply(idev, NULL, 0, idev->report_rsp_id,
+ ETIMEDOUT);
break;
case HIDP_TRANS_SET_REPORT:
req_type_str = "SET_REPORT";
+ uhid_send_set_report_reply(idev, idev->report_rsp_id,
+ ETIMEDOUT);
break;
default:
/* Should never happen */
@@ -598,6 +632,17 @@ static gboolean hidp_report_req_timeout(gpointer data)
return FALSE;
}
+static void hidp_send_output(struct uhid_event *ev, void *user_data)
+{
+ struct input_device *idev = user_data;
+ uint8_t hdr = HIDP_TRANS_DATA | HIDP_DATA_RTYPE_OUTPUT;
+
+ DBG("");
+
+ hidp_send_intr_message(idev, hdr, ev->u.output.data,
+ ev->u.output.size);
+}
+
static void hidp_send_set_report(struct uhid_event *ev, void *user_data)
{
struct input_device *idev = user_data;
@@ -606,34 +651,37 @@ static void hidp_send_set_report(struct uhid_event *ev, void *user_data)
DBG("");
- switch (ev->u.output.rtype) {
+ switch (ev->u.set_report.rtype) {
case UHID_FEATURE_REPORT:
- /* Send SET_REPORT on control channel */
- if (idev->report_req_pending) {
- DBG("Old GET_REPORT or SET_REPORT still pending");
- return;
- }
-
hdr = HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_FEATURE;
- sent = hidp_send_ctrl_message(idev, hdr, ev->u.output.data,
- ev->u.output.size);
- if (sent) {
- idev->report_req_pending = hdr;
- idev->report_req_timer =
- g_timeout_add_seconds(REPORT_REQ_TIMEOUT,
- hidp_report_req_timeout, idev);
- }
+ break;
+ case UHID_INPUT_REPORT:
+ hdr = HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_INPUT;
break;
case UHID_OUTPUT_REPORT:
- /* Send DATA on interrupt channel */
- hdr = HIDP_TRANS_DATA | HIDP_DATA_RTYPE_OUTPUT;
- hidp_send_intr_message(idev, hdr, ev->u.output.data,
- ev->u.output.size);
+ hdr = HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_OUTPUT;
break;
default:
- DBG("Unsupported HID report type %u", ev->u.output.rtype);
+ DBG("Unsupported HID report type %u", ev->u.set_report.rtype);
+ return;
+ }
+
+ if (idev->report_req_pending) {
+ DBG("Old GET_REPORT or SET_REPORT still pending");
+ uhid_send_set_report_reply(idev, ev->u.set_report.id, EBUSY);
return;
}
+
+ sent = hidp_send_ctrl_message(idev, hdr, ev->u.set_report.data,
+ ev->u.set_report.size);
+ if (sent) {
+ idev->report_req_pending = hdr;
+ idev->report_req_timer =
+ g_timeout_add_seconds(REPORT_REQ_TIMEOUT,
+ hidp_report_req_timeout, idev);
+ idev->report_rsp_id = ev->u.set_report.id;
+ } else
+ uhid_send_set_report_reply(idev, ev->u.set_report.id, EIO);
}
static void hidp_send_get_report(struct uhid_event *ev, void *user_data)
@@ -675,7 +723,9 @@ static void hidp_send_get_report(struct uhid_event *ev, void *user_data)
g_timeout_add_seconds(REPORT_REQ_TIMEOUT,
hidp_report_req_timeout, idev);
idev->report_rsp_id = ev->u.get_report.id;
- }
+ } else
+ uhid_send_get_report_reply(idev, NULL, 0, ev->u.get_report.id,
+ EIO);
}
static void epox_endian_quirk(unsigned char *data, int size)
@@ -908,9 +958,11 @@ static int uhid_connadd(struct input_device *idev, struct hidp_connadd_req *req)
return err;
}
- bt_uhid_register(idev->uhid, UHID_OUTPUT, hidp_send_set_report, idev);
+ bt_uhid_register(idev->uhid, UHID_OUTPUT, hidp_send_output, idev);
bt_uhid_register(idev->uhid, UHID_GET_REPORT, hidp_send_get_report,
idev);
+ bt_uhid_register(idev->uhid, UHID_SET_REPORT, hidp_send_set_report,
+ idev);
idev->uhid_created = true;
--
2.28.0.163.g6104cc2f0b6-goog
next prev parent reply other threads:[~2020-08-03 6:52 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-08-03 6:52 [Bluez PATCH v2 1/3] input/device: Replace UHID_FEATURE with UHID_GET_REPORT Archie Pusaka
2020-08-03 6:52 ` Archie Pusaka [this message]
2020-08-03 6:52 ` [Bluez PATCH v2 3/3] input/device: Send UHID_DESTROY upon disconnection Archie Pusaka
2020-08-03 20:01 ` [Bluez PATCH v2 1/3] input/device: Replace UHID_FEATURE with UHID_GET_REPORT Luiz Augusto von Dentz
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20200803145200.Bluez.v2.2.I90a7cdf110044e880cf5610972e93a0f47d6c9fd@changeid \
--to=apusaka@google.com \
--cc=abhishekpandit@chromium.org \
--cc=alainm@chromium.org \
--cc=apusaka@chromium.org \
--cc=chromeos-bluetooth-upstreaming@chromium.org \
--cc=linux-bluetooth@vger.kernel.org \
--cc=luiz.dentz@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).