diff --git a/.builds/archlinux.yml b/.builds/archlinux.yml index e98996d..0f73310 100644 --- a/.builds/archlinux.yml +++ b/.builds/archlinux.yml @@ -1,4 +1,10 @@ image: archlinux +packages: +- autoconf +- automake +- libtool +- libusb +- libudev0 sources: - https://github.com/libusb/hidapi tasks: diff --git a/.gitignore b/.gitignore index 8438c4b..9963751 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,5 @@ windows/Makefile.in Makefile stamp-h1 libtool + +.DS_Store diff --git a/VERSION b/VERSION index 899f24f..71172b4 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.9.0 \ No newline at end of file +0.10.1 \ No newline at end of file diff --git a/dist/hidapi.podspec b/dist/hidapi.podspec index 271e428..b2f061b 100644 --- a/dist/hidapi.podspec +++ b/dist/hidapi.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |spec| spec.name = "hidapi" - spec.version = "" + 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 diff --git a/hidapi/hidapi.h b/hidapi/hidapi.h index d3ba5b7..efba318 100644 --- a/hidapi/hidapi.h +++ b/hidapi/hidapi.h @@ -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 } diff --git a/hidtest/test.c b/hidtest/test.c index a694b8e..bbea421 100644 --- a/hidtest/test.c +++ b/hidtest/test.c @@ -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; diff --git a/libusb/hid.c b/libusb/hid.c index a82f9cc..0b8aa1e 100644 --- a/libusb/hid.c +++ b/libusb/hid.c @@ -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"; } diff --git a/linux/hid.c b/linux/hid.c index 3d9eb86..718541e 100644 --- a/linux/hid.c +++ b/linux/hid.c @@ -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, /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 /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; } diff --git a/mac/hid.c b/mac/hid.c index c40fc08..d88a9ad 100644 --- a/mac/hid.c +++ b/mac/hid.c @@ -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"; diff --git a/windows/hid.c b/windows/hid.c index 636b031..57cb78d 100755 --- a/windows/hid.c +++ b/windows/hid.c @@ -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