aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Ott <alan@signal11.us>2010-05-16 18:07:09 -0400
committerJiri Kosina <jkosina@suse.cz>2010-05-18 04:43:23 -0400
commita8ab5d58b0238b8199cc699b8dff7c5e1da24138 (patch)
tree9e737c8618433cb8a603a3f32c382ef08ef287ab
parent117ea33a18392685b92928bbaa4e84dbc5be8f93 (diff)
HID: hidraw: Use Interrupt Endpoint for OUT Transfers if Available
This patch makes the hidraw driver use the first Interrupt OUT endpoint for HID transfers to the device if such an endpoint exists. This is consistent with the behavior of the hiddev driver, and the logic is similar. From the USB HID specification: The Interrupt Out pipe is optional. If a device declares an Interrupt Out endpoint then Output reports are transmitted by the host to the device through the Interrupt Out endpoint. If no Interrupt Out endpoint is declared then Output reports are transmitted to a device through the Control endpoint, using Set_Report(Output) requests. Signed-off-by: Alan Ott <alan@signal11.us> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
-rw-r--r--drivers/hid/usbhid/hid-core.c40
1 files changed, 30 insertions, 10 deletions
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index 245aef0de8f2..f9640a362caa 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -807,16 +807,36 @@ static int usbhid_output_raw_report(struct hid_device *hid, __u8 *buf, size_t co
807 struct usb_host_interface *interface = intf->cur_altsetting; 807 struct usb_host_interface *interface = intf->cur_altsetting;
808 int ret; 808 int ret;
809 809
810 ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 810 if (usbhid->urbout) {
811 HID_REQ_SET_REPORT, 811 int actual_length;
812 USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, 812 int skipped_report_id = 0;
813 ((report_type + 1) << 8) | *buf, 813 if (buf[0] == 0x0) {
814 interface->desc.bInterfaceNumber, buf + 1, count - 1, 814 /* Don't send the Report ID */
815 USB_CTRL_SET_TIMEOUT); 815 buf++;
816 816 count--;
817 /* count also the report id */ 817 skipped_report_id = 1;
818 if (ret > 0) 818 }
819 ret++; 819 ret = usb_interrupt_msg(dev, usbhid->urbout->pipe,
820 buf, count, &actual_length,
821 USB_CTRL_SET_TIMEOUT);
822 /* return the number of bytes transferred */
823 if (ret == 0) {
824 ret = actual_length;
825 /* count also the report id */
826 if (skipped_report_id)
827 ret++;
828 }
829 } else {
830 ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
831 HID_REQ_SET_REPORT,
832 USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
833 ((report_type + 1) << 8) | *buf,
834 interface->desc.bInterfaceNumber, buf + 1, count - 1,
835 USB_CTRL_SET_TIMEOUT);
836 /* count also the report id */
837 if (ret > 0)
838 ret++;
839 }
820 840
821 return ret; 841 return ret;
822} 842}