sdl

FORK: Simple Directmedia Layer
git clone https://git.neptards.moe/neptards/sdl.git
Log | Files | Refs

SDL_bsdjoystick.c (22596B)


      1 /*
      2   Simple DirectMedia Layer
      3   Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
      4 
      5   This software is provided 'as-is', without any express or implied
      6   warranty.  In no event will the authors be held liable for any damages
      7   arising from the use of this software.
      8 
      9   Permission is granted to anyone to use this software for any purpose,
     10   including commercial applications, and to alter it and redistribute it
     11   freely, subject to the following restrictions:
     12 
     13   1. The origin of this software must not be misrepresented; you must not
     14      claim that you wrote the original software. If you use this software
     15      in a product, an acknowledgment in the product documentation would be
     16      appreciated but is not required.
     17   2. Altered source versions must be plainly marked as such, and must not be
     18      misrepresented as being the original software.
     19   3. This notice may not be removed or altered from any source distribution.
     20 */
     21 #include "../../SDL_internal.h"
     22 
     23 #ifdef SDL_JOYSTICK_USBHID
     24 
     25 /*
     26  * Joystick driver for the uhid(4) interface found in OpenBSD,
     27  * NetBSD and FreeBSD.
     28  *
     29  * Maintainer: <vedge at csoft.org>
     30  */
     31 
     32 #include <sys/param.h>
     33 
     34 #include <unistd.h>
     35 #include <fcntl.h>
     36 #include <errno.h>
     37 
     38 #ifndef __FreeBSD_kernel_version
     39 #define __FreeBSD_kernel_version __FreeBSD_version
     40 #endif
     41 
     42 #if defined(HAVE_USB_H)
     43 #include <usb.h>
     44 #endif
     45 #ifdef __DragonFly__
     46 #include <bus/u4b/usb.h>
     47 #include <bus/u4b/usbhid.h>
     48 #else
     49 #include <dev/usb/usb.h>
     50 #include <dev/usb/usbhid.h>
     51 #endif
     52 
     53 #if defined(HAVE_USBHID_H)
     54 #include <usbhid.h>
     55 #elif defined(HAVE_LIBUSB_H)
     56 #include <libusb.h>
     57 #elif defined(HAVE_LIBUSBHID_H)
     58 #include <libusbhid.h>
     59 #endif
     60 
     61 #if defined(__FREEBSD__) || defined(__FreeBSD_kernel__)
     62 #include <osreldate.h>
     63 #if __FreeBSD_kernel_version > 800063
     64 #include <dev/usb/usb_ioctl.h>
     65 #endif
     66 #include <sys/joystick.h>
     67 #elif defined(__DragonFly__)
     68 #include <bus/u4b/usb_ioctl.h>
     69 #include <sys/joystick.h>
     70 #endif
     71 
     72 #if SDL_JOYSTICK_USBHID_MACHINE_JOYSTICK_H
     73 #include <machine/joystick.h>
     74 #endif
     75 
     76 #include "SDL_joystick.h"
     77 #include "../SDL_sysjoystick.h"
     78 #include "../SDL_joystick_c.h"
     79 
     80 #define MAX_UHID_JOYS   64
     81 #define MAX_JOY_JOYS    2
     82 #define MAX_JOYS    (MAX_UHID_JOYS + MAX_JOY_JOYS)
     83 
     84 #ifdef __OpenBSD__
     85 
     86 #define HUG_DPAD_UP         0x90
     87 #define HUG_DPAD_DOWN       0x91
     88 #define HUG_DPAD_RIGHT      0x92
     89 #define HUG_DPAD_LEFT       0x93
     90 
     91 #define HAT_CENTERED        0x00
     92 #define HAT_UP              0x01
     93 #define HAT_RIGHT           0x02
     94 #define HAT_DOWN            0x04
     95 #define HAT_LEFT            0x08
     96 #define HAT_RIGHTUP         (HAT_RIGHT|HAT_UP)
     97 #define HAT_RIGHTDOWN       (HAT_RIGHT|HAT_DOWN)
     98 #define HAT_LEFTUP          (HAT_LEFT|HAT_UP)
     99 #define HAT_LEFTDOWN        (HAT_LEFT|HAT_DOWN)
    100 
    101 /* calculate the value from the state of the dpad */
    102 int
    103 dpad_to_sdl(Sint32 *dpad)
    104 {
    105     if (dpad[2]) {
    106         if (dpad[0])
    107             return HAT_RIGHTUP;
    108         else if (dpad[1])
    109             return HAT_RIGHTDOWN;
    110         else
    111             return HAT_RIGHT;
    112     } else if (dpad[3]) {
    113         if (dpad[0])
    114             return HAT_LEFTUP;
    115         else if (dpad[1])
    116             return HAT_LEFTDOWN;
    117         else
    118             return HAT_LEFT;
    119     } else if (dpad[0]) {
    120         return HAT_UP;
    121     } else if (dpad[1]) {
    122         return HAT_DOWN;
    123     }
    124     return HAT_CENTERED;
    125 }
    126 #endif
    127 
    128 struct report
    129 {
    130 #if defined(__FREEBSD__) && (__FreeBSD_kernel_version > 900000) || \
    131     defined(__DragonFly__)
    132     void *buf; /* Buffer */
    133 #elif defined(__FREEBSD__) && (__FreeBSD_kernel_version > 800063)
    134     struct usb_gen_descriptor *buf; /* Buffer */
    135 #else
    136     struct usb_ctl_report *buf; /* Buffer */
    137 #endif
    138     size_t size;                /* Buffer size */
    139     int rid;                    /* Report ID */
    140     enum
    141     {
    142         SREPORT_UNINIT,
    143         SREPORT_CLEAN,
    144         SREPORT_DIRTY
    145     } status;
    146 };
    147 
    148 static struct
    149 {
    150     int uhid_report;
    151     hid_kind_t kind;
    152     const char *name;
    153 } const repinfo[] = {
    154     {UHID_INPUT_REPORT, hid_input, "input"},
    155     {UHID_OUTPUT_REPORT, hid_output, "output"},
    156     {UHID_FEATURE_REPORT, hid_feature, "feature"}
    157 };
    158 
    159 enum
    160 {
    161     REPORT_INPUT = 0,
    162     REPORT_OUTPUT = 1,
    163     REPORT_FEATURE = 2
    164 };
    165 
    166 enum
    167 {
    168     JOYAXE_X,
    169     JOYAXE_Y,
    170     JOYAXE_Z,
    171     JOYAXE_SLIDER,
    172     JOYAXE_WHEEL,
    173     JOYAXE_RX,
    174     JOYAXE_RY,
    175     JOYAXE_RZ,
    176     JOYAXE_count
    177 };
    178 
    179 struct joystick_hwdata
    180 {
    181     int fd;
    182     char *path;
    183     enum
    184     {
    185         BSDJOY_UHID,            /* uhid(4) */
    186         BSDJOY_JOY              /* joy(4) */
    187     } type;
    188     struct report_desc *repdesc;
    189     struct report inreport;
    190     int axis_map[JOYAXE_count]; /* map present JOYAXE_* to 0,1,.. */
    191 };
    192 
    193 static char *joynames[MAX_JOYS];
    194 static char *joydevnames[MAX_JOYS];
    195 
    196 static int report_alloc(struct report *, struct report_desc *, int);
    197 static void report_free(struct report *);
    198 
    199 #if defined(USBHID_UCR_DATA) || (defined(__FreeBSD_kernel__) && __FreeBSD_kernel_version <= 800063)
    200 #define REP_BUF_DATA(rep) ((rep)->buf->ucr_data)
    201 #elif (defined(__FREEBSD__) && (__FreeBSD_kernel_version > 900000)) || \
    202     defined(__DragonFly__)
    203 #define REP_BUF_DATA(rep) ((rep)->buf)
    204 #elif (defined(__FREEBSD__) && (__FreeBSD_kernel_version > 800063))
    205 #define REP_BUF_DATA(rep) ((rep)->buf->ugd_data)
    206 #else
    207 #define REP_BUF_DATA(rep) ((rep)->buf->data)
    208 #endif
    209 
    210 static int numjoysticks = 0;
    211 
    212 static int BSD_JoystickOpen(SDL_Joystick *joy, int device_index);
    213 static void BSD_JoystickClose(SDL_Joystick *joy);
    214 
    215 static int
    216 BSD_JoystickInit(void)
    217 {
    218     char s[16];
    219     int i, fd;
    220 
    221     numjoysticks = 0;
    222 
    223     SDL_memset(joynames, 0, sizeof(joynames));
    224     SDL_memset(joydevnames, 0, sizeof(joydevnames));
    225 
    226     for (i = 0; i < MAX_UHID_JOYS; i++) {
    227         SDL_Joystick nj;
    228 
    229         SDL_snprintf(s, SDL_arraysize(s), "/dev/uhid%d", i);
    230 
    231         joynames[numjoysticks] = SDL_strdup(s);
    232 
    233         if (BSD_JoystickOpen(&nj, numjoysticks) == 0) {
    234             BSD_JoystickClose(&nj);
    235             numjoysticks++;
    236         } else {
    237             SDL_free(joynames[numjoysticks]);
    238             joynames[numjoysticks] = NULL;
    239         }
    240     }
    241     for (i = 0; i < MAX_JOY_JOYS; i++) {
    242         SDL_snprintf(s, SDL_arraysize(s), "/dev/joy%d", i);
    243         fd = open(s, O_RDONLY);
    244         if (fd != -1) {
    245             joynames[numjoysticks++] = SDL_strdup(s);
    246             close(fd);
    247         }
    248     }
    249 
    250     /* Read the default USB HID usage table. */
    251     hid_init(NULL);
    252 
    253     return (numjoysticks);
    254 }
    255 
    256 static int
    257 BSD_JoystickGetCount(void)
    258 {
    259     return numjoysticks;
    260 }
    261 
    262 static void
    263 BSD_JoystickDetect(void)
    264 {
    265 }
    266 
    267 static const char *
    268 BSD_JoystickGetDeviceName(int device_index)
    269 {
    270     if (joydevnames[device_index] != NULL) {
    271         return (joydevnames[device_index]);
    272     }
    273     return (joynames[device_index]);
    274 }
    275 
    276 static int
    277 BSD_JoystickGetDevicePlayerIndex(int device_index)
    278 {
    279     return -1;
    280 }
    281 
    282 static void
    283 BSD_JoystickSetDevicePlayerIndex(int device_index, int player_index)
    284 {
    285 }
    286 
    287 /* Function to perform the mapping from device index to the instance id for this index */
    288 static SDL_JoystickID
    289 BSD_JoystickGetDeviceInstanceID(int device_index)
    290 {
    291     return device_index;
    292 }
    293 
    294 static int
    295 usage_to_joyaxe(unsigned usage)
    296 {
    297     int joyaxe;
    298     switch (usage) {
    299     case HUG_X:
    300         joyaxe = JOYAXE_X;
    301         break;
    302     case HUG_Y:
    303         joyaxe = JOYAXE_Y;
    304         break;
    305     case HUG_Z:
    306         joyaxe = JOYAXE_Z;
    307         break;
    308     case HUG_SLIDER:
    309         joyaxe = JOYAXE_SLIDER;
    310         break;
    311     case HUG_WHEEL:
    312         joyaxe = JOYAXE_WHEEL;
    313         break;
    314     case HUG_RX:
    315         joyaxe = JOYAXE_RX;
    316         break;
    317     case HUG_RY:
    318         joyaxe = JOYAXE_RY;
    319         break;
    320     case HUG_RZ:
    321         joyaxe = JOYAXE_RZ;
    322         break;
    323     default:
    324         joyaxe = -1;
    325     }
    326     return joyaxe;
    327 }
    328 
    329 static unsigned
    330 hatval_to_sdl(Sint32 hatval)
    331 {
    332     static const unsigned hat_dir_map[8] = {
    333         SDL_HAT_UP, SDL_HAT_RIGHTUP, SDL_HAT_RIGHT, SDL_HAT_RIGHTDOWN,
    334         SDL_HAT_DOWN, SDL_HAT_LEFTDOWN, SDL_HAT_LEFT, SDL_HAT_LEFTUP
    335     };
    336     unsigned result;
    337     if ((hatval & 7) == hatval)
    338         result = hat_dir_map[hatval];
    339     else
    340         result = SDL_HAT_CENTERED;
    341     return result;
    342 }
    343 
    344 
    345 static int
    346 BSD_JoystickOpen(SDL_Joystick *joy, int device_index)
    347 {
    348     char *path = joynames[device_index];
    349     struct joystick_hwdata *hw;
    350     struct hid_item hitem;
    351     struct hid_data *hdata;
    352     struct report *rep = NULL;
    353 #if defined(__NetBSD__)
    354     usb_device_descriptor_t udd;
    355     struct usb_string_desc usd;
    356 #endif
    357     int fd;
    358     int i;
    359 
    360     fd = open(path, O_RDONLY);
    361     if (fd == -1) {
    362         return SDL_SetError("%s: %s", path, strerror(errno));
    363     }
    364 
    365     joy->instance_id = device_index;
    366     hw = (struct joystick_hwdata *)
    367         SDL_malloc(sizeof(struct joystick_hwdata));
    368     if (hw == NULL) {
    369         close(fd);
    370         return SDL_OutOfMemory();
    371     }
    372     joy->hwdata = hw;
    373     hw->fd = fd;
    374     hw->path = SDL_strdup(path);
    375     if (!SDL_strncmp(path, "/dev/joy", 8)) {
    376         hw->type = BSDJOY_JOY;
    377         joy->naxes = 2;
    378         joy->nbuttons = 2;
    379         joy->nhats = 0;
    380         joy->nballs = 0;
    381         joydevnames[device_index] = SDL_strdup("Gameport joystick");
    382         goto usbend;
    383     } else {
    384         hw->type = BSDJOY_UHID;
    385     }
    386 
    387     {
    388         int ax;
    389         for (ax = 0; ax < JOYAXE_count; ax++)
    390             hw->axis_map[ax] = -1;
    391     }
    392     hw->repdesc = hid_get_report_desc(fd);
    393     if (hw->repdesc == NULL) {
    394         SDL_SetError("%s: USB_GET_REPORT_DESC: %s", hw->path,
    395                      strerror(errno));
    396         goto usberr;
    397     }
    398     rep = &hw->inreport;
    399 #if defined(__FREEBSD__) && (__FreeBSD_kernel_version > 800063) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
    400     rep->rid = hid_get_report_id(fd);
    401     if (rep->rid < 0) {
    402 #else
    403     if (ioctl(fd, USB_GET_REPORT_ID, &rep->rid) < 0) {
    404 #endif
    405         rep->rid = -1;          /* XXX */
    406     }
    407 #if defined(__NetBSD__)
    408     if (ioctl(fd, USB_GET_DEVICE_DESC, &udd) == -1)
    409         goto desc_failed;
    410 
    411     /* Get default language */
    412     usd.usd_string_index = USB_LANGUAGE_TABLE;
    413     usd.usd_language_id = 0;
    414     if (ioctl(fd, USB_GET_STRING_DESC, &usd) == -1 || usd.usd_desc.bLength < 4) {
    415         usd.usd_language_id = 0;
    416     } else {
    417         usd.usd_language_id = UGETW(usd.usd_desc.bString[0]);
    418     }
    419 
    420     usd.usd_string_index = udd.iProduct;
    421     if (ioctl(fd, USB_GET_STRING_DESC, &usd) == 0) {
    422         char str[128];
    423         char *new_name = NULL;
    424         int i;
    425         for (i = 0; i < (usd.usd_desc.bLength >> 1) - 1 && i < sizeof(str) - 1; i++) {
    426             str[i] = UGETW(usd.usd_desc.bString[i]);
    427         }
    428         str[i] = '\0';
    429         asprintf(&new_name, "%s @ %s", str, path);
    430         if (new_name != NULL) {
    431             SDL_free(joydevnames[numjoysticks]);
    432             joydevnames[numjoysticks] = new_name;
    433         }
    434     }
    435 desc_failed:
    436 #endif
    437     if (report_alloc(rep, hw->repdesc, REPORT_INPUT) < 0) {
    438         goto usberr;
    439     }
    440     if (rep->size <= 0) {
    441         SDL_SetError("%s: Input report descriptor has invalid length",
    442                      hw->path);
    443         goto usberr;
    444     }
    445 #if defined(USBHID_NEW) || (defined(__FREEBSD__) && __FreeBSD_kernel_version >= 500111) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
    446     hdata = hid_start_parse(hw->repdesc, 1 << hid_input, rep->rid);
    447 #else
    448     hdata = hid_start_parse(hw->repdesc, 1 << hid_input);
    449 #endif
    450     if (hdata == NULL) {
    451         SDL_SetError("%s: Cannot start HID parser", hw->path);
    452         goto usberr;
    453     }
    454     joy->naxes = 0;
    455     joy->nbuttons = 0;
    456     joy->nhats = 0;
    457     joy->nballs = 0;
    458     for (i = 0; i < JOYAXE_count; i++)
    459         hw->axis_map[i] = -1;
    460 
    461     while (hid_get_item(hdata, &hitem) > 0) {
    462         char *sp;
    463         const char *s;
    464 
    465         switch (hitem.kind) {
    466         case hid_collection:
    467             switch (HID_PAGE(hitem.usage)) {
    468             case HUP_GENERIC_DESKTOP:
    469                 switch (HID_USAGE(hitem.usage)) {
    470                 case HUG_JOYSTICK:
    471                 case HUG_GAME_PAD:
    472                     s = hid_usage_in_page(hitem.usage);
    473                     sp = SDL_malloc(SDL_strlen(s) + 5);
    474                     SDL_snprintf(sp, SDL_strlen(s) + 5, "%s (%d)",
    475                                  s, device_index);
    476                     joydevnames[device_index] = sp;
    477                 }
    478             }
    479             break;
    480         case hid_input:
    481             switch (HID_PAGE(hitem.usage)) {
    482             case HUP_GENERIC_DESKTOP:
    483                 {
    484                     unsigned usage = HID_USAGE(hitem.usage);
    485                     int joyaxe = usage_to_joyaxe(usage);
    486                     if (joyaxe >= 0) {
    487                         hw->axis_map[joyaxe] = 1;
    488                     } else if (usage == HUG_HAT_SWITCH
    489 #ifdef __OpenBSD__
    490                                || usage == HUG_DPAD_UP
    491 #endif
    492                                ) {
    493                         joy->nhats++;
    494                     }
    495                     break;
    496                 }
    497             case HUP_BUTTON:
    498                 joy->nbuttons++;
    499                 break;
    500             default:
    501                 break;
    502             }
    503             break;
    504         default:
    505             break;
    506         }
    507     }
    508     hid_end_parse(hdata);
    509     for (i = 0; i < JOYAXE_count; i++)
    510         if (hw->axis_map[i] > 0)
    511             hw->axis_map[i] = joy->naxes++;
    512 
    513     if (joy->naxes == 0 && joy->nbuttons == 0 && joy->nhats == 0 && joy->nballs == 0) {
    514         SDL_SetError("%s: Not a joystick, ignoring", hw->path);
    515         goto usberr;
    516     }
    517 
    518   usbend:
    519     /* The poll blocks the event thread. */
    520     fcntl(fd, F_SETFL, O_NONBLOCK);
    521 #ifdef __NetBSD__
    522     /* Flush pending events */
    523     if (rep) {
    524         while (read(joy->hwdata->fd, REP_BUF_DATA(rep), rep->size) == rep->size)
    525             ;
    526     }
    527 #endif
    528 
    529     return (0);
    530   usberr:
    531     close(hw->fd);
    532     SDL_free(hw->path);
    533     SDL_free(hw);
    534     return (-1);
    535 }
    536 
    537 static void
    538 BSD_JoystickUpdate(SDL_Joystick *joy)
    539 {
    540     struct hid_item hitem;
    541     struct hid_data *hdata;
    542     struct report *rep;
    543     int nbutton, naxe = -1;
    544     Sint32 v;
    545 #ifdef __OpenBSD__
    546     Sint32 dpad[4] = {0, 0, 0, 0};
    547 #endif
    548 
    549 #if defined(__FREEBSD__) || SDL_JOYSTICK_USBHID_MACHINE_JOYSTICK_H || defined(__FreeBSD_kernel__) || defined(__DragonFly_)
    550     struct joystick gameport;
    551     static int x, y, xmin = 0xffff, ymin = 0xffff, xmax = 0, ymax = 0;
    552 
    553     if (joy->hwdata->type == BSDJOY_JOY) {
    554         while (read(joy->hwdata->fd, &gameport, sizeof gameport) == sizeof gameport) {
    555             if (abs(x - gameport.x) > 8) {
    556                 x = gameport.x;
    557                 if (x < xmin) {
    558                     xmin = x;
    559                 }
    560                 if (x > xmax) {
    561                     xmax = x;
    562                 }
    563                 if (xmin == xmax) {
    564                     xmin--;
    565                     xmax++;
    566                 }
    567                 v = (Sint32) x;
    568                 v -= (xmax + xmin + 1) / 2;
    569                 v *= 32768 / ((xmax - xmin + 1) / 2);
    570                 SDL_PrivateJoystickAxis(joy, 0, v);
    571             }
    572             if (abs(y - gameport.y) > 8) {
    573                 y = gameport.y;
    574                 if (y < ymin) {
    575                     ymin = y;
    576                 }
    577                 if (y > ymax) {
    578                     ymax = y;
    579                 }
    580                 if (ymin == ymax) {
    581                     ymin--;
    582                     ymax++;
    583                 }
    584                 v = (Sint32) y;
    585                 v -= (ymax + ymin + 1) / 2;
    586                 v *= 32768 / ((ymax - ymin + 1) / 2);
    587                 SDL_PrivateJoystickAxis(joy, 1, v);
    588             }
    589             SDL_PrivateJoystickButton(joy, 0, gameport.b1);
    590             SDL_PrivateJoystickButton(joy, 1, gameport.b2);
    591         }
    592         return;
    593     }
    594 #endif /* defined(__FREEBSD__) || SDL_JOYSTICK_USBHID_MACHINE_JOYSTICK_H */
    595 
    596     rep = &joy->hwdata->inreport;
    597 
    598     while (read(joy->hwdata->fd, REP_BUF_DATA(rep), rep->size) == rep->size) {
    599 #if defined(USBHID_NEW) || (defined(__FREEBSD__) && __FreeBSD_kernel_version >= 500111) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
    600         hdata = hid_start_parse(joy->hwdata->repdesc, 1 << hid_input, rep->rid);
    601 #else
    602         hdata = hid_start_parse(joy->hwdata->repdesc, 1 << hid_input);
    603 #endif
    604         if (hdata == NULL) {
    605             /*fprintf(stderr, "%s: Cannot start HID parser\n", joy->hwdata->path);*/
    606             continue;
    607         }
    608 
    609         for (nbutton = 0; hid_get_item(hdata, &hitem) > 0;) {
    610             switch (hitem.kind) {
    611             case hid_input:
    612                 switch (HID_PAGE(hitem.usage)) {
    613                 case HUP_GENERIC_DESKTOP:
    614                     {
    615                         unsigned usage = HID_USAGE(hitem.usage);
    616                         int joyaxe = usage_to_joyaxe(usage);
    617                         if (joyaxe >= 0) {
    618                             naxe = joy->hwdata->axis_map[joyaxe];
    619                             /* scaleaxe */
    620                             v = (Sint32) hid_get_data(REP_BUF_DATA(rep), &hitem);
    621                             v -= (hitem.logical_maximum +
    622                                   hitem.logical_minimum + 1) / 2;
    623                             v *= 32768 /
    624                                 ((hitem.logical_maximum -
    625                                   hitem.logical_minimum + 1) / 2);
    626                             SDL_PrivateJoystickAxis(joy, naxe, v);
    627                         } else if (usage == HUG_HAT_SWITCH) {
    628                             v = (Sint32) hid_get_data(REP_BUF_DATA(rep), &hitem);
    629                             SDL_PrivateJoystickHat(joy, 0,
    630                                                    hatval_to_sdl(v) -
    631                                                    hitem.logical_minimum);
    632                         }
    633 #ifdef __OpenBSD__
    634                         else if (usage == HUG_DPAD_UP) {
    635                             dpad[0] = (Sint32) hid_get_data(REP_BUF_DATA(rep), &hitem);
    636                             SDL_PrivateJoystickHat(joy, 0, dpad_to_sdl(dpad));
    637                         }
    638                         else if (usage == HUG_DPAD_DOWN) {
    639                             dpad[1] = (Sint32) hid_get_data(REP_BUF_DATA(rep), &hitem);
    640                             SDL_PrivateJoystickHat(joy, 0, dpad_to_sdl(dpad));
    641                         }
    642                         else if (usage == HUG_DPAD_RIGHT) {
    643                             dpad[2] = (Sint32) hid_get_data(REP_BUF_DATA(rep), &hitem);
    644                             SDL_PrivateJoystickHat(joy, 0, dpad_to_sdl(dpad));
    645                         }
    646                         else if (usage == HUG_DPAD_LEFT) {
    647                             dpad[3] = (Sint32) hid_get_data(REP_BUF_DATA(rep), &hitem);
    648                             SDL_PrivateJoystickHat(joy, 0, dpad_to_sdl(dpad));
    649                         }
    650 #endif
    651                         break;
    652                     }
    653                 case HUP_BUTTON:
    654                     v = (Sint32) hid_get_data(REP_BUF_DATA(rep), &hitem);
    655                     SDL_PrivateJoystickButton(joy, nbutton, v);
    656                     nbutton++;
    657                     break;
    658                 default:
    659                     continue;
    660                 }
    661                 break;
    662             default:
    663                 break;
    664             }
    665         }
    666         hid_end_parse(hdata);
    667     }
    668 }
    669 
    670 /* Function to close a joystick after use */
    671 static void
    672 BSD_JoystickClose(SDL_Joystick *joy)
    673 {
    674     if (SDL_strncmp(joy->hwdata->path, "/dev/joy", 8)) {
    675         report_free(&joy->hwdata->inreport);
    676         hid_dispose_report_desc(joy->hwdata->repdesc);
    677     }
    678     close(joy->hwdata->fd);
    679     SDL_free(joy->hwdata->path);
    680     SDL_free(joy->hwdata);
    681 }
    682 
    683 static void
    684 BSD_JoystickQuit(void)
    685 {
    686     int i;
    687 
    688     for (i = 0; i < MAX_JOYS; i++) {
    689         SDL_free(joynames[i]);
    690         SDL_free(joydevnames[i]);
    691     }
    692 
    693     return;
    694 }
    695 
    696 static SDL_JoystickGUID
    697 BSD_JoystickGetDeviceGUID( int device_index )
    698 {
    699     SDL_JoystickGUID guid;
    700     /* the GUID is just the first 16 chars of the name for now */
    701     const char *name = BSD_JoystickGetDeviceName( device_index );
    702     SDL_zero( guid );
    703     SDL_memcpy( &guid, name, SDL_min( sizeof(guid), SDL_strlen( name ) ) );
    704     return guid;
    705 }
    706 
    707 static int
    708 report_alloc(struct report *r, struct report_desc *rd, int repind)
    709 {
    710     int len;
    711 
    712 #ifdef __DragonFly__
    713     len = hid_report_size(rd, repinfo[repind].kind, r->rid);
    714 #elif __FREEBSD__
    715 # if (__FreeBSD_kernel_version >= 460000) || defined(__FreeBSD_kernel__)
    716 #  if (__FreeBSD_kernel_version <= 500111)
    717     len = hid_report_size(rd, r->rid, repinfo[repind].kind);
    718 #  else
    719     len = hid_report_size(rd, repinfo[repind].kind, r->rid);
    720 #  endif
    721 # else
    722     len = hid_report_size(rd, repinfo[repind].kind, &r->rid);
    723 # endif
    724 #else
    725 # ifdef USBHID_NEW
    726     len = hid_report_size(rd, repinfo[repind].kind, r->rid);
    727 # else
    728     len = hid_report_size(rd, repinfo[repind].kind, &r->rid);
    729 # endif
    730 #endif
    731 
    732     if (len < 0) {
    733         return SDL_SetError("Negative HID report size");
    734     }
    735     r->size = len;
    736 
    737     if (r->size > 0) {
    738 #if defined(__FREEBSD__) && (__FreeBSD_kernel_version > 900000) || defined(__DragonFly__)
    739         r->buf = SDL_malloc(r->size);
    740 #else
    741         r->buf = SDL_malloc(sizeof(*r->buf) - sizeof(REP_BUF_DATA(r)) +
    742                             r->size);
    743 #endif
    744         if (r->buf == NULL) {
    745             return SDL_OutOfMemory();
    746         }
    747     } else {
    748         r->buf = NULL;
    749     }
    750 
    751     r->status = SREPORT_CLEAN;
    752     return 0;
    753 }
    754 
    755 static void
    756 report_free(struct report *r)
    757 {
    758     SDL_free(r->buf);
    759     r->status = SREPORT_UNINIT;
    760 }
    761 
    762 static int
    763 BSD_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble)
    764 {
    765     return SDL_Unsupported();
    766 }
    767 
    768 static int
    769 BSD_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble)
    770 {
    771     return SDL_Unsupported();
    772 }
    773 
    774 static SDL_bool
    775 BSD_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping *out)
    776 {
    777     return SDL_FALSE;
    778 }
    779 
    780 static SDL_bool
    781 BSD_JoystickHasLED(SDL_Joystick *joystick)
    782 {
    783     return SDL_FALSE;
    784 }
    785 
    786 static int
    787 BSD_JoystickSetLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue)
    788 {
    789     return SDL_Unsupported();
    790 }
    791 
    792 static int
    793 BSD_JoystickSetSensorsEnabled(SDL_Joystick *joystick, SDL_bool enabled)
    794 {
    795     return SDL_Unsupported();
    796 }
    797 
    798 SDL_JoystickDriver SDL_BSD_JoystickDriver =
    799 {
    800     BSD_JoystickInit,
    801     BSD_JoystickGetCount,
    802     BSD_JoystickDetect,
    803     BSD_JoystickGetDeviceName,
    804     BSD_JoystickGetDevicePlayerIndex,
    805     BSD_JoystickSetDevicePlayerIndex,
    806     BSD_JoystickGetDeviceGUID,
    807     BSD_JoystickGetDeviceInstanceID,
    808     BSD_JoystickOpen,
    809     BSD_JoystickRumble,
    810     BSD_JoystickRumbleTriggers,
    811     BSD_JoystickHasLED,
    812     BSD_JoystickSetLED,
    813     BSD_JoystickSetSensorsEnabled,
    814     BSD_JoystickUpdate,
    815     BSD_JoystickClose,
    816     BSD_JoystickQuit,
    817     BSD_JoystickGetGamepadMapping
    818 };
    819 
    820 #endif /* SDL_JOYSTICK_USBHID */
    821 
    822 /* vi: set ts=4 sw=4 expandtab: */