HID: hid-sony.c: Fix sending Output reports to the Sixaxis
authorAntonio Ospite <ospite@studenti.unina.it>
Sun, 20 Feb 2011 17:26:45 +0000 (18:26 +0100)
committerJiri Kosina <jkosina@suse.cz>
Mon, 21 Feb 2011 12:48:50 +0000 (13:48 +0100)
The Sixaxis does not want the report_id as part of the data packet in
Output reports, so we have to discard buf[0] when sending the actual
control message.

Add also some documentation about that and about why
hdev->hid_output_raw_report needs to be overridden.

Signed-off-by: Antonio Ospite <ospite@studenti.unina.it>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
drivers/hid/hid-sony.c

index 68d7b36e31e43b800e18542918a21ffa75eb2483..93819a08121a2a188ed6f7798806404fceac7d36 100644 (file)
@@ -46,6 +46,16 @@ static __u8 *sony_report_fixup(struct hid_device *hdev, __u8 *rdesc,
        return rdesc;
 }
 
+/*
+ * The Sony Sixaxis does not handle HID Output Reports on the Interrupt EP
+ * like it should according to usbhid/hid-core.c::usbhid_output_raw_report()
+ * so we need to override that forcing HID Output Reports on the Control EP.
+ *
+ * There is also another issue about HID Output Reports via USB, the Sixaxis
+ * does not want the report_id as part of the data packet, so we have to
+ * discard buf[0] when sending the actual control message, even for numbered
+ * reports, humpf!
+ */
 static int sixaxis_usb_output_raw_report(struct hid_device *hid, __u8 *buf,
                size_t count, unsigned char report_type)
 {
@@ -55,6 +65,12 @@ static int sixaxis_usb_output_raw_report(struct hid_device *hid, __u8 *buf,
        int report_id = buf[0];
        int ret;
 
+       if (report_type == HID_OUTPUT_REPORT) {
+               /* Don't send the Report ID */
+               buf++;
+               count--;
+       }
+
        ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
                HID_REQ_SET_REPORT,
                USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
@@ -62,6 +78,10 @@ static int sixaxis_usb_output_raw_report(struct hid_device *hid, __u8 *buf,
                interface->desc.bInterfaceNumber, buf, count,
                USB_CTRL_SET_TIMEOUT);
 
+       /* Count also the Report ID, in case of an Output report. */
+       if (ret > 0 && report_type == HID_OUTPUT_REPORT)
+               ret++;
+
        return ret;
 }