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/ps4dshock.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  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   25  * SUCH DAMAGE.
   26  */
   27 
   28 #include <sys/cdefs.h>
   29 __FBSDID("$FreeBSD$");
   30 
   31 /*
   32  * Sony PS4 DualShock 4 driver
   33  * https://eleccelerator.com/wiki/index.php?title=DualShock_4
   34  * https://gist.github.com/johndrinkwater/7708901
   35  * https://www.psdevwiki.com/ps4/DS4-USB
   36  */
   37 
   38 #include "opt_hid.h"
   39 
   40 #include <sys/param.h>
   41 #include <sys/bus.h>
   42 #include <sys/kernel.h>
   43 #include <sys/lock.h>
   44 #include <sys/malloc.h>
   45 #include <sys/module.h>
   46 #include <sys/sx.h>
   47 #include <sys/sysctl.h>
   48 
   49 #include <dev/evdev/input.h>
   50 #include <dev/evdev/evdev.h>
   51 
   52 #define HID_DEBUG_VAR   ps4dshock_debug
   53 #include <dev/hid/hid.h>
   54 #include <dev/hid/hidbus.h>
   55 #include <dev/hid/hidquirk.h>
   56 #include <dev/hid/hidmap.h>
   57 #include "usbdevs.h"
   58 
   59 #ifdef HID_DEBUG
   60 static int ps4dshock_debug = 1;
   61 
   62 static SYSCTL_NODE(_hw_hid, OID_AUTO, ps4dshock, CTLFLAG_RW, 0,
   63                 "Sony PS4 DualShock Gamepad");
   64 SYSCTL_INT(_hw_hid_ps4dshock, OID_AUTO, debug, CTLFLAG_RWTUN,
   65                 &ps4dshock_debug, 0, "Debug level");
   66 #endif
   67 
   68 static const uint8_t    ps4dshock_rdesc[] = {
   69         0x05, 0x01,             /* Usage Page (Generic Desktop Ctrls)   */
   70         0x09, 0x05,             /* Usage (Game Pad)                     */
   71         0xA1, 0x01,             /* Collection (Application)             */
   72         0x85, 0x01,             /*   Report ID (1)                      */
   73         0x09, 0x30,             /*   Usage (X)                          */
   74         0x09, 0x31,             /*   Usage (Y)                          */
   75         0x09, 0x33,             /*   Usage (Rx)                         */
   76         0x09, 0x34,             /*   Usage (Ry)                         */
   77         0x15, 0x00,             /*   Logical Minimum (0)                */
   78         0x26, 0xFF, 0x00,       /*   Logical Maximum (255)              */
   79         0x75, 0x08,             /*   Report Size (8)                    */
   80         0x95, 0x04,             /*   Report Count (4)                   */
   81         0x81, 0x02,             /*   Input (Data,Var,Abs)               */
   82         0x09, 0x39,             /*   Usage (Hat switch)                 */
   83         0x15, 0x00,             /*   Logical Minimum (0)                */
   84         0x25, 0x07,             /*   Logical Maximum (7)                */
   85         0x35, 0x00,             /*   Physical Minimum (0)               */
   86         0x46, 0x3B, 0x01,       /*   Physical Maximum (315)             */
   87         0x65, 0x14,             /*   Unit (System: English Rotation, Length: Centimeter) */
   88         0x75, 0x04,             /*   Report Size (4)                    */
   89         0x95, 0x01,             /*   Report Count (1)                   */
   90         0x81, 0x42,             /*   Input (Data,Var,Abs,Null State)    */
   91         0x65, 0x00,             /*   Unit (None)                        */
   92         0x45, 0x00,             /*   Physical Maximum (0)               */
   93         0x05, 0x09,             /*   Usage Page (Button)                */
   94         0x19, 0x01,             /*   Usage Minimum (0x01)               */
   95         0x29, 0x0E,             /*   Usage Maximum (0x0E)               */
   96         0x15, 0x00,             /*   Logical Minimum (0)                */
   97         0x25, 0x01,             /*   Logical Maximum (1)                */
   98         0x75, 0x01,             /*   Report Size (1)                    */
   99         0x95, 0x0E,             /*   Report Count (14)                  */
  100         0x81, 0x02,             /*   Input (Data,Var,Abs)               */
  101         0x06, 0x00, 0xFF,       /*   Usage Page (Vendor Defined 0xFF00) */
  102         0x09, 0x20,             /*   Usage (0x20)                       */
  103         0x75, 0x06,             /*   Report Size (6)                    */
  104         0x95, 0x01,             /*   Report Count (1)                   */
  105         0x15, 0x00,             /*   Logical Minimum (0)                */
  106         0x25, 0x3F,             /*   Logical Maximum (63)               */
  107         0x81, 0x02,             /*   Input (Data,Var,Abs)               */
  108         0x05, 0x01,             /*   Usage Page (Generic Desktop Ctrls) */
  109         0x09, 0x32,             /*   Usage (Z)                          */
  110         0x09, 0x35,             /*   Usage (Rz)                         */
  111         0x15, 0x00,             /*   Logical Minimum (0)                */
  112         0x26, 0xFF, 0x00,       /*   Logical Maximum (255)              */
  113         0x75, 0x08,             /*   Report Size (8)                    */
  114         0x95, 0x02,             /*   Report Count (2)                   */
  115         0x81, 0x02,             /*   Input (Data,Var,Abs)               */
  116         0xC0,                   /* End Collection                       */
  117         0x05, 0x01,             /* Usage Page (Generic Desktop Ctrls)   */
  118         0x09, 0x08,             /* Usage (Multi-axis Controller)        */
  119         0xA1, 0x01,             /* Collection (Application)             */
  120         0x06, 0x00, 0xFF,       /*   Usage Page (Vendor Defined 0xFF00) */
  121         0x09, 0x21,             /*   Usage (0x21)                       */
  122         0x27, 0xFF, 0xFF, 0x00, 0x00,   /*   Logical Maximum (65534)    */
  123         0x75, 0x10,             /*   Report Size (16)                   */
  124         0x95, 0x01,             /*   Report Count (1)                   */
  125         0x81, 0x02,             /*   Input (Data,Var,Abs)               */
  126         0x05, 0x06,             /*   Usage Page (Generic Dev Ctrls)     */
  127         0x09, 0x20,             /*   Usage (Battery Strength)           */
  128         0x26, 0xFF, 0x00,       /*   Logical Maximum (255)              */
  129         0x75, 0x08,             /*   Report Size (8)                    */
  130         0x95, 0x01,             /*   Report Count (1)                   */
  131         0x81, 0x02,             /*   Input (Data,Var,Abs)               */
  132         0x05, 0x01,             /*   Usage Page (Generic Desktop Ctrls) */
  133         0x19, 0x33,             /*   Usage Minimum (RX)                 */
  134         0x29, 0x35,             /*   Usage Maximum (RZ)                 */
  135         0x16, 0x00, 0x80,       /*   Logical Minimum (-32768)           */
  136         0x26, 0xFF, 0x7F,       /*   Logical Maximum (32767)            */
  137         0x75, 0x10,             /*   Report Size (16)                   */
  138         0x95, 0x03,             /*   Report Count (3)                   */
  139         0x81, 0x02,             /*   Input (Data,Var,Abs)               */
  140         0x19, 0x30,             /*   Usage Minimum (X)                  */
  141         0x29, 0x32,             /*   Usage Maximum (Z)                  */
  142         0x16, 0x00, 0x80,       /*   Logical Minimum (-32768)           */
  143         0x26, 0xFF, 0x7F,       /*   Logical Maximum (32767)            */
  144         0x95, 0x03,             /*   Report Count (3)                   */
  145         0x81, 0x02,             /*   Input (Data,Var,Abs)               */
  146         0x06, 0x00, 0xFF,       /*   Usage Page (Vendor Defined 0xFF00) */
  147         0x09, 0x21,             /*   Usage (0x21)                       */
  148         0x15, 0x00,             /*   Logical Minimum (0)                */
  149         0x26, 0xFF, 0x00,       /*   Logical Maximum (255)              */
  150         0x75, 0x08,             /*   Report Size (8)                    */
  151         0x95, 0x05,             /*   Report Count (5)                   */
  152         0x81, 0x03,             /*   Input (Const)                      */
  153         0xC0,                   /* End Collection                       */
  154         0x05, 0x0C,             /* Usage Page (Consumer)                */
  155         0x09, 0x05,             /* Usage (Headphone)                    */
  156         0xA1, 0x01,             /* Collection (Application)             */
  157         0x75, 0x05,             /*   Report Size (5)                    */
  158         0x95, 0x01,             /*   Report Count (1)                   */
  159         0x81, 0x03,             /*   Input (Const)                      */
  160         0x06, 0x00, 0xFF,       /*   Usage Page (Vendor Defined 0xFF00) */
  161         0x09, 0x20,             /*   Usage (0x20)                       */
  162         0x09, 0x21,             /*   Usage (0x21)                       */
  163         0x15, 0x00,             /*   Logical Minimum (0)                */
  164         0x25, 0x01,             /*   Logical Maximum (1)                */
  165         0x75, 0x01,             /*   Report Size (1)                    */
  166         0x95, 0x02,             /*   Report Count (2)                   */
  167         0x81, 0x02,             /*   Input (Data,Var,Abs)               */
  168         0x75, 0x01,             /*   Report Size (1)                    */
  169         0x95, 0x01,             /*   Report Count (1)                   */
  170         0x81, 0x03,             /*   Input (Const)                      */
  171         0x75, 0x08,             /*   Report Size (8)                    */
  172         0x95, 0x02,             /*   Report Count (2)                   */
  173         0x81, 0x03,             /*   Input (Const)                      */
  174         0xC0,                   /* End Collection                       */
  175         0x05, 0x0D,             /* Usage Page (Digitizer)               */
  176         0x09, 0x05,             /* Usage (Touch Pad)                    */
  177         0xA1, 0x01,             /* Collection (Application)             */
  178         0x06, 0x00, 0xFF,       /*   Usage Page (Vendor Defined 0xFF00) */
  179         0x09, 0x21,             /*   Usage (0x21)                       */
  180         0x15, 0x00,             /*   Logical Minimum (0)                */
  181         0x25, 0x03,             /*   Logical Maximum (3)                */
  182         0x75, 0x04,             /*   Report Size (4)                    */
  183         0x95, 0x01,             /*   Report Count (1)                   */
  184         0x81, 0x02,             /*   Input (Data,Var,Abs)               */
  185         0x75, 0x04,             /*   Report Size (4)                    */
  186         0x95, 0x01,             /*   Report Count (1)                   */
  187         0x81, 0x03,             /*   Input (Data,Var,Abs)               */
  188         0x05, 0x0D,             /*   Usage Page (Digitizer)             */
  189         0x09, 0x56,             /*   Usage (0x56)                       */
  190         0x55, 0x0C,             /*   Unit Exponent (-4)                 */
  191         0x66, 0x01, 0x10,       /*   Unit (System: SI Linear, Time: Seconds) */
  192         0x46, 0xCC, 0x06,       /*   Physical Maximum (1740)            */
  193         0x26, 0xFF, 0x00,       /*   Logical Maximum (255)              */
  194         0x75, 0x08,             /*   Report Size (8)                    */
  195         0x95, 0x01,             /*   Report Count (1)                   */
  196         0x81, 0x02,             /*   Input (Data,Var,Abs)               */
  197         0x65, 0x00,             /*   Unit (None)                        */
  198         0x45, 0x00,             /*   Physical Maximum (0)               */
  199         0x05, 0x0D,             /*   Usage Page (Digitizer)             */
  200         0x09, 0x22,             /*   Usage (Finger)                     */
  201         0xA1, 0x02,             /*   Collection (Logical)               */
  202         0x09, 0x51,             /*     Usage (0x51)                     */
  203         0x25, 0x7F,             /*     Logical Maximum (127)            */
  204         0x75, 0x07,             /*     Report Size (7)                  */
  205         0x95, 0x01,             /*     Report Count (1)                 */
  206         0x81, 0x02,             /*     Input (Data,Var,Abs)             */
  207         0x09, 0x42,             /*     Usage (Tip Switch)               */
  208         0x25, 0x01,             /*     Logical Maximum (1)              */
  209         0x75, 0x01,             /*     Report Size (1)                  */
  210         0x95, 0x01,             /*     Report Count (1)                 */
  211         0x81, 0x02,             /*     Input (Data,Var,Abs)             */
  212         0x05, 0x01,             /*     Usage Page (Generic Desktop Ctrls) */
  213         0x09, 0x30,             /*     Usage (X)                        */
  214         0x55, 0x0E,             /*     Unit Exponent (-2)               */
  215         0x65, 0x11,             /*     Unit (System: SI Linear, Length: Centimeter) */
  216         0x35, 0x00,             /*     Physical Minimum (0)             */
  217         0x46, 0x80, 0x02,       /*     Physical Maximum (640)           */
  218         0x26, 0x80, 0x07,       /*     Logical Maximum (1920)           */
  219         0x75, 0x0C,             /*     Report Size (12)                 */
  220         0x81, 0x02,             /*     Input (Data,Var,Abs)             */
  221         0x09, 0x31,             /*     Usage (Y)                        */
  222         0x46, 0xC0, 0x00,       /*     Physical Maximum (192)           */
  223         0x26, 0xAE, 0x03,       /*     Logical Maximum (942)            */
  224         0x81, 0x02,             /*     Input (Data,Var,Abs)             */
  225         0x65, 0x00,             /*     Unit (None)                      */
  226         0x45, 0x00,             /*     Physical Maximum (0)             */
  227         0xC0,                   /*   End Collection                     */
  228         0x05, 0x0D,             /*   Usage Page (Digitizer)             */
  229         0x09, 0x22,             /*   Usage (Finger)                     */
  230         0xA1, 0x02,             /*   Collection (Logical)               */
  231         0x09, 0x51,             /*     Usage (0x51)                     */
  232         0x25, 0x7F,             /*     Logical Maximum (127)            */
  233         0x75, 0x07,             /*     Report Size (7)                  */
  234         0x95, 0x01,             /*     Report Count (1)                 */
  235         0x81, 0x02,             /*     Input (Data,Var,Abs)             */
  236         0x09, 0x42,             /*     Usage (Tip Switch)               */
  237         0x25, 0x01,             /*     Logical Maximum (1)              */
  238         0x75, 0x01,             /*     Report Size (1)                  */
  239         0x95, 0x01,             /*     Report Count (1)                 */
  240         0x81, 0x02,             /*     Input (Data,Var,Abs)             */
  241         0x05, 0x01,             /*     Usage Page (Generic Desktop Ctrls) */
  242         0x09, 0x30,             /*     Usage (X)                        */
  243         0x55, 0x0E,             /*     Unit Exponent (-2)               */
  244         0x65, 0x11,             /*     Unit (System: SI Linear, Length: Centimeter) */
  245         0x35, 0x00,             /*     Physical Minimum (0)             */
  246         0x46, 0x80, 0x02,       /*     Physical Maximum (640)           */
  247         0x26, 0x80, 0x07,       /*     Logical Maximum (1920)           */
  248         0x75, 0x0C,             /*     Report Size (12)                 */
  249         0x81, 0x02,             /*     Input (Data,Var,Abs)             */
  250         0x09, 0x31,             /*     Usage (Y)                        */
  251         0x46, 0xC0, 0x00,       /*     Physical Maximum (192)           */
  252         0x26, 0xAE, 0x03,       /*     Logical Maximum (942)            */
  253         0x81, 0x02,             /*     Input (Data,Var,Abs)             */
  254         0x65, 0x00,             /*     Unit (None)                      */
  255         0x45, 0x00,             /*     Physical Maximum (0)             */
  256         0xC0,                   /*   End Collection                     */
  257         0x05, 0x0D,             /*   Usage Page (Digitizer)             */
  258         0x09, 0x56,             /*   Usage (0x56)                       */
  259         0x55, 0x0C,             /*   Unit Exponent (-4)                 */
  260         0x66, 0x01, 0x10,       /*   Unit (System: SI Linear, Time: Seconds) */
  261         0x46, 0xCC, 0x06,       /*   Physical Maximum (1740)            */
  262         0x26, 0xFF, 0x00,       /*   Logical Maximum (255)              */
  263         0x75, 0x08,             /*   Report Size (8)                    */
  264         0x95, 0x01,             /*   Report Count (1)                   */
  265         0x81, 0x02,             /*   Input (Data,Var,Abs)               */
  266         0x65, 0x00,             /*   Unit (None)                        */
  267         0x45, 0x00,             /*   Physical Maximum (0)               */
  268         0x05, 0x0D,             /*   Usage Page (Digitizer)             */
  269         0x09, 0x22,             /*   Usage (Finger)                     */
  270         0xA1, 0x02,             /*   Collection (Logical)               */
  271         0x09, 0x51,             /*     Usage (0x51)                     */
  272         0x25, 0x7F,             /*     Logical Maximum (127)            */
  273         0x75, 0x07,             /*     Report Size (7)                  */
  274         0x95, 0x01,             /*     Report Count (1)                 */
  275         0x81, 0x02,             /*     Input (Data,Var,Abs)             */
  276         0x09, 0x42,             /*     Usage (Tip Switch)               */
  277         0x25, 0x01,             /*     Logical Maximum (1)              */
  278         0x75, 0x01,             /*     Report Size (1)                  */
  279         0x95, 0x01,             /*     Report Count (1)                 */
  280         0x81, 0x02,             /*     Input (Data,Var,Abs)             */
  281         0x05, 0x01,             /*     Usage Page (Generic Desktop Ctrls) */
  282         0x09, 0x30,             /*     Usage (X)                        */
  283         0x55, 0x0E,             /*     Unit Exponent (-2)               */
  284         0x65, 0x11,             /*     Unit (System: SI Linear, Length: Centimeter) */
  285         0x35, 0x00,             /*     Physical Minimum (0)             */
  286         0x46, 0x80, 0x02,       /*     Physical Maximum (640)           */
  287         0x26, 0x80, 0x07,       /*     Logical Maximum (1920)           */
  288         0x75, 0x0C,             /*     Report Size (12)                 */
  289         0x81, 0x02,             /*     Input (Data,Var,Abs)             */
  290         0x09, 0x31,             /*     Usage (Y)                        */
  291         0x46, 0xC0, 0x00,       /*     Physical Maximum (192)           */
  292         0x26, 0xAE, 0x03,       /*     Logical Maximum (942)            */
  293         0x81, 0x02,             /*     Input (Data,Var,Abs)             */
  294         0x65, 0x00,             /*     Unit (None)                      */
  295         0x45, 0x00,             /*     Physical Maximum (0)             */
  296         0xC0,                   /*   End Collection                     */
  297         0x05, 0x0D,             /*   Usage Page (Digitizer)             */
  298         0x09, 0x22,             /*   Usage (Finger)                     */
  299         0xA1, 0x02,             /*   Collection (Logical)               */
  300         0x09, 0x51,             /*     Usage (0x51)                     */
  301         0x25, 0x7F,             /*     Logical Maximum (127)            */
  302         0x75, 0x07,             /*     Report Size (7)                  */
  303         0x95, 0x01,             /*     Report Count (1)                 */
  304         0x81, 0x02,             /*     Input (Data,Var,Abs)             */
  305         0x09, 0x42,             /*     Usage (Tip Switch)               */
  306         0x25, 0x01,             /*     Logical Maximum (1)              */
  307         0x75, 0x01,             /*     Report Size (1)                  */
  308         0x95, 0x01,             /*     Report Count (1)                 */
  309         0x81, 0x02,             /*     Input (Data,Var,Abs)             */
  310         0x05, 0x01,             /*     Usage Page (Generic Desktop Ctrls) */
  311         0x09, 0x30,             /*     Usage (X)                        */
  312         0x55, 0x0E,             /*     Unit Exponent (-2)               */
  313         0x65, 0x11,             /*     Unit (System: SI Linear, Length: Centimeter) */
  314         0x35, 0x00,             /*     Physical Minimum (0)             */
  315         0x46, 0x80, 0x02,       /*     Physical Maximum (640)           */
  316         0x26, 0x80, 0x07,       /*     Logical Maximum (1920)           */
  317         0x75, 0x0C,             /*     Report Size (12)                 */
  318         0x81, 0x02,             /*     Input (Data,Var,Abs)             */
  319         0x09, 0x31,             /*     Usage (Y)                        */
  320         0x46, 0xC0, 0x00,       /*     Physical Maximum (192)           */
  321         0x26, 0xAE, 0x03,       /*     Logical Maximum (942)            */
  322         0x81, 0x02,             /*     Input (Data,Var,Abs)             */
  323         0x65, 0x00,             /*     Unit (None)                      */
  324         0x45, 0x00,             /*     Physical Maximum (0)             */
  325         0xC0,                   /*   End Collection                     */
  326         0x05, 0x0D,             /*   Usage Page (Digitizer)             */
  327         0x09, 0x56,             /*   Usage (0x56)                       */
  328         0x55, 0x0C,             /*   Unit Exponent (-4)                 */
  329         0x66, 0x01, 0x10,       /*   Unit (System: SI Linear, Time: Seconds) */
  330         0x46, 0xCC, 0x06,       /*   Physical Maximum (1740)            */
  331         0x26, 0xFF, 0x00,       /*   Logical Maximum (255)              */
  332         0x75, 0x08,             /*   Report Size (8)                    */
  333         0x95, 0x01,             /*   Report Count (1)                   */
  334         0x81, 0x02,             /*   Input (Data,Var,Abs)               */
  335         0x65, 0x00,             /*   Unit (None)                        */
  336         0x45, 0x00,             /*   Physical Maximum (0)               */
  337         0x05, 0x0D,             /*   Usage Page (Digitizer)             */
  338         0x09, 0x22,             /*   Usage (Finger)                     */
  339         0xA1, 0x02,             /*   Collection (Logical)               */
  340         0x09, 0x51,             /*     Usage (0x51)                     */
  341         0x25, 0x7F,             /*     Logical Maximum (127)            */
  342         0x75, 0x07,             /*     Report Size (7)                  */
  343         0x95, 0x01,             /*     Report Count (1)                 */
  344         0x81, 0x02,             /*     Input (Data,Var,Abs)             */
  345         0x09, 0x42,             /*     Usage (Tip Switch)               */
  346         0x25, 0x01,             /*     Logical Maximum (1)              */
  347         0x75, 0x01,             /*     Report Size (1)                  */
  348         0x95, 0x01,             /*     Report Count (1)                 */
  349         0x81, 0x02,             /*     Input (Data,Var,Abs)             */
  350         0x05, 0x01,             /*     Usage Page (Generic Desktop Ctrls) */
  351         0x09, 0x30,             /*     Usage (X)                        */
  352         0x55, 0x0E,             /*     Unit Exponent (-2)               */
  353         0x65, 0x11,             /*     Unit (System: SI Linear, Length: Centimeter) */
  354         0x35, 0x00,             /*     Physical Minimum (0)             */
  355         0x46, 0x80, 0x02,       /*     Physical Maximum (640)           */
  356         0x26, 0x80, 0x07,       /*     Logical Maximum (1920)           */
  357         0x75, 0x0C,             /*     Report Size (12)                 */
  358         0x81, 0x02,             /*     Input (Data,Var,Abs)             */
  359         0x09, 0x31,             /*     Usage (Y)                        */
  360         0x46, 0xC0, 0x00,       /*     Physical Maximum (192)           */
  361         0x26, 0xAE, 0x03,       /*     Logical Maximum (942)            */
  362         0x81, 0x02,             /*     Input (Data,Var,Abs)             */
  363         0x65, 0x00,             /*     Unit (None)                      */
  364         0x45, 0x00,             /*     Physical Maximum (0)             */
  365         0xC0,                   /*   End Collection                     */
  366         0x05, 0x0D,             /*   Usage Page (Digitizer)             */
  367         0x09, 0x22,             /*   Usage (Finger)                     */
  368         0xA1, 0x02,             /*   Collection (Logical)               */
  369         0x09, 0x51,             /*     Usage (0x51)                     */
  370         0x25, 0x7F,             /*     Logical Maximum (127)            */
  371         0x75, 0x07,             /*     Report Size (7)                  */
  372         0x95, 0x01,             /*     Report Count (1)                 */
  373         0x81, 0x02,             /*     Input (Data,Var,Abs)             */
  374         0x09, 0x42,             /*     Usage (Tip Switch)               */
  375         0x25, 0x01,             /*     Logical Maximum (1)              */
  376         0x75, 0x01,             /*     Report Size (1)                  */
  377         0x95, 0x01,             /*     Report Count (1)                 */
  378         0x81, 0x02,             /*     Input (Data,Var,Abs)             */
  379         0x05, 0x01,             /*     Usage Page (Generic Desktop Ctrls) */
  380         0x09, 0x30,             /*     Usage (X)                        */
  381         0x55, 0x0E,             /*     Unit Exponent (-2)               */
  382         0x65, 0x11,             /*     Unit (System: SI Linear, Length: Centimeter) */
  383         0x35, 0x00,             /*     Physical Minimum (0)             */
  384         0x46, 0x80, 0x02,       /*     Physical Maximum (640)           */
  385         0x26, 0x80, 0x07,       /*     Logical Maximum (1920)           */
  386         0x75, 0x0C,             /*     Report Size (12)                 */
  387         0x81, 0x02,             /*     Input (Data,Var,Abs)             */
  388         0x09, 0x31,             /*     Usage (Y)                        */
  389         0x46, 0xC0, 0x00,       /*     Physical Maximum (192)           */
  390         0x26, 0xAE, 0x03,       /*     Logical Maximum (942)            */
  391         0x81, 0x02,             /*     Input (Data,Var,Abs)             */
  392         0x65, 0x00,             /*     Unit (None)                      */
  393         0x45, 0x00,             /*     Physical Maximum (0)             */
  394         0xC0,                   /*   End Collection                     */
  395         0x75, 0x08,             /*   Report Size (8)                    */
  396         0x95, 0x03,             /*   Report Count (3)                   */
  397         0x81, 0x03,             /*   Input (Const)                      */
  398         /* Output and feature reports */
  399         0x85, 0x05,             /*   Report ID (5)                      */
  400         0x06, 0x00, 0xFF,       /*   Usage Page (Vendor Defined 0xFF00) */
  401         0x09, 0x22,             /*   Usage (0x22)                       */
  402         0x15, 0x00,             /*   Logical Minimum (0)                */
  403         0x26, 0xFF, 0x00,       /*   Logical Maximum (255)              */
  404         0x95, 0x1F,             /*   Report Count (31)                  */
  405         0x91, 0x02,             /*   Output (Data,Var,Abs)              */
  406         0x85, 0x04,             /*   Report ID (4)                      */
  407         0x09, 0x23,             /*   Usage (0x23)                       */
  408         0x95, 0x24,             /*   Report Count (36)                  */
  409         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  410         0x85, 0x02,             /*   Report ID (2)                      */
  411         0x09, 0x24,             /*   Usage (0x24)                       */
  412         0x95, 0x24,             /*   Report Count (36)                  */
  413         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  414         0x85, 0x08,             /*   Report ID (8)                      */
  415         0x09, 0x25,             /*   Usage (0x25)                       */
  416         0x95, 0x03,             /*   Report Count (3)                   */
  417         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  418         0x85, 0x10,             /*   Report ID (16)                     */
  419         0x09, 0x26,             /*   Usage (0x26)                       */
  420         0x95, 0x04,             /*   Report Count (4)                   */
  421         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  422         0x85, 0x11,             /*   Report ID (17)                     */
  423         0x09, 0x27,             /*   Usage (0x27)                       */
  424         0x95, 0x02,             /*   Report Count (2)                   */
  425         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  426         0x85, 0x12,             /*   Report ID (18)                     */
  427         0x06, 0x02, 0xFF,       /*   Usage Page (Vendor Defined 0xFF02) */
  428         0x09, 0x21,             /*   Usage (0x21)                       */
  429         0x95, 0x0F,             /*   Report Count (15)                  */
  430         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  431         0x85, 0x13,             /*   Report ID (19)                     */
  432         0x09, 0x22,             /*   Usage (0x22)                       */
  433         0x95, 0x16,             /*   Report Count (22)                  */
  434         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  435         0x85, 0x14,             /*   Report ID (20)                     */
  436         0x06, 0x05, 0xFF,       /*   Usage Page (Vendor Defined 0xFF05) */
  437         0x09, 0x20,             /*   Usage (0x20)                       */
  438         0x95, 0x10,             /*   Report Count (16)                  */
  439         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  440         0x85, 0x15,             /*   Report ID (21)                     */
  441         0x09, 0x21,             /*   Usage (0x21)                       */
  442         0x95, 0x2C,             /*   Report Count (44)                  */
  443         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  444         0x06, 0x80, 0xFF,       /*   Usage Page (Vendor Defined 0xFF80) */
  445         0x85, 0x80,             /*   Report ID (-128)                   */
  446         0x09, 0x20,             /*   Usage (0x20)                       */
  447         0x95, 0x06,             /*   Report Count (6)                   */
  448         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  449         0x85, 0x81,             /*   Report ID (-127)                   */
  450         0x09, 0x21,             /*   Usage (0x21)                       */
  451         0x95, 0x06,             /*   Report Count (6)                   */
  452         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  453         0x85, 0x82,             /*   Report ID (-126)                   */
  454         0x09, 0x22,             /*   Usage (0x22)                       */
  455         0x95, 0x05,             /*   Report Count (5)                   */
  456         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  457         0x85, 0x83,             /*   Report ID (-125)                   */
  458         0x09, 0x23,             /*   Usage (0x23)                       */
  459         0x95, 0x01,             /*   Report Count (1)                   */
  460         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  461         0x85, 0x84,             /*   Report ID (-124)                   */
  462         0x09, 0x24,             /*   Usage (0x24)                       */
  463         0x95, 0x04,             /*   Report Count (4)                   */
  464         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  465         0x85, 0x85,             /*   Report ID (-123)                   */
  466         0x09, 0x25,             /*   Usage (0x25)                       */
  467         0x95, 0x06,             /*   Report Count (6)                   */
  468         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  469         0x85, 0x86,             /*   Report ID (-122)                   */
  470         0x09, 0x26,             /*   Usage (0x26)                       */
  471         0x95, 0x06,             /*   Report Count (6)                   */
  472         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  473         0x85, 0x87,             /*   Report ID (-121)                   */
  474         0x09, 0x27,             /*   Usage (0x27)                       */
  475         0x95, 0x23,             /*   Report Count (35)                  */
  476         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  477         0x85, 0x88,             /*   Report ID (-120)                   */
  478         0x09, 0x28,             /*   Usage (0x28)                       */
  479         0x95, 0x22,             /*   Report Count (34)                  */
  480         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  481         0x85, 0x89,             /*   Report ID (-119)                   */
  482         0x09, 0x29,             /*   Usage (0x29)                       */
  483         0x95, 0x02,             /*   Report Count (2)                   */
  484         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  485         0x85, 0x90,             /*   Report ID (-112)                   */
  486         0x09, 0x30,             /*   Usage (0x30)                       */
  487         0x95, 0x05,             /*   Report Count (5)                   */
  488         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  489         0x85, 0x91,             /*   Report ID (-111)                   */
  490         0x09, 0x31,             /*   Usage (0x31)                       */
  491         0x95, 0x03,             /*   Report Count (3)                   */
  492         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  493         0x85, 0x92,             /*   Report ID (-110)                   */
  494         0x09, 0x32,             /*   Usage (0x32)                       */
  495         0x95, 0x03,             /*   Report Count (3)                   */
  496         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  497         0x85, 0x93,             /*   Report ID (-109)                   */
  498         0x09, 0x33,             /*   Usage (0x33)                       */
  499         0x95, 0x0C,             /*   Report Count (12)                  */
  500         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  501         0x85, 0xA0,             /*   Report ID (-96)                    */
  502         0x09, 0x40,             /*   Usage (0x40)                       */
  503         0x95, 0x06,             /*   Report Count (6)                   */
  504         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  505         0x85, 0xA1,             /*   Report ID (-95)                    */
  506         0x09, 0x41,             /*   Usage (0x41)                       */
  507         0x95, 0x01,             /*   Report Count (1)                   */
  508         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  509         0x85, 0xA2,             /*   Report ID (-94)                    */
  510         0x09, 0x42,             /*   Usage (0x42)                       */
  511         0x95, 0x01,             /*   Report Count (1)                   */
  512         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  513         0x85, 0xA3,             /*   Report ID (-93)                    */
  514         0x09, 0x43,             /*   Usage (0x43)                       */
  515         0x95, 0x30,             /*   Report Count (48)                  */
  516         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  517         0x85, 0xA4,             /*   Report ID (-92)                    */
  518         0x09, 0x44,             /*   Usage (0x44)                       */
  519         0x95, 0x0D,             /*   Report Count (13)                  */
  520         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  521         0x85, 0xA5,             /*   Report ID (-91)                    */
  522         0x09, 0x45,             /*   Usage (0x45)                       */
  523         0x95, 0x15,             /*   Report Count (21)                  */
  524         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  525         0x85, 0xA6,             /*   Report ID (-90)                    */
  526         0x09, 0x46,             /*   Usage (0x46)                       */
  527         0x95, 0x15,             /*   Report Count (21)                  */
  528         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  529         0x85, 0xF0,             /*   Report ID (-16)                    */
  530         0x09, 0x47,             /*   Usage (0x47)                       */
  531         0x95, 0x3F,             /*   Report Count (63)                  */
  532         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  533         0x85, 0xF1,             /*   Report ID (-15)                    */
  534         0x09, 0x48,             /*   Usage (0x48)                       */
  535         0x95, 0x3F,             /*   Report Count (63)                  */
  536         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  537         0x85, 0xF2,             /*   Report ID (-14)                    */
  538         0x09, 0x49,             /*   Usage (0x49)                       */
  539         0x95, 0x0F,             /*   Report Count (15)                  */
  540         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  541         0x85, 0xA7,             /*   Report ID (-89)                    */
  542         0x09, 0x4A,             /*   Usage (0x4A)                       */
  543         0x95, 0x01,             /*   Report Count (1)                   */
  544         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  545         0x85, 0xA8,             /*   Report ID (-88)                    */
  546         0x09, 0x4B,             /*   Usage (0x4B)                       */
  547         0x95, 0x01,             /*   Report Count (1)                   */
  548         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  549         0x85, 0xA9,             /*   Report ID (-87)                    */
  550         0x09, 0x4C,             /*   Usage (0x4C)                       */
  551         0x95, 0x08,             /*   Report Count (8)                   */
  552         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  553         0x85, 0xAA,             /*   Report ID (-86)                    */
  554         0x09, 0x4E,             /*   Usage (0x4E)                       */
  555         0x95, 0x01,             /*   Report Count (1)                   */
  556         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  557         0x85, 0xAB,             /*   Report ID (-85)                    */
  558         0x09, 0x4F,             /*   Usage (0x4F)                       */
  559         0x95, 0x39,             /*   Report Count (57)                  */
  560         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  561         0x85, 0xAC,             /*   Report ID (-84)                    */
  562         0x09, 0x50,             /*   Usage (0x50)                       */
  563         0x95, 0x39,             /*   Report Count (57)                  */
  564         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  565         0x85, 0xAD,             /*   Report ID (-83)                    */
  566         0x09, 0x51,             /*   Usage (0x51)                       */
  567         0x95, 0x0B,             /*   Report Count (11)                  */
  568         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  569         0x85, 0xAE,             /*   Report ID (-82)                    */
  570         0x09, 0x52,             /*   Usage (0x52)                       */
  571         0x95, 0x01,             /*   Report Count (1)                   */
  572         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  573         0x85, 0xAF,             /*   Report ID (-81)                    */
  574         0x09, 0x53,             /*   Usage (0x53)                       */
  575         0x95, 0x02,             /*   Report Count (2)                   */
  576         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  577         0x85, 0xB0,             /*   Report ID (-80)                    */
  578         0x09, 0x54,             /*   Usage (0x54)                       */
  579         0x95, 0x3F,             /*   Report Count (63)                  */
  580         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  581         0xC0,                   /* End Collection                       */
  582 };
  583 
  584 #define PS4DS_GYRO_RES_PER_DEG_S        1024
  585 #define PS4DS_ACC_RES_PER_G             8192
  586 #define PS4DS_MAX_TOUCHPAD_PACKETS      4
  587 #define PS4DS_FEATURE_REPORT2_SIZE      37
  588 #define PS4DS_OUTPUT_REPORT5_SIZE       32
  589 #define PS4DS_OUTPUT_REPORT11_SIZE      78
  590 
  591 static hidmap_cb_t      ps4dshock_hat_switch_cb;
  592 static hidmap_cb_t      ps4dshock_final_cb;
  593 static hidmap_cb_t      ps4dsacc_data_cb;
  594 static hidmap_cb_t      ps4dsacc_tstamp_cb;
  595 static hidmap_cb_t      ps4dsacc_final_cb;
  596 static hidmap_cb_t      ps4dsmtp_data_cb;
  597 static hidmap_cb_t      ps4dsmtp_npackets_cb;
  598 static hidmap_cb_t      ps4dsmtp_final_cb;
  599 
  600 struct ps4ds_out5 {
  601         uint8_t features;
  602         uint8_t reserved1;
  603         uint8_t reserved2;
  604         uint8_t rumble_right;
  605         uint8_t rumble_left;
  606         uint8_t led_color_r;
  607         uint8_t led_color_g;
  608         uint8_t led_color_b;
  609         uint8_t led_delay_on;   /* centiseconds */
  610         uint8_t led_delay_off;
  611 } __attribute__((packed));
  612 
  613 static const struct ps4ds_led {
  614         int     r;
  615         int     g;
  616         int     b;
  617 } ps4ds_leds[] = {
  618         /* The first 4 entries match the PS4, other from Linux driver */
  619         { 0x00, 0x00, 0x40 },   /* Blue   */
  620         { 0x40, 0x00, 0x00 },   /* Red    */
  621         { 0x00, 0x40, 0x00 },   /* Green  */
  622         { 0x20, 0x00, 0x20 },   /* Pink   */
  623         { 0x02, 0x01, 0x00 },   /* Orange */
  624         { 0x00, 0x01, 0x01 },   /* Teal   */
  625         { 0x01, 0x01, 0x01 }    /* White  */
  626 };
  627 
  628 enum ps4ds_led_state {
  629         PS4DS_LED_OFF,
  630         PS4DS_LED_ON,
  631         PS4DS_LED_BLINKING,
  632         PD4DS_LED_CNT,
  633 };
  634 
  635 /* Map structure for accelerometer and gyro. */
  636 struct ps4ds_calib_data {
  637         int32_t usage;
  638         int32_t code;
  639         int32_t res;
  640         int32_t range;
  641         /* Calibration data for accelerometer and gyro. */
  642         int16_t bias;
  643         int32_t sens_numer;
  644         int32_t sens_denom;
  645 };
  646 
  647 enum {
  648         PS4DS_TSTAMP,
  649         PS4DS_CID1,
  650         PS4DS_TIP1,
  651         PS4DS_X1,
  652         PS4DS_Y1,
  653         PS4DS_CID2,
  654         PS4DS_TIP2,
  655         PS4DS_X2,
  656         PS4DS_Y2,
  657         PS4DS_NTPUSAGES,
  658 };
  659 
  660 struct ps4dshock_softc {
  661         struct hidmap           hm;
  662 
  663         bool                    is_bluetooth;
  664 
  665         struct sx               lock;
  666         enum ps4ds_led_state    led_state;
  667         struct ps4ds_led        led_color;
  668         int                     led_delay_on;   /* msecs */
  669         int                     led_delay_off;
  670 
  671         int                     rumble_right;
  672         int                     rumble_left;
  673 };
  674 
  675 struct ps4dsacc_softc {
  676         struct hidmap           hm;
  677 
  678         uint16_t                hw_tstamp;
  679         int32_t                 ev_tstamp;
  680 
  681         struct ps4ds_calib_data calib_data[6];
  682 };
  683 
  684 struct ps4dsmtp_softc {
  685         struct hidmap           hm;
  686 
  687         struct hid_location     btn_loc;
  688         u_int           npackets;
  689         int32_t         *data_ptr;
  690         int32_t         data[PS4DS_MAX_TOUCHPAD_PACKETS * PS4DS_NTPUSAGES];
  691 
  692         bool            do_tstamps;
  693         uint8_t         hw_tstamp;
  694         int32_t         ev_tstamp;
  695         bool            touch;
  696 };
  697 
  698 #define PD4DSHOCK_OFFSET(field) offsetof(struct ps4dshock_softc, field)
  699 enum {
  700         PD4DSHOCK_SYSCTL_LED_STATE =    PD4DSHOCK_OFFSET(led_state),
  701         PD4DSHOCK_SYSCTL_LED_COLOR_R =  PD4DSHOCK_OFFSET(led_color.r),
  702         PD4DSHOCK_SYSCTL_LED_COLOR_G =  PD4DSHOCK_OFFSET(led_color.g),
  703         PD4DSHOCK_SYSCTL_LED_COLOR_B =  PD4DSHOCK_OFFSET(led_color.b),
  704         PD4DSHOCK_SYSCTL_LED_DELAY_ON = PD4DSHOCK_OFFSET(led_delay_on),
  705         PD4DSHOCK_SYSCTL_LED_DELAY_OFF= PD4DSHOCK_OFFSET(led_delay_off),
  706 #define PD4DSHOCK_SYSCTL_LAST           PD4DSHOCK_SYSCTL_LED_DELAY_OFF
  707 };
  708 
  709 #define PS4DS_MAP_BTN(number, code)             \
  710         { HIDMAP_KEY(HUP_BUTTON, number, code) }
  711 #define PS4DS_MAP_ABS(usage, code)              \
  712         { HIDMAP_ABS(HUP_GENERIC_DESKTOP, HUG_##usage, code) }
  713 #define PS4DS_MAP_FLT(usage, code)              \
  714         { HIDMAP_ABS(HUP_GENERIC_DESKTOP, HUG_##usage, code), .flat = 15 }
  715 #define PS4DS_MAP_VSW(usage, code)      \
  716         { HIDMAP_SW(HUP_MICROSOFT, usage, code) }
  717 #define PS4DS_MAP_GCB(usage, callback)  \
  718         { HIDMAP_ANY_CB(HUP_GENERIC_DESKTOP, HUG_##usage, callback) }
  719 #define PS4DS_MAP_VCB(usage, callback)  \
  720         { HIDMAP_ANY_CB(HUP_MICROSOFT, usage, callback) }
  721 #define PS4DS_FINALCB(cb)                       \
  722         { HIDMAP_FINAL_CB(&cb) }
  723 
  724 static const struct hidmap_item ps4dshock_map[] = {
  725         PS4DS_MAP_FLT(X,                ABS_X),
  726         PS4DS_MAP_FLT(Y,                ABS_Y),
  727         PS4DS_MAP_ABS(Z,                ABS_Z),
  728         PS4DS_MAP_FLT(RX,               ABS_RX),
  729         PS4DS_MAP_FLT(RY,               ABS_RY),
  730         PS4DS_MAP_ABS(RZ,               ABS_RZ),
  731         PS4DS_MAP_BTN(1,                BTN_WEST),
  732         PS4DS_MAP_BTN(2,                BTN_SOUTH),
  733         PS4DS_MAP_BTN(3,                BTN_EAST),
  734         PS4DS_MAP_BTN(4,                BTN_NORTH),
  735         PS4DS_MAP_BTN(5,                BTN_TL),
  736         PS4DS_MAP_BTN(6,                BTN_TR),
  737         PS4DS_MAP_BTN(7,                BTN_TL2),
  738         PS4DS_MAP_BTN(8,                BTN_TR2),
  739         PS4DS_MAP_BTN(9,                BTN_SELECT),
  740         PS4DS_MAP_BTN(10,               BTN_START),
  741         PS4DS_MAP_BTN(11,               BTN_THUMBL),
  742         PS4DS_MAP_BTN(12,               BTN_THUMBR),
  743         PS4DS_MAP_BTN(13,               BTN_MODE),
  744         /* Click button is handled by touchpad driver */
  745         /* PS4DS_MAP_BTN(14,    BTN_LEFT), */
  746         PS4DS_MAP_GCB(HAT_SWITCH,       ps4dshock_hat_switch_cb),
  747         PS4DS_FINALCB(                  ps4dshock_final_cb),
  748 };
  749 static const struct hidmap_item ps4dsacc_map[] = {
  750         PS4DS_MAP_GCB(X,                ps4dsacc_data_cb),
  751         PS4DS_MAP_GCB(Y,                ps4dsacc_data_cb),
  752         PS4DS_MAP_GCB(Z,                ps4dsacc_data_cb),
  753         PS4DS_MAP_GCB(RX,               ps4dsacc_data_cb),
  754         PS4DS_MAP_GCB(RY,               ps4dsacc_data_cb),
  755         PS4DS_MAP_GCB(RZ,               ps4dsacc_data_cb),
  756         PS4DS_MAP_VCB(0x0021,           ps4dsacc_tstamp_cb),
  757         PS4DS_FINALCB(                  ps4dsacc_final_cb),
  758 };
  759 static const struct hidmap_item ps4dshead_map[] = {
  760         PS4DS_MAP_VSW(0x0020,           SW_MICROPHONE_INSERT),
  761         PS4DS_MAP_VSW(0x0021,           SW_HEADPHONE_INSERT),
  762 };
  763 static const struct hidmap_item ps4dsmtp_map[] = {
  764         { HIDMAP_ABS_CB(HUP_MICROSOFT, 0x0021,          ps4dsmtp_npackets_cb)},
  765         { HIDMAP_ABS_CB(HUP_DIGITIZERS, HUD_SCAN_TIME,  ps4dsmtp_data_cb) },
  766         { HIDMAP_ABS_CB(HUP_DIGITIZERS, HUD_CONTACTID,  ps4dsmtp_data_cb) },
  767         { HIDMAP_ABS_CB(HUP_DIGITIZERS, HUD_TIP_SWITCH, ps4dsmtp_data_cb) },
  768         { HIDMAP_ABS_CB(HUP_GENERIC_DESKTOP, HUG_X,     ps4dsmtp_data_cb) },
  769         { HIDMAP_ABS_CB(HUP_GENERIC_DESKTOP, HUG_Y,     ps4dsmtp_data_cb) },
  770         { HIDMAP_FINAL_CB(                              ps4dsmtp_final_cb) },
  771 };
  772 
  773 static const struct hid_device_id ps4dshock_devs[] = {
  774         { HID_BVP(BUS_USB, USB_VENDOR_SONY, 0x9cc),
  775           HID_TLC(HUP_GENERIC_DESKTOP, HUG_GAME_PAD) },
  776 };
  777 static const struct hid_device_id ps4dsacc_devs[] = {
  778         { HID_BVP(BUS_USB, USB_VENDOR_SONY, 0x9cc),
  779           HID_TLC(HUP_GENERIC_DESKTOP, HUG_MULTIAXIS_CNTROLLER) },
  780 };
  781 static const struct hid_device_id ps4dshead_devs[] = {
  782         { HID_BVP(BUS_USB, USB_VENDOR_SONY, 0x9cc),
  783           HID_TLC(HUP_CONSUMER, HUC_HEADPHONE) },
  784 };
  785 static const struct hid_device_id ps4dsmtp_devs[] = {
  786         { HID_BVP(BUS_USB, USB_VENDOR_SONY, 0x9cc),
  787           HID_TLC(HUP_DIGITIZERS, HUD_TOUCHPAD) },
  788 };
  789 
  790 static int
  791 ps4dshock_hat_switch_cb(HIDMAP_CB_ARGS)
  792 {
  793         static const struct { int32_t x; int32_t y; } hat_switch_map[] = {
  794             {0, -1}, {1, -1}, {1, 0}, {1, 1}, {0, 1}, {-1, 1}, {-1, 0},
  795             {-1, -1},{0, 0}
  796         };
  797         struct evdev_dev *evdev = HIDMAP_CB_GET_EVDEV();
  798         u_int idx;
  799 
  800         switch (HIDMAP_CB_GET_STATE()) {
  801         case HIDMAP_CB_IS_ATTACHING:
  802                 evdev_support_event(evdev, EV_ABS);
  803                 evdev_support_abs(evdev, ABS_HAT0X, -1, 1, 0, 0, 0);
  804                 evdev_support_abs(evdev, ABS_HAT0Y, -1, 1, 0, 0, 0);
  805                 break;
  806 
  807         case HIDMAP_CB_IS_RUNNING:
  808                 idx = MIN(nitems(hat_switch_map) - 1, (u_int)ctx.data);
  809                 evdev_push_abs(evdev, ABS_HAT0X, hat_switch_map[idx].x);
  810                 evdev_push_abs(evdev, ABS_HAT0Y, hat_switch_map[idx].y);
  811                 break;
  812 
  813         default:
  814                 break;
  815         }
  816 
  817         return (0);
  818 }
  819 
  820 static int
  821 ps4dshock_final_cb(HIDMAP_CB_ARGS)
  822 {
  823         struct evdev_dev *evdev = HIDMAP_CB_GET_EVDEV();
  824 
  825         if (HIDMAP_CB_GET_STATE() == HIDMAP_CB_IS_ATTACHING)
  826                 evdev_support_prop(evdev, INPUT_PROP_DIRECT);
  827 
  828         /* Do not execute callback at interrupt handler and detach */
  829         return (ENOSYS);
  830 }
  831 
  832 static int
  833 ps4dsacc_data_cb(HIDMAP_CB_ARGS)
  834 {
  835         struct evdev_dev *evdev = HIDMAP_CB_GET_EVDEV();
  836         struct ps4dsacc_softc *sc = HIDMAP_CB_GET_SOFTC();
  837         struct ps4ds_calib_data *calib;
  838         u_int i;
  839 
  840         switch (HIDMAP_CB_GET_STATE()) {
  841         case HIDMAP_CB_IS_ATTACHING:
  842                 for (i = 0; i < nitems(sc->calib_data); i++) {
  843                         if (sc->calib_data[i].usage == ctx.hi->usage) {
  844                                 evdev_support_abs(evdev,
  845                                      sc->calib_data[i].code,
  846                                     -sc->calib_data[i].range,
  847                                      sc->calib_data[i].range, 16, 0,
  848                                      sc->calib_data[i].res);
  849                                 HIDMAP_CB_UDATA = &sc->calib_data[i];
  850                                 break;
  851                         }
  852                 }
  853                 break;
  854 
  855         case HIDMAP_CB_IS_RUNNING:
  856                 calib = HIDMAP_CB_UDATA;
  857                 evdev_push_abs(evdev, calib->code,
  858                     ((int64_t)ctx.data - calib->bias) * calib->sens_numer /
  859                     calib->sens_denom);
  860                 break;
  861 
  862         default:
  863                 break;
  864         }
  865 
  866         return (0);
  867 }
  868 
  869 static int
  870 ps4dsacc_tstamp_cb(HIDMAP_CB_ARGS)
  871 {
  872         struct evdev_dev *evdev = HIDMAP_CB_GET_EVDEV();
  873         struct ps4dsacc_softc *sc = HIDMAP_CB_GET_SOFTC();
  874         uint16_t tstamp;
  875 
  876         switch (HIDMAP_CB_GET_STATE()) {
  877         case HIDMAP_CB_IS_ATTACHING:
  878                 evdev_support_event(evdev, EV_MSC);
  879                 evdev_support_msc(evdev, MSC_TIMESTAMP);
  880                 break;
  881 
  882         case HIDMAP_CB_IS_RUNNING:
  883                 /* Convert timestamp (in 5.33us unit) to timestamp_us */
  884                 tstamp = (uint16_t)ctx.data;
  885                 sc->ev_tstamp += (uint16_t)(tstamp - sc->hw_tstamp) * 16 / 3;
  886                 sc->hw_tstamp = tstamp;
  887                 evdev_push_msc(evdev, MSC_TIMESTAMP, sc->ev_tstamp);
  888                 break;
  889 
  890         default:
  891                 break;
  892         }
  893 
  894         return (0);
  895 }
  896 
  897 static int
  898 ps4dsacc_final_cb(HIDMAP_CB_ARGS)
  899 {
  900         struct evdev_dev *evdev = HIDMAP_CB_GET_EVDEV();
  901 
  902         if (HIDMAP_CB_GET_STATE() == HIDMAP_CB_IS_ATTACHING) {
  903                 evdev_support_event(evdev, EV_ABS);
  904                 evdev_support_prop(evdev, INPUT_PROP_ACCELEROMETER);
  905         }
  906         /* Do not execute callback at interrupt handler and detach */
  907         return (ENOSYS);
  908 }
  909 
  910 static int
  911 ps4dsmtp_npackets_cb(HIDMAP_CB_ARGS)
  912 {
  913         struct ps4dsmtp_softc *sc = HIDMAP_CB_GET_SOFTC();
  914 
  915         if (HIDMAP_CB_GET_STATE() == HIDMAP_CB_IS_RUNNING) {
  916                 sc->npackets = MIN(PS4DS_MAX_TOUCHPAD_PACKETS,(u_int)ctx.data);
  917                 /* Reset pointer here as it is first usage in touchpad TLC */
  918                 sc->data_ptr = sc->data;
  919         }
  920 
  921         return (0);
  922 }
  923 
  924 static int
  925 ps4dsmtp_data_cb(HIDMAP_CB_ARGS)
  926 {
  927         struct ps4dsmtp_softc *sc = HIDMAP_CB_GET_SOFTC();
  928 
  929         if (HIDMAP_CB_GET_STATE() == HIDMAP_CB_IS_RUNNING) {
  930                 *sc->data_ptr = ctx.data;
  931                 ++sc->data_ptr;
  932         }
  933 
  934         return (0);
  935 }
  936 
  937 static void
  938 ps4dsmtp_push_packet(struct ps4dsmtp_softc *sc, struct evdev_dev *evdev,
  939     int32_t *data)
  940 {
  941         uint8_t hw_tstamp, delta;
  942         bool touch;
  943 
  944         evdev_push_abs(evdev, ABS_MT_SLOT, 0);
  945         if (data[PS4DS_TIP1] == 0) {
  946                 evdev_push_abs(evdev, ABS_MT_TRACKING_ID, data[PS4DS_CID1]);
  947                 evdev_push_abs(evdev, ABS_MT_POSITION_X, data[PS4DS_X1]);
  948                 evdev_push_abs(evdev, ABS_MT_POSITION_Y, data[PS4DS_Y1]);
  949         } else
  950                 evdev_push_abs(evdev, ABS_MT_TRACKING_ID, -1);
  951         evdev_push_abs(evdev, ABS_MT_SLOT, 1);
  952         if (data[PS4DS_TIP2] == 0) {
  953                 evdev_push_abs(evdev, ABS_MT_TRACKING_ID, data[PS4DS_CID2]);
  954                 evdev_push_abs(evdev, ABS_MT_POSITION_X, data[PS4DS_X2]);
  955                 evdev_push_abs(evdev, ABS_MT_POSITION_Y, data[PS4DS_Y2]);
  956         } else
  957                 evdev_push_abs(evdev, ABS_MT_TRACKING_ID, -1);
  958 
  959         if (sc->do_tstamps) {
  960                 /*
  961                  * Export hardware timestamps in libinput-friendly way.
  962                  * Make timestamp counter 32-bit, scale up hardware
  963                  * timestamps to be on per 1usec basis and reset
  964                  * counter at the start of each touch.
  965                  */
  966                 hw_tstamp = (uint8_t)data[PS4DS_TSTAMP];
  967                 delta = hw_tstamp - sc->hw_tstamp;
  968                 sc->hw_tstamp = hw_tstamp;
  969                 touch = data[PS4DS_TIP1] == 0 || data[PS4DS_TIP2] == 0;
  970                 /* Hardware timestamp counter ticks in 682 usec interval. */
  971                 if ((touch || sc->touch) && delta != 0) {
  972                         if (sc->touch)
  973                                 sc->ev_tstamp += delta * 682;
  974                         evdev_push_msc(evdev, MSC_TIMESTAMP, sc->ev_tstamp);
  975                 }
  976                 if (!touch)
  977                         sc->ev_tstamp = 0;
  978                 sc->touch = touch;
  979         }
  980 }
  981 
  982 static int
  983 ps4dsmtp_final_cb(HIDMAP_CB_ARGS)
  984 {
  985         struct ps4dsmtp_softc *sc = HIDMAP_CB_GET_SOFTC();
  986         struct evdev_dev *evdev = HIDMAP_CB_GET_EVDEV();
  987         int32_t *data;
  988 
  989         switch (HIDMAP_CB_GET_STATE()) {
  990         case HIDMAP_CB_IS_ATTACHING:
  991                 if (hid_test_quirk(hid_get_device_info(sc->hm.dev),
  992                     HQ_MT_TIMESTAMP))
  993                         sc->do_tstamps = true;
  994                 /*
  995                  * Dualshock 4 touchpad TLC contained in fixed report
  996                  * descriptor is almost compatible with MS precission touchpad
  997                  * specs and hmt(4) driver. But... for some reasons "Click"
  998                  * button location was grouped with other GamePad buttons by
  999                  * touchpad designers so it belongs to GamePad TLC. Fix it with
 1000                  * direct reading of "Click" button value from interrupt frame.
 1001                  */
 1002                 sc->btn_loc = (struct hid_location) { 1, 0, 49 };
 1003                 evdev_support_event(evdev, EV_SYN);
 1004                 evdev_support_event(evdev, EV_KEY);
 1005                 evdev_support_event(evdev, EV_ABS);
 1006                 if (sc->do_tstamps) {
 1007                         evdev_support_event(evdev, EV_MSC);
 1008                         evdev_support_msc(evdev, MSC_TIMESTAMP);
 1009                 }
 1010                 evdev_support_key(evdev, BTN_LEFT);
 1011                 evdev_support_abs(evdev, ABS_MT_SLOT, 0, 1, 0, 0, 0);
 1012                 evdev_support_abs(evdev, ABS_MT_TRACKING_ID, -1, 127, 0, 0, 0);
 1013                 evdev_support_abs(evdev, ABS_MT_POSITION_X, 0, 1920, 0, 0, 30);
 1014                 evdev_support_abs(evdev, ABS_MT_POSITION_Y, 0, 942, 0, 0, 49);
 1015                 evdev_support_prop(evdev, INPUT_PROP_POINTER);
 1016                 evdev_support_prop(evdev, INPUT_PROP_BUTTONPAD);
 1017                 evdev_set_flag(evdev, EVDEV_FLAG_MT_STCOMPAT);
 1018                 break;
 1019 
 1020         case HIDMAP_CB_IS_RUNNING:
 1021                 /* Only packets with ReportID=1 are accepted */
 1022                 if (HIDMAP_CB_GET_RID() != 1)
 1023                         return (ENOTSUP);
 1024                 evdev_push_key(evdev, BTN_LEFT,
 1025                     HIDMAP_CB_GET_UDATA(&sc->btn_loc));
 1026                 for (data = sc->data;
 1027                      data < sc->data + PS4DS_NTPUSAGES * sc->npackets;
 1028                      data += PS4DS_NTPUSAGES) {
 1029                         ps4dsmtp_push_packet(sc, evdev, data);
 1030                         evdev_sync(evdev);
 1031                 }
 1032                 break;
 1033 
 1034         default:
 1035                 break;
 1036         }
 1037 
 1038         /* Do execute callback at interrupt handler and detach */
 1039         return (0);
 1040 }
 1041 
 1042 static int
 1043 ps4dshock_write(struct ps4dshock_softc *sc)
 1044 {
 1045         hid_size_t osize = sc->is_bluetooth ?
 1046             PS4DS_OUTPUT_REPORT11_SIZE : PS4DS_OUTPUT_REPORT5_SIZE;
 1047         uint8_t buf[osize];
 1048         int offset;
 1049         bool led_on, led_blinks;
 1050 
 1051         memset(buf, 0, osize);
 1052         buf[0] = sc->is_bluetooth ? 0x11 : 0x05;
 1053         offset = sc->is_bluetooth ? 3 : 1;
 1054         led_on = sc->led_state != PS4DS_LED_OFF;
 1055         led_blinks = sc->led_state == PS4DS_LED_BLINKING;
 1056         *(struct ps4ds_out5 *)(buf + offset) = (struct ps4ds_out5) {
 1057                 .features = 0x07, /* blink + LEDs + motor */
 1058                 .rumble_right = sc->rumble_right,
 1059                 .rumble_left = sc->rumble_left,
 1060                 .led_color_r = led_on ? sc->led_color.r : 0,
 1061                 .led_color_g = led_on ? sc->led_color.g : 0,
 1062                 .led_color_b = led_on ? sc->led_color.b : 0,
 1063                 /* convert milliseconds to centiseconds */
 1064                 .led_delay_on = led_blinks ? sc->led_delay_on / 10 : 0,
 1065                 .led_delay_off = led_blinks ? sc->led_delay_off / 10 : 0,
 1066         };
 1067 
 1068         return (hid_write(sc->hm.dev, buf, osize));
 1069 }
 1070 
 1071 /* Synaptics Touchpad */
 1072 static int
 1073 ps4dshock_sysctl(SYSCTL_HANDLER_ARGS)
 1074 {
 1075         struct ps4dshock_softc *sc;
 1076         int error, arg;
 1077 
 1078         if (oidp->oid_arg1 == NULL || oidp->oid_arg2 < 0 ||
 1079             oidp->oid_arg2 > PD4DSHOCK_SYSCTL_LAST)
 1080                 return (EINVAL);
 1081 
 1082         sc = oidp->oid_arg1;
 1083         sx_xlock(&sc->lock);
 1084 
 1085         /* Read the current value. */
 1086         arg = *(int *)((char *)sc + oidp->oid_arg2);
 1087         error = sysctl_handle_int(oidp, &arg, 0, req);
 1088 
 1089         /* Sanity check. */
 1090         if (error || !req->newptr)
 1091                 goto unlock;
 1092 
 1093         /*
 1094          * Check that the new value is in the concerned node's range
 1095          * of values.
 1096          */
 1097         switch (oidp->oid_arg2) {
 1098         case PD4DSHOCK_SYSCTL_LED_STATE:
 1099                 if (arg < 0 || arg >= PD4DS_LED_CNT)
 1100                         error = EINVAL;
 1101                 break;
 1102         case PD4DSHOCK_SYSCTL_LED_COLOR_R:
 1103         case PD4DSHOCK_SYSCTL_LED_COLOR_G:
 1104         case PD4DSHOCK_SYSCTL_LED_COLOR_B:
 1105                 if (arg < 0 || arg > UINT8_MAX)
 1106                         error = EINVAL;
 1107                 break;
 1108         case PD4DSHOCK_SYSCTL_LED_DELAY_ON:
 1109         case PD4DSHOCK_SYSCTL_LED_DELAY_OFF:
 1110                 if (arg < 0 || arg > UINT8_MAX * 10)
 1111                         error = EINVAL;
 1112                 break;
 1113         default:
 1114                 error = EINVAL;
 1115         }
 1116 
 1117         /* Update. */
 1118         if (error == 0) {
 1119                 *(int *)((char *)sc + oidp->oid_arg2) = arg;
 1120                 ps4dshock_write(sc);
 1121         }
 1122 unlock:
 1123         sx_unlock(&sc->lock);
 1124 
 1125         return (error);
 1126 }
 1127 
 1128 static void
 1129 ps4dshock_identify(driver_t *driver, device_t parent)
 1130 {
 1131 
 1132         /* Overload PS4 DualShock gamepad rudimentary report descriptor */
 1133         if (HIDBUS_LOOKUP_ID(parent, ps4dshock_devs) != NULL)
 1134                 hid_set_report_descr(parent, ps4dshock_rdesc,
 1135                     sizeof(ps4dshock_rdesc));
 1136 }
 1137 
 1138 static int
 1139 ps4dshock_probe(device_t dev)
 1140 {
 1141         struct ps4dshock_softc *sc = device_get_softc(dev);
 1142 
 1143         hidmap_set_debug_var(&sc->hm, &HID_DEBUG_VAR);
 1144         return (
 1145             HIDMAP_PROBE(&sc->hm, dev, ps4dshock_devs, ps4dshock_map, NULL)
 1146         );
 1147 }
 1148 
 1149 static int
 1150 ps4dsacc_probe(device_t dev)
 1151 {
 1152         struct ps4dsacc_softc *sc = device_get_softc(dev);
 1153 
 1154         hidmap_set_debug_var(&sc->hm, &HID_DEBUG_VAR);
 1155         return (
 1156             HIDMAP_PROBE(&sc->hm, dev, ps4dsacc_devs, ps4dsacc_map, "Sensors")
 1157         );
 1158 }
 1159 
 1160 static int
 1161 ps4dshead_probe(device_t dev)
 1162 {
 1163         struct hidmap *hm = device_get_softc(dev);
 1164 
 1165         hidmap_set_debug_var(hm, &HID_DEBUG_VAR);
 1166         return (
 1167             HIDMAP_PROBE(hm, dev, ps4dshead_devs, ps4dshead_map, "Headset")
 1168         );
 1169 }
 1170 
 1171 static int
 1172 ps4dsmtp_probe(device_t dev)
 1173 {
 1174         struct ps4dshock_softc *sc = device_get_softc(dev);
 1175 
 1176         hidmap_set_debug_var(&sc->hm, &HID_DEBUG_VAR);
 1177         return (
 1178             HIDMAP_PROBE(&sc->hm, dev, ps4dsmtp_devs, ps4dsmtp_map, "Touchpad")
 1179         );
 1180 }
 1181 
 1182 static int
 1183 ps4dshock_attach(device_t dev)
 1184 {
 1185         struct ps4dshock_softc *sc = device_get_softc(dev);
 1186         struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(dev);
 1187         struct sysctl_oid *tree = device_get_sysctl_tree(dev);
 1188 
 1189         sc->led_state = PS4DS_LED_ON;
 1190         sc->led_color = ps4ds_leds[device_get_unit(dev) % nitems(ps4ds_leds)];
 1191         sc->led_delay_on = 500; /* 1 Hz */
 1192         sc->led_delay_off = 500;
 1193         ps4dshock_write(sc);
 1194 
 1195         sx_init(&sc->lock, "ps4dshock");
 1196 
 1197         SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
 1198             "led_state", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY, sc,
 1199             PD4DSHOCK_SYSCTL_LED_STATE, ps4dshock_sysctl, "I",
 1200             "LED state: 0 - off, 1 - on, 2 - blinking.");
 1201 
 1202         SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
 1203             "led_color_r", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY, sc,
 1204             PD4DSHOCK_SYSCTL_LED_COLOR_R, ps4dshock_sysctl, "I",
 1205             "LED color. Red component.");
 1206 
 1207         SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
 1208             "led_color_g", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY, sc,
 1209             PD4DSHOCK_SYSCTL_LED_COLOR_G, ps4dshock_sysctl, "I",
 1210             "LED color. Green component.");
 1211 
 1212         SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
 1213             "led_color_b", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY, sc,
 1214             PD4DSHOCK_SYSCTL_LED_COLOR_B, ps4dshock_sysctl, "I",
 1215             "LED color. Blue component.");
 1216 
 1217         SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
 1218             "led_delay_on", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY, sc,
 1219             PD4DSHOCK_SYSCTL_LED_DELAY_ON, ps4dshock_sysctl, "I",
 1220             "LED blink. On delay, msecs.");
 1221 
 1222         SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
 1223             "led_delay_off", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY, sc,
 1224             PD4DSHOCK_SYSCTL_LED_DELAY_OFF, ps4dshock_sysctl, "I",
 1225             "LED blink. Off delay, msecs.");
 1226 
 1227         return (hidmap_attach(&sc->hm));
 1228 }
 1229 
 1230 static int
 1231 ps4dsacc_attach(device_t dev)
 1232 {
 1233         struct ps4dsacc_softc *sc = device_get_softc(dev);
 1234         uint8_t buf[PS4DS_FEATURE_REPORT2_SIZE];
 1235         int error, speed_2x, range_2g;
 1236 
 1237         /* Read accelerometers and gyroscopes calibration data */
 1238         error = hid_get_report(dev, buf, sizeof(buf), NULL,
 1239             HID_FEATURE_REPORT, 0x02);
 1240         if (error)
 1241                 DPRINTF("get feature report failed, error=%d "
 1242                     "(ignored)\n", error);
 1243 
 1244         DPRINTFN(5, "calibration data: %*D\n", (int)sizeof(buf), buf, " ");
 1245 
 1246         /*
 1247          * Set gyroscope calibration and normalization parameters.
 1248          * Data values will be normalized to 1/ PS4DS_GYRO_RES_PER_DEG_S
 1249          * degree/s.
 1250          */
 1251 #define HGETW(w) ((int16_t)((w)[0] | (((uint16_t)((w)[1])) << 8)))
 1252         speed_2x = HGETW(&buf[19]) + HGETW(&buf[21]);
 1253         sc->calib_data[0].usage = HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_RX);
 1254         sc->calib_data[0].code = ABS_RX;
 1255         sc->calib_data[0].range = PS4DS_GYRO_RES_PER_DEG_S * 2048;
 1256         sc->calib_data[0].res = PS4DS_GYRO_RES_PER_DEG_S;
 1257         sc->calib_data[0].bias = HGETW(&buf[1]);
 1258         sc->calib_data[0].sens_numer = speed_2x * PS4DS_GYRO_RES_PER_DEG_S;
 1259         sc->calib_data[0].sens_denom = HGETW(&buf[7]) - HGETW(&buf[9]);
 1260         /* BT case */
 1261         /* sc->calib_data[0].sens_denom = HGETW(&buf[7]) - HGETW(&buf[13]); */
 1262 
 1263         sc->calib_data[1].usage = HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_RY);
 1264         sc->calib_data[1].code = ABS_RY;
 1265         sc->calib_data[1].range = PS4DS_GYRO_RES_PER_DEG_S * 2048;
 1266         sc->calib_data[1].res = PS4DS_GYRO_RES_PER_DEG_S;
 1267         sc->calib_data[1].bias = HGETW(&buf[3]);
 1268         sc->calib_data[1].sens_numer = speed_2x * PS4DS_GYRO_RES_PER_DEG_S;
 1269         sc->calib_data[1].sens_denom = HGETW(&buf[11]) - HGETW(&buf[13]);
 1270         /* BT case */
 1271         /* sc->calib_data[1].sens_denom = HGETW(&buf[9]) - HGETW(&buf[15]); */
 1272 
 1273         sc->calib_data[2].usage = HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_RZ);
 1274         sc->calib_data[2].code = ABS_RZ;
 1275         sc->calib_data[2].range = PS4DS_GYRO_RES_PER_DEG_S * 2048;
 1276         sc->calib_data[2].res = PS4DS_GYRO_RES_PER_DEG_S;
 1277         sc->calib_data[2].bias = HGETW(&buf[5]);
 1278         sc->calib_data[2].sens_numer = speed_2x * PS4DS_GYRO_RES_PER_DEG_S;
 1279         sc->calib_data[2].sens_denom = HGETW(&buf[15]) - HGETW(&buf[17]);
 1280         /* BT case */
 1281         /* sc->calib_data[2].sens_denom = HGETW(&buf[11]) - HGETW(&buf[17]); */
 1282 
 1283         /*
 1284          * Set accelerometer calibration and normalization parameters.
 1285          * Data values will be normalized to 1 / PS4DS_ACC_RES_PER_G G.
 1286          */
 1287         range_2g = HGETW(&buf[23]) - HGETW(&buf[25]);
 1288         sc->calib_data[3].usage = HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X);
 1289         sc->calib_data[3].code = ABS_X;
 1290         sc->calib_data[3].range = PS4DS_ACC_RES_PER_G * 4;
 1291         sc->calib_data[3].res = PS4DS_ACC_RES_PER_G;
 1292         sc->calib_data[3].bias = HGETW(&buf[23]) - range_2g / 2;
 1293         sc->calib_data[3].sens_numer = 2 * PS4DS_ACC_RES_PER_G;
 1294         sc->calib_data[3].sens_denom = range_2g;
 1295 
 1296         range_2g = HGETW(&buf[27]) - HGETW(&buf[29]);
 1297         sc->calib_data[4].usage =  HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y);
 1298         sc->calib_data[4].code = ABS_Y;
 1299         sc->calib_data[4].range = PS4DS_ACC_RES_PER_G * 4;
 1300         sc->calib_data[4].res = PS4DS_ACC_RES_PER_G;
 1301         sc->calib_data[4].bias = HGETW(&buf[27]) - range_2g / 2;
 1302         sc->calib_data[4].sens_numer = 2 * PS4DS_ACC_RES_PER_G;
 1303         sc->calib_data[4].sens_denom = range_2g;
 1304 
 1305         range_2g = HGETW(&buf[31]) - HGETW(&buf[33]);
 1306         sc->calib_data[5].usage = HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Z);
 1307         sc->calib_data[5].code = ABS_Z;
 1308         sc->calib_data[5].range = PS4DS_ACC_RES_PER_G * 4;
 1309         sc->calib_data[5].res = PS4DS_ACC_RES_PER_G;
 1310         sc->calib_data[5].bias = HGETW(&buf[31]) - range_2g / 2;
 1311         sc->calib_data[5].sens_numer = 2 * PS4DS_ACC_RES_PER_G;
 1312         sc->calib_data[5].sens_denom = range_2g;
 1313 
 1314         return (hidmap_attach(&sc->hm));
 1315 }
 1316 
 1317 static int
 1318 ps4dshead_attach(device_t dev)
 1319 {
 1320         return (hidmap_attach(device_get_softc(dev)));
 1321 }
 1322 
 1323 static int
 1324 ps4dsmtp_attach(device_t dev)
 1325 {
 1326         struct ps4dsmtp_softc *sc = device_get_softc(dev);
 1327 
 1328         return (hidmap_attach(&sc->hm));
 1329 }
 1330 
 1331 static int
 1332 ps4dshock_detach(device_t dev)
 1333 {
 1334         struct ps4dshock_softc *sc = device_get_softc(dev);
 1335 
 1336         hidmap_detach(&sc->hm);
 1337         sc->led_state = PS4DS_LED_OFF;
 1338         ps4dshock_write(sc);
 1339         sx_destroy(&sc->lock);
 1340 
 1341         return (0);
 1342 }
 1343 
 1344 static int
 1345 ps4dsacc_detach(device_t dev)
 1346 {
 1347         struct ps4dsacc_softc *sc = device_get_softc(dev);
 1348 
 1349         return (hidmap_detach(&sc->hm));
 1350 }
 1351 
 1352 static int
 1353 ps4dshead_detach(device_t dev)
 1354 {
 1355         return (hidmap_detach(device_get_softc(dev)));
 1356 }
 1357 
 1358 static int
 1359 ps4dsmtp_detach(device_t dev)
 1360 {
 1361         struct ps4dsmtp_softc *sc = device_get_softc(dev);
 1362 
 1363         return (hidmap_detach(&sc->hm));
 1364 }
 1365 
 1366 static devclass_t ps4dshock_devclass;
 1367 static devclass_t ps4dsacc_devclass;
 1368 static devclass_t ps4dshead_devclass;
 1369 static devclass_t ps4dsmtp_devclass;
 1370 
 1371 static device_method_t ps4dshock_methods[] = {
 1372         DEVMETHOD(device_identify,      ps4dshock_identify),
 1373         DEVMETHOD(device_probe,         ps4dshock_probe),
 1374         DEVMETHOD(device_attach,        ps4dshock_attach),
 1375         DEVMETHOD(device_detach,        ps4dshock_detach),
 1376 
 1377         DEVMETHOD_END
 1378 };
 1379 static device_method_t ps4dsacc_methods[] = {
 1380         DEVMETHOD(device_probe,         ps4dsacc_probe),
 1381         DEVMETHOD(device_attach,        ps4dsacc_attach),
 1382         DEVMETHOD(device_detach,        ps4dsacc_detach),
 1383 
 1384         DEVMETHOD_END
 1385 };
 1386 static device_method_t ps4dshead_methods[] = {
 1387         DEVMETHOD(device_probe,         ps4dshead_probe),
 1388         DEVMETHOD(device_attach,        ps4dshead_attach),
 1389         DEVMETHOD(device_detach,        ps4dshead_detach),
 1390 
 1391         DEVMETHOD_END
 1392 };
 1393 static device_method_t ps4dsmtp_methods[] = {
 1394         DEVMETHOD(device_probe,         ps4dsmtp_probe),
 1395         DEVMETHOD(device_attach,        ps4dsmtp_attach),
 1396         DEVMETHOD(device_detach,        ps4dsmtp_detach),
 1397 
 1398         DEVMETHOD_END
 1399 };
 1400 
 1401 DEFINE_CLASS_0(ps4dsacc, ps4dsacc_driver, ps4dsacc_methods,
 1402     sizeof(struct ps4dsacc_softc));
 1403 DRIVER_MODULE(ps4dsacc, hidbus, ps4dsacc_driver, ps4dsacc_devclass, NULL, 0);
 1404 DEFINE_CLASS_0(ps4dshead, ps4dshead_driver, ps4dshead_methods,
 1405     sizeof(struct hidmap));
 1406 DRIVER_MODULE(ps4dshead, hidbus, ps4dshead_driver, ps4dshead_devclass, NULL, 0);
 1407 DEFINE_CLASS_0(ps4dsmtp, ps4dsmtp_driver, ps4dsmtp_methods,
 1408     sizeof(struct ps4dsmtp_softc));
 1409 DRIVER_MODULE(ps4dsmtp, hidbus, ps4dsmtp_driver, ps4dsmtp_devclass, NULL, 0);
 1410 DEFINE_CLASS_0(ps4dshock, ps4dshock_driver, ps4dshock_methods,
 1411     sizeof(struct ps4dshock_softc));
 1412 DRIVER_MODULE(ps4dshock, hidbus, ps4dshock_driver, ps4dshock_devclass, NULL, 0);
 1413 
 1414 MODULE_DEPEND(ps4dshock, hid, 1, 1, 1);
 1415 MODULE_DEPEND(ps4dshock, hidbus, 1, 1, 1);
 1416 MODULE_DEPEND(ps4dshock, hidmap, 1, 1, 1);
 1417 MODULE_DEPEND(ps4dshock, evdev, 1, 1, 1);
 1418 MODULE_VERSION(ps4dshock, 1);
 1419 HID_PNP_INFO(ps4dshock_devs);

Cache object: 7568e8cfd8eb867434637119d1df6b48


[ 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.