The previous thread[1] discussing these controllers includes two
patches but they seem to have been merged for the commit in a way
that limits support to only Microsoft controllers. 3rd party Xbox 360
controllers have their own vendor and product IDs but use the same
subclass and protocol as the Microsoft controllers.

Here's a diff based on the first patch that will match controllers
and assign the report descriptor more generally using subclass/protocol
rather than vendor/product. Is it more correct to create an array
of known vendors/products and match against a call to usb_lookup()?

[1] http://marc.info/?l=openbsd-tech&m=138229619410284&w=2

Thanks,
Christian


Index: uhidev.c
===================================================================
RCS file: /cvs/src/sys/dev/usb/uhidev.c,v
retrieving revision 1.70
diff -u -p -r1.70 uhidev.c
--- uhidev.c    28 Feb 2015 08:42:41 -0000      1.70
+++ uhidev.c    5 Dec 2015 20:14:49 -0000
@@ -62,7 +62,10 @@
 #ifndef SMALL_KERNEL
 /* Replacement report descriptors for devices shipped with broken ones */
 #include <dev/usb/uhid_rdesc.h>
-int uhidev_use_rdesc(struct uhidev_softc *, int, int, void **, int *);
+int uhidev_use_rdesc(struct uhidev_softc *, usb_interface_descriptor_t *,
+               int, int, void **, int *);
+#define UISUBCLASS_XBOX360_CONTROLLER 0x5d
+#define UIPROTO_XBOX360_GAMEPAD 0x01
 #endif /* !SMALL_KERNEL */
 
 #define DEVNAME(sc)            ((sc)->sc_dev.dv_xname)
@@ -118,10 +121,10 @@ uhidev_match(struct device *parent, void
        if (id == NULL)
                return (UMATCH_NONE);
 #ifndef SMALL_KERNEL
-       if (uaa->vendor == USB_VENDOR_MICROSOFT &&
-           uaa->product == USB_PRODUCT_MICROSOFT_XBOX360_CONTROLLER &&
-           id->bInterfaceNumber == 0)
-               return (UMATCH_VENDOR_PRODUCT);
+       if (id->bInterfaceClass == UICLASS_VENDOR &&
+           id->bInterfaceSubClass == UISUBCLASS_XBOX360_CONTROLLER &&
+           id->bInterfaceProtocol == UIPROTO_XBOX360_GAMEPAD)
+               return (UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO);
 #endif /* !SMALL_KERNEL */
        if (id->bInterfaceClass != UICLASS_HID)
                return (UMATCH_NONE);
@@ -191,7 +194,7 @@ uhidev_attach(struct device *parent, str
        }
 
 #ifndef SMALL_KERNEL
-       if (uhidev_use_rdesc(sc, uaa->vendor, uaa->product, &desc, &size))
+       if (uhidev_use_rdesc(sc, id, uaa->vendor, uaa->product, &desc, &size))
                return;
 #endif /* !SMALL_KERNEL */
 
@@ -275,8 +278,8 @@ uhidev_attach(struct device *parent, str
 
 #ifndef SMALL_KERNEL
 int
-uhidev_use_rdesc(struct uhidev_softc *sc, int vendor, int product,
-    void **descp, int *sizep)
+uhidev_use_rdesc(struct uhidev_softc *sc, usb_interface_descriptor_t *id,
+               int vendor, int product, void **descp, int *sizep)
 {
        static uByte reportbuf[] = {2, 2};
        const void *descptr = NULL;
@@ -300,8 +303,9 @@ uhidev_use_rdesc(struct uhidev_softc *sc
                default:
                        break;
                }
-       } else if (vendor == USB_VENDOR_MICROSOFT &&
-           product == USB_PRODUCT_MICROSOFT_XBOX360_CONTROLLER) {
+       } 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;

Reply via email to