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/hgame.h>
   54 #include <dev/hid/hid.h>
   55 #include <dev/hid/hidbus.h>
   56 #include <dev/hid/hidquirk.h>
   57 #include <dev/hid/hidmap.h>
   58 #include "usbdevs.h"
   59 
   60 #ifdef HID_DEBUG
   61 static int ps4dshock_debug = 1;
   62 
   63 static SYSCTL_NODE(_hw_hid, OID_AUTO, ps4dshock, CTLFLAG_RW, 0,
   64                 "Sony PS4 DualShock Gamepad");
   65 SYSCTL_INT(_hw_hid_ps4dshock, OID_AUTO, debug, CTLFLAG_RWTUN,
   66                 &ps4dshock_debug, 0, "Debug level");
   67 #endif
   68 
   69 static const uint8_t    ps4dshock_rdesc[] = {
   70         0x05, 0x01,             /* Usage Page (Generic Desktop Ctrls)   */
   71         0x09, 0x05,             /* Usage (Game Pad)                     */
   72         0xA1, 0x01,             /* Collection (Application)             */
   73         0x85, 0x01,             /*   Report ID (1)                      */
   74         0x09, 0x30,             /*   Usage (X)                          */
   75         0x09, 0x31,             /*   Usage (Y)                          */
   76         0x09, 0x33,             /*   Usage (Rx)                         */
   77         0x09, 0x34,             /*   Usage (Ry)                         */
   78         0x15, 0x00,             /*   Logical Minimum (0)                */
   79         0x26, 0xFF, 0x00,       /*   Logical Maximum (255)              */
   80         0x75, 0x08,             /*   Report Size (8)                    */
   81         0x95, 0x04,             /*   Report Count (4)                   */
   82         0x81, 0x02,             /*   Input (Data,Var,Abs)               */
   83         0x09, 0x39,             /*   Usage (Hat switch)                 */
   84         0x15, 0x00,             /*   Logical Minimum (0)                */
   85         0x25, 0x07,             /*   Logical Maximum (7)                */
   86         0x35, 0x00,             /*   Physical Minimum (0)               */
   87         0x46, 0x3B, 0x01,       /*   Physical Maximum (315)             */
   88         0x65, 0x14,             /*   Unit (System: English Rotation, Length: Centimeter) */
   89         0x75, 0x04,             /*   Report Size (4)                    */
   90         0x95, 0x01,             /*   Report Count (1)                   */
   91         0x81, 0x42,             /*   Input (Data,Var,Abs,Null State)    */
   92         0x65, 0x00,             /*   Unit (None)                        */
   93         0x45, 0x00,             /*   Physical Maximum (0)               */
   94         0x05, 0x09,             /*   Usage Page (Button)                */
   95         0x19, 0x01,             /*   Usage Minimum (0x01)               */
   96         0x29, 0x0E,             /*   Usage Maximum (0x0E)               */
   97         0x15, 0x00,             /*   Logical Minimum (0)                */
   98         0x25, 0x01,             /*   Logical Maximum (1)                */
   99         0x75, 0x01,             /*   Report Size (1)                    */
  100         0x95, 0x0E,             /*   Report Count (14)                  */
  101         0x81, 0x02,             /*   Input (Data,Var,Abs)               */
  102         0x06, 0x00, 0xFF,       /*   Usage Page (Vendor Defined 0xFF00) */
  103         0x09, 0x20,             /*   Usage (0x20)                       */
  104         0x75, 0x06,             /*   Report Size (6)                    */
  105         0x95, 0x01,             /*   Report Count (1)                   */
  106         0x15, 0x00,             /*   Logical Minimum (0)                */
  107         0x25, 0x3F,             /*   Logical Maximum (63)               */
  108         0x81, 0x02,             /*   Input (Data,Var,Abs)               */
  109         0x05, 0x01,             /*   Usage Page (Generic Desktop Ctrls) */
  110         0x09, 0x32,             /*   Usage (Z)                          */
  111         0x09, 0x35,             /*   Usage (Rz)                         */
  112         0x15, 0x00,             /*   Logical Minimum (0)                */
  113         0x26, 0xFF, 0x00,       /*   Logical Maximum (255)              */
  114         0x75, 0x08,             /*   Report Size (8)                    */
  115         0x95, 0x02,             /*   Report Count (2)                   */
  116         0x81, 0x02,             /*   Input (Data,Var,Abs)               */
  117         0xC0,                   /* End Collection                       */
  118         0x05, 0x01,             /* Usage Page (Generic Desktop Ctrls)   */
  119         0x09, 0x08,             /* Usage (Multi-axis Controller)        */
  120         0xA1, 0x01,             /* Collection (Application)             */
  121         0x06, 0x00, 0xFF,       /*   Usage Page (Vendor Defined 0xFF00) */
  122         0x09, 0x21,             /*   Usage (0x21)                       */
  123         0x27, 0xFF, 0xFF, 0x00, 0x00,   /*   Logical Maximum (65534)    */
  124         0x75, 0x10,             /*   Report Size (16)                   */
  125         0x95, 0x01,             /*   Report Count (1)                   */
  126         0x81, 0x02,             /*   Input (Data,Var,Abs)               */
  127         0x05, 0x06,             /*   Usage Page (Generic Dev Ctrls)     */
  128         0x09, 0x20,             /*   Usage (Battery Strength)           */
  129         0x26, 0xFF, 0x00,       /*   Logical Maximum (255)              */
  130         0x75, 0x08,             /*   Report Size (8)                    */
  131         0x95, 0x01,             /*   Report Count (1)                   */
  132         0x81, 0x02,             /*   Input (Data,Var,Abs)               */
  133         0x05, 0x01,             /*   Usage Page (Generic Desktop Ctrls) */
  134         0x19, 0x33,             /*   Usage Minimum (RX)                 */
  135         0x29, 0x35,             /*   Usage Maximum (RZ)                 */
  136         0x16, 0x00, 0x80,       /*   Logical Minimum (-32768)           */
  137         0x26, 0xFF, 0x7F,       /*   Logical Maximum (32767)            */
  138         0x75, 0x10,             /*   Report Size (16)                   */
  139         0x95, 0x03,             /*   Report Count (3)                   */
  140         0x81, 0x02,             /*   Input (Data,Var,Abs)               */
  141         0x19, 0x30,             /*   Usage Minimum (X)                  */
  142         0x29, 0x32,             /*   Usage Maximum (Z)                  */
  143         0x16, 0x00, 0x80,       /*   Logical Minimum (-32768)           */
  144         0x26, 0xFF, 0x7F,       /*   Logical Maximum (32767)            */
  145         0x95, 0x03,             /*   Report Count (3)                   */
  146         0x81, 0x02,             /*   Input (Data,Var,Abs)               */
  147         0x06, 0x00, 0xFF,       /*   Usage Page (Vendor Defined 0xFF00) */
  148         0x09, 0x21,             /*   Usage (0x21)                       */
  149         0x15, 0x00,             /*   Logical Minimum (0)                */
  150         0x26, 0xFF, 0x00,       /*   Logical Maximum (255)              */
  151         0x75, 0x08,             /*   Report Size (8)                    */
  152         0x95, 0x05,             /*   Report Count (5)                   */
  153         0x81, 0x03,             /*   Input (Const)                      */
  154         0xC0,                   /* End Collection                       */
  155         0x05, 0x0C,             /* Usage Page (Consumer)                */
  156         0x09, 0x05,             /* Usage (Headphone)                    */
  157         0xA1, 0x01,             /* Collection (Application)             */
  158         0x75, 0x05,             /*   Report Size (5)                    */
  159         0x95, 0x01,             /*   Report Count (1)                   */
  160         0x81, 0x03,             /*   Input (Const)                      */
  161         0x06, 0x00, 0xFF,       /*   Usage Page (Vendor Defined 0xFF00) */
  162         0x09, 0x20,             /*   Usage (0x20)                       */
  163         0x09, 0x21,             /*   Usage (0x21)                       */
  164         0x15, 0x00,             /*   Logical Minimum (0)                */
  165         0x25, 0x01,             /*   Logical Maximum (1)                */
  166         0x75, 0x01,             /*   Report Size (1)                    */
  167         0x95, 0x02,             /*   Report Count (2)                   */
  168         0x81, 0x02,             /*   Input (Data,Var,Abs)               */
  169         0x75, 0x01,             /*   Report Size (1)                    */
  170         0x95, 0x01,             /*   Report Count (1)                   */
  171         0x81, 0x03,             /*   Input (Const)                      */
  172         0x75, 0x08,             /*   Report Size (8)                    */
  173         0x95, 0x02,             /*   Report Count (2)                   */
  174         0x81, 0x03,             /*   Input (Const)                      */
  175         0xC0,                   /* End Collection                       */
  176         0x05, 0x0D,             /* Usage Page (Digitizer)               */
  177         0x09, 0x05,             /* Usage (Touch Pad)                    */
  178         0xA1, 0x01,             /* Collection (Application)             */
  179         0x06, 0x00, 0xFF,       /*   Usage Page (Vendor Defined 0xFF00) */
  180         0x09, 0x21,             /*   Usage (0x21)                       */
  181         0x15, 0x00,             /*   Logical Minimum (0)                */
  182         0x25, 0x03,             /*   Logical Maximum (3)                */
  183         0x75, 0x04,             /*   Report Size (4)                    */
  184         0x95, 0x01,             /*   Report Count (1)                   */
  185         0x81, 0x02,             /*   Input (Data,Var,Abs)               */
  186         0x75, 0x04,             /*   Report Size (4)                    */
  187         0x95, 0x01,             /*   Report Count (1)                   */
  188         0x81, 0x03,             /*   Input (Data,Var,Abs)               */
  189         0x05, 0x0D,             /*   Usage Page (Digitizer)             */
  190         0x09, 0x56,             /*   Usage (0x56)                       */
  191         0x55, 0x0C,             /*   Unit Exponent (-4)                 */
  192         0x66, 0x01, 0x10,       /*   Unit (System: SI Linear, Time: Seconds) */
  193         0x46, 0xCC, 0x06,       /*   Physical Maximum (1740)            */
  194         0x26, 0xFF, 0x00,       /*   Logical Maximum (255)              */
  195         0x75, 0x08,             /*   Report Size (8)                    */
  196         0x95, 0x01,             /*   Report Count (1)                   */
  197         0x81, 0x02,             /*   Input (Data,Var,Abs)               */
  198         0x65, 0x00,             /*   Unit (None)                        */
  199         0x45, 0x00,             /*   Physical Maximum (0)               */
  200         0x05, 0x0D,             /*   Usage Page (Digitizer)             */
  201         0x09, 0x22,             /*   Usage (Finger)                     */
  202         0xA1, 0x02,             /*   Collection (Logical)               */
  203         0x09, 0x51,             /*     Usage (0x51)                     */
  204         0x25, 0x7F,             /*     Logical Maximum (127)            */
  205         0x75, 0x07,             /*     Report Size (7)                  */
  206         0x95, 0x01,             /*     Report Count (1)                 */
  207         0x81, 0x02,             /*     Input (Data,Var,Abs)             */
  208         0x09, 0x42,             /*     Usage (Tip Switch)               */
  209         0x25, 0x01,             /*     Logical Maximum (1)              */
  210         0x75, 0x01,             /*     Report Size (1)                  */
  211         0x95, 0x01,             /*     Report Count (1)                 */
  212         0x81, 0x02,             /*     Input (Data,Var,Abs)             */
  213         0x05, 0x01,             /*     Usage Page (Generic Desktop Ctrls) */
  214         0x09, 0x30,             /*     Usage (X)                        */
  215         0x55, 0x0E,             /*     Unit Exponent (-2)               */
  216         0x65, 0x11,             /*     Unit (System: SI Linear, Length: Centimeter) */
  217         0x35, 0x00,             /*     Physical Minimum (0)             */
  218         0x46, 0xB8, 0x01,       /*     Physical Maximum (440)           */
  219         0x26, 0x80, 0x07,       /*     Logical Maximum (1920)           */
  220         0x75, 0x0C,             /*     Report Size (12)                 */
  221         0x81, 0x02,             /*     Input (Data,Var,Abs)             */
  222         0x09, 0x31,             /*     Usage (Y)                        */
  223         0x46, 0xC0, 0x00,       /*     Physical Maximum (192)           */
  224         0x26, 0xAE, 0x03,       /*     Logical Maximum (942)            */
  225         0x81, 0x02,             /*     Input (Data,Var,Abs)             */
  226         0x65, 0x00,             /*     Unit (None)                      */
  227         0x45, 0x00,             /*     Physical Maximum (0)             */
  228         0xC0,                   /*   End Collection                     */
  229         0x05, 0x0D,             /*   Usage Page (Digitizer)             */
  230         0x09, 0x22,             /*   Usage (Finger)                     */
  231         0xA1, 0x02,             /*   Collection (Logical)               */
  232         0x09, 0x51,             /*     Usage (0x51)                     */
  233         0x25, 0x7F,             /*     Logical Maximum (127)            */
  234         0x75, 0x07,             /*     Report Size (7)                  */
  235         0x95, 0x01,             /*     Report Count (1)                 */
  236         0x81, 0x02,             /*     Input (Data,Var,Abs)             */
  237         0x09, 0x42,             /*     Usage (Tip Switch)               */
  238         0x25, 0x01,             /*     Logical Maximum (1)              */
  239         0x75, 0x01,             /*     Report Size (1)                  */
  240         0x95, 0x01,             /*     Report Count (1)                 */
  241         0x81, 0x02,             /*     Input (Data,Var,Abs)             */
  242         0x05, 0x01,             /*     Usage Page (Generic Desktop Ctrls) */
  243         0x09, 0x30,             /*     Usage (X)                        */
  244         0x55, 0x0E,             /*     Unit Exponent (-2)               */
  245         0x65, 0x11,             /*     Unit (System: SI Linear, Length: Centimeter) */
  246         0x35, 0x00,             /*     Physical Minimum (0)             */
  247         0x46, 0xB8, 0x01,       /*     Physical Maximum (440)           */
  248         0x26, 0x80, 0x07,       /*     Logical Maximum (1920)           */
  249         0x75, 0x0C,             /*     Report Size (12)                 */
  250         0x81, 0x02,             /*     Input (Data,Var,Abs)             */
  251         0x09, 0x31,             /*     Usage (Y)                        */
  252         0x46, 0xC0, 0x00,       /*     Physical Maximum (192)           */
  253         0x26, 0xAE, 0x03,       /*     Logical Maximum (942)            */
  254         0x81, 0x02,             /*     Input (Data,Var,Abs)             */
  255         0x65, 0x00,             /*     Unit (None)                      */
  256         0x45, 0x00,             /*     Physical Maximum (0)             */
  257         0xC0,                   /*   End Collection                     */
  258         0x05, 0x0D,             /*   Usage Page (Digitizer)             */
  259         0x09, 0x56,             /*   Usage (0x56)                       */
  260         0x55, 0x0C,             /*   Unit Exponent (-4)                 */
  261         0x66, 0x01, 0x10,       /*   Unit (System: SI Linear, Time: Seconds) */
  262         0x46, 0xCC, 0x06,       /*   Physical Maximum (1740)            */
  263         0x26, 0xFF, 0x00,       /*   Logical Maximum (255)              */
  264         0x75, 0x08,             /*   Report Size (8)                    */
  265         0x95, 0x01,             /*   Report Count (1)                   */
  266         0x81, 0x02,             /*   Input (Data,Var,Abs)               */
  267         0x65, 0x00,             /*   Unit (None)                        */
  268         0x45, 0x00,             /*   Physical Maximum (0)               */
  269         0x05, 0x0D,             /*   Usage Page (Digitizer)             */
  270         0x09, 0x22,             /*   Usage (Finger)                     */
  271         0xA1, 0x02,             /*   Collection (Logical)               */
  272         0x09, 0x51,             /*     Usage (0x51)                     */
  273         0x25, 0x7F,             /*     Logical Maximum (127)            */
  274         0x75, 0x07,             /*     Report Size (7)                  */
  275         0x95, 0x01,             /*     Report Count (1)                 */
  276         0x81, 0x02,             /*     Input (Data,Var,Abs)             */
  277         0x09, 0x42,             /*     Usage (Tip Switch)               */
  278         0x25, 0x01,             /*     Logical Maximum (1)              */
  279         0x75, 0x01,             /*     Report Size (1)                  */
  280         0x95, 0x01,             /*     Report Count (1)                 */
  281         0x81, 0x02,             /*     Input (Data,Var,Abs)             */
  282         0x05, 0x01,             /*     Usage Page (Generic Desktop Ctrls) */
  283         0x09, 0x30,             /*     Usage (X)                        */
  284         0x55, 0x0E,             /*     Unit Exponent (-2)               */
  285         0x65, 0x11,             /*     Unit (System: SI Linear, Length: Centimeter) */
  286         0x35, 0x00,             /*     Physical Minimum (0)             */
  287         0x46, 0xB8, 0x01,       /*     Physical Maximum (440)           */
  288         0x26, 0x80, 0x07,       /*     Logical Maximum (1920)           */
  289         0x75, 0x0C,             /*     Report Size (12)                 */
  290         0x81, 0x02,             /*     Input (Data,Var,Abs)             */
  291         0x09, 0x31,             /*     Usage (Y)                        */
  292         0x46, 0xC0, 0x00,       /*     Physical Maximum (192)           */
  293         0x26, 0xAE, 0x03,       /*     Logical Maximum (942)            */
  294         0x81, 0x02,             /*     Input (Data,Var,Abs)             */
  295         0x65, 0x00,             /*     Unit (None)                      */
  296         0x45, 0x00,             /*     Physical Maximum (0)             */
  297         0xC0,                   /*   End Collection                     */
  298         0x05, 0x0D,             /*   Usage Page (Digitizer)             */
  299         0x09, 0x22,             /*   Usage (Finger)                     */
  300         0xA1, 0x02,             /*   Collection (Logical)               */
  301         0x09, 0x51,             /*     Usage (0x51)                     */
  302         0x25, 0x7F,             /*     Logical Maximum (127)            */
  303         0x75, 0x07,             /*     Report Size (7)                  */
  304         0x95, 0x01,             /*     Report Count (1)                 */
  305         0x81, 0x02,             /*     Input (Data,Var,Abs)             */
  306         0x09, 0x42,             /*     Usage (Tip Switch)               */
  307         0x25, 0x01,             /*     Logical Maximum (1)              */
  308         0x75, 0x01,             /*     Report Size (1)                  */
  309         0x95, 0x01,             /*     Report Count (1)                 */
  310         0x81, 0x02,             /*     Input (Data,Var,Abs)             */
  311         0x05, 0x01,             /*     Usage Page (Generic Desktop Ctrls) */
  312         0x09, 0x30,             /*     Usage (X)                        */
  313         0x55, 0x0E,             /*     Unit Exponent (-2)               */
  314         0x65, 0x11,             /*     Unit (System: SI Linear, Length: Centimeter) */
  315         0x35, 0x00,             /*     Physical Minimum (0)             */
  316         0x46, 0xB8, 0x01,       /*     Physical Maximum (440)           */
  317         0x26, 0x80, 0x07,       /*     Logical Maximum (1920)           */
  318         0x75, 0x0C,             /*     Report Size (12)                 */
  319         0x81, 0x02,             /*     Input (Data,Var,Abs)             */
  320         0x09, 0x31,             /*     Usage (Y)                        */
  321         0x46, 0xC0, 0x00,       /*     Physical Maximum (192)           */
  322         0x26, 0xAE, 0x03,       /*     Logical Maximum (942)            */
  323         0x81, 0x02,             /*     Input (Data,Var,Abs)             */
  324         0x65, 0x00,             /*     Unit (None)                      */
  325         0x45, 0x00,             /*     Physical Maximum (0)             */
  326         0xC0,                   /*   End Collection                     */
  327         0x05, 0x0D,             /*   Usage Page (Digitizer)             */
  328         0x09, 0x56,             /*   Usage (0x56)                       */
  329         0x55, 0x0C,             /*   Unit Exponent (-4)                 */
  330         0x66, 0x01, 0x10,       /*   Unit (System: SI Linear, Time: Seconds) */
  331         0x46, 0xCC, 0x06,       /*   Physical Maximum (1740)            */
  332         0x26, 0xFF, 0x00,       /*   Logical Maximum (255)              */
  333         0x75, 0x08,             /*   Report Size (8)                    */
  334         0x95, 0x01,             /*   Report Count (1)                   */
  335         0x81, 0x02,             /*   Input (Data,Var,Abs)               */
  336         0x65, 0x00,             /*   Unit (None)                        */
  337         0x45, 0x00,             /*   Physical Maximum (0)               */
  338         0x05, 0x0D,             /*   Usage Page (Digitizer)             */
  339         0x09, 0x22,             /*   Usage (Finger)                     */
  340         0xA1, 0x02,             /*   Collection (Logical)               */
  341         0x09, 0x51,             /*     Usage (0x51)                     */
  342         0x25, 0x7F,             /*     Logical Maximum (127)            */
  343         0x75, 0x07,             /*     Report Size (7)                  */
  344         0x95, 0x01,             /*     Report Count (1)                 */
  345         0x81, 0x02,             /*     Input (Data,Var,Abs)             */
  346         0x09, 0x42,             /*     Usage (Tip Switch)               */
  347         0x25, 0x01,             /*     Logical Maximum (1)              */
  348         0x75, 0x01,             /*     Report Size (1)                  */
  349         0x95, 0x01,             /*     Report Count (1)                 */
  350         0x81, 0x02,             /*     Input (Data,Var,Abs)             */
  351         0x05, 0x01,             /*     Usage Page (Generic Desktop Ctrls) */
  352         0x09, 0x30,             /*     Usage (X)                        */
  353         0x55, 0x0E,             /*     Unit Exponent (-2)               */
  354         0x65, 0x11,             /*     Unit (System: SI Linear, Length: Centimeter) */
  355         0x35, 0x00,             /*     Physical Minimum (0)             */
  356         0x46, 0xB8, 0x01,       /*     Physical Maximum (440)           */
  357         0x26, 0x80, 0x07,       /*     Logical Maximum (1920)           */
  358         0x75, 0x0C,             /*     Report Size (12)                 */
  359         0x81, 0x02,             /*     Input (Data,Var,Abs)             */
  360         0x09, 0x31,             /*     Usage (Y)                        */
  361         0x46, 0xC0, 0x00,       /*     Physical Maximum (192)           */
  362         0x26, 0xAE, 0x03,       /*     Logical Maximum (942)            */
  363         0x81, 0x02,             /*     Input (Data,Var,Abs)             */
  364         0x65, 0x00,             /*     Unit (None)                      */
  365         0x45, 0x00,             /*     Physical Maximum (0)             */
  366         0xC0,                   /*   End Collection                     */
  367         0x05, 0x0D,             /*   Usage Page (Digitizer)             */
  368         0x09, 0x22,             /*   Usage (Finger)                     */
  369         0xA1, 0x02,             /*   Collection (Logical)               */
  370         0x09, 0x51,             /*     Usage (0x51)                     */
  371         0x25, 0x7F,             /*     Logical Maximum (127)            */
  372         0x75, 0x07,             /*     Report Size (7)                  */
  373         0x95, 0x01,             /*     Report Count (1)                 */
  374         0x81, 0x02,             /*     Input (Data,Var,Abs)             */
  375         0x09, 0x42,             /*     Usage (Tip Switch)               */
  376         0x25, 0x01,             /*     Logical Maximum (1)              */
  377         0x75, 0x01,             /*     Report Size (1)                  */
  378         0x95, 0x01,             /*     Report Count (1)                 */
  379         0x81, 0x02,             /*     Input (Data,Var,Abs)             */
  380         0x05, 0x01,             /*     Usage Page (Generic Desktop Ctrls) */
  381         0x09, 0x30,             /*     Usage (X)                        */
  382         0x55, 0x0E,             /*     Unit Exponent (-2)               */
  383         0x65, 0x11,             /*     Unit (System: SI Linear, Length: Centimeter) */
  384         0x35, 0x00,             /*     Physical Minimum (0)             */
  385         0x46, 0xB8, 0x01,       /*     Physical Maximum (440)           */
  386         0x26, 0x80, 0x07,       /*     Logical Maximum (1920)           */
  387         0x75, 0x0C,             /*     Report Size (12)                 */
  388         0x81, 0x02,             /*     Input (Data,Var,Abs)             */
  389         0x09, 0x31,             /*     Usage (Y)                        */
  390         0x46, 0xC0, 0x00,       /*     Physical Maximum (192)           */
  391         0x26, 0xAE, 0x03,       /*     Logical Maximum (942)            */
  392         0x81, 0x02,             /*     Input (Data,Var,Abs)             */
  393         0x65, 0x00,             /*     Unit (None)                      */
  394         0x45, 0x00,             /*     Physical Maximum (0)             */
  395         0xC0,                   /*   End Collection                     */
  396         0x75, 0x08,             /*   Report Size (8)                    */
  397         0x95, 0x03,             /*   Report Count (3)                   */
  398         0x81, 0x03,             /*   Input (Const)                      */
  399         /* Output and feature reports */
  400         0x85, 0x05,             /*   Report ID (5)                      */
  401         0x06, 0x00, 0xFF,       /*   Usage Page (Vendor Defined 0xFF00) */
  402         0x09, 0x22,             /*   Usage (0x22)                       */
  403         0x15, 0x00,             /*   Logical Minimum (0)                */
  404         0x26, 0xFF, 0x00,       /*   Logical Maximum (255)              */
  405         0x95, 0x1F,             /*   Report Count (31)                  */
  406         0x91, 0x02,             /*   Output (Data,Var,Abs)              */
  407         0x85, 0x04,             /*   Report ID (4)                      */
  408         0x09, 0x23,             /*   Usage (0x23)                       */
  409         0x95, 0x24,             /*   Report Count (36)                  */
  410         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  411         0x85, 0x02,             /*   Report ID (2)                      */
  412         0x09, 0x24,             /*   Usage (0x24)                       */
  413         0x95, 0x24,             /*   Report Count (36)                  */
  414         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  415         0x85, 0x08,             /*   Report ID (8)                      */
  416         0x09, 0x25,             /*   Usage (0x25)                       */
  417         0x95, 0x03,             /*   Report Count (3)                   */
  418         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  419         0x85, 0x10,             /*   Report ID (16)                     */
  420         0x09, 0x26,             /*   Usage (0x26)                       */
  421         0x95, 0x04,             /*   Report Count (4)                   */
  422         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  423         0x85, 0x11,             /*   Report ID (17)                     */
  424         0x09, 0x27,             /*   Usage (0x27)                       */
  425         0x95, 0x02,             /*   Report Count (2)                   */
  426         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  427         0x85, 0x12,             /*   Report ID (18)                     */
  428         0x06, 0x02, 0xFF,       /*   Usage Page (Vendor Defined 0xFF02) */
  429         0x09, 0x21,             /*   Usage (0x21)                       */
  430         0x95, 0x0F,             /*   Report Count (15)                  */
  431         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  432         0x85, 0x13,             /*   Report ID (19)                     */
  433         0x09, 0x22,             /*   Usage (0x22)                       */
  434         0x95, 0x16,             /*   Report Count (22)                  */
  435         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  436         0x85, 0x14,             /*   Report ID (20)                     */
  437         0x06, 0x05, 0xFF,       /*   Usage Page (Vendor Defined 0xFF05) */
  438         0x09, 0x20,             /*   Usage (0x20)                       */
  439         0x95, 0x10,             /*   Report Count (16)                  */
  440         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  441         0x85, 0x15,             /*   Report ID (21)                     */
  442         0x09, 0x21,             /*   Usage (0x21)                       */
  443         0x95, 0x2C,             /*   Report Count (44)                  */
  444         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  445         0x06, 0x80, 0xFF,       /*   Usage Page (Vendor Defined 0xFF80) */
  446         0x85, 0x80,             /*   Report ID (-128)                   */
  447         0x09, 0x20,             /*   Usage (0x20)                       */
  448         0x95, 0x06,             /*   Report Count (6)                   */
  449         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  450         0x85, 0x81,             /*   Report ID (-127)                   */
  451         0x09, 0x21,             /*   Usage (0x21)                       */
  452         0x95, 0x06,             /*   Report Count (6)                   */
  453         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  454         0x85, 0x82,             /*   Report ID (-126)                   */
  455         0x09, 0x22,             /*   Usage (0x22)                       */
  456         0x95, 0x05,             /*   Report Count (5)                   */
  457         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  458         0x85, 0x83,             /*   Report ID (-125)                   */
  459         0x09, 0x23,             /*   Usage (0x23)                       */
  460         0x95, 0x01,             /*   Report Count (1)                   */
  461         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  462         0x85, 0x84,             /*   Report ID (-124)                   */
  463         0x09, 0x24,             /*   Usage (0x24)                       */
  464         0x95, 0x04,             /*   Report Count (4)                   */
  465         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  466         0x85, 0x85,             /*   Report ID (-123)                   */
  467         0x09, 0x25,             /*   Usage (0x25)                       */
  468         0x95, 0x06,             /*   Report Count (6)                   */
  469         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  470         0x85, 0x86,             /*   Report ID (-122)                   */
  471         0x09, 0x26,             /*   Usage (0x26)                       */
  472         0x95, 0x06,             /*   Report Count (6)                   */
  473         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  474         0x85, 0x87,             /*   Report ID (-121)                   */
  475         0x09, 0x27,             /*   Usage (0x27)                       */
  476         0x95, 0x23,             /*   Report Count (35)                  */
  477         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  478         0x85, 0x88,             /*   Report ID (-120)                   */
  479         0x09, 0x28,             /*   Usage (0x28)                       */
  480         0x95, 0x22,             /*   Report Count (34)                  */
  481         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  482         0x85, 0x89,             /*   Report ID (-119)                   */
  483         0x09, 0x29,             /*   Usage (0x29)                       */
  484         0x95, 0x02,             /*   Report Count (2)                   */
  485         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  486         0x85, 0x90,             /*   Report ID (-112)                   */
  487         0x09, 0x30,             /*   Usage (0x30)                       */
  488         0x95, 0x05,             /*   Report Count (5)                   */
  489         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  490         0x85, 0x91,             /*   Report ID (-111)                   */
  491         0x09, 0x31,             /*   Usage (0x31)                       */
  492         0x95, 0x03,             /*   Report Count (3)                   */
  493         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  494         0x85, 0x92,             /*   Report ID (-110)                   */
  495         0x09, 0x32,             /*   Usage (0x32)                       */
  496         0x95, 0x03,             /*   Report Count (3)                   */
  497         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  498         0x85, 0x93,             /*   Report ID (-109)                   */
  499         0x09, 0x33,             /*   Usage (0x33)                       */
  500         0x95, 0x0C,             /*   Report Count (12)                  */
  501         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  502         0x85, 0xA0,             /*   Report ID (-96)                    */
  503         0x09, 0x40,             /*   Usage (0x40)                       */
  504         0x95, 0x06,             /*   Report Count (6)                   */
  505         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  506         0x85, 0xA1,             /*   Report ID (-95)                    */
  507         0x09, 0x41,             /*   Usage (0x41)                       */
  508         0x95, 0x01,             /*   Report Count (1)                   */
  509         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  510         0x85, 0xA2,             /*   Report ID (-94)                    */
  511         0x09, 0x42,             /*   Usage (0x42)                       */
  512         0x95, 0x01,             /*   Report Count (1)                   */
  513         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  514         0x85, 0xA3,             /*   Report ID (-93)                    */
  515         0x09, 0x43,             /*   Usage (0x43)                       */
  516         0x95, 0x30,             /*   Report Count (48)                  */
  517         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  518         0x85, 0xA4,             /*   Report ID (-92)                    */
  519         0x09, 0x44,             /*   Usage (0x44)                       */
  520         0x95, 0x0D,             /*   Report Count (13)                  */
  521         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  522         0x85, 0xA5,             /*   Report ID (-91)                    */
  523         0x09, 0x45,             /*   Usage (0x45)                       */
  524         0x95, 0x15,             /*   Report Count (21)                  */
  525         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  526         0x85, 0xA6,             /*   Report ID (-90)                    */
  527         0x09, 0x46,             /*   Usage (0x46)                       */
  528         0x95, 0x15,             /*   Report Count (21)                  */
  529         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  530         0x85, 0xF0,             /*   Report ID (-16)                    */
  531         0x09, 0x47,             /*   Usage (0x47)                       */
  532         0x95, 0x3F,             /*   Report Count (63)                  */
  533         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  534         0x85, 0xF1,             /*   Report ID (-15)                    */
  535         0x09, 0x48,             /*   Usage (0x48)                       */
  536         0x95, 0x3F,             /*   Report Count (63)                  */
  537         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  538         0x85, 0xF2,             /*   Report ID (-14)                    */
  539         0x09, 0x49,             /*   Usage (0x49)                       */
  540         0x95, 0x0F,             /*   Report Count (15)                  */
  541         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  542         0x85, 0xA7,             /*   Report ID (-89)                    */
  543         0x09, 0x4A,             /*   Usage (0x4A)                       */
  544         0x95, 0x01,             /*   Report Count (1)                   */
  545         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  546         0x85, 0xA8,             /*   Report ID (-88)                    */
  547         0x09, 0x4B,             /*   Usage (0x4B)                       */
  548         0x95, 0x01,             /*   Report Count (1)                   */
  549         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  550         0x85, 0xA9,             /*   Report ID (-87)                    */
  551         0x09, 0x4C,             /*   Usage (0x4C)                       */
  552         0x95, 0x08,             /*   Report Count (8)                   */
  553         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  554         0x85, 0xAA,             /*   Report ID (-86)                    */
  555         0x09, 0x4E,             /*   Usage (0x4E)                       */
  556         0x95, 0x01,             /*   Report Count (1)                   */
  557         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  558         0x85, 0xAB,             /*   Report ID (-85)                    */
  559         0x09, 0x4F,             /*   Usage (0x4F)                       */
  560         0x95, 0x39,             /*   Report Count (57)                  */
  561         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  562         0x85, 0xAC,             /*   Report ID (-84)                    */
  563         0x09, 0x50,             /*   Usage (0x50)                       */
  564         0x95, 0x39,             /*   Report Count (57)                  */
  565         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  566         0x85, 0xAD,             /*   Report ID (-83)                    */
  567         0x09, 0x51,             /*   Usage (0x51)                       */
  568         0x95, 0x0B,             /*   Report Count (11)                  */
  569         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  570         0x85, 0xAE,             /*   Report ID (-82)                    */
  571         0x09, 0x52,             /*   Usage (0x52)                       */
  572         0x95, 0x01,             /*   Report Count (1)                   */
  573         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  574         0x85, 0xAF,             /*   Report ID (-81)                    */
  575         0x09, 0x53,             /*   Usage (0x53)                       */
  576         0x95, 0x02,             /*   Report Count (2)                   */
  577         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  578         0x85, 0xB0,             /*   Report ID (-80)                    */
  579         0x09, 0x54,             /*   Usage (0x54)                       */
  580         0x95, 0x3F,             /*   Report Count (63)                  */
  581         0xB1, 0x02,             /*   Feature (Data,Var,Abs)             */
  582         0xC0,                   /* End Collection                       */
  583 };
  584 
  585 #define PS4DS_GYRO_RES_PER_DEG_S        1024
  586 #define PS4DS_ACC_RES_PER_G             8192
  587 #define PS4DS_MAX_TOUCHPAD_PACKETS      4
  588 #define PS4DS_FEATURE_REPORT2_SIZE      37
  589 #define PS4DS_OUTPUT_REPORT5_SIZE       32
  590 #define PS4DS_OUTPUT_REPORT11_SIZE      78
  591 
  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,       hgame_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_final_cb(HIDMAP_CB_ARGS)
  792 {
  793         struct evdev_dev *evdev = HIDMAP_CB_GET_EVDEV();
  794 
  795         if (HIDMAP_CB_GET_STATE() == HIDMAP_CB_IS_ATTACHING)
  796                 evdev_support_prop(evdev, INPUT_PROP_DIRECT);
  797 
  798         /* Do not execute callback at interrupt handler and detach */
  799         return (ENOSYS);
  800 }
  801 
  802 static int
  803 ps4dsacc_data_cb(HIDMAP_CB_ARGS)
  804 {
  805         struct evdev_dev *evdev = HIDMAP_CB_GET_EVDEV();
  806         struct ps4dsacc_softc *sc = HIDMAP_CB_GET_SOFTC();
  807         struct ps4ds_calib_data *calib;
  808         u_int i;
  809 
  810         switch (HIDMAP_CB_GET_STATE()) {
  811         case HIDMAP_CB_IS_ATTACHING:
  812                 for (i = 0; i < nitems(sc->calib_data); i++) {
  813                         if (sc->calib_data[i].usage == ctx.hi->usage) {
  814                                 evdev_support_abs(evdev,
  815                                      sc->calib_data[i].code,
  816                                     -sc->calib_data[i].range,
  817                                      sc->calib_data[i].range, 16, 0,
  818                                      sc->calib_data[i].res);
  819                                 HIDMAP_CB_UDATA = &sc->calib_data[i];
  820                                 break;
  821                         }
  822                 }
  823                 break;
  824 
  825         case HIDMAP_CB_IS_RUNNING:
  826                 calib = HIDMAP_CB_UDATA;
  827                 evdev_push_abs(evdev, calib->code,
  828                     ((int64_t)ctx.data - calib->bias) * calib->sens_numer /
  829                     calib->sens_denom);
  830                 break;
  831 
  832         default:
  833                 break;
  834         }
  835 
  836         return (0);
  837 }
  838 
  839 static int
  840 ps4dsacc_tstamp_cb(HIDMAP_CB_ARGS)
  841 {
  842         struct evdev_dev *evdev = HIDMAP_CB_GET_EVDEV();
  843         struct ps4dsacc_softc *sc = HIDMAP_CB_GET_SOFTC();
  844         uint16_t tstamp;
  845 
  846         switch (HIDMAP_CB_GET_STATE()) {
  847         case HIDMAP_CB_IS_ATTACHING:
  848                 evdev_support_event(evdev, EV_MSC);
  849                 evdev_support_msc(evdev, MSC_TIMESTAMP);
  850                 break;
  851 
  852         case HIDMAP_CB_IS_RUNNING:
  853                 /* Convert timestamp (in 5.33us unit) to timestamp_us */
  854                 tstamp = (uint16_t)ctx.data;
  855                 sc->ev_tstamp += (uint16_t)(tstamp - sc->hw_tstamp) * 16 / 3;
  856                 sc->hw_tstamp = tstamp;
  857                 evdev_push_msc(evdev, MSC_TIMESTAMP, sc->ev_tstamp);
  858                 break;
  859 
  860         default:
  861                 break;
  862         }
  863 
  864         return (0);
  865 }
  866 
  867 static int
  868 ps4dsacc_final_cb(HIDMAP_CB_ARGS)
  869 {
  870         struct evdev_dev *evdev = HIDMAP_CB_GET_EVDEV();
  871 
  872         if (HIDMAP_CB_GET_STATE() == HIDMAP_CB_IS_ATTACHING) {
  873                 evdev_support_event(evdev, EV_ABS);
  874                 evdev_support_prop(evdev, INPUT_PROP_ACCELEROMETER);
  875         }
  876         /* Do not execute callback at interrupt handler and detach */
  877         return (ENOSYS);
  878 }
  879 
  880 static int
  881 ps4dsmtp_npackets_cb(HIDMAP_CB_ARGS)
  882 {
  883         struct ps4dsmtp_softc *sc = HIDMAP_CB_GET_SOFTC();
  884 
  885         if (HIDMAP_CB_GET_STATE() == HIDMAP_CB_IS_RUNNING) {
  886                 sc->npackets = MIN(PS4DS_MAX_TOUCHPAD_PACKETS,(u_int)ctx.data);
  887                 /* Reset pointer here as it is first usage in touchpad TLC */
  888                 sc->data_ptr = sc->data;
  889         }
  890 
  891         return (0);
  892 }
  893 
  894 static int
  895 ps4dsmtp_data_cb(HIDMAP_CB_ARGS)
  896 {
  897         struct ps4dsmtp_softc *sc = HIDMAP_CB_GET_SOFTC();
  898 
  899         if (HIDMAP_CB_GET_STATE() == HIDMAP_CB_IS_RUNNING) {
  900                 *sc->data_ptr = ctx.data;
  901                 ++sc->data_ptr;
  902         }
  903 
  904         return (0);
  905 }
  906 
  907 static void
  908 ps4dsmtp_push_packet(struct ps4dsmtp_softc *sc, struct evdev_dev *evdev,
  909     int32_t *data)
  910 {
  911         uint8_t hw_tstamp, delta;
  912         bool touch;
  913 
  914         evdev_push_abs(evdev, ABS_MT_SLOT, 0);
  915         if (data[PS4DS_TIP1] == 0) {
  916                 evdev_push_abs(evdev, ABS_MT_TRACKING_ID, data[PS4DS_CID1]);
  917                 evdev_push_abs(evdev, ABS_MT_POSITION_X, data[PS4DS_X1]);
  918                 evdev_push_abs(evdev, ABS_MT_POSITION_Y, data[PS4DS_Y1]);
  919         } else
  920                 evdev_push_abs(evdev, ABS_MT_TRACKING_ID, -1);
  921         evdev_push_abs(evdev, ABS_MT_SLOT, 1);
  922         if (data[PS4DS_TIP2] == 0) {
  923                 evdev_push_abs(evdev, ABS_MT_TRACKING_ID, data[PS4DS_CID2]);
  924                 evdev_push_abs(evdev, ABS_MT_POSITION_X, data[PS4DS_X2]);
  925                 evdev_push_abs(evdev, ABS_MT_POSITION_Y, data[PS4DS_Y2]);
  926         } else
  927                 evdev_push_abs(evdev, ABS_MT_TRACKING_ID, -1);
  928 
  929         if (sc->do_tstamps) {
  930                 /*
  931                  * Export hardware timestamps in libinput-friendly way.
  932                  * Make timestamp counter 32-bit, scale up hardware
  933                  * timestamps to be on per 1usec basis and reset
  934                  * counter at the start of each touch.
  935                  */
  936                 hw_tstamp = (uint8_t)data[PS4DS_TSTAMP];
  937                 delta = hw_tstamp - sc->hw_tstamp;
  938                 sc->hw_tstamp = hw_tstamp;
  939                 touch = data[PS4DS_TIP1] == 0 || data[PS4DS_TIP2] == 0;
  940                 /* Hardware timestamp counter ticks in 682 usec interval. */
  941                 if ((touch || sc->touch) && delta != 0) {
  942                         if (sc->touch)
  943                                 sc->ev_tstamp += delta * 682;
  944                         evdev_push_msc(evdev, MSC_TIMESTAMP, sc->ev_tstamp);
  945                 }
  946                 if (!touch)
  947                         sc->ev_tstamp = 0;
  948                 sc->touch = touch;
  949         }
  950 }
  951 
  952 static int
  953 ps4dsmtp_final_cb(HIDMAP_CB_ARGS)
  954 {
  955         struct ps4dsmtp_softc *sc = HIDMAP_CB_GET_SOFTC();
  956         struct evdev_dev *evdev = HIDMAP_CB_GET_EVDEV();
  957         int32_t *data;
  958 
  959         switch (HIDMAP_CB_GET_STATE()) {
  960         case HIDMAP_CB_IS_ATTACHING:
  961                 if (hid_test_quirk(hid_get_device_info(sc->hm.dev),
  962                     HQ_MT_TIMESTAMP))
  963                         sc->do_tstamps = true;
  964                 /*
  965                  * Dualshock 4 touchpad TLC contained in fixed report
  966                  * descriptor is almost compatible with MS precission touchpad
  967                  * specs and hmt(4) driver. But... for some reasons "Click"
  968                  * button location was grouped with other GamePad buttons by
  969                  * touchpad designers so it belongs to GamePad TLC. Fix it with
  970                  * direct reading of "Click" button value from interrupt frame.
  971                  */
  972                 sc->btn_loc = (struct hid_location) { 1, 0, 49 };
  973                 evdev_support_event(evdev, EV_SYN);
  974                 evdev_support_event(evdev, EV_KEY);
  975                 evdev_support_event(evdev, EV_ABS);
  976                 if (sc->do_tstamps) {
  977                         evdev_support_event(evdev, EV_MSC);
  978                         evdev_support_msc(evdev, MSC_TIMESTAMP);
  979                 }
  980                 evdev_support_key(evdev, BTN_LEFT);
  981                 evdev_support_abs(evdev, ABS_MT_SLOT, 0, 1, 0, 0, 0);
  982                 evdev_support_abs(evdev, ABS_MT_TRACKING_ID, -1, 127, 0, 0, 0);
  983                 evdev_support_abs(evdev, ABS_MT_POSITION_X, 0, 1920, 0, 0, 30);
  984                 evdev_support_abs(evdev, ABS_MT_POSITION_Y, 0, 942, 0, 0, 49);
  985                 evdev_support_prop(evdev, INPUT_PROP_POINTER);
  986                 evdev_support_prop(evdev, INPUT_PROP_BUTTONPAD);
  987                 evdev_set_flag(evdev, EVDEV_FLAG_MT_STCOMPAT);
  988                 break;
  989 
  990         case HIDMAP_CB_IS_RUNNING:
  991                 /* Only packets with ReportID=1 are accepted */
  992                 if (HIDMAP_CB_GET_RID() != 1)
  993                         return (ENOTSUP);
  994                 evdev_push_key(evdev, BTN_LEFT,
  995                     HIDMAP_CB_GET_UDATA(&sc->btn_loc));
  996                 for (data = sc->data;
  997                      data < sc->data + PS4DS_NTPUSAGES * sc->npackets;
  998                      data += PS4DS_NTPUSAGES) {
  999                         ps4dsmtp_push_packet(sc, evdev, data);
 1000                         evdev_sync(evdev);
 1001                 }
 1002                 break;
 1003 
 1004         default:
 1005                 break;
 1006         }
 1007 
 1008         /* Do execute callback at interrupt handler and detach */
 1009         return (0);
 1010 }
 1011 
 1012 static int
 1013 ps4dshock_write(struct ps4dshock_softc *sc)
 1014 {
 1015         hid_size_t osize = sc->is_bluetooth ?
 1016             PS4DS_OUTPUT_REPORT11_SIZE : PS4DS_OUTPUT_REPORT5_SIZE;
 1017         uint8_t buf[osize];
 1018         int offset;
 1019         bool led_on, led_blinks;
 1020 
 1021         memset(buf, 0, osize);
 1022         buf[0] = sc->is_bluetooth ? 0x11 : 0x05;
 1023         offset = sc->is_bluetooth ? 3 : 1;
 1024         led_on = sc->led_state != PS4DS_LED_OFF;
 1025         led_blinks = sc->led_state == PS4DS_LED_BLINKING;
 1026         *(struct ps4ds_out5 *)(buf + offset) = (struct ps4ds_out5) {
 1027                 .features = 0x07, /* blink + LEDs + motor */
 1028                 .rumble_right = sc->rumble_right,
 1029                 .rumble_left = sc->rumble_left,
 1030                 .led_color_r = led_on ? sc->led_color.r : 0,
 1031                 .led_color_g = led_on ? sc->led_color.g : 0,
 1032                 .led_color_b = led_on ? sc->led_color.b : 0,
 1033                 /* convert milliseconds to centiseconds */
 1034                 .led_delay_on = led_blinks ? sc->led_delay_on / 10 : 0,
 1035                 .led_delay_off = led_blinks ? sc->led_delay_off / 10 : 0,
 1036         };
 1037 
 1038         return (hid_write(sc->hm.dev, buf, osize));
 1039 }
 1040 
 1041 /* Synaptics Touchpad */
 1042 static int
 1043 ps4dshock_sysctl(SYSCTL_HANDLER_ARGS)
 1044 {
 1045         struct ps4dshock_softc *sc;
 1046         int error, arg;
 1047 
 1048         if (oidp->oid_arg1 == NULL || oidp->oid_arg2 < 0 ||
 1049             oidp->oid_arg2 > PD4DSHOCK_SYSCTL_LAST)
 1050                 return (EINVAL);
 1051 
 1052         sc = oidp->oid_arg1;
 1053         sx_xlock(&sc->lock);
 1054 
 1055         /* Read the current value. */
 1056         arg = *(int *)((char *)sc + oidp->oid_arg2);
 1057         error = sysctl_handle_int(oidp, &arg, 0, req);
 1058 
 1059         /* Sanity check. */
 1060         if (error || !req->newptr)
 1061                 goto unlock;
 1062 
 1063         /*
 1064          * Check that the new value is in the concerned node's range
 1065          * of values.
 1066          */
 1067         switch (oidp->oid_arg2) {
 1068         case PD4DSHOCK_SYSCTL_LED_STATE:
 1069                 if (arg < 0 || arg >= PD4DS_LED_CNT)
 1070                         error = EINVAL;
 1071                 break;
 1072         case PD4DSHOCK_SYSCTL_LED_COLOR_R:
 1073         case PD4DSHOCK_SYSCTL_LED_COLOR_G:
 1074         case PD4DSHOCK_SYSCTL_LED_COLOR_B:
 1075                 if (arg < 0 || arg > UINT8_MAX)
 1076                         error = EINVAL;
 1077                 break;
 1078         case PD4DSHOCK_SYSCTL_LED_DELAY_ON:
 1079         case PD4DSHOCK_SYSCTL_LED_DELAY_OFF:
 1080                 if (arg < 0 || arg > UINT8_MAX * 10)
 1081                         error = EINVAL;
 1082                 break;
 1083         default:
 1084                 error = EINVAL;
 1085         }
 1086 
 1087         /* Update. */
 1088         if (error == 0) {
 1089                 *(int *)((char *)sc + oidp->oid_arg2) = arg;
 1090                 ps4dshock_write(sc);
 1091         }
 1092 unlock:
 1093         sx_unlock(&sc->lock);
 1094 
 1095         return (error);
 1096 }
 1097 
 1098 static void
 1099 ps4dshock_identify(driver_t *driver, device_t parent)
 1100 {
 1101 
 1102         /* Overload PS4 DualShock gamepad rudimentary report descriptor */
 1103         if (HIDBUS_LOOKUP_ID(parent, ps4dshock_devs) != NULL)
 1104                 hid_set_report_descr(parent, ps4dshock_rdesc,
 1105                     sizeof(ps4dshock_rdesc));
 1106 }
 1107 
 1108 static int
 1109 ps4dshock_probe(device_t dev)
 1110 {
 1111         struct ps4dshock_softc *sc = device_get_softc(dev);
 1112 
 1113         hidmap_set_debug_var(&sc->hm, &HID_DEBUG_VAR);
 1114         return (
 1115             HIDMAP_PROBE(&sc->hm, dev, ps4dshock_devs, ps4dshock_map, NULL)
 1116         );
 1117 }
 1118 
 1119 static int
 1120 ps4dsacc_probe(device_t dev)
 1121 {
 1122         struct ps4dsacc_softc *sc = device_get_softc(dev);
 1123 
 1124         hidmap_set_debug_var(&sc->hm, &HID_DEBUG_VAR);
 1125         return (
 1126             HIDMAP_PROBE(&sc->hm, dev, ps4dsacc_devs, ps4dsacc_map, "Sensors")
 1127         );
 1128 }
 1129 
 1130 static int
 1131 ps4dshead_probe(device_t dev)
 1132 {
 1133         struct hidmap *hm = device_get_softc(dev);
 1134 
 1135         hidmap_set_debug_var(hm, &HID_DEBUG_VAR);
 1136         return (
 1137             HIDMAP_PROBE(hm, dev, ps4dshead_devs, ps4dshead_map, "Headset")
 1138         );
 1139 }
 1140 
 1141 static int
 1142 ps4dsmtp_probe(device_t dev)
 1143 {
 1144         struct ps4dshock_softc *sc = device_get_softc(dev);
 1145 
 1146         hidmap_set_debug_var(&sc->hm, &HID_DEBUG_VAR);
 1147         return (
 1148             HIDMAP_PROBE(&sc->hm, dev, ps4dsmtp_devs, ps4dsmtp_map, "Touchpad")
 1149         );
 1150 }
 1151 
 1152 static int
 1153 ps4dshock_attach(device_t dev)
 1154 {
 1155         struct ps4dshock_softc *sc = device_get_softc(dev);
 1156         struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(dev);
 1157         struct sysctl_oid *tree = device_get_sysctl_tree(dev);
 1158 
 1159         sc->led_state = PS4DS_LED_ON;
 1160         sc->led_color = ps4ds_leds[device_get_unit(dev) % nitems(ps4ds_leds)];
 1161         sc->led_delay_on = 500; /* 1 Hz */
 1162         sc->led_delay_off = 500;
 1163         ps4dshock_write(sc);
 1164 
 1165         sx_init(&sc->lock, "ps4dshock");
 1166 
 1167         SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
 1168             "led_state", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY, sc,
 1169             PD4DSHOCK_SYSCTL_LED_STATE, ps4dshock_sysctl, "I",
 1170             "LED state: 0 - off, 1 - on, 2 - blinking.");
 1171 
 1172         SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
 1173             "led_color_r", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY, sc,
 1174             PD4DSHOCK_SYSCTL_LED_COLOR_R, ps4dshock_sysctl, "I",
 1175             "LED color. Red component.");
 1176 
 1177         SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
 1178             "led_color_g", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY, sc,
 1179             PD4DSHOCK_SYSCTL_LED_COLOR_G, ps4dshock_sysctl, "I",
 1180             "LED color. Green component.");
 1181 
 1182         SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
 1183             "led_color_b", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY, sc,
 1184             PD4DSHOCK_SYSCTL_LED_COLOR_B, ps4dshock_sysctl, "I",
 1185             "LED color. Blue component.");
 1186 
 1187         SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
 1188             "led_delay_on", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY, sc,
 1189             PD4DSHOCK_SYSCTL_LED_DELAY_ON, ps4dshock_sysctl, "I",
 1190             "LED blink. On delay, msecs.");
 1191 
 1192         SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
 1193             "led_delay_off", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY, sc,
 1194             PD4DSHOCK_SYSCTL_LED_DELAY_OFF, ps4dshock_sysctl, "I",
 1195             "LED blink. Off delay, msecs.");
 1196 
 1197         return (hidmap_attach(&sc->hm));
 1198 }
 1199 
 1200 static int
 1201 ps4dsacc_attach(device_t dev)
 1202 {
 1203         struct ps4dsacc_softc *sc = device_get_softc(dev);
 1204         uint8_t buf[PS4DS_FEATURE_REPORT2_SIZE];
 1205         int error, speed_2x, range_2g;
 1206 
 1207         /* Read accelerometers and gyroscopes calibration data */
 1208         error = hid_get_report(dev, buf, sizeof(buf), NULL,
 1209             HID_FEATURE_REPORT, 0x02);
 1210         if (error)
 1211                 DPRINTF("get feature report failed, error=%d "
 1212                     "(ignored)\n", error);
 1213 
 1214         DPRINTFN(5, "calibration data: %*D\n", (int)sizeof(buf), buf, " ");
 1215 
 1216         /*
 1217          * Set gyroscope calibration and normalization parameters.
 1218          * Data values will be normalized to 1/ PS4DS_GYRO_RES_PER_DEG_S
 1219          * degree/s.
 1220          */
 1221 #define HGETW(w) ((int16_t)((w)[0] | (((uint16_t)((w)[1])) << 8)))
 1222         speed_2x = HGETW(&buf[19]) + HGETW(&buf[21]);
 1223         sc->calib_data[0].usage = HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_RX);
 1224         sc->calib_data[0].code = ABS_RX;
 1225         sc->calib_data[0].range = PS4DS_GYRO_RES_PER_DEG_S * 2048;
 1226         sc->calib_data[0].res = PS4DS_GYRO_RES_PER_DEG_S;
 1227         sc->calib_data[0].bias = HGETW(&buf[1]);
 1228         sc->calib_data[0].sens_numer = speed_2x * PS4DS_GYRO_RES_PER_DEG_S;
 1229         sc->calib_data[0].sens_denom = HGETW(&buf[7]) - HGETW(&buf[9]);
 1230         /* BT case */
 1231         /* sc->calib_data[0].sens_denom = HGETW(&buf[7]) - HGETW(&buf[13]); */
 1232 
 1233         sc->calib_data[1].usage = HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_RY);
 1234         sc->calib_data[1].code = ABS_RY;
 1235         sc->calib_data[1].range = PS4DS_GYRO_RES_PER_DEG_S * 2048;
 1236         sc->calib_data[1].res = PS4DS_GYRO_RES_PER_DEG_S;
 1237         sc->calib_data[1].bias = HGETW(&buf[3]);
 1238         sc->calib_data[1].sens_numer = speed_2x * PS4DS_GYRO_RES_PER_DEG_S;
 1239         sc->calib_data[1].sens_denom = HGETW(&buf[11]) - HGETW(&buf[13]);
 1240         /* BT case */
 1241         /* sc->calib_data[1].sens_denom = HGETW(&buf[9]) - HGETW(&buf[15]); */
 1242 
 1243         sc->calib_data[2].usage = HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_RZ);
 1244         sc->calib_data[2].code = ABS_RZ;
 1245         sc->calib_data[2].range = PS4DS_GYRO_RES_PER_DEG_S * 2048;
 1246         sc->calib_data[2].res = PS4DS_GYRO_RES_PER_DEG_S;
 1247         sc->calib_data[2].bias = HGETW(&buf[5]);
 1248         sc->calib_data[2].sens_numer = speed_2x * PS4DS_GYRO_RES_PER_DEG_S;
 1249         sc->calib_data[2].sens_denom = HGETW(&buf[15]) - HGETW(&buf[17]);
 1250         /* BT case */
 1251         /* sc->calib_data[2].sens_denom = HGETW(&buf[11]) - HGETW(&buf[17]); */
 1252 
 1253         /*
 1254          * Set accelerometer calibration and normalization parameters.
 1255          * Data values will be normalized to 1 / PS4DS_ACC_RES_PER_G G.
 1256          */
 1257         range_2g = HGETW(&buf[23]) - HGETW(&buf[25]);
 1258         sc->calib_data[3].usage = HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X);
 1259         sc->calib_data[3].code = ABS_X;
 1260         sc->calib_data[3].range = PS4DS_ACC_RES_PER_G * 4;
 1261         sc->calib_data[3].res = PS4DS_ACC_RES_PER_G;
 1262         sc->calib_data[3].bias = HGETW(&buf[23]) - range_2g / 2;
 1263         sc->calib_data[3].sens_numer = 2 * PS4DS_ACC_RES_PER_G;
 1264         sc->calib_data[3].sens_denom = range_2g;
 1265 
 1266         range_2g = HGETW(&buf[27]) - HGETW(&buf[29]);
 1267         sc->calib_data[4].usage =  HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y);
 1268         sc->calib_data[4].code = ABS_Y;
 1269         sc->calib_data[4].range = PS4DS_ACC_RES_PER_G * 4;
 1270         sc->calib_data[4].res = PS4DS_ACC_RES_PER_G;
 1271         sc->calib_data[4].bias = HGETW(&buf[27]) - range_2g / 2;
 1272         sc->calib_data[4].sens_numer = 2 * PS4DS_ACC_RES_PER_G;
 1273         sc->calib_data[4].sens_denom = range_2g;
 1274 
 1275         range_2g = HGETW(&buf[31]) - HGETW(&buf[33]);
 1276         sc->calib_data[5].usage = HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Z);
 1277         sc->calib_data[5].code = ABS_Z;
 1278         sc->calib_data[5].range = PS4DS_ACC_RES_PER_G * 4;
 1279         sc->calib_data[5].res = PS4DS_ACC_RES_PER_G;
 1280         sc->calib_data[5].bias = HGETW(&buf[31]) - range_2g / 2;
 1281         sc->calib_data[5].sens_numer = 2 * PS4DS_ACC_RES_PER_G;
 1282         sc->calib_data[5].sens_denom = range_2g;
 1283 
 1284         return (hidmap_attach(&sc->hm));
 1285 }
 1286 
 1287 static int
 1288 ps4dshead_attach(device_t dev)
 1289 {
 1290         return (hidmap_attach(device_get_softc(dev)));
 1291 }
 1292 
 1293 static int
 1294 ps4dsmtp_attach(device_t dev)
 1295 {
 1296         struct ps4dsmtp_softc *sc = device_get_softc(dev);
 1297 
 1298         return (hidmap_attach(&sc->hm));
 1299 }
 1300 
 1301 static int
 1302 ps4dshock_detach(device_t dev)
 1303 {
 1304         struct ps4dshock_softc *sc = device_get_softc(dev);
 1305 
 1306         hidmap_detach(&sc->hm);
 1307         sc->led_state = PS4DS_LED_OFF;
 1308         ps4dshock_write(sc);
 1309         sx_destroy(&sc->lock);
 1310 
 1311         return (0);
 1312 }
 1313 
 1314 static int
 1315 ps4dsacc_detach(device_t dev)
 1316 {
 1317         struct ps4dsacc_softc *sc = device_get_softc(dev);
 1318 
 1319         return (hidmap_detach(&sc->hm));
 1320 }
 1321 
 1322 static int
 1323 ps4dshead_detach(device_t dev)
 1324 {
 1325         return (hidmap_detach(device_get_softc(dev)));
 1326 }
 1327 
 1328 static int
 1329 ps4dsmtp_detach(device_t dev)
 1330 {
 1331         struct ps4dsmtp_softc *sc = device_get_softc(dev);
 1332 
 1333         return (hidmap_detach(&sc->hm));
 1334 }
 1335 
 1336 static device_method_t ps4dshock_methods[] = {
 1337         DEVMETHOD(device_identify,      ps4dshock_identify),
 1338         DEVMETHOD(device_probe,         ps4dshock_probe),
 1339         DEVMETHOD(device_attach,        ps4dshock_attach),
 1340         DEVMETHOD(device_detach,        ps4dshock_detach),
 1341 
 1342         DEVMETHOD_END
 1343 };
 1344 static device_method_t ps4dsacc_methods[] = {
 1345         DEVMETHOD(device_probe,         ps4dsacc_probe),
 1346         DEVMETHOD(device_attach,        ps4dsacc_attach),
 1347         DEVMETHOD(device_detach,        ps4dsacc_detach),
 1348 
 1349         DEVMETHOD_END
 1350 };
 1351 static device_method_t ps4dshead_methods[] = {
 1352         DEVMETHOD(device_probe,         ps4dshead_probe),
 1353         DEVMETHOD(device_attach,        ps4dshead_attach),
 1354         DEVMETHOD(device_detach,        ps4dshead_detach),
 1355 
 1356         DEVMETHOD_END
 1357 };
 1358 static device_method_t ps4dsmtp_methods[] = {
 1359         DEVMETHOD(device_probe,         ps4dsmtp_probe),
 1360         DEVMETHOD(device_attach,        ps4dsmtp_attach),
 1361         DEVMETHOD(device_detach,        ps4dsmtp_detach),
 1362 
 1363         DEVMETHOD_END
 1364 };
 1365 
 1366 DEFINE_CLASS_0(ps4dsacc, ps4dsacc_driver, ps4dsacc_methods,
 1367     sizeof(struct ps4dsacc_softc));
 1368 DRIVER_MODULE(ps4dsacc, hidbus, ps4dsacc_driver, NULL, NULL);
 1369 DEFINE_CLASS_0(ps4dshead, ps4dshead_driver, ps4dshead_methods,
 1370     sizeof(struct hidmap));
 1371 DRIVER_MODULE(ps4dshead, hidbus, ps4dshead_driver, NULL, NULL);
 1372 DEFINE_CLASS_0(ps4dsmtp, ps4dsmtp_driver, ps4dsmtp_methods,
 1373     sizeof(struct ps4dsmtp_softc));
 1374 DRIVER_MODULE(ps4dsmtp, hidbus, ps4dsmtp_driver, NULL, NULL);
 1375 DEFINE_CLASS_0(ps4dshock, ps4dshock_driver, ps4dshock_methods,
 1376     sizeof(struct ps4dshock_softc));
 1377 DRIVER_MODULE(ps4dshock, hidbus, ps4dshock_driver, NULL, NULL);
 1378 
 1379 MODULE_DEPEND(ps4dshock, hid, 1, 1, 1);
 1380 MODULE_DEPEND(ps4dshock, hidbus, 1, 1, 1);
 1381 MODULE_DEPEND(ps4dshock, hidmap, 1, 1, 1);
 1382 MODULE_DEPEND(ps4dshock, hgame, 1, 1, 1);
 1383 MODULE_DEPEND(ps4dshock, evdev, 1, 1, 1);
 1384 MODULE_VERSION(ps4dshock, 1);
 1385 HID_PNP_INFO(ps4dshock_devs);

Cache object: 6505e3b2061a04eae5bf67a8dfb7cd08


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