Sync with v0.10.1 (master)

This commit is contained in:
Ihor Dutchak
2020-11-26 22:51:45 +02:00
10 changed files with 383 additions and 110 deletions
+6
View File
@@ -1,4 +1,10 @@
image: archlinux
packages:
- autoconf
- automake
- libtool
- libusb
- libudev0
sources:
- https://github.com/libusb/hidapi
tasks:
+2
View File
@@ -20,3 +20,5 @@ windows/Makefile.in
Makefile
stamp-h1
libtool
.DS_Store
+1 -1
View File
@@ -1 +1 @@
0.9.0
0.10.1
+2 -2
View File
@@ -1,7 +1,7 @@
Pod::Spec.new do |spec|
spec.name = "hidapi"
spec.version = "<fill me up from VERSION file, before submit>"
spec.version = File.read('../VERSION')
spec.summary = "A Simple library for communicating with USB and Bluetooth HID devices on Linux, Mac and Windows."
spec.description = <<-DESC
@@ -26,6 +26,6 @@ Pod::Spec.new do |spec|
spec.public_header_files = "hidapi/hidapi.h"
spec.frameworks = "IOKit", "CoreFoundation"
spec.frameworks = "IOKit", "CoreFoundation", "AppKit"
end
+7 -7
View File
@@ -48,12 +48,12 @@
@ingroup API
*/
#define HID_API_VERSION_MINOR 9
#define HID_API_VERSION_MINOR 10
/** @brief Static/compile-time patch version of the library.
@ingroup API
*/
#define HID_API_VERSION_PATCH 0
#define HID_API_VERSION_PATCH 1
/* Helper macros */
#define HID_API_AS_STR_IMPL(x) #x
@@ -96,10 +96,10 @@ extern "C" {
/** Product string */
wchar_t *product_string;
/** Usage Page for this Device/Interface
(Windows/Mac only). */
(Windows/Mac/hidraw only) */
unsigned short usage_page;
/** Usage for this Device/Interface
(Windows/Mac only).*/
(Windows/Mac/hidraw only) */
unsigned short usage;
/** The USB interface which this logical device
represents.
@@ -124,7 +124,7 @@ extern "C" {
needed. This function should be called at the beginning of
execution however, if there is a chance of HIDAPI handles
being opened by different threads simultaneously.
@ingroup API
@returns
@@ -478,7 +478,7 @@ extern "C" {
@returns
Pointer to statically allocated struct, that contains version.
*/
HID_API_EXPORT const struct hid_api_version* HID_API_CALL hid_version();
HID_API_EXPORT const struct hid_api_version* HID_API_CALL hid_version(void);
/** @brief Get a runtime version string of the library.
@@ -488,7 +488,7 @@ extern "C" {
@returns
Pointer to statically allocated string, that contains version string.
*/
HID_API_EXPORT const char* HID_API_CALL hid_version_str();
HID_API_EXPORT const char* HID_API_CALL hid_version_str(void);
#ifdef __cplusplus
}
+8 -10
View File
@@ -7,7 +7,7 @@
8/22/2009
Copyright 2009
This contents of this file may be used by anyone
for any reason without any conditions and may be
used as a starting point for your own applications
@@ -29,6 +29,9 @@
int main(int argc, char* argv[])
{
(void)argc;
(void)argv;
int res;
unsigned char buf[256];
#define MAX_STR 255
@@ -36,11 +39,6 @@ int main(int argc, char* argv[])
hid_device *handle;
int i;
#ifdef WIN32
UNREFERENCED_PARAMETER(argc);
UNREFERENCED_PARAMETER(argv);
#endif
struct hid_device_info *devs, *cur_dev;
printf("hidapi test/example tool. Compiled with hidapi version %s, runtime version %s.\n", HID_API_VERSION_STR, hid_version_str());
@@ -55,7 +53,7 @@ int main(int argc, char* argv[])
return -1;
devs = hid_enumerate(0x0, 0x0);
cur_dev = devs;
cur_dev = devs;
while (cur_dev) {
printf("Device Found\n type: %04hx %04hx\n path: %s\n serial_number: %ls", cur_dev->vendor_id, cur_dev->product_id, cur_dev->path, cur_dev->serial_number);
printf("\n");
@@ -73,7 +71,7 @@ int main(int argc, char* argv[])
memset(buf,0x00,sizeof(buf));
buf[0] = 0x01;
buf[1] = 0x81;
// Open the device using the VID, PID,
// and optionally the Serial number.
@@ -115,7 +113,7 @@ int main(int argc, char* argv[])
// Set the hid_read() function to be non-blocking.
hid_set_nonblocking(handle, 1);
// Try to read from the device. There should be no
// data here, but execution should not block.
res = hid_read(handle, buf, 17);
@@ -158,7 +156,7 @@ int main(int argc, char* argv[])
printf("Unable to write()\n");
printf("Error: %ls\n", hid_error(handle));
}
// Request state (cmd 0x81). The first byte is the report number (0x1).
buf[0] = 0x1;
+6 -2
View File
@@ -1098,18 +1098,21 @@ static void cleanup_mutex(void *param)
int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds)
{
int bytes_read = -1;
#if 0
int transferred;
int res = libusb_interrupt_transfer(dev->device_handle, dev->input_endpoint, data, length, &transferred, 5000);
LOG("transferred: %d\n", transferred);
return transferred;
#endif
/* by initialising this variable right here, GCC gives a compilation warning/error: */
/* error: variable bytes_read might be clobbered by longjmp or vfork [-Werror=clobbered] */
int bytes_read; /* = -1; */
pthread_mutex_lock(&dev->mutex);
pthread_cleanup_push(&cleanup_mutex, dev);
bytes_read = -1;
/* There's an input report queued up. Return it. */
if (dev->input_reports) {
/* Return the first one */
@@ -1359,6 +1362,7 @@ int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *dev, int string_index
HID_API_EXPORT const wchar_t * HID_API_CALL hid_error(hid_device *dev)
{
(void)dev;
return L"hid_error is not implemented yet";
}
+329 -85
View File
@@ -123,6 +123,19 @@ static void register_global_error(const char *msg)
last_global_error_str = utf8_to_wchar_t(msg);
}
/* See register_global_error, but you can pass a format string into this function. */
static void register_global_error_format(const char *format, ...)
{
va_list args;
va_start(args, format);
char msg[100];
vsnprintf(msg, sizeof(msg), format, args);
va_end(args);
register_global_error(msg);
}
/* Set the last error for a device to be reported by hid_error(device).
* The given error message will be copied (and decoded according to the
@@ -158,11 +171,67 @@ static wchar_t *copy_udev_string(struct udev_device *dev, const char *udev_name)
return utf8_to_wchar_t(udev_device_get_sysattr_value(dev, udev_name));
}
/*
* Gets the size of the HID item at the given position
* Returns 1 if successful, 0 if an invalid key
* Sets data_len and key_size when successful
*/
static int get_hid_item_size(__u8 *report_descriptor, unsigned int pos, __u32 size, int *data_len, int *key_size)
{
int key = report_descriptor[pos];
int size_code;
/*
* This is a Long Item. The next byte contains the
* length of the data section (value) for this key.
* See the HID specification, version 1.11, section
* 6.2.2.3, titled "Long Items."
*/
if ((key & 0xf0) == 0xf0) {
if (pos + 1 < size)
{
*data_len = report_descriptor[pos + 1];
*key_size = 3;
return 1;
}
*data_len = 0; /* malformed report */
*key_size = 0;
}
/*
* This is a Short Item. The bottom two bits of the
* key contain the size code for the data section
* (value) for this key. Refer to the HID
* specification, version 1.11, section 6.2.2.2,
* titled "Short Items."
*/
size_code = key & 0x3;
switch (size_code) {
case 0:
case 1:
case 2:
*data_len = size_code;
*key_size = 1;
return 1;
case 3:
*data_len = 4;
*key_size = 1;
return 1;
default:
/* Can't ever happen since size_code is & 0x3 */
*data_len = 0;
*key_size = 0;
break;
};
/* malformed report */
return 0;
}
/* uses_numbered_reports() returns 1 if report_descriptor describes a device
which contains numbered reports. */
static int uses_numbered_reports(__u8 *report_descriptor, __u32 size) {
unsigned int i = 0;
int size_code;
int data_len, key_size;
while (i < size) {
@@ -175,42 +244,9 @@ static int uses_numbered_reports(__u8 *report_descriptor, __u32 size) {
return 1;
}
//printf("key: %02hhx\n", key);
if ((key & 0xf0) == 0xf0) {
/* This is a Long Item. The next byte contains the
length of the data section (value) for this key.
See the HID specification, version 1.11, section
6.2.2.3, titled "Long Items." */
if (i+1 < size)
data_len = report_descriptor[i+1];
else
data_len = 0; /* malformed report */
key_size = 3;
}
else {
/* This is a Short Item. The bottom two bits of the
key contain the size code for the data section
(value) for this key. Refer to the HID
specification, version 1.11, section 6.2.2.2,
titled "Short Items." */
size_code = key & 0x3;
switch (size_code) {
case 0:
case 1:
case 2:
data_len = size_code;
break;
case 3:
data_len = 4;
break;
default:
/* Can't ever happen since size_code is & 0x3 */
data_len = 0;
break;
};
key_size = 1;
}
/* Determine data_len and key_size */
if (!get_hid_item_size(report_descriptor, i, size, &data_len, &key_size))
return 0; /* malformed report */
/* Skip over this key and it's associated data */
i += data_len + key_size;
@@ -220,12 +256,163 @@ static int uses_numbered_reports(__u8 *report_descriptor, __u32 size) {
return 0;
}
/*
* Get bytes from a HID Report Descriptor.
* Only call with a num_bytes of 0, 1, 2, or 4.
*/
static __u32 get_hid_report_bytes(__u8 *rpt, size_t len, size_t num_bytes, size_t cur)
{
/* Return if there aren't enough bytes. */
if (cur + num_bytes >= len)
return 0;
if (num_bytes == 0)
return 0;
else if (num_bytes == 1)
return rpt[cur + 1];
else if (num_bytes == 2)
return (rpt[cur + 2] * 256 + rpt[cur + 1]);
else if (num_bytes == 4)
return (
rpt[cur + 4] * 0x01000000 +
rpt[cur + 3] * 0x00010000 +
rpt[cur + 2] * 0x00000100 +
rpt[cur + 1] * 0x00000001
);
else
return 0;
}
/*
* Retrieves the device's Usage Page and Usage from the report descriptor.
* The algorithm returns the current Usage Page/Usage pair whenever a new
* Collection is found and a Usage Local Item is currently in scope.
* Usage Local Items are consumed by each Main Item (See. 6.2.2.8).
* The algorithm should give similar results as Apple's:
* https://developer.apple.com/documentation/iokit/kiohiddeviceusagepairskey?language=objc
* Physical Collections are also matched (macOS does the same).
*
* This function can be called repeatedly until it returns non-0
* Usage is found. pos is the starting point (initially 0) and will be updated
* to the next search position.
*
* The return value is 0 when a pair is found.
* 1 when finished processing descriptor.
* -1 on a malformed report.
*/
static int get_next_hid_usage(__u8 *report_descriptor, __u32 size, unsigned int *pos, unsigned short *usage_page, unsigned short *usage)
{
int data_len, key_size;
int initial = *pos == 0; /* Used to handle case where no top-level application collection is defined */
int usage_pair_ready = 0;
/* Usage is a Local Item, it must be set before each Main Item (Collection) before a pair is returned */
int usage_found = 0;
while (*pos < size) {
int key = report_descriptor[*pos];
int key_cmd = key & 0xfc;
/* Determine data_len and key_size */
if (!get_hid_item_size(report_descriptor, *pos, size, &data_len, &key_size))
return -1; /* malformed report */
switch (key_cmd) {
case 0x4: /* Usage Page 6.2.2.7 (Global) */
*usage_page = get_hid_report_bytes(report_descriptor, size, data_len, *pos);
break;
case 0x8: /* Usage 6.2.2.8 (Local) */
*usage = get_hid_report_bytes(report_descriptor, size, data_len, *pos);
usage_found = 1;
break;
case 0xa0: /* Collection 6.2.2.4 (Main) */
/* A Usage Item (Local) must be found for the pair to be valid */
if (usage_found)
usage_pair_ready = 1;
/* Usage is a Local Item, unset it */
usage_found = 0;
break;
case 0x80: /* Input 6.2.2.4 (Main) */
case 0x90: /* Output 6.2.2.4 (Main) */
case 0xb0: /* Feature 6.2.2.4 (Main) */
case 0xc0: /* End Collection 6.2.2.4 (Main) */
/* Usage is a Local Item, unset it */
usage_found = 0;
break;
}
/* Skip over this key and it's associated data */
*pos += data_len + key_size;
/* Return usage pair */
if (usage_pair_ready)
return 0;
}
/* If no top-level application collection is found and usage page/usage pair is found, pair is valid
https://docs.microsoft.com/en-us/windows-hardware/drivers/hid/top-level-collections */
if (initial && usage_found)
return 0; /* success */
return 1; /* finished processing */
}
/*
* Retrieves the hidraw report descriptor from a file.
* When using this form, <sysfs_path>/device/report_descriptor, elevated priviledges are not required.
*/
static int get_hid_report_descriptor(const char *rpt_path, struct hidraw_report_descriptor *rpt_desc)
{
int rpt_handle;
ssize_t res;
rpt_handle = open(rpt_path, O_RDONLY);
if (rpt_handle < 0) {
register_global_error_format("open failed (%s): %s", rpt_path, strerror(errno));
return -1;
}
/*
* Read in the Report Descriptor
* The sysfs file has a maximum size of 4096 (which is the same as HID_MAX_DESCRIPTOR_SIZE) so we should always
* be ok when reading the descriptor.
* In practice if the HID descriptor is any larger I suspect many other things will break.
*/
memset(rpt_desc, 0x0, sizeof(*rpt_desc));
res = read(rpt_handle, rpt_desc->value, HID_MAX_DESCRIPTOR_SIZE);
if (res < 0) {
register_global_error_format("read failed (%s): %s", rpt_path, strerror(errno));
}
rpt_desc->size = (__u32) res;
close(rpt_handle);
return (int) res;
}
static int get_hid_report_descriptor_from_sysfs(const char *sysfs_path, struct hidraw_report_descriptor *rpt_desc)
{
int res = -1;
/* Construct <sysfs_path>/device/report_descriptor */
size_t rpt_path_len = strlen(sysfs_path) + 25 + 1;
char* rpt_path = (char*) calloc(1, rpt_path_len);
snprintf(rpt_path, rpt_path_len, "%s/device/report_descriptor", sysfs_path);
res = get_hid_report_descriptor(rpt_path, rpt_desc);
free(rpt_path);
return res;
}
/*
* The caller is responsible for free()ing the (newly-allocated) character
* strings pointed to by serial_number_utf8 and product_name_utf8 after use.
*/
static int
parse_uevent_info(const char *uevent, int *bus_type,
parse_uevent_info(const char *uevent, unsigned *bus_type,
unsigned short *vendor_id, unsigned short *product_id,
char **serial_number_utf8, char **product_name_utf8)
{
@@ -284,8 +471,8 @@ static int get_device_string(hid_device *dev, enum device_string_id key, wchar_t
struct udev_device *udev_dev, *parent, *hid_dev;
struct stat s;
int ret = -1;
char *serial_number_utf8 = NULL;
char *product_name_utf8 = NULL;
char *serial_number_utf8 = NULL;
char *product_name_utf8 = NULL;
/* Create the udev object */
udev = udev_new();
@@ -308,7 +495,7 @@ static int get_device_string(hid_device *dev, enum device_string_id key, wchar_t
if (hid_dev) {
unsigned short dev_vid;
unsigned short dev_pid;
int bus_type;
unsigned bus_type;
size_t retm;
ret = parse_uevent_info(
@@ -319,27 +506,8 @@ static int get_device_string(hid_device *dev, enum device_string_id key, wchar_t
&serial_number_utf8,
&product_name_utf8);
if (bus_type == BUS_BLUETOOTH) {
switch (key) {
case DEVICE_STRING_MANUFACTURER:
wcsncpy(string, L"", maxlen);
ret = 0;
break;
case DEVICE_STRING_PRODUCT:
retm = mbstowcs(string, product_name_utf8, maxlen);
ret = (retm == (size_t)-1)? -1: 0;
break;
case DEVICE_STRING_SERIAL:
retm = mbstowcs(string, serial_number_utf8, maxlen);
ret = (retm == (size_t)-1)? -1: 0;
break;
case DEVICE_STRING_COUNT:
default:
ret = -1;
break;
}
}
else {
/* Standard USB device */
if (bus_type == BUS_USB) {
/* This is a USB device. Find its parent USB Device node. */
parent = udev_device_get_parent_with_subsystem_devtype(
udev_dev,
@@ -361,16 +529,46 @@ static int get_device_string(hid_device *dev, enum device_string_id key, wchar_t
/* Convert the string from UTF-8 to wchar_t */
retm = mbstowcs(string, str, maxlen);
ret = (retm == (size_t)-1)? -1: 0;
goto end;
}
/* USB information parsed */
goto end;
}
else {
/* Correctly handled below */
}
}
/* USB information not available (uhid) or another type of HID bus */
switch (bus_type) {
case BUS_BLUETOOTH:
case BUS_I2C:
case BUS_USB:
switch (key) {
case DEVICE_STRING_MANUFACTURER:
wcsncpy(string, L"", maxlen);
ret = 0;
break;
case DEVICE_STRING_PRODUCT:
retm = mbstowcs(string, product_name_utf8, maxlen);
ret = (retm == (size_t)-1)? -1: 0;
break;
case DEVICE_STRING_SERIAL:
retm = mbstowcs(string, serial_number_utf8, maxlen);
ret = (retm == (size_t)-1)? -1: 0;
break;
case DEVICE_STRING_COUNT:
default:
ret = -1;
break;
}
}
}
}
end:
free(serial_number_utf8);
free(product_name_utf8);
free(serial_number_utf8);
free(product_name_utf8);
udev_device_unref(udev_dev);
/* parent and hid_dev don't need to be (and can't be) unref'd.
@@ -449,8 +647,9 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id,
unsigned short dev_pid;
char *serial_number_utf8 = NULL;
char *product_name_utf8 = NULL;
int bus_type;
unsigned bus_type;
int result;
struct hidraw_report_descriptor report_desc;
/* Get the filename of the /sys entry for the device
and create a udev_device object (dev) representing it */
@@ -481,9 +680,15 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id,
goto next;
}
if (bus_type != BUS_USB && bus_type != BUS_BLUETOOTH) {
/* We only know how to handle USB and BT devices. */
goto next;
/* Filter out unhandled devices right away */
switch (bus_type) {
case BUS_BLUETOOTH:
case BUS_I2C:
case BUS_USB:
break;
default:
goto next;
}
/* Check the VID/PID against the arguments */
@@ -532,22 +737,14 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id,
"usb",
"usb_device");
/* uhid USB devices
Since this is a virtual hid interface, no USB information will
be available. */
if (!usb_dev) {
/* Free this device */
free(cur_dev->serial_number);
free(cur_dev->path);
free(cur_dev);
/* Take it off the device list. */
if (prev_dev) {
prev_dev->next = NULL;
cur_dev = prev_dev;
}
else {
cur_dev = root = NULL;
}
goto next;
/* Manufacturer and Product strings */
cur_dev->manufacturer_string = wcsdup(L"");
cur_dev->product_string = utf8_to_wchar_t(product_name_utf8);
break;
}
/* Manufacturer and Product strings */
@@ -571,6 +768,7 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id,
break;
case BUS_BLUETOOTH:
case BUS_I2C:
/* Manufacturer and Product strings */
cur_dev->manufacturer_string = wcsdup(L"");
cur_dev->product_string = utf8_to_wchar_t(product_name_utf8);
@@ -582,6 +780,45 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id,
* check for USB and Bluetooth devices above */
break;
}
/* Usage Page and Usage */
result = get_hid_report_descriptor_from_sysfs(sysfs_path, &report_desc);
if (result >= 0) {
unsigned short page = 0, usage = 0;
unsigned int pos = 0;
/*
* Parse the first usage and usage page
* out of the report descriptor.
*/
if (!get_next_hid_usage(report_desc.value, report_desc.size, &pos, &page, &usage)) {
cur_dev->usage_page = page;
cur_dev->usage = usage;
}
/*
* Parse any additional usage and usage pages
* out of the report descriptor.
*/
while (!get_next_hid_usage(report_desc.value, report_desc.size, &pos, &page, &usage)) {
/* Create new record for additional usage pairs */
tmp = (struct hid_device_info*) calloc(1, sizeof(struct hid_device_info));
cur_dev->next = tmp;
prev_dev = cur_dev;
cur_dev = tmp;
/* Update fields */
cur_dev->path = strdup(dev_path);
cur_dev->vendor_id = dev_vid;
cur_dev->product_id = dev_pid;
cur_dev->serial_number = prev_dev->serial_number? wcsdup(prev_dev->serial_number): NULL;
cur_dev->release_number = prev_dev->release_number;
cur_dev->interface_number = prev_dev->interface_number;
cur_dev->manufacturer_string = prev_dev->manufacturer_string? wcsdup(prev_dev->manufacturer_string): NULL;
cur_dev->product_string = prev_dev->product_string? wcsdup(prev_dev->product_string): NULL;
cur_dev->usage_page = page;
cur_dev->usage = usage;
}
}
}
next:
@@ -668,7 +905,7 @@ hid_device * HID_API_EXPORT hid_open_path(const char *path)
dev->device_handle = open(path, O_RDWR);
/* If we have a good handle, return it. */
if (dev->device_handle > 0) {
if (dev->device_handle >= 0) {
/* Set device error to none */
register_device_error(dev, NULL);
@@ -809,6 +1046,9 @@ int HID_API_EXPORT hid_get_feature_report(hid_device *dev, unsigned char *data,
// Not supported by Linux HidRaw yet
int HID_API_EXPORT HID_API_CALL hid_get_input_report(hid_device *dev, unsigned char *data, size_t length)
{
(void)dev;
(void)data;
(void)length;
return -1;
}
@@ -845,6 +1085,10 @@ int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *s
int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *dev, int string_index, wchar_t *string, size_t maxlen)
{
(void)dev;
(void)string_index;
(void)string;
(void)maxlen;
return -1;
}
+21 -2
View File
@@ -53,6 +53,8 @@ typedef struct pthread_barrier {
static int pthread_barrier_init(pthread_barrier_t *barrier, const pthread_barrierattr_t *attr, unsigned int count)
{
(void) attr;
if(count == 0) {
errno = EINVAL;
return -1;
@@ -274,8 +276,8 @@ static int get_string_property(IOHIDDeviceRef device, CFStringRef prop, wchar_t
len * sizeof(wchar_t),
&used_buf_len);
if (chars_copied == len)
buf[len] = 0; /* len is decremented above */
if (chars_copied <= 0)
buf[0] = 0;
else
buf[chars_copied] = 0;
@@ -581,6 +583,9 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id,
}
CFSetRef device_set = IOHIDManagerCopyDevices(hid_mgr);
if (device_set == NULL) {
return NULL;
}
/* Convert the list into a C array so we can iterate easily. */
num_devices = CFSetGetCount(device_set);
@@ -674,6 +679,9 @@ hid_device * HID_API_EXPORT hid_open(unsigned short vendor_id, unsigned short pr
static void hid_device_removal_callback(void *context, IOReturn result,
void *sender)
{
(void) result;
(void) sender;
/* Stop the Run Loop for this device. */
hid_device *d = (hid_device*) context;
@@ -688,6 +696,11 @@ static void hid_report_callback(void *context, IOReturn result, void *sender,
IOHIDReportType report_type, uint32_t report_id,
uint8_t *report, CFIndex report_length)
{
(void) result;
(void) sender;
(void) report_type;
(void) report_id;
struct input_report *rpt;
hid_device *dev = (hid_device*) context;
@@ -1178,6 +1191,11 @@ int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *s
int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *dev, int string_index, wchar_t *string, size_t maxlen)
{
(void) dev;
(void) string_index;
(void) string;
(void) maxlen;
/* TODO: */
return 0;
@@ -1186,6 +1204,7 @@ int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *dev, int string_index
HID_API_EXPORT const wchar_t * HID_API_CALL hid_error(hid_device *dev)
{
(void) dev;
/* TODO: */
return L"hid_error is not implemented yet";
+1 -1
View File
@@ -192,7 +192,7 @@ static void register_error(hid_device *dev, const char *op)
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPVOID)&msg, 0/*sz*/,
(LPWSTR)&msg, 0/*sz*/,
NULL);
/* Get rid of the CR and LF that FormatMessage() sticks at the