mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-03-19 12:20:57 +00:00
Updates SDL to 2.0.12
This commit is contained in:
parent
3108a08650
commit
a526029f2f
861 changed files with 25596 additions and 8904 deletions
|
|
@ -12,5 +12,5 @@ Ludovic Rousseau <rousseau@debian.org>:
|
|||
|
||||
|
||||
For a comprehensive list of contributions, see the commit list at github:
|
||||
http://github.com/signal11/hidapi/commits/master
|
||||
https://github.com/libusb/hidapi/commits/master
|
||||
|
||||
|
|
|
|||
|
|
@ -122,7 +122,7 @@ HIDAPI may be used by one of three licenses as outlined in LICENSE.txt.
|
|||
Download
|
||||
=========
|
||||
HIDAPI can be downloaded from github
|
||||
git clone git://github.com/signal11/hidapi.git
|
||||
git clone git://github.com/libusb/hidapi.git
|
||||
|
||||
Build Instructions
|
||||
===================
|
||||
|
|
|
|||
752
Engine/lib/sdl/src/hidapi/SDL_hidapi.c
Normal file
752
Engine/lib/sdl/src/hidapi/SDL_hidapi.c
Normal file
|
|
@ -0,0 +1,752 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/* Original hybrid wrapper for Linux by Valve Software. Their original notes:
|
||||
*
|
||||
* The libusb version doesn't support Bluetooth, but not all Linux
|
||||
* distributions allow access to /dev/hidraw*
|
||||
*
|
||||
* This merges the two, at a small performance cost, until distributions
|
||||
* have granted access to /dev/hidraw*
|
||||
*/
|
||||
|
||||
#include "../SDL_internal.h"
|
||||
#include "SDL_loadso.h"
|
||||
|
||||
#ifdef SDL_JOYSTICK_HIDAPI
|
||||
|
||||
/* Platform HIDAPI Implementation */
|
||||
|
||||
#define hid_device_ PLATFORM_hid_device_
|
||||
#define hid_device PLATFORM_hid_device
|
||||
#define hid_device_info PLATFORM_hid_device_info
|
||||
#define hid_init PLATFORM_hid_init
|
||||
#define hid_exit PLATFORM_hid_exit
|
||||
#define hid_enumerate PLATFORM_hid_enumerate
|
||||
#define hid_free_enumeration PLATFORM_hid_free_enumeration
|
||||
#define hid_open PLATFORM_hid_open
|
||||
#define hid_open_path PLATFORM_hid_open_path
|
||||
#define hid_write PLATFORM_hid_write
|
||||
#define hid_read_timeout PLATFORM_hid_read_timeout
|
||||
#define hid_read PLATFORM_hid_read
|
||||
#define hid_set_nonblocking PLATFORM_hid_set_nonblocking
|
||||
#define hid_send_feature_report PLATFORM_hid_send_feature_report
|
||||
#define hid_get_feature_report PLATFORM_hid_get_feature_report
|
||||
#define hid_close PLATFORM_hid_close
|
||||
#define hid_get_manufacturer_string PLATFORM_hid_get_manufacturer_string
|
||||
#define hid_get_product_string PLATFORM_hid_get_product_string
|
||||
#define hid_get_serial_number_string PLATFORM_hid_get_serial_number_string
|
||||
#define hid_get_indexed_string PLATFORM_hid_get_indexed_string
|
||||
#define hid_error PLATFORM_hid_error
|
||||
#define new_hid_device PLATFORM_new_hid_device
|
||||
#define free_hid_device PLATFORM_free_hid_device
|
||||
#define input_report PLATFORM_input_report
|
||||
#define return_data PLATFORM_return_data
|
||||
#define make_path PLATFORM_make_path
|
||||
#define read_thread PLATFORM_read_thread
|
||||
|
||||
#if __LINUX__
|
||||
|
||||
#include "../../core/linux/SDL_udev.h"
|
||||
#if SDL_USE_LIBUDEV
|
||||
static const SDL_UDEV_Symbols *udev_ctx = NULL;
|
||||
|
||||
#define udev_device_get_sysattr_value udev_ctx->udev_device_get_sysattr_value
|
||||
#define udev_new udev_ctx->udev_new
|
||||
#define udev_unref udev_ctx->udev_unref
|
||||
#define udev_device_new_from_devnum udev_ctx->udev_device_new_from_devnum
|
||||
#define udev_device_get_parent_with_subsystem_devtype udev_ctx->udev_device_get_parent_with_subsystem_devtype
|
||||
#define udev_device_unref udev_ctx->udev_device_unref
|
||||
#define udev_enumerate_new udev_ctx->udev_enumerate_new
|
||||
#define udev_enumerate_add_match_subsystem udev_ctx->udev_enumerate_add_match_subsystem
|
||||
#define udev_enumerate_scan_devices udev_ctx->udev_enumerate_scan_devices
|
||||
#define udev_enumerate_get_list_entry udev_ctx->udev_enumerate_get_list_entry
|
||||
#define udev_list_entry_get_name udev_ctx->udev_list_entry_get_name
|
||||
#define udev_device_new_from_syspath udev_ctx->udev_device_new_from_syspath
|
||||
#define udev_device_get_devnode udev_ctx->udev_device_get_devnode
|
||||
#define udev_list_entry_get_next udev_ctx->udev_list_entry_get_next
|
||||
#define udev_enumerate_unref udev_ctx->udev_enumerate_unref
|
||||
|
||||
#include "linux/hid.c"
|
||||
#define HAVE_PLATFORM_BACKEND 1
|
||||
#endif /* SDL_USE_LIBUDEV */
|
||||
|
||||
#elif __MACOSX__
|
||||
#include "mac/hid.c"
|
||||
#define HAVE_PLATFORM_BACKEND 1
|
||||
#define udev_ctx 1
|
||||
#elif __WINDOWS__
|
||||
#include "windows/hid.c"
|
||||
#define HAVE_PLATFORM_BACKEND 1
|
||||
#define udev_ctx 1
|
||||
#else
|
||||
#error Need a hid.c for this platform!
|
||||
#endif
|
||||
|
||||
#undef hid_device_
|
||||
#undef hid_device
|
||||
#undef hid_device_info
|
||||
#undef hid_init
|
||||
#undef hid_exit
|
||||
#undef hid_enumerate
|
||||
#undef hid_free_enumeration
|
||||
#undef hid_open
|
||||
#undef hid_open_path
|
||||
#undef hid_write
|
||||
#undef hid_read_timeout
|
||||
#undef hid_read
|
||||
#undef hid_set_nonblocking
|
||||
#undef hid_send_feature_report
|
||||
#undef hid_get_feature_report
|
||||
#undef hid_close
|
||||
#undef hid_get_manufacturer_string
|
||||
#undef hid_get_product_string
|
||||
#undef hid_get_serial_number_string
|
||||
#undef hid_get_indexed_string
|
||||
#undef hid_error
|
||||
#undef new_hid_device
|
||||
#undef free_hid_device
|
||||
#undef input_report
|
||||
#undef return_data
|
||||
#undef make_path
|
||||
#undef read_thread
|
||||
|
||||
#ifdef SDL_LIBUSB_DYNAMIC
|
||||
/* libusb HIDAPI Implementation */
|
||||
|
||||
/* Include this now, for our dynamically-loaded libusb context */
|
||||
#include <libusb.h>
|
||||
|
||||
static struct
|
||||
{
|
||||
void* libhandle;
|
||||
|
||||
int (*init)(libusb_context **ctx);
|
||||
void (*exit)(libusb_context *ctx);
|
||||
ssize_t (*get_device_list)(libusb_context *ctx, libusb_device ***list);
|
||||
void (*free_device_list)(libusb_device **list, int unref_devices);
|
||||
int (*get_device_descriptor)(libusb_device *dev, struct libusb_device_descriptor *desc);
|
||||
int (*get_active_config_descriptor)(libusb_device *dev, struct libusb_config_descriptor **config);
|
||||
int (*get_config_descriptor)(
|
||||
libusb_device *dev,
|
||||
uint8_t config_index,
|
||||
struct libusb_config_descriptor **config
|
||||
);
|
||||
void (*free_config_descriptor)(struct libusb_config_descriptor *config);
|
||||
uint8_t (*get_bus_number)(libusb_device *dev);
|
||||
uint8_t (*get_device_address)(libusb_device *dev);
|
||||
int (*open)(libusb_device *dev, libusb_device_handle **dev_handle);
|
||||
void (*close)(libusb_device_handle *dev_handle);
|
||||
int (*claim_interface)(libusb_device_handle *dev_handle, int interface_number);
|
||||
int (*release_interface)(libusb_device_handle *dev_handle, int interface_number);
|
||||
int (*kernel_driver_active)(libusb_device_handle *dev_handle, int interface_number);
|
||||
int (*detach_kernel_driver)(libusb_device_handle *dev_handle, int interface_number);
|
||||
int (*attach_kernel_driver)(libusb_device_handle *dev_handle, int interface_number);
|
||||
int (*set_interface_alt_setting)(libusb_device_handle *dev, int interface_number, int alternate_setting);
|
||||
struct libusb_transfer * (*alloc_transfer)(int iso_packets);
|
||||
int (*submit_transfer)(struct libusb_transfer *transfer);
|
||||
int (*cancel_transfer)(struct libusb_transfer *transfer);
|
||||
void (*free_transfer)(struct libusb_transfer *transfer);
|
||||
int (*control_transfer)(
|
||||
libusb_device_handle *dev_handle,
|
||||
uint8_t request_type,
|
||||
uint8_t bRequest,
|
||||
uint16_t wValue,
|
||||
uint16_t wIndex,
|
||||
unsigned char *data,
|
||||
uint16_t wLength,
|
||||
unsigned int timeout
|
||||
);
|
||||
int (*interrupt_transfer)(
|
||||
libusb_device_handle *dev_handle,
|
||||
unsigned char endpoint,
|
||||
unsigned char *data,
|
||||
int length,
|
||||
int *actual_length,
|
||||
unsigned int timeout
|
||||
);
|
||||
int (*handle_events)(libusb_context *ctx);
|
||||
int (*handle_events_completed)(libusb_context *ctx, int *completed);
|
||||
} libusb_ctx;
|
||||
|
||||
#define libusb_init libusb_ctx.init
|
||||
#define libusb_exit libusb_ctx.exit
|
||||
#define libusb_get_device_list libusb_ctx.get_device_list
|
||||
#define libusb_free_device_list libusb_ctx.free_device_list
|
||||
#define libusb_get_device_descriptor libusb_ctx.get_device_descriptor
|
||||
#define libusb_get_active_config_descriptor libusb_ctx.get_active_config_descriptor
|
||||
#define libusb_get_config_descriptor libusb_ctx.get_config_descriptor
|
||||
#define libusb_free_config_descriptor libusb_ctx.free_config_descriptor
|
||||
#define libusb_get_bus_number libusb_ctx.get_bus_number
|
||||
#define libusb_get_device_address libusb_ctx.get_device_address
|
||||
#define libusb_open libusb_ctx.open
|
||||
#define libusb_close libusb_ctx.close
|
||||
#define libusb_claim_interface libusb_ctx.claim_interface
|
||||
#define libusb_release_interface libusb_ctx.release_interface
|
||||
#define libusb_kernel_driver_active libusb_ctx.kernel_driver_active
|
||||
#define libusb_detach_kernel_driver libusb_ctx.detach_kernel_driver
|
||||
#define libusb_attach_kernel_driver libusb_ctx.attach_kernel_driver
|
||||
#define libusb_set_interface_alt_setting libusb_ctx.set_interface_alt_setting
|
||||
#define libusb_alloc_transfer libusb_ctx.alloc_transfer
|
||||
#define libusb_submit_transfer libusb_ctx.submit_transfer
|
||||
#define libusb_cancel_transfer libusb_ctx.cancel_transfer
|
||||
#define libusb_free_transfer libusb_ctx.free_transfer
|
||||
#define libusb_control_transfer libusb_ctx.control_transfer
|
||||
#define libusb_interrupt_transfer libusb_ctx.interrupt_transfer
|
||||
#define libusb_handle_events libusb_ctx.handle_events
|
||||
#define libusb_handle_events_completed libusb_ctx.handle_events_completed
|
||||
|
||||
#define hid_device_ LIBUSB_hid_device_
|
||||
#define hid_device LIBUSB_hid_device
|
||||
#define hid_device_info LIBUSB_hid_device_info
|
||||
#define hid_init LIBUSB_hid_init
|
||||
#define hid_exit LIBUSB_hid_exit
|
||||
#define hid_enumerate LIBUSB_hid_enumerate
|
||||
#define hid_free_enumeration LIBUSB_hid_free_enumeration
|
||||
#define hid_open LIBUSB_hid_open
|
||||
#define hid_open_path LIBUSB_hid_open_path
|
||||
#define hid_write LIBUSB_hid_write
|
||||
#define hid_read_timeout LIBUSB_hid_read_timeout
|
||||
#define hid_read LIBUSB_hid_read
|
||||
#define hid_set_nonblocking LIBUSB_hid_set_nonblocking
|
||||
#define hid_send_feature_report LIBUSB_hid_send_feature_report
|
||||
#define hid_get_feature_report LIBUSB_hid_get_feature_report
|
||||
#define hid_close LIBUSB_hid_close
|
||||
#define hid_get_manufacturer_string LIBUSB_hid_get_manufacturer_string
|
||||
#define hid_get_product_string LIBUSB_hid_get_product_string
|
||||
#define hid_get_serial_number_string LIBUSB_hid_get_serial_number_string
|
||||
#define hid_get_indexed_string LIBUSB_hid_get_indexed_string
|
||||
#define hid_error LIBUSB_hid_error
|
||||
#define new_hid_device LIBUSB_new_hid_device
|
||||
#define free_hid_device LIBUSB_free_hid_device
|
||||
#define input_report LIBUSB_input_report
|
||||
#define return_data LIBUSB_return_data
|
||||
#define make_path LIBUSB_make_path
|
||||
#define read_thread LIBUSB_read_thread
|
||||
|
||||
#ifndef __FreeBSD__
|
||||
/* this is awkwardly inlined, so we need to re-implement it here
|
||||
* so we can override the libusb_control_transfer call */
|
||||
static int
|
||||
SDL_libusb_get_string_descriptor(libusb_device_handle *dev,
|
||||
uint8_t descriptor_index, uint16_t lang_id,
|
||||
unsigned char *data, int length)
|
||||
{
|
||||
return libusb_control_transfer(dev,
|
||||
LIBUSB_ENDPOINT_IN | 0x0, /* Endpoint 0 IN */
|
||||
LIBUSB_REQUEST_GET_DESCRIPTOR,
|
||||
(LIBUSB_DT_STRING << 8) | descriptor_index,
|
||||
lang_id,
|
||||
data,
|
||||
(uint16_t) length,
|
||||
1000);
|
||||
}
|
||||
#define libusb_get_string_descriptor SDL_libusb_get_string_descriptor
|
||||
#endif /* __FreeBSD__ */
|
||||
|
||||
#undef HIDAPI_H__
|
||||
#include "libusb/hid.c"
|
||||
|
||||
#undef hid_device_
|
||||
#undef hid_device
|
||||
#undef hid_device_info
|
||||
#undef hid_init
|
||||
#undef hid_exit
|
||||
#undef hid_enumerate
|
||||
#undef hid_free_enumeration
|
||||
#undef hid_open
|
||||
#undef hid_open_path
|
||||
#undef hid_write
|
||||
#undef hid_read_timeout
|
||||
#undef hid_read
|
||||
#undef hid_set_nonblocking
|
||||
#undef hid_send_feature_report
|
||||
#undef hid_get_feature_report
|
||||
#undef hid_close
|
||||
#undef hid_get_manufacturer_string
|
||||
#undef hid_get_product_string
|
||||
#undef hid_get_serial_number_string
|
||||
#undef hid_get_indexed_string
|
||||
#undef hid_error
|
||||
#undef new_hid_device
|
||||
#undef free_hid_device
|
||||
#undef input_report
|
||||
#undef return_data
|
||||
#undef make_path
|
||||
#undef read_thread
|
||||
|
||||
#endif /* SDL_LIBUSB_DYNAMIC */
|
||||
|
||||
/* Shared HIDAPI Implementation */
|
||||
|
||||
#undef HIDAPI_H__
|
||||
#include "hidapi.h"
|
||||
|
||||
struct hidapi_backend {
|
||||
#define F(x) typeof(x) *x
|
||||
F(hid_write);
|
||||
F(hid_read_timeout);
|
||||
F(hid_read);
|
||||
F(hid_set_nonblocking);
|
||||
F(hid_send_feature_report);
|
||||
F(hid_get_feature_report);
|
||||
F(hid_close);
|
||||
F(hid_get_manufacturer_string);
|
||||
F(hid_get_product_string);
|
||||
F(hid_get_serial_number_string);
|
||||
F(hid_get_indexed_string);
|
||||
F(hid_error);
|
||||
#undef F
|
||||
};
|
||||
|
||||
#if HAVE_PLATFORM_BACKEND
|
||||
static const struct hidapi_backend PLATFORM_Backend = {
|
||||
(void*)PLATFORM_hid_write,
|
||||
(void*)PLATFORM_hid_read_timeout,
|
||||
(void*)PLATFORM_hid_read,
|
||||
(void*)PLATFORM_hid_set_nonblocking,
|
||||
(void*)PLATFORM_hid_send_feature_report,
|
||||
(void*)PLATFORM_hid_get_feature_report,
|
||||
(void*)PLATFORM_hid_close,
|
||||
(void*)PLATFORM_hid_get_manufacturer_string,
|
||||
(void*)PLATFORM_hid_get_product_string,
|
||||
(void*)PLATFORM_hid_get_serial_number_string,
|
||||
(void*)PLATFORM_hid_get_indexed_string,
|
||||
(void*)PLATFORM_hid_error
|
||||
};
|
||||
#endif /* HAVE_PLATFORM_BACKEND */
|
||||
|
||||
#ifdef SDL_LIBUSB_DYNAMIC
|
||||
static const struct hidapi_backend LIBUSB_Backend = {
|
||||
(void*)LIBUSB_hid_write,
|
||||
(void*)LIBUSB_hid_read_timeout,
|
||||
(void*)LIBUSB_hid_read,
|
||||
(void*)LIBUSB_hid_set_nonblocking,
|
||||
(void*)LIBUSB_hid_send_feature_report,
|
||||
(void*)LIBUSB_hid_get_feature_report,
|
||||
(void*)LIBUSB_hid_close,
|
||||
(void*)LIBUSB_hid_get_manufacturer_string,
|
||||
(void*)LIBUSB_hid_get_product_string,
|
||||
(void*)LIBUSB_hid_get_serial_number_string,
|
||||
(void*)LIBUSB_hid_get_indexed_string,
|
||||
(void*)LIBUSB_hid_error
|
||||
};
|
||||
#endif /* SDL_LIBUSB_DYNAMIC */
|
||||
|
||||
typedef struct _HIDDeviceWrapper HIDDeviceWrapper;
|
||||
struct _HIDDeviceWrapper
|
||||
{
|
||||
hid_device *device; /* must be first field */
|
||||
const struct hidapi_backend *backend;
|
||||
};
|
||||
|
||||
static HIDDeviceWrapper *
|
||||
CreateHIDDeviceWrapper(hid_device *device, const struct hidapi_backend *backend)
|
||||
{
|
||||
HIDDeviceWrapper *ret = SDL_malloc(sizeof(*ret));
|
||||
ret->device = device;
|
||||
ret->backend = backend;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static hid_device *
|
||||
WrapHIDDevice(HIDDeviceWrapper *wrapper)
|
||||
{
|
||||
return (hid_device *)wrapper;
|
||||
}
|
||||
|
||||
static HIDDeviceWrapper *
|
||||
UnwrapHIDDevice(hid_device *device)
|
||||
{
|
||||
return (HIDDeviceWrapper *)device;
|
||||
}
|
||||
|
||||
static void
|
||||
DeleteHIDDeviceWrapper(HIDDeviceWrapper *device)
|
||||
{
|
||||
SDL_free(device);
|
||||
}
|
||||
|
||||
#define COPY_IF_EXISTS(var) \
|
||||
if (pSrc->var != NULL) { \
|
||||
pDst->var = SDL_strdup(pSrc->var); \
|
||||
} else { \
|
||||
pDst->var = NULL; \
|
||||
}
|
||||
#define WCOPY_IF_EXISTS(var) \
|
||||
if (pSrc->var != NULL) { \
|
||||
pDst->var = SDL_wcsdup(pSrc->var); \
|
||||
} else { \
|
||||
pDst->var = NULL; \
|
||||
}
|
||||
|
||||
#ifdef SDL_LIBUSB_DYNAMIC
|
||||
static void
|
||||
LIBUSB_CopyHIDDeviceInfo(struct LIBUSB_hid_device_info *pSrc,
|
||||
struct hid_device_info *pDst)
|
||||
{
|
||||
COPY_IF_EXISTS(path)
|
||||
pDst->vendor_id = pSrc->vendor_id;
|
||||
pDst->product_id = pSrc->product_id;
|
||||
WCOPY_IF_EXISTS(serial_number)
|
||||
pDst->release_number = pSrc->release_number;
|
||||
WCOPY_IF_EXISTS(manufacturer_string)
|
||||
WCOPY_IF_EXISTS(product_string)
|
||||
pDst->usage_page = pSrc->usage_page;
|
||||
pDst->usage = pSrc->usage;
|
||||
pDst->interface_number = pSrc->interface_number;
|
||||
pDst->interface_class = pSrc->interface_class;
|
||||
pDst->interface_subclass = pSrc->interface_subclass;
|
||||
pDst->interface_protocol = pSrc->interface_protocol;
|
||||
pDst->next = NULL;
|
||||
}
|
||||
#endif /* SDL_LIBUSB_DYNAMIC */
|
||||
|
||||
#if HAVE_PLATFORM_BACKEND
|
||||
static void
|
||||
PLATFORM_CopyHIDDeviceInfo(struct PLATFORM_hid_device_info *pSrc,
|
||||
struct hid_device_info *pDst)
|
||||
{
|
||||
COPY_IF_EXISTS(path)
|
||||
pDst->vendor_id = pSrc->vendor_id;
|
||||
pDst->product_id = pSrc->product_id;
|
||||
WCOPY_IF_EXISTS(serial_number)
|
||||
pDst->release_number = pSrc->release_number;
|
||||
WCOPY_IF_EXISTS(manufacturer_string)
|
||||
WCOPY_IF_EXISTS(product_string)
|
||||
pDst->usage_page = pSrc->usage_page;
|
||||
pDst->usage = pSrc->usage;
|
||||
pDst->interface_number = pSrc->interface_number;
|
||||
pDst->interface_class = pSrc->interface_class;
|
||||
pDst->interface_subclass = pSrc->interface_subclass;
|
||||
pDst->interface_protocol = pSrc->interface_protocol;
|
||||
pDst->next = NULL;
|
||||
}
|
||||
#endif /* HAVE_PLATFORM_BACKEND */
|
||||
|
||||
#undef COPY_IF_EXISTS
|
||||
#undef WCOPY_IF_EXISTS
|
||||
|
||||
static SDL_bool SDL_hidapi_wasinit = SDL_FALSE;
|
||||
|
||||
int HID_API_EXPORT HID_API_CALL hid_init(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (SDL_hidapi_wasinit == SDL_TRUE) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef SDL_LIBUSB_DYNAMIC
|
||||
libusb_ctx.libhandle = SDL_LoadObject(SDL_LIBUSB_DYNAMIC);
|
||||
if (libusb_ctx.libhandle != NULL) {
|
||||
#define LOAD_LIBUSB_SYMBOL(func) \
|
||||
libusb_ctx.func = SDL_LoadFunction(libusb_ctx.libhandle, "libusb_" #func);
|
||||
LOAD_LIBUSB_SYMBOL(init)
|
||||
LOAD_LIBUSB_SYMBOL(exit)
|
||||
LOAD_LIBUSB_SYMBOL(get_device_list)
|
||||
LOAD_LIBUSB_SYMBOL(free_device_list)
|
||||
LOAD_LIBUSB_SYMBOL(get_device_descriptor)
|
||||
LOAD_LIBUSB_SYMBOL(get_active_config_descriptor)
|
||||
LOAD_LIBUSB_SYMBOL(get_config_descriptor)
|
||||
LOAD_LIBUSB_SYMBOL(free_config_descriptor)
|
||||
LOAD_LIBUSB_SYMBOL(get_bus_number)
|
||||
LOAD_LIBUSB_SYMBOL(get_device_address)
|
||||
LOAD_LIBUSB_SYMBOL(open)
|
||||
LOAD_LIBUSB_SYMBOL(close)
|
||||
LOAD_LIBUSB_SYMBOL(claim_interface)
|
||||
LOAD_LIBUSB_SYMBOL(release_interface)
|
||||
LOAD_LIBUSB_SYMBOL(kernel_driver_active)
|
||||
LOAD_LIBUSB_SYMBOL(detach_kernel_driver)
|
||||
LOAD_LIBUSB_SYMBOL(attach_kernel_driver)
|
||||
LOAD_LIBUSB_SYMBOL(set_interface_alt_setting)
|
||||
LOAD_LIBUSB_SYMBOL(alloc_transfer)
|
||||
LOAD_LIBUSB_SYMBOL(submit_transfer)
|
||||
LOAD_LIBUSB_SYMBOL(cancel_transfer)
|
||||
LOAD_LIBUSB_SYMBOL(free_transfer)
|
||||
LOAD_LIBUSB_SYMBOL(control_transfer)
|
||||
LOAD_LIBUSB_SYMBOL(interrupt_transfer)
|
||||
LOAD_LIBUSB_SYMBOL(handle_events)
|
||||
LOAD_LIBUSB_SYMBOL(handle_events_completed)
|
||||
#undef LOAD_LIBUSB_SYMBOL
|
||||
|
||||
if ((err = LIBUSB_hid_init()) < 0) {
|
||||
SDL_UnloadObject(libusb_ctx.libhandle);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
#endif /* SDL_LIBUSB_DYNAMIC */
|
||||
|
||||
#if HAVE_PLATFORM_BACKEND
|
||||
#if __LINUX__
|
||||
udev_ctx = SDL_UDEV_GetUdevSyms();
|
||||
#endif /* __LINUX __ */
|
||||
if (udev_ctx && (err = PLATFORM_hid_init()) < 0) {
|
||||
#ifdef SDL_LIBUSB_DYNAMIC
|
||||
if (libusb_ctx.libhandle) {
|
||||
SDL_UnloadObject(libusb_ctx.libhandle);
|
||||
}
|
||||
#endif /* SDL_LIBUSB_DYNAMIC */
|
||||
return err;
|
||||
}
|
||||
#endif /* HAVE_PLATFORM_BACKEND */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int HID_API_EXPORT HID_API_CALL hid_exit(void)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
if (SDL_hidapi_wasinit == SDL_FALSE) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if HAVE_PLATFORM_BACKEND
|
||||
if (udev_ctx) {
|
||||
err = PLATFORM_hid_exit();
|
||||
}
|
||||
#endif /* HAVE_PLATFORM_BACKEND */
|
||||
#ifdef SDL_LIBUSB_DYNAMIC
|
||||
if (libusb_ctx.libhandle) {
|
||||
err |= LIBUSB_hid_exit(); /* Ehhhhh */
|
||||
SDL_UnloadObject(libusb_ctx.libhandle);
|
||||
}
|
||||
#endif /* SDL_LIBUSB_DYNAMIC */
|
||||
return err;
|
||||
}
|
||||
|
||||
struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id)
|
||||
{
|
||||
#ifdef SDL_LIBUSB_DYNAMIC
|
||||
struct LIBUSB_hid_device_info *usb_devs = NULL;
|
||||
struct LIBUSB_hid_device_info *usb_dev;
|
||||
#endif
|
||||
#if HAVE_PLATFORM_BACKEND
|
||||
struct PLATFORM_hid_device_info *raw_devs = NULL;
|
||||
struct PLATFORM_hid_device_info *raw_dev;
|
||||
#endif
|
||||
struct hid_device_info *devs = NULL, *last = NULL, *new_dev;
|
||||
|
||||
if (SDL_hidapi_wasinit == SDL_FALSE) {
|
||||
hid_init();
|
||||
}
|
||||
|
||||
#ifdef SDL_LIBUSB_DYNAMIC
|
||||
if (libusb_ctx.libhandle) {
|
||||
usb_devs = LIBUSB_hid_enumerate(vendor_id, product_id);
|
||||
for (usb_dev = usb_devs; usb_dev; usb_dev = usb_dev->next) {
|
||||
new_dev = (struct hid_device_info*) SDL_malloc(sizeof(struct hid_device_info));
|
||||
LIBUSB_CopyHIDDeviceInfo(usb_dev, new_dev);
|
||||
|
||||
if (last != NULL) {
|
||||
last->next = new_dev;
|
||||
} else {
|
||||
devs = new_dev;
|
||||
}
|
||||
last = new_dev;
|
||||
}
|
||||
}
|
||||
#endif /* SDL_LIBUSB_DYNAMIC */
|
||||
|
||||
#if HAVE_PLATFORM_BACKEND
|
||||
if (udev_ctx) {
|
||||
raw_devs = PLATFORM_hid_enumerate(vendor_id, product_id);
|
||||
for (raw_dev = raw_devs; raw_dev; raw_dev = raw_dev->next) {
|
||||
SDL_bool bFound = SDL_FALSE;
|
||||
#ifdef SDL_LIBUSB_DYNAMIC
|
||||
for (usb_dev = usb_devs; usb_dev; usb_dev = usb_dev->next) {
|
||||
if (raw_dev->vendor_id == usb_dev->vendor_id &&
|
||||
raw_dev->product_id == usb_dev->product_id &&
|
||||
(raw_dev->interface_number < 0 || raw_dev->interface_number == usb_dev->interface_number)) {
|
||||
bFound = SDL_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (!bFound) {
|
||||
new_dev = (struct hid_device_info*) SDL_malloc(sizeof(struct hid_device_info));
|
||||
PLATFORM_CopyHIDDeviceInfo(raw_dev, new_dev);
|
||||
new_dev->next = NULL;
|
||||
|
||||
if (last != NULL) {
|
||||
last->next = new_dev;
|
||||
} else {
|
||||
devs = new_dev;
|
||||
}
|
||||
last = new_dev;
|
||||
}
|
||||
}
|
||||
PLATFORM_hid_free_enumeration(raw_devs);
|
||||
}
|
||||
#endif /* HAVE_PLATFORM_BACKEND */
|
||||
|
||||
#ifdef SDL_LIBUSB_DYNAMIC
|
||||
if (libusb_ctx.libhandle) {
|
||||
LIBUSB_hid_free_enumeration(usb_devs);
|
||||
}
|
||||
#endif
|
||||
return devs;
|
||||
}
|
||||
|
||||
void HID_API_EXPORT HID_API_CALL hid_free_enumeration(struct hid_device_info *devs)
|
||||
{
|
||||
while (devs) {
|
||||
struct hid_device_info *next = devs->next;
|
||||
SDL_free(devs->path);
|
||||
SDL_free(devs->serial_number);
|
||||
SDL_free(devs->manufacturer_string);
|
||||
SDL_free(devs->product_string);
|
||||
SDL_free(devs);
|
||||
devs = next;
|
||||
}
|
||||
}
|
||||
|
||||
HID_API_EXPORT hid_device * HID_API_CALL hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number)
|
||||
{
|
||||
hid_device *pDevice = NULL;
|
||||
|
||||
if (SDL_hidapi_wasinit == SDL_FALSE) {
|
||||
hid_init();
|
||||
}
|
||||
|
||||
#if HAVE_PLATFORM_BACKEND
|
||||
if (udev_ctx &&
|
||||
(pDevice = (hid_device*) PLATFORM_hid_open(vendor_id, product_id, serial_number)) != NULL) {
|
||||
|
||||
HIDDeviceWrapper *wrapper = CreateHIDDeviceWrapper(pDevice, &PLATFORM_Backend);
|
||||
return WrapHIDDevice(wrapper);
|
||||
}
|
||||
#endif /* HAVE_PLATFORM_BACKEND */
|
||||
#ifdef SDL_LIBUSB_DYNAMIC
|
||||
if (libusb_ctx.libhandle &&
|
||||
(pDevice = (hid_device*) LIBUSB_hid_open(vendor_id, product_id, serial_number)) != NULL) {
|
||||
|
||||
HIDDeviceWrapper *wrapper = CreateHIDDeviceWrapper(pDevice, &LIBUSB_Backend);
|
||||
return WrapHIDDevice(wrapper);
|
||||
}
|
||||
#endif /* SDL_LIBUSB_DYNAMIC */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path, int bExclusive /* = false */)
|
||||
{
|
||||
hid_device *pDevice = NULL;
|
||||
|
||||
if (SDL_hidapi_wasinit == SDL_FALSE) {
|
||||
hid_init();
|
||||
}
|
||||
|
||||
#if HAVE_PLATFORM_BACKEND
|
||||
if (udev_ctx &&
|
||||
(pDevice = (hid_device*) PLATFORM_hid_open_path(path, bExclusive)) != NULL) {
|
||||
|
||||
HIDDeviceWrapper *wrapper = CreateHIDDeviceWrapper(pDevice, &PLATFORM_Backend);
|
||||
return WrapHIDDevice(wrapper);
|
||||
}
|
||||
#endif /* HAVE_PLATFORM_BACKEND */
|
||||
#ifdef SDL_LIBUSB_DYNAMIC
|
||||
if (libusb_ctx.libhandle &&
|
||||
(pDevice = (hid_device*) LIBUSB_hid_open_path(path, bExclusive)) != NULL) {
|
||||
|
||||
HIDDeviceWrapper *wrapper = CreateHIDDeviceWrapper(pDevice, &LIBUSB_Backend);
|
||||
return WrapHIDDevice(wrapper);
|
||||
}
|
||||
#endif /* SDL_LIBUSB_DYNAMIC */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int HID_API_EXPORT HID_API_CALL hid_write(hid_device *device, const unsigned char *data, size_t length)
|
||||
{
|
||||
HIDDeviceWrapper *wrapper = UnwrapHIDDevice(device);
|
||||
return wrapper->backend->hid_write(wrapper->device, data, length);
|
||||
}
|
||||
|
||||
int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *device, unsigned char *data, size_t length, int milliseconds)
|
||||
{
|
||||
HIDDeviceWrapper *wrapper = UnwrapHIDDevice(device);
|
||||
return wrapper->backend->hid_read_timeout(wrapper->device, data, length, milliseconds);
|
||||
}
|
||||
|
||||
int HID_API_EXPORT HID_API_CALL hid_read(hid_device *device, unsigned char *data, size_t length)
|
||||
{
|
||||
HIDDeviceWrapper *wrapper = UnwrapHIDDevice(device);
|
||||
return wrapper->backend->hid_read(wrapper->device, data, length);
|
||||
}
|
||||
|
||||
int HID_API_EXPORT HID_API_CALL hid_set_nonblocking(hid_device *device, int nonblock)
|
||||
{
|
||||
HIDDeviceWrapper *wrapper = UnwrapHIDDevice(device);
|
||||
return wrapper->backend->hid_set_nonblocking(wrapper->device, nonblock);
|
||||
}
|
||||
|
||||
int HID_API_EXPORT HID_API_CALL hid_send_feature_report(hid_device *device, const unsigned char *data, size_t length)
|
||||
{
|
||||
HIDDeviceWrapper *wrapper = UnwrapHIDDevice(device);
|
||||
return wrapper->backend->hid_send_feature_report(wrapper->device, data, length);
|
||||
}
|
||||
|
||||
int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *device, unsigned char *data, size_t length)
|
||||
{
|
||||
HIDDeviceWrapper *wrapper = UnwrapHIDDevice(device);
|
||||
return wrapper->backend->hid_get_feature_report(wrapper->device, data, length);
|
||||
}
|
||||
|
||||
void HID_API_EXPORT HID_API_CALL hid_close(hid_device *device)
|
||||
{
|
||||
HIDDeviceWrapper *wrapper = UnwrapHIDDevice(device);
|
||||
wrapper->backend->hid_close(wrapper->device);
|
||||
DeleteHIDDeviceWrapper(wrapper);
|
||||
}
|
||||
|
||||
int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *device, wchar_t *string, size_t maxlen)
|
||||
{
|
||||
HIDDeviceWrapper *wrapper = UnwrapHIDDevice(device);
|
||||
return wrapper->backend->hid_get_manufacturer_string(wrapper->device, string, maxlen);
|
||||
}
|
||||
|
||||
int HID_API_EXPORT_CALL hid_get_product_string(hid_device *device, wchar_t *string, size_t maxlen)
|
||||
{
|
||||
HIDDeviceWrapper *wrapper = UnwrapHIDDevice(device);
|
||||
return wrapper->backend->hid_get_product_string(wrapper->device, string, maxlen);
|
||||
}
|
||||
|
||||
int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *device, wchar_t *string, size_t maxlen)
|
||||
{
|
||||
HIDDeviceWrapper *wrapper = UnwrapHIDDevice(device);
|
||||
return wrapper->backend->hid_get_serial_number_string(wrapper->device, string, maxlen);
|
||||
}
|
||||
|
||||
int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *device, int string_index, wchar_t *string, size_t maxlen)
|
||||
{
|
||||
HIDDeviceWrapper *wrapper = UnwrapHIDDevice(device);
|
||||
return wrapper->backend->hid_get_indexed_string(wrapper->device, string_index, string, maxlen);
|
||||
}
|
||||
|
||||
HID_API_EXPORT const wchar_t* HID_API_CALL hid_error(hid_device *device)
|
||||
{
|
||||
HIDDeviceWrapper *wrapper = UnwrapHIDDevice(device);
|
||||
return wrapper->backend->hid_error(wrapper->device);
|
||||
}
|
||||
|
||||
#endif /* SDL_JOYSTICK_HIDAPI */
|
||||
|
||||
/* vi: set sts=4 ts=4 sw=4 expandtab: */
|
||||
|
|
@ -739,7 +739,7 @@ extern "C"
|
|||
JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceReleaseCallback)(JNIEnv *env, jobject thiz);
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceConnected)(JNIEnv *env, jobject thiz, int nDeviceID, jstring sIdentifier, int nVendorId, int nProductId, jstring sSerialNumber, int nReleaseNumber, jstring sManufacturer, jstring sProduct, int nInterface );
|
||||
JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceConnected)(JNIEnv *env, jobject thiz, int nDeviceID, jstring sIdentifier, int nVendorId, int nProductId, jstring sSerialNumber, int nReleaseNumber, jstring sManufacturer, jstring sProduct, int nInterface, int nInterfaceClass, int nInterfaceSubclass, int nInterfaceProtocol );
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceOpenPending)(JNIEnv *env, jobject thiz, int nDeviceID);
|
||||
|
|
@ -828,7 +828,7 @@ JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceReleaseCallbac
|
|||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceConnected)(JNIEnv *env, jobject thiz, int nDeviceID, jstring sIdentifier, int nVendorId, int nProductId, jstring sSerialNumber, int nReleaseNumber, jstring sManufacturer, jstring sProduct, int nInterface )
|
||||
JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceConnected)(JNIEnv *env, jobject thiz, int nDeviceID, jstring sIdentifier, int nVendorId, int nProductId, jstring sSerialNumber, int nReleaseNumber, jstring sManufacturer, jstring sProduct, int nInterface, int nInterfaceClass, int nInterfaceSubclass, int nInterfaceProtocol )
|
||||
{
|
||||
LOGV( "HIDDeviceConnected() id=%d VID/PID = %.4x/%.4x, interface %d\n", nDeviceID, nVendorId, nProductId, nInterface );
|
||||
|
||||
|
|
@ -842,6 +842,9 @@ JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceConnected)(JNI
|
|||
pInfo->manufacturer_string = CreateWStringFromJString( env, sManufacturer );
|
||||
pInfo->product_string = CreateWStringFromJString( env, sProduct );
|
||||
pInfo->interface_number = nInterface;
|
||||
pInfo->interface_class = nInterfaceClass;
|
||||
pInfo->interface_subclass = nInterfaceSubclass;
|
||||
pInfo->interface_protocol = nInterfaceProtocol;
|
||||
|
||||
hid_device_ref<CHIDDevice> pDevice( new CHIDDevice( nDeviceID, pInfo ) );
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
files located at the root of the source distribution.
|
||||
These files may also be found in the public source
|
||||
code repository located at:
|
||||
http://github.com/signal11/hidapi .
|
||||
https://github.com/libusb/hidapi .
|
||||
********************************************************/
|
||||
|
||||
/** @file
|
||||
|
|
@ -33,9 +33,13 @@
|
|||
#define HID_API_EXPORT __declspec(dllexport)
|
||||
#define HID_API_CALL
|
||||
#else
|
||||
#ifndef HID_API_EXPORT
|
||||
#define HID_API_EXPORT /**< API export macro */
|
||||
#endif
|
||||
#ifndef HID_API_CALL
|
||||
#define HID_API_CALL /**< API call macro */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define HID_API_EXPORT_CALL HID_API_EXPORT HID_API_CALL /**< API export and call macro*/
|
||||
|
||||
|
|
@ -78,6 +82,12 @@ namespace NAMESPACE {
|
|||
only if the device contains more than one interface. */
|
||||
int interface_number;
|
||||
|
||||
/** Additional information about the USB interface.
|
||||
Valid on libusb and Android implementations. */
|
||||
int interface_class;
|
||||
int interface_subclass;
|
||||
int interface_protocol;
|
||||
|
||||
/** Pointer to the next device */
|
||||
struct hid_device_info *next;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -282,6 +282,7 @@ typedef enum
|
|||
NSLog( @"connected peripheral: %@", peripheral );
|
||||
if ( [peripheral.name isEqualToString:@"SteamController"] )
|
||||
{
|
||||
self.nPendingPairs += 1;
|
||||
HIDBLEDevice *steamController = [[HIDBLEDevice alloc] initWithPeripheral:peripheral];
|
||||
[self.deviceMap setObject:steamController forKey:peripheral];
|
||||
[self.centralManager connectPeripheral:peripheral options:nil];
|
||||
|
|
|
|||
|
|
@ -20,39 +20,21 @@
|
|||
files located at the root of the source distribution.
|
||||
These files may also be found in the public source
|
||||
code repository located at:
|
||||
http://github.com/signal11/hidapi .
|
||||
https://github.com/libusb/hidapi .
|
||||
********************************************************/
|
||||
|
||||
/* This file is heavily modified from the original libusb.c, for portability.
|
||||
* Last upstream update was from July 25, 2019, Git commit 93dca807.
|
||||
*/
|
||||
|
||||
#include "../../SDL_internal.h"
|
||||
#include "SDL_thread.h"
|
||||
#include "SDL_mutex.h"
|
||||
|
||||
#ifdef SDL_JOYSTICK_HIDAPI
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE /* needed for wcsdup() before glibc 2.10 */
|
||||
#endif
|
||||
|
||||
/* C */
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <locale.h>
|
||||
#include <errno.h>
|
||||
|
||||
/* Unix */
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <fcntl.h>
|
||||
#include <pthread.h>
|
||||
#include <wchar.h>
|
||||
|
||||
/* GNU / LibUSB */
|
||||
#include <libusb.h>
|
||||
#ifndef __ANDROID__
|
||||
#include <iconv.h>
|
||||
#endif
|
||||
#include <locale.h> /* setlocale */
|
||||
|
||||
#include "hidapi.h"
|
||||
|
||||
|
|
@ -61,67 +43,63 @@ namespace NAMESPACE
|
|||
{
|
||||
#endif
|
||||
|
||||
#ifdef __ANDROID__
|
||||
|
||||
/* Barrier implementation because Android/Bionic don't have pthread_barrier.
|
||||
This implementation came from Brent Priddy and was posted on
|
||||
StackOverflow. It is used with his permission. */
|
||||
typedef int pthread_barrierattr_t;
|
||||
typedef struct pthread_barrier {
|
||||
pthread_mutex_t mutex;
|
||||
pthread_cond_t cond;
|
||||
int count;
|
||||
int trip_count;
|
||||
} pthread_barrier_t;
|
||||
|
||||
static int pthread_barrier_init(pthread_barrier_t *barrier, const pthread_barrierattr_t *attr, unsigned int count)
|
||||
typedef struct _SDL_ThreadBarrier
|
||||
{
|
||||
if(count == 0) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
SDL_mutex *mutex;
|
||||
SDL_cond *cond;
|
||||
Uint32 count;
|
||||
Uint32 trip_count;
|
||||
} SDL_ThreadBarrier;
|
||||
|
||||
static int SDL_CreateThreadBarrier(SDL_ThreadBarrier *barrier, Uint32 count)
|
||||
{
|
||||
if (barrier == NULL) {
|
||||
return SDL_SetError("barrier must be non-NULL");
|
||||
}
|
||||
if (count == 0) {
|
||||
return SDL_SetError("count must be > 0");
|
||||
}
|
||||
|
||||
if(pthread_mutex_init(&barrier->mutex, 0) < 0) {
|
||||
return -1;
|
||||
barrier->mutex = SDL_CreateMutex();
|
||||
if (barrier->mutex == NULL) {
|
||||
return -1; /* Error set by CreateMutex */
|
||||
}
|
||||
if(pthread_cond_init(&barrier->cond, 0) < 0) {
|
||||
pthread_mutex_destroy(&barrier->mutex);
|
||||
return -1;
|
||||
barrier->cond = SDL_CreateCond();
|
||||
if (barrier->cond == NULL) {
|
||||
return -1; /* Error set by CreateCond */
|
||||
}
|
||||
|
||||
barrier->trip_count = count;
|
||||
barrier->count = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pthread_barrier_destroy(pthread_barrier_t *barrier)
|
||||
static void SDL_DestroyThreadBarrier(SDL_ThreadBarrier *barrier)
|
||||
{
|
||||
pthread_cond_destroy(&barrier->cond);
|
||||
pthread_mutex_destroy(&barrier->mutex);
|
||||
return 0;
|
||||
SDL_DestroyCond(barrier->cond);
|
||||
SDL_DestroyMutex(barrier->mutex);
|
||||
}
|
||||
|
||||
static int pthread_barrier_wait(pthread_barrier_t *barrier)
|
||||
static int SDL_WaitThreadBarrier(SDL_ThreadBarrier *barrier)
|
||||
{
|
||||
pthread_mutex_lock(&barrier->mutex);
|
||||
++(barrier->count);
|
||||
if(barrier->count >= barrier->trip_count)
|
||||
{
|
||||
SDL_LockMutex(barrier->mutex);
|
||||
barrier->count += 1;
|
||||
if (barrier->count >= barrier->trip_count) {
|
||||
barrier->count = 0;
|
||||
pthread_cond_broadcast(&barrier->cond);
|
||||
pthread_mutex_unlock(&barrier->mutex);
|
||||
SDL_CondBroadcast(barrier->cond);
|
||||
SDL_UnlockMutex(barrier->mutex);
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
pthread_cond_wait(&barrier->cond, &(barrier->mutex));
|
||||
pthread_mutex_unlock(&barrier->mutex);
|
||||
return 0;
|
||||
}
|
||||
SDL_CondWait(barrier->cond, barrier->mutex);
|
||||
SDL_UnlockMutex(barrier->mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus) && !defined(NAMESPACE)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
|
@ -163,6 +141,7 @@ struct hid_device_ {
|
|||
|
||||
/* The interface number of the HID */
|
||||
int interface;
|
||||
int detached_driver;
|
||||
|
||||
/* Indexes of Strings */
|
||||
int manufacturer_index;
|
||||
|
|
@ -173,10 +152,10 @@ struct hid_device_ {
|
|||
int blocking; /* boolean */
|
||||
|
||||
/* Read thread objects */
|
||||
pthread_t thread;
|
||||
pthread_mutex_t mutex; /* Protects input_reports */
|
||||
pthread_cond_t condition;
|
||||
pthread_barrier_t barrier; /* Ensures correct startup sequence */
|
||||
SDL_Thread *thread;
|
||||
SDL_mutex *mutex; /* Protects input_reports */
|
||||
SDL_cond *condition;
|
||||
SDL_ThreadBarrier barrier; /* Ensures correct startup sequence */
|
||||
int shutdown_thread;
|
||||
int cancelled;
|
||||
struct libusb_transfer *transfer;
|
||||
|
|
@ -192,12 +171,12 @@ static int return_data(hid_device *dev, unsigned char *data, size_t length);
|
|||
|
||||
static hid_device *new_hid_device(void)
|
||||
{
|
||||
hid_device *dev = (hid_device *)calloc(1, sizeof(hid_device));
|
||||
hid_device *dev = (hid_device*) calloc(1, sizeof(hid_device));
|
||||
dev->blocking = 1;
|
||||
|
||||
pthread_mutex_init(&dev->mutex, NULL);
|
||||
pthread_cond_init(&dev->condition, NULL);
|
||||
pthread_barrier_init(&dev->barrier, NULL, 2);
|
||||
dev->mutex = SDL_CreateMutex();
|
||||
dev->condition = SDL_CreateCond();
|
||||
SDL_CreateThreadBarrier(&dev->barrier, 2);
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
|
@ -205,17 +184,17 @@ static hid_device *new_hid_device(void)
|
|||
static void free_hid_device(hid_device *dev)
|
||||
{
|
||||
/* Clean up the thread objects */
|
||||
pthread_barrier_destroy(&dev->barrier);
|
||||
pthread_cond_destroy(&dev->condition);
|
||||
pthread_mutex_destroy(&dev->mutex);
|
||||
SDL_DestroyThreadBarrier(&dev->barrier);
|
||||
SDL_DestroyCond(dev->condition);
|
||||
SDL_DestroyMutex(dev->mutex);
|
||||
|
||||
/* Free the device itself */
|
||||
free(dev);
|
||||
}
|
||||
|
||||
#if 0
|
||||
/*TODO: Implement this funciton on hidapi/libusb.. */
|
||||
static void register_error(hid_device *device, const char *op)
|
||||
/*TODO: Implement this function on hidapi/libusb.. */
|
||||
static void register_error(hid_device *dev, const char *op)
|
||||
{
|
||||
|
||||
}
|
||||
|
|
@ -400,20 +379,13 @@ static wchar_t *get_usb_string(libusb_device_handle *dev, uint8_t idx)
|
|||
int len;
|
||||
wchar_t *str = NULL;
|
||||
|
||||
#ifndef __ANDROID__ /* we don't use iconv on Android */
|
||||
wchar_t wbuf[256];
|
||||
/* iconv variables */
|
||||
iconv_t ic;
|
||||
SDL_iconv_t ic;
|
||||
size_t inbytes;
|
||||
size_t outbytes;
|
||||
size_t res;
|
||||
#ifdef __FreeBSD__
|
||||
const char *inptr;
|
||||
#else
|
||||
char *inptr;
|
||||
#endif
|
||||
char *outptr;
|
||||
#endif
|
||||
|
||||
/* Determine which language to use. */
|
||||
uint16_t lang;
|
||||
|
|
@ -430,32 +402,13 @@ static wchar_t *get_usb_string(libusb_device_handle *dev, uint8_t idx)
|
|||
if (len < 0)
|
||||
return NULL;
|
||||
|
||||
#ifdef __ANDROID__
|
||||
|
||||
/* Bionic does not have iconv support nor wcsdup() function, so it
|
||||
has to be done manually. The following code will only work for
|
||||
code points that can be represented as a single UTF-16 character,
|
||||
and will incorrectly convert any code points which require more
|
||||
than one UTF-16 character.
|
||||
|
||||
Skip over the first character (2-bytes). */
|
||||
len -= 2;
|
||||
str = malloc((len / 2 + 1) * sizeof(wchar_t));
|
||||
int i;
|
||||
for (i = 0; i < len / 2; i++) {
|
||||
str[i] = buf[i * 2 + 2] | (buf[i * 2 + 3] << 8);
|
||||
}
|
||||
str[len / 2] = 0x00000000;
|
||||
|
||||
#else
|
||||
|
||||
/* buf does not need to be explicitly NULL-terminated because
|
||||
it is only passed into iconv() which does not need it. */
|
||||
|
||||
/* Initialize iconv. */
|
||||
ic = iconv_open("WCHAR_T", "UTF-16LE");
|
||||
if (ic == (iconv_t)-1) {
|
||||
LOG("iconv_open() failed\n");
|
||||
ic = SDL_iconv_open("WCHAR_T", "UTF-16LE");
|
||||
if (ic == (SDL_iconv_t)-1) {
|
||||
LOG("SDL_iconv_open() failed\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -465,9 +418,9 @@ static wchar_t *get_usb_string(libusb_device_handle *dev, uint8_t idx)
|
|||
inbytes = len-2;
|
||||
outptr = (char*) wbuf;
|
||||
outbytes = sizeof(wbuf);
|
||||
res = iconv(ic, &inptr, &inbytes, &outptr, &outbytes);
|
||||
res = SDL_iconv(ic, &inptr, &inbytes, &outptr, &outbytes);
|
||||
if (res == (size_t)-1) {
|
||||
LOG("iconv() failed\n");
|
||||
LOG("SDL_iconv() failed\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
|
|
@ -480,9 +433,7 @@ static wchar_t *get_usb_string(libusb_device_handle *dev, uint8_t idx)
|
|||
str = wcsdup(wbuf);
|
||||
|
||||
err:
|
||||
iconv_close(ic);
|
||||
|
||||
#endif
|
||||
SDL_iconv_close(ic);
|
||||
|
||||
return str;
|
||||
}
|
||||
|
|
@ -531,7 +482,8 @@ int HID_API_EXPORT hid_exit(void)
|
|||
static int is_xbox360(unsigned short vendor_id, const struct libusb_interface_descriptor *intf_desc)
|
||||
{
|
||||
static const int XB360_IFACE_SUBCLASS = 93;
|
||||
static const int XB360_IFACE_PROTOCOL = 1; /* Wired only */
|
||||
static const int XB360_IFACE_PROTOCOL = 1; /* Wired */
|
||||
static const int XB360W_IFACE_PROTOCOL = 129; /* Wireless */
|
||||
static const int SUPPORTED_VENDORS[] = {
|
||||
0x0079, /* GPD Win 2 */
|
||||
0x044f, /* Thrustmaster */
|
||||
|
|
@ -541,8 +493,9 @@ static int is_xbox360(unsigned short vendor_id, const struct libusb_interface_de
|
|||
0x06a3, /* Saitek */
|
||||
0x0738, /* Mad Catz */
|
||||
0x07ff, /* Mad Catz */
|
||||
0x0e6f, /* Unknown */
|
||||
0x0e6f, /* PDP */
|
||||
0x0f0d, /* Hori */
|
||||
0x1038, /* SteelSeries */
|
||||
0x11c9, /* Nacon */
|
||||
0x12ab, /* Unknown */
|
||||
0x1430, /* RedOctane */
|
||||
|
|
@ -555,10 +508,10 @@ static int is_xbox360(unsigned short vendor_id, const struct libusb_interface_de
|
|||
0x24c6, /* PowerA */
|
||||
};
|
||||
|
||||
if (intf_desc->bInterfaceNumber == 0 &&
|
||||
intf_desc->bInterfaceClass == LIBUSB_CLASS_VENDOR_SPEC &&
|
||||
if (intf_desc->bInterfaceClass == LIBUSB_CLASS_VENDOR_SPEC &&
|
||||
intf_desc->bInterfaceSubClass == XB360_IFACE_SUBCLASS &&
|
||||
intf_desc->bInterfaceProtocol == XB360_IFACE_PROTOCOL) {
|
||||
(intf_desc->bInterfaceProtocol == XB360_IFACE_PROTOCOL ||
|
||||
intf_desc->bInterfaceProtocol == XB360W_IFACE_PROTOCOL)) {
|
||||
int i;
|
||||
for (i = 0; i < sizeof(SUPPORTED_VENDORS)/sizeof(SUPPORTED_VENDORS[0]); ++i) {
|
||||
if (vendor_id == SUPPORTED_VENDORS[i]) {
|
||||
|
|
@ -576,10 +529,11 @@ static int is_xboxone(unsigned short vendor_id, const struct libusb_interface_de
|
|||
static const int SUPPORTED_VENDORS[] = {
|
||||
0x045e, /* Microsoft */
|
||||
0x0738, /* Mad Catz */
|
||||
0x0e6f, /* Unknown */
|
||||
0x0e6f, /* PDP */
|
||||
0x0f0d, /* Hori */
|
||||
0x1532, /* Razer Wildcat */
|
||||
0x24c6, /* PowerA */
|
||||
0x2e24, /* Hyperkin */
|
||||
};
|
||||
|
||||
if (intf_desc->bInterfaceNumber == 0 &&
|
||||
|
|
@ -603,13 +557,7 @@ static int should_enumerate_interface(unsigned short vendor_id, const struct lib
|
|||
|
||||
/* Also enumerate Xbox 360 controllers */
|
||||
if (is_xbox360(vendor_id, intf_desc))
|
||||
{
|
||||
/* hid_write() to Xbox 360 controllers doesn't seem to work on Linux:
|
||||
- xpad 1-2:1.0: xpad_try_sending_next_out_packet - usb_submit_urb failed with result -2
|
||||
Xbox 360 controller support is good on Linux anyway, so we'll ignore this for now.
|
||||
return 1;
|
||||
*/
|
||||
}
|
||||
|
||||
/* Also enumerate Xbox One controllers */
|
||||
if (is_xboxone(vendor_id, intf_desc))
|
||||
|
|
@ -660,25 +608,25 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id,
|
|||
/* Check the VID/PID against the arguments */
|
||||
if ((vendor_id == 0x0 || vendor_id == dev_vid) &&
|
||||
(product_id == 0x0 || product_id == dev_pid)) {
|
||||
struct hid_device_info *tmp;
|
||||
|
||||
/* VID/PID match. Create the record. */
|
||||
tmp = (struct hid_device_info *)calloc(1, sizeof(struct hid_device_info));
|
||||
if (cur_dev) {
|
||||
cur_dev->next = tmp;
|
||||
}
|
||||
else {
|
||||
root = tmp;
|
||||
}
|
||||
cur_dev = tmp;
|
||||
|
||||
/* Fill out the record */
|
||||
cur_dev->next = NULL;
|
||||
cur_dev->path = make_path(dev, interface_num);
|
||||
|
||||
res = libusb_open(dev, &handle);
|
||||
|
||||
if (res >= 0) {
|
||||
struct hid_device_info *tmp;
|
||||
|
||||
/* VID/PID match. Create the record. */
|
||||
tmp = (struct hid_device_info*) calloc(1, sizeof(struct hid_device_info));
|
||||
if (cur_dev) {
|
||||
cur_dev->next = tmp;
|
||||
}
|
||||
else {
|
||||
root = tmp;
|
||||
}
|
||||
cur_dev = tmp;
|
||||
|
||||
/* Fill out the record */
|
||||
cur_dev->next = NULL;
|
||||
cur_dev->path = make_path(dev, interface_num);
|
||||
|
||||
/* Serial Number */
|
||||
if (desc.iSerialNumber > 0)
|
||||
cur_dev->serial_number =
|
||||
|
|
@ -756,16 +704,22 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id,
|
|||
#endif /* INVASIVE_GET_USAGE */
|
||||
|
||||
libusb_close(handle);
|
||||
}
|
||||
/* VID/PID */
|
||||
cur_dev->vendor_id = dev_vid;
|
||||
cur_dev->product_id = dev_pid;
|
||||
|
||||
/* Release Number */
|
||||
cur_dev->release_number = desc.bcdDevice;
|
||||
/* VID/PID */
|
||||
cur_dev->vendor_id = dev_vid;
|
||||
cur_dev->product_id = dev_pid;
|
||||
|
||||
/* Interface Number */
|
||||
cur_dev->interface_number = interface_num;
|
||||
/* Release Number */
|
||||
cur_dev->release_number = desc.bcdDevice;
|
||||
|
||||
/* Interface Number */
|
||||
cur_dev->interface_number = interface_num;
|
||||
cur_dev->interface_class = intf_desc->bInterfaceClass;
|
||||
cur_dev->interface_subclass = intf_desc->bInterfaceSubClass;
|
||||
cur_dev->interface_protocol = intf_desc->bInterfaceProtocol;
|
||||
|
||||
} else
|
||||
LOG("Can't open device 0x%.4x/0x%.4x during enumeration: %d\n", dev_vid, dev_pid, res);
|
||||
}
|
||||
}
|
||||
} /* altsettings */
|
||||
|
|
@ -836,19 +790,19 @@ static void read_callback(struct libusb_transfer *transfer)
|
|||
|
||||
if (transfer->status == LIBUSB_TRANSFER_COMPLETED) {
|
||||
|
||||
struct input_report *rpt = (struct input_report *)malloc(sizeof(*rpt));
|
||||
rpt->data = (uint8_t *)malloc(transfer->actual_length);
|
||||
struct input_report *rpt = (struct input_report*) malloc(sizeof(*rpt));
|
||||
rpt->data = (uint8_t*) malloc(transfer->actual_length);
|
||||
memcpy(rpt->data, transfer->buffer, transfer->actual_length);
|
||||
rpt->len = transfer->actual_length;
|
||||
rpt->next = NULL;
|
||||
|
||||
pthread_mutex_lock(&dev->mutex);
|
||||
SDL_LockMutex(dev->mutex);
|
||||
|
||||
/* Attach the new report object to the end of the list. */
|
||||
if (dev->input_reports == NULL) {
|
||||
/* The list is empty. Put it at the root. */
|
||||
dev->input_reports = rpt;
|
||||
pthread_cond_signal(&dev->condition);
|
||||
SDL_CondSignal(dev->condition);
|
||||
}
|
||||
else {
|
||||
/* Find the end of the list and attach. */
|
||||
|
|
@ -867,7 +821,7 @@ static void read_callback(struct libusb_transfer *transfer)
|
|||
return_data(dev, NULL, 0);
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&dev->mutex);
|
||||
SDL_UnlockMutex(dev->mutex);
|
||||
}
|
||||
else if (transfer->status == LIBUSB_TRANSFER_CANCELLED) {
|
||||
dev->shutdown_thread = 1;
|
||||
|
|
@ -896,14 +850,14 @@ static void read_callback(struct libusb_transfer *transfer)
|
|||
}
|
||||
|
||||
|
||||
static void *read_thread(void *param)
|
||||
static int read_thread(void *param)
|
||||
{
|
||||
hid_device *dev = (hid_device *)param;
|
||||
unsigned char *buf;
|
||||
uint8_t *buf;
|
||||
const size_t length = dev->input_ep_max_packet_size;
|
||||
|
||||
/* Set up the transfer object. */
|
||||
buf = (unsigned char *)malloc(length);
|
||||
buf = (uint8_t*) malloc(length);
|
||||
dev->transfer = libusb_alloc_transfer(0);
|
||||
libusb_fill_interrupt_transfer(dev->transfer,
|
||||
dev->device_handle,
|
||||
|
|
@ -919,7 +873,7 @@ static void *read_thread(void *param)
|
|||
libusb_submit_transfer(dev->transfer);
|
||||
|
||||
/* Notify the main thread that the read thread is up and running. */
|
||||
pthread_barrier_wait(&dev->barrier);
|
||||
SDL_WaitThreadBarrier(&dev->barrier);
|
||||
|
||||
/* Handle all the events. */
|
||||
while (!dev->shutdown_thread) {
|
||||
|
|
@ -951,9 +905,9 @@ static void *read_thread(void *param)
|
|||
make sure that a thread which is about to go to sleep waiting on
|
||||
the condition actually will go to sleep before the condition is
|
||||
signaled. */
|
||||
pthread_mutex_lock(&dev->mutex);
|
||||
pthread_cond_broadcast(&dev->condition);
|
||||
pthread_mutex_unlock(&dev->mutex);
|
||||
SDL_LockMutex(dev->mutex);
|
||||
SDL_CondBroadcast(dev->condition);
|
||||
SDL_UnlockMutex(dev->mutex);
|
||||
|
||||
/* The dev->transfer->buffer and dev->transfer objects are cleaned up
|
||||
in hid_close(). They are not cleaned up here because this thread
|
||||
|
|
@ -963,9 +917,42 @@ static void *read_thread(void *param)
|
|||
since hid_close() calls libusb_cancel_transfer(), on these objects,
|
||||
they can not be cleaned up here. */
|
||||
|
||||
return NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void init_xboxone(libusb_device_handle *device_handle, struct libusb_config_descriptor *conf_desc)
|
||||
{
|
||||
static const int XB1_IFACE_SUBCLASS = 71;
|
||||
static const int XB1_IFACE_PROTOCOL = 208;
|
||||
int j, k, res;
|
||||
|
||||
for (j = 0; j < conf_desc->bNumInterfaces; j++) {
|
||||
const struct libusb_interface *intf = &conf_desc->interface[j];
|
||||
for (k = 0; k < intf->num_altsetting; k++) {
|
||||
const struct libusb_interface_descriptor *intf_desc;
|
||||
intf_desc = &intf->altsetting[k];
|
||||
|
||||
if (intf_desc->bInterfaceNumber != 0 &&
|
||||
intf_desc->bAlternateSetting == 0 &&
|
||||
intf_desc->bInterfaceClass == LIBUSB_CLASS_VENDOR_SPEC &&
|
||||
intf_desc->bInterfaceSubClass == XB1_IFACE_SUBCLASS &&
|
||||
intf_desc->bInterfaceProtocol == XB1_IFACE_PROTOCOL) {
|
||||
res = libusb_claim_interface(device_handle, intf_desc->bInterfaceNumber);
|
||||
if (res < 0) {
|
||||
LOG("can't claim interface %d: %d\n", intf_desc->bInterfaceNumber, res);
|
||||
continue;
|
||||
}
|
||||
|
||||
res = libusb_set_interface_alt_setting(device_handle, intf_desc->bInterfaceNumber, intf_desc->bAlternateSetting);
|
||||
if (res < 0) {
|
||||
LOG("xbox init: can't set alt setting %d: %d\n", intf_desc->bInterfaceNumber, res);
|
||||
}
|
||||
|
||||
libusb_release_interface(device_handle, intf_desc->bInterfaceNumber);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hid_device * HID_API_EXPORT hid_open_path(const char *path, int bExclusive)
|
||||
{
|
||||
|
|
@ -987,9 +974,13 @@ hid_device * HID_API_EXPORT hid_open_path(const char *path, int bExclusive)
|
|||
struct libusb_device_descriptor desc;
|
||||
struct libusb_config_descriptor *conf_desc = NULL;
|
||||
int i,j,k;
|
||||
|
||||
libusb_get_device_descriptor(usb_dev, &desc);
|
||||
|
||||
if (libusb_get_active_config_descriptor(usb_dev, &conf_desc) < 0)
|
||||
res = libusb_get_active_config_descriptor(usb_dev, &conf_desc);
|
||||
if (res < 0)
|
||||
libusb_get_config_descriptor(usb_dev, 0, &conf_desc);
|
||||
if (!conf_desc)
|
||||
continue;
|
||||
for (j = 0; j < conf_desc->bNumInterfaces; j++) {
|
||||
const struct libusb_interface *intf = &conf_desc->interface[j];
|
||||
|
|
@ -999,6 +990,8 @@ hid_device * HID_API_EXPORT hid_open_path(const char *path, int bExclusive)
|
|||
if (should_enumerate_interface(desc.idVendor, intf_desc)) {
|
||||
char *dev_path = make_path(usb_dev, intf_desc->bInterfaceNumber);
|
||||
if (!strcmp(dev_path, path)) {
|
||||
int detached_driver = 0;
|
||||
|
||||
/* Matched Paths. Open this device */
|
||||
|
||||
/* OPEN HERE */
|
||||
|
|
@ -1009,6 +1002,7 @@ hid_device * HID_API_EXPORT hid_open_path(const char *path, int bExclusive)
|
|||
break;
|
||||
}
|
||||
good_open = 1;
|
||||
|
||||
#ifdef DETACH_KERNEL_DRIVER
|
||||
/* Detach the kernel driver, but only if the
|
||||
device is managed by the kernel */
|
||||
|
|
@ -1021,8 +1015,10 @@ hid_device * HID_API_EXPORT hid_open_path(const char *path, int bExclusive)
|
|||
good_open = 0;
|
||||
break;
|
||||
}
|
||||
detached_driver = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
res = libusb_claim_interface(dev->device_handle, intf_desc->bInterfaceNumber);
|
||||
if (res < 0) {
|
||||
LOG("can't claim interface %d: %d\n", intf_desc->bInterfaceNumber, res);
|
||||
|
|
@ -1032,6 +1028,11 @@ hid_device * HID_API_EXPORT hid_open_path(const char *path, int bExclusive)
|
|||
break;
|
||||
}
|
||||
|
||||
/* Initialize XBox One controllers */
|
||||
if (is_xboxone(desc.idVendor, intf_desc)) {
|
||||
init_xboxone(dev->device_handle, conf_desc);
|
||||
}
|
||||
|
||||
/* Store off the string descriptor indexes */
|
||||
dev->manufacturer_index = desc.iManufacturer;
|
||||
dev->product_index = desc.iProduct;
|
||||
|
|
@ -1039,6 +1040,7 @@ hid_device * HID_API_EXPORT hid_open_path(const char *path, int bExclusive)
|
|||
|
||||
/* Store off the interface number */
|
||||
dev->interface = intf_desc->bInterfaceNumber;
|
||||
dev->detached_driver = detached_driver;
|
||||
|
||||
/* Find the INPUT and OUTPUT endpoints. An
|
||||
OUTPUT endpoint is not required. */
|
||||
|
|
@ -1072,10 +1074,10 @@ hid_device * HID_API_EXPORT hid_open_path(const char *path, int bExclusive)
|
|||
}
|
||||
}
|
||||
|
||||
pthread_create(&dev->thread, NULL, read_thread, dev);
|
||||
dev->thread = SDL_CreateThread(read_thread, NULL, dev);
|
||||
|
||||
/* Wait here for the read thread to be initialized. */
|
||||
pthread_barrier_wait(&dev->barrier);
|
||||
SDL_WaitThreadBarrier(&dev->barrier);
|
||||
|
||||
}
|
||||
free(dev_path);
|
||||
|
|
@ -1103,17 +1105,17 @@ hid_device * HID_API_EXPORT hid_open_path(const char *path, int bExclusive)
|
|||
int HID_API_EXPORT hid_write(hid_device *dev, const unsigned char *data, size_t length)
|
||||
{
|
||||
int res;
|
||||
int report_number = data[0];
|
||||
int skipped_report_id = 0;
|
||||
|
||||
if (report_number == 0x0) {
|
||||
data++;
|
||||
length--;
|
||||
skipped_report_id = 1;
|
||||
}
|
||||
|
||||
|
||||
if (dev->output_endpoint <= 0) {
|
||||
int report_number = data[0];
|
||||
int skipped_report_id = 0;
|
||||
|
||||
if (report_number == 0x0) {
|
||||
data++;
|
||||
length--;
|
||||
skipped_report_id = 1;
|
||||
}
|
||||
|
||||
/* No interrupt out endpoint. Use the Control Endpoint */
|
||||
res = libusb_control_transfer(dev->device_handle,
|
||||
LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE|LIBUSB_ENDPOINT_OUT,
|
||||
|
|
@ -1143,9 +1145,6 @@ int HID_API_EXPORT hid_write(hid_device *dev, const unsigned char *data, size_t
|
|||
if (res < 0)
|
||||
return -1;
|
||||
|
||||
if (skipped_report_id)
|
||||
actual_length++;
|
||||
|
||||
return actual_length;
|
||||
}
|
||||
}
|
||||
|
|
@ -1166,11 +1165,13 @@ static int return_data(hid_device *dev, unsigned char *data, size_t length)
|
|||
return len;
|
||||
}
|
||||
|
||||
#if 0 /* TODO: pthread_cleanup SDL? */
|
||||
static void cleanup_mutex(void *param)
|
||||
{
|
||||
hid_device *dev = (hid_device *)param;
|
||||
pthread_mutex_unlock(&dev->mutex);
|
||||
SDL_UnlockMutex(dev->mutex);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds)
|
||||
|
|
@ -1184,8 +1185,8 @@ int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t
|
|||
return transferred;
|
||||
#endif
|
||||
|
||||
pthread_mutex_lock(&dev->mutex);
|
||||
pthread_cleanup_push(&cleanup_mutex, dev);
|
||||
SDL_LockMutex(dev->mutex);
|
||||
/* TODO: pthread_cleanup SDL? */
|
||||
|
||||
/* There's an input report queued up. Return it. */
|
||||
if (dev->input_reports) {
|
||||
|
|
@ -1204,7 +1205,7 @@ int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t
|
|||
if (milliseconds == -1) {
|
||||
/* Blocking */
|
||||
while (!dev->input_reports && !dev->shutdown_thread) {
|
||||
pthread_cond_wait(&dev->condition, &dev->mutex);
|
||||
SDL_CondWait(dev->condition, dev->mutex);
|
||||
}
|
||||
if (dev->input_reports) {
|
||||
bytes_read = return_data(dev, data, length);
|
||||
|
|
@ -1213,17 +1214,9 @@ int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t
|
|||
else if (milliseconds > 0) {
|
||||
/* Non-blocking, but called with timeout. */
|
||||
int res;
|
||||
struct timespec ts;
|
||||
clock_gettime(CLOCK_REALTIME, &ts);
|
||||
ts.tv_sec += milliseconds / 1000;
|
||||
ts.tv_nsec += (milliseconds % 1000) * 1000000;
|
||||
if (ts.tv_nsec >= 1000000000L) {
|
||||
ts.tv_sec++;
|
||||
ts.tv_nsec -= 1000000000L;
|
||||
}
|
||||
|
||||
while (!dev->input_reports && !dev->shutdown_thread) {
|
||||
res = pthread_cond_timedwait(&dev->condition, &dev->mutex, &ts);
|
||||
res = SDL_CondWaitTimeout(dev->condition, dev->mutex, milliseconds);
|
||||
if (res == 0) {
|
||||
if (dev->input_reports) {
|
||||
bytes_read = return_data(dev, data, length);
|
||||
|
|
@ -1234,7 +1227,7 @@ int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t
|
|||
or the read thread was shutdown. Run the
|
||||
loop again (ie: don't break). */
|
||||
}
|
||||
else if (res == ETIMEDOUT) {
|
||||
else if (res == SDL_MUTEX_TIMEDOUT) {
|
||||
/* Timed out. */
|
||||
bytes_read = 0;
|
||||
break;
|
||||
|
|
@ -1252,8 +1245,8 @@ int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t
|
|||
}
|
||||
|
||||
ret:
|
||||
pthread_mutex_unlock(&dev->mutex);
|
||||
pthread_cleanup_pop(0);
|
||||
SDL_UnlockMutex(dev->mutex);
|
||||
/* TODO: pthread_cleanup SDL? */
|
||||
|
||||
return bytes_read;
|
||||
}
|
||||
|
|
@ -1334,6 +1327,8 @@ int HID_API_EXPORT hid_get_feature_report(hid_device *dev, unsigned char *data,
|
|||
|
||||
void HID_API_EXPORT hid_close(hid_device *dev)
|
||||
{
|
||||
int status;
|
||||
|
||||
if (!dev)
|
||||
return;
|
||||
|
||||
|
|
@ -1342,7 +1337,7 @@ void HID_API_EXPORT hid_close(hid_device *dev)
|
|||
libusb_cancel_transfer(dev->transfer);
|
||||
|
||||
/* Wait for read_thread() to end. */
|
||||
pthread_join(dev->thread, NULL);
|
||||
SDL_WaitThread(dev->thread, &status);
|
||||
|
||||
/* Clean up the Transfer objects allocated in read_thread(). */
|
||||
free(dev->transfer->buffer);
|
||||
|
|
@ -1351,15 +1346,24 @@ void HID_API_EXPORT hid_close(hid_device *dev)
|
|||
/* release the interface */
|
||||
libusb_release_interface(dev->device_handle, dev->interface);
|
||||
|
||||
#ifdef DETACH_KERNEL_DRIVER
|
||||
/* Re-attach kernel driver if necessary. */
|
||||
if (dev->detached_driver) {
|
||||
int res = libusb_attach_kernel_driver(dev->device_handle, dev->interface);
|
||||
if (res < 0)
|
||||
LOG("Couldn't re-attach kernel driver.\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Close the handle */
|
||||
libusb_close(dev->device_handle);
|
||||
|
||||
/* Clear out the queue of received reports. */
|
||||
pthread_mutex_lock(&dev->mutex);
|
||||
SDL_LockMutex(dev->mutex);
|
||||
while (dev->input_reports) {
|
||||
return_data(dev, NULL, 0);
|
||||
}
|
||||
pthread_mutex_unlock(&dev->mutex);
|
||||
SDL_UnlockMutex(dev->mutex);
|
||||
|
||||
free_hid_device(dev);
|
||||
}
|
||||
|
|
@ -1452,7 +1456,7 @@ static struct lang_map_entry lang_map[] = {
|
|||
LANG("English - Ireland", "en_ie", 0x1809),
|
||||
LANG("English - Jamaica", "en_jm", 0x2009),
|
||||
LANG("English - New Zealand", "en_nz", 0x1409),
|
||||
LANG("English - Phillippines", "en_ph", 0x3409),
|
||||
LANG("English - Philippines", "en_ph", 0x3409),
|
||||
LANG("English - Southern Africa", "en_za", 0x1C09),
|
||||
LANG("English - Trinidad", "en_tt", 0x2C09),
|
||||
LANG("English - Great Britain", "en_gb", 0x0809),
|
||||
|
|
@ -1487,7 +1491,7 @@ static struct lang_map_entry lang_map[] = {
|
|||
LANG("Lithuanian", "lt", 0x0427),
|
||||
LANG("F.Y.R.O. Macedonia", "mk", 0x042F),
|
||||
LANG("Malay - Malaysia", "ms_my", 0x043E),
|
||||
LANG("Malay – Brunei", "ms_bn", 0x083E),
|
||||
LANG("Malay ??? Brunei", "ms_bn", 0x083E),
|
||||
LANG("Maltese", "mt", 0x043A),
|
||||
LANG("Marathi", "mr", 0x044E),
|
||||
LANG("Norwegian - Bokml", "no_no", 0x0414),
|
||||
|
|
@ -1538,7 +1542,7 @@ static struct lang_map_entry lang_map[] = {
|
|||
LANG("Ukrainian", "uk", 0x0422),
|
||||
LANG("Urdu", "ur", 0x0420),
|
||||
LANG("Uzbek - Cyrillic", "uz_uz", 0x0843),
|
||||
LANG("Uzbek – Latin", "uz_uz", 0x0443),
|
||||
LANG("Uzbek ??? Latin", "uz_uz", 0x0443),
|
||||
LANG("Vietnamese", "vi", 0x042A),
|
||||
LANG("Xhosa", "xh", 0x0434),
|
||||
LANG("Yiddish", "yi", 0x043D),
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
files located at the root of the source distribution.
|
||||
These files may also be found in the public source
|
||||
code repository located at:
|
||||
http://github.com/signal11/hidapi .
|
||||
https://github.com/libusb/hidapi .
|
||||
********************************************************/
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
files located at the root of the source distribution.
|
||||
These files may also be found in the public source
|
||||
code repository located at:
|
||||
http://github.com/signal11/hidapi .
|
||||
https://github.com/libusb/hidapi .
|
||||
********************************************************/
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
|
|
@ -29,7 +29,6 @@
|
|||
#include <IOKit/hid/IOHIDKeys.h>
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#include <wchar.h>
|
||||
#include <locale.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
|
|
@ -42,10 +41,10 @@
|
|||
StackOverflow. It is used with his permission. */
|
||||
typedef int pthread_barrierattr_t;
|
||||
typedef struct pthread_barrier {
|
||||
pthread_mutex_t mutex;
|
||||
pthread_cond_t cond;
|
||||
int count;
|
||||
int trip_count;
|
||||
pthread_mutex_t mutex;
|
||||
pthread_cond_t cond;
|
||||
int count;
|
||||
int trip_count;
|
||||
} pthread_barrier_t;
|
||||
|
||||
static int pthread_barrier_init(pthread_barrier_t *barrier, const pthread_barrierattr_t *attr, unsigned int count)
|
||||
|
|
@ -179,22 +178,22 @@ static void free_hid_device(hid_device *dev)
|
|||
free(dev->input_report_buf);
|
||||
|
||||
if (device_list) {
|
||||
if (device_list->dev == dev) {
|
||||
device_list = device_list->next;
|
||||
}
|
||||
else {
|
||||
struct hid_device_list_node *node = device_list;
|
||||
while (node) {
|
||||
if (node->next && node->next->dev == dev) {
|
||||
struct hid_device_list_node *new_next = node->next->next;
|
||||
free(node->next);
|
||||
node->next = new_next;
|
||||
break;
|
||||
}
|
||||
if (device_list->dev == dev) {
|
||||
device_list = device_list->next;
|
||||
}
|
||||
else {
|
||||
struct hid_device_list_node *node = device_list;
|
||||
while (node) {
|
||||
if (node->next && node->next->dev == dev) {
|
||||
struct hid_device_list_node *new_next = node->next->next;
|
||||
free(node->next);
|
||||
node->next = new_next;
|
||||
break;
|
||||
}
|
||||
|
||||
node = node->next;
|
||||
}
|
||||
}
|
||||
node = node->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Clean up the thread objects */
|
||||
|
|
@ -372,6 +371,27 @@ static int make_path(IOHIDDeviceRef device, char *buf, size_t len)
|
|||
return res+1;
|
||||
}
|
||||
|
||||
static void hid_device_removal_callback(void *context, IOReturn result,
|
||||
void *sender, IOHIDDeviceRef hid_ref)
|
||||
{
|
||||
// The device removal callback is sometimes called even after being
|
||||
// unregistered, leading to a crash when trying to access fields in
|
||||
// the already freed hid_device. We keep a linked list of all created
|
||||
// hid_device's so that the one being removed can be checked against
|
||||
// the list to see if it really hasn't been closed yet and needs to
|
||||
// be dealt with here.
|
||||
struct hid_device_list_node *node = device_list;
|
||||
while (node) {
|
||||
if (node->dev->device_handle == hid_ref) {
|
||||
node->dev->disconnected = 1;
|
||||
CFRunLoopStop(node->dev->run_loop);
|
||||
break;
|
||||
}
|
||||
|
||||
node = node->next;
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialize the IOHIDManager. Return 0 for success and -1 for failure. */
|
||||
static int init_hid_manager(void)
|
||||
{
|
||||
|
|
@ -381,6 +401,7 @@ static int init_hid_manager(void)
|
|||
if (hid_mgr) {
|
||||
IOHIDManagerSetDeviceMatching(hid_mgr, NULL);
|
||||
IOHIDManagerScheduleWithRunLoop(hid_mgr, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
|
||||
IOHIDManagerRegisterDeviceRemovalCallback(hid_mgr, hid_device_removal_callback, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -426,8 +447,6 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id,
|
|||
CFIndex num_devices;
|
||||
int i;
|
||||
|
||||
setlocale(LC_ALL,"");
|
||||
|
||||
/* Set up the HID Manager if it hasn't been done */
|
||||
if (hid_init() < 0)
|
||||
return NULL;
|
||||
|
|
@ -459,9 +478,10 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id,
|
|||
|
||||
IOHIDDeviceRef dev = device_array[i];
|
||||
|
||||
if (!dev) {
|
||||
continue;
|
||||
}
|
||||
if (!dev) {
|
||||
continue;
|
||||
}
|
||||
|
||||
dev_vid = get_vendor_id(dev);
|
||||
dev_pid = get_product_id(dev);
|
||||
|
||||
|
|
@ -569,30 +589,6 @@ hid_device * HID_API_EXPORT hid_open(unsigned short vendor_id, unsigned short pr
|
|||
return handle;
|
||||
}
|
||||
|
||||
static void hid_device_removal_callback(void *context, IOReturn result,
|
||||
void *sender)
|
||||
{
|
||||
/* Stop the Run Loop for this device. */
|
||||
hid_device *dev = (hid_device *)context;
|
||||
|
||||
// The device removal callback is sometimes called even after being
|
||||
// unregistered, leading to a crash when trying to access fields in
|
||||
// the already freed hid_device. We keep a linked list of all created
|
||||
// hid_device's so that the one being removed can be checked against
|
||||
// the list to see if it really hasn't been closed yet and needs to
|
||||
// be dealt with here.
|
||||
struct hid_device_list_node *node = device_list;
|
||||
while (node) {
|
||||
if (node->dev == dev) {
|
||||
dev->disconnected = 1;
|
||||
CFRunLoopStop(dev->run_loop);
|
||||
break;
|
||||
}
|
||||
|
||||
node = node->next;
|
||||
}
|
||||
}
|
||||
|
||||
/* The Run Loop calls this function for each input report received.
|
||||
This function puts the data into a linked list to be picked up by
|
||||
hid_read(). */
|
||||
|
|
@ -766,7 +762,6 @@ hid_device * HID_API_EXPORT hid_open_path(const char *path, int bExclusive)
|
|||
IOHIDDeviceRegisterInputReportCallback(
|
||||
os_dev, dev->input_report_buf, dev->max_input_report_len,
|
||||
&hid_report_callback, dev);
|
||||
IOHIDDeviceRegisterRemovalCallback(dev->device_handle, hid_device_removal_callback, dev);
|
||||
|
||||
struct hid_device_list_node *node = (struct hid_device_list_node *)calloc(1, sizeof(struct hid_device_list_node));
|
||||
node->dev = dev;
|
||||
|
|
@ -1042,7 +1037,6 @@ void HID_API_EXPORT hid_close(hid_device *dev)
|
|||
IOHIDDeviceRegisterInputReportCallback(
|
||||
dev->device_handle, dev->input_report_buf, dev->max_input_report_len,
|
||||
NULL, dev);
|
||||
IOHIDDeviceRegisterRemovalCallback(dev->device_handle, NULL, dev);
|
||||
IOHIDDeviceUnscheduleFromRunLoop(dev->device_handle, dev->run_loop, dev->run_loop_mode);
|
||||
IOHIDDeviceScheduleWithRunLoop(dev->device_handle, CFRunLoopGetMain(), kCFRunLoopDefaultMode);
|
||||
}
|
||||
|
|
@ -1157,8 +1151,6 @@ int main(void)
|
|||
IOHIDDeviceRef *device_array = calloc(num_devices, sizeof(IOHIDDeviceRef));
|
||||
CFSetGetValues(device_set, (const void **) device_array);
|
||||
|
||||
setlocale(LC_ALL, "");
|
||||
|
||||
for (i = 0; i < num_devices; i++) {
|
||||
IOHIDDeviceRef dev = device_array[i];
|
||||
printf("Device: %p\n", dev);
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
files located at the root of the source distribution.
|
||||
These files may also be found in the public source
|
||||
code repository located at:
|
||||
http://github.com/signal11/hidapi .
|
||||
https://github.com/libusb/hidapi .
|
||||
********************************************************/
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
|
|
@ -63,6 +63,11 @@ typedef LONG NTSTATUS;
|
|||
|
||||
/*#define HIDAPI_USE_DDK*/
|
||||
|
||||
/* The timeout in milliseconds for waiting on WriteFile to
|
||||
complete in hid_write. The longest observed time to do a output
|
||||
report that we've seen is ~200-250ms so let's double that */
|
||||
#define HID_WRITE_TIMEOUT_MILLISECONDS 500
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
|
@ -163,6 +168,7 @@ struct hid_device_ {
|
|||
BOOL read_pending;
|
||||
char *read_buf;
|
||||
OVERLAPPED ol;
|
||||
OVERLAPPED write_ol;
|
||||
};
|
||||
|
||||
static hid_device *new_hid_device()
|
||||
|
|
@ -178,6 +184,8 @@ static hid_device *new_hid_device()
|
|||
dev->read_buf = NULL;
|
||||
memset(&dev->ol, 0, sizeof(dev->ol));
|
||||
dev->ol.hEvent = CreateEvent(NULL, FALSE, FALSE /*initial state f=nonsignaled*/, NULL);
|
||||
memset(&dev->write_ol, 0, sizeof(dev->write_ol));
|
||||
dev->write_ol.hEvent = CreateEvent(NULL, FALSE, FALSE /*initial state f=nonsignaled*/, NULL);
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
|
@ -185,6 +193,7 @@ static hid_device *new_hid_device()
|
|||
static void free_hid_device(hid_device *dev)
|
||||
{
|
||||
CloseHandle(dev->ol.hEvent);
|
||||
CloseHandle(dev->write_ol.hEvent);
|
||||
CloseHandle(dev->device_handle);
|
||||
LocalFree(dev->last_error_str);
|
||||
free(dev->read_buf);
|
||||
|
|
@ -298,8 +307,25 @@ int HID_API_EXPORT hid_exit(void)
|
|||
|
||||
int hid_blacklist(unsigned short vendor_id, unsigned short product_id)
|
||||
{
|
||||
return vendor_id == 0x1B1C && // (Corsair)
|
||||
product_id == 0x1B3D; // Gaming keyboard? Causes deadlock when asking for device details
|
||||
// Corsair Gaming keyboard - Causes deadlock when asking for device details
|
||||
if ( vendor_id == 0x1B1C && product_id == 0x1B3D )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
// SPEEDLINK COMPETITION PRO - turns into an Android controller when enumerated
|
||||
if ( vendor_id == 0x0738 && product_id == 0x2217 )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Sound BlasterX G1 - Causes 10 second stalls when asking for manufacturer's string
|
||||
if ( vendor_id == 0x041E && product_id == 0x3249 )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id)
|
||||
|
|
@ -661,14 +687,12 @@ int HID_API_EXPORT HID_API_CALL hid_write_output_report(hid_device *dev, const u
|
|||
return -1;
|
||||
}
|
||||
|
||||
int HID_API_EXPORT HID_API_CALL hid_write(hid_device *dev, const unsigned char *data, size_t length)
|
||||
static int hid_write_timeout(hid_device *dev, const unsigned char *data, size_t length, int milliseconds)
|
||||
{
|
||||
DWORD bytes_written;
|
||||
BOOL res;
|
||||
size_t stashed_length = length;
|
||||
OVERLAPPED ol;
|
||||
unsigned char *buf;
|
||||
memset(&ol, 0, sizeof(ol));
|
||||
|
||||
/* Make sure the right number of bytes are passed to WriteFile. Windows
|
||||
expects the number of bytes which are in the _longest_ report (plus
|
||||
|
|
@ -693,7 +717,7 @@ int HID_API_EXPORT HID_API_CALL hid_write(hid_device *dev, const unsigned char *
|
|||
}
|
||||
else
|
||||
{
|
||||
res = WriteFile( dev->device_handle, buf, ( DWORD ) length, NULL, &ol );
|
||||
res = WriteFile( dev->device_handle, buf, ( DWORD ) length, NULL, &dev->write_ol );
|
||||
if (!res) {
|
||||
if (GetLastError() != ERROR_IO_PENDING) {
|
||||
/* WriteFile() failed. Return error. */
|
||||
|
|
@ -705,7 +729,16 @@ int HID_API_EXPORT HID_API_CALL hid_write(hid_device *dev, const unsigned char *
|
|||
|
||||
/* Wait here until the write is done. This makes
|
||||
hid_write() synchronous. */
|
||||
res = GetOverlappedResult(dev->device_handle, &ol, &bytes_written, TRUE/*wait*/);
|
||||
res = WaitForSingleObject(dev->write_ol.hEvent, milliseconds);
|
||||
if (res != WAIT_OBJECT_0)
|
||||
{
|
||||
// There was a Timeout.
|
||||
bytes_written = (DWORD) -1;
|
||||
register_error(dev, "WriteFile/WaitForSingleObject Timeout");
|
||||
goto end_of_function;
|
||||
}
|
||||
|
||||
res = GetOverlappedResult(dev->device_handle, &dev->write_ol, &bytes_written, FALSE/*F=don't_wait*/);
|
||||
if (!res) {
|
||||
/* The Write operation failed. */
|
||||
register_error(dev, "WriteFile");
|
||||
|
|
@ -720,6 +753,10 @@ end_of_function:
|
|||
return bytes_written;
|
||||
}
|
||||
|
||||
int HID_API_EXPORT HID_API_CALL hid_write(hid_device *dev, const unsigned char *data, size_t length)
|
||||
{
|
||||
return hid_write_timeout(dev, data, length, HID_WRITE_TIMEOUT_MILLISECONDS);
|
||||
}
|
||||
|
||||
int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds)
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue