src/hidapi/SDL_hidapi.c
author Sam Lantinga
Sun, 01 Mar 2020 17:53:30 -0800
changeset 13565 7f96440b8e3d
parent 13429 1fa9a405fab3
child 13586 2f5e3f0be62c
permissions -rw-r--r--
We already have a hidapi implementation for Windows, we don't need libusb
     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 
    22 /* Original hybrid wrapper for Linux by Valve Software. Their original notes:
    23  *
    24  * The libusb version doesn't support Bluetooth, but not all Linux
    25  * distributions allow access to /dev/hidraw*
    26  *
    27  * This merges the two, at a small performance cost, until distributions
    28  * have granted access to /dev/hidraw*
    29  */
    30 
    31 #include "../SDL_internal.h"
    32 #include "SDL_loadso.h"
    33 
    34 #ifdef SDL_JOYSTICK_HIDAPI
    35 
    36 /* Platform HIDAPI Implementation */
    37 
    38 #define hid_device_                     PLATFORM_hid_device_
    39 #define hid_device                      PLATFORM_hid_device
    40 #define hid_device_info                 PLATFORM_hid_device_info
    41 #define hid_init                        PLATFORM_hid_init
    42 #define hid_exit                        PLATFORM_hid_exit
    43 #define hid_enumerate                   PLATFORM_hid_enumerate
    44 #define hid_free_enumeration            PLATFORM_hid_free_enumeration
    45 #define hid_open                        PLATFORM_hid_open
    46 #define hid_open_path                   PLATFORM_hid_open_path
    47 #define hid_write                       PLATFORM_hid_write
    48 #define hid_read_timeout                PLATFORM_hid_read_timeout
    49 #define hid_read                        PLATFORM_hid_read
    50 #define hid_set_nonblocking             PLATFORM_hid_set_nonblocking
    51 #define hid_send_feature_report         PLATFORM_hid_send_feature_report
    52 #define hid_get_feature_report          PLATFORM_hid_get_feature_report
    53 #define hid_close                       PLATFORM_hid_close
    54 #define hid_get_manufacturer_string     PLATFORM_hid_get_manufacturer_string
    55 #define hid_get_product_string          PLATFORM_hid_get_product_string
    56 #define hid_get_serial_number_string    PLATFORM_hid_get_serial_number_string
    57 #define hid_get_indexed_string          PLATFORM_hid_get_indexed_string
    58 #define hid_error                       PLATFORM_hid_error
    59 #define new_hid_device                  PLATFORM_new_hid_device
    60 #define free_hid_device                 PLATFORM_free_hid_device
    61 #define input_report                    PLATFORM_input_report
    62 #define return_data                     PLATFORM_return_data
    63 #define make_path                       PLATFORM_make_path
    64 #define read_thread                     PLATFORM_read_thread
    65 
    66 #if __LINUX__
    67 
    68 #include "../../core/linux/SDL_udev.h"
    69 #if SDL_USE_LIBUDEV
    70 static const SDL_UDEV_Symbols *udev_ctx = NULL;
    71 
    72 #define udev_device_get_sysattr_value                    udev_ctx->udev_device_get_sysattr_value
    73 #define udev_new                                         udev_ctx->udev_new
    74 #define udev_unref                                       udev_ctx->udev_unref
    75 #define udev_device_new_from_devnum                      udev_ctx->udev_device_new_from_devnum
    76 #define udev_device_get_parent_with_subsystem_devtype    udev_ctx->udev_device_get_parent_with_subsystem_devtype
    77 #define udev_device_unref                                udev_ctx->udev_device_unref
    78 #define udev_enumerate_new                               udev_ctx->udev_enumerate_new
    79 #define udev_enumerate_add_match_subsystem               udev_ctx->udev_enumerate_add_match_subsystem
    80 #define udev_enumerate_scan_devices                      udev_ctx->udev_enumerate_scan_devices
    81 #define udev_enumerate_get_list_entry                    udev_ctx->udev_enumerate_get_list_entry
    82 #define udev_list_entry_get_name                         udev_ctx->udev_list_entry_get_name
    83 #define udev_device_new_from_syspath                     udev_ctx->udev_device_new_from_syspath
    84 #define udev_device_get_devnode                          udev_ctx->udev_device_get_devnode
    85 #define udev_list_entry_get_next                         udev_ctx->udev_list_entry_get_next
    86 #define udev_enumerate_unref                             udev_ctx->udev_enumerate_unref
    87 
    88 #include "linux/hid.c"
    89 #define HAVE_PLATFORM_BACKEND 1
    90 #endif /* SDL_USE_LIBUDEV */
    91 
    92 #elif __MACOSX__
    93 #include "mac/hid.c"
    94 #define HAVE_PLATFORM_BACKEND 1
    95 #define udev_ctx 1
    96 #elif __WINDOWS__
    97 #include "windows/hid.c"
    98 #define HAVE_PLATFORM_BACKEND 1
    99 #define udev_ctx 1
   100 #else
   101 #error Need a hid.c for this platform!
   102 #endif
   103 
   104 #undef hid_device_
   105 #undef hid_device
   106 #undef hid_device_info
   107 #undef hid_init
   108 #undef hid_exit
   109 #undef hid_enumerate
   110 #undef hid_free_enumeration
   111 #undef hid_open
   112 #undef hid_open_path
   113 #undef hid_write
   114 #undef hid_read_timeout
   115 #undef hid_read
   116 #undef hid_set_nonblocking
   117 #undef hid_send_feature_report
   118 #undef hid_get_feature_report
   119 #undef hid_close
   120 #undef hid_get_manufacturer_string
   121 #undef hid_get_product_string
   122 #undef hid_get_serial_number_string
   123 #undef hid_get_indexed_string
   124 #undef hid_error
   125 #undef new_hid_device
   126 #undef free_hid_device
   127 #undef input_report
   128 #undef return_data
   129 #undef make_path
   130 #undef read_thread
   131 
   132 #ifdef SDL_LIBUSB_DYNAMIC
   133 /* libusb HIDAPI Implementation */
   134 
   135 /* Include this now, for our dynamically-loaded libusb context */
   136 #include <libusb.h>
   137 
   138 static struct
   139 {
   140     void* libhandle;
   141 
   142     int (*init)(libusb_context **ctx);
   143     void (*exit)(libusb_context *ctx);
   144     ssize_t (*get_device_list)(libusb_context *ctx, libusb_device ***list);
   145     void (*free_device_list)(libusb_device **list, int unref_devices);
   146     int (*get_device_descriptor)(libusb_device *dev, struct libusb_device_descriptor *desc);
   147     int (*get_active_config_descriptor)(libusb_device *dev,    struct libusb_config_descriptor **config);
   148     int (*get_config_descriptor)(
   149         libusb_device *dev,
   150         uint8_t config_index,
   151         struct libusb_config_descriptor **config
   152     );
   153     void (*free_config_descriptor)(struct libusb_config_descriptor *config);
   154     uint8_t (*get_bus_number)(libusb_device *dev);
   155     uint8_t (*get_device_address)(libusb_device *dev);
   156     int (*open)(libusb_device *dev, libusb_device_handle **dev_handle);
   157     void (*close)(libusb_device_handle *dev_handle);
   158     int (*claim_interface)(libusb_device_handle *dev_handle, int interface_number);
   159     int (*release_interface)(libusb_device_handle *dev_handle, int interface_number);
   160     int (*kernel_driver_active)(libusb_device_handle *dev_handle, int interface_number);
   161     int (*detach_kernel_driver)(libusb_device_handle *dev_handle, int interface_number);
   162     int (*attach_kernel_driver)(libusb_device_handle *dev_handle, int interface_number);
   163     int (*set_interface_alt_setting)(libusb_device_handle *dev, int interface_number, int alternate_setting);
   164     struct libusb_transfer * (*alloc_transfer)(int iso_packets);
   165     int (*submit_transfer)(struct libusb_transfer *transfer);
   166     int (*cancel_transfer)(struct libusb_transfer *transfer);
   167     void (*free_transfer)(struct libusb_transfer *transfer);
   168     int (*control_transfer)(
   169         libusb_device_handle *dev_handle,
   170         uint8_t request_type,
   171         uint8_t bRequest,
   172         uint16_t wValue,
   173         uint16_t wIndex,
   174         unsigned char *data,
   175         uint16_t wLength,
   176         unsigned int timeout
   177     );
   178     int (*interrupt_transfer)(
   179         libusb_device_handle *dev_handle,
   180         unsigned char endpoint,
   181         unsigned char *data,
   182         int length,
   183         int *actual_length,
   184         unsigned int timeout
   185     );
   186     int (*handle_events)(libusb_context *ctx);
   187     int (*handle_events_completed)(libusb_context *ctx, int *completed);
   188 } libusb_ctx;
   189 
   190 #define libusb_init                            libusb_ctx.init
   191 #define libusb_exit                            libusb_ctx.exit
   192 #define libusb_get_device_list                 libusb_ctx.get_device_list
   193 #define libusb_free_device_list                libusb_ctx.free_device_list
   194 #define libusb_get_device_descriptor           libusb_ctx.get_device_descriptor
   195 #define libusb_get_active_config_descriptor    libusb_ctx.get_active_config_descriptor
   196 #define libusb_get_config_descriptor           libusb_ctx.get_config_descriptor
   197 #define libusb_free_config_descriptor          libusb_ctx.free_config_descriptor
   198 #define libusb_get_bus_number                  libusb_ctx.get_bus_number
   199 #define libusb_get_device_address              libusb_ctx.get_device_address
   200 #define libusb_open                            libusb_ctx.open
   201 #define libusb_close                           libusb_ctx.close
   202 #define libusb_claim_interface                 libusb_ctx.claim_interface
   203 #define libusb_release_interface               libusb_ctx.release_interface
   204 #define libusb_kernel_driver_active            libusb_ctx.kernel_driver_active
   205 #define libusb_detach_kernel_driver            libusb_ctx.detach_kernel_driver
   206 #define libusb_attach_kernel_driver            libusb_ctx.attach_kernel_driver
   207 #define libusb_set_interface_alt_setting       libusb_ctx.set_interface_alt_setting
   208 #define libusb_alloc_transfer                  libusb_ctx.alloc_transfer
   209 #define libusb_submit_transfer                 libusb_ctx.submit_transfer
   210 #define libusb_cancel_transfer                 libusb_ctx.cancel_transfer
   211 #define libusb_free_transfer                   libusb_ctx.free_transfer
   212 #define libusb_control_transfer                libusb_ctx.control_transfer
   213 #define libusb_interrupt_transfer              libusb_ctx.interrupt_transfer
   214 #define libusb_handle_events                   libusb_ctx.handle_events
   215 #define libusb_handle_events_completed         libusb_ctx.handle_events_completed
   216 
   217 #define hid_device_                     LIBUSB_hid_device_
   218 #define hid_device                      LIBUSB_hid_device
   219 #define hid_device_info                 LIBUSB_hid_device_info
   220 #define hid_init                        LIBUSB_hid_init
   221 #define hid_exit                        LIBUSB_hid_exit
   222 #define hid_enumerate                   LIBUSB_hid_enumerate
   223 #define hid_free_enumeration            LIBUSB_hid_free_enumeration
   224 #define hid_open                        LIBUSB_hid_open
   225 #define hid_open_path                   LIBUSB_hid_open_path
   226 #define hid_write                       LIBUSB_hid_write
   227 #define hid_read_timeout                LIBUSB_hid_read_timeout
   228 #define hid_read                        LIBUSB_hid_read
   229 #define hid_set_nonblocking             LIBUSB_hid_set_nonblocking
   230 #define hid_send_feature_report         LIBUSB_hid_send_feature_report
   231 #define hid_get_feature_report          LIBUSB_hid_get_feature_report
   232 #define hid_close                       LIBUSB_hid_close
   233 #define hid_get_manufacturer_string     LIBUSB_hid_get_manufacturer_string
   234 #define hid_get_product_string          LIBUSB_hid_get_product_string
   235 #define hid_get_serial_number_string    LIBUSB_hid_get_serial_number_string
   236 #define hid_get_indexed_string          LIBUSB_hid_get_indexed_string
   237 #define hid_error                       LIBUSB_hid_error
   238 #define new_hid_device                  LIBUSB_new_hid_device
   239 #define free_hid_device                 LIBUSB_free_hid_device
   240 #define input_report                    LIBUSB_input_report
   241 #define return_data                     LIBUSB_return_data
   242 #define make_path                       LIBUSB_make_path
   243 #define read_thread                     LIBUSB_read_thread
   244 
   245 #ifndef __FreeBSD__
   246 /* this is awkwardly inlined, so we need to re-implement it here
   247  * so we can override the libusb_control_transfer call */
   248 static int
   249 SDL_libusb_get_string_descriptor(libusb_device_handle *dev,
   250                                  uint8_t descriptor_index, uint16_t lang_id,
   251                                  unsigned char *data, int length)
   252 {
   253     return libusb_control_transfer(dev,
   254                                    LIBUSB_ENDPOINT_IN | 0x0, /* Endpoint 0 IN */
   255                                    LIBUSB_REQUEST_GET_DESCRIPTOR,
   256                                    (LIBUSB_DT_STRING << 8) | descriptor_index,
   257                                    lang_id,
   258                                    data,
   259                                    (uint16_t) length,
   260                                    1000);
   261 }
   262 #define libusb_get_string_descriptor SDL_libusb_get_string_descriptor
   263 #endif /* __FreeBSD__ */
   264 
   265 #undef HIDAPI_H__
   266 #include "libusb/hid.c"
   267 
   268 #undef hid_device_
   269 #undef hid_device
   270 #undef hid_device_info
   271 #undef hid_init
   272 #undef hid_exit
   273 #undef hid_enumerate
   274 #undef hid_free_enumeration
   275 #undef hid_open
   276 #undef hid_open_path
   277 #undef hid_write
   278 #undef hid_read_timeout
   279 #undef hid_read
   280 #undef hid_set_nonblocking
   281 #undef hid_send_feature_report
   282 #undef hid_get_feature_report
   283 #undef hid_close
   284 #undef hid_get_manufacturer_string
   285 #undef hid_get_product_string
   286 #undef hid_get_serial_number_string
   287 #undef hid_get_indexed_string
   288 #undef hid_error
   289 #undef new_hid_device
   290 #undef free_hid_device
   291 #undef input_report
   292 #undef return_data
   293 #undef make_path
   294 #undef read_thread
   295 
   296 #endif /* SDL_LIBUSB_DYNAMIC */
   297 
   298 /* Shared HIDAPI Implementation */
   299 
   300 #undef HIDAPI_H__
   301 #include "hidapi.h"
   302 
   303 struct hidapi_backend {
   304 #define F(x) typeof(x) *x
   305     F(hid_write);
   306     F(hid_read_timeout);
   307     F(hid_read);
   308     F(hid_set_nonblocking);
   309     F(hid_send_feature_report);
   310     F(hid_get_feature_report);
   311     F(hid_close);
   312     F(hid_get_manufacturer_string);
   313     F(hid_get_product_string);
   314     F(hid_get_serial_number_string);
   315     F(hid_get_indexed_string);
   316     F(hid_error);
   317 #undef F
   318 };
   319 
   320 #if HAVE_PLATFORM_BACKEND
   321 static const struct hidapi_backend PLATFORM_Backend = {
   322     (void*)PLATFORM_hid_write,
   323     (void*)PLATFORM_hid_read_timeout,
   324     (void*)PLATFORM_hid_read,
   325     (void*)PLATFORM_hid_set_nonblocking,
   326     (void*)PLATFORM_hid_send_feature_report,
   327     (void*)PLATFORM_hid_get_feature_report,
   328     (void*)PLATFORM_hid_close,
   329     (void*)PLATFORM_hid_get_manufacturer_string,
   330     (void*)PLATFORM_hid_get_product_string,
   331     (void*)PLATFORM_hid_get_serial_number_string,
   332     (void*)PLATFORM_hid_get_indexed_string,
   333     (void*)PLATFORM_hid_error
   334 };
   335 #endif /* HAVE_PLATFORM_BACKEND */
   336 
   337 #ifdef SDL_LIBUSB_DYNAMIC
   338 static const struct hidapi_backend LIBUSB_Backend = {
   339     (void*)LIBUSB_hid_write,
   340     (void*)LIBUSB_hid_read_timeout,
   341     (void*)LIBUSB_hid_read,
   342     (void*)LIBUSB_hid_set_nonblocking,
   343     (void*)LIBUSB_hid_send_feature_report,
   344     (void*)LIBUSB_hid_get_feature_report,
   345     (void*)LIBUSB_hid_close,
   346     (void*)LIBUSB_hid_get_manufacturer_string,
   347     (void*)LIBUSB_hid_get_product_string,
   348     (void*)LIBUSB_hid_get_serial_number_string,
   349     (void*)LIBUSB_hid_get_indexed_string,
   350     (void*)LIBUSB_hid_error
   351 };
   352 #endif /* SDL_LIBUSB_DYNAMIC */
   353 
   354 typedef struct _HIDDeviceWrapper HIDDeviceWrapper;
   355 struct _HIDDeviceWrapper
   356 {
   357     hid_device *device; /* must be first field */
   358     const struct hidapi_backend *backend;
   359 };
   360 
   361 static HIDDeviceWrapper *
   362 CreateHIDDeviceWrapper(hid_device *device, const struct hidapi_backend *backend)
   363 {
   364     HIDDeviceWrapper *ret = SDL_malloc(sizeof(*ret));
   365     ret->device = device;
   366     ret->backend = backend;
   367     return ret;
   368 }
   369 
   370 static hid_device *
   371 WrapHIDDevice(HIDDeviceWrapper *wrapper)
   372 {
   373     return (hid_device *)wrapper;
   374 }
   375 
   376 static HIDDeviceWrapper *
   377 UnwrapHIDDevice(hid_device *device)
   378 {
   379     return (HIDDeviceWrapper *)device;
   380 }
   381 
   382 static void
   383 DeleteHIDDeviceWrapper(HIDDeviceWrapper *device)
   384 {
   385     SDL_free(device);
   386 }
   387 
   388 #define COPY_IF_EXISTS(var) \
   389     if (pSrc->var != NULL) { \
   390         pDst->var = SDL_strdup(pSrc->var); \
   391     } else { \
   392         pDst->var = NULL; \
   393     }
   394 #define WCOPY_IF_EXISTS(var) \
   395     if (pSrc->var != NULL) { \
   396         pDst->var = SDL_wcsdup(pSrc->var); \
   397     } else { \
   398         pDst->var = NULL; \
   399     }
   400 
   401 #ifdef SDL_LIBUSB_DYNAMIC
   402 static void
   403 LIBUSB_CopyHIDDeviceInfo(struct LIBUSB_hid_device_info *pSrc,
   404                          struct hid_device_info *pDst)
   405 {
   406     COPY_IF_EXISTS(path)
   407     pDst->vendor_id = pSrc->vendor_id;
   408     pDst->product_id = pSrc->product_id;
   409     WCOPY_IF_EXISTS(serial_number)
   410     pDst->release_number = pSrc->release_number;
   411     WCOPY_IF_EXISTS(manufacturer_string)
   412     WCOPY_IF_EXISTS(product_string)
   413     pDst->usage_page = pSrc->usage_page;
   414     pDst->usage = pSrc->usage;
   415     pDst->interface_number = pSrc->interface_number;
   416     pDst->interface_class = pSrc->interface_class;
   417     pDst->interface_subclass = pSrc->interface_subclass;
   418     pDst->interface_protocol = pSrc->interface_protocol;
   419     pDst->next = NULL;
   420 }
   421 #endif /* SDL_LIBUSB_DYNAMIC */
   422 
   423 #if HAVE_PLATFORM_BACKEND
   424 static void
   425 PLATFORM_CopyHIDDeviceInfo(struct PLATFORM_hid_device_info *pSrc,
   426                            struct hid_device_info *pDst)
   427 {
   428     COPY_IF_EXISTS(path)
   429     pDst->vendor_id = pSrc->vendor_id;
   430     pDst->product_id = pSrc->product_id;
   431     WCOPY_IF_EXISTS(serial_number)
   432     pDst->release_number = pSrc->release_number;
   433     WCOPY_IF_EXISTS(manufacturer_string)
   434     WCOPY_IF_EXISTS(product_string)
   435     pDst->usage_page = pSrc->usage_page;
   436     pDst->usage = pSrc->usage;
   437     pDst->interface_number = pSrc->interface_number;
   438     pDst->interface_class = pSrc->interface_class;
   439     pDst->interface_subclass = pSrc->interface_subclass;
   440     pDst->interface_protocol = pSrc->interface_protocol;
   441     pDst->next = NULL;
   442 }
   443 #endif /* HAVE_PLATFORM_BACKEND */
   444 
   445 #undef COPY_IF_EXISTS
   446 #undef WCOPY_IF_EXISTS
   447 
   448 static SDL_bool SDL_hidapi_wasinit = SDL_FALSE;
   449 
   450 int HID_API_EXPORT HID_API_CALL hid_init(void)
   451 {
   452     int err;
   453 
   454     if (SDL_hidapi_wasinit == SDL_TRUE) {
   455         return 0;
   456     }
   457 
   458 #ifdef SDL_LIBUSB_DYNAMIC
   459     libusb_ctx.libhandle = SDL_LoadObject(SDL_LIBUSB_DYNAMIC);
   460     if (libusb_ctx.libhandle != NULL) {
   461         #define LOAD_LIBUSB_SYMBOL(func) \
   462             libusb_ctx.func = SDL_LoadFunction(libusb_ctx.libhandle, "libusb_" #func);
   463         LOAD_LIBUSB_SYMBOL(init)
   464         LOAD_LIBUSB_SYMBOL(exit)
   465         LOAD_LIBUSB_SYMBOL(get_device_list)
   466         LOAD_LIBUSB_SYMBOL(free_device_list)
   467         LOAD_LIBUSB_SYMBOL(get_device_descriptor)
   468         LOAD_LIBUSB_SYMBOL(get_active_config_descriptor)
   469         LOAD_LIBUSB_SYMBOL(get_config_descriptor)
   470         LOAD_LIBUSB_SYMBOL(free_config_descriptor)
   471         LOAD_LIBUSB_SYMBOL(get_bus_number)
   472         LOAD_LIBUSB_SYMBOL(get_device_address)
   473         LOAD_LIBUSB_SYMBOL(open)
   474         LOAD_LIBUSB_SYMBOL(close)
   475         LOAD_LIBUSB_SYMBOL(claim_interface)
   476         LOAD_LIBUSB_SYMBOL(release_interface)
   477         LOAD_LIBUSB_SYMBOL(kernel_driver_active)
   478         LOAD_LIBUSB_SYMBOL(detach_kernel_driver)
   479         LOAD_LIBUSB_SYMBOL(attach_kernel_driver)
   480         LOAD_LIBUSB_SYMBOL(set_interface_alt_setting)
   481         LOAD_LIBUSB_SYMBOL(alloc_transfer)
   482         LOAD_LIBUSB_SYMBOL(submit_transfer)
   483         LOAD_LIBUSB_SYMBOL(cancel_transfer)
   484         LOAD_LIBUSB_SYMBOL(free_transfer)
   485         LOAD_LIBUSB_SYMBOL(control_transfer)
   486         LOAD_LIBUSB_SYMBOL(interrupt_transfer)
   487         LOAD_LIBUSB_SYMBOL(handle_events)
   488         LOAD_LIBUSB_SYMBOL(handle_events_completed)
   489         #undef LOAD_LIBUSB_SYMBOL
   490 
   491         if ((err = LIBUSB_hid_init()) < 0) {
   492             SDL_UnloadObject(libusb_ctx.libhandle);
   493             return err;
   494         }
   495     }
   496 #endif /* SDL_LIBUSB_DYNAMIC */
   497 
   498 #if HAVE_PLATFORM_BACKEND
   499 #if __LINUX__
   500     udev_ctx = SDL_UDEV_GetUdevSyms();
   501 #endif /* __LINUX __ */
   502     if (udev_ctx && (err = PLATFORM_hid_init()) < 0) {
   503 #ifdef SDL_LIBUSB_DYNAMIC
   504         if (libusb_ctx.libhandle) {
   505             SDL_UnloadObject(libusb_ctx.libhandle);
   506         }
   507 #endif /* SDL_LIBUSB_DYNAMIC */
   508         return err;
   509     }
   510 #endif /* HAVE_PLATFORM_BACKEND */
   511 
   512     return 0;
   513 }
   514 
   515 int HID_API_EXPORT HID_API_CALL hid_exit(void)
   516 {
   517     int err = 0;
   518 
   519     if (SDL_hidapi_wasinit == SDL_FALSE) {
   520         return 0;
   521     }
   522 
   523 #if HAVE_PLATFORM_BACKEND
   524     if (udev_ctx) {
   525         err = PLATFORM_hid_exit();
   526     }
   527 #endif /* HAVE_PLATFORM_BACKEND */
   528 #ifdef SDL_LIBUSB_DYNAMIC
   529     if (libusb_ctx.libhandle) {
   530         err |= LIBUSB_hid_exit(); /* Ehhhhh */
   531         SDL_UnloadObject(libusb_ctx.libhandle);
   532     }
   533 #endif /* SDL_LIBUSB_DYNAMIC */
   534     return err;
   535 }
   536 
   537 struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id)
   538 {
   539 #if HAVE_PLATFORM_BACKEND
   540     struct PLATFORM_hid_device_info *raw_devs = NULL;
   541     struct PLATFORM_hid_device_info *raw_dev;
   542 #endif /* HAVE_PLATFORM_BACKEND */
   543     struct hid_device_info *devs = NULL, *last = NULL, *new_dev;
   544     SDL_bool bFound;
   545 
   546     if (SDL_hidapi_wasinit == SDL_FALSE) {
   547         hid_init();
   548     }
   549 
   550 #if HAVE_PLATFORM_BACKEND
   551     if (udev_ctx) {
   552         raw_devs = PLATFORM_hid_enumerate(vendor_id, product_id);
   553     }
   554 #endif /* HAVE_PLATFORM_BACKEND */
   555 
   556 #ifdef SDL_LIBUSB_DYNAMIC
   557     if (libusb_ctx.libhandle) {
   558         struct LIBUSB_hid_device_info *usb_devs = LIBUSB_hid_enumerate(vendor_id, product_id);
   559         struct LIBUSB_hid_device_info *usb_dev;
   560         for (usb_dev = usb_devs; usb_dev; usb_dev = usb_dev->next) {
   561             bFound = SDL_FALSE;
   562 #if HAVE_PLATFORM_BACKEND
   563             for (raw_dev = raw_devs; raw_dev; raw_dev = raw_dev->next) {
   564                 if (raw_dev->vendor_id == 0x057e && raw_dev->product_id == 0x0337) {
   565                     /* The GameCube adapter is handled by the USB HIDAPI driver */
   566                     continue;
   567                 }
   568                 if (usb_dev->vendor_id == raw_dev->vendor_id &&
   569                     usb_dev->product_id == raw_dev->product_id &&
   570                     (raw_dev->interface_number < 0 || usb_dev->interface_number == raw_dev->interface_number)) {
   571                     bFound = SDL_TRUE;
   572                     break;
   573                 }
   574             }
   575 #endif
   576 
   577             if (!bFound) {
   578                 new_dev = (struct hid_device_info*) SDL_malloc(sizeof(struct hid_device_info));
   579                 LIBUSB_CopyHIDDeviceInfo(usb_dev, new_dev);
   580 
   581                 if (last != NULL) {
   582                     last->next = new_dev;
   583                 } else {
   584                     devs = new_dev;
   585                 }
   586                 last = new_dev;
   587             }
   588         }
   589         LIBUSB_hid_free_enumeration(usb_devs);
   590     }
   591 #endif /* SDL_LIBUSB_DYNAMIC */
   592 
   593 #if HAVE_PLATFORM_BACKEND
   594     if (udev_ctx) {
   595         for (raw_dev = raw_devs; raw_dev; raw_dev = raw_dev->next) {
   596             bFound = SDL_FALSE;
   597             for (new_dev = devs; new_dev; new_dev = new_dev->next) {
   598                 if (raw_dev->vendor_id == new_dev->vendor_id &&
   599                     raw_dev->product_id == new_dev->product_id &&
   600                     raw_dev->interface_number == new_dev->interface_number) {
   601                     bFound = SDL_TRUE;
   602                     break;
   603                 }
   604             }
   605 
   606             if (!bFound) {
   607                 new_dev = (struct hid_device_info*) SDL_malloc(sizeof(struct hid_device_info));
   608                 PLATFORM_CopyHIDDeviceInfo(raw_dev, new_dev);
   609                 new_dev->next = NULL;
   610 
   611                 if (last != NULL) {
   612                     last->next = new_dev;
   613                 } else {
   614                     devs = new_dev;
   615                 }
   616                 last = new_dev;
   617             }
   618         }
   619         PLATFORM_hid_free_enumeration(raw_devs);
   620     }
   621 #endif /* HAVE_PLATFORM_BACKEND */
   622 
   623     return devs;
   624 }
   625 
   626 void  HID_API_EXPORT HID_API_CALL hid_free_enumeration(struct hid_device_info *devs)
   627 {
   628     while (devs) {
   629         struct hid_device_info *next = devs->next;
   630         SDL_free(devs->path);
   631         SDL_free(devs->serial_number);
   632         SDL_free(devs->manufacturer_string);
   633         SDL_free(devs->product_string);
   634         SDL_free(devs);
   635         devs = next;
   636     }
   637 }
   638 
   639 HID_API_EXPORT hid_device * HID_API_CALL hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number)
   640 {
   641     hid_device *pDevice = NULL;
   642 
   643     if (SDL_hidapi_wasinit == SDL_FALSE) {
   644         hid_init();
   645     }
   646 
   647 #if HAVE_PLATFORM_BACKEND
   648     if (udev_ctx &&
   649         (pDevice = (hid_device*) PLATFORM_hid_open(vendor_id, product_id, serial_number)) != NULL) {
   650 
   651         HIDDeviceWrapper *wrapper = CreateHIDDeviceWrapper(pDevice, &PLATFORM_Backend);
   652         return WrapHIDDevice(wrapper);
   653     }
   654 #endif /* HAVE_PLATFORM_BACKEND */
   655 #ifdef SDL_LIBUSB_DYNAMIC
   656     if (libusb_ctx.libhandle &&
   657         (pDevice = (hid_device*) LIBUSB_hid_open(vendor_id, product_id, serial_number)) != NULL) {
   658 
   659         HIDDeviceWrapper *wrapper = CreateHIDDeviceWrapper(pDevice, &LIBUSB_Backend);
   660         return WrapHIDDevice(wrapper);
   661     }
   662 #endif /* SDL_LIBUSB_DYNAMIC */
   663     return NULL;
   664 }
   665 
   666 HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path, int bExclusive /* = false */)
   667 {
   668     hid_device *pDevice = NULL;
   669 
   670     if (SDL_hidapi_wasinit == SDL_FALSE) {
   671         hid_init();
   672     }
   673 
   674 #if HAVE_PLATFORM_BACKEND
   675     if (udev_ctx &&
   676         (pDevice = (hid_device*) PLATFORM_hid_open_path(path, bExclusive)) != NULL) {
   677 
   678         HIDDeviceWrapper *wrapper = CreateHIDDeviceWrapper(pDevice, &PLATFORM_Backend);
   679         return WrapHIDDevice(wrapper);
   680     }
   681 #endif /* HAVE_PLATFORM_BACKEND */
   682 #ifdef SDL_LIBUSB_DYNAMIC
   683     if (libusb_ctx.libhandle &&
   684         (pDevice = (hid_device*) LIBUSB_hid_open_path(path, bExclusive)) != NULL) {
   685 
   686         HIDDeviceWrapper *wrapper = CreateHIDDeviceWrapper(pDevice, &LIBUSB_Backend);
   687         return WrapHIDDevice(wrapper);
   688     }
   689 #endif /* SDL_LIBUSB_DYNAMIC */
   690     return NULL;
   691 }
   692 
   693 int  HID_API_EXPORT HID_API_CALL hid_write(hid_device *device, const unsigned char *data, size_t length)
   694 {
   695     HIDDeviceWrapper *wrapper = UnwrapHIDDevice(device);
   696     return wrapper->backend->hid_write(wrapper->device, data, length);
   697 }
   698 
   699 int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *device, unsigned char *data, size_t length, int milliseconds)
   700 {
   701     HIDDeviceWrapper *wrapper = UnwrapHIDDevice(device);
   702     return wrapper->backend->hid_read_timeout(wrapper->device, data, length, milliseconds);
   703 }
   704 
   705 int  HID_API_EXPORT HID_API_CALL hid_read(hid_device *device, unsigned char *data, size_t length)
   706 {
   707     HIDDeviceWrapper *wrapper = UnwrapHIDDevice(device);
   708     return wrapper->backend->hid_read(wrapper->device, data, length);
   709 }
   710 
   711 int  HID_API_EXPORT HID_API_CALL hid_set_nonblocking(hid_device *device, int nonblock)
   712 {
   713     HIDDeviceWrapper *wrapper = UnwrapHIDDevice(device);
   714     return wrapper->backend->hid_set_nonblocking(wrapper->device, nonblock);
   715 }
   716 
   717 int HID_API_EXPORT HID_API_CALL hid_send_feature_report(hid_device *device, const unsigned char *data, size_t length)
   718 {
   719     HIDDeviceWrapper *wrapper = UnwrapHIDDevice(device);
   720     return wrapper->backend->hid_send_feature_report(wrapper->device, data, length);
   721 }
   722 
   723 int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *device, unsigned char *data, size_t length)
   724 {
   725     HIDDeviceWrapper *wrapper = UnwrapHIDDevice(device);
   726     return wrapper->backend->hid_get_feature_report(wrapper->device, data, length);
   727 }
   728 
   729 void HID_API_EXPORT HID_API_CALL hid_close(hid_device *device)
   730 {
   731     HIDDeviceWrapper *wrapper = UnwrapHIDDevice(device);
   732     wrapper->backend->hid_close(wrapper->device);
   733     DeleteHIDDeviceWrapper(wrapper);
   734 }
   735 
   736 int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *device, wchar_t *string, size_t maxlen)
   737 {
   738     HIDDeviceWrapper *wrapper = UnwrapHIDDevice(device);
   739     return wrapper->backend->hid_get_manufacturer_string(wrapper->device, string, maxlen);
   740 }
   741 
   742 int HID_API_EXPORT_CALL hid_get_product_string(hid_device *device, wchar_t *string, size_t maxlen)
   743 {
   744     HIDDeviceWrapper *wrapper = UnwrapHIDDevice(device);
   745     return wrapper->backend->hid_get_product_string(wrapper->device, string, maxlen);
   746 }
   747 
   748 int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *device, wchar_t *string, size_t maxlen)
   749 {
   750     HIDDeviceWrapper *wrapper = UnwrapHIDDevice(device);
   751     return wrapper->backend->hid_get_serial_number_string(wrapper->device, string, maxlen);
   752 }
   753 
   754 int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *device, int string_index, wchar_t *string, size_t maxlen)
   755 {
   756     HIDDeviceWrapper *wrapper = UnwrapHIDDevice(device);
   757     return wrapper->backend->hid_get_indexed_string(wrapper->device, string_index, string, maxlen);
   758 }
   759 
   760 HID_API_EXPORT const wchar_t* HID_API_CALL hid_error(hid_device *device)
   761 {
   762     HIDDeviceWrapper *wrapper = UnwrapHIDDevice(device);
   763     return wrapper->backend->hid_error(wrapper->device);
   764 }
   765 
   766 #endif /* SDL_JOYSTICK_HIDAPI */