Update hidapi
This commit is contained in:
parent
e4d9344d2a
commit
8fea1ea42e
@ -1,2 +1 @@
|
|||||||
http://www.signal11.us/oss/hidapi/
|
hidapi-0.14.0-35-gc3c79a7 (2024-08-21) from https://github.com/libusb/hidapi
|
||||||
hidapi-0.8.0-rc1-21-ga6a622f (2016-01-08) from https://github.com/signal11/hidapi
|
|
||||||
|
@ -5,9 +5,9 @@
|
|||||||
Alan Ott
|
Alan Ott
|
||||||
Signal 11 Software
|
Signal 11 Software
|
||||||
|
|
||||||
8/22/2009
|
libusb/hidapi Team
|
||||||
|
|
||||||
Copyright 2009, All Rights Reserved.
|
Copyright 2023, All Rights Reserved.
|
||||||
|
|
||||||
At the discretion of the user of this library,
|
At the discretion of the user of this library,
|
||||||
this software may be licensed under the terms of the
|
this software may be licensed under the terms of the
|
||||||
@ -17,7 +17,7 @@
|
|||||||
files located at the root of the source distribution.
|
files located at the root of the source distribution.
|
||||||
These files may also be found in the public source
|
These files may also be found in the public source
|
||||||
code repository located at:
|
code repository located at:
|
||||||
http://github.com/signal11/hidapi .
|
https://github.com/libusb/hidapi .
|
||||||
********************************************************/
|
********************************************************/
|
||||||
|
|
||||||
/** @file
|
/** @file
|
||||||
@ -29,22 +29,123 @@
|
|||||||
|
|
||||||
#include <wchar.h>
|
#include <wchar.h>
|
||||||
|
|
||||||
#if 0 // XXX we compile hidapi as static library
|
/* #480: this is to be refactored properly for v1.0 */
|
||||||
|
#ifdef _WIN32
|
||||||
|
#ifndef HID_API_NO_EXPORT_DEFINE
|
||||||
#define HID_API_EXPORT __declspec(dllexport)
|
#define HID_API_EXPORT __declspec(dllexport)
|
||||||
#define HID_API_CALL
|
#endif
|
||||||
#else
|
|
||||||
#define HID_API_EXPORT /**< API export macro */
|
|
||||||
#define HID_API_CALL /**< API call macro */
|
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef HID_API_EXPORT
|
||||||
|
#define HID_API_EXPORT /**< API export macro */
|
||||||
|
#endif
|
||||||
|
/* To be removed in v1.0 */
|
||||||
|
#define HID_API_CALL /**< API call macro */
|
||||||
|
|
||||||
#define HID_API_EXPORT_CALL HID_API_EXPORT HID_API_CALL /**< API export and call macro*/
|
#define HID_API_EXPORT_CALL HID_API_EXPORT HID_API_CALL /**< API export and call macro*/
|
||||||
|
|
||||||
|
/** @brief Static/compile-time major version of the library.
|
||||||
|
|
||||||
|
@ingroup API
|
||||||
|
*/
|
||||||
|
#define HID_API_VERSION_MAJOR 0
|
||||||
|
/** @brief Static/compile-time minor version of the library.
|
||||||
|
|
||||||
|
@ingroup API
|
||||||
|
*/
|
||||||
|
#define HID_API_VERSION_MINOR 15
|
||||||
|
/** @brief Static/compile-time patch version of the library.
|
||||||
|
|
||||||
|
@ingroup API
|
||||||
|
*/
|
||||||
|
#define HID_API_VERSION_PATCH 0
|
||||||
|
|
||||||
|
/* Helper macros */
|
||||||
|
#define HID_API_AS_STR_IMPL(x) #x
|
||||||
|
#define HID_API_AS_STR(x) HID_API_AS_STR_IMPL(x)
|
||||||
|
#define HID_API_TO_VERSION_STR(v1, v2, v3) HID_API_AS_STR(v1.v2.v3)
|
||||||
|
|
||||||
|
/** @brief Coverts a version as Major/Minor/Patch into a number:
|
||||||
|
<8 bit major><16 bit minor><8 bit patch>.
|
||||||
|
|
||||||
|
This macro was added in version 0.12.0.
|
||||||
|
|
||||||
|
Convenient function to be used for compile-time checks, like:
|
||||||
|
@code{.c}
|
||||||
|
#if HID_API_VERSION >= HID_API_MAKE_VERSION(0, 12, 0)
|
||||||
|
@endcode
|
||||||
|
|
||||||
|
@ingroup API
|
||||||
|
*/
|
||||||
|
#define HID_API_MAKE_VERSION(mj, mn, p) (((mj) << 24) | ((mn) << 8) | (p))
|
||||||
|
|
||||||
|
/** @brief Static/compile-time version of the library.
|
||||||
|
|
||||||
|
This macro was added in version 0.12.0.
|
||||||
|
|
||||||
|
@see @ref HID_API_MAKE_VERSION.
|
||||||
|
|
||||||
|
@ingroup API
|
||||||
|
*/
|
||||||
|
#define HID_API_VERSION HID_API_MAKE_VERSION(HID_API_VERSION_MAJOR, HID_API_VERSION_MINOR, HID_API_VERSION_PATCH)
|
||||||
|
|
||||||
|
/** @brief Static/compile-time string version of the library.
|
||||||
|
|
||||||
|
@ingroup API
|
||||||
|
*/
|
||||||
|
#define HID_API_VERSION_STR HID_API_TO_VERSION_STR(HID_API_VERSION_MAJOR, HID_API_VERSION_MINOR, HID_API_VERSION_PATCH)
|
||||||
|
|
||||||
|
/** @brief Maximum expected HID Report descriptor size in bytes.
|
||||||
|
|
||||||
|
Since version 0.13.0, @ref HID_API_VERSION >= HID_API_MAKE_VERSION(0, 13, 0)
|
||||||
|
|
||||||
|
@ingroup API
|
||||||
|
*/
|
||||||
|
#define HID_API_MAX_REPORT_DESCRIPTOR_SIZE 4096
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
/** A structure to hold the version numbers. */
|
||||||
|
struct hid_api_version {
|
||||||
|
int major; /**< major version number */
|
||||||
|
int minor; /**< minor version number */
|
||||||
|
int patch; /**< patch version number */
|
||||||
|
};
|
||||||
|
|
||||||
struct hid_device_;
|
struct hid_device_;
|
||||||
typedef struct hid_device_ hid_device; /**< opaque hidapi structure */
|
typedef struct hid_device_ hid_device; /**< opaque hidapi structure */
|
||||||
|
|
||||||
|
/** @brief HID underlying bus types.
|
||||||
|
|
||||||
|
@ingroup API
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
/** Unknown bus type */
|
||||||
|
HID_API_BUS_UNKNOWN = 0x00,
|
||||||
|
|
||||||
|
/** USB bus
|
||||||
|
Specifications:
|
||||||
|
https://usb.org/hid */
|
||||||
|
HID_API_BUS_USB = 0x01,
|
||||||
|
|
||||||
|
/** Bluetooth or Bluetooth LE bus
|
||||||
|
Specifications:
|
||||||
|
https://www.bluetooth.com/specifications/specs/human-interface-device-profile-1-1-1/
|
||||||
|
https://www.bluetooth.com/specifications/specs/hid-service-1-0/
|
||||||
|
https://www.bluetooth.com/specifications/specs/hid-over-gatt-profile-1-0/ */
|
||||||
|
HID_API_BUS_BLUETOOTH = 0x02,
|
||||||
|
|
||||||
|
/** I2C bus
|
||||||
|
Specifications:
|
||||||
|
https://docs.microsoft.com/previous-versions/windows/hardware/design/dn642101(v=vs.85) */
|
||||||
|
HID_API_BUS_I2C = 0x03,
|
||||||
|
|
||||||
|
/** SPI bus
|
||||||
|
Specifications:
|
||||||
|
https://www.microsoft.com/download/details.aspx?id=103325 */
|
||||||
|
HID_API_BUS_SPI = 0x04,
|
||||||
|
} hid_bus_type;
|
||||||
|
|
||||||
/** hidapi info structure */
|
/** hidapi info structure */
|
||||||
struct hid_device_info {
|
struct hid_device_info {
|
||||||
/** Platform-specific device path */
|
/** Platform-specific device path */
|
||||||
@ -63,19 +164,26 @@ extern "C" {
|
|||||||
/** Product string */
|
/** Product string */
|
||||||
wchar_t *product_string;
|
wchar_t *product_string;
|
||||||
/** Usage Page for this Device/Interface
|
/** Usage Page for this Device/Interface
|
||||||
(Windows/Mac only). */
|
(Windows/Mac/hidraw only) */
|
||||||
unsigned short usage_page;
|
unsigned short usage_page;
|
||||||
/** Usage for this Device/Interface
|
/** Usage for this Device/Interface
|
||||||
(Windows/Mac only).*/
|
(Windows/Mac/hidraw only) */
|
||||||
unsigned short usage;
|
unsigned short usage;
|
||||||
/** The USB interface which this logical device
|
/** The USB interface which this logical device
|
||||||
represents. Valid on both Linux implementations
|
represents.
|
||||||
in all cases, and valid on the Windows implementation
|
|
||||||
only if the device contains more than one interface. */
|
Valid only if the device is a USB HID device.
|
||||||
|
Set to -1 in all other cases.
|
||||||
|
*/
|
||||||
int interface_number;
|
int interface_number;
|
||||||
|
|
||||||
/** Pointer to the next device */
|
/** Pointer to the next device */
|
||||||
struct hid_device_info *next;
|
struct hid_device_info *next;
|
||||||
|
|
||||||
|
/** Underlying bus type
|
||||||
|
Since version 0.13.0, @ref HID_API_VERSION >= HID_API_MAKE_VERSION(0, 13, 0)
|
||||||
|
*/
|
||||||
|
hid_bus_type bus_type;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -87,11 +195,12 @@ extern "C" {
|
|||||||
needed. This function should be called at the beginning of
|
needed. This function should be called at the beginning of
|
||||||
execution however, if there is a chance of HIDAPI handles
|
execution however, if there is a chance of HIDAPI handles
|
||||||
being opened by different threads simultaneously.
|
being opened by different threads simultaneously.
|
||||||
|
|
||||||
@ingroup API
|
@ingroup API
|
||||||
|
|
||||||
@returns
|
@returns
|
||||||
This function returns 0 on success and -1 on error.
|
This function returns 0 on success and -1 on error.
|
||||||
|
Call hid_error(NULL) to get the failure reason.
|
||||||
*/
|
*/
|
||||||
int HID_API_EXPORT HID_API_CALL hid_init(void);
|
int HID_API_EXPORT HID_API_CALL hid_init(void);
|
||||||
|
|
||||||
@ -103,7 +212,7 @@ extern "C" {
|
|||||||
|
|
||||||
@ingroup API
|
@ingroup API
|
||||||
|
|
||||||
@returns
|
@returns
|
||||||
This function returns 0 on success and -1 on error.
|
This function returns 0 on success and -1 on error.
|
||||||
*/
|
*/
|
||||||
int HID_API_EXPORT HID_API_CALL hid_exit(void);
|
int HID_API_EXPORT HID_API_CALL hid_exit(void);
|
||||||
@ -123,21 +232,25 @@ extern "C" {
|
|||||||
@param product_id The Product ID (PID) of the types of
|
@param product_id The Product ID (PID) of the types of
|
||||||
device to open.
|
device to open.
|
||||||
|
|
||||||
@returns
|
@returns
|
||||||
This function returns a pointer to a linked list of type
|
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
|
attached to the system,
|
||||||
this linked list by calling hid_free_enumeration().
|
or NULL in the case of failure or if no HID devices present in the system.
|
||||||
|
Call hid_error(NULL) to get the failure reason.
|
||||||
|
|
||||||
|
@note The returned value by this function must to be freed by calling hid_free_enumeration(),
|
||||||
|
when not needed anymore.
|
||||||
*/
|
*/
|
||||||
struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id);
|
struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id);
|
||||||
|
|
||||||
/** @brief Free an enumeration Linked List
|
/** @brief Free an enumeration Linked List
|
||||||
|
|
||||||
This function frees a linked list created by hid_enumerate().
|
This function frees a linked list created by hid_enumerate().
|
||||||
|
|
||||||
@ingroup API
|
@ingroup API
|
||||||
@param devs Pointer to a list of struct_device returned from
|
@param devs Pointer to a list of struct_device returned from
|
||||||
hid_enumerate().
|
hid_enumerate().
|
||||||
*/
|
*/
|
||||||
void HID_API_EXPORT HID_API_CALL hid_free_enumeration(struct hid_device_info *devs);
|
void HID_API_EXPORT HID_API_CALL hid_free_enumeration(struct hid_device_info *devs);
|
||||||
|
|
||||||
@ -151,11 +264,15 @@ extern "C" {
|
|||||||
@param vendor_id The Vendor ID (VID) of the device to open.
|
@param vendor_id The Vendor ID (VID) of the device to open.
|
||||||
@param product_id The Product ID (PID) of the device to open.
|
@param product_id The Product ID (PID) of the device to open.
|
||||||
@param serial_number The Serial Number of the device to open
|
@param serial_number The Serial Number of the device to open
|
||||||
(Optionally NULL).
|
(Optionally NULL).
|
||||||
|
|
||||||
@returns
|
@returns
|
||||||
This function returns a pointer to a #hid_device object on
|
This function returns a pointer to a #hid_device object on
|
||||||
success or NULL on failure.
|
success or NULL on failure.
|
||||||
|
Call hid_error(NULL) to get the failure reason.
|
||||||
|
|
||||||
|
@note The returned object must be freed by calling hid_close(),
|
||||||
|
when not needed anymore.
|
||||||
*/
|
*/
|
||||||
HID_API_EXPORT hid_device * HID_API_CALL hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number);
|
HID_API_EXPORT hid_device * HID_API_CALL hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number);
|
||||||
|
|
||||||
@ -166,11 +283,15 @@ extern "C" {
|
|||||||
Linux).
|
Linux).
|
||||||
|
|
||||||
@ingroup API
|
@ingroup API
|
||||||
@param path The path name of the device to open
|
@param path The path name of the device to open
|
||||||
|
|
||||||
@returns
|
@returns
|
||||||
This function returns a pointer to a #hid_device object on
|
This function returns a pointer to a #hid_device object on
|
||||||
success or NULL on failure.
|
success or NULL on failure.
|
||||||
|
Call hid_error(NULL) to get the failure reason.
|
||||||
|
|
||||||
|
@note The returned object must be freed by calling hid_close(),
|
||||||
|
when not needed anymore.
|
||||||
*/
|
*/
|
||||||
HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path);
|
HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path);
|
||||||
|
|
||||||
@ -186,12 +307,12 @@ extern "C" {
|
|||||||
single report), followed by the report data (16 bytes). In
|
single report), followed by the report data (16 bytes). In
|
||||||
this example, the length passed in would be 17.
|
this example, the length passed in would be 17.
|
||||||
|
|
||||||
hid_write() will send the data on the first OUT endpoint, if
|
hid_write() will send the data on the first interrupt OUT
|
||||||
one exists. If it does not, it will send the data through
|
endpoint, if one exists. If it does not the behaviour is as
|
||||||
the Control Endpoint (Endpoint 0).
|
@ref hid_send_output_report
|
||||||
|
|
||||||
@ingroup API
|
@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
|
@param data The data to send, including the report number as
|
||||||
the first byte.
|
the first byte.
|
||||||
@param length The length in bytes of the data to send.
|
@param length The length in bytes of the data to send.
|
||||||
@ -199,8 +320,9 @@ extern "C" {
|
|||||||
@returns
|
@returns
|
||||||
This function returns the actual number of bytes written and
|
This function returns the actual number of bytes written and
|
||||||
-1 on error.
|
-1 on error.
|
||||||
|
Call hid_error(dev) to get the failure reason.
|
||||||
*/
|
*/
|
||||||
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.
|
/** @brief Read an Input report from a HID device with timeout.
|
||||||
|
|
||||||
@ -209,7 +331,7 @@ extern "C" {
|
|||||||
contain the Report number if the device uses numbered reports.
|
contain the Report number if the device uses numbered reports.
|
||||||
|
|
||||||
@ingroup API
|
@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 data A buffer to put the read data into.
|
||||||
@param length The number of bytes to read. For devices with
|
@param length The number of bytes to read. For devices with
|
||||||
multiple reports, make sure to read an extra byte for
|
multiple reports, make sure to read an extra byte for
|
||||||
@ -218,7 +340,9 @@ extern "C" {
|
|||||||
|
|
||||||
@returns
|
@returns
|
||||||
This function returns the actual number of bytes read and
|
This function returns the actual number of bytes read and
|
||||||
-1 on error. If no packet was available to be read within
|
-1 on error.
|
||||||
|
Call hid_error(dev) to get the failure reason.
|
||||||
|
If no packet was available to be read within
|
||||||
the timeout period, this function returns 0.
|
the timeout period, this function returns 0.
|
||||||
*/
|
*/
|
||||||
int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, 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);
|
||||||
@ -226,11 +350,11 @@ extern "C" {
|
|||||||
/** @brief Read an Input report from a HID device.
|
/** @brief Read an Input report from a HID device.
|
||||||
|
|
||||||
Input reports are returned
|
Input reports are returned
|
||||||
to the host through the INTERRUPT IN endpoint. The first byte will
|
to the host through the INTERRUPT IN endpoint. The first byte will
|
||||||
contain the Report number if the device uses numbered reports.
|
contain the Report number if the device uses numbered reports.
|
||||||
|
|
||||||
@ingroup API
|
@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 data A buffer to put the read data into.
|
||||||
@param length The number of bytes to read. For devices with
|
@param length The number of bytes to read. For devices with
|
||||||
multiple reports, make sure to read an extra byte for
|
multiple reports, make sure to read an extra byte for
|
||||||
@ -238,10 +362,12 @@ extern "C" {
|
|||||||
|
|
||||||
@returns
|
@returns
|
||||||
This function returns the actual number of bytes read and
|
This function returns the actual number of bytes read and
|
||||||
-1 on error. If no packet was available to be read and
|
-1 on error.
|
||||||
|
Call hid_error(dev) to get the failure reason.
|
||||||
|
If no packet was available to be read and
|
||||||
the handle is in non-blocking mode, this function returns 0.
|
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.
|
/** @brief Set the device handle to be non-blocking.
|
||||||
|
|
||||||
@ -253,15 +379,16 @@ extern "C" {
|
|||||||
Nonblocking can be turned on and off at any time.
|
Nonblocking can be turned on and off at any time.
|
||||||
|
|
||||||
@ingroup API
|
@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
|
@param nonblock enable or not the nonblocking reads
|
||||||
- 1 to enable nonblocking
|
- 1 to enable nonblocking
|
||||||
- 0 to disable nonblocking.
|
- 0 to disable nonblocking.
|
||||||
|
|
||||||
@returns
|
@returns
|
||||||
This function returns 0 on success and -1 on error.
|
This function returns 0 on success and -1 on error.
|
||||||
|
Call hid_error(dev) to get the failure reason.
|
||||||
*/
|
*/
|
||||||
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.
|
/** @brief Send a Feature report to the device.
|
||||||
|
|
||||||
@ -279,7 +406,7 @@ extern "C" {
|
|||||||
in would be 17.
|
in would be 17.
|
||||||
|
|
||||||
@ingroup API
|
@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
|
@param data The data to send, including the report number as
|
||||||
the first byte.
|
the first byte.
|
||||||
@param length The length in bytes of the data to send, including
|
@param length The length in bytes of the data to send, including
|
||||||
@ -288,8 +415,9 @@ extern "C" {
|
|||||||
@returns
|
@returns
|
||||||
This function returns the actual number of bytes written and
|
This function returns the actual number of bytes written and
|
||||||
-1 on error.
|
-1 on error.
|
||||||
|
Call hid_error(dev) to get the failure reason.
|
||||||
*/
|
*/
|
||||||
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.
|
/** @brief Get a feature report from a HID device.
|
||||||
|
|
||||||
@ -300,7 +428,7 @@ extern "C" {
|
|||||||
start in data[1].
|
start in data[1].
|
||||||
|
|
||||||
@ingroup API
|
@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
|
@param data A buffer to put the read data into, including
|
||||||
the Report ID. Set the first byte of @p data[] to the
|
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
|
Report ID of the report to be read, or set it to zero
|
||||||
@ -313,79 +441,218 @@ extern "C" {
|
|||||||
This function returns the number of bytes read plus
|
This function returns the number of bytes read plus
|
||||||
one for the report ID (which is still in the first
|
one for the report ID (which is still in the first
|
||||||
byte), or -1 on error.
|
byte), or -1 on error.
|
||||||
|
Call hid_error(dev) to get the failure reason.
|
||||||
*/
|
*/
|
||||||
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 Send a Output report to the device.
|
||||||
|
|
||||||
|
Since version 0.15.0, @ref HID_API_VERSION >= HID_API_MAKE_VERSION(0, 15, 0)
|
||||||
|
|
||||||
|
Output reports are sent over the Control endpoint as a
|
||||||
|
Set_Report transfer. The first byte of @p data[] must
|
||||||
|
contain the Report ID. For devices which only support a
|
||||||
|
single report, this must be set to 0x0. The remaining bytes
|
||||||
|
contain the report data. Since the Report ID is mandatory,
|
||||||
|
calls to hid_send_output_report() will always contain one
|
||||||
|
more byte than the report contains. For example, if a hid
|
||||||
|
report is 16 bytes long, 17 bytes must be passed to
|
||||||
|
hid_send_output_report(): the Report ID (or 0x0, for
|
||||||
|
devices which do not use numbered reports), followed by the
|
||||||
|
report data (16 bytes). In this example, the length passed
|
||||||
|
in would be 17.
|
||||||
|
|
||||||
|
This function sets the return value of hid_error().
|
||||||
|
|
||||||
|
@ingroup API
|
||||||
|
@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
|
||||||
|
the report number.
|
||||||
|
|
||||||
|
@returns
|
||||||
|
This function returns the actual number of bytes written and
|
||||||
|
-1 on error.
|
||||||
|
|
||||||
|
@see @ref hid_write
|
||||||
|
*/
|
||||||
|
int HID_API_EXPORT HID_API_CALL hid_send_output_report(hid_device* dev, const unsigned char* data, size_t length);
|
||||||
|
|
||||||
|
/** @brief Get a input report from a HID device.
|
||||||
|
|
||||||
|
Since version 0.10.0, @ref HID_API_VERSION >= HID_API_MAKE_VERSION(0, 10, 0)
|
||||||
|
|
||||||
|
Set the first byte of @p data[] to the Report ID of the
|
||||||
|
report to be read. Make sure to allow space for this
|
||||||
|
extra byte in @p data[]. Upon return, the first byte will
|
||||||
|
still contain the Report ID, and the report data will
|
||||||
|
start in data[1].
|
||||||
|
|
||||||
|
@ingroup API
|
||||||
|
@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
|
||||||
|
if your device does not use numbered reports.
|
||||||
|
@param length The number of bytes to read, including an
|
||||||
|
extra byte for the report ID. The buffer can be longer
|
||||||
|
than the actual report.
|
||||||
|
|
||||||
|
@returns
|
||||||
|
This function returns the number of bytes read plus
|
||||||
|
one for the report ID (which is still in the first
|
||||||
|
byte), or -1 on error.
|
||||||
|
Call hid_error(dev) to get the failure reason.
|
||||||
|
*/
|
||||||
|
int HID_API_EXPORT HID_API_CALL hid_get_input_report(hid_device *dev, unsigned char *data, size_t length);
|
||||||
|
|
||||||
/** @brief Close a HID device.
|
/** @brief Close a HID device.
|
||||||
|
|
||||||
@ingroup API
|
@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.
|
/** @brief Get The Manufacturer String from a HID device.
|
||||||
|
|
||||||
@ingroup API
|
@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 string A wide string buffer to put the data into.
|
||||||
@param maxlen The length of the buffer in multiples of wchar_t.
|
@param maxlen The length of the buffer in multiples of wchar_t.
|
||||||
|
|
||||||
@returns
|
@returns
|
||||||
This function returns 0 on success and -1 on error.
|
This function returns 0 on success and -1 on error.
|
||||||
|
Call hid_error(dev) to get the failure reason.
|
||||||
*/
|
*/
|
||||||
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.
|
/** @brief Get The Product String from a HID device.
|
||||||
|
|
||||||
@ingroup API
|
@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 string A wide string buffer to put the data into.
|
||||||
@param maxlen The length of the buffer in multiples of wchar_t.
|
@param maxlen The length of the buffer in multiples of wchar_t.
|
||||||
|
|
||||||
@returns
|
@returns
|
||||||
This function returns 0 on success and -1 on error.
|
This function returns 0 on success and -1 on error.
|
||||||
|
Call hid_error(dev) to get the failure reason.
|
||||||
*/
|
*/
|
||||||
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.
|
/** @brief Get The Serial Number String from a HID device.
|
||||||
|
|
||||||
@ingroup API
|
@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 string A wide string buffer to put the data into.
|
||||||
@param maxlen The length of the buffer in multiples of wchar_t.
|
@param maxlen The length of the buffer in multiples of wchar_t.
|
||||||
|
|
||||||
@returns
|
@returns
|
||||||
This function returns 0 on success and -1 on error.
|
This function returns 0 on success and -1 on error.
|
||||||
|
Call hid_error(dev) to get the failure reason.
|
||||||
*/
|
*/
|
||||||
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 The struct #hid_device_info from a HID device.
|
||||||
|
|
||||||
|
Since version 0.13.0, @ref HID_API_VERSION >= HID_API_MAKE_VERSION(0, 13, 0)
|
||||||
|
|
||||||
|
@ingroup API
|
||||||
|
@param dev A device handle returned from hid_open().
|
||||||
|
|
||||||
|
@returns
|
||||||
|
This function returns a pointer to the struct #hid_device_info
|
||||||
|
for this hid_device, or NULL in the case of failure.
|
||||||
|
Call hid_error(dev) to get the failure reason.
|
||||||
|
This struct is valid until the device is closed with hid_close().
|
||||||
|
|
||||||
|
@note The returned object is owned by the @p dev, and SHOULD NOT be freed by the user.
|
||||||
|
*/
|
||||||
|
struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_get_device_info(hid_device *dev);
|
||||||
|
|
||||||
/** @brief Get a string from a HID device, based on its string index.
|
/** @brief Get a string from a HID device, based on its string index.
|
||||||
|
|
||||||
@ingroup API
|
@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_index The index of the string to get.
|
||||||
@param string A wide string buffer to put the data into.
|
@param string A wide string buffer to put the data into.
|
||||||
@param maxlen The length of the buffer in multiples of wchar_t.
|
@param maxlen The length of the buffer in multiples of wchar_t.
|
||||||
|
|
||||||
@returns
|
@returns
|
||||||
This function returns 0 on success and -1 on error.
|
This function returns 0 on success and -1 on error.
|
||||||
|
Call hid_error(dev) to get the failure reason.
|
||||||
*/
|
*/
|
||||||
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 report descriptor from a HID device.
|
||||||
|
|
||||||
|
Since version 0.14.0, @ref HID_API_VERSION >= HID_API_MAKE_VERSION(0, 14, 0)
|
||||||
|
|
||||||
|
User has to provide a preallocated buffer where descriptor will be copied to.
|
||||||
|
The recommended size for preallocated buffer is @ref HID_API_MAX_REPORT_DESCRIPTOR_SIZE bytes.
|
||||||
|
|
||||||
|
@ingroup API
|
||||||
|
@param dev A device handle returned from hid_open().
|
||||||
|
@param buf The buffer to copy descriptor into.
|
||||||
|
@param buf_size The size of the buffer in bytes.
|
||||||
|
|
||||||
|
@returns
|
||||||
|
This function returns non-negative number of bytes actually copied, or -1 on error.
|
||||||
|
*/
|
||||||
|
int HID_API_EXPORT_CALL hid_get_report_descriptor(hid_device *dev, unsigned char *buf, size_t buf_size);
|
||||||
|
|
||||||
/** @brief Get a string describing the last error which occurred.
|
/** @brief Get a string describing the last error which occurred.
|
||||||
|
|
||||||
|
This function is intended for logging/debugging purposes.
|
||||||
|
|
||||||
|
This function guarantees to never return NULL.
|
||||||
|
If there was no error in the last function call -
|
||||||
|
the returned string clearly indicates that.
|
||||||
|
|
||||||
|
Any HIDAPI function that can explicitly indicate an execution failure
|
||||||
|
(e.g. by an error code, or by returning NULL) - may set the error string,
|
||||||
|
to be returned by this function.
|
||||||
|
|
||||||
|
Strings returned from hid_error() must not be freed by the user,
|
||||||
|
i.e. owned by HIDAPI library.
|
||||||
|
Device-specific error string may remain allocated at most until hid_close() is called.
|
||||||
|
Global error string may remain allocated at most until hid_exit() is called.
|
||||||
|
|
||||||
@ingroup API
|
@ingroup API
|
||||||
@param device A device handle returned from hid_open().
|
@param dev A device handle returned from hid_open(),
|
||||||
|
or NULL to get the last non-device-specific error
|
||||||
|
(e.g. for errors in hid_open() or hid_enumerate()).
|
||||||
|
|
||||||
@returns
|
@returns
|
||||||
This function returns a string containing the last error
|
A string describing the last error (if any).
|
||||||
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);
|
||||||
|
|
||||||
|
/** @brief Get a runtime version of the library.
|
||||||
|
|
||||||
|
This function is thread-safe.
|
||||||
|
|
||||||
|
@ingroup API
|
||||||
|
|
||||||
|
@returns
|
||||||
|
Pointer to statically allocated struct, that contains version.
|
||||||
|
*/
|
||||||
|
HID_API_EXPORT const struct hid_api_version* HID_API_CALL hid_version(void);
|
||||||
|
|
||||||
|
|
||||||
|
/** @brief Get a runtime version string of the library.
|
||||||
|
|
||||||
|
This function is thread-safe.
|
||||||
|
|
||||||
|
@ingroup API
|
||||||
|
|
||||||
|
@returns
|
||||||
|
Pointer to statically allocated string, that contains version string.
|
||||||
|
*/
|
||||||
|
HID_API_EXPORT const char* HID_API_CALL hid_version_str(void);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
98
libs/hidapi/mac/hidapi_darwin.h
Normal file
98
libs/hidapi/mac/hidapi_darwin.h
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
/*******************************************************
|
||||||
|
HIDAPI - Multi-Platform library for
|
||||||
|
communication with HID devices.
|
||||||
|
|
||||||
|
libusb/hidapi Team
|
||||||
|
|
||||||
|
Copyright 2022, All Rights Reserved.
|
||||||
|
|
||||||
|
At the discretion of the user of this library,
|
||||||
|
this software may be licensed under the terms of the
|
||||||
|
GNU General Public License v3, a BSD-Style license, or the
|
||||||
|
original HIDAPI license as outlined in the LICENSE.txt,
|
||||||
|
LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt
|
||||||
|
files located at the root of the source distribution.
|
||||||
|
These files may also be found in the public source
|
||||||
|
code repository located at:
|
||||||
|
https://github.com/libusb/hidapi .
|
||||||
|
********************************************************/
|
||||||
|
|
||||||
|
/** @file
|
||||||
|
* @defgroup API hidapi API
|
||||||
|
|
||||||
|
* Since version 0.12.0, @ref HID_API_VERSION >= HID_API_MAKE_VERSION(0, 12, 0)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HIDAPI_DARWIN_H__
|
||||||
|
#define HIDAPI_DARWIN_H__
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "hidapi.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** @brief Get the location ID for a HID device.
|
||||||
|
|
||||||
|
Since version 0.12.0, @ref HID_API_VERSION >= HID_API_MAKE_VERSION(0, 12, 0)
|
||||||
|
|
||||||
|
@ingroup API
|
||||||
|
@param dev A device handle returned from hid_open().
|
||||||
|
@param location_id The device's location ID on return.
|
||||||
|
|
||||||
|
@returns
|
||||||
|
This function returns 0 on success and -1 on error.
|
||||||
|
*/
|
||||||
|
int HID_API_EXPORT_CALL hid_darwin_get_location_id(hid_device *dev, uint32_t *location_id);
|
||||||
|
|
||||||
|
|
||||||
|
/** @brief Changes the behavior of all further calls to @ref hid_open or @ref hid_open_path.
|
||||||
|
|
||||||
|
By default on Darwin platform all devices opened by HIDAPI with @ref hid_open or @ref hid_open_path
|
||||||
|
are opened in exclusive mode (see kIOHIDOptionsTypeSeizeDevice).
|
||||||
|
|
||||||
|
Since version 0.12.0, @ref HID_API_VERSION >= HID_API_MAKE_VERSION(0, 12, 0)
|
||||||
|
|
||||||
|
@ingroup API
|
||||||
|
@param open_exclusive When set to 0 - all further devices will be opened
|
||||||
|
in non-exclusive mode. Otherwise - all further devices will be opened
|
||||||
|
in exclusive mode.
|
||||||
|
|
||||||
|
@note During the initialisation by @ref hid_init - this property is set to 1 (TRUE).
|
||||||
|
This is done to preserve full backward compatibility with previous behavior.
|
||||||
|
|
||||||
|
@note Calling this function before @ref hid_init or after @ref hid_exit has no effect.
|
||||||
|
*/
|
||||||
|
void HID_API_EXPORT_CALL hid_darwin_set_open_exclusive(int open_exclusive);
|
||||||
|
|
||||||
|
/** @brief Getter for option set by @ref hid_darwin_set_open_exclusive.
|
||||||
|
|
||||||
|
Since version 0.12.0, @ref HID_API_VERSION >= HID_API_MAKE_VERSION(0, 12, 0)
|
||||||
|
|
||||||
|
@ingroup API
|
||||||
|
@return 1 if all further devices will be opened in exclusive mode.
|
||||||
|
|
||||||
|
@note Value returned by this function before calling to @ref hid_init or after @ref hid_exit
|
||||||
|
is not reliable.
|
||||||
|
*/
|
||||||
|
int HID_API_EXPORT_CALL hid_darwin_get_open_exclusive(void);
|
||||||
|
|
||||||
|
/** @brief Check how the device was opened.
|
||||||
|
|
||||||
|
Since version 0.12.0, @ref HID_API_VERSION >= HID_API_MAKE_VERSION(0, 12, 0)
|
||||||
|
|
||||||
|
@ingroup API
|
||||||
|
@param dev A device to get property from.
|
||||||
|
|
||||||
|
@return 1 if the device is opened in exclusive mode, 0 - opened in non-exclusive,
|
||||||
|
-1 - if dev is invalid.
|
||||||
|
*/
|
||||||
|
int HID_API_EXPORT_CALL hid_darwin_is_device_open_exclusive(hid_device *dev);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
File diff suppressed because it is too large
Load Diff
75
libs/hidapi/windows/hidapi_cfgmgr32.h
Normal file
75
libs/hidapi/windows/hidapi_cfgmgr32.h
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
/*******************************************************
|
||||||
|
HIDAPI - Multi-Platform library for
|
||||||
|
communication with HID devices.
|
||||||
|
|
||||||
|
libusb/hidapi Team
|
||||||
|
|
||||||
|
Copyright 2022, All Rights Reserved.
|
||||||
|
|
||||||
|
At the discretion of the user of this library,
|
||||||
|
this software may be licensed under the terms of the
|
||||||
|
GNU General Public License v3, a BSD-Style license, or the
|
||||||
|
original HIDAPI license as outlined in the LICENSE.txt,
|
||||||
|
LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt
|
||||||
|
files located at the root of the source distribution.
|
||||||
|
These files may also be found in the public source
|
||||||
|
code repository located at:
|
||||||
|
https://github.com/libusb/hidapi .
|
||||||
|
********************************************************/
|
||||||
|
|
||||||
|
#ifndef HIDAPI_CFGMGR32_H
|
||||||
|
#define HIDAPI_CFGMGR32_H
|
||||||
|
|
||||||
|
#ifdef HIDAPI_USE_DDK
|
||||||
|
|
||||||
|
#include <cfgmgr32.h>
|
||||||
|
#include <initguid.h>
|
||||||
|
#include <devpkey.h>
|
||||||
|
#include <propkey.h>
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
/* This part of the header mimics cfgmgr32.h,
|
||||||
|
but only what is used by HIDAPI */
|
||||||
|
|
||||||
|
#include <initguid.h>
|
||||||
|
#include <devpropdef.h>
|
||||||
|
#include <propkeydef.h>
|
||||||
|
|
||||||
|
typedef DWORD RETURN_TYPE;
|
||||||
|
typedef RETURN_TYPE CONFIGRET;
|
||||||
|
typedef DWORD DEVNODE, DEVINST;
|
||||||
|
typedef DEVNODE* PDEVNODE, * PDEVINST;
|
||||||
|
typedef WCHAR* DEVNODEID_W, * DEVINSTID_W;
|
||||||
|
|
||||||
|
#define CR_SUCCESS (0x00000000)
|
||||||
|
#define CR_BUFFER_SMALL (0x0000001A)
|
||||||
|
#define CR_FAILURE (0x00000013)
|
||||||
|
|
||||||
|
#define CM_LOCATE_DEVNODE_NORMAL 0x00000000
|
||||||
|
|
||||||
|
#define CM_GET_DEVICE_INTERFACE_LIST_PRESENT (0x00000000)
|
||||||
|
|
||||||
|
typedef CONFIGRET(__stdcall* CM_Locate_DevNodeW_)(PDEVINST pdnDevInst, DEVINSTID_W pDeviceID, ULONG ulFlags);
|
||||||
|
typedef CONFIGRET(__stdcall* CM_Get_Parent_)(PDEVINST pdnDevInst, DEVINST dnDevInst, ULONG ulFlags);
|
||||||
|
typedef CONFIGRET(__stdcall* CM_Get_DevNode_PropertyW_)(DEVINST dnDevInst, CONST DEVPROPKEY* PropertyKey, DEVPROPTYPE* PropertyType, PBYTE PropertyBuffer, PULONG PropertyBufferSize, ULONG ulFlags);
|
||||||
|
typedef CONFIGRET(__stdcall* CM_Get_Device_Interface_PropertyW_)(LPCWSTR pszDeviceInterface, CONST DEVPROPKEY* PropertyKey, DEVPROPTYPE* PropertyType, PBYTE PropertyBuffer, PULONG PropertyBufferSize, ULONG ulFlags);
|
||||||
|
typedef CONFIGRET(__stdcall* CM_Get_Device_Interface_List_SizeW_)(PULONG pulLen, LPGUID InterfaceClassGuid, DEVINSTID_W pDeviceID, ULONG ulFlags);
|
||||||
|
typedef CONFIGRET(__stdcall* CM_Get_Device_Interface_ListW_)(LPGUID InterfaceClassGuid, DEVINSTID_W pDeviceID, PZZWSTR Buffer, ULONG BufferLen, ULONG ulFlags);
|
||||||
|
|
||||||
|
// from devpkey.h
|
||||||
|
DEFINE_DEVPROPKEY(DEVPKEY_NAME, 0xb725f130, 0x47ef, 0x101a, 0xa5, 0xf1, 0x02, 0x60, 0x8c, 0x9e, 0xeb, 0xac, 10); // DEVPROP_TYPE_STRING
|
||||||
|
DEFINE_DEVPROPKEY(DEVPKEY_Device_Manufacturer, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 13); // DEVPROP_TYPE_STRING
|
||||||
|
DEFINE_DEVPROPKEY(DEVPKEY_Device_InstanceId, 0x78c34fc8, 0x104a, 0x4aca, 0x9e, 0xa4, 0x52, 0x4d, 0x52, 0x99, 0x6e, 0x57, 256); // DEVPROP_TYPE_STRING
|
||||||
|
DEFINE_DEVPROPKEY(DEVPKEY_Device_HardwareIds, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 3); // DEVPROP_TYPE_STRING_LIST
|
||||||
|
DEFINE_DEVPROPKEY(DEVPKEY_Device_CompatibleIds, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 4); // DEVPROP_TYPE_STRING_LIST
|
||||||
|
DEFINE_DEVPROPKEY(DEVPKEY_Device_ContainerId, 0x8c7ed206, 0x3f8a, 0x4827, 0xb3, 0xab, 0xae, 0x9e, 0x1f, 0xae, 0xfc, 0x6c, 2); // DEVPROP_TYPE_GUID
|
||||||
|
|
||||||
|
// from propkey.h
|
||||||
|
DEFINE_PROPERTYKEY(PKEY_DeviceInterface_Bluetooth_DeviceAddress, 0x2BD67D8B, 0x8BEB, 0x48D5, 0x87, 0xE0, 0x6C, 0xDA, 0x34, 0x28, 0x04, 0x0A, 1); // DEVPROP_TYPE_STRING
|
||||||
|
DEFINE_PROPERTYKEY(PKEY_DeviceInterface_Bluetooth_Manufacturer, 0x2BD67D8B, 0x8BEB, 0x48D5, 0x87, 0xE0, 0x6C, 0xDA, 0x34, 0x28, 0x04, 0x0A, 4); // DEVPROP_TYPE_STRING
|
||||||
|
DEFINE_PROPERTYKEY(PKEY_DeviceInterface_Bluetooth_ModelNumber, 0x2BD67D8B, 0x8BEB, 0x48D5, 0x87, 0xE0, 0x6C, 0xDA, 0x34, 0x28, 0x04, 0x0A, 5); // DEVPROP_TYPE_STRING
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* HIDAPI_CFGMGR32_H */
|
987
libs/hidapi/windows/hidapi_descriptor_reconstruct.c
Normal file
987
libs/hidapi/windows/hidapi_descriptor_reconstruct.c
Normal file
@ -0,0 +1,987 @@
|
|||||||
|
/*******************************************************
|
||||||
|
HIDAPI - Multi-Platform library for
|
||||||
|
communication with HID devices.
|
||||||
|
|
||||||
|
libusb/hidapi Team
|
||||||
|
|
||||||
|
Copyright 2022, All Rights Reserved.
|
||||||
|
|
||||||
|
At the discretion of the user of this library,
|
||||||
|
this software may be licensed under the terms of the
|
||||||
|
GNU General Public License v3, a BSD-Style license, or the
|
||||||
|
original HIDAPI license as outlined in the LICENSE.txt,
|
||||||
|
LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt
|
||||||
|
files located at the root of the source distribution.
|
||||||
|
These files may also be found in the public source
|
||||||
|
code repository located at:
|
||||||
|
https://github.com/libusb/hidapi .
|
||||||
|
********************************************************/
|
||||||
|
#include "hidapi_descriptor_reconstruct.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief References to report descriptor buffer.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
struct rd_buffer {
|
||||||
|
unsigned char* buf; /* Pointer to the array which stores the reconstructed descriptor */
|
||||||
|
size_t buf_size; /* Size of the buffer in bytes */
|
||||||
|
size_t byte_idx; /* Index of the next report byte to write to buf array */
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Function that appends a byte to encoded report descriptor buffer.
|
||||||
|
*
|
||||||
|
* @param[in] byte Single byte to append.
|
||||||
|
* @param rpt_desc Pointer to report descriptor buffer struct.
|
||||||
|
*/
|
||||||
|
static void rd_append_byte(unsigned char byte, struct rd_buffer* rpt_desc) {
|
||||||
|
if (rpt_desc->byte_idx < rpt_desc->buf_size) {
|
||||||
|
rpt_desc->buf[rpt_desc->byte_idx] = byte;
|
||||||
|
rpt_desc->byte_idx++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Writes a short report descriptor item according USB HID spec 1.11 chapter 6.2.2.2.
|
||||||
|
*
|
||||||
|
* @param[in] rd_item Enumeration identifying type (Main, Global, Local) and function (e.g Usage or Report Count) of the item.
|
||||||
|
* @param[in] data Data (Size depends on rd_item 0,1,2 or 4bytes).
|
||||||
|
* @param rpt_desc Pointer to report descriptor buffer struct.
|
||||||
|
*
|
||||||
|
* @return Returns 0 if successful, -1 for error.
|
||||||
|
*/
|
||||||
|
static int rd_write_short_item(rd_items rd_item, LONG64 data, struct rd_buffer* rpt_desc) {
|
||||||
|
if (rd_item & 0x03) {
|
||||||
|
// Invalid input data, last to bits are reserved for data size
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rd_item == rd_main_collection_end) {
|
||||||
|
// Item without data (1Byte prefix only)
|
||||||
|
unsigned char oneBytePrefix = (unsigned char) rd_item + 0x00;
|
||||||
|
rd_append_byte(oneBytePrefix, rpt_desc);
|
||||||
|
}
|
||||||
|
else if ((rd_item == rd_global_logical_minimum) ||
|
||||||
|
(rd_item == rd_global_logical_maximum) ||
|
||||||
|
(rd_item == rd_global_physical_minimum) ||
|
||||||
|
(rd_item == rd_global_physical_maximum)) {
|
||||||
|
// Item with signed integer data
|
||||||
|
if ((data >= -128) && (data <= 127)) {
|
||||||
|
// 1Byte prefix + 1Byte data
|
||||||
|
unsigned char oneBytePrefix = (unsigned char) rd_item + 0x01;
|
||||||
|
char localData = (char)data;
|
||||||
|
rd_append_byte(oneBytePrefix, rpt_desc);
|
||||||
|
rd_append_byte(localData & 0xFF, rpt_desc);
|
||||||
|
}
|
||||||
|
else if ((data >= -32768) && (data <= 32767)) {
|
||||||
|
// 1Byte prefix + 2Byte data
|
||||||
|
unsigned char oneBytePrefix = (unsigned char) rd_item + 0x02;
|
||||||
|
INT16 localData = (INT16)data;
|
||||||
|
rd_append_byte(oneBytePrefix, rpt_desc);
|
||||||
|
rd_append_byte(localData & 0xFF, rpt_desc);
|
||||||
|
rd_append_byte(localData >> 8 & 0xFF, rpt_desc);
|
||||||
|
}
|
||||||
|
else if ((data >= -2147483648LL) && (data <= 2147483647)) {
|
||||||
|
// 1Byte prefix + 4Byte data
|
||||||
|
unsigned char oneBytePrefix = (unsigned char) rd_item + 0x03;
|
||||||
|
INT32 localData = (INT32)data;
|
||||||
|
rd_append_byte(oneBytePrefix, rpt_desc);
|
||||||
|
rd_append_byte(localData & 0xFF, rpt_desc);
|
||||||
|
rd_append_byte(localData >> 8 & 0xFF, rpt_desc);
|
||||||
|
rd_append_byte(localData >> 16 & 0xFF, rpt_desc);
|
||||||
|
rd_append_byte(localData >> 24 & 0xFF, rpt_desc);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Data out of 32 bit signed integer range
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Item with unsigned integer data
|
||||||
|
if ((data >= 0) && (data <= 0xFF)) {
|
||||||
|
// 1Byte prefix + 1Byte data
|
||||||
|
unsigned char oneBytePrefix = (unsigned char) rd_item + 0x01;
|
||||||
|
unsigned char localData = (unsigned char)data;
|
||||||
|
rd_append_byte(oneBytePrefix, rpt_desc);
|
||||||
|
rd_append_byte(localData & 0xFF, rpt_desc);
|
||||||
|
}
|
||||||
|
else if ((data >= 0) && (data <= 0xFFFF)) {
|
||||||
|
// 1Byte prefix + 2Byte data
|
||||||
|
unsigned char oneBytePrefix = (unsigned char) rd_item + 0x02;
|
||||||
|
UINT16 localData = (UINT16)data;
|
||||||
|
rd_append_byte(oneBytePrefix, rpt_desc);
|
||||||
|
rd_append_byte(localData & 0xFF, rpt_desc);
|
||||||
|
rd_append_byte(localData >> 8 & 0xFF, rpt_desc);
|
||||||
|
}
|
||||||
|
else if ((data >= 0) && (data <= 0xFFFFFFFF)) {
|
||||||
|
// 1Byte prefix + 4Byte data
|
||||||
|
unsigned char oneBytePrefix = (unsigned char) rd_item + 0x03;
|
||||||
|
UINT32 localData = (UINT32)data;
|
||||||
|
rd_append_byte(oneBytePrefix, rpt_desc);
|
||||||
|
rd_append_byte(localData & 0xFF, rpt_desc);
|
||||||
|
rd_append_byte(localData >> 8 & 0xFF, rpt_desc);
|
||||||
|
rd_append_byte(localData >> 16 & 0xFF, rpt_desc);
|
||||||
|
rd_append_byte(localData >> 24 & 0xFF, rpt_desc);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Data out of 32 bit unsigned integer range
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct rd_main_item_node * rd_append_main_item_node(int first_bit, int last_bit, rd_node_type type_of_node, int caps_index, int collection_index, rd_main_items main_item_type, unsigned char report_id, struct rd_main_item_node **list) {
|
||||||
|
struct rd_main_item_node *new_list_node;
|
||||||
|
|
||||||
|
// Determine last node in the list
|
||||||
|
while (*list != NULL)
|
||||||
|
{
|
||||||
|
list = &(*list)->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
new_list_node = malloc(sizeof(*new_list_node)); // Create new list entry
|
||||||
|
new_list_node->FirstBit = first_bit;
|
||||||
|
new_list_node->LastBit = last_bit;
|
||||||
|
new_list_node->TypeOfNode = type_of_node;
|
||||||
|
new_list_node->CapsIndex = caps_index;
|
||||||
|
new_list_node->CollectionIndex = collection_index;
|
||||||
|
new_list_node->MainItemType = main_item_type;
|
||||||
|
new_list_node->ReportID = report_id;
|
||||||
|
new_list_node->next = NULL; // NULL marks last node in the list
|
||||||
|
|
||||||
|
*list = new_list_node;
|
||||||
|
return new_list_node;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct rd_main_item_node * rd_insert_main_item_node(int first_bit, int last_bit, rd_node_type type_of_node, int caps_index, int collection_index, rd_main_items main_item_type, unsigned char report_id, struct rd_main_item_node **list) {
|
||||||
|
// Insert item after the main item node referenced by list
|
||||||
|
struct rd_main_item_node *next_item = (*list)->next;
|
||||||
|
(*list)->next = NULL;
|
||||||
|
rd_append_main_item_node(first_bit, last_bit, type_of_node, caps_index, collection_index, main_item_type, report_id, list);
|
||||||
|
(*list)->next->next = next_item;
|
||||||
|
return (*list)->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct rd_main_item_node * rd_search_main_item_list_for_bit_position(int search_bit, rd_main_items main_item_type, unsigned char report_id, struct rd_main_item_node **list) {
|
||||||
|
// Determine first INPUT/OUTPUT/FEATURE main item, where the last bit position is equal or greater than the search bit position
|
||||||
|
|
||||||
|
while (((*list)->next->MainItemType != rd_collection) &&
|
||||||
|
((*list)->next->MainItemType != rd_collection_end) &&
|
||||||
|
!(((*list)->next->LastBit >= search_bit) &&
|
||||||
|
((*list)->next->ReportID == report_id) &&
|
||||||
|
((*list)->next->MainItemType == main_item_type))
|
||||||
|
)
|
||||||
|
{
|
||||||
|
list = &(*list)->next;
|
||||||
|
}
|
||||||
|
return *list;
|
||||||
|
}
|
||||||
|
|
||||||
|
int hid_winapi_descriptor_reconstruct_pp_data(void *preparsed_data, unsigned char *buf, size_t buf_size)
|
||||||
|
{
|
||||||
|
hidp_preparsed_data *pp_data = (hidp_preparsed_data *) preparsed_data;
|
||||||
|
|
||||||
|
// Check if MagicKey is correct, to ensure that pp_data points to an valid preparse data structure
|
||||||
|
if (memcmp(pp_data->MagicKey, "HidP KDR", 8) != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct rd_buffer rpt_desc = {
|
||||||
|
.buf = buf,
|
||||||
|
.buf_size = buf_size,
|
||||||
|
.byte_idx = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
// Set pointer to the first node of link_collection_nodes
|
||||||
|
phid_pp_link_collection_node link_collection_nodes = (phid_pp_link_collection_node)(((unsigned char*)&pp_data->caps[0]) + pp_data->FirstByteOfLinkCollectionArray);
|
||||||
|
|
||||||
|
// ****************************************************************************************************************************
|
||||||
|
// Create lookup tables for the bit range of each report per collection (position of first bit and last bit in each collection)
|
||||||
|
// coll_bit_range[COLLECTION_INDEX][REPORT_ID][INPUT/OUTPUT/FEATURE]
|
||||||
|
// ****************************************************************************************************************************
|
||||||
|
|
||||||
|
// Allocate memory and initialize lookup table
|
||||||
|
rd_bit_range ****coll_bit_range;
|
||||||
|
coll_bit_range = malloc(pp_data->NumberLinkCollectionNodes * sizeof(*coll_bit_range));
|
||||||
|
for (USHORT collection_node_idx = 0; collection_node_idx < pp_data->NumberLinkCollectionNodes; collection_node_idx++) {
|
||||||
|
coll_bit_range[collection_node_idx] = malloc(256 * sizeof(*coll_bit_range[0])); // 256 possible report IDs (incl. 0x00)
|
||||||
|
for (int reportid_idx = 0; reportid_idx < 256; reportid_idx++) {
|
||||||
|
coll_bit_range[collection_node_idx][reportid_idx] = malloc(NUM_OF_HIDP_REPORT_TYPES * sizeof(*coll_bit_range[0][0]));
|
||||||
|
for (HIDP_REPORT_TYPE rt_idx = 0; rt_idx < NUM_OF_HIDP_REPORT_TYPES; rt_idx++) {
|
||||||
|
coll_bit_range[collection_node_idx][reportid_idx][rt_idx] = malloc(sizeof(rd_bit_range));
|
||||||
|
coll_bit_range[collection_node_idx][reportid_idx][rt_idx]->FirstBit = -1;
|
||||||
|
coll_bit_range[collection_node_idx][reportid_idx][rt_idx]->LastBit = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fill the lookup table where caps exist
|
||||||
|
for (HIDP_REPORT_TYPE rt_idx = 0; rt_idx < NUM_OF_HIDP_REPORT_TYPES; rt_idx++) {
|
||||||
|
for (USHORT caps_idx = pp_data->caps_info[rt_idx].FirstCap; caps_idx < pp_data->caps_info[rt_idx].LastCap; caps_idx++) {
|
||||||
|
int first_bit, last_bit;
|
||||||
|
first_bit = (pp_data->caps[caps_idx].BytePosition - 1) * 8
|
||||||
|
+ pp_data->caps[caps_idx].BitPosition;
|
||||||
|
last_bit = first_bit + pp_data->caps[caps_idx].ReportSize
|
||||||
|
* pp_data->caps[caps_idx].ReportCount - 1;
|
||||||
|
if (coll_bit_range[pp_data->caps[caps_idx].LinkCollection][pp_data->caps[caps_idx].ReportID][rt_idx]->FirstBit == -1 ||
|
||||||
|
coll_bit_range[pp_data->caps[caps_idx].LinkCollection][pp_data->caps[caps_idx].ReportID][rt_idx]->FirstBit > first_bit) {
|
||||||
|
coll_bit_range[pp_data->caps[caps_idx].LinkCollection][pp_data->caps[caps_idx].ReportID][rt_idx]->FirstBit = first_bit;
|
||||||
|
}
|
||||||
|
if (coll_bit_range[pp_data->caps[caps_idx].LinkCollection][pp_data->caps[caps_idx].ReportID][rt_idx]->LastBit < last_bit) {
|
||||||
|
coll_bit_range[pp_data->caps[caps_idx].LinkCollection][pp_data->caps[caps_idx].ReportID][rt_idx]->LastBit = last_bit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// *************************************************************************
|
||||||
|
// -Determine hierarchy levels of each collections and store it in:
|
||||||
|
// coll_levels[COLLECTION_INDEX]
|
||||||
|
// -Determine number of direct childs of each collections and store it in:
|
||||||
|
// coll_number_of_direct_childs[COLLECTION_INDEX]
|
||||||
|
// *************************************************************************
|
||||||
|
int max_coll_level = 0;
|
||||||
|
int *coll_levels = malloc(pp_data->NumberLinkCollectionNodes * sizeof(coll_levels[0]));
|
||||||
|
int *coll_number_of_direct_childs = malloc(pp_data->NumberLinkCollectionNodes * sizeof(coll_number_of_direct_childs[0]));
|
||||||
|
for (USHORT collection_node_idx = 0; collection_node_idx < pp_data->NumberLinkCollectionNodes; collection_node_idx++) {
|
||||||
|
coll_levels[collection_node_idx] = -1;
|
||||||
|
coll_number_of_direct_childs[collection_node_idx] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
int actual_coll_level = 0;
|
||||||
|
USHORT collection_node_idx = 0;
|
||||||
|
while (actual_coll_level >= 0) {
|
||||||
|
coll_levels[collection_node_idx] = actual_coll_level;
|
||||||
|
if ((link_collection_nodes[collection_node_idx].NumberOfChildren > 0) &&
|
||||||
|
(coll_levels[link_collection_nodes[collection_node_idx].FirstChild] == -1)) {
|
||||||
|
actual_coll_level++;
|
||||||
|
coll_levels[collection_node_idx] = actual_coll_level;
|
||||||
|
if (max_coll_level < actual_coll_level) {
|
||||||
|
max_coll_level = actual_coll_level;
|
||||||
|
}
|
||||||
|
coll_number_of_direct_childs[collection_node_idx]++;
|
||||||
|
collection_node_idx = link_collection_nodes[collection_node_idx].FirstChild;
|
||||||
|
}
|
||||||
|
else if (link_collection_nodes[collection_node_idx].NextSibling != 0) {
|
||||||
|
coll_number_of_direct_childs[link_collection_nodes[collection_node_idx].Parent]++;
|
||||||
|
collection_node_idx = link_collection_nodes[collection_node_idx].NextSibling;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
actual_coll_level--;
|
||||||
|
if (actual_coll_level >= 0) {
|
||||||
|
collection_node_idx = link_collection_nodes[collection_node_idx].Parent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// *********************************************************************************
|
||||||
|
// Propagate the bit range of each report from the child collections to their parent
|
||||||
|
// and store the merged result for the parent
|
||||||
|
// *********************************************************************************
|
||||||
|
for (int actual_coll_level = max_coll_level - 1; actual_coll_level >= 0; actual_coll_level--) {
|
||||||
|
for (USHORT collection_node_idx = 0; collection_node_idx < pp_data->NumberLinkCollectionNodes; collection_node_idx++) {
|
||||||
|
if (coll_levels[collection_node_idx] == actual_coll_level) {
|
||||||
|
USHORT child_idx = link_collection_nodes[collection_node_idx].FirstChild;
|
||||||
|
while (child_idx) {
|
||||||
|
for (int reportid_idx = 0; reportid_idx < 256; reportid_idx++) {
|
||||||
|
for (HIDP_REPORT_TYPE rt_idx = 0; rt_idx < NUM_OF_HIDP_REPORT_TYPES; rt_idx++) {
|
||||||
|
// Merge bit range from childs
|
||||||
|
if ((coll_bit_range[child_idx][reportid_idx][rt_idx]->FirstBit != -1) &&
|
||||||
|
(coll_bit_range[collection_node_idx][reportid_idx][rt_idx]->FirstBit > coll_bit_range[child_idx][reportid_idx][rt_idx]->FirstBit)) {
|
||||||
|
coll_bit_range[collection_node_idx][reportid_idx][rt_idx]->FirstBit = coll_bit_range[child_idx][reportid_idx][rt_idx]->FirstBit;
|
||||||
|
}
|
||||||
|
if (coll_bit_range[collection_node_idx][reportid_idx][rt_idx]->LastBit < coll_bit_range[child_idx][reportid_idx][rt_idx]->LastBit) {
|
||||||
|
coll_bit_range[collection_node_idx][reportid_idx][rt_idx]->LastBit = coll_bit_range[child_idx][reportid_idx][rt_idx]->LastBit;
|
||||||
|
}
|
||||||
|
child_idx = link_collection_nodes[child_idx].NextSibling;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// **************************************************************************************************
|
||||||
|
// Determine child collection order of the whole hierarchy, based on previously determined bit ranges
|
||||||
|
// and store it this index coll_child_order[COLLECTION_INDEX][DIRECT_CHILD_INDEX]
|
||||||
|
// **************************************************************************************************
|
||||||
|
USHORT **coll_child_order;
|
||||||
|
coll_child_order = malloc(pp_data->NumberLinkCollectionNodes * sizeof(*coll_child_order));
|
||||||
|
{
|
||||||
|
BOOLEAN *coll_parsed_flag;
|
||||||
|
coll_parsed_flag = malloc(pp_data->NumberLinkCollectionNodes * sizeof(coll_parsed_flag[0]));
|
||||||
|
for (USHORT collection_node_idx = 0; collection_node_idx < pp_data->NumberLinkCollectionNodes; collection_node_idx++) {
|
||||||
|
coll_parsed_flag[collection_node_idx] = FALSE;
|
||||||
|
}
|
||||||
|
int actual_coll_level = 0;
|
||||||
|
USHORT collection_node_idx = 0;
|
||||||
|
while (actual_coll_level >= 0) {
|
||||||
|
if ((coll_number_of_direct_childs[collection_node_idx] != 0) &&
|
||||||
|
(coll_parsed_flag[link_collection_nodes[collection_node_idx].FirstChild] == FALSE)) {
|
||||||
|
coll_parsed_flag[link_collection_nodes[collection_node_idx].FirstChild] = TRUE;
|
||||||
|
coll_child_order[collection_node_idx] = malloc((coll_number_of_direct_childs[collection_node_idx]) * sizeof(*coll_child_order[0]));
|
||||||
|
|
||||||
|
{
|
||||||
|
// Create list of child collection indices
|
||||||
|
// sorted reverse to the order returned to HidP_GetLinkCollectionNodeschild
|
||||||
|
// which seems to match the original order, as long as no bit position needs to be considered
|
||||||
|
USHORT child_idx = link_collection_nodes[collection_node_idx].FirstChild;
|
||||||
|
int child_count = coll_number_of_direct_childs[collection_node_idx] - 1;
|
||||||
|
coll_child_order[collection_node_idx][child_count] = child_idx;
|
||||||
|
while (link_collection_nodes[child_idx].NextSibling) {
|
||||||
|
child_count--;
|
||||||
|
child_idx = link_collection_nodes[child_idx].NextSibling;
|
||||||
|
coll_child_order[collection_node_idx][child_count] = child_idx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (coll_number_of_direct_childs[collection_node_idx] > 1) {
|
||||||
|
// Sort child collections indices by bit positions
|
||||||
|
for (HIDP_REPORT_TYPE rt_idx = 0; rt_idx < NUM_OF_HIDP_REPORT_TYPES; rt_idx++) {
|
||||||
|
for (int reportid_idx = 0; reportid_idx < 256; reportid_idx++) {
|
||||||
|
for (int child_idx = 1; child_idx < coll_number_of_direct_childs[collection_node_idx]; child_idx++) {
|
||||||
|
// since the coll_bit_range array is not sorted, we need to reference the collection index in
|
||||||
|
// our sorted coll_child_order array, and look up the corresponding bit ranges for comparing values to sort
|
||||||
|
int prev_coll_idx = coll_child_order[collection_node_idx][child_idx - 1];
|
||||||
|
int cur_coll_idx = coll_child_order[collection_node_idx][child_idx];
|
||||||
|
if ((coll_bit_range[prev_coll_idx][reportid_idx][rt_idx]->FirstBit != -1) &&
|
||||||
|
(coll_bit_range[cur_coll_idx][reportid_idx][rt_idx]->FirstBit != -1) &&
|
||||||
|
(coll_bit_range[prev_coll_idx][reportid_idx][rt_idx]->FirstBit > coll_bit_range[cur_coll_idx][reportid_idx][rt_idx]->FirstBit)) {
|
||||||
|
// Swap position indices of the two compared child collections
|
||||||
|
USHORT idx_latch = coll_child_order[collection_node_idx][child_idx - 1];
|
||||||
|
coll_child_order[collection_node_idx][child_idx - 1] = coll_child_order[collection_node_idx][child_idx];
|
||||||
|
coll_child_order[collection_node_idx][child_idx] = idx_latch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
actual_coll_level++;
|
||||||
|
collection_node_idx = link_collection_nodes[collection_node_idx].FirstChild;
|
||||||
|
}
|
||||||
|
else if (link_collection_nodes[collection_node_idx].NextSibling != 0) {
|
||||||
|
collection_node_idx = link_collection_nodes[collection_node_idx].NextSibling;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
actual_coll_level--;
|
||||||
|
if (actual_coll_level >= 0) {
|
||||||
|
collection_node_idx = link_collection_nodes[collection_node_idx].Parent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(coll_parsed_flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ***************************************************************************************
|
||||||
|
// Create sorted main_item_list containing all the Collection and CollectionEnd main items
|
||||||
|
// ***************************************************************************************
|
||||||
|
struct rd_main_item_node *main_item_list = NULL; // List root
|
||||||
|
// Lookup table to find the Collection items in the list by index
|
||||||
|
struct rd_main_item_node **coll_begin_lookup = malloc(pp_data->NumberLinkCollectionNodes * sizeof(*coll_begin_lookup));
|
||||||
|
struct rd_main_item_node **coll_end_lookup = malloc(pp_data->NumberLinkCollectionNodes * sizeof(*coll_end_lookup));
|
||||||
|
{
|
||||||
|
int *coll_last_written_child = malloc(pp_data->NumberLinkCollectionNodes * sizeof(coll_last_written_child[0]));
|
||||||
|
for (USHORT collection_node_idx = 0; collection_node_idx < pp_data->NumberLinkCollectionNodes; collection_node_idx++) {
|
||||||
|
coll_last_written_child[collection_node_idx] = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int actual_coll_level = 0;
|
||||||
|
USHORT collection_node_idx = 0;
|
||||||
|
struct rd_main_item_node *firstDelimiterNode = NULL;
|
||||||
|
struct rd_main_item_node *delimiterCloseNode = NULL;
|
||||||
|
coll_begin_lookup[0] = rd_append_main_item_node(0, 0, rd_item_node_collection, 0, collection_node_idx, rd_collection, 0, &main_item_list);
|
||||||
|
while (actual_coll_level >= 0) {
|
||||||
|
if ((coll_number_of_direct_childs[collection_node_idx] != 0) &&
|
||||||
|
(coll_last_written_child[collection_node_idx] == -1)) {
|
||||||
|
// Collection has child collections, but none is written to the list yet
|
||||||
|
|
||||||
|
coll_last_written_child[collection_node_idx] = coll_child_order[collection_node_idx][0];
|
||||||
|
collection_node_idx = coll_child_order[collection_node_idx][0];
|
||||||
|
|
||||||
|
// In a HID Report Descriptor, the first usage declared is the most preferred usage for the control.
|
||||||
|
// While the order in the WIN32 capabiliy strutures is the opposite:
|
||||||
|
// Here the preferred usage is the last aliased usage in the sequence.
|
||||||
|
|
||||||
|
if (link_collection_nodes[collection_node_idx].IsAlias && (firstDelimiterNode == NULL)) {
|
||||||
|
// Alliased Collection (First node in link_collection_nodes -> Last entry in report descriptor output)
|
||||||
|
firstDelimiterNode = main_item_list;
|
||||||
|
coll_begin_lookup[collection_node_idx] = rd_append_main_item_node(0, 0, rd_item_node_collection, 0, collection_node_idx, rd_delimiter_usage, 0, &main_item_list);
|
||||||
|
coll_begin_lookup[collection_node_idx] = rd_append_main_item_node(0, 0, rd_item_node_collection, 0, collection_node_idx, rd_delimiter_close, 0, &main_item_list);
|
||||||
|
delimiterCloseNode = main_item_list;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Normal not aliased collection
|
||||||
|
coll_begin_lookup[collection_node_idx] = rd_append_main_item_node(0, 0, rd_item_node_collection, 0, collection_node_idx, rd_collection, 0, &main_item_list);
|
||||||
|
actual_coll_level++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
else if ((coll_number_of_direct_childs[collection_node_idx] > 1) &&
|
||||||
|
(coll_last_written_child[collection_node_idx] != coll_child_order[collection_node_idx][coll_number_of_direct_childs[collection_node_idx] - 1])) {
|
||||||
|
// Collection has child collections, and this is not the first child
|
||||||
|
|
||||||
|
int nextChild = 1;
|
||||||
|
while (coll_last_written_child[collection_node_idx] != coll_child_order[collection_node_idx][nextChild - 1]) {
|
||||||
|
nextChild++;
|
||||||
|
}
|
||||||
|
coll_last_written_child[collection_node_idx] = coll_child_order[collection_node_idx][nextChild];
|
||||||
|
collection_node_idx = coll_child_order[collection_node_idx][nextChild];
|
||||||
|
|
||||||
|
if (link_collection_nodes[collection_node_idx].IsAlias && (firstDelimiterNode == NULL)) {
|
||||||
|
// Alliased Collection (First node in link_collection_nodes -> Last entry in report descriptor output)
|
||||||
|
firstDelimiterNode = main_item_list;
|
||||||
|
coll_begin_lookup[collection_node_idx] = rd_append_main_item_node(0, 0, rd_item_node_collection, 0, collection_node_idx, rd_delimiter_usage, 0, &main_item_list);
|
||||||
|
coll_begin_lookup[collection_node_idx] = rd_append_main_item_node(0, 0, rd_item_node_collection, 0, collection_node_idx, rd_delimiter_close, 0, &main_item_list);
|
||||||
|
delimiterCloseNode = main_item_list;
|
||||||
|
}
|
||||||
|
else if (link_collection_nodes[collection_node_idx].IsAlias && (firstDelimiterNode != NULL)) {
|
||||||
|
coll_begin_lookup[collection_node_idx] = rd_insert_main_item_node(0, 0, rd_item_node_collection, 0, collection_node_idx, rd_delimiter_usage, 0, &firstDelimiterNode);
|
||||||
|
}
|
||||||
|
else if (!link_collection_nodes[collection_node_idx].IsAlias && (firstDelimiterNode != NULL)) {
|
||||||
|
coll_begin_lookup[collection_node_idx] = rd_insert_main_item_node(0, 0, rd_item_node_collection, 0, collection_node_idx, rd_delimiter_usage, 0, &firstDelimiterNode);
|
||||||
|
coll_begin_lookup[collection_node_idx] = rd_insert_main_item_node(0, 0, rd_item_node_collection, 0, collection_node_idx, rd_delimiter_open, 0, &firstDelimiterNode);
|
||||||
|
firstDelimiterNode = NULL;
|
||||||
|
main_item_list = delimiterCloseNode;
|
||||||
|
delimiterCloseNode = NULL; // Last entry of alias has .IsAlias == FALSE
|
||||||
|
}
|
||||||
|
if (!link_collection_nodes[collection_node_idx].IsAlias) {
|
||||||
|
coll_begin_lookup[collection_node_idx] = rd_append_main_item_node(0, 0, rd_item_node_collection, 0, collection_node_idx, rd_collection, 0, &main_item_list);
|
||||||
|
actual_coll_level++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
actual_coll_level--;
|
||||||
|
coll_end_lookup[collection_node_idx] = rd_append_main_item_node(0, 0, rd_item_node_collection, 0, collection_node_idx, rd_collection_end, 0, &main_item_list);
|
||||||
|
collection_node_idx = link_collection_nodes[collection_node_idx].Parent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(coll_last_written_child);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ****************************************************************
|
||||||
|
// Inserted Input/Output/Feature main items into the main_item_list
|
||||||
|
// in order of reconstructed bit positions
|
||||||
|
// ****************************************************************
|
||||||
|
for (HIDP_REPORT_TYPE rt_idx = 0; rt_idx < NUM_OF_HIDP_REPORT_TYPES; rt_idx++) {
|
||||||
|
// Add all value caps to node list
|
||||||
|
struct rd_main_item_node *firstDelimiterNode = NULL;
|
||||||
|
struct rd_main_item_node *delimiterCloseNode = NULL;
|
||||||
|
for (USHORT caps_idx = pp_data->caps_info[rt_idx].FirstCap; caps_idx < pp_data->caps_info[rt_idx].LastCap; caps_idx++) {
|
||||||
|
struct rd_main_item_node *coll_begin = coll_begin_lookup[pp_data->caps[caps_idx].LinkCollection];
|
||||||
|
int first_bit, last_bit;
|
||||||
|
first_bit = (pp_data->caps[caps_idx].BytePosition - 1) * 8 +
|
||||||
|
pp_data->caps[caps_idx].BitPosition;
|
||||||
|
last_bit = first_bit + pp_data->caps[caps_idx].ReportSize *
|
||||||
|
pp_data->caps[caps_idx].ReportCount - 1;
|
||||||
|
|
||||||
|
for (int child_idx = 0; child_idx < coll_number_of_direct_childs[pp_data->caps[caps_idx].LinkCollection]; child_idx++) {
|
||||||
|
// Determine in which section before/between/after child collection the item should be inserted
|
||||||
|
if (first_bit < coll_bit_range[coll_child_order[pp_data->caps[caps_idx].LinkCollection][child_idx]][pp_data->caps[caps_idx].ReportID][rt_idx]->FirstBit)
|
||||||
|
{
|
||||||
|
// Note, that the default value for undefined coll_bit_range is -1, which can't be greater than the bit position
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
coll_begin = coll_end_lookup[coll_child_order[pp_data->caps[caps_idx].LinkCollection][child_idx]];
|
||||||
|
}
|
||||||
|
struct rd_main_item_node *list_node;
|
||||||
|
list_node = rd_search_main_item_list_for_bit_position(first_bit, (rd_main_items) rt_idx, pp_data->caps[caps_idx].ReportID, &coll_begin);
|
||||||
|
|
||||||
|
// In a HID Report Descriptor, the first usage declared is the most preferred usage for the control.
|
||||||
|
// While the order in the WIN32 capabiliy strutures is the opposite:
|
||||||
|
// Here the preferred usage is the last aliased usage in the sequence.
|
||||||
|
|
||||||
|
if (pp_data->caps[caps_idx].IsAlias && (firstDelimiterNode == NULL)) {
|
||||||
|
// Alliased Usage (First node in pp_data->caps -> Last entry in report descriptor output)
|
||||||
|
firstDelimiterNode = list_node;
|
||||||
|
rd_insert_main_item_node(first_bit, last_bit, rd_item_node_cap, caps_idx, pp_data->caps[caps_idx].LinkCollection, rd_delimiter_usage, pp_data->caps[caps_idx].ReportID, &list_node);
|
||||||
|
rd_insert_main_item_node(first_bit, last_bit, rd_item_node_cap, caps_idx, pp_data->caps[caps_idx].LinkCollection, rd_delimiter_close, pp_data->caps[caps_idx].ReportID, &list_node);
|
||||||
|
delimiterCloseNode = list_node;
|
||||||
|
} else if (pp_data->caps[caps_idx].IsAlias && (firstDelimiterNode != NULL)) {
|
||||||
|
rd_insert_main_item_node(first_bit, last_bit, rd_item_node_cap, caps_idx, pp_data->caps[caps_idx].LinkCollection, rd_delimiter_usage, pp_data->caps[caps_idx].ReportID, &list_node);
|
||||||
|
}
|
||||||
|
else if (!pp_data->caps[caps_idx].IsAlias && (firstDelimiterNode != NULL)) {
|
||||||
|
// Alliased Collection (Last node in pp_data->caps -> First entry in report descriptor output)
|
||||||
|
rd_insert_main_item_node(first_bit, last_bit, rd_item_node_cap, caps_idx, pp_data->caps[caps_idx].LinkCollection, rd_delimiter_usage, pp_data->caps[caps_idx].ReportID, &list_node);
|
||||||
|
rd_insert_main_item_node(first_bit, last_bit, rd_item_node_cap, caps_idx, pp_data->caps[caps_idx].LinkCollection, rd_delimiter_open, pp_data->caps[caps_idx].ReportID, &list_node);
|
||||||
|
firstDelimiterNode = NULL;
|
||||||
|
list_node = delimiterCloseNode;
|
||||||
|
delimiterCloseNode = NULL; // Last entry of alias has .IsAlias == FALSE
|
||||||
|
}
|
||||||
|
if (!pp_data->caps[caps_idx].IsAlias) {
|
||||||
|
rd_insert_main_item_node(first_bit, last_bit, rd_item_node_cap, caps_idx, pp_data->caps[caps_idx].LinkCollection, (rd_main_items) rt_idx, pp_data->caps[caps_idx].ReportID, &list_node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ***********************************************************
|
||||||
|
// Add const main items for padding to main_item_list
|
||||||
|
// -To fill all bit gaps
|
||||||
|
// -At each report end for 8bit padding
|
||||||
|
// Note that information about the padding at the report end,
|
||||||
|
// is not stored in the preparsed data, but in practice all
|
||||||
|
// report descriptors seem to have it, as assumed here.
|
||||||
|
// ***********************************************************
|
||||||
|
{
|
||||||
|
int last_bit_position[NUM_OF_HIDP_REPORT_TYPES][256];
|
||||||
|
struct rd_main_item_node *last_report_item_lookup[NUM_OF_HIDP_REPORT_TYPES][256];
|
||||||
|
for (HIDP_REPORT_TYPE rt_idx = 0; rt_idx < NUM_OF_HIDP_REPORT_TYPES; rt_idx++) {
|
||||||
|
for (int reportid_idx = 0; reportid_idx < 256; reportid_idx++) {
|
||||||
|
last_bit_position[rt_idx][reportid_idx] = -1;
|
||||||
|
last_report_item_lookup[rt_idx][reportid_idx] = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct rd_main_item_node *list = main_item_list; // List root;
|
||||||
|
|
||||||
|
while (list->next != NULL)
|
||||||
|
{
|
||||||
|
if ((list->MainItemType >= rd_input) &&
|
||||||
|
(list->MainItemType <= rd_feature)) {
|
||||||
|
// INPUT, OUTPUT or FEATURE
|
||||||
|
if (list->FirstBit != -1) {
|
||||||
|
if ((last_bit_position[list->MainItemType][list->ReportID] + 1 != list->FirstBit) &&
|
||||||
|
(last_report_item_lookup[list->MainItemType][list->ReportID] != NULL) &&
|
||||||
|
(last_report_item_lookup[list->MainItemType][list->ReportID]->FirstBit != list->FirstBit) // Happens in case of IsMultipleItemsForArray for multiple dedicated usages for a multi-button array
|
||||||
|
) {
|
||||||
|
struct rd_main_item_node *list_node = rd_search_main_item_list_for_bit_position(last_bit_position[list->MainItemType][list->ReportID], list->MainItemType, list->ReportID, &last_report_item_lookup[list->MainItemType][list->ReportID]);
|
||||||
|
rd_insert_main_item_node(last_bit_position[list->MainItemType][list->ReportID] + 1, list->FirstBit - 1, rd_item_node_padding, -1, 0, list->MainItemType, list->ReportID, &list_node);
|
||||||
|
}
|
||||||
|
last_bit_position[list->MainItemType][list->ReportID] = list->LastBit;
|
||||||
|
last_report_item_lookup[list->MainItemType][list->ReportID] = list;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
list = list->next;
|
||||||
|
}
|
||||||
|
// Add 8 bit padding at each report end
|
||||||
|
for (HIDP_REPORT_TYPE rt_idx = 0; rt_idx < NUM_OF_HIDP_REPORT_TYPES; rt_idx++) {
|
||||||
|
for (int reportid_idx = 0; reportid_idx < 256; reportid_idx++) {
|
||||||
|
if (last_bit_position[rt_idx][reportid_idx] != -1) {
|
||||||
|
int padding = 8 - ((last_bit_position[rt_idx][reportid_idx] + 1) % 8);
|
||||||
|
if (padding < 8) {
|
||||||
|
// Insert padding item after item referenced in last_report_item_lookup
|
||||||
|
rd_insert_main_item_node(last_bit_position[rt_idx][reportid_idx] + 1, last_bit_position[rt_idx][reportid_idx] + padding, rd_item_node_padding, -1, 0, (rd_main_items) rt_idx, (unsigned char) reportid_idx, &last_report_item_lookup[rt_idx][reportid_idx]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ***********************************
|
||||||
|
// Encode the report descriptor output
|
||||||
|
// ***********************************
|
||||||
|
UCHAR last_report_id = 0;
|
||||||
|
USAGE last_usage_page = 0;
|
||||||
|
LONG last_physical_min = 0;// If both, Physical Minimum and Physical Maximum are 0, the logical limits should be taken as physical limits according USB HID spec 1.11 chapter 6.2.2.7
|
||||||
|
LONG last_physical_max = 0;
|
||||||
|
ULONG last_unit_exponent = 0; // If Unit Exponent is Undefined it should be considered as 0 according USB HID spec 1.11 chapter 6.2.2.7
|
||||||
|
ULONG last_unit = 0; // If the first nibble is 7, or second nibble of Unit is 0, the unit is None according USB HID spec 1.11 chapter 6.2.2.7
|
||||||
|
BOOLEAN inhibit_write_of_usage = FALSE; // Needed in case of delimited usage print, before the normal collection or cap
|
||||||
|
int report_count = 0;
|
||||||
|
while (main_item_list != NULL)
|
||||||
|
{
|
||||||
|
int rt_idx = main_item_list->MainItemType;
|
||||||
|
int caps_idx = main_item_list->CapsIndex;
|
||||||
|
if (main_item_list->MainItemType == rd_collection) {
|
||||||
|
if (last_usage_page != link_collection_nodes[main_item_list->CollectionIndex].LinkUsagePage) {
|
||||||
|
// Write "Usage Page" at the begin of a collection - except it refers the same table as wrote last
|
||||||
|
rd_write_short_item(rd_global_usage_page, link_collection_nodes[main_item_list->CollectionIndex].LinkUsagePage, &rpt_desc);
|
||||||
|
last_usage_page = link_collection_nodes[main_item_list->CollectionIndex].LinkUsagePage;
|
||||||
|
}
|
||||||
|
if (inhibit_write_of_usage) {
|
||||||
|
// Inhibit only once after DELIMITER statement
|
||||||
|
inhibit_write_of_usage = FALSE;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Write "Usage" of collection
|
||||||
|
rd_write_short_item(rd_local_usage, link_collection_nodes[main_item_list->CollectionIndex].LinkUsage, &rpt_desc);
|
||||||
|
}
|
||||||
|
// Write begin of "Collection"
|
||||||
|
rd_write_short_item(rd_main_collection, link_collection_nodes[main_item_list->CollectionIndex].CollectionType, &rpt_desc);
|
||||||
|
}
|
||||||
|
else if (main_item_list->MainItemType == rd_collection_end) {
|
||||||
|
// Write "End Collection"
|
||||||
|
rd_write_short_item(rd_main_collection_end, 0, &rpt_desc);
|
||||||
|
}
|
||||||
|
else if (main_item_list->MainItemType == rd_delimiter_open) {
|
||||||
|
if (main_item_list->CollectionIndex != -1) {
|
||||||
|
// Write "Usage Page" inside of a collection delmiter section
|
||||||
|
if (last_usage_page != link_collection_nodes[main_item_list->CollectionIndex].LinkUsagePage) {
|
||||||
|
rd_write_short_item(rd_global_usage_page, link_collection_nodes[main_item_list->CollectionIndex].LinkUsagePage, &rpt_desc);
|
||||||
|
last_usage_page = link_collection_nodes[main_item_list->CollectionIndex].LinkUsagePage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (main_item_list->CapsIndex != 0) {
|
||||||
|
// Write "Usage Page" inside of a main item delmiter section
|
||||||
|
if (pp_data->caps[caps_idx].UsagePage != last_usage_page) {
|
||||||
|
rd_write_short_item(rd_global_usage_page, pp_data->caps[caps_idx].UsagePage, &rpt_desc);
|
||||||
|
last_usage_page = pp_data->caps[caps_idx].UsagePage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Write "Delimiter Open"
|
||||||
|
rd_write_short_item(rd_local_delimiter, 1, &rpt_desc); // 1 = open set of aliased usages
|
||||||
|
}
|
||||||
|
else if (main_item_list->MainItemType == rd_delimiter_usage) {
|
||||||
|
if (main_item_list->CollectionIndex != -1) {
|
||||||
|
// Write aliased collection "Usage"
|
||||||
|
rd_write_short_item(rd_local_usage, link_collection_nodes[main_item_list->CollectionIndex].LinkUsage, &rpt_desc);
|
||||||
|
} if (main_item_list->CapsIndex != 0) {
|
||||||
|
// Write aliased main item range from "Usage Minimum" to "Usage Maximum"
|
||||||
|
if (pp_data->caps[caps_idx].IsRange) {
|
||||||
|
rd_write_short_item(rd_local_usage_minimum, pp_data->caps[caps_idx].Range.UsageMin, &rpt_desc);
|
||||||
|
rd_write_short_item(rd_local_usage_maximum, pp_data->caps[caps_idx].Range.UsageMax, &rpt_desc);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Write single aliased main item "Usage"
|
||||||
|
rd_write_short_item(rd_local_usage, pp_data->caps[caps_idx].NotRange.Usage, &rpt_desc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (main_item_list->MainItemType == rd_delimiter_close) {
|
||||||
|
// Write "Delimiter Close"
|
||||||
|
rd_write_short_item(rd_local_delimiter, 0, &rpt_desc); // 0 = close set of aliased usages
|
||||||
|
// Inhibit next usage write
|
||||||
|
inhibit_write_of_usage = TRUE;
|
||||||
|
}
|
||||||
|
else if (main_item_list->TypeOfNode == rd_item_node_padding) {
|
||||||
|
// Padding
|
||||||
|
// The preparsed data doesn't contain any information about padding. Therefore all undefined gaps
|
||||||
|
// in the reports are filled with the same style of constant padding.
|
||||||
|
|
||||||
|
// Write "Report Size" with number of padding bits
|
||||||
|
rd_write_short_item(rd_global_report_size, (main_item_list->LastBit - main_item_list->FirstBit + 1), &rpt_desc);
|
||||||
|
|
||||||
|
// Write "Report Count" for padding always as 1
|
||||||
|
rd_write_short_item(rd_global_report_count, 1, &rpt_desc);
|
||||||
|
|
||||||
|
if (rt_idx == HidP_Input) {
|
||||||
|
// Write "Input" main item - We know it's Constant - We can only guess the other bits, but they don't matter in case of const
|
||||||
|
rd_write_short_item(rd_main_input, 0x03, &rpt_desc); // Const / Abs
|
||||||
|
}
|
||||||
|
else if (rt_idx == HidP_Output) {
|
||||||
|
// Write "Output" main item - We know it's Constant - We can only guess the other bits, but they don't matter in case of const
|
||||||
|
rd_write_short_item(rd_main_output, 0x03, &rpt_desc); // Const / Abs
|
||||||
|
}
|
||||||
|
else if (rt_idx == HidP_Feature) {
|
||||||
|
// Write "Feature" main item - We know it's Constant - We can only guess the other bits, but they don't matter in case of const
|
||||||
|
rd_write_short_item(rd_main_feature, 0x03, &rpt_desc); // Const / Abs
|
||||||
|
}
|
||||||
|
report_count = 0;
|
||||||
|
}
|
||||||
|
else if (pp_data->caps[caps_idx].IsButtonCap) {
|
||||||
|
// Button
|
||||||
|
// (The preparsed data contain different data for 1 bit Button caps, than for parametric Value caps)
|
||||||
|
|
||||||
|
if (last_report_id != pp_data->caps[caps_idx].ReportID) {
|
||||||
|
// Write "Report ID" if changed
|
||||||
|
rd_write_short_item(rd_global_report_id, pp_data->caps[caps_idx].ReportID, &rpt_desc);
|
||||||
|
last_report_id = pp_data->caps[caps_idx].ReportID;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write "Usage Page" when changed
|
||||||
|
if (pp_data->caps[caps_idx].UsagePage != last_usage_page) {
|
||||||
|
rd_write_short_item(rd_global_usage_page, pp_data->caps[caps_idx].UsagePage, &rpt_desc);
|
||||||
|
last_usage_page = pp_data->caps[caps_idx].UsagePage;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write only local report items for each cap, if ReportCount > 1
|
||||||
|
if (pp_data->caps[caps_idx].IsRange) {
|
||||||
|
report_count += (pp_data->caps[caps_idx].Range.DataIndexMax - pp_data->caps[caps_idx].Range.DataIndexMin);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inhibit_write_of_usage) {
|
||||||
|
// Inhibit only once after Delimiter - Reset flag
|
||||||
|
inhibit_write_of_usage = FALSE;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (pp_data->caps[caps_idx].IsRange) {
|
||||||
|
// Write range from "Usage Minimum" to "Usage Maximum"
|
||||||
|
rd_write_short_item(rd_local_usage_minimum, pp_data->caps[caps_idx].Range.UsageMin, &rpt_desc);
|
||||||
|
rd_write_short_item(rd_local_usage_maximum, pp_data->caps[caps_idx].Range.UsageMax, &rpt_desc);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Write single "Usage"
|
||||||
|
rd_write_short_item(rd_local_usage, pp_data->caps[caps_idx].NotRange.Usage, &rpt_desc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pp_data->caps[caps_idx].IsDesignatorRange) {
|
||||||
|
// Write physical descriptor indices range from "Designator Minimum" to "Designator Maximum"
|
||||||
|
rd_write_short_item(rd_local_designator_minimum, pp_data->caps[caps_idx].Range.DesignatorMin, &rpt_desc);
|
||||||
|
rd_write_short_item(rd_local_designator_maximum, pp_data->caps[caps_idx].Range.DesignatorMax, &rpt_desc);
|
||||||
|
}
|
||||||
|
else if (pp_data->caps[caps_idx].NotRange.DesignatorIndex != 0) {
|
||||||
|
// Designator set 0 is a special descriptor set (of the HID Physical Descriptor),
|
||||||
|
// that specifies the number of additional descriptor sets.
|
||||||
|
// Therefore Designator Index 0 can never be a useful reference for a control and we can inhibit it.
|
||||||
|
// Write single "Designator Index"
|
||||||
|
rd_write_short_item(rd_local_designator_index, pp_data->caps[caps_idx].NotRange.DesignatorIndex, &rpt_desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pp_data->caps[caps_idx].IsStringRange) {
|
||||||
|
// Write range of indices of the USB string descriptor, from "String Minimum" to "String Maximum"
|
||||||
|
rd_write_short_item(rd_local_string_minimum, pp_data->caps[caps_idx].Range.StringMin, &rpt_desc);
|
||||||
|
rd_write_short_item(rd_local_string_maximum, pp_data->caps[caps_idx].Range.StringMax, &rpt_desc);
|
||||||
|
}
|
||||||
|
else if (pp_data->caps[caps_idx].NotRange.StringIndex != 0) {
|
||||||
|
// String Index 0 is a special entry of the USB string descriptor, that contains a list of supported languages,
|
||||||
|
// therefore Designator Index 0 can never be a useful reference for a control and we can inhibit it.
|
||||||
|
// Write single "String Index"
|
||||||
|
rd_write_short_item(rd_local_string, pp_data->caps[caps_idx].NotRange.StringIndex, &rpt_desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((main_item_list->next != NULL) &&
|
||||||
|
((int)main_item_list->next->MainItemType == rt_idx) &&
|
||||||
|
(main_item_list->next->TypeOfNode == rd_item_node_cap) &&
|
||||||
|
(pp_data->caps[main_item_list->next->CapsIndex].IsButtonCap) &&
|
||||||
|
(!pp_data->caps[caps_idx].IsRange) && // This node in list is no array
|
||||||
|
(!pp_data->caps[main_item_list->next->CapsIndex].IsRange) && // Next node in list is no array
|
||||||
|
(pp_data->caps[main_item_list->next->CapsIndex].UsagePage == pp_data->caps[caps_idx].UsagePage) &&
|
||||||
|
(pp_data->caps[main_item_list->next->CapsIndex].ReportID == pp_data->caps[caps_idx].ReportID) &&
|
||||||
|
(pp_data->caps[main_item_list->next->CapsIndex].BitField == pp_data->caps[caps_idx].BitField)
|
||||||
|
) {
|
||||||
|
if (main_item_list->next->FirstBit != main_item_list->FirstBit) {
|
||||||
|
// In case of IsMultipleItemsForArray for multiple dedicated usages for a multi-button array, the report count should be incremented
|
||||||
|
|
||||||
|
// Skip global items until any of them changes, than use ReportCount item to write the count of identical report fields
|
||||||
|
report_count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
if ((pp_data->caps[caps_idx].Button.LogicalMin == 0) &&
|
||||||
|
(pp_data->caps[caps_idx].Button.LogicalMax == 0)) {
|
||||||
|
// While a HID report descriptor must always contain LogicalMinimum and LogicalMaximum,
|
||||||
|
// the preparsed data contain both fields set to zero, for the case of simple buttons
|
||||||
|
// Write "Logical Minimum" set to 0 and "Logical Maximum" set to 1
|
||||||
|
rd_write_short_item(rd_global_logical_minimum, 0, &rpt_desc);
|
||||||
|
rd_write_short_item(rd_global_logical_maximum, 1, &rpt_desc);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Write logical range from "Logical Minimum" to "Logical Maximum"
|
||||||
|
rd_write_short_item(rd_global_logical_minimum, pp_data->caps[caps_idx].Button.LogicalMin, &rpt_desc);
|
||||||
|
rd_write_short_item(rd_global_logical_maximum, pp_data->caps[caps_idx].Button.LogicalMax, &rpt_desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write "Report Size"
|
||||||
|
rd_write_short_item(rd_global_report_size, pp_data->caps[caps_idx].ReportSize, &rpt_desc);
|
||||||
|
|
||||||
|
// Write "Report Count"
|
||||||
|
if (!pp_data->caps[caps_idx].IsRange) {
|
||||||
|
// Variable bit field with one bit per button
|
||||||
|
// In case of multiple usages with the same items, only "Usage" is written per cap, and "Report Count" is incremented
|
||||||
|
rd_write_short_item(rd_global_report_count, pp_data->caps[caps_idx].ReportCount + report_count, &rpt_desc);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Button array of "Report Size" x "Report Count
|
||||||
|
rd_write_short_item(rd_global_report_count, pp_data->caps[caps_idx].ReportCount, &rpt_desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Buttons have only 1 bit and therefore no physical limits/units -> Set to undefined state
|
||||||
|
if (last_physical_min != 0) {
|
||||||
|
// Write "Physical Minimum", but only if changed
|
||||||
|
last_physical_min = 0;
|
||||||
|
rd_write_short_item(rd_global_physical_minimum, last_physical_min, &rpt_desc);
|
||||||
|
}
|
||||||
|
if (last_physical_max != 0) {
|
||||||
|
// Write "Physical Maximum", but only if changed
|
||||||
|
last_physical_max = 0;
|
||||||
|
rd_write_short_item(rd_global_physical_maximum, last_physical_max, &rpt_desc);
|
||||||
|
}
|
||||||
|
if (last_unit_exponent != 0) {
|
||||||
|
// Write "Unit Exponent", but only if changed
|
||||||
|
last_unit_exponent = 0;
|
||||||
|
rd_write_short_item(rd_global_unit_exponent, last_unit_exponent, &rpt_desc);
|
||||||
|
}
|
||||||
|
if (last_unit != 0) {
|
||||||
|
// Write "Unit",but only if changed
|
||||||
|
last_unit = 0;
|
||||||
|
rd_write_short_item(rd_global_unit, last_unit, &rpt_desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write "Input" main item
|
||||||
|
if (rt_idx == HidP_Input) {
|
||||||
|
rd_write_short_item(rd_main_input, pp_data->caps[caps_idx].BitField, &rpt_desc);
|
||||||
|
}
|
||||||
|
// Write "Output" main item
|
||||||
|
else if (rt_idx == HidP_Output) {
|
||||||
|
rd_write_short_item(rd_main_output, pp_data->caps[caps_idx].BitField, &rpt_desc);
|
||||||
|
}
|
||||||
|
// Write "Feature" main item
|
||||||
|
else if (rt_idx == HidP_Feature) {
|
||||||
|
rd_write_short_item(rd_main_feature, pp_data->caps[caps_idx].BitField, &rpt_desc);
|
||||||
|
}
|
||||||
|
report_count = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
if (last_report_id != pp_data->caps[caps_idx].ReportID) {
|
||||||
|
// Write "Report ID" if changed
|
||||||
|
rd_write_short_item(rd_global_report_id, pp_data->caps[caps_idx].ReportID, &rpt_desc);
|
||||||
|
last_report_id = pp_data->caps[caps_idx].ReportID;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write "Usage Page" if changed
|
||||||
|
if (pp_data->caps[caps_idx].UsagePage != last_usage_page) {
|
||||||
|
rd_write_short_item(rd_global_usage_page, pp_data->caps[caps_idx].UsagePage, &rpt_desc);
|
||||||
|
last_usage_page = pp_data->caps[caps_idx].UsagePage;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inhibit_write_of_usage) {
|
||||||
|
// Inhibit only once after Delimiter - Reset flag
|
||||||
|
inhibit_write_of_usage = FALSE;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (pp_data->caps[caps_idx].IsRange) {
|
||||||
|
// Write usage range from "Usage Minimum" to "Usage Maximum"
|
||||||
|
rd_write_short_item(rd_local_usage_minimum, pp_data->caps[caps_idx].Range.UsageMin, &rpt_desc);
|
||||||
|
rd_write_short_item(rd_local_usage_maximum, pp_data->caps[caps_idx].Range.UsageMax, &rpt_desc);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Write single "Usage"
|
||||||
|
rd_write_short_item(rd_local_usage, pp_data->caps[caps_idx].NotRange.Usage, &rpt_desc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pp_data->caps[caps_idx].IsDesignatorRange) {
|
||||||
|
// Write physical descriptor indices range from "Designator Minimum" to "Designator Maximum"
|
||||||
|
rd_write_short_item(rd_local_designator_minimum, pp_data->caps[caps_idx].Range.DesignatorMin, &rpt_desc);
|
||||||
|
rd_write_short_item(rd_local_designator_maximum, pp_data->caps[caps_idx].Range.DesignatorMax, &rpt_desc);
|
||||||
|
}
|
||||||
|
else if (pp_data->caps[caps_idx].NotRange.DesignatorIndex != 0) {
|
||||||
|
// Designator set 0 is a special descriptor set (of the HID Physical Descriptor),
|
||||||
|
// that specifies the number of additional descriptor sets.
|
||||||
|
// Therefore Designator Index 0 can never be a useful reference for a control and we can inhibit it.
|
||||||
|
// Write single "Designator Index"
|
||||||
|
rd_write_short_item(rd_local_designator_index, pp_data->caps[caps_idx].NotRange.DesignatorIndex, &rpt_desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pp_data->caps[caps_idx].IsStringRange) {
|
||||||
|
// Write range of indices of the USB string descriptor, from "String Minimum" to "String Maximum"
|
||||||
|
rd_write_short_item(rd_local_string_minimum, pp_data->caps[caps_idx].Range.StringMin, &rpt_desc);
|
||||||
|
rd_write_short_item(rd_local_string_maximum, pp_data->caps[caps_idx].Range.StringMax, &rpt_desc);
|
||||||
|
}
|
||||||
|
else if (pp_data->caps[caps_idx].NotRange.StringIndex != 0) {
|
||||||
|
// String Index 0 is a special entry of the USB string descriptor, that contains a list of supported languages,
|
||||||
|
// therefore Designator Index 0 can never be a useful reference for a control and we can inhibit it.
|
||||||
|
// Write single "String Index"
|
||||||
|
rd_write_short_item(rd_local_string, pp_data->caps[caps_idx].NotRange.StringIndex, &rpt_desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((pp_data->caps[caps_idx].BitField & 0x02) != 0x02) {
|
||||||
|
// In case of an value array overwrite "Report Count"
|
||||||
|
pp_data->caps[caps_idx].ReportCount = pp_data->caps[caps_idx].Range.DataIndexMax - pp_data->caps[caps_idx].Range.DataIndexMin + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Print only local report items for each cap, if ReportCount > 1
|
||||||
|
if ((main_item_list->next != NULL) &&
|
||||||
|
((int) main_item_list->next->MainItemType == rt_idx) &&
|
||||||
|
(main_item_list->next->TypeOfNode == rd_item_node_cap) &&
|
||||||
|
(!pp_data->caps[main_item_list->next->CapsIndex].IsButtonCap) &&
|
||||||
|
(!pp_data->caps[caps_idx].IsRange) && // This node in list is no array
|
||||||
|
(!pp_data->caps[main_item_list->next->CapsIndex].IsRange) && // Next node in list is no array
|
||||||
|
(pp_data->caps[main_item_list->next->CapsIndex].UsagePage == pp_data->caps[caps_idx].UsagePage) &&
|
||||||
|
(pp_data->caps[main_item_list->next->CapsIndex].NotButton.LogicalMin == pp_data->caps[caps_idx].NotButton.LogicalMin) &&
|
||||||
|
(pp_data->caps[main_item_list->next->CapsIndex].NotButton.LogicalMax == pp_data->caps[caps_idx].NotButton.LogicalMax) &&
|
||||||
|
(pp_data->caps[main_item_list->next->CapsIndex].NotButton.PhysicalMin == pp_data->caps[caps_idx].NotButton.PhysicalMin) &&
|
||||||
|
(pp_data->caps[main_item_list->next->CapsIndex].NotButton.PhysicalMax == pp_data->caps[caps_idx].NotButton.PhysicalMax) &&
|
||||||
|
(pp_data->caps[main_item_list->next->CapsIndex].UnitsExp == pp_data->caps[caps_idx].UnitsExp) &&
|
||||||
|
(pp_data->caps[main_item_list->next->CapsIndex].Units == pp_data->caps[caps_idx].Units) &&
|
||||||
|
(pp_data->caps[main_item_list->next->CapsIndex].ReportSize == pp_data->caps[caps_idx].ReportSize) &&
|
||||||
|
(pp_data->caps[main_item_list->next->CapsIndex].ReportID == pp_data->caps[caps_idx].ReportID) &&
|
||||||
|
(pp_data->caps[main_item_list->next->CapsIndex].BitField == pp_data->caps[caps_idx].BitField) &&
|
||||||
|
(pp_data->caps[main_item_list->next->CapsIndex].ReportCount == 1) &&
|
||||||
|
(pp_data->caps[caps_idx].ReportCount == 1)
|
||||||
|
) {
|
||||||
|
// Skip global items until any of them changes, than use ReportCount item to write the count of identical report fields
|
||||||
|
report_count++;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Value
|
||||||
|
|
||||||
|
// Write logical range from "Logical Minimum" to "Logical Maximum"
|
||||||
|
rd_write_short_item(rd_global_logical_minimum, pp_data->caps[caps_idx].NotButton.LogicalMin, &rpt_desc);
|
||||||
|
rd_write_short_item(rd_global_logical_maximum, pp_data->caps[caps_idx].NotButton.LogicalMax, &rpt_desc);
|
||||||
|
|
||||||
|
if ((last_physical_min != pp_data->caps[caps_idx].NotButton.PhysicalMin) ||
|
||||||
|
(last_physical_max != pp_data->caps[caps_idx].NotButton.PhysicalMax)) {
|
||||||
|
// Write range from "Physical Minimum" to " Physical Maximum", but only if one of them changed
|
||||||
|
rd_write_short_item(rd_global_physical_minimum, pp_data->caps[caps_idx].NotButton.PhysicalMin, &rpt_desc);
|
||||||
|
last_physical_min = pp_data->caps[caps_idx].NotButton.PhysicalMin;
|
||||||
|
rd_write_short_item(rd_global_physical_maximum, pp_data->caps[caps_idx].NotButton.PhysicalMax, &rpt_desc);
|
||||||
|
last_physical_max = pp_data->caps[caps_idx].NotButton.PhysicalMax;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (last_unit_exponent != pp_data->caps[caps_idx].UnitsExp) {
|
||||||
|
// Write "Unit Exponent", but only if changed
|
||||||
|
rd_write_short_item(rd_global_unit_exponent, pp_data->caps[caps_idx].UnitsExp, &rpt_desc);
|
||||||
|
last_unit_exponent = pp_data->caps[caps_idx].UnitsExp;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (last_unit != pp_data->caps[caps_idx].Units) {
|
||||||
|
// Write physical "Unit", but only if changed
|
||||||
|
rd_write_short_item(rd_global_unit, pp_data->caps[caps_idx].Units, &rpt_desc);
|
||||||
|
last_unit = pp_data->caps[caps_idx].Units;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write "Report Size"
|
||||||
|
rd_write_short_item(rd_global_report_size, pp_data->caps[caps_idx].ReportSize, &rpt_desc);
|
||||||
|
|
||||||
|
// Write "Report Count"
|
||||||
|
rd_write_short_item(rd_global_report_count, pp_data->caps[caps_idx].ReportCount + report_count, &rpt_desc);
|
||||||
|
|
||||||
|
if (rt_idx == HidP_Input) {
|
||||||
|
// Write "Input" main item
|
||||||
|
rd_write_short_item(rd_main_input, pp_data->caps[caps_idx].BitField, &rpt_desc);
|
||||||
|
}
|
||||||
|
else if (rt_idx == HidP_Output) {
|
||||||
|
// Write "Output" main item
|
||||||
|
rd_write_short_item(rd_main_output, pp_data->caps[caps_idx].BitField, &rpt_desc);
|
||||||
|
}
|
||||||
|
else if (rt_idx == HidP_Feature) {
|
||||||
|
// Write "Feature" main item
|
||||||
|
rd_write_short_item(rd_main_feature, pp_data->caps[caps_idx].BitField, &rpt_desc);
|
||||||
|
}
|
||||||
|
report_count = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Go to next item in main_item_list and free the memory of the actual item
|
||||||
|
struct rd_main_item_node *main_item_list_prev = main_item_list;
|
||||||
|
main_item_list = main_item_list->next;
|
||||||
|
free(main_item_list_prev);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Free multidimensionable array: coll_bit_range[COLLECTION_INDEX][REPORT_ID][INPUT/OUTPUT/FEATURE]
|
||||||
|
// Free multidimensionable array: coll_child_order[COLLECTION_INDEX][DIRECT_CHILD_INDEX]
|
||||||
|
for (USHORT collection_node_idx = 0; collection_node_idx < pp_data->NumberLinkCollectionNodes; collection_node_idx++) {
|
||||||
|
for (int reportid_idx = 0; reportid_idx < 256; reportid_idx++) {
|
||||||
|
for (HIDP_REPORT_TYPE rt_idx = 0; rt_idx < NUM_OF_HIDP_REPORT_TYPES; rt_idx++) {
|
||||||
|
free(coll_bit_range[collection_node_idx][reportid_idx][rt_idx]);
|
||||||
|
}
|
||||||
|
free(coll_bit_range[collection_node_idx][reportid_idx]);
|
||||||
|
}
|
||||||
|
free(coll_bit_range[collection_node_idx]);
|
||||||
|
if (coll_number_of_direct_childs[collection_node_idx] != 0) free(coll_child_order[collection_node_idx]);
|
||||||
|
}
|
||||||
|
free(coll_bit_range);
|
||||||
|
free(coll_child_order);
|
||||||
|
|
||||||
|
// Free one dimensional arrays
|
||||||
|
free(coll_begin_lookup);
|
||||||
|
free(coll_end_lookup);
|
||||||
|
free(coll_levels);
|
||||||
|
free(coll_number_of_direct_childs);
|
||||||
|
|
||||||
|
return (int) rpt_desc.byte_idx;
|
||||||
|
}
|
247
libs/hidapi/windows/hidapi_descriptor_reconstruct.h
Normal file
247
libs/hidapi/windows/hidapi_descriptor_reconstruct.h
Normal file
@ -0,0 +1,247 @@
|
|||||||
|
/*******************************************************
|
||||||
|
HIDAPI - Multi-Platform library for
|
||||||
|
communication with HID devices.
|
||||||
|
|
||||||
|
libusb/hidapi Team
|
||||||
|
|
||||||
|
Copyright 2022, All Rights Reserved.
|
||||||
|
|
||||||
|
At the discretion of the user of this library,
|
||||||
|
this software may be licensed under the terms of the
|
||||||
|
GNU General Public License v3, a BSD-Style license, or the
|
||||||
|
original HIDAPI license as outlined in the LICENSE.txt,
|
||||||
|
LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt
|
||||||
|
files located at the root of the source distribution.
|
||||||
|
These files may also be found in the public source
|
||||||
|
code repository located at:
|
||||||
|
https://github.com/libusb/hidapi .
|
||||||
|
********************************************************/
|
||||||
|
#ifndef HIDAPI_DESCRIPTOR_RECONSTRUCT_H__
|
||||||
|
#define HIDAPI_DESCRIPTOR_RECONSTRUCT_H__
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
|
||||||
|
/* Do not warn about wcsncpy usage.
|
||||||
|
https://docs.microsoft.com/cpp/c-runtime-library/security-features-in-the-crt */
|
||||||
|
#define _CRT_SECURE_NO_WARNINGS
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "hidapi_winapi.h"
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable: 4200)
|
||||||
|
#pragma warning(disable: 4201)
|
||||||
|
#pragma warning(disable: 4214)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#include "hidapi_hidsdi.h"
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#define NUM_OF_HIDP_REPORT_TYPES 3
|
||||||
|
|
||||||
|
typedef enum rd_items_ {
|
||||||
|
rd_main_input = 0x80, /* 1000 00 nn */
|
||||||
|
rd_main_output = 0x90, /* 1001 00 nn */
|
||||||
|
rd_main_feature = 0xB0, /* 1011 00 nn */
|
||||||
|
rd_main_collection = 0xA0, /* 1010 00 nn */
|
||||||
|
rd_main_collection_end = 0xC0, /* 1100 00 nn */
|
||||||
|
rd_global_usage_page = 0x04, /* 0000 01 nn */
|
||||||
|
rd_global_logical_minimum = 0x14, /* 0001 01 nn */
|
||||||
|
rd_global_logical_maximum = 0x24, /* 0010 01 nn */
|
||||||
|
rd_global_physical_minimum = 0x34, /* 0011 01 nn */
|
||||||
|
rd_global_physical_maximum = 0x44, /* 0100 01 nn */
|
||||||
|
rd_global_unit_exponent = 0x54, /* 0101 01 nn */
|
||||||
|
rd_global_unit = 0x64, /* 0110 01 nn */
|
||||||
|
rd_global_report_size = 0x74, /* 0111 01 nn */
|
||||||
|
rd_global_report_id = 0x84, /* 1000 01 nn */
|
||||||
|
rd_global_report_count = 0x94, /* 1001 01 nn */
|
||||||
|
rd_global_push = 0xA4, /* 1010 01 nn */
|
||||||
|
rd_global_pop = 0xB4, /* 1011 01 nn */
|
||||||
|
rd_local_usage = 0x08, /* 0000 10 nn */
|
||||||
|
rd_local_usage_minimum = 0x18, /* 0001 10 nn */
|
||||||
|
rd_local_usage_maximum = 0x28, /* 0010 10 nn */
|
||||||
|
rd_local_designator_index = 0x38, /* 0011 10 nn */
|
||||||
|
rd_local_designator_minimum = 0x48, /* 0100 10 nn */
|
||||||
|
rd_local_designator_maximum = 0x58, /* 0101 10 nn */
|
||||||
|
rd_local_string = 0x78, /* 0111 10 nn */
|
||||||
|
rd_local_string_minimum = 0x88, /* 1000 10 nn */
|
||||||
|
rd_local_string_maximum = 0x98, /* 1001 10 nn */
|
||||||
|
rd_local_delimiter = 0xA8 /* 1010 10 nn */
|
||||||
|
} rd_items;
|
||||||
|
|
||||||
|
typedef enum rd_main_items_ {
|
||||||
|
rd_input = HidP_Input,
|
||||||
|
rd_output = HidP_Output,
|
||||||
|
rd_feature = HidP_Feature,
|
||||||
|
rd_collection,
|
||||||
|
rd_collection_end,
|
||||||
|
rd_delimiter_open,
|
||||||
|
rd_delimiter_usage,
|
||||||
|
rd_delimiter_close,
|
||||||
|
} rd_main_items;
|
||||||
|
|
||||||
|
typedef struct rd_bit_range_ {
|
||||||
|
int FirstBit;
|
||||||
|
int LastBit;
|
||||||
|
} rd_bit_range;
|
||||||
|
|
||||||
|
typedef enum rd_item_node_type_ {
|
||||||
|
rd_item_node_cap,
|
||||||
|
rd_item_node_padding,
|
||||||
|
rd_item_node_collection,
|
||||||
|
} rd_node_type;
|
||||||
|
|
||||||
|
struct rd_main_item_node {
|
||||||
|
int FirstBit; /* Position of first bit in report (counting from 0) */
|
||||||
|
int LastBit; /* Position of last bit in report (counting from 0) */
|
||||||
|
rd_node_type TypeOfNode; /* Information if caps index refers to the array of button caps, value caps,
|
||||||
|
or if the node is just a padding element to fill unused bit positions.
|
||||||
|
The node can also be a collection node without any bits in the report. */
|
||||||
|
int CapsIndex; /* Index in the array of caps */
|
||||||
|
int CollectionIndex; /* Index in the array of link collections */
|
||||||
|
rd_main_items MainItemType; /* Input, Output, Feature, Collection or Collection End */
|
||||||
|
unsigned char ReportID;
|
||||||
|
struct rd_main_item_node* next;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct hid_pp_caps_info_ {
|
||||||
|
USHORT FirstCap;
|
||||||
|
USHORT NumberOfCaps; // Includes empty caps after LastCap
|
||||||
|
USHORT LastCap;
|
||||||
|
USHORT ReportByteLength;
|
||||||
|
} hid_pp_caps_info, *phid_pp_caps_info;
|
||||||
|
|
||||||
|
typedef struct hid_pp_link_collection_node_ {
|
||||||
|
USAGE LinkUsage;
|
||||||
|
USAGE LinkUsagePage;
|
||||||
|
USHORT Parent;
|
||||||
|
USHORT NumberOfChildren;
|
||||||
|
USHORT NextSibling;
|
||||||
|
USHORT FirstChild;
|
||||||
|
ULONG CollectionType : 8;
|
||||||
|
ULONG IsAlias : 1;
|
||||||
|
ULONG Reserved : 23;
|
||||||
|
// Same as the public API structure HIDP_LINK_COLLECTION_NODE, but without PVOID UserContext at the end
|
||||||
|
} hid_pp_link_collection_node, *phid_pp_link_collection_node;
|
||||||
|
|
||||||
|
// Note: This is risk-reduction-measure for this specific struct, as it has ULONG bit-field.
|
||||||
|
// Although very unlikely, it might still be possible that the compiler creates a memory layout that is
|
||||||
|
// not binary compatile.
|
||||||
|
// Other structs are not checked at the time of writing.
|
||||||
|
static_assert(sizeof(struct hid_pp_link_collection_node_) == 16,
|
||||||
|
"Size of struct hid_pp_link_collection_node_ not as expected. This might break binary compatibility");
|
||||||
|
|
||||||
|
typedef struct hidp_unknown_token_ {
|
||||||
|
UCHAR Token; /* Specifies the one-byte prefix of a global item. */
|
||||||
|
UCHAR Reserved[3];
|
||||||
|
ULONG BitField; /* Specifies the data part of the global item. */
|
||||||
|
} hidp_unknown_token, * phidp_unknown_token;
|
||||||
|
|
||||||
|
typedef struct hid_pp_cap_ {
|
||||||
|
USAGE UsagePage;
|
||||||
|
UCHAR ReportID;
|
||||||
|
UCHAR BitPosition;
|
||||||
|
USHORT ReportSize; // WIN32 term for this is BitSize
|
||||||
|
USHORT ReportCount;
|
||||||
|
USHORT BytePosition;
|
||||||
|
USHORT BitCount;
|
||||||
|
ULONG BitField;
|
||||||
|
USHORT NextBytePosition;
|
||||||
|
USHORT LinkCollection;
|
||||||
|
USAGE LinkUsagePage;
|
||||||
|
USAGE LinkUsage;
|
||||||
|
|
||||||
|
// Start of 8 Flags in one byte
|
||||||
|
BOOLEAN IsMultipleItemsForArray:1;
|
||||||
|
|
||||||
|
BOOLEAN IsPadding:1;
|
||||||
|
BOOLEAN IsButtonCap:1;
|
||||||
|
BOOLEAN IsAbsolute:1;
|
||||||
|
BOOLEAN IsRange:1;
|
||||||
|
BOOLEAN IsAlias:1; // IsAlias is set to TRUE in the first n-1 capability structures added to the capability array. IsAlias set to FALSE in the nth capability structure.
|
||||||
|
BOOLEAN IsStringRange:1;
|
||||||
|
BOOLEAN IsDesignatorRange:1;
|
||||||
|
// End of 8 Flags in one byte
|
||||||
|
BOOLEAN Reserved1[3];
|
||||||
|
|
||||||
|
hidp_unknown_token UnknownTokens[4]; // 4 x 8 Byte
|
||||||
|
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
USAGE UsageMin;
|
||||||
|
USAGE UsageMax;
|
||||||
|
USHORT StringMin;
|
||||||
|
USHORT StringMax;
|
||||||
|
USHORT DesignatorMin;
|
||||||
|
USHORT DesignatorMax;
|
||||||
|
USHORT DataIndexMin;
|
||||||
|
USHORT DataIndexMax;
|
||||||
|
} Range;
|
||||||
|
struct {
|
||||||
|
USAGE Usage;
|
||||||
|
USAGE Reserved1;
|
||||||
|
USHORT StringIndex;
|
||||||
|
USHORT Reserved2;
|
||||||
|
USHORT DesignatorIndex;
|
||||||
|
USHORT Reserved3;
|
||||||
|
USHORT DataIndex;
|
||||||
|
USHORT Reserved4;
|
||||||
|
} NotRange;
|
||||||
|
};
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
LONG LogicalMin;
|
||||||
|
LONG LogicalMax;
|
||||||
|
} Button;
|
||||||
|
struct {
|
||||||
|
BOOLEAN HasNull;
|
||||||
|
UCHAR Reserved4[3];
|
||||||
|
LONG LogicalMin;
|
||||||
|
LONG LogicalMax;
|
||||||
|
LONG PhysicalMin;
|
||||||
|
LONG PhysicalMax;
|
||||||
|
} NotButton;
|
||||||
|
};
|
||||||
|
ULONG Units;
|
||||||
|
ULONG UnitsExp;
|
||||||
|
|
||||||
|
} hid_pp_cap, *phid_pp_cap;
|
||||||
|
|
||||||
|
typedef struct hidp_preparsed_data_ {
|
||||||
|
UCHAR MagicKey[8];
|
||||||
|
USAGE Usage;
|
||||||
|
USAGE UsagePage;
|
||||||
|
USHORT Reserved[2];
|
||||||
|
|
||||||
|
// CAPS structure for Input, Output and Feature
|
||||||
|
hid_pp_caps_info caps_info[3];
|
||||||
|
|
||||||
|
USHORT FirstByteOfLinkCollectionArray;
|
||||||
|
USHORT NumberLinkCollectionNodes;
|
||||||
|
|
||||||
|
#ifndef _MSC_VER
|
||||||
|
// MINGW fails with: Flexible array member in union not supported
|
||||||
|
// Solution: https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html
|
||||||
|
union {
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#pragma GCC diagnostic ignored "-Wpedantic"
|
||||||
|
hid_pp_cap caps[0];
|
||||||
|
hid_pp_link_collection_node LinkCollectionArray[0];
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
|
};
|
||||||
|
#else
|
||||||
|
union {
|
||||||
|
hid_pp_cap caps[];
|
||||||
|
hid_pp_link_collection_node LinkCollectionArray[];
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} hidp_preparsed_data;
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
38
libs/hidapi/windows/hidapi_hidclass.h
Normal file
38
libs/hidapi/windows/hidapi_hidclass.h
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
/*******************************************************
|
||||||
|
HIDAPI - Multi-Platform library for
|
||||||
|
communication with HID devices.
|
||||||
|
|
||||||
|
libusb/hidapi Team
|
||||||
|
|
||||||
|
Copyright 2022, All Rights Reserved.
|
||||||
|
|
||||||
|
At the discretion of the user of this library,
|
||||||
|
this software may be licensed under the terms of the
|
||||||
|
GNU General Public License v3, a BSD-Style license, or the
|
||||||
|
original HIDAPI license as outlined in the LICENSE.txt,
|
||||||
|
LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt
|
||||||
|
files located at the root of the source distribution.
|
||||||
|
These files may also be found in the public source
|
||||||
|
code repository located at:
|
||||||
|
https://github.com/libusb/hidapi .
|
||||||
|
********************************************************/
|
||||||
|
|
||||||
|
#ifndef HIDAPI_HIDCLASS_H
|
||||||
|
#define HIDAPI_HIDCLASS_H
|
||||||
|
|
||||||
|
#ifdef HIDAPI_USE_DDK
|
||||||
|
|
||||||
|
#include <hidclass.h>
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
/* This part of the header mimics hidclass.h,
|
||||||
|
but only what is used by HIDAPI */
|
||||||
|
|
||||||
|
#define HID_OUT_CTL_CODE(id) CTL_CODE(FILE_DEVICE_KEYBOARD, (id), METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
|
||||||
|
#define IOCTL_HID_GET_FEATURE HID_OUT_CTL_CODE(100)
|
||||||
|
#define IOCTL_HID_GET_INPUT_REPORT HID_OUT_CTL_CODE(104)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* HIDAPI_HIDCLASS_H */
|
72
libs/hidapi/windows/hidapi_hidpi.h
Normal file
72
libs/hidapi/windows/hidapi_hidpi.h
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
/*******************************************************
|
||||||
|
HIDAPI - Multi-Platform library for
|
||||||
|
communication with HID devices.
|
||||||
|
|
||||||
|
libusb/hidapi Team
|
||||||
|
|
||||||
|
Copyright 2022, All Rights Reserved.
|
||||||
|
|
||||||
|
At the discretion of the user of this library,
|
||||||
|
this software may be licensed under the terms of the
|
||||||
|
GNU General Public License v3, a BSD-Style license, or the
|
||||||
|
original HIDAPI license as outlined in the LICENSE.txt,
|
||||||
|
LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt
|
||||||
|
files located at the root of the source distribution.
|
||||||
|
These files may also be found in the public source
|
||||||
|
code repository located at:
|
||||||
|
https://github.com/libusb/hidapi .
|
||||||
|
********************************************************/
|
||||||
|
|
||||||
|
#ifndef HIDAPI_HIDPI_H
|
||||||
|
#define HIDAPI_HIDPI_H
|
||||||
|
|
||||||
|
#ifdef HIDAPI_USE_DDK
|
||||||
|
|
||||||
|
#include <hidpi.h>
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
/* This part of the header mimics hidpi.h,
|
||||||
|
but only what is used by HIDAPI */
|
||||||
|
|
||||||
|
typedef enum _HIDP_REPORT_TYPE
|
||||||
|
{
|
||||||
|
HidP_Input,
|
||||||
|
HidP_Output,
|
||||||
|
HidP_Feature
|
||||||
|
} HIDP_REPORT_TYPE;
|
||||||
|
|
||||||
|
typedef struct _HIDP_PREPARSED_DATA * PHIDP_PREPARSED_DATA;
|
||||||
|
|
||||||
|
typedef struct _HIDP_CAPS
|
||||||
|
{
|
||||||
|
USAGE Usage;
|
||||||
|
USAGE UsagePage;
|
||||||
|
USHORT InputReportByteLength;
|
||||||
|
USHORT OutputReportByteLength;
|
||||||
|
USHORT FeatureReportByteLength;
|
||||||
|
USHORT Reserved[17];
|
||||||
|
|
||||||
|
USHORT NumberLinkCollectionNodes;
|
||||||
|
|
||||||
|
USHORT NumberInputButtonCaps;
|
||||||
|
USHORT NumberInputValueCaps;
|
||||||
|
USHORT NumberInputDataIndices;
|
||||||
|
|
||||||
|
USHORT NumberOutputButtonCaps;
|
||||||
|
USHORT NumberOutputValueCaps;
|
||||||
|
USHORT NumberOutputDataIndices;
|
||||||
|
|
||||||
|
USHORT NumberFeatureButtonCaps;
|
||||||
|
USHORT NumberFeatureValueCaps;
|
||||||
|
USHORT NumberFeatureDataIndices;
|
||||||
|
} HIDP_CAPS, *PHIDP_CAPS;
|
||||||
|
|
||||||
|
#define HIDP_STATUS_SUCCESS 0x00110000
|
||||||
|
#define HIDP_STATUS_INVALID_PREPARSED_DATA 0xc0110001
|
||||||
|
|
||||||
|
typedef NTSTATUS (__stdcall *HidP_GetCaps_)(PHIDP_PREPARSED_DATA preparsed_data, PHIDP_CAPS caps);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* HIDAPI_HIDPI_H */
|
59
libs/hidapi/windows/hidapi_hidsdi.h
Normal file
59
libs/hidapi/windows/hidapi_hidsdi.h
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
/*******************************************************
|
||||||
|
HIDAPI - Multi-Platform library for
|
||||||
|
communication with HID devices.
|
||||||
|
|
||||||
|
libusb/hidapi Team
|
||||||
|
|
||||||
|
Copyright 2022, All Rights Reserved.
|
||||||
|
|
||||||
|
At the discretion of the user of this library,
|
||||||
|
this software may be licensed under the terms of the
|
||||||
|
GNU General Public License v3, a BSD-Style license, or the
|
||||||
|
original HIDAPI license as outlined in the LICENSE.txt,
|
||||||
|
LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt
|
||||||
|
files located at the root of the source distribution.
|
||||||
|
These files may also be found in the public source
|
||||||
|
code repository located at:
|
||||||
|
https://github.com/libusb/hidapi .
|
||||||
|
********************************************************/
|
||||||
|
|
||||||
|
#ifndef HIDAPI_HIDSDI_H
|
||||||
|
#define HIDAPI_HIDSDI_H
|
||||||
|
|
||||||
|
#ifdef HIDAPI_USE_DDK
|
||||||
|
|
||||||
|
#include <hidsdi.h>
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
/* This part of the header mimics hidsdi.h,
|
||||||
|
but only what is used by HIDAPI */
|
||||||
|
|
||||||
|
typedef USHORT USAGE;
|
||||||
|
|
||||||
|
#include "hidapi_hidpi.h"
|
||||||
|
|
||||||
|
typedef struct _HIDD_ATTRIBUTES{
|
||||||
|
ULONG Size;
|
||||||
|
USHORT VendorID;
|
||||||
|
USHORT ProductID;
|
||||||
|
USHORT VersionNumber;
|
||||||
|
} HIDD_ATTRIBUTES, *PHIDD_ATTRIBUTES;
|
||||||
|
|
||||||
|
typedef void (__stdcall *HidD_GetHidGuid_)(LPGUID hid_guid);
|
||||||
|
typedef BOOLEAN (__stdcall *HidD_GetAttributes_)(HANDLE device, PHIDD_ATTRIBUTES attrib);
|
||||||
|
typedef BOOLEAN (__stdcall *HidD_GetSerialNumberString_)(HANDLE device, PVOID buffer, ULONG buffer_len);
|
||||||
|
typedef BOOLEAN (__stdcall *HidD_GetManufacturerString_)(HANDLE handle, PVOID buffer, ULONG buffer_len);
|
||||||
|
typedef BOOLEAN (__stdcall *HidD_GetProductString_)(HANDLE handle, PVOID buffer, ULONG buffer_len);
|
||||||
|
typedef BOOLEAN (__stdcall *HidD_SetFeature_)(HANDLE handle, PVOID data, ULONG length);
|
||||||
|
typedef BOOLEAN (__stdcall *HidD_GetFeature_)(HANDLE handle, PVOID data, ULONG length);
|
||||||
|
typedef BOOLEAN (__stdcall* HidD_SetOutputReport_)(HANDLE handle, PVOID data, ULONG length);
|
||||||
|
typedef BOOLEAN (__stdcall *HidD_GetInputReport_)(HANDLE handle, PVOID data, ULONG length);
|
||||||
|
typedef BOOLEAN (__stdcall *HidD_GetIndexedString_)(HANDLE handle, ULONG string_index, PVOID buffer, ULONG buffer_len);
|
||||||
|
typedef BOOLEAN (__stdcall *HidD_GetPreparsedData_)(HANDLE handle, PHIDP_PREPARSED_DATA *preparsed_data);
|
||||||
|
typedef BOOLEAN (__stdcall *HidD_FreePreparsedData_)(PHIDP_PREPARSED_DATA preparsed_data);
|
||||||
|
typedef BOOLEAN (__stdcall *HidD_SetNumInputBuffers_)(HANDLE handle, ULONG number_buffers);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* HIDAPI_HIDSDI_H */
|
74
libs/hidapi/windows/hidapi_winapi.h
Normal file
74
libs/hidapi/windows/hidapi_winapi.h
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
/*******************************************************
|
||||||
|
HIDAPI - Multi-Platform library for
|
||||||
|
communication with HID devices.
|
||||||
|
|
||||||
|
libusb/hidapi Team
|
||||||
|
|
||||||
|
Copyright 2022, All Rights Reserved.
|
||||||
|
|
||||||
|
At the discretion of the user of this library,
|
||||||
|
this software may be licensed under the terms of the
|
||||||
|
GNU General Public License v3, a BSD-Style license, or the
|
||||||
|
original HIDAPI license as outlined in the LICENSE.txt,
|
||||||
|
LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt
|
||||||
|
files located at the root of the source distribution.
|
||||||
|
These files may also be found in the public source
|
||||||
|
code repository located at:
|
||||||
|
https://github.com/libusb/hidapi .
|
||||||
|
********************************************************/
|
||||||
|
|
||||||
|
/** @file
|
||||||
|
* @defgroup API hidapi API
|
||||||
|
*
|
||||||
|
* Since version 0.12.0, @ref HID_API_VERSION >= HID_API_MAKE_VERSION(0, 12, 0)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HIDAPI_WINAPI_H__
|
||||||
|
#define HIDAPI_WINAPI_H__
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <guiddef.h>
|
||||||
|
|
||||||
|
#include "hidapi.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** @brief Get the container ID for a HID device.
|
||||||
|
|
||||||
|
Since version 0.12.0, @ref HID_API_VERSION >= HID_API_MAKE_VERSION(0, 12, 0)
|
||||||
|
|
||||||
|
This function returns the `DEVPKEY_Device_ContainerId` property of
|
||||||
|
the given device. This can be used to correlate different
|
||||||
|
interfaces/ports on the same hardware device.
|
||||||
|
|
||||||
|
@ingroup API
|
||||||
|
@param dev A device handle returned from hid_open().
|
||||||
|
@param container_id The device's container ID on return.
|
||||||
|
|
||||||
|
@returns
|
||||||
|
This function returns 0 on success and -1 on error.
|
||||||
|
*/
|
||||||
|
int HID_API_EXPORT_CALL hid_winapi_get_container_id(hid_device *dev, GUID *container_id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reconstructs a HID Report Descriptor from a Win32 HIDP_PREPARSED_DATA structure.
|
||||||
|
* This reconstructed report descriptor is logical identical to the real report descriptor,
|
||||||
|
* but not byte wise identical.
|
||||||
|
*
|
||||||
|
* @param[in] hidp_preparsed_data Pointer to the HIDP_PREPARSED_DATA to read, i.e.: the value of PHIDP_PREPARSED_DATA,
|
||||||
|
* as returned by HidD_GetPreparsedData WinAPI function.
|
||||||
|
* @param buf Pointer to the buffer where the report descriptor should be stored.
|
||||||
|
* @param[in] buf_size Size of the buffer. The recommended size for the buffer is @ref HID_API_MAX_REPORT_DESCRIPTOR_SIZE bytes.
|
||||||
|
*
|
||||||
|
* @return Returns size of reconstructed report descriptor if successful, -1 for error.
|
||||||
|
*/
|
||||||
|
int HID_API_EXPORT_CALL hid_winapi_descriptor_reconstruct_pp_data(void *hidp_preparsed_data, unsigned char *buf, size_t buf_size);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
@ -50,6 +50,7 @@ def build(bld):
|
|||||||
obj.source = 'mac/hid.c'
|
obj.source = 'mac/hid.c'
|
||||||
obj.framework = [ 'IOKit', 'CoreFoundation' ]
|
obj.framework = [ 'IOKit', 'CoreFoundation' ]
|
||||||
else:
|
else:
|
||||||
|
# with '-strict' this needs "-std=gnu99" to compile w/o warnings
|
||||||
obj.source = 'linux/hid.c'
|
obj.source = 'linux/hid.c'
|
||||||
if re.search ("linux", sys.platform) != None:
|
if re.search ("linux", sys.platform) != None:
|
||||||
obj.uselib = 'UDEV'
|
obj.uselib = 'UDEV'
|
||||||
|
Loading…
Reference in New Issue
Block a user