The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/hid/xb360gp.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 2020 Vladimir Kondratyev <wulf@FreeBSD.org>
    5  * Copyright (c) 2020 Val Packett <val@packett.cool>
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   26  * SUCH DAMAGE.
   27  */
   28 
   29 #include <sys/cdefs.h>
   30 __FBSDID("$FreeBSD$");
   31 
   32 /*
   33  * XBox 360 gamepad driver thanks to the custom descriptor in usbhid.
   34  *
   35  * Tested on: SVEN GC-5070 in both XInput (XBox 360) and DirectInput modes
   36  */
   37 
   38 #include <sys/param.h>
   39 #include <sys/bus.h>
   40 #include <sys/kernel.h>
   41 #include <sys/module.h>
   42 #include <sys/sysctl.h>
   43 
   44 #include <dev/evdev/input.h>
   45 #include <dev/evdev/evdev.h>
   46 
   47 #include <dev/hid/hgame.h>
   48 #include <dev/hid/hid.h>
   49 #include <dev/hid/hidbus.h>
   50 #include <dev/hid/hidmap.h>
   51 #include <dev/hid/hidquirk.h>
   52 #include <dev/hid/hidrdesc.h>
   53 
   54 #include <dev/usb/usb.h>
   55 #include <dev/usb/usbdi.h>
   56 
   57 static const uint8_t    xb360gp_rdesc[] = {HID_XB360GP_REPORT_DESCR()};
   58 
   59 #define XB360GP_MAP_BUT(number, code)   \
   60         { HIDMAP_KEY(HUP_BUTTON, number, code) }
   61 #define XB360GP_MAP_ABS(usage, code)    \
   62         { HIDMAP_ABS(HUP_GENERIC_DESKTOP, HUG_##usage, code) }
   63 #define XB360GP_MAP_ABS_FLT(usage, code)        \
   64         { HIDMAP_ABS(HUP_GENERIC_DESKTOP, HUG_##usage, code),   \
   65             .fuzz = 16, .flat = 128 }
   66 #define XB360GP_MAP_ABS_INV(usage, code)        \
   67         { HIDMAP_ABS(HUP_GENERIC_DESKTOP, HUG_##usage, code),   \
   68             .fuzz = 16, .flat = 128, .invert_value = true }
   69 #define XB360GP_MAP_CRG(usage_from, usage_to, callback) \
   70         { HIDMAP_ANY_CB_RANGE(HUP_GENERIC_DESKTOP,      \
   71             HUG_##usage_from, HUG_##usage_to, callback) }
   72 #define XB360GP_FINALCB(cb)             \
   73         { HIDMAP_FINAL_CB(&cb) }
   74 
   75 /* Customized to match usbhid's XBox 360 descriptor */
   76 static const struct hidmap_item xb360gp_map[] = {
   77         XB360GP_MAP_BUT(1,              BTN_SOUTH),
   78         XB360GP_MAP_BUT(2,              BTN_EAST),
   79         XB360GP_MAP_BUT(3,              BTN_WEST),
   80         XB360GP_MAP_BUT(4,              BTN_NORTH),
   81         XB360GP_MAP_BUT(5,              BTN_TL),
   82         XB360GP_MAP_BUT(6,              BTN_TR),
   83         XB360GP_MAP_BUT(7,              BTN_SELECT),
   84         XB360GP_MAP_BUT(8,              BTN_START),
   85         XB360GP_MAP_BUT(9,              BTN_THUMBL),
   86         XB360GP_MAP_BUT(10,             BTN_THUMBR),
   87         XB360GP_MAP_BUT(11,             BTN_MODE),
   88         XB360GP_MAP_CRG(D_PAD_UP, D_PAD_LEFT, hgame_dpad_cb),
   89         XB360GP_MAP_ABS_FLT(X,          ABS_X),
   90         XB360GP_MAP_ABS_INV(Y,          ABS_Y),
   91         XB360GP_MAP_ABS(Z,              ABS_Z),
   92         XB360GP_MAP_ABS_FLT(RX,         ABS_RX),
   93         XB360GP_MAP_ABS_INV(RY,         ABS_RY),
   94         XB360GP_MAP_ABS(RZ,             ABS_RZ),
   95         XB360GP_FINALCB(                hgame_final_cb),
   96 };
   97 
   98 static const STRUCT_USB_HOST_ID xb360gp_devs[] = {
   99         /* the Xbox 360 gamepad doesn't use the HID class */
  100         {USB_IFACE_CLASS(UICLASS_VENDOR),
  101          USB_IFACE_SUBCLASS(UISUBCLASS_XBOX360_CONTROLLER),
  102          USB_IFACE_PROTOCOL(UIPROTO_XBOX360_GAMEPAD),},
  103 };
  104 
  105 static void
  106 xb360gp_identify(driver_t *driver, device_t parent)
  107 {
  108         const struct hid_device_info *hw = hid_get_device_info(parent);
  109 
  110         /* the Xbox 360 gamepad has no report descriptor */
  111         if (hid_test_quirk(hw, HQ_IS_XBOX360GP))
  112                 hid_set_report_descr(parent, xb360gp_rdesc,
  113                     sizeof(xb360gp_rdesc));
  114 }
  115 
  116 static int
  117 xb360gp_probe(device_t dev)
  118 {
  119         struct hgame_softc *sc = device_get_softc(dev);
  120         const struct hid_device_info *hw = hid_get_device_info(dev);
  121         int error;
  122 
  123         if (!hid_test_quirk(hw, HQ_IS_XBOX360GP))
  124                 return (ENXIO);
  125 
  126         hidmap_set_dev(&sc->hm, dev);
  127 
  128         error = HIDMAP_ADD_MAP(&sc->hm, xb360gp_map, NULL);
  129         if (error != 0)
  130                 return (error);
  131 
  132         device_set_desc(dev, "XBox 360 Gamepad");
  133 
  134         return (BUS_PROBE_DEFAULT);
  135 }
  136 
  137 static int
  138 xb360gp_attach(device_t dev)
  139 {
  140         struct hgame_softc *sc = device_get_softc(dev);
  141         int error;
  142 
  143         /*
  144          * Turn off the four LEDs on the gamepad which
  145          * are blinking by default:
  146          */
  147         static const uint8_t reportbuf[3] = {1, 3, 0};
  148         error = hid_set_report(dev, reportbuf, sizeof(reportbuf),
  149             HID_OUTPUT_REPORT, 0);
  150         if (error)
  151                 device_printf(dev, "set output report failed, error=%d "
  152                     "(ignored)\n", error);
  153 
  154         return (hidmap_attach(&sc->hm));
  155 }
  156 
  157 static int
  158 xb360gp_detach(device_t dev)
  159 {
  160         struct hgame_softc *sc = device_get_softc(dev);
  161 
  162         return (hidmap_detach(&sc->hm));
  163 }
  164 
  165 static device_method_t xb360gp_methods[] = {
  166         DEVMETHOD(device_identify,      xb360gp_identify),
  167         DEVMETHOD(device_probe,         xb360gp_probe),
  168         DEVMETHOD(device_attach,        xb360gp_attach),
  169         DEVMETHOD(device_detach,        xb360gp_detach),
  170         DEVMETHOD_END
  171 };
  172 
  173 DEFINE_CLASS_0(xb360gp, xb360gp_driver, xb360gp_methods,
  174     sizeof(struct hgame_softc));
  175 DRIVER_MODULE(xb360gp, hidbus, xb360gp_driver, NULL, NULL);
  176 MODULE_DEPEND(xb360gp, hid, 1, 1, 1);
  177 MODULE_DEPEND(xb360gp, hidbus, 1, 1, 1);
  178 MODULE_DEPEND(xb360gp, hidmap, 1, 1, 1);
  179 MODULE_DEPEND(xb360gp, hgame, 1, 1, 1);
  180 MODULE_DEPEND(xb360gp, evdev, 1, 1, 1);
  181 MODULE_VERSION(xb360gp, 1);
  182 USB_PNP_HOST_INFO(xb360gp_devs);

Cache object: c8ce72b271269fa5f231ffbdeb379ebe


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.