Sat Jul 30 12:15:44 2011 UTC ()
add support for game controllers in "XInput" mode, they are basically
HID devices without a report descriptor


(jmcneill)
diff -r1.50 -r1.51 src/sys/dev/usb/uhidev.c
diff -r0 -r1.1 src/sys/dev/usb/xinput_rdesc.h

cvs diff -r1.50 -r1.51 src/sys/dev/usb/uhidev.c (expand / switch to unified diff)

--- src/sys/dev/usb/uhidev.c 2011/07/20 19:27:53 1.50
+++ src/sys/dev/usb/uhidev.c 2011/07/30 12:15:44 1.51
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: uhidev.c,v 1.50 2011/07/20 19:27:53 ryoon Exp $ */ 1/* $NetBSD: uhidev.c,v 1.51 2011/07/30 12:15:44 jmcneill Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2001 The NetBSD Foundation, Inc. 4 * Copyright (c) 2001 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Lennart Augustsson (lennart@augustsson.net) at 8 * by Lennart Augustsson (lennart@augustsson.net) at
9 * Carlstedt Research & Technology. 9 * Carlstedt Research & Technology.
10 * 10 *
11 * Redistribution and use in source and binary forms, with or without 11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions 12 * modification, are permitted provided that the following conditions
13 * are met: 13 * are met:
14 * 1. Redistributions of source code must retain the above copyright 14 * 1. Redistributions of source code must retain the above copyright
@@ -25,50 +25,52 @@ @@ -25,50 +25,52 @@
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE. 30 * POSSIBILITY OF SUCH DAMAGE.
31 */ 31 */
32 32
33/* 33/*
34 * HID spec: http://www.usb.org/developers/devclass_docs/HID1_11.pdf 34 * HID spec: http://www.usb.org/developers/devclass_docs/HID1_11.pdf
35 */ 35 */
36 36
37#include <sys/cdefs.h> 37#include <sys/cdefs.h>
38__KERNEL_RCSID(0, "$NetBSD: uhidev.c,v 1.50 2011/07/20 19:27:53 ryoon Exp $"); 38__KERNEL_RCSID(0, "$NetBSD: uhidev.c,v 1.51 2011/07/30 12:15:44 jmcneill Exp $");
39 39
40#include <sys/param.h> 40#include <sys/param.h>
41#include <sys/systm.h> 41#include <sys/systm.h>
42#include <sys/kernel.h> 42#include <sys/kernel.h>
43#include <sys/malloc.h> 43#include <sys/malloc.h>
44#include <sys/signalvar.h> 44#include <sys/signalvar.h>
45#include <sys/device.h> 45#include <sys/device.h>
46#include <sys/ioctl.h> 46#include <sys/ioctl.h>
47#include <sys/conf.h> 47#include <sys/conf.h>
48 48
49#include <dev/usb/usb.h> 49#include <dev/usb/usb.h>
50#include <dev/usb/usbhid.h> 50#include <dev/usb/usbhid.h>
51 51
52#include <dev/usb/usbdevs.h> 52#include <dev/usb/usbdevs.h>
53#include <dev/usb/usbdi.h> 53#include <dev/usb/usbdi.h>
54#include <dev/usb/usbdi_util.h> 54#include <dev/usb/usbdi_util.h>
55#include <dev/usb/hid.h> 55#include <dev/usb/hid.h>
56#include <dev/usb/usb_quirks.h> 56#include <dev/usb/usb_quirks.h>
57 57
58#include <dev/usb/uhidev.h> 58#include <dev/usb/uhidev.h>
59 59
60/* Report descriptor for broken Wacom Graphire */ 60/* Report descriptor for broken Wacom Graphire */
61#include <dev/usb/ugraphire_rdesc.h> 61#include <dev/usb/ugraphire_rdesc.h>
 62/* Report descriptor for game controllers in "XInput" mode */
 63#include <dev/usb/xinput_rdesc.h>
62 64
63#include "locators.h" 65#include "locators.h"
64 66
65#ifdef UHIDEV_DEBUG 67#ifdef UHIDEV_DEBUG
66#define DPRINTF(x) if (uhidevdebug) printf x 68#define DPRINTF(x) if (uhidevdebug) printf x
67#define DPRINTFN(n,x) if (uhidevdebug>(n)) printf x 69#define DPRINTFN(n,x) if (uhidevdebug>(n)) printf x
68int uhidevdebug = 0; 70int uhidevdebug = 0;
69#else 71#else
70#define DPRINTF(x) 72#define DPRINTF(x)
71#define DPRINTFN(n,x) 73#define DPRINTFN(n,x)
72#endif 74#endif
73 75
74Static void uhidev_intr(usbd_xfer_handle, usbd_private_handle, usbd_status); 76Static void uhidev_intr(usbd_xfer_handle, usbd_private_handle, usbd_status);
@@ -80,26 +82,29 @@ int uhidev_match(device_t, cfdata_t, voi @@ -80,26 +82,29 @@ int uhidev_match(device_t, cfdata_t, voi
80void uhidev_attach(device_t, device_t, void *); 82void uhidev_attach(device_t, device_t, void *);
81void uhidev_childdet(device_t, device_t); 83void uhidev_childdet(device_t, device_t);
82int uhidev_detach(device_t, int); 84int uhidev_detach(device_t, int);
83int uhidev_activate(device_t, enum devact); 85int uhidev_activate(device_t, enum devact);
84extern struct cfdriver uhidev_cd; 86extern struct cfdriver uhidev_cd;
85CFATTACH_DECL2_NEW(uhidev, sizeof(struct uhidev_softc), uhidev_match, 87CFATTACH_DECL2_NEW(uhidev, sizeof(struct uhidev_softc), uhidev_match,
86 uhidev_attach, uhidev_detach, uhidev_activate, NULL, uhidev_childdet); 88 uhidev_attach, uhidev_detach, uhidev_activate, NULL, uhidev_childdet);
87 89
88int  90int
89uhidev_match(device_t parent, cfdata_t match, void *aux) 91uhidev_match(device_t parent, cfdata_t match, void *aux)
90{ 92{
91 struct usbif_attach_arg *uaa = aux; 93 struct usbif_attach_arg *uaa = aux;
92 94
 95 /* Game controllers in "XInput" mode */
 96 if (USBIF_IS_XINPUT(uaa))
 97 return UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO;
93 if (uaa->class != UICLASS_HID) 98 if (uaa->class != UICLASS_HID)
94 return (UMATCH_NONE); 99 return (UMATCH_NONE);
95 if (usbd_get_quirks(uaa->device)->uq_flags & UQ_HID_IGNORE) 100 if (usbd_get_quirks(uaa->device)->uq_flags & UQ_HID_IGNORE)
96 return (UMATCH_NONE); 101 return (UMATCH_NONE);
97 return (UMATCH_IFACECLASS_GENERIC); 102 return (UMATCH_IFACECLASS_GENERIC);
98} 103}
99 104
100void  105void
101uhidev_attach(device_t parent, device_t self, void *aux) 106uhidev_attach(device_t parent, device_t self, void *aux)
102{ 107{
103 struct uhidev_softc *sc = device_private(self); 108 struct uhidev_softc *sc = device_private(self);
104 struct usbif_attach_arg *uaa = aux; 109 struct usbif_attach_arg *uaa = aux;
105 usbd_interface_handle iface = uaa->iface; 110 usbd_interface_handle iface = uaa->iface;
@@ -203,26 +208,30 @@ uhidev_attach(device_t parent, device_t  @@ -203,26 +208,30 @@ uhidev_attach(device_t parent, device_t
203 * returning digitizer data. 208 * returning digitizer data.
204 */ 209 */
205 usbd_set_report(uaa->iface, UHID_FEATURE_REPORT, 2, 210 usbd_set_report(uaa->iface, UHID_FEATURE_REPORT, 2,
206 &reportbuf, sizeof reportbuf); 211 &reportbuf, sizeof reportbuf);
207 212
208 size = sizeof uhid_graphire3_4x5_report_descr; 213 size = sizeof uhid_graphire3_4x5_report_descr;
209 descptr = uhid_graphire3_4x5_report_descr; 214 descptr = uhid_graphire3_4x5_report_descr;
210 break; 215 break;
211 default: 216 default:
212 /* Keep descriptor */ 217 /* Keep descriptor */
213 break; 218 break;
214 } 219 }
215 } 220 }
 221 if (USBIF_IS_XINPUT(uaa)) {
 222 size = sizeof uhid_xinput_report_descr;
 223 descptr = uhid_xinput_report_descr;
 224 }
216 225
217 if (descptr) { 226 if (descptr) {
218 desc = malloc(size, M_USBDEV, M_NOWAIT); 227 desc = malloc(size, M_USBDEV, M_NOWAIT);
219 if (desc == NULL) 228 if (desc == NULL)
220 err = USBD_NOMEM; 229 err = USBD_NOMEM;
221 else { 230 else {
222 err = USBD_NORMAL_COMPLETION; 231 err = USBD_NORMAL_COMPLETION;
223 memcpy(desc, descptr, size); 232 memcpy(desc, descptr, size);
224 } 233 }
225 } else { 234 } else {
226 desc = NULL; 235 desc = NULL;
227 err = usbd_read_report_desc(uaa->iface, &desc, &size, 236 err = usbd_read_report_desc(uaa->iface, &desc, &size,
228 M_USBDEV); 237 M_USBDEV);

File Added: src/sys/dev/usb/xinput_rdesc.h
/* $NetBSD: xinput_rdesc.h,v 1.1 2011/07/30 12:15:44 jmcneill Exp $ */

/*-
 * Copyright (c) 2011 Jared D. McNeill <jmcneill@invisible.ca>
 * 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 FOUNDATION 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.
 */

/*
 * Descriptor from http://euc.jp/periphs/xbox-pad-report-desc.txt
 */

#define	USBIF_IS_XINPUT(uaa)			\
	((uaa)->class == UICLASS_VENDOR && 	\
	 (uaa)->subclass == 0x5d &&		\
	 (uaa)->proto == 0x01)

static const uByte uhid_xinput_report_descr[] = {
    0x05, 0x01,		/* Usage Page (Generic Desktop) */
    0x09, 0x05,		/* Usage (Game Pad) */
    0xa1, 0x01,		/* Collection (Application) */
    0x05, 0x01,		/* Usage Page (Generic Desktop) */
    0x09, 0x3a,		/* Usage (Counted Buffer) */
    0xa1, 0x02,		/* Collection (Logical) */
    0x75, 0x08,		/* Report Size (8) */
    0x95, 0x01,		/* Report Count (1) */
    0x81, 0x01,		/* Input (Constant) */
    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) */
    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 */
    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, 0x07,		/* Usage Minimum (Button 7) */
    0x29, 0x0a,		/* Usage Maximum (Button 10) */
    0x81, 0x02,		/* Input (Data,Variable,Absolute) */
    0x75, 0x01,		/* Report Size (1) */
    0x95, 0x08,		/* Report Count (8) */
    0x81, 0x01,		/* Input (Constant) */
    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, 0x06,		/* Report Count (6) */
    0x05, 0x09,		/* Usage Page (Button) */
    0x19, 0x01,		/* Usage Minimum (Button 1) */
    0x29, 0x06,		/* Usage Minimum (Button 6) */
    0x81, 0x02,		/* Input (Data,Variable,Absolute) */
    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 Count (2) */
    0x05, 0x01,		/* Usage Page (Generic Desktop) */
    0x09, 0x32,		/* Usage (Z) */
    0x09, 0x35,		/* Usage (Rz) */
    0x81, 0x02,		/* Input (Data,Variable,Absolute) */
    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) */
    0x05, 0x01,		/* Usage Page (Generic Desktop) */
    0x09, 0x01,		/* Usage (Pointer) */
    0xa1, 0x00,		/* Collection (Physical) */
    0x95, 0x02,		/* Report Count (2) */
    0x05, 0x01,		/* Usage Page (Generic Desktop) */
    0x09, 0x30,		/* Usage (X) */
    0x09, 0x31,		/* Usage (Y) */
    0x81, 0x02,		/* Input (Data,Variable,Absolute) */
    0xc0,		/* End Collection */
    0x05, 0x01,		/* Usage Page (Generic Desktop) */
    0x09, 0x01,		/* Usage (Pointer) */
    0xa1, 0x00,		/* Collection (Physical) */
    0x95, 0x02,		/* Report Count (2) */
    0x05, 0x01,		/* Usage Page (Generic Desktop) */
    0x09, 0x33,		/* Usage (Rx) */
    0x09, 0x34,		/* Usage (Ry) */
    0x81, 0x02,		/* Input (Data,Variable,Absolute) */
    0xc0,		/* End Collection */
    0xc0,		/* End Collection */
    0x05, 0x01,		/* Usage Page (Generic Desktop) */
    0x09, 0x3a,		/* Usage (Counted Buffer) */
    0xa1, 0x02,		/* Collection (Logical) */
    0x75, 0x08,		/* Report Size (8) */
    0x95, 0x01,		/* Report Count (1) */
    0x91, 0x01,		/* Output (Constant) */
    0x75, 0x08,		/* Report Size (8) */
    0x95, 0x01,		/* Report Count (1) */
    0x05, 0x01,		/* Usage Page (Generic Desktop) */
    0x09, 0x3b,		/* Usage (Byte Count) */
    0x91, 0x01,		/* Output (Constant) */
    0x75, 0x08,		/* Report Size (8) */
    0x95, 0x01,		/* Report Count (1) */
    0x91, 0x01,		/* Output (Constant) */
    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, 0x01,		/* Report Count (1) */
    0x06, 0x00, 0xff,	/* Usage Page (vendor-defined) */
    0x09, 0x01,		/* Usage (1) */
    0x91, 0x02,		/* Output (Data,Variable,Absolute) */
    0x75, 0x08,		/* Report Size (8) */
    0x95, 0x01,		/* Report Count (1) */
    0x91, 0x01,		/* Output (Constant) */
    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, 0x01,		/* Report Count (1) */
    0x06, 0x00, 0xff,	/* Usage Page (vendor-defined) */
    0x09, 0x02,		/* Usage (2) */
    0x91, 0x02,		/* Output (Data,Variable,Absolute) */
    0xc0,		/* End Collection */
    0xc0,		/* End Collection */
};