On 10/20 03:52, Martin Pieuchot wrote:
> Hi Jeremy,
> 
> On 18/10/13(Fri) 09:11, Jeremy Evans wrote:
> > This was originally submitted by Joe Gidi in November 2010, based on a
> > FreeBSD commit by Ed Schouten from back in December 2005.  See
> > http://marc.info/?l=openbsd-tech&m=128924886803756&w=2 for previous
> > thread.  The only comment was from tedu@, that SMALL_KERNEL should be
> > added, which I've done but I'm not sure correctly.
> > 
> > Tested on amd64 using usbhidctl and some SDL-based emulators (mednafen,
> > snes9x-gtk, desmume).  The controller works fine except that the
> > directional pad is not processed as a hat but as a series of buttons
> > (that usbhidctl sees but SDL seems not to recognize).  Also, the bottom
> > L/R triggers are axes instead of buttons.
> > 
> > I've built a release with this, and checked that the amd64 floppy
> > still fits.
> 
> Good stuff, some comments below.

Martin,

Thanks for responding.  Here's a new diff that incorporates most of your
suggestions.  Unfortunately, using the existing quirks infrastructure
doesn't work correctly, because the quirks API is based on device
manufacturer and vendor, and matching on that instead of interface
subclass and protocol appears to not work correctly.  When you plug in
the controller with my original diff and the first diff below, you get:

uhidev0 at uhub3 port 3 configuration 1 interface 0 "\M-)Microsoft Corporation 
Controller" rev 2.00/1.10 addr 2
uhidev0: iclass 255/93
uhid0 at uhidev0: input=20, output=0, feature=0
ugen0 at uhub3 port 3 configuration 1 "\M-)Microsoft Corporation Controller" 
rev 2.00/1.10 addr 2
 
As you can see, the controller shows up as both a uhid and a ugen.

With the second diff below, when you plugin the controller, it
attaches as follows:

uhidev0 at uhub3 port 3 configuration 1 interface 0 "\M-)Microsoft Corporation 
Controller" rev 2.00/1.10 addr 2
uhidev0: iclass 255/93
uhid0 at uhidev0: input=20, output=0, feature=0
uhidev1 at uhub3 port 3 configuration 1 interface 1 "\M-)Microsoft Corporation 
Controller" rev 2.00/1.10 addr 2
uhidev1: iclass 255/93
uhid1 at uhidev1: input=20, output=0, feature=0
uhidev2 at uhub3 port 3 configuration 1 interface 2 "\M-)Microsoft Corporation 
Controller" rev 2.00/1.10 addr 2
uhidev2: iclass 255/93
uhid2 at uhidev2: input=20, output=0, feature=0
uhidev3 at uhub3 port 3 configuration 1 interface 3 "\M-)Microsoft Corporation 
Controller" rev 2.00/1.10 addr 2
uhidev3: no input interrupt endpoint

In this case uhid0 appears to work, but uhid1 and uhid2 do not:

$ usbhidctl -f 1 -a 
usbhidctl: USB_GET_REPORT (probably not supported by device): Input/output error

Anyway, let me know what you think about the first diff, or if I'm doing
something wrong with the second diff that is causing it to attach
multiple times.

Thanks,
Jeremy

Working diff:

Index: uhidev.c
===================================================================
RCS file: /cvs/src/sys/dev/usb/uhidev.c,v
retrieving revision 1.46
diff -u -p -r1.46 uhidev.c
--- uhidev.c    20 Sep 2013 15:34:50 -0000      1.46
+++ uhidev.c    20 Oct 2013 18:23:37 -0000
@@ -55,8 +55,13 @@
 
 #include <dev/usb/uhidev.h>
 
-/* Report descriptor for broken Wacom Graphire */
+#ifndef SMALL_KERNEL
+/* Replacement report descriptors for devices shipped with broken ones */
 #include <dev/usb/ugraphire_rdesc.h>
+#include <dev/usb/uxb360gp_rdesc.h>
+#define        UISUBCLASS_XBOX360_CONTROLLER   0x5d
+#define        UIPROTO_XBOX360_GAMEPAD         0x01
+#endif /* !SMALL_KERNEL */
 
 #ifdef UHIDEV_DEBUG
 #define DPRINTF(x)     do { if (uhidevdebug) printf x; } while (0)
@@ -99,8 +104,17 @@ uhidev_match(struct device *parent, void
        if (uaa->iface == NULL)
                return (UMATCH_NONE);
        id = usbd_get_interface_descriptor(uaa->iface);
-       if (id == NULL || id->bInterfaceClass != UICLASS_HID)
-               return (UMATCH_NONE);
+        if (id == NULL)
+                return (UMATCH_NONE);
+        if  (id->bInterfaceClass != UICLASS_HID) {
+#ifndef SMALL_KERNEL
+                /* The Xbox 360 gamepad doesn't use the HID class. */
+                if (id->bInterfaceClass != UICLASS_VENDOR ||
+                    id->bInterfaceSubClass != UISUBCLASS_XBOX360_CONTROLLER ||
+                    id->bInterfaceProtocol != UIPROTO_XBOX360_GAMEPAD)
+#endif /* !SMALL_KERNEL */
+                        return (UMATCH_NONE);
+        }
        if (usbd_get_quirks(uaa->device)->uq_flags & UQ_BAD_HID)
                return (UMATCH_NONE);
        if (uaa->matchlvl)
@@ -180,6 +194,7 @@ uhidev_attach(struct device *parent, str
 
        /* XXX need to extend this */
        descptr = NULL;
+#ifndef SMALL_KERNEL
        if (uaa->vendor == USB_VENDOR_WACOM) {
                static uByte reportbuf[] = {2, 2, 2};
 
@@ -200,7 +215,15 @@ uhidev_attach(struct device *parent, str
                        /* Keep descriptor */
                        break;
                }
+       } else if (id->bInterfaceClass == UICLASS_VENDOR &&
+           id->bInterfaceSubClass == UISUBCLASS_XBOX360_CONTROLLER &&
+           id->bInterfaceProtocol == UIPROTO_XBOX360_GAMEPAD) {
+               /* The Xbox 360 gamepad has no report descriptor. */
+               size = sizeof uhid_xb360gp_report_descr;
+               descptr = uhid_xb360gp_report_descr;
        }
+#endif /* !SMALL_KERNEL */
+
 
        if (descptr) {
                desc = malloc(size, M_USBDEV, M_NOWAIT);
Index: uxb360gp_rdesc.h
===================================================================
RCS file: uxb360gp_rdesc.h
diff -N uxb360gp_rdesc.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ uxb360gp_rdesc.h    20 Oct 2013 18:24:41 -0000
@@ -0,0 +1,125 @@
+/* $OpenBSD$ */
+/*-
+ * Copyright (c) 2005 Ed Schouten <e...@freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/dev/usb/uxb360gp_rdesc.h,v 1.3 2008/05/24 18:35:55 ed Exp 
$
+ */
+
+/*
+ * The descriptor has no output report format, thus preventing you from
+ * controlling the LEDs and the built-in rumblers.
+ */
+static const uByte uhid_xb360gp_report_descr[] = {
+    0x05, 0x01,                /* USAGE PAGE (Generic Desktop)         */
+    0x09, 0x05,                /* USAGE (Gamepad)                      */
+    0xa1, 0x01,                /* COLLECTION (Application)             */
+    /* Unused */
+    0x75, 0x08,                /*  REPORT SIZE (8)                     */
+    0x95, 0x01,                /*  REPORT COUNT (1)                    */
+    0x81, 0x01,                /*  INPUT (Constant)                    */
+    /* Byte count */
+    0x75, 0x08,                /*  REPORT SIZE (8)                     */
+    0x95, 0x01,                /*  REPORT COUNT (1)                    */
+    0x05, 0x01,                /*  USAGE PAGE (Generic Desktop)        */
+    0x09, 0x3b,                /*  USAGE (Byte Count)                  */
+    0x81, 0x01,                /*  INPUT (Constant)                    */
+    /* D-Pad */
+    0x05, 0x01,                /*  USAGE PAGE (Generic Desktop)        */
+    0x09, 0x01,                /*  USAGE (Pointer)                     */
+    0xa1, 0x00,                /*  COLLECTION (Physical)               */
+    0x75, 0x01,                /*   REPORT SIZE (1)                    */
+    0x15, 0x00,                /*   LOGICAL MINIMUM (0)                */
+    0x25, 0x01,                /*   LOGICAL MAXIMUM (1)                */
+    0x35, 0x00,                /*   PHYSICAL MINIMUM (0)               */
+    0x45, 0x01,                /*   PHYSICAL MAXIMUM (1)               */
+    0x95, 0x04,                /*   REPORT COUNT (4)                   */
+    0x05, 0x01,                /*   USAGE PAGE (Generic Desktop)       */
+    0x09, 0x90,                /*   USAGE (D-Pad Up)                   */
+    0x09, 0x91,                /*   USAGE (D-Pad Down)                 */
+    0x09, 0x93,                /*   USAGE (D-Pad Left)                 */
+    0x09, 0x92,                /*   USAGE (D-Pad Right)                */
+    0x81, 0x02,                /*   INPUT (Data, Variable, Absolute)   */
+    0xc0,              /*  END COLLECTION                      */
+    /* Buttons 5-11 */
+    0x75, 0x01,                /*  REPORT SIZE (1)                     */
+    0x15, 0x00,                /*  LOGICAL MINIMUM (0)                 */
+    0x25, 0x01,                /*  LOGICAL MAXIMUM (1)                 */
+    0x35, 0x00,                /*  PHYSICAL MINIMUM (0)                */
+    0x45, 0x01,                /*  PHYSICAL MAXIMUM (1)                */
+    0x95, 0x07,                /*  REPORT COUNT (7)                    */
+    0x05, 0x09,                /*  USAGE PAGE (Button)                 */
+    0x09, 0x08,                /*  USAGE (Button 8)                    */
+    0x09, 0x07,                /*  USAGE (Button 7)                    */
+    0x09, 0x09,                /*  USAGE (Button 9)                    */
+    0x09, 0x0a,                /*  USAGE (Button 10)                   */
+    0x09, 0x05,                /*  USAGE (Button 5)                    */
+    0x09, 0x06,                /*  USAGE (Button 6)                    */
+    0x09, 0x0b,                /*  USAGE (Button 11)                   */
+    0x81, 0x02,                /*  INPUT (Data, Variable, Absolute)    */
+    /* Unused */
+    0x75, 0x01,                /*  REPORT SIZE (1)                     */
+    0x95, 0x01,                /*  REPORT COUNT (1)                    */
+    0x81, 0x01,                /*  INPUT (Constant)                    */
+    /* Buttons 1-4 */
+    0x75, 0x01,                /*  REPORT SIZE (1)                     */
+    0x15, 0x00,                /*  LOGICAL MINIMUM (0)                 */
+    0x25, 0x01,                /*  LOGICAL MAXIMUM (1)                 */
+    0x35, 0x00,                /*  PHYSICAL MINIMUM (0)                */
+    0x45, 0x01,                /*  PHYSICAL MAXIMUM (1)                */
+    0x95, 0x04,                /*  REPORT COUNT (4)                    */
+    0x05, 0x09,                /*  USAGE PAGE (Button)                 */
+    0x19, 0x01,                /*  USAGE MINIMUM (Button 1)            */
+    0x29, 0x04,                /*  USAGE MAXIMUM (Button 4)            */
+    0x81, 0x02,                /*  INPUT (Data, Variable, Absolute)    */
+    /* Triggers */
+    0x75, 0x08,                /*  REPORT SIZE (8)                     */
+    0x15, 0x00,                /*  LOGICAL MINIMUM (0)                 */
+    0x26, 0xff, 0x00,  /*  LOGICAL MAXIMUM (255)               */
+    0x35, 0x00,                /*  PHYSICAL MINIMUM (0)                */
+    0x46, 0xff, 0x00,  /*  PHYSICAL MAXIMUM (255)              */
+    0x95, 0x02,                /*  REPORT SIZE (2)                     */
+    0x05, 0x01,                /*  USAGE PAGE (Generic Desktop)        */
+    0x09, 0x32,                /*  USAGE (Z)                           */
+    0x09, 0x35,                /*  USAGE (Rz)                          */
+    0x81, 0x02,                /*  INPUT (Data, Variable, Absolute)    */
+    /* Sticks */
+    0x75, 0x10,                /*  REPORT SIZE (16)                    */
+    0x16, 0x00, 0x80,  /*  LOGICAL MINIMUM (-32768)            */
+    0x26, 0xff, 0x7f,  /*  LOGICAL MAXIMUM (32767)             */
+    0x36, 0x00, 0x80,  /*  PHYSICAL MINIMUM (-32768)           */
+    0x46, 0xff, 0x7f,  /*  PHYSICAL MAXIMUM (32767)            */
+    0x95, 0x04,                /*  REPORT COUNT (4)                    */
+    0x05, 0x01,                /*  USAGE PAGE (Generic Desktop)        */
+    0x09, 0x30,                /*  USAGE (X)                           */
+    0x09, 0x31,                /*  USAGE (Y)                           */
+    0x09, 0x33,                /*  USAGE (Rx)                          */
+    0x09, 0x34,                /*  USAGE (Ry)                          */
+    0x81, 0x02,                /*  INPUT (Data, Variable, Absolute)    */
+    /* Unused */
+    0x75, 0x30,                /*  REPORT SIZE (48)                    */
+    0x95, 0x01,                /*  REPORT COUNT (1)                    */
+    0x81, 0x01,                /*  INPUT (Constant)                    */
+    0xc0,              /* END COLLECTION                       */
+};


Broken diff using quirks:

Index: uhidev.c
===================================================================
RCS file: /cvs/src/sys/dev/usb/uhidev.c,v
retrieving revision 1.46
diff -u -p -r1.46 uhidev.c
--- uhidev.c    20 Sep 2013 15:34:50 -0000      1.46
+++ uhidev.c    20 Oct 2013 17:21:47 -0000
@@ -55,8 +55,11 @@
 
 #include <dev/usb/uhidev.h>
 
-/* Report descriptor for broken Wacom Graphire */
+#ifndef SMALL_KERNEL
+/* Replacement report descriptors for devices shipped with broken ones */
 #include <dev/usb/ugraphire_rdesc.h>
+#include <dev/usb/uxb360gp_rdesc.h>
+#endif /* !SMALL_KERNEL */
 
 #ifdef UHIDEV_DEBUG
 #define DPRINTF(x)     do { if (uhidevdebug) printf x; } while (0)
@@ -99,9 +102,14 @@ uhidev_match(struct device *parent, void
        if (uaa->iface == NULL)
                return (UMATCH_NONE);
        id = usbd_get_interface_descriptor(uaa->iface);
-       if (id == NULL || id->bInterfaceClass != UICLASS_HID)
+       if (id == NULL)
                return (UMATCH_NONE);
-       if (usbd_get_quirks(uaa->device)->uq_flags & UQ_BAD_HID)
+       if  (id->bInterfaceClass != UICLASS_HID) {
+#ifndef SMALL_KERNEL
+               if (!(usbd_get_quirks(uaa->device)->uq_flags & UQ_FORCE_HID))
+#endif /* !SMALL_KERNEL */
+                       return (UMATCH_NONE);
+       } else if (usbd_get_quirks(uaa->device)->uq_flags & UQ_BAD_HID)
                return (UMATCH_NONE);
        if (uaa->matchlvl)
                return (uaa->matchlvl);
@@ -180,6 +188,7 @@ uhidev_attach(struct device *parent, str
 
        /* XXX need to extend this */
        descptr = NULL;
+#ifndef SMALL_KERNEL
        if (uaa->vendor == USB_VENDOR_WACOM) {
                static uByte reportbuf[] = {2, 2, 2};
 
@@ -200,7 +209,13 @@ uhidev_attach(struct device *parent, str
                        /* Keep descriptor */
                        break;
                }
+       } else if (uaa->vendor == USB_VENDOR_MICROSOFT &&
+           uaa->product == USB_PRODUCT_MICROSOFT_XBOX360_CONTROLLER) {
+               /* The Xbox 360 gamepad has no report descriptor. */
+               size = sizeof uhid_xb360gp_report_descr;
+               descptr = uhid_xb360gp_report_descr;
        }
+#endif /* !SMALL_KERNEL */
 
        if (descptr) {
                desc = malloc(size, M_USBDEV, M_NOWAIT);
Index: usb_quirks.c
===================================================================
RCS file: /cvs/src/sys/dev/usb/usb_quirks.c,v
retrieving revision 1.68
diff -u -p -r1.68 usb_quirks.c
--- usb_quirks.c        8 Mar 2013 02:21:43 -0000       1.68
+++ usb_quirks.c        20 Oct 2013 16:48:30 -0000
@@ -171,6 +171,10 @@ const struct usbd_quirk_entry {
        ANY, { UQ_MS_BAD_CLASS | UQ_MS_LEADING_BYTE }},
  { USB_VENDOR_MICROSOFT, USB_PRODUCT_MICROSOFT_WLNOTEBOOK2,
        ANY, { UQ_MS_BAD_CLASS | UQ_MS_LEADING_BYTE }},
+#ifndef SMALL_KERNEL
+ { USB_VENDOR_MICROSOFT, USB_PRODUCT_MICROSOFT_XBOX360_CONTROLLER,
+       ANY, { UQ_FORCE_HID }},
+#endif /* !SMALL_KERNEL */
 
  { 0, 0, 0, { 0 } }
 };
Index: usb_quirks.h
===================================================================
RCS file: /cvs/src/sys/dev/usb/usb_quirks.h,v
retrieving revision 1.16
diff -u -p -r1.16 usb_quirks.h
--- usb_quirks.h        19 Jul 2010 05:08:37 -0000      1.16
+++ usb_quirks.h        20 Oct 2013 16:24:07 -0000
@@ -49,6 +49,7 @@ struct usbd_quirks {
 #define UQ_MS_LEADING_BYTE     0x00010000 /* mouse sends unknown leading byte 
*/
 #define UQ_EHCI_NEEDTO_DISOWN  0x00020000 /* must hand device over to USB 1.1
                                                if attached to EHCI */
+#define UQ_FORCE_HID           0x00040000 /* device claims not uhid, but is */
 };
 
 extern const struct usbd_quirks usbd_no_quirk;
Index: usbdevs.h
===================================================================
RCS file: /cvs/src/sys/dev/usb/usbdevs.h,v
retrieving revision 1.618
diff -u -p -r1.618 usbdevs.h
--- usbdevs.h   7 Oct 2013 05:39:11 -0000       1.618
+++ usbdevs.h   20 Oct 2013 16:40:21 -0000
@@ -2868,6 +2868,7 @@
 #define        USB_PRODUCT_MICROSOFT_WLNOTEBOOK        0x00b9          /* 
Wireless Optical Mouse (Model 1023) */
 #define        USB_PRODUCT_MICROSOFT_WLNOTEBOOK3       0x00d2          /* 
Wireless Optical Mouse 3000 (Model 1049) */
 #define        USB_PRODUCT_MICROSOFT_WLNOTEBOOK2       0x00e1          /* 
Wireless Optical Mouse 3000 (Model 1056) */
+#define        USB_PRODUCT_MICROSOFT_XBOX360_CONTROLLER        0x028e          
/* XBOX 360 Controller */
 #define        USB_PRODUCT_MICROSOFT_XBOX360   0x0292          /* XBOX 360 
WLAN */
 #define        USB_PRODUCT_MICROSOFT_LIFECAM   0x074a          /* Microsoft 
LifeCam */
 
Index: uxb360gp_rdesc.h
===================================================================
RCS file: uxb360gp_rdesc.h
diff -N uxb360gp_rdesc.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ uxb360gp_rdesc.h    20 Oct 2013 16:59:26 -0000
@@ -0,0 +1,125 @@
+/*      $OpenBSD$ */
+/*-
+ * Copyright (c) 2005 Ed Schouten <e...@freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/dev/usb/uxb360gp_rdesc.h,v 1.3 2008/05/24 18:35:55 ed Exp 
$
+ */
+
+/*
+ * The descriptor has no output report format, thus preventing you from
+ * controlling the LEDs and the built-in rumblers.
+ */
+static const uByte uhid_xb360gp_report_descr[] = {
+    0x05, 0x01,                /* USAGE PAGE (Generic Desktop)         */
+    0x09, 0x05,                /* USAGE (Gamepad)                      */
+    0xa1, 0x01,                /* COLLECTION (Application)             */
+    /* Unused */
+    0x75, 0x08,                /*  REPORT SIZE (8)                     */
+    0x95, 0x01,                /*  REPORT COUNT (1)                    */
+    0x81, 0x01,                /*  INPUT (Constant)                    */
+    /* Byte count */
+    0x75, 0x08,                /*  REPORT SIZE (8)                     */
+    0x95, 0x01,                /*  REPORT COUNT (1)                    */
+    0x05, 0x01,                /*  USAGE PAGE (Generic Desktop)        */
+    0x09, 0x3b,                /*  USAGE (Byte Count)                  */
+    0x81, 0x01,                /*  INPUT (Constant)                    */
+    /* D-Pad */
+    0x05, 0x01,                /*  USAGE PAGE (Generic Desktop)        */
+    0x09, 0x01,                /*  USAGE (Pointer)                     */
+    0xa1, 0x00,                /*  COLLECTION (Physical)               */
+    0x75, 0x01,                /*   REPORT SIZE (1)                    */
+    0x15, 0x00,                /*   LOGICAL MINIMUM (0)                */
+    0x25, 0x01,                /*   LOGICAL MAXIMUM (1)                */
+    0x35, 0x00,                /*   PHYSICAL MINIMUM (0)               */
+    0x45, 0x01,                /*   PHYSICAL MAXIMUM (1)               */
+    0x95, 0x04,                /*   REPORT COUNT (4)                   */
+    0x05, 0x01,                /*   USAGE PAGE (Generic Desktop)       */
+    0x09, 0x90,                /*   USAGE (D-Pad Up)                   */
+    0x09, 0x91,                /*   USAGE (D-Pad Down)                 */
+    0x09, 0x93,                /*   USAGE (D-Pad Left)                 */
+    0x09, 0x92,                /*   USAGE (D-Pad Right)                */
+    0x81, 0x02,                /*   INPUT (Data, Variable, Absolute)   */
+    0xc0,              /*  END COLLECTION                      */
+    /* Buttons 5-11 */
+    0x75, 0x01,                /*  REPORT SIZE (1)                     */
+    0x15, 0x00,                /*  LOGICAL MINIMUM (0)                 */
+    0x25, 0x01,                /*  LOGICAL MAXIMUM (1)                 */
+    0x35, 0x00,                /*  PHYSICAL MINIMUM (0)                */
+    0x45, 0x01,                /*  PHYSICAL MAXIMUM (1)                */
+    0x95, 0x07,                /*  REPORT COUNT (7)                    */
+    0x05, 0x09,                /*  USAGE PAGE (Button)                 */
+    0x09, 0x08,                /*  USAGE (Button 8)                    */
+    0x09, 0x07,                /*  USAGE (Button 7)                    */
+    0x09, 0x09,                /*  USAGE (Button 9)                    */
+    0x09, 0x0a,                /*  USAGE (Button 10)                   */
+    0x09, 0x05,                /*  USAGE (Button 5)                    */
+    0x09, 0x06,                /*  USAGE (Button 6)                    */
+    0x09, 0x0b,                /*  USAGE (Button 11)                   */
+    0x81, 0x02,                /*  INPUT (Data, Variable, Absolute)    */
+    /* Unused */
+    0x75, 0x01,                /*  REPORT SIZE (1)                     */
+    0x95, 0x01,                /*  REPORT COUNT (1)                    */
+    0x81, 0x01,                /*  INPUT (Constant)                    */
+    /* Buttons 1-4 */
+    0x75, 0x01,                /*  REPORT SIZE (1)                     */
+    0x15, 0x00,                /*  LOGICAL MINIMUM (0)                 */
+    0x25, 0x01,                /*  LOGICAL MAXIMUM (1)                 */
+    0x35, 0x00,                /*  PHYSICAL MINIMUM (0)                */
+    0x45, 0x01,                /*  PHYSICAL MAXIMUM (1)                */
+    0x95, 0x04,                /*  REPORT COUNT (4)                    */
+    0x05, 0x09,                /*  USAGE PAGE (Button)                 */
+    0x19, 0x01,                /*  USAGE MINIMUM (Button 1)            */
+    0x29, 0x04,                /*  USAGE MAXIMUM (Button 4)            */
+    0x81, 0x02,                /*  INPUT (Data, Variable, Absolute)    */
+    /* Triggers */
+    0x75, 0x08,                /*  REPORT SIZE (8)                     */
+    0x15, 0x00,                /*  LOGICAL MINIMUM (0)                 */
+    0x26, 0xff, 0x00,  /*  LOGICAL MAXIMUM (255)               */
+    0x35, 0x00,                /*  PHYSICAL MINIMUM (0)                */
+    0x46, 0xff, 0x00,  /*  PHYSICAL MAXIMUM (255)              */
+    0x95, 0x02,                /*  REPORT SIZE (2)                     */
+    0x05, 0x01,                /*  USAGE PAGE (Generic Desktop)        */
+    0x09, 0x32,                /*  USAGE (Z)                           */
+    0x09, 0x35,                /*  USAGE (Rz)                          */
+    0x81, 0x02,                /*  INPUT (Data, Variable, Absolute)    */
+    /* Sticks */
+    0x75, 0x10,                /*  REPORT SIZE (16)                    */
+    0x16, 0x00, 0x80,  /*  LOGICAL MINIMUM (-32768)            */
+    0x26, 0xff, 0x7f,  /*  LOGICAL MAXIMUM (32767)             */
+    0x36, 0x00, 0x80,  /*  PHYSICAL MINIMUM (-32768)           */
+    0x46, 0xff, 0x7f,  /*  PHYSICAL MAXIMUM (32767)            */
+    0x95, 0x04,                /*  REPORT COUNT (4)                    */
+    0x05, 0x01,                /*  USAGE PAGE (Generic Desktop)        */
+    0x09, 0x30,                /*  USAGE (X)                           */
+    0x09, 0x31,                /*  USAGE (Y)                           */
+    0x09, 0x33,                /*  USAGE (Rx)                          */
+    0x09, 0x34,                /*  USAGE (Ry)                          */
+    0x81, 0x02,                /*  INPUT (Data, Variable, Absolute)    */
+    /* Unused */
+    0x75, 0x30,                /*  REPORT SIZE (48)                    */
+    0x95, 0x01,                /*  REPORT COUNT (1)                    */
+    0x81, 0x01,                /*  INPUT (Constant)                    */
+    0xc0,              /* END COLLECTION                       */
+};

Reply via email to