HID: Add the transport-driver functions to the HIDP driver.
diff mbox

Message ID 1416315877-22703-2-git-send-email-kengyu@canonical.com
State New
Headers show

Commit Message

Keng-Yu Lin Nov. 18, 2014, 1:04 p.m. UTC
From: Frank Praznik <frank.praznik@oh.rr.com>

Add raw_request, set_raw_report and output_report transport-driver functions to
the HIDP driver.

Signed-off-by: Frank Praznik <frank.praznik@oh.rr.com>
Acked-by: David Herrmann <dh.herrmann@gmail.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Signed-off-by: Keng-Yu Lin <kegnyu@canonical.com>
Tested-By: Keng-Yu Lin <kengyu@canonical.com>
Tested-By: Gerald Yang <gerald.yang@canonical.com>
---
 net/bluetooth/hidp/core.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 90 insertions(+)

Comments

Andy Whitcroft Nov. 18, 2014, 4:06 p.m. UTC | #1
On Tue, Nov 18, 2014 at 09:04:37PM +0800, Keng-Yu Lin wrote:
> From: Frank Praznik <frank.praznik@oh.rr.com>
> 
> Add raw_request, set_raw_report and output_report transport-driver functions to
> the HIDP driver.
> 
> Signed-off-by: Frank Praznik <frank.praznik@oh.rr.com>
> Acked-by: David Herrmann <dh.herrmann@gmail.com>
> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
> Signed-off-by: Keng-Yu Lin <kegnyu@canonical.com>
> Tested-By: Keng-Yu Lin <kengyu@canonical.com>
> Tested-By: Gerald Yang <gerald.yang@canonical.com>
> ---
>  net/bluetooth/hidp/core.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 90 insertions(+)

Ok, this has no upstream provenance, I assume from a search of linus'
tree that this is the following commit:

  commit 0a7f364e812285246cd617a51194a3f8bd0e8daa
  Author: Frank Praznik <frank.praznik@oh.rr.com>
  Date:   Wed Jan 22 13:49:44 2014 -0500

    HID: Add the transport-driver functions to the HIDP driver.

Indeed this commit seems to be cherry-pickable.  Please when submitting
patches include this information (git cherry-pick -sx is your friend), it
is _very_ important for tracking CVEs and the like later in the kernel's
life.  Also the patch itself is missing the BugLink: which just makes
work for the person applying this later on, and risks it becoming missed.

For other reviewers, this patch does appear to need a foundational commit,
which would normally not be in trusty but for other fixes has already
been applied.  Lastly this fix was applied in v3.15-rc1 and therefore is
not required in either Utopic or Vivid.

Assuming this is confirmed as the implied cherry-pick of the above sha1,
then: 

Acked-by: Andy Whitcroft <apw@canonical.com>

-apw
Tim Gardner Nov. 18, 2014, 5:29 p.m. UTC | #2
I compared the upstream patch with this email version and they are
identical.

Keng-yu - as Andy pointed out, pay attention to the requirements for
Ubuntu stable patches.

rtg

Patch
diff mbox

diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
index f41f637..e1d21bf 100644
--- a/net/bluetooth/hidp/core.c
+++ b/net/bluetooth/hidp/core.c
@@ -353,6 +353,71 @@  err:
 	return ret;
 }
 
+static int hidp_set_raw_report(struct hid_device *hid, unsigned char reportnum,
+			       unsigned char *data, size_t count,
+			       unsigned char report_type)
+{
+	struct hidp_session *session = hid->driver_data;
+	int ret;
+
+	switch (report_type) {
+	case HID_FEATURE_REPORT:
+		report_type = HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_FEATURE;
+		break;
+	case HID_INPUT_REPORT:
+		report_type = HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_INPUT;
+		break;
+	case HID_OUTPUT_REPORT:
+		report_type = HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_OUPUT;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (mutex_lock_interruptible(&session->report_mutex))
+		return -ERESTARTSYS;
+
+	/* Set up our wait, and send the report request to the device. */
+	data[0] = reportnum;
+	set_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags);
+	ret = hidp_send_ctrl_message(session, report_type, data, count);
+	if (ret)
+		goto err;
+
+	/* Wait for the ACK from the device. */
+	while (test_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags) &&
+	       !atomic_read(&session->terminate)) {
+		int res;
+
+		res = wait_event_interruptible_timeout(session->report_queue,
+			!test_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags)
+				|| atomic_read(&session->terminate),
+			10*HZ);
+		if (res == 0) {
+			/* timeout */
+			ret = -EIO;
+			goto err;
+		}
+		if (res < 0) {
+			/* signal */
+			ret = -ERESTARTSYS;
+			goto err;
+		}
+	}
+
+	if (!session->output_report_success) {
+		ret = -EIO;
+		goto err;
+	}
+
+	ret = count;
+
+err:
+	clear_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags);
+	mutex_unlock(&session->report_mutex);
+	return ret;
+}
+
 static int hidp_output_raw_report(struct hid_device *hid, unsigned char *data, size_t count,
 		unsigned char report_type)
 {
@@ -411,6 +476,29 @@  err:
 	return ret;
 }
 
+static int hidp_raw_request(struct hid_device *hid, unsigned char reportnum,
+			    __u8 *buf, size_t len, unsigned char rtype,
+			    int reqtype)
+{
+	switch (reqtype) {
+	case HID_REQ_GET_REPORT:
+		return hidp_get_raw_report(hid, reportnum, buf, len, rtype);
+	case HID_REQ_SET_REPORT:
+		return hidp_set_raw_report(hid, reportnum, buf, len, rtype);
+	default:
+		return -EIO;
+	}
+}
+
+static int hidp_output_report(struct hid_device *hid, __u8 *data, size_t count)
+{
+	struct hidp_session *session = hid->driver_data;
+
+	return hidp_send_intr_message(session,
+				      HIDP_TRANS_DATA | HIDP_DATA_RTYPE_OUPUT,
+				      data, count);
+}
+
 static void hidp_idle_timeout(unsigned long arg)
 {
 	struct hidp_session *session = (struct hidp_session *) arg;
@@ -739,6 +827,8 @@  static struct hid_ll_driver hidp_hid_driver = {
 	.stop = hidp_stop,
 	.open  = hidp_open,
 	.close = hidp_close,
+	.raw_request = hidp_raw_request,
+	.output_report = hidp_output_report,
 	.hidinput_input_event = hidp_hidinput_event,
 };