src/joystick/bsd/SDL_sysjoystick.c
author Ryan C. Gordon <icculus@icculus.org>
Sun, 31 Mar 2013 12:48:50 -0400
changeset 7037 3fedf1f25b94
parent 6963 4658b1101200
child 7191 75360622e65f
permissions -rw-r--r--
Make SDL_SetError and friends unconditionally return -1.

This lets us change things like this...

if (Failed) {
SDL_SetError("We failed");
return -1;
}

...into this...

if (Failed) {
return SDL_SetError("We failed");
}


Fixes Bugzilla #1778.
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2013 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_config.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	16
    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 SDL_SYS_numjoysticks = 0;
   165 
   166 int
   167 SDL_SYS_JoystickInit(void)
   168 {
   169     char s[16];
   170     int i, fd;
   171 
   172     SDL_SYS_numjoysticks = 0;
   173 
   174     SDL_memset(joynames, 0, sizeof(joynames));
   175     SDL_memset(joydevnames, 0, sizeof(joydevnames));
   176 
   177     for (i = 0; i < MAX_UHID_JOYS; i++) {
   178         SDL_Joystick nj;
   179 
   180         SDL_snprintf(s, SDL_arraysize(s), "/dev/uhid%d", i);
   181 
   182         joynames[SDL_SYS_numjoysticks] = strdup(s);
   183 
   184         if (SDL_SYS_JoystickOpen(&nj, SDL_SYS_numjoysticks) == 0) {
   185             SDL_SYS_JoystickClose(&nj);
   186             SDL_SYS_numjoysticks++;
   187         } else {
   188             SDL_free(joynames[SDL_SYS_numjoysticks]);
   189             joynames[SDL_SYS_numjoysticks] = NULL;
   190         }
   191     }
   192     for (i = 0; i < MAX_JOY_JOYS; i++) {
   193         SDL_snprintf(s, SDL_arraysize(s), "/dev/joy%d", i);
   194         fd = open(s, O_RDONLY);
   195         if (fd != -1) {
   196             joynames[SDL_SYS_numjoysticks++] = strdup(s);
   197             close(fd);
   198         }
   199     }
   200 
   201     /* Read the default USB HID usage table. */
   202     hid_init(NULL);
   203 
   204     return (SDL_SYS_numjoysticks);
   205 }
   206 
   207 int SDL_SYS_NumJoysticks()
   208 {
   209     return SDL_SYS_numjoysticks;
   210 }
   211 
   212 void SDL_SYS_JoystickDetect()
   213 {
   214 }
   215 
   216 SDL_bool SDL_SYS_JoystickNeedsPolling()
   217 {
   218     return SDL_FALSE;
   219 }
   220 
   221 const char *
   222 SDL_SYS_JoystickNameForDeviceIndex(int device_index)
   223 {
   224     if (joydevnames[device_index] != NULL) {
   225         return (joydevnames[device_index]);
   226     }
   227     return (joynames[device_index]);
   228 }
   229 
   230 /* Function to perform the mapping from device index to the instance id for this index */
   231 SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index)
   232 {
   233     return device_index;
   234 }
   235 
   236 static int
   237 usage_to_joyaxe(unsigned usage)
   238 {
   239     int joyaxe;
   240     switch (usage) {
   241     case HUG_X:
   242         joyaxe = JOYAXE_X;
   243         break;
   244     case HUG_Y:
   245         joyaxe = JOYAXE_Y;
   246         break;
   247     case HUG_Z:
   248         joyaxe = JOYAXE_Z;
   249         break;
   250     case HUG_SLIDER:
   251         joyaxe = JOYAXE_SLIDER;
   252         break;
   253     case HUG_WHEEL:
   254         joyaxe = JOYAXE_WHEEL;
   255         break;
   256     case HUG_RX:
   257         joyaxe = JOYAXE_RX;
   258         break;
   259     case HUG_RY:
   260         joyaxe = JOYAXE_RY;
   261         break;
   262     case HUG_RZ:
   263         joyaxe = JOYAXE_RZ;
   264         break;
   265     default:
   266         joyaxe = -1;
   267     }
   268     return joyaxe;
   269 }
   270 
   271 static unsigned
   272 hatval_to_sdl(Sint32 hatval)
   273 {
   274     static const unsigned hat_dir_map[8] = {
   275         SDL_HAT_UP, SDL_HAT_RIGHTUP, SDL_HAT_RIGHT, SDL_HAT_RIGHTDOWN,
   276         SDL_HAT_DOWN, SDL_HAT_LEFTDOWN, SDL_HAT_LEFT, SDL_HAT_LEFTUP
   277     };
   278     unsigned result;
   279     if ((hatval & 7) == hatval)
   280         result = hat_dir_map[hatval];
   281     else
   282         result = SDL_HAT_CENTERED;
   283     return result;
   284 }
   285 
   286 
   287 int
   288 SDL_SYS_JoystickOpen(SDL_Joystick * joy, int device_index)
   289 {
   290     char *path = joynames[device_index];
   291     struct joystick_hwdata *hw;
   292     struct hid_item hitem;
   293     struct hid_data *hdata;
   294     struct report *rep;
   295     int fd;
   296     int i;
   297 
   298     fd = open(path, O_RDONLY);
   299     if (fd == -1) {
   300         return SDL_SetError("%s: %s", path, strerror(errno));
   301     }
   302 
   303     joy->instance_id = device_index;
   304     hw = (struct joystick_hwdata *)
   305         SDL_malloc(sizeof(struct joystick_hwdata));
   306     if (hw == NULL) {
   307         close(fd);
   308         return SDL_OutOfMemory();
   309     }
   310     joy->hwdata = hw;
   311     hw->fd = fd;
   312     hw->path = strdup(path);
   313     if (!SDL_strncmp(path, "/dev/joy", 8)) {
   314         hw->type = BSDJOY_JOY;
   315         joy->naxes = 2;
   316         joy->nbuttons = 2;
   317         joy->nhats = 0;
   318         joy->nballs = 0;
   319         joydevnames[device_index] = strdup("Gameport joystick");
   320         goto usbend;
   321     } else {
   322         hw->type = BSDJOY_UHID;
   323     }
   324 
   325     {
   326         int ax;
   327         for (ax = 0; ax < JOYAXE_count; ax++)
   328             hw->axis_map[ax] = -1;
   329     }
   330     hw->repdesc = hid_get_report_desc(fd);
   331     if (hw->repdesc == NULL) {
   332         SDL_SetError("%s: USB_GET_REPORT_DESC: %s", hw->path,
   333                      strerror(errno));
   334         goto usberr;
   335     }
   336     rep = &hw->inreport;
   337 #if defined(__FREEBSD__) && (__FreeBSD_kernel_version > 800063) || defined(__FreeBSD_kernel__)
   338     rep->rid = hid_get_report_id(fd);
   339     if (rep->rid < 0) {
   340 #else
   341     if (ioctl(fd, USB_GET_REPORT_ID, &rep->rid) < 0) {
   342 #endif
   343         rep->rid = -1;          /* XXX */
   344     }
   345     if (report_alloc(rep, hw->repdesc, REPORT_INPUT) < 0) {
   346         goto usberr;
   347     }
   348     if (rep->size <= 0) {
   349         SDL_SetError("%s: Input report descriptor has invalid length",
   350                      hw->path);
   351         goto usberr;
   352     }
   353 #if defined(USBHID_NEW) || (defined(__FREEBSD__) && __FreeBSD_kernel_version >= 500111) || defined(__FreeBSD_kernel__)
   354     hdata = hid_start_parse(hw->repdesc, 1 << hid_input, rep->rid);
   355 #else
   356     hdata = hid_start_parse(hw->repdesc, 1 << hid_input);
   357 #endif
   358     if (hdata == NULL) {
   359         SDL_SetError("%s: Cannot start HID parser", hw->path);
   360         goto usberr;
   361     }
   362     joy->naxes = 0;
   363     joy->nbuttons = 0;
   364     joy->nhats = 0;
   365     joy->nballs = 0;
   366     for (i = 0; i < JOYAXE_count; i++)
   367         hw->axis_map[i] = -1;
   368 
   369     while (hid_get_item(hdata, &hitem) > 0) {
   370         char *sp;
   371         const char *s;
   372 
   373         switch (hitem.kind) {
   374         case hid_collection:
   375             switch (HID_PAGE(hitem.usage)) {
   376             case HUP_GENERIC_DESKTOP:
   377                 switch (HID_USAGE(hitem.usage)) {
   378                 case HUG_JOYSTICK:
   379                 case HUG_GAME_PAD:
   380                     s = hid_usage_in_page(hitem.usage);
   381                     sp = SDL_malloc(SDL_strlen(s) + 5);
   382                     SDL_snprintf(sp, SDL_strlen(s) + 5, "%s (%d)",
   383                                  s, device_index);
   384                     joydevnames[device_index] = sp;
   385                 }
   386             }
   387             break;
   388         case hid_input:
   389             switch (HID_PAGE(hitem.usage)) {
   390             case HUP_GENERIC_DESKTOP:
   391                 {
   392                     unsigned usage = HID_USAGE(hitem.usage);
   393                     int joyaxe = usage_to_joyaxe(usage);
   394                     if (joyaxe >= 0) {
   395                         hw->axis_map[joyaxe] = 1;
   396                     } else if (usage == HUG_HAT_SWITCH) {
   397                         joy->nhats++;
   398                     }
   399                     break;
   400                 }
   401             case HUP_BUTTON:
   402                 joy->nbuttons++;
   403                 break;
   404             default:
   405                 break;
   406             }
   407             break;
   408         default:
   409             break;
   410         }
   411     }
   412     hid_end_parse(hdata);
   413     for (i = 0; i < JOYAXE_count; i++)
   414         if (hw->axis_map[i] > 0)
   415             hw->axis_map[i] = joy->naxes++;
   416 
   417   usbend:
   418     /* The poll blocks the event thread. */
   419     fcntl(fd, F_SETFL, O_NONBLOCK);
   420 
   421     return (0);
   422   usberr:
   423     close(hw->fd);
   424     SDL_free(hw->path);
   425     SDL_free(hw);
   426     return (-1);
   427 }
   428 
   429 /* Function to determine is this joystick is attached to the system right now */
   430 SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick *joystick)
   431 {
   432     return SDL_TRUE;
   433 }
   434 
   435 void
   436 SDL_SYS_JoystickUpdate(SDL_Joystick * joy)
   437 {
   438     struct hid_item hitem;
   439     struct hid_data *hdata;
   440     struct report *rep;
   441     int nbutton, naxe = -1;
   442     Sint32 v;
   443 
   444 #if defined(__FREEBSD__) || SDL_JOYSTICK_USBHID_MACHINE_JOYSTICK_H || defined(__FreeBSD_kernel__)
   445     struct joystick gameport;
   446     static int x, y, xmin = 0xffff, ymin = 0xffff, xmax = 0, ymax = 0;
   447 
   448     if (joy->hwdata->type == BSDJOY_JOY) {
   449         if (read(joy->hwdata->fd, &gameport, sizeof gameport) !=
   450             sizeof gameport)
   451             return;
   452         if (abs(x - gameport.x) > 8) {
   453             x = gameport.x;
   454             if (x < xmin) {
   455                 xmin = x;
   456             }
   457             if (x > xmax) {
   458                 xmax = x;
   459             }
   460             if (xmin == xmax) {
   461                 xmin--;
   462                 xmax++;
   463             }
   464             v = (Sint32) x;
   465             v -= (xmax + xmin + 1) / 2;
   466             v *= 32768 / ((xmax - xmin + 1) / 2);
   467             SDL_PrivateJoystickAxis(joy, 0, v);
   468         }
   469         if (abs(y - gameport.y) > 8) {
   470             y = gameport.y;
   471             if (y < ymin) {
   472                 ymin = y;
   473             }
   474             if (y > ymax) {
   475                 ymax = y;
   476             }
   477             if (ymin == ymax) {
   478                 ymin--;
   479                 ymax++;
   480             }
   481             v = (Sint32) y;
   482             v -= (ymax + ymin + 1) / 2;
   483             v *= 32768 / ((ymax - ymin + 1) / 2);
   484             SDL_PrivateJoystickAxis(joy, 1, v);
   485         }
   486         if (gameport.b1 != joy->buttons[0]) {
   487             SDL_PrivateJoystickButton(joy, 0, gameport.b1);
   488         }
   489         if (gameport.b2 != joy->buttons[1]) {
   490             SDL_PrivateJoystickButton(joy, 1, gameport.b2);
   491         }
   492         return;
   493     }
   494 #endif /* defined(__FREEBSD__) || SDL_JOYSTICK_USBHID_MACHINE_JOYSTICK_H */
   495 
   496     rep = &joy->hwdata->inreport;
   497 
   498     if (read(joy->hwdata->fd, REP_BUF_DATA(rep), rep->size) != rep->size) {
   499         return;
   500     }
   501 #if defined(USBHID_NEW) || (defined(__FREEBSD__) && __FreeBSD_kernel_version >= 500111) || defined(__FreeBSD_kernel__)
   502     hdata = hid_start_parse(joy->hwdata->repdesc, 1 << hid_input, rep->rid);
   503 #else
   504     hdata = hid_start_parse(joy->hwdata->repdesc, 1 << hid_input);
   505 #endif
   506     if (hdata == NULL) {
   507         fprintf(stderr, "%s: Cannot start HID parser\n", joy->hwdata->path);
   508         return;
   509     }
   510 
   511     for (nbutton = 0; hid_get_item(hdata, &hitem) > 0;) {
   512         switch (hitem.kind) {
   513         case hid_input:
   514             switch (HID_PAGE(hitem.usage)) {
   515             case HUP_GENERIC_DESKTOP:
   516                 {
   517                     unsigned usage = HID_USAGE(hitem.usage);
   518                     int joyaxe = usage_to_joyaxe(usage);
   519                     if (joyaxe >= 0) {
   520                         naxe = joy->hwdata->axis_map[joyaxe];
   521                         /* scaleaxe */
   522                         v = (Sint32) hid_get_data(REP_BUF_DATA(rep), &hitem);
   523                         v -= (hitem.logical_maximum +
   524                               hitem.logical_minimum + 1) / 2;
   525                         v *= 32768 /
   526                             ((hitem.logical_maximum -
   527                               hitem.logical_minimum + 1) / 2);
   528                         if (v != joy->axes[naxe]) {
   529                             SDL_PrivateJoystickAxis(joy, naxe, v);
   530                         }
   531                     } else if (usage == HUG_HAT_SWITCH) {
   532                         v = (Sint32) hid_get_data(REP_BUF_DATA(rep), &hitem);
   533                         SDL_PrivateJoystickHat(joy, 0,
   534                                                hatval_to_sdl(v) -
   535                                                hitem.logical_minimum);
   536                     }
   537                     break;
   538                 }
   539             case HUP_BUTTON:
   540                 v = (Sint32) hid_get_data(REP_BUF_DATA(rep), &hitem);
   541                 if (joy->buttons[nbutton] != v) {
   542                     SDL_PrivateJoystickButton(joy, nbutton, v);
   543                 }
   544                 nbutton++;
   545                 break;
   546             default:
   547                 continue;
   548             }
   549             break;
   550         default:
   551             break;
   552         }
   553     }
   554     hid_end_parse(hdata);
   555 
   556     return;
   557 }
   558 
   559 /* Function to close a joystick after use */
   560 void
   561 SDL_SYS_JoystickClose(SDL_Joystick * joy)
   562 {
   563     if (SDL_strncmp(joy->hwdata->path, "/dev/joy", 8)) {
   564         report_free(&joy->hwdata->inreport);
   565         hid_dispose_report_desc(joy->hwdata->repdesc);
   566     }
   567     close(joy->hwdata->fd);
   568     SDL_free(joy->hwdata->path);
   569     SDL_free(joy->hwdata);
   570 
   571     return;
   572 }
   573 
   574 void
   575 SDL_SYS_JoystickQuit(void)
   576 {
   577     int i;
   578 
   579     for (i = 0; i < MAX_JOYS; i++) {
   580         if (joynames[i] != NULL)
   581             SDL_free(joynames[i]);
   582         if (joydevnames[i] != NULL)
   583             SDL_free(joydevnames[i]);
   584     }
   585 
   586     return;
   587 }
   588 
   589 SDL_JoystickGUID SDL_SYS_JoystickGetDeviceGUID( int device_index )
   590 {
   591     SDL_JoystickGUID guid;
   592     // the GUID is just the first 16 chars of the name for now
   593     const char *name = SDL_SYS_JoystickNameForDeviceIndex( device_index );
   594     SDL_zero( guid );
   595     SDL_memcpy( &guid, name, SDL_min( sizeof(guid), SDL_strlen( name ) ) );
   596     return guid;
   597 }
   598 
   599 SDL_JoystickGUID SDL_SYS_JoystickGetGUID(SDL_Joystick * joystick)
   600 {
   601     SDL_JoystickGUID guid;
   602     // the GUID is just the first 16 chars of the name for now
   603     const char *name = joystick->name;
   604     SDL_zero( guid );
   605     SDL_memcpy( &guid, name, SDL_min( sizeof(guid), SDL_strlen( name ) ) );
   606     return guid;
   607 }
   608 
   609 static int
   610 report_alloc(struct report *r, struct report_desc *rd, int repind)
   611 {
   612     int len;
   613 
   614 #ifdef __DragonFly__
   615     len = hid_report_size(rd, r->rid, repinfo[repind].kind);
   616 #elif __FREEBSD__
   617 # if (__FreeBSD_kernel_version >= 460000) || defined(__FreeBSD_kernel__)
   618 #  if (__FreeBSD_kernel_version <= 500111)
   619     len = hid_report_size(rd, r->rid, repinfo[repind].kind);
   620 #  else
   621     len = hid_report_size(rd, repinfo[repind].kind, r->rid);
   622 #  endif
   623 # else
   624     len = hid_report_size(rd, repinfo[repind].kind, &r->rid);
   625 # endif
   626 #else
   627 # ifdef USBHID_NEW
   628     len = hid_report_size(rd, repinfo[repind].kind, r->rid);
   629 # else
   630     len = hid_report_size(rd, repinfo[repind].kind, &r->rid);
   631 # endif
   632 #endif
   633 
   634     if (len < 0) {
   635         return SDL_SetError("Negative HID report size");
   636     }
   637     r->size = len;
   638 
   639     if (r->size > 0) {
   640 #if defined(__FREEBSD__) && (__FreeBSD_kernel_version > 900000)
   641         r->buf = SDL_malloc(r->size);
   642 #else
   643         r->buf = SDL_malloc(sizeof(*r->buf) - sizeof(REP_BUF_DATA(r)) +
   644                             r->size);
   645 #endif
   646         if (r->buf == NULL) {
   647             return SDL_OutOfMemory();
   648         }
   649     } else {
   650         r->buf = NULL;
   651     }
   652 
   653     r->status = SREPORT_CLEAN;
   654     return 0;
   655 }
   656 
   657 static void
   658 report_free(struct report *r)
   659 {
   660     if (r->buf != NULL) {
   661         SDL_free(r->buf);
   662     }
   663     r->status = SREPORT_UNINIT;
   664 }
   665 
   666 #endif /* SDL_JOYSTICK_USBHID */
   667 
   668 /* vi: set ts=4 sw=4 expandtab: */