src/joystick/bsd/SDL_sysjoystick.c
author Ozkan Sezer <sezeroz@gmail.com>
Thu, 01 Nov 2018 12:35:00 +0300
changeset 12378 61b267339239
parent 12359 691c32a30fb9
child 12503 806492103856
permissions -rw-r--r--
fix NetBSD C90 build failure

src/vendor/SDL2/src/joystick/bsd/SDL_sysjoystick.c:353:5: error:
ISO C90 forbids mixed declarations and code [-Werror=declaration-after-statement]

reported by 'bch' at https://discourse.libsdl.org/t/25231
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2018 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/usb/usb.h>
    47 #include <bus/usb/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 #ifndef __DragonFly__
    63 #include <osreldate.h>
    64 #endif
    65 #if __FreeBSD_kernel_version > 800063
    66 #include <dev/usb/usb_ioctl.h>
    67 #endif
    68 #include <sys/joystick.h>
    69 #endif
    70 
    71 #if SDL_JOYSTICK_USBHID_MACHINE_JOYSTICK_H
    72 #include <machine/joystick.h>
    73 #endif
    74 
    75 #include "SDL_joystick.h"
    76 #include "../SDL_sysjoystick.h"
    77 #include "../SDL_joystick_c.h"
    78 
    79 #define MAX_UHID_JOYS   64
    80 #define MAX_JOY_JOYS    2
    81 #define MAX_JOYS    (MAX_UHID_JOYS + MAX_JOY_JOYS)
    82 
    83 
    84 struct report
    85 {
    86 #if defined(__FREEBSD__) && (__FreeBSD_kernel_version > 900000)
    87     void *buf; /* Buffer */
    88 #elif defined(__FREEBSD__) && (__FreeBSD_kernel_version > 800063)
    89     struct usb_gen_descriptor *buf; /* Buffer */
    90 #else
    91     struct usb_ctl_report *buf; /* Buffer */
    92 #endif
    93     size_t size;                /* Buffer size */
    94     int rid;                    /* Report ID */
    95     enum
    96     {
    97         SREPORT_UNINIT,
    98         SREPORT_CLEAN,
    99         SREPORT_DIRTY
   100     } status;
   101 };
   102 
   103 static struct
   104 {
   105     int uhid_report;
   106     hid_kind_t kind;
   107     const char *name;
   108 } const repinfo[] = {
   109     {UHID_INPUT_REPORT, hid_input, "input"},
   110     {UHID_OUTPUT_REPORT, hid_output, "output"},
   111     {UHID_FEATURE_REPORT, hid_feature, "feature"}
   112 };
   113 
   114 enum
   115 {
   116     REPORT_INPUT = 0,
   117     REPORT_OUTPUT = 1,
   118     REPORT_FEATURE = 2
   119 };
   120 
   121 enum
   122 {
   123     JOYAXE_X,
   124     JOYAXE_Y,
   125     JOYAXE_Z,
   126     JOYAXE_SLIDER,
   127     JOYAXE_WHEEL,
   128     JOYAXE_RX,
   129     JOYAXE_RY,
   130     JOYAXE_RZ,
   131     JOYAXE_count
   132 };
   133 
   134 struct joystick_hwdata
   135 {
   136     int fd;
   137     char *path;
   138     enum
   139     {
   140         BSDJOY_UHID,            /* uhid(4) */
   141         BSDJOY_JOY              /* joy(4) */
   142     } type;
   143     struct report_desc *repdesc;
   144     struct report inreport;
   145     int axis_map[JOYAXE_count]; /* map present JOYAXE_* to 0,1,.. */
   146 };
   147 
   148 static char *joynames[MAX_JOYS];
   149 static char *joydevnames[MAX_JOYS];
   150 
   151 static int report_alloc(struct report *, struct report_desc *, int);
   152 static void report_free(struct report *);
   153 
   154 #if defined(USBHID_UCR_DATA) || (defined(__FreeBSD_kernel__) && __FreeBSD_kernel_version <= 800063)
   155 #define REP_BUF_DATA(rep) ((rep)->buf->ucr_data)
   156 #elif (defined(__FREEBSD__) && (__FreeBSD_kernel_version > 900000))
   157 #define REP_BUF_DATA(rep) ((rep)->buf)
   158 #elif (defined(__FREEBSD__) && (__FreeBSD_kernel_version > 800063))
   159 #define REP_BUF_DATA(rep) ((rep)->buf->ugd_data)
   160 #else
   161 #define REP_BUF_DATA(rep) ((rep)->buf->data)
   162 #endif
   163 
   164 static int numjoysticks = 0;
   165 
   166 static int BSD_JoystickOpen(SDL_Joystick * joy, int device_index);
   167 static void BSD_JoystickClose(SDL_Joystick * joy);
   168 
   169 static int
   170 BSD_JoystickInit(void)
   171 {
   172     char s[16];
   173     int i, fd;
   174 
   175     numjoysticks = 0;
   176 
   177     SDL_memset(joynames, 0, sizeof(joynames));
   178     SDL_memset(joydevnames, 0, sizeof(joydevnames));
   179 
   180     for (i = 0; i < MAX_UHID_JOYS; i++) {
   181         SDL_Joystick nj;
   182 
   183         SDL_snprintf(s, SDL_arraysize(s), "/dev/uhid%d", i);
   184 
   185         joynames[numjoysticks] = SDL_strdup(s);
   186 
   187         if (BSD_JoystickOpen(&nj, numjoysticks) == 0) {
   188             BSD_JoystickClose(&nj);
   189             numjoysticks++;
   190         } else {
   191             SDL_free(joynames[numjoysticks]);
   192             joynames[numjoysticks] = NULL;
   193         }
   194     }
   195     for (i = 0; i < MAX_JOY_JOYS; i++) {
   196         SDL_snprintf(s, SDL_arraysize(s), "/dev/joy%d", i);
   197         fd = open(s, O_RDONLY);
   198         if (fd != -1) {
   199             joynames[numjoysticks++] = SDL_strdup(s);
   200             close(fd);
   201         }
   202     }
   203 
   204     /* Read the default USB HID usage table. */
   205     hid_init(NULL);
   206 
   207     return (numjoysticks);
   208 }
   209 
   210 static int
   211 BSD_JoystickGetCount(void)
   212 {
   213     return numjoysticks;
   214 }
   215 
   216 static void
   217 BSD_JoystickDetect(void)
   218 {
   219 }
   220 
   221 static const char *
   222 BSD_JoystickGetDeviceName(int device_index)
   223 {
   224     if (joydevnames[device_index] != NULL) {
   225         return (joydevnames[device_index]);
   226     }
   227     return (joynames[device_index]);
   228 }
   229 
   230 static int
   231 BSD_JoystickGetDevicePlayerIndex(int device_index)
   232 {
   233     return -1;
   234 }
   235 
   236 /* Function to perform the mapping from device index to the instance id for this index */
   237 static SDL_JoystickID
   238 BSD_JoystickGetDeviceInstanceID(int device_index)
   239 {
   240     return device_index;
   241 }
   242 
   243 static int
   244 usage_to_joyaxe(unsigned usage)
   245 {
   246     int joyaxe;
   247     switch (usage) {
   248     case HUG_X:
   249         joyaxe = JOYAXE_X;
   250         break;
   251     case HUG_Y:
   252         joyaxe = JOYAXE_Y;
   253         break;
   254     case HUG_Z:
   255         joyaxe = JOYAXE_Z;
   256         break;
   257     case HUG_SLIDER:
   258         joyaxe = JOYAXE_SLIDER;
   259         break;
   260     case HUG_WHEEL:
   261         joyaxe = JOYAXE_WHEEL;
   262         break;
   263     case HUG_RX:
   264         joyaxe = JOYAXE_RX;
   265         break;
   266     case HUG_RY:
   267         joyaxe = JOYAXE_RY;
   268         break;
   269     case HUG_RZ:
   270         joyaxe = JOYAXE_RZ;
   271         break;
   272     default:
   273         joyaxe = -1;
   274     }
   275     return joyaxe;
   276 }
   277 
   278 static unsigned
   279 hatval_to_sdl(Sint32 hatval)
   280 {
   281     static const unsigned hat_dir_map[8] = {
   282         SDL_HAT_UP, SDL_HAT_RIGHTUP, SDL_HAT_RIGHT, SDL_HAT_RIGHTDOWN,
   283         SDL_HAT_DOWN, SDL_HAT_LEFTDOWN, SDL_HAT_LEFT, SDL_HAT_LEFTUP
   284     };
   285     unsigned result;
   286     if ((hatval & 7) == hatval)
   287         result = hat_dir_map[hatval];
   288     else
   289         result = SDL_HAT_CENTERED;
   290     return result;
   291 }
   292 
   293 
   294 static int
   295 BSD_JoystickOpen(SDL_Joystick * joy, int device_index)
   296 {
   297     char *path = joynames[device_index];
   298     struct joystick_hwdata *hw;
   299     struct hid_item hitem;
   300     struct hid_data *hdata;
   301     struct report *rep = NULL;
   302 #if defined(__NetBSD__)
   303     usb_device_descriptor_t udd;
   304     struct usb_string_desc usd;
   305 #endif
   306     int fd;
   307     int i;
   308 
   309     fd = open(path, O_RDONLY);
   310     if (fd == -1) {
   311         return SDL_SetError("%s: %s", path, strerror(errno));
   312     }
   313 
   314     joy->instance_id = device_index;
   315     hw = (struct joystick_hwdata *)
   316         SDL_malloc(sizeof(struct joystick_hwdata));
   317     if (hw == NULL) {
   318         close(fd);
   319         return SDL_OutOfMemory();
   320     }
   321     joy->hwdata = hw;
   322     hw->fd = fd;
   323     hw->path = SDL_strdup(path);
   324     if (!SDL_strncmp(path, "/dev/joy", 8)) {
   325         hw->type = BSDJOY_JOY;
   326         joy->naxes = 2;
   327         joy->nbuttons = 2;
   328         joy->nhats = 0;
   329         joy->nballs = 0;
   330         joydevnames[device_index] = SDL_strdup("Gameport joystick");
   331         goto usbend;
   332     } else {
   333         hw->type = BSDJOY_UHID;
   334     }
   335 
   336     {
   337         int ax;
   338         for (ax = 0; ax < JOYAXE_count; ax++)
   339             hw->axis_map[ax] = -1;
   340     }
   341     hw->repdesc = hid_get_report_desc(fd);
   342     if (hw->repdesc == NULL) {
   343         SDL_SetError("%s: USB_GET_REPORT_DESC: %s", hw->path,
   344                      strerror(errno));
   345         goto usberr;
   346     }
   347     rep = &hw->inreport;
   348 #if defined(__FREEBSD__) && (__FreeBSD_kernel_version > 800063) || defined(__FreeBSD_kernel__)
   349     rep->rid = hid_get_report_id(fd);
   350     if (rep->rid < 0) {
   351 #else
   352     if (ioctl(fd, USB_GET_REPORT_ID, &rep->rid) < 0) {
   353 #endif
   354         rep->rid = -1;          /* XXX */
   355     }
   356 #if defined(__NetBSD__)
   357     if (ioctl(fd, USB_GET_DEVICE_DESC, &udd) == -1)
   358         goto desc_failed;
   359 
   360     /* Get default language */
   361     usd.usd_string_index = USB_LANGUAGE_TABLE;
   362     usd.usd_language_id = 0;
   363     if (ioctl(fd, USB_GET_STRING_DESC, &usd) == -1 || usd.usd_desc.bLength < 4) {
   364         usd.usd_language_id = 0;
   365     } else {
   366         usd.usd_language_id = UGETW(usd.usd_desc.bString[0]);
   367     }
   368 
   369     usd.usd_string_index = udd.iProduct;
   370     if (ioctl(fd, USB_GET_STRING_DESC, &usd) == 0) {
   371         char str[128];
   372         char *new_name = NULL;
   373         int i;
   374         for (i = 0; i < (usd.usd_desc.bLength >> 1) - 1 && i < sizeof(str) - 1; i++) {
   375             str[i] = UGETW(usd.usd_desc.bString[i]);
   376         }
   377         str[i] = '\0';
   378         asprintf(&new_name, "%s @ %s", str, path);
   379         if (new_name != NULL) {
   380             SDL_free(joydevnames[numjoysticks]);
   381             joydevnames[numjoysticks] = new_name;
   382         }
   383     }
   384 desc_failed:
   385 #endif
   386     if (report_alloc(rep, hw->repdesc, REPORT_INPUT) < 0) {
   387         goto usberr;
   388     }
   389     if (rep->size <= 0) {
   390         SDL_SetError("%s: Input report descriptor has invalid length",
   391                      hw->path);
   392         goto usberr;
   393     }
   394 #if defined(USBHID_NEW) || (defined(__FREEBSD__) && __FreeBSD_kernel_version >= 500111) || defined(__FreeBSD_kernel__)
   395     hdata = hid_start_parse(hw->repdesc, 1 << hid_input, rep->rid);
   396 #else
   397     hdata = hid_start_parse(hw->repdesc, 1 << hid_input);
   398 #endif
   399     if (hdata == NULL) {
   400         SDL_SetError("%s: Cannot start HID parser", hw->path);
   401         goto usberr;
   402     }
   403     joy->naxes = 0;
   404     joy->nbuttons = 0;
   405     joy->nhats = 0;
   406     joy->nballs = 0;
   407     for (i = 0; i < JOYAXE_count; i++)
   408         hw->axis_map[i] = -1;
   409 
   410     while (hid_get_item(hdata, &hitem) > 0) {
   411         char *sp;
   412         const char *s;
   413 
   414         switch (hitem.kind) {
   415         case hid_collection:
   416             switch (HID_PAGE(hitem.usage)) {
   417             case HUP_GENERIC_DESKTOP:
   418                 switch (HID_USAGE(hitem.usage)) {
   419                 case HUG_JOYSTICK:
   420                 case HUG_GAME_PAD:
   421                     s = hid_usage_in_page(hitem.usage);
   422                     sp = SDL_malloc(SDL_strlen(s) + 5);
   423                     SDL_snprintf(sp, SDL_strlen(s) + 5, "%s (%d)",
   424                                  s, device_index);
   425                     joydevnames[device_index] = sp;
   426                 }
   427             }
   428             break;
   429         case hid_input:
   430             switch (HID_PAGE(hitem.usage)) {
   431             case HUP_GENERIC_DESKTOP:
   432                 {
   433                     unsigned usage = HID_USAGE(hitem.usage);
   434                     int joyaxe = usage_to_joyaxe(usage);
   435                     if (joyaxe >= 0) {
   436                         hw->axis_map[joyaxe] = 1;
   437                     } else if (usage == HUG_HAT_SWITCH) {
   438                         joy->nhats++;
   439                     }
   440                     break;
   441                 }
   442             case HUP_BUTTON:
   443                 joy->nbuttons++;
   444                 break;
   445             default:
   446                 break;
   447             }
   448             break;
   449         default:
   450             break;
   451         }
   452     }
   453     hid_end_parse(hdata);
   454     for (i = 0; i < JOYAXE_count; i++)
   455         if (hw->axis_map[i] > 0)
   456             hw->axis_map[i] = joy->naxes++;
   457 
   458     if (joy->naxes == 0 && joy->nbuttons == 0 && joy->nhats == 0 && joy->nballs == 0) {
   459         SDL_SetError("%s: Not a joystick, ignoring", hw->path);
   460         goto usberr;
   461     }
   462 
   463   usbend:
   464     /* The poll blocks the event thread. */
   465     fcntl(fd, F_SETFL, O_NONBLOCK);
   466 #ifdef __NetBSD__
   467     /* Flush pending events */
   468     if (rep) {
   469         while (read(joy->hwdata->fd, REP_BUF_DATA(rep), rep->size) == rep->size)
   470             ;
   471     }
   472 #endif
   473 
   474     return (0);
   475   usberr:
   476     close(hw->fd);
   477     SDL_free(hw->path);
   478     SDL_free(hw);
   479     return (-1);
   480 }
   481 
   482 static void
   483 BSD_JoystickUpdate(SDL_Joystick * joy)
   484 {
   485     struct hid_item hitem;
   486     struct hid_data *hdata;
   487     struct report *rep;
   488     int nbutton, naxe = -1;
   489     Sint32 v;
   490 
   491 #if defined(__FREEBSD__) || SDL_JOYSTICK_USBHID_MACHINE_JOYSTICK_H || defined(__FreeBSD_kernel__)
   492     struct joystick gameport;
   493     static int x, y, xmin = 0xffff, ymin = 0xffff, xmax = 0, ymax = 0;
   494 
   495     if (joy->hwdata->type == BSDJOY_JOY) {
   496         while (read(joy->hwdata->fd, &gameport, sizeof gameport) == sizeof gameport) {
   497             if (abs(x - gameport.x) > 8) {
   498                 x = gameport.x;
   499                 if (x < xmin) {
   500                     xmin = x;
   501                 }
   502                 if (x > xmax) {
   503                     xmax = x;
   504                 }
   505                 if (xmin == xmax) {
   506                     xmin--;
   507                     xmax++;
   508                 }
   509                 v = (Sint32) x;
   510                 v -= (xmax + xmin + 1) / 2;
   511                 v *= 32768 / ((xmax - xmin + 1) / 2);
   512                 SDL_PrivateJoystickAxis(joy, 0, v);
   513             }
   514             if (abs(y - gameport.y) > 8) {
   515                 y = gameport.y;
   516                 if (y < ymin) {
   517                     ymin = y;
   518                 }
   519                 if (y > ymax) {
   520                     ymax = y;
   521                 }
   522                 if (ymin == ymax) {
   523                     ymin--;
   524                     ymax++;
   525                 }
   526                 v = (Sint32) y;
   527                 v -= (ymax + ymin + 1) / 2;
   528                 v *= 32768 / ((ymax - ymin + 1) / 2);
   529                 SDL_PrivateJoystickAxis(joy, 1, v);
   530             }
   531             SDL_PrivateJoystickButton(joy, 0, gameport.b1);
   532             SDL_PrivateJoystickButton(joy, 1, gameport.b2);
   533         }
   534         return;
   535     }
   536 #endif /* defined(__FREEBSD__) || SDL_JOYSTICK_USBHID_MACHINE_JOYSTICK_H */
   537 
   538     rep = &joy->hwdata->inreport;
   539 
   540     while (read(joy->hwdata->fd, REP_BUF_DATA(rep), rep->size) == rep->size) {
   541 #if defined(USBHID_NEW) || (defined(__FREEBSD__) && __FreeBSD_kernel_version >= 500111) || defined(__FreeBSD_kernel__)
   542         hdata = hid_start_parse(joy->hwdata->repdesc, 1 << hid_input, rep->rid);
   543 #else
   544         hdata = hid_start_parse(joy->hwdata->repdesc, 1 << hid_input);
   545 #endif
   546         if (hdata == NULL) {
   547             /*fprintf(stderr, "%s: Cannot start HID parser\n", joy->hwdata->path);*/
   548             continue;
   549         }
   550 
   551         for (nbutton = 0; hid_get_item(hdata, &hitem) > 0;) {
   552             switch (hitem.kind) {
   553             case hid_input:
   554                 switch (HID_PAGE(hitem.usage)) {
   555                 case HUP_GENERIC_DESKTOP:
   556                     {
   557                         unsigned usage = HID_USAGE(hitem.usage);
   558                         int joyaxe = usage_to_joyaxe(usage);
   559                         if (joyaxe >= 0) {
   560                             naxe = joy->hwdata->axis_map[joyaxe];
   561                             /* scaleaxe */
   562                             v = (Sint32) hid_get_data(REP_BUF_DATA(rep), &hitem);
   563                             v -= (hitem.logical_maximum +
   564                                   hitem.logical_minimum + 1) / 2;
   565                             v *= 32768 /
   566                                 ((hitem.logical_maximum -
   567                                   hitem.logical_minimum + 1) / 2);
   568                             SDL_PrivateJoystickAxis(joy, naxe, v);
   569                         } else if (usage == HUG_HAT_SWITCH) {
   570                             v = (Sint32) hid_get_data(REP_BUF_DATA(rep), &hitem);
   571                             SDL_PrivateJoystickHat(joy, 0,
   572                                                    hatval_to_sdl(v) -
   573                                                    hitem.logical_minimum);
   574                         }
   575                         break;
   576                     }
   577                 case HUP_BUTTON:
   578                     v = (Sint32) hid_get_data(REP_BUF_DATA(rep), &hitem);
   579                     SDL_PrivateJoystickButton(joy, nbutton, v);
   580                     nbutton++;
   581                     break;
   582                 default:
   583                     continue;
   584                 }
   585                 break;
   586             default:
   587                 break;
   588             }
   589         }
   590         hid_end_parse(hdata);
   591     }
   592 }
   593 
   594 /* Function to close a joystick after use */
   595 static void
   596 BSD_JoystickClose(SDL_Joystick * joy)
   597 {
   598     if (SDL_strncmp(joy->hwdata->path, "/dev/joy", 8)) {
   599         report_free(&joy->hwdata->inreport);
   600         hid_dispose_report_desc(joy->hwdata->repdesc);
   601     }
   602     close(joy->hwdata->fd);
   603     SDL_free(joy->hwdata->path);
   604     SDL_free(joy->hwdata);
   605 }
   606 
   607 static void
   608 BSD_JoystickQuit(void)
   609 {
   610     int i;
   611 
   612     for (i = 0; i < MAX_JOYS; i++) {
   613         SDL_free(joynames[i]);
   614         SDL_free(joydevnames[i]);
   615     }
   616 
   617     return;
   618 }
   619 
   620 static SDL_JoystickGUID
   621 BSD_JoystickGetDeviceGUID( int device_index )
   622 {
   623     SDL_JoystickGUID guid;
   624     /* the GUID is just the first 16 chars of the name for now */
   625     const char *name = BSD_JoystickGetDeviceName( device_index );
   626     SDL_zero( guid );
   627     SDL_memcpy( &guid, name, SDL_min( sizeof(guid), SDL_strlen( name ) ) );
   628     return guid;
   629 }
   630 
   631 static int
   632 report_alloc(struct report *r, struct report_desc *rd, int repind)
   633 {
   634     int len;
   635 
   636 #ifdef __DragonFly__
   637     len = hid_report_size(rd, r->rid, repinfo[repind].kind);
   638 #elif __FREEBSD__
   639 # if (__FreeBSD_kernel_version >= 460000) || defined(__FreeBSD_kernel__)
   640 #  if (__FreeBSD_kernel_version <= 500111)
   641     len = hid_report_size(rd, r->rid, repinfo[repind].kind);
   642 #  else
   643     len = hid_report_size(rd, repinfo[repind].kind, r->rid);
   644 #  endif
   645 # else
   646     len = hid_report_size(rd, repinfo[repind].kind, &r->rid);
   647 # endif
   648 #else
   649 # ifdef USBHID_NEW
   650     len = hid_report_size(rd, repinfo[repind].kind, r->rid);
   651 # else
   652     len = hid_report_size(rd, repinfo[repind].kind, &r->rid);
   653 # endif
   654 #endif
   655 
   656     if (len < 0) {
   657         return SDL_SetError("Negative HID report size");
   658     }
   659     r->size = len;
   660 
   661     if (r->size > 0) {
   662 #if defined(__FREEBSD__) && (__FreeBSD_kernel_version > 900000)
   663         r->buf = SDL_malloc(r->size);
   664 #else
   665         r->buf = SDL_malloc(sizeof(*r->buf) - sizeof(REP_BUF_DATA(r)) +
   666                             r->size);
   667 #endif
   668         if (r->buf == NULL) {
   669             return SDL_OutOfMemory();
   670         }
   671     } else {
   672         r->buf = NULL;
   673     }
   674 
   675     r->status = SREPORT_CLEAN;
   676     return 0;
   677 }
   678 
   679 static void
   680 report_free(struct report *r)
   681 {
   682     SDL_free(r->buf);
   683     r->status = SREPORT_UNINIT;
   684 }
   685 
   686 static int
   687 BSD_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms)
   688 {
   689     return SDL_Unsupported();
   690 }
   691 
   692 SDL_JoystickDriver SDL_BSD_JoystickDriver =
   693 {
   694     BSD_JoystickInit,
   695     BSD_JoystickGetCount,
   696     BSD_JoystickDetect,
   697     BSD_JoystickGetDeviceName,
   698     BSD_JoystickGetDevicePlayerIndex,
   699     BSD_JoystickGetDeviceGUID,
   700     BSD_JoystickGetDeviceInstanceID,
   701     BSD_JoystickOpen,
   702     BSD_JoystickRumble,
   703     BSD_JoystickUpdate,
   704     BSD_JoystickClose,
   705     BSD_JoystickQuit,
   706 };
   707 
   708 #endif /* SDL_JOYSTICK_USBHID */
   709 
   710 /* vi: set ts=4 sw=4 expandtab: */