early-access version 1667
This commit is contained in:
122
externals/SDL/src/hidapi/SDL_hidapi.c
vendored
122
externals/SDL/src/hidapi/SDL_hidapi.c
vendored
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2021 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
|
||||
@@ -27,9 +27,10 @@
|
||||
* 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"
|
||||
#include "SDL_hidapi.h"
|
||||
|
||||
#ifdef SDL_JOYSTICK_HIDAPI
|
||||
|
||||
@@ -434,6 +435,8 @@ struct _HIDDeviceWrapper
|
||||
const struct hidapi_backend *backend;
|
||||
};
|
||||
|
||||
#if HAVE_PLATFORM_BACKEND || HAVE_DRIVER_BACKEND || defined(SDL_LIBUSB_DYNAMIC)
|
||||
|
||||
static HIDDeviceWrapper *
|
||||
CreateHIDDeviceWrapper(hid_device *device, const struct hidapi_backend *backend)
|
||||
{
|
||||
@@ -449,6 +452,8 @@ WrapHIDDevice(HIDDeviceWrapper *wrapper)
|
||||
return (hid_device *)wrapper;
|
||||
}
|
||||
|
||||
#endif /* HAVE_PLATFORM_BACKEND || HAVE_DRIVER_BACKEND || SDL_LIBUSB_DYNAMIC */
|
||||
|
||||
static HIDDeviceWrapper *
|
||||
UnwrapHIDDevice(hid_device *device)
|
||||
{
|
||||
@@ -547,13 +552,14 @@ static SDL_bool SDL_hidapi_wasinit = SDL_FALSE;
|
||||
|
||||
int HID_API_EXPORT HID_API_CALL hid_init(void)
|
||||
{
|
||||
int err;
|
||||
int attempts = 0, success = 0;
|
||||
|
||||
if (SDL_hidapi_wasinit == SDL_TRUE) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef SDL_LIBUSB_DYNAMIC
|
||||
++attempts;
|
||||
libusb_ctx.libhandle = SDL_LoadObject(SDL_LIBUSB_DYNAMIC);
|
||||
if (libusb_ctx.libhandle != NULL) {
|
||||
SDL_bool loaded = SDL_TRUE;
|
||||
@@ -587,44 +593,40 @@ int HID_API_EXPORT HID_API_CALL hid_init(void)
|
||||
LOAD_LIBUSB_SYMBOL(handle_events_completed)
|
||||
#undef LOAD_LIBUSB_SYMBOL
|
||||
|
||||
if (loaded == SDL_TRUE) {
|
||||
if ((err = LIBUSB_hid_init()) < 0) {
|
||||
SDL_UnloadObject(libusb_ctx.libhandle);
|
||||
libusb_ctx.libhandle = NULL;
|
||||
return err;
|
||||
}
|
||||
} else {
|
||||
if (!loaded) {
|
||||
SDL_UnloadObject(libusb_ctx.libhandle);
|
||||
libusb_ctx.libhandle = NULL;
|
||||
/* SDL_LogWarn(SDL_LOG_CATEGORY_INPUT, SDL_LIBUSB_DYNAMIC " found but could not load function."); */
|
||||
/* ignore error: continue without libusb */
|
||||
/* SDL_LogWarn(SDL_LOG_CATEGORY_INPUT, SDL_LIBUSB_DYNAMIC " found but could not load function"); */
|
||||
} else if (LIBUSB_hid_init() < 0) {
|
||||
SDL_UnloadObject(libusb_ctx.libhandle);
|
||||
libusb_ctx.libhandle = NULL;
|
||||
} else {
|
||||
++success;
|
||||
}
|
||||
}
|
||||
#endif /* SDL_LIBUSB_DYNAMIC */
|
||||
|
||||
#if HAVE_PLATFORM_BACKEND
|
||||
++attempts;
|
||||
#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) {
|
||||
LIBUSB_hid_exit();
|
||||
SDL_UnloadObject(libusb_ctx.libhandle);
|
||||
libusb_ctx.libhandle = NULL;
|
||||
}
|
||||
#endif /* SDL_LIBUSB_DYNAMIC */
|
||||
return err;
|
||||
if (udev_ctx && PLATFORM_hid_init() == 0) {
|
||||
++success;
|
||||
}
|
||||
#endif /* HAVE_PLATFORM_BACKEND */
|
||||
|
||||
if (attempts > 0 && success == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
SDL_hidapi_wasinit = SDL_TRUE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int HID_API_EXPORT HID_API_CALL hid_exit(void)
|
||||
{
|
||||
int err = 0;
|
||||
int result = 0;
|
||||
|
||||
if (SDL_hidapi_wasinit == SDL_FALSE) {
|
||||
return 0;
|
||||
@@ -633,21 +635,24 @@ int HID_API_EXPORT HID_API_CALL hid_exit(void)
|
||||
|
||||
#if HAVE_PLATFORM_BACKEND
|
||||
if (udev_ctx) {
|
||||
err = PLATFORM_hid_exit();
|
||||
result |= PLATFORM_hid_exit();
|
||||
}
|
||||
#endif /* HAVE_PLATFORM_BACKEND */
|
||||
|
||||
#ifdef SDL_LIBUSB_DYNAMIC
|
||||
if (libusb_ctx.libhandle) {
|
||||
err |= LIBUSB_hid_exit(); /* Ehhhhh */
|
||||
result |= LIBUSB_hid_exit();
|
||||
SDL_UnloadObject(libusb_ctx.libhandle);
|
||||
libusb_ctx.libhandle = NULL;
|
||||
}
|
||||
#endif /* SDL_LIBUSB_DYNAMIC */
|
||||
return err;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id)
|
||||
{
|
||||
#if HAVE_PLATFORM_BACKEND || HAVE_DRIVER_BACKEND || defined(SDL_LIBUSB_DYNAMIC)
|
||||
#ifdef SDL_LIBUSB_DYNAMIC
|
||||
struct LIBUSB_hid_device_info *usb_devs = NULL;
|
||||
struct LIBUSB_hid_device_info *usb_dev;
|
||||
@@ -779,6 +784,10 @@ struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned shor
|
||||
}
|
||||
#endif
|
||||
return devs;
|
||||
|
||||
#else
|
||||
return NULL;
|
||||
#endif /* HAVE_PLATFORM_BACKEND || HAVE_DRIVER_BACKEND || SDL_LIBUSB_DYNAMIC */
|
||||
}
|
||||
|
||||
void HID_API_EXPORT HID_API_CALL hid_free_enumeration(struct hid_device_info *devs)
|
||||
@@ -796,6 +805,7 @@ void HID_API_EXPORT HID_API_CALL hid_free_enumeration(struct hid_device_info *d
|
||||
|
||||
HID_API_EXPORT hid_device * HID_API_CALL hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number)
|
||||
{
|
||||
#if HAVE_PLATFORM_BACKEND || HAVE_DRIVER_BACKEND || defined(SDL_LIBUSB_DYNAMIC)
|
||||
hid_device *pDevice = NULL;
|
||||
|
||||
if (hid_init() != 0) {
|
||||
@@ -828,11 +838,14 @@ HID_API_EXPORT hid_device * HID_API_CALL hid_open(unsigned short vendor_id, unsi
|
||||
}
|
||||
#endif /* SDL_LIBUSB_DYNAMIC */
|
||||
|
||||
#endif /* HAVE_PLATFORM_BACKEND || HAVE_DRIVER_BACKEND || SDL_LIBUSB_DYNAMIC */
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path, int bExclusive /* = false */)
|
||||
{
|
||||
#if HAVE_PLATFORM_BACKEND || HAVE_DRIVER_BACKEND || defined(SDL_LIBUSB_DYNAMIC)
|
||||
hid_device *pDevice = NULL;
|
||||
|
||||
if (hid_init() != 0) {
|
||||
@@ -865,6 +878,8 @@ HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path, int bEx
|
||||
}
|
||||
#endif /* SDL_LIBUSB_DYNAMIC */
|
||||
|
||||
#endif /* HAVE_PLATFORM_BACKEND || HAVE_DRIVER_BACKEND || SDL_LIBUSB_DYNAMIC */
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -941,6 +956,63 @@ HID_API_EXPORT const wchar_t* HID_API_CALL hid_error(hid_device *device)
|
||||
return wrapper->backend->hid_error(wrapper->device);
|
||||
}
|
||||
|
||||
#ifdef HAVE_ENABLE_GAMECUBE_ADAPTORS
|
||||
/* This is needed to enable input for Nyko and EVORETRO GameCube adaptors */
|
||||
void SDL_EnableGameCubeAdaptors(void)
|
||||
{
|
||||
#ifdef SDL_LIBUSB_DYNAMIC
|
||||
libusb_context *usb_context = NULL;
|
||||
libusb_device **devs = NULL;
|
||||
libusb_device_handle *handle = NULL;
|
||||
struct libusb_device_descriptor desc;
|
||||
ssize_t i, num_devs;
|
||||
int kernel_detached = 0;
|
||||
|
||||
if (libusb_ctx.libhandle == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (libusb_init(&usb_context) == 0) {
|
||||
num_devs = libusb_get_device_list(usb_context, &devs);
|
||||
for (i = 0; i < num_devs; ++i) {
|
||||
if (libusb_get_device_descriptor(devs[i], &desc) != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (desc.idVendor != 0x057e || desc.idProduct != 0x0337) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (libusb_open(devs[i], &handle) != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (libusb_kernel_driver_active(handle, 0)) {
|
||||
if (libusb_detach_kernel_driver(handle, 0) == 0) {
|
||||
kernel_detached = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (libusb_claim_interface(handle, 0) == 0) {
|
||||
libusb_control_transfer(handle, 0x21, 11, 0x0001, 0, NULL, 0, 1000);
|
||||
libusb_release_interface(handle, 0);
|
||||
}
|
||||
|
||||
if (kernel_detached) {
|
||||
libusb_attach_kernel_driver(handle, 0);
|
||||
}
|
||||
|
||||
libusb_close(handle);
|
||||
}
|
||||
|
||||
libusb_free_device_list(devs, 1);
|
||||
|
||||
libusb_exit(usb_context);
|
||||
}
|
||||
#endif /* SDL_LIBUSB_DYNAMIC */
|
||||
}
|
||||
#endif /* HAVE_ENABLE_GAMECUBE_ADAPTORS */
|
||||
|
||||
#endif /* SDL_JOYSTICK_HIDAPI */
|
||||
|
||||
/* vi: set sts=4 ts=4 sw=4 expandtab: */
|
||||
|
35
externals/SDL/src/hidapi/SDL_hidapi.h
vendored
Executable file
35
externals/SDL/src/hidapi/SDL_hidapi.h
vendored
Executable file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2021 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.
|
||||
*/
|
||||
#include "../SDL_internal.h"
|
||||
|
||||
#ifdef SDL_JOYSTICK_HIDAPI
|
||||
|
||||
#ifdef SDL_LIBUSB_DYNAMIC
|
||||
#define HAVE_ENABLE_GAMECUBE_ADAPTORS
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ENABLE_GAMECUBE_ADAPTORS
|
||||
extern void SDL_EnableGameCubeAdaptors(void);
|
||||
#endif
|
||||
|
||||
#endif /* SDL_JOYSTICK_HIDAPI */
|
||||
|
||||
/* vi: set sts=4 ts=4 sw=4 expandtab: */
|
24
externals/SDL/src/hidapi/android/hid.cpp
vendored
24
externals/SDL/src/hidapi/android/hid.cpp
vendored
@@ -1,10 +1,26 @@
|
||||
//=================== Copyright Valve Corporation, All rights reserved. =======
|
||||
//
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 2021 Valve Corporation
|
||||
|
||||
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.
|
||||
*/
|
||||
// Purpose: A wrapper implementing "HID" API for Android
|
||||
//
|
||||
// This layer glues the hidapi API to Android's USB and BLE stack.
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include <jni.h>
|
||||
#include <android/log.h>
|
||||
|
60
externals/SDL/src/hidapi/hidapi/hidapi.h
vendored
60
externals/SDL/src/hidapi/hidapi/hidapi.h
vendored
@@ -77,9 +77,11 @@ namespace NAMESPACE {
|
||||
(Windows/Mac only).*/
|
||||
unsigned short usage;
|
||||
/** The USB interface which this logical device
|
||||
represents. Valid on both Linux implementations
|
||||
in all cases, and valid on the Windows implementation
|
||||
only if the device contains more than one interface. */
|
||||
represents.
|
||||
|
||||
* Valid on both Linux implementations in all cases.
|
||||
* Valid on the Windows implementation only if the device
|
||||
contains more than one interface. */
|
||||
int interface_number;
|
||||
|
||||
/** Additional information about the USB interface.
|
||||
@@ -101,7 +103,7 @@ namespace NAMESPACE {
|
||||
needed. This function should be called at the beginning of
|
||||
execution however, if there is a chance of HIDAPI handles
|
||||
being opened by different threads simultaneously.
|
||||
|
||||
|
||||
@ingroup API
|
||||
|
||||
@returns
|
||||
@@ -139,7 +141,7 @@ namespace NAMESPACE {
|
||||
|
||||
@returns
|
||||
This function returns a pointer to a linked list of type
|
||||
struct #hid_device, containing information about the HID devices
|
||||
struct #hid_device_info, containing information about the HID devices
|
||||
attached to the system, or NULL in the case of failure. Free
|
||||
this linked list by calling hid_free_enumeration().
|
||||
*/
|
||||
@@ -205,7 +207,7 @@ namespace NAMESPACE {
|
||||
the Control Endpoint (Endpoint 0).
|
||||
|
||||
@ingroup API
|
||||
@param device A device handle returned from hid_open().
|
||||
@param dev A device handle returned from hid_open().
|
||||
@param data The data to send, including the report number as
|
||||
the first byte.
|
||||
@param length The length in bytes of the data to send.
|
||||
@@ -214,7 +216,7 @@ namespace NAMESPACE {
|
||||
This function returns the actual number of bytes written and
|
||||
-1 on error.
|
||||
*/
|
||||
int HID_API_EXPORT HID_API_CALL hid_write(hid_device *device, const unsigned char *data, size_t length);
|
||||
int HID_API_EXPORT HID_API_CALL hid_write(hid_device *dev, const unsigned char *data, size_t length);
|
||||
|
||||
/** @brief Read an Input report from a HID device with timeout.
|
||||
|
||||
@@ -223,7 +225,7 @@ namespace NAMESPACE {
|
||||
contain the Report number if the device uses numbered reports.
|
||||
|
||||
@ingroup API
|
||||
@param device A device handle returned from hid_open().
|
||||
@param dev A device handle returned from hid_open().
|
||||
@param data A buffer to put the read data into.
|
||||
@param length The number of bytes to read. For devices with
|
||||
multiple reports, make sure to read an extra byte for
|
||||
@@ -235,7 +237,7 @@ namespace NAMESPACE {
|
||||
-1 on error. If no packet was available to be read within
|
||||
the timeout period, this function returns 0.
|
||||
*/
|
||||
int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *device, unsigned char *data, size_t length, int milliseconds);
|
||||
int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds);
|
||||
|
||||
/** @brief Read an Input report from a HID device.
|
||||
|
||||
@@ -244,7 +246,7 @@ namespace NAMESPACE {
|
||||
contain the Report number if the device uses numbered reports.
|
||||
|
||||
@ingroup API
|
||||
@param device A device handle returned from hid_open().
|
||||
@param dev A device handle returned from hid_open().
|
||||
@param data A buffer to put the read data into.
|
||||
@param length The number of bytes to read. For devices with
|
||||
multiple reports, make sure to read an extra byte for
|
||||
@@ -255,7 +257,7 @@ namespace NAMESPACE {
|
||||
-1 on error. If no packet was available to be read and
|
||||
the handle is in non-blocking mode, this function returns 0.
|
||||
*/
|
||||
int HID_API_EXPORT HID_API_CALL hid_read(hid_device *device, unsigned char *data, size_t length);
|
||||
int HID_API_EXPORT HID_API_CALL hid_read(hid_device *dev, unsigned char *data, size_t length);
|
||||
|
||||
/** @brief Set the device handle to be non-blocking.
|
||||
|
||||
@@ -267,7 +269,7 @@ namespace NAMESPACE {
|
||||
Nonblocking can be turned on and off at any time.
|
||||
|
||||
@ingroup API
|
||||
@param device A device handle returned from hid_open().
|
||||
@param dev A device handle returned from hid_open().
|
||||
@param nonblock enable or not the nonblocking reads
|
||||
- 1 to enable nonblocking
|
||||
- 0 to disable nonblocking.
|
||||
@@ -275,7 +277,7 @@ namespace NAMESPACE {
|
||||
@returns
|
||||
This function returns 0 on success and -1 on error.
|
||||
*/
|
||||
int HID_API_EXPORT HID_API_CALL hid_set_nonblocking(hid_device *device, int nonblock);
|
||||
int HID_API_EXPORT HID_API_CALL hid_set_nonblocking(hid_device *dev, int nonblock);
|
||||
|
||||
/** @brief Send a Feature report to the device.
|
||||
|
||||
@@ -293,7 +295,7 @@ namespace NAMESPACE {
|
||||
in would be 17.
|
||||
|
||||
@ingroup API
|
||||
@param device A device handle returned from hid_open().
|
||||
@param dev A device handle returned from hid_open().
|
||||
@param data The data to send, including the report number as
|
||||
the first byte.
|
||||
@param length The length in bytes of the data to send, including
|
||||
@@ -303,7 +305,7 @@ namespace NAMESPACE {
|
||||
This function returns the actual number of bytes written and
|
||||
-1 on error.
|
||||
*/
|
||||
int HID_API_EXPORT HID_API_CALL hid_send_feature_report(hid_device *device, const unsigned char *data, size_t length);
|
||||
int HID_API_EXPORT HID_API_CALL hid_send_feature_report(hid_device *dev, const unsigned char *data, size_t length);
|
||||
|
||||
/** @brief Get a feature report from a HID device.
|
||||
|
||||
@@ -314,7 +316,7 @@ namespace NAMESPACE {
|
||||
start in data[1].
|
||||
|
||||
@ingroup API
|
||||
@param device A device handle returned from hid_open().
|
||||
@param dev A device handle returned from hid_open().
|
||||
@param data A buffer to put the read data into, including
|
||||
the Report ID. Set the first byte of @p data[] to the
|
||||
Report ID of the report to be read, or set it to zero
|
||||
@@ -328,55 +330,55 @@ namespace NAMESPACE {
|
||||
one for the report ID (which is still in the first
|
||||
byte), or -1 on error.
|
||||
*/
|
||||
int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *device, unsigned char *data, size_t length);
|
||||
int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *dev, unsigned char *data, size_t length);
|
||||
|
||||
/** @brief Close a HID device.
|
||||
|
||||
@ingroup API
|
||||
@param device A device handle returned from hid_open().
|
||||
@param dev A device handle returned from hid_open().
|
||||
*/
|
||||
void HID_API_EXPORT HID_API_CALL hid_close(hid_device *device);
|
||||
void HID_API_EXPORT HID_API_CALL hid_close(hid_device *dev);
|
||||
|
||||
/** @brief Get The Manufacturer String from a HID device.
|
||||
|
||||
@ingroup API
|
||||
@param device A device handle returned from hid_open().
|
||||
@param dev A device handle returned from hid_open().
|
||||
@param string A wide string buffer to put the data into.
|
||||
@param maxlen The length of the buffer in multiples of wchar_t.
|
||||
|
||||
@returns
|
||||
This function returns 0 on success and -1 on error.
|
||||
*/
|
||||
int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *device, wchar_t *string, size_t maxlen);
|
||||
int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *string, size_t maxlen);
|
||||
|
||||
/** @brief Get The Product String from a HID device.
|
||||
|
||||
@ingroup API
|
||||
@param device A device handle returned from hid_open().
|
||||
@param dev A device handle returned from hid_open().
|
||||
@param string A wide string buffer to put the data into.
|
||||
@param maxlen The length of the buffer in multiples of wchar_t.
|
||||
|
||||
@returns
|
||||
This function returns 0 on success and -1 on error.
|
||||
*/
|
||||
int HID_API_EXPORT_CALL hid_get_product_string(hid_device *device, wchar_t *string, size_t maxlen);
|
||||
int HID_API_EXPORT_CALL hid_get_product_string(hid_device *dev, wchar_t *string, size_t maxlen);
|
||||
|
||||
/** @brief Get The Serial Number String from a HID device.
|
||||
|
||||
@ingroup API
|
||||
@param device A device handle returned from hid_open().
|
||||
@param dev A device handle returned from hid_open().
|
||||
@param string A wide string buffer to put the data into.
|
||||
@param maxlen The length of the buffer in multiples of wchar_t.
|
||||
|
||||
@returns
|
||||
This function returns 0 on success and -1 on error.
|
||||
*/
|
||||
int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *device, wchar_t *string, size_t maxlen);
|
||||
int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *string, size_t maxlen);
|
||||
|
||||
/** @brief Get a string from a HID device, based on its string index.
|
||||
|
||||
@ingroup API
|
||||
@param device A device handle returned from hid_open().
|
||||
@param dev A device handle returned from hid_open().
|
||||
@param string_index The index of the string to get.
|
||||
@param string A wide string buffer to put the data into.
|
||||
@param maxlen The length of the buffer in multiples of wchar_t.
|
||||
@@ -384,18 +386,18 @@ namespace NAMESPACE {
|
||||
@returns
|
||||
This function returns 0 on success and -1 on error.
|
||||
*/
|
||||
int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *device, int string_index, wchar_t *string, size_t maxlen);
|
||||
int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *dev, int string_index, wchar_t *string, size_t maxlen);
|
||||
|
||||
/** @brief Get a string describing the last error which occurred.
|
||||
|
||||
@ingroup API
|
||||
@param device A device handle returned from hid_open().
|
||||
@param dev A device handle returned from hid_open().
|
||||
|
||||
@returns
|
||||
This function returns a string containing the last error
|
||||
which occurred or NULL if none has occurred.
|
||||
*/
|
||||
HID_API_EXPORT const wchar_t* HID_API_CALL hid_error(hid_device *device);
|
||||
HID_API_EXPORT const wchar_t* HID_API_CALL hid_error(hid_device *dev);
|
||||
|
||||
#if defined(__cplusplus) && !defined(NAMESPACE)
|
||||
}
|
||||
|
25
externals/SDL/src/hidapi/ios/hid.m
vendored
25
externals/SDL/src/hidapi/ios/hid.m
vendored
@@ -1,8 +1,23 @@
|
||||
//======== Copyright (c) 2017 Valve Corporation, All rights reserved. =========
|
||||
//
|
||||
// Purpose: HID device abstraction temporary stub
|
||||
//
|
||||
//=============================================================================
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 2021 Valve Corporation
|
||||
|
||||
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.
|
||||
*/
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#ifdef SDL_JOYSTICK_HIDAPI
|
||||
|
170
externals/SDL/src/hidapi/libusb/hid.c
vendored
170
externals/SDL/src/hidapi/libusb/hid.c
vendored
@@ -33,6 +33,10 @@
|
||||
|
||||
#ifdef SDL_JOYSTICK_HIDAPI
|
||||
|
||||
#if defined(HAVE__WCSDUP) && !defined(HAVE_WCSDUP)
|
||||
#define wcsdup _wcsdup
|
||||
#endif
|
||||
|
||||
#include <libusb.h>
|
||||
#include <locale.h> /* setlocale */
|
||||
|
||||
@@ -157,7 +161,7 @@ struct hid_device_ {
|
||||
SDL_cond *condition;
|
||||
SDL_ThreadBarrier barrier; /* Ensures correct startup sequence */
|
||||
int shutdown_thread;
|
||||
int cancelled;
|
||||
int transfer_loop_finished;
|
||||
struct libusb_transfer *transfer;
|
||||
|
||||
/* List of received input reports. */
|
||||
@@ -196,7 +200,6 @@ static void free_hid_device(hid_device *dev)
|
||||
/*TODO: Implement this function on hidapi/libusb.. */
|
||||
static void register_error(hid_device *dev, const char *op)
|
||||
{
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -320,7 +323,6 @@ static inline int libusb_get_string_descriptor(libusb_device_handle *dev,
|
||||
(LIBUSB_DT_STRING << 8) | descriptor_index,
|
||||
lang_id, data, (uint16_t) length, 1000);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -438,6 +440,94 @@ err:
|
||||
return str;
|
||||
}
|
||||
|
||||
struct usb_string_cache_entry {
|
||||
uint16_t vid;
|
||||
uint16_t pid;
|
||||
wchar_t *vendor;
|
||||
wchar_t *product;
|
||||
};
|
||||
|
||||
static struct usb_string_cache_entry *usb_string_cache = NULL;
|
||||
static size_t usb_string_cache_size = 0;
|
||||
static size_t usb_string_cache_insert_pos = 0;
|
||||
|
||||
static int usb_string_cache_grow()
|
||||
{
|
||||
struct usb_string_cache_entry *new_cache;
|
||||
size_t allocSize;
|
||||
size_t new_cache_size;
|
||||
|
||||
new_cache_size = usb_string_cache_size + 8;
|
||||
allocSize = sizeof(struct usb_string_cache_entry) * new_cache_size;
|
||||
new_cache = (struct usb_string_cache_entry *)realloc(usb_string_cache, allocSize);
|
||||
if (!new_cache)
|
||||
return -1;
|
||||
|
||||
usb_string_cache = new_cache;
|
||||
usb_string_cache_size = new_cache_size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void usb_string_cache_destroy()
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < usb_string_cache_insert_pos; i++) {
|
||||
free(usb_string_cache[i].vendor);
|
||||
free(usb_string_cache[i].product);
|
||||
}
|
||||
free(usb_string_cache);
|
||||
|
||||
usb_string_cache = NULL;
|
||||
usb_string_cache_size = 0;
|
||||
}
|
||||
|
||||
static struct usb_string_cache_entry *usb_string_cache_insert()
|
||||
{
|
||||
struct usb_string_cache_entry *new_entry = NULL;
|
||||
if (usb_string_cache_insert_pos >= usb_string_cache_size) {
|
||||
if (usb_string_cache_grow() < 0)
|
||||
return NULL;
|
||||
}
|
||||
new_entry = &usb_string_cache[usb_string_cache_insert_pos];
|
||||
usb_string_cache_insert_pos++;
|
||||
return new_entry;
|
||||
}
|
||||
|
||||
static const struct usb_string_cache_entry *usb_string_cache_find(struct libusb_device_descriptor *desc, struct libusb_device_handle *handle)
|
||||
{
|
||||
struct usb_string_cache_entry *entry = NULL;
|
||||
size_t i;
|
||||
|
||||
/* Search for existing string cache entry */
|
||||
for (i = 0; i < usb_string_cache_insert_pos; i++) {
|
||||
entry = &usb_string_cache[i];
|
||||
if (entry->vid != desc->idVendor)
|
||||
continue;
|
||||
if (entry->pid != desc->idProduct)
|
||||
continue;
|
||||
return entry;
|
||||
}
|
||||
|
||||
/* Not found, create one. */
|
||||
entry = usb_string_cache_insert();
|
||||
if (!entry)
|
||||
return NULL;
|
||||
|
||||
entry->vid = desc->idVendor;
|
||||
entry->pid = desc->idProduct;
|
||||
if (desc->iManufacturer > 0)
|
||||
entry->vendor = get_usb_string(handle, desc->iManufacturer);
|
||||
else
|
||||
entry->vendor = NULL;
|
||||
if (desc->iProduct > 0)
|
||||
entry->product = get_usb_string(handle, desc->iProduct);
|
||||
else
|
||||
entry->product = NULL;
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
static char *make_path(libusb_device *dev, int interface_number)
|
||||
{
|
||||
char str[64];
|
||||
@@ -471,6 +561,8 @@ int HID_API_EXPORT hid_init(void)
|
||||
|
||||
int HID_API_EXPORT hid_exit(void)
|
||||
{
|
||||
usb_string_cache_destroy();
|
||||
|
||||
if (usb_context) {
|
||||
libusb_exit(usb_context);
|
||||
usb_context = NULL;
|
||||
@@ -504,7 +596,9 @@ static int is_xbox360(unsigned short vendor_id, const struct libusb_interface_de
|
||||
0x15e4, /* Numark */
|
||||
0x162e, /* Joytech */
|
||||
0x1689, /* Razer Onza */
|
||||
0x1949, /* Lab126, Inc. */
|
||||
0x1bad, /* Harmonix */
|
||||
0x20d6, /* PowerA */
|
||||
0x24c6, /* PowerA */
|
||||
};
|
||||
|
||||
@@ -524,17 +618,18 @@ static int is_xbox360(unsigned short vendor_id, const struct libusb_interface_de
|
||||
|
||||
static int is_xboxone(unsigned short vendor_id, const struct libusb_interface_descriptor *intf_desc)
|
||||
{
|
||||
static const int XB1_IFACE_SUBCLASS = 71;
|
||||
static const int XB1_IFACE_PROTOCOL = 208;
|
||||
static const int SUPPORTED_VENDORS[] = {
|
||||
0x045e, /* Microsoft */
|
||||
0x0738, /* Mad Catz */
|
||||
0x0e6f, /* PDP */
|
||||
0x0f0d, /* Hori */
|
||||
0x1532, /* Razer Wildcat */
|
||||
0x24c6, /* PowerA */
|
||||
0x2e24, /* Hyperkin */
|
||||
};
|
||||
static const int XB1_IFACE_SUBCLASS = 71;
|
||||
static const int XB1_IFACE_PROTOCOL = 208;
|
||||
static const int SUPPORTED_VENDORS[] = {
|
||||
0x045e, /* Microsoft */
|
||||
0x0738, /* Mad Catz */
|
||||
0x0e6f, /* PDP */
|
||||
0x0f0d, /* Hori */
|
||||
0x1532, /* Razer Wildcat */
|
||||
0x20d6, /* PowerA */
|
||||
0x24c6, /* PowerA */
|
||||
0x2e24, /* Hyperkin */
|
||||
};
|
||||
|
||||
if (intf_desc->bInterfaceNumber == 0 &&
|
||||
intf_desc->bInterfaceClass == LIBUSB_CLASS_VENDOR_SPEC &&
|
||||
@@ -612,6 +707,7 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id,
|
||||
|
||||
if (res >= 0) {
|
||||
struct hid_device_info *tmp;
|
||||
const struct usb_string_cache_entry *string_cache;
|
||||
|
||||
/* VID/PID match. Create the record. */
|
||||
tmp = (struct hid_device_info*) calloc(1, sizeof(struct hid_device_info));
|
||||
@@ -633,12 +729,20 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id,
|
||||
get_usb_string(handle, desc.iSerialNumber);
|
||||
|
||||
/* Manufacturer and Product strings */
|
||||
if (desc.iManufacturer > 0)
|
||||
cur_dev->manufacturer_string =
|
||||
get_usb_string(handle, desc.iManufacturer);
|
||||
if (desc.iProduct > 0)
|
||||
cur_dev->product_string =
|
||||
get_usb_string(handle, desc.iProduct);
|
||||
if (dev_vid && dev_pid) {
|
||||
string_cache = usb_string_cache_find(&desc, handle);
|
||||
if (string_cache) {
|
||||
cur_dev->manufacturer_string = wcsdup(string_cache->vendor);
|
||||
cur_dev->product_string = wcsdup(string_cache->product);
|
||||
}
|
||||
} else {
|
||||
if (desc.iManufacturer > 0)
|
||||
cur_dev->manufacturer_string =
|
||||
get_usb_string(handle, desc.iManufacturer);
|
||||
if (desc.iProduct > 0)
|
||||
cur_dev->product_string =
|
||||
get_usb_string(handle, desc.iProduct);
|
||||
}
|
||||
|
||||
#ifdef INVASIVE_GET_USAGE
|
||||
{
|
||||
@@ -825,13 +929,9 @@ static void LIBUSB_CALL read_callback(struct libusb_transfer *transfer)
|
||||
}
|
||||
else if (transfer->status == LIBUSB_TRANSFER_CANCELLED) {
|
||||
dev->shutdown_thread = 1;
|
||||
dev->cancelled = 1;
|
||||
return;
|
||||
}
|
||||
else if (transfer->status == LIBUSB_TRANSFER_NO_DEVICE) {
|
||||
dev->shutdown_thread = 1;
|
||||
dev->cancelled = 1;
|
||||
return;
|
||||
}
|
||||
else if (transfer->status == LIBUSB_TRANSFER_TIMED_OUT) {
|
||||
//LOG("Timeout (normal)\n");
|
||||
@@ -840,12 +940,17 @@ static void LIBUSB_CALL read_callback(struct libusb_transfer *transfer)
|
||||
LOG("Unknown transfer code: %d\n", transfer->status);
|
||||
}
|
||||
|
||||
if (dev->shutdown_thread) {
|
||||
dev->transfer_loop_finished = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Re-submit the transfer object. */
|
||||
res = libusb_submit_transfer(transfer);
|
||||
if (res != 0) {
|
||||
LOG("Unable to submit URB. libusb error code: %d\n", res);
|
||||
dev->shutdown_thread = 1;
|
||||
dev->cancelled = 1;
|
||||
dev->transfer_loop_finished = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -888,6 +993,7 @@ static int read_thread(void *param)
|
||||
res != LIBUSB_ERROR_TIMEOUT &&
|
||||
res != LIBUSB_ERROR_OVERFLOW &&
|
||||
res != LIBUSB_ERROR_INTERRUPTED) {
|
||||
dev->shutdown_thread = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -897,8 +1003,8 @@ static int read_thread(void *param)
|
||||
if no transfers are pending, but that's OK. */
|
||||
libusb_cancel_transfer(dev->transfer);
|
||||
|
||||
while (!dev->cancelled)
|
||||
libusb_handle_events_completed(usb_context, &dev->cancelled);
|
||||
while (!dev->transfer_loop_finished)
|
||||
libusb_handle_events_completed(usb_context, &dev->transfer_loop_finished);
|
||||
|
||||
/* Now that the read thread is stopping, Wake any threads which are
|
||||
waiting on data (in hid_read_timeout()). Do this under a mutex to
|
||||
@@ -922,8 +1028,8 @@ static int read_thread(void *param)
|
||||
|
||||
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;
|
||||
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++) {
|
||||
@@ -1173,21 +1279,21 @@ static void cleanup_mutex(void *param)
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds)
|
||||
{
|
||||
int bytes_read = -1;
|
||||
|
||||
#if 0
|
||||
int transferred;
|
||||
int res = libusb_interrupt_transfer(dev->device_handle, dev->input_endpoint, data, length, &transferred, 5000);
|
||||
LOG("transferred: %d\n", transferred);
|
||||
return transferred;
|
||||
#endif
|
||||
int bytes_read;
|
||||
|
||||
SDL_LockMutex(dev->mutex);
|
||||
/* TODO: pthread_cleanup SDL? */
|
||||
|
||||
bytes_read = -1;
|
||||
|
||||
/* There's an input report queued up. Return it. */
|
||||
if (dev->input_reports) {
|
||||
/* Return the first one */
|
||||
|
8
externals/SDL/src/hidapi/mac/hid.c
vendored
8
externals/SDL/src/hidapi/mac/hid.c
vendored
@@ -251,7 +251,10 @@ static int get_string_property(IOHIDDeviceRef device, CFStringRef prop, wchar_t
|
||||
|
||||
if (!len)
|
||||
return 0;
|
||||
|
||||
|
||||
if (CFGetTypeID(prop) != CFStringGetTypeID())
|
||||
return 0;
|
||||
|
||||
str = (CFStringRef)IOHIDDeviceGetProperty(device, prop);
|
||||
|
||||
buf[0] = 0;
|
||||
@@ -288,6 +291,9 @@ static int get_string_property_utf8(IOHIDDeviceRef device, CFStringRef prop, cha
|
||||
if (!len)
|
||||
return 0;
|
||||
|
||||
if (CFGetTypeID(prop) != CFStringGetTypeID())
|
||||
return 0;
|
||||
|
||||
str = (CFStringRef)IOHIDDeviceGetProperty(device, prop);
|
||||
|
||||
buf[0] = 0;
|
||||
|
141
externals/SDL/src/hidapi/windows/hid.c
vendored
141
externals/SDL/src/hidapi/windows/hid.c
vendored
@@ -25,6 +25,10 @@
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#ifndef _WIN32_WINNT_WIN8
|
||||
#define _WIN32_WINNT_WIN8 0x0602
|
||||
#endif
|
||||
|
||||
#if 0 /* can cause redefinition errors on some toolchains */
|
||||
#ifdef __MINGW32__
|
||||
#include <ntdef.h>
|
||||
@@ -105,6 +109,9 @@ extern "C" {
|
||||
#ifdef _MSC_VER
|
||||
/* Thanks Microsoft, but I know how to use strncpy(). */
|
||||
#pragma warning(disable:4996)
|
||||
|
||||
/* Yes, we have some unreferenced formal parameters */
|
||||
#pragma warning(disable:4100)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -176,8 +183,29 @@ struct hid_device_ {
|
||||
char *read_buf;
|
||||
OVERLAPPED ol;
|
||||
OVERLAPPED write_ol;
|
||||
BOOL use_hid_write_output_report;
|
||||
};
|
||||
|
||||
static BOOL
|
||||
IsWindowsVersionOrGreater(WORD wMajorVersion, WORD wMinorVersion, WORD wServicePackMajor)
|
||||
{
|
||||
OSVERSIONINFOEXW osvi;
|
||||
DWORDLONG const dwlConditionMask = VerSetConditionMask(
|
||||
VerSetConditionMask(
|
||||
VerSetConditionMask(
|
||||
0, VER_MAJORVERSION, VER_GREATER_EQUAL ),
|
||||
VER_MINORVERSION, VER_GREATER_EQUAL ),
|
||||
VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL );
|
||||
|
||||
memset(&osvi, 0, sizeof(osvi));
|
||||
osvi.dwOSVersionInfoSize = sizeof( osvi );
|
||||
osvi.dwMajorVersion = wMajorVersion;
|
||||
osvi.dwMinorVersion = wMinorVersion;
|
||||
osvi.wServicePackMajor = wServicePackMajor;
|
||||
|
||||
return VerifyVersionInfoW(&osvi, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR, dwlConditionMask) != FALSE;
|
||||
}
|
||||
|
||||
static hid_device *new_hid_device()
|
||||
{
|
||||
hid_device *dev = (hid_device*) calloc(1, sizeof(hid_device));
|
||||
@@ -242,7 +270,7 @@ static void register_error(hid_device *device, const char *op)
|
||||
#ifndef HIDAPI_USE_DDK
|
||||
static int lookup_functions()
|
||||
{
|
||||
lib_handle = LoadLibraryA("hid.dll");
|
||||
lib_handle = LoadLibrary(TEXT("hid.dll"));
|
||||
if (lib_handle) {
|
||||
#define RESOLVE(x) x = (x##_)GetProcAddress(lib_handle, #x); if (!x) return -1;
|
||||
RESOLVE(HidD_GetAttributes);
|
||||
@@ -321,6 +349,7 @@ int hid_blacklist(unsigned short vendor_id, unsigned short product_id)
|
||||
{ 0x1532, 0x0109 }, /* Razer Lycosa Gaming keyboard */
|
||||
{ 0x1532, 0x010B }, /* Razer Arctosa Gaming keyboard */
|
||||
{ 0x045E, 0x0822 }, /* Microsoft Precision Mouse */
|
||||
{ 0x0D8C, 0x0014 }, /* Sharkoon Skiller SGH2 headset */
|
||||
|
||||
/* Turns into an Android controller when enumerated... */
|
||||
{ 0x0738, 0x2217 } /* SPEEDLINK COMPETITION PRO */
|
||||
@@ -692,6 +721,11 @@ HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path, int bEx
|
||||
dev->input_report_length = caps.InputReportByteLength;
|
||||
HidD_FreePreparsedData(pp_data);
|
||||
|
||||
/* On Windows 7, we need to use hid_write_output_report() over Bluetooth */
|
||||
if (dev->output_report_length > 512) {
|
||||
dev->use_hid_write_output_report = !IsWindowsVersionOrGreater( HIBYTE( _WIN32_WINNT_WIN8 ), LOBYTE( _WIN32_WINNT_WIN8 ), 0 );
|
||||
}
|
||||
|
||||
dev->read_buf = (char*) malloc(dev->input_report_length);
|
||||
|
||||
return dev;
|
||||
@@ -717,17 +751,12 @@ static int hid_write_timeout(hid_device *dev, const unsigned char *data, size_t
|
||||
{
|
||||
DWORD bytes_written;
|
||||
BOOL res;
|
||||
size_t stashed_length = length;
|
||||
unsigned char *buf;
|
||||
|
||||
#if 1
|
||||
/* If the application is writing to the device, it knows how much data to write.
|
||||
* This matches the behavior on other platforms. It's also important when writing
|
||||
* to Sony game controllers over Bluetooth, where there's a CRC at the end which
|
||||
* must not be tampered with.
|
||||
*/
|
||||
buf = (unsigned char *) data;
|
||||
#else
|
||||
if (dev->use_hid_write_output_report) {
|
||||
return hid_write_output_report(dev, data, length);
|
||||
}
|
||||
|
||||
/* Make sure the right number of bytes are passed to WriteFile. Windows
|
||||
expects the number of bytes which are in the _longest_ report (plus
|
||||
one for the report number) bytes even if the data is a report
|
||||
@@ -745,42 +774,35 @@ static int hid_write_timeout(hid_device *dev, const unsigned char *data, size_t
|
||||
memset(buf + length, 0, dev->output_report_length - length);
|
||||
length = dev->output_report_length;
|
||||
}
|
||||
#endif
|
||||
if (length > 512)
|
||||
{
|
||||
return hid_write_output_report( dev, data, stashed_length );
|
||||
}
|
||||
else
|
||||
{
|
||||
res = WriteFile( dev->device_handle, buf, ( DWORD ) length, NULL, &dev->write_ol );
|
||||
if (!res) {
|
||||
if (GetLastError() != ERROR_IO_PENDING) {
|
||||
/* WriteFile() failed. Return error. */
|
||||
register_error(dev, "WriteFile");
|
||||
bytes_written = (DWORD) -1;
|
||||
goto end_of_function;
|
||||
}
|
||||
}
|
||||
|
||||
/* Wait here until the write is done. This makes
|
||||
hid_write() synchronous. */
|
||||
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. */
|
||||
res = WriteFile( dev->device_handle, buf, ( DWORD ) length, NULL, &dev->write_ol );
|
||||
if (!res) {
|
||||
if (GetLastError() != ERROR_IO_PENDING) {
|
||||
/* WriteFile() failed. Return error. */
|
||||
register_error(dev, "WriteFile");
|
||||
bytes_written = (DWORD) -1;
|
||||
goto end_of_function;
|
||||
}
|
||||
}
|
||||
|
||||
/* Wait here until the write is done. This makes hid_write() synchronous. */
|
||||
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");
|
||||
bytes_written = (DWORD) -1;
|
||||
goto end_of_function;
|
||||
}
|
||||
|
||||
end_of_function:
|
||||
if (buf != data)
|
||||
free(buf);
|
||||
@@ -820,20 +842,19 @@ int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char
|
||||
}
|
||||
}
|
||||
|
||||
if (milliseconds >= 0) {
|
||||
/* See if there is any data yet. */
|
||||
res = WaitForSingleObject(ev, milliseconds);
|
||||
if (res != WAIT_OBJECT_0) {
|
||||
/* There was no data this time. Return zero bytes available,
|
||||
but leave the Overlapped I/O running. */
|
||||
return 0;
|
||||
}
|
||||
/* See if there is any data yet. */
|
||||
res = WaitForSingleObject(ev, milliseconds >= 0 ? milliseconds : INFINITE);
|
||||
if (res != WAIT_OBJECT_0) {
|
||||
/* There was no data this time. Return zero bytes available,
|
||||
but leave the Overlapped I/O running. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Either WaitForSingleObject() told us that ReadFile has completed, or
|
||||
we are in non-blocking mode. Get the number of bytes read. The actual
|
||||
data has been copied to the data[] array which was passed to ReadFile(). */
|
||||
res = GetOverlappedResult(dev->device_handle, &dev->ol, &bytes_read, TRUE/*wait*/);
|
||||
/* Get the number of bytes read. The actual data has been copied to the data[]
|
||||
array which was passed to ReadFile(). We must not wait here because we've
|
||||
already waited on our event above, and since it's auto-reset, it will have
|
||||
been reset back to unsignalled by now. */
|
||||
res = GetOverlappedResult(dev->device_handle, &dev->ol, &bytes_read, FALSE/*don't wait*/);
|
||||
|
||||
/* Set pending back to false, even if GetOverlappedResult() returned error. */
|
||||
dev->read_pending = FALSE;
|
||||
@@ -932,9 +953,23 @@ int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *dev, unsigned
|
||||
|
||||
void HID_API_EXPORT HID_API_CALL hid_close(hid_device *dev)
|
||||
{
|
||||
typedef BOOL (WINAPI *CancelIoEx_t)(HANDLE hFile, LPOVERLAPPED lpOverlapped);
|
||||
CancelIoEx_t CancelIoExFunc = (CancelIoEx_t)GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "CancelIoEx");
|
||||
|
||||
if (!dev)
|
||||
return;
|
||||
CancelIo(dev->device_handle);
|
||||
|
||||
if (CancelIoExFunc) {
|
||||
CancelIoExFunc(dev->device_handle, NULL);
|
||||
} else {
|
||||
/* Windows XP, this will only cancel I/O on the current thread */
|
||||
CancelIo(dev->device_handle);
|
||||
}
|
||||
if (dev->read_pending) {
|
||||
DWORD bytes_read = 0;
|
||||
|
||||
GetOverlappedResult(dev->device_handle, &dev->ol, &bytes_read, TRUE/*wait*/);
|
||||
}
|
||||
free_hid_device(dev);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user