From ce8c03662b577b0a4c08e35abb728b8102a74a52 Mon Sep 17 00:00:00 2001 From: Steven Michalske Date: Sat, 31 Jul 2021 12:14:52 -0700 Subject: [PATCH 1/2] Add error reporting to the MacOS port. --- mac/hid.c | 154 ++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 132 insertions(+), 22 deletions(-) diff --git a/mac/hid.c b/mac/hid.c index 868244254..7d7161244 100644 --- a/mac/hid.c +++ b/mac/hid.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -126,6 +127,7 @@ struct hid_device_ { pthread_barrier_t barrier; /* Ensures correct startup sequence */ pthread_barrier_t shutdown_barrier; /* Ensures correct shutdown sequence */ int shutdown_thread; + wchar_t *last_error_str; }; static hid_device *new_hid_device(void) @@ -141,6 +143,7 @@ static hid_device *new_hid_device(void) dev->input_report_buf = NULL; dev->input_reports = NULL; dev->shutdown_thread = 0; + dev->last_error_str = NULL; /* Thread objects */ pthread_mutex_init(&dev->mutex, NULL); @@ -193,13 +196,84 @@ static struct hid_api_version api_version = { static IOHIDManagerRef hid_mgr = 0x0; static int is_macos_10_10_or_greater = 0; +/* Global error message that is not specific to a device, e.g. for + hid_open(). It is thread-local like errno. */ +__thread wchar_t *last_global_error_str = NULL; -#if 0 -static void register_error(hid_device *dev, const char *op) + +/* The caller must free the returned string with free(). */ +static wchar_t *utf8_to_wchar_t(const char *utf8) +{ + wchar_t *ret = NULL; + + if (utf8) { + size_t wlen = mbstowcs(NULL, utf8, 0); + if ((size_t) -1 == wlen) { + return wcsdup(L""); + } + ret = (wchar_t*) calloc(wlen+1, sizeof(wchar_t)); + mbstowcs(ret, utf8, wlen+1); + ret[wlen] = 0x0000; + } + + return ret; +} + + +/* Set the last global error to be reported by hid_error(NULL). + * The given error message will be copied (and decoded according to the + * currently locale, so do not pass in string constants). + * The last stored global error message is freed. + * Use register_global_error(NULL) to indicate "no error". */ +static void register_global_error(const char *msg) { + if (last_global_error_str) + free(last_global_error_str); + last_global_error_str = utf8_to_wchar_t(msg); } -#endif + +/* 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[1024]; + 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 + * currently locale, so do not pass in string constants). + * The last stored global error message is freed. + * Use register_device_error(device, NULL) to indicate "no error". */ +static void register_device_error(hid_device *dev, const char *msg) +{ + if (dev->last_error_str) + free(dev->last_error_str); + + dev->last_error_str = utf8_to_wchar_t(msg); +} + +/* See register_device_error, but you can pass a format string into this function. */ +static void register_device_error_format(hid_device *dev, const char *format, ...) +{ + va_list args; + va_start(args, format); + + char msg[1024]; + vsnprintf(msg, sizeof(msg), format, args); + + va_end(args); + + register_device_error(dev, msg); +} + static CFArrayRef get_array_property(IOHIDDeviceRef device, CFStringRef key) { @@ -496,8 +570,10 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, int i; /* Set up the HID Manager if it hasn't been done */ - if (hid_init() < 0) + if (hid_init() < 0) { + register_global_error("hid_enumerate: Call to hid_init failed."); return NULL; + } /* give the IOHIDManager a chance to update itself */ process_pending_events(); @@ -585,6 +661,9 @@ void HID_API_EXPORT hid_free_enumeration(struct hid_device_info *devs) hid_device * HID_API_EXPORT hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number) { /* This function is identical to the Linux version. Platform independent. */ + /* Set global error to none */ + register_global_error(NULL); + struct hid_device_info *devs, *cur_dev; const char *path_to_open = NULL; hid_device * handle = NULL; @@ -611,6 +690,8 @@ hid_device * HID_API_EXPORT hid_open(unsigned short vendor_id, unsigned short pr if (path_to_open) { /* Open the device */ handle = hid_open_path(path_to_open); + } else { + register_global_error("No such device"); } hid_free_enumeration(devs); @@ -766,13 +847,18 @@ static void *read_thread(void *param) */ hid_device * HID_API_EXPORT hid_open_path(const char *path) { + /* Set global error to none */ + register_global_error(NULL); + hid_device *dev = NULL; io_registry_entry_t entry = MACH_PORT_NULL; IOReturn ret = kIOReturnInvalid; /* Set up the HID Manager if it hasn't been done */ - if (hid_init() < 0) + if (hid_init() < 0) { + register_global_error("hid_open_path: Call to hid_init failed."); goto return_error; + } dev = new_hid_device(); @@ -780,6 +866,7 @@ hid_device * HID_API_EXPORT hid_open_path(const char *path) entry = IORegistryEntryFromPath(kIOMasterPortDefault, path); if (entry == MACH_PORT_NULL) { /* Path wasn't valid (maybe device was removed?) */ + register_global_error("hid_open_path: device not found at path."); goto return_error; } @@ -787,6 +874,7 @@ hid_device * HID_API_EXPORT hid_open_path(const char *path) dev->device_handle = IOHIDDeviceCreate(kCFAllocatorDefault, entry); if (dev->device_handle == NULL) { /* Error creating the HID device */ + register_global_error("hid_open_path: failed to open device."); goto return_error; } @@ -821,6 +909,7 @@ hid_device * HID_API_EXPORT hid_open_path(const char *path) return dev; } else { + register_global_error_format("0x%08X: %s", ret, mach_error_string(ret)); goto return_error; } @@ -842,7 +931,10 @@ static int set_report(hid_device *dev, IOHIDReportType type, const unsigned char IOReturn res; unsigned char report_id; + register_device_error(dev, NULL); + if (!data || (length == 0)) { + register_device_error(dev, strerror(EINVAL)); return -1; } @@ -857,6 +949,7 @@ static int set_report(hid_device *dev, IOHIDReportType type, const unsigned char /* Avoid crash if the device has been unplugged. */ if (dev->disconnected) { + register_device_error(dev, "Device has disconnected."); return -1; } @@ -865,11 +958,12 @@ static int set_report(hid_device *dev, IOHIDReportType type, const unsigned char report_id, data_to_send, length_to_send); - if (res == kIOReturnSuccess) { - return length; + if (res != kIOReturnSuccess) { + register_device_error_format(dev, "0x%08X: %s", res, mach_error_string(res)); + return -1; } - return -1; + return length; } static int get_report(hid_device *dev, IOHIDReportType type, unsigned char *data, size_t length) @@ -879,6 +973,8 @@ static int get_report(hid_device *dev, IOHIDReportType type, unsigned char *data IOReturn res = kIOReturnSuccess; const unsigned char report_id = data[0]; + register_device_error(dev, NULL); + if (report_id == 0x0) { /* Not using numbered Reports. Don't send the report number. */ @@ -888,6 +984,7 @@ static int get_report(hid_device *dev, IOHIDReportType type, unsigned char *data /* Avoid crash if the device has been unplugged. */ if (dev->disconnected) { + register_device_error(dev, "Device has disconnected."); return -1; } @@ -896,14 +993,15 @@ static int get_report(hid_device *dev, IOHIDReportType type, unsigned char *data report_id, report, &report_length); - if (res == kIOReturnSuccess) { - if (report_id == 0x0) { /* 0 report number still present at the beginning */ - report_length++; - } - return report_length; + if (res != kIOReturnSuccess) { + register_device_error_format(dev, "0x%08X: %s", res, mach_error_string(res)); + return -1; } - return -1; + if (report_id == 0x0) { /* 0 report number still present at the beginning */ + report_length++; + } + return report_length; } int HID_API_EXPORT hid_write(hid_device *dev, const unsigned char *data, size_t length) @@ -925,7 +1023,7 @@ static int return_data(hid_device *dev, unsigned char *data, size_t length) return len; } -static int cond_wait(const hid_device *dev, pthread_cond_t *cond, pthread_mutex_t *mutex) +static int cond_wait(hid_device *dev, pthread_cond_t *cond, pthread_mutex_t *mutex) { while (!dev->input_reports) { int res = pthread_cond_wait(cond, mutex); @@ -938,14 +1036,16 @@ static int cond_wait(const hid_device *dev, pthread_cond_t *cond, pthread_mutex_ to sleep. See the pthread_cond_timedwait() man page for details. */ - if (dev->shutdown_thread || dev->disconnected) + if (dev->shutdown_thread || dev->disconnected) { + register_device_error(dev, "cond_wait: Device may have been disconnected or thread stopped."); return -1; + } } return 0; } -static int cond_timedwait(const hid_device *dev, pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime) +static int cond_timedwait(hid_device *dev, pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime) { while (!dev->input_reports) { int res = pthread_cond_timedwait(cond, mutex, abstime); @@ -958,8 +1058,10 @@ static int cond_timedwait(const hid_device *dev, pthread_cond_t *cond, pthread_m to sleep. See the pthread_cond_timedwait() man page for details. */ - if (dev->shutdown_thread || dev->disconnected) + if (dev->shutdown_thread || dev->disconnected) { + register_device_error(dev, "cond_timedwait: Device may have been disconnected or thread stopped."); return -1; + } } return 0; @@ -983,6 +1085,7 @@ int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t /* Return if the device has been disconnected. */ if (dev->disconnected) { bytes_read = -1; + register_device_error(dev, "hid_read_timeout: Device disconnected."); goto ret; } @@ -991,6 +1094,7 @@ int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t has been an error. An error code of -1 should be returned. */ bytes_read = -1; + register_device_error(dev, "hid_read_timeout: thread shutdown."); goto ret; } @@ -1004,6 +1108,7 @@ int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t bytes_read = return_data(dev, data, length); else { /* There was an error, or a device disconnection. */ + register_device_error(dev, "hid_read_timeout: Error reading or device disconnected."); bytes_read = -1; } } @@ -1064,7 +1169,7 @@ int HID_API_EXPORT hid_get_feature_report(hid_device *dev, unsigned char *data, } int HID_API_EXPORT HID_API_CALL hid_get_input_report(hid_device *dev, unsigned char *data, size_t length) -{ +{ return get_report(dev, kIOHIDReportTypeInput, data, length); } @@ -1152,10 +1257,15 @@ 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: */ + if (dev) { + if (dev->last_error_str == NULL) + return L"Success"; + return dev->last_error_str; + } - return L"hid_error is not implemented yet"; + if (last_global_error_str == NULL) + return L"Success"; + return last_global_error_str; } From 202b3ad3eabf41a3c80360b0068ab399d0f861c7 Mon Sep 17 00:00:00 2001 From: Ihor Dutchak <> Date: Sun, 2 Oct 2022 20:12:06 +0300 Subject: [PATCH 2/2] give a little love to the error messages/error handling --- mac/hid.c | 168 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 95 insertions(+), 73 deletions(-) diff --git a/mac/hid.c b/mac/hid.c index 1e76edf89..303ec6653 100644 --- a/mac/hid.c +++ b/mac/hid.c @@ -147,6 +147,10 @@ struct hid_device_ { static hid_device *new_hid_device(void) { hid_device *dev = (hid_device*) calloc(1, sizeof(hid_device)); + if (dev == NULL) { + return NULL; + } + dev->device_handle = NULL; dev->open_options = device_open_options; dev->blocking = 1; @@ -409,6 +413,7 @@ static int init_hid_manager(void) return 0; } + register_global_error("Failed to create IOHIDManager"); return -1; } @@ -427,6 +432,8 @@ HID_API_EXPORT const char* HID_API_CALL hid_version_str() for failure. */ int HID_API_EXPORT hid_init(void) { + register_global_error(NULL); + if (!hid_mgr) { is_macos_10_10_or_greater = (NSAppKitVersionNumber >= 1343); /* NSAppKitVersionNumber10_10 */ hid_darwin_set_open_exclusive(1); /* Backward compatibility */ @@ -446,6 +453,9 @@ int HID_API_EXPORT hid_exit(void) hid_mgr = NULL; } + /* Free global error message */ + register_global_error(NULL); + return 0; } @@ -616,9 +626,9 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, /* Set up the HID Manager if it hasn't been done */ if (hid_init() < 0) { - register_global_error("hid_enumerate: Call to hid_init failed."); return NULL; } + /* register_global_error: global error is set/reset by hid_init */ /* give the IOHIDManager a chance to update itself */ process_pending_events(); @@ -646,14 +656,17 @@ 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); - IOHIDDeviceRef *device_array = (IOHIDDeviceRef*) calloc(num_devices, sizeof(IOHIDDeviceRef)); - CFSetGetValues(device_set, (const void **) device_array); + IOHIDDeviceRef *device_array = NULL; + + if (device_set != NULL) { + /* Convert the list into a C array so we can iterate easily. */ + num_devices = CFSetGetCount(device_set); + device_array = (IOHIDDeviceRef*) calloc(num_devices, sizeof(IOHIDDeviceRef)); + CFSetGetValues(device_set, (const void **) device_array); + } else { + num_devices = 0; + } /* Iterate over each device, making an entry for it. */ for (i = 0; i < num_devices; i++) { @@ -683,7 +696,16 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, } free(device_array); - CFRelease(device_set); + if (device_set != NULL) + CFRelease(device_set); + + if (root == NULL) { + if (vendor_id == 0 && product_id == 0) { + register_global_error("No HID devices found in the system."); + } else { + register_global_error("No HID devices with requested VID/PID found in the system."); + } + } return root; } @@ -706,14 +728,18 @@ void HID_API_EXPORT hid_free_enumeration(struct hid_device_info *devs) hid_device * HID_API_EXPORT hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number) { /* This function is identical to the Linux version. Platform independent. */ - /* Set global error to none */ - register_global_error(NULL); struct hid_device_info *devs, *cur_dev; const char *path_to_open = NULL; hid_device * handle = NULL; + /* register_global_error: global error is reset by hid_enumerate/hid_init */ devs = hid_enumerate(vendor_id, product_id); + if (devs == NULL) { + /* register_global_error: global error is already set by hid_enumerate */ + return NULL; + } + cur_dev = devs; while (cur_dev) { if (cur_dev->vendor_id == vendor_id && @@ -733,10 +759,9 @@ hid_device * HID_API_EXPORT hid_open(unsigned short vendor_id, unsigned short pr } if (path_to_open) { - /* Open the device */ handle = hid_open_path(path_to_open); } else { - register_global_error("No such device"); + register_global_error("Device with requested VID/PID/(SerialNumber) not found"); } hid_free_enumeration(devs); @@ -914,26 +939,28 @@ static io_registry_entry_t hid_open_service_registry_from_path(const char *path) hid_device * HID_API_EXPORT hid_open_path(const char *path) { - /* Set global error to none */ - register_global_error(NULL); - hid_device *dev = NULL; io_registry_entry_t entry = MACH_PORT_NULL; IOReturn ret = kIOReturnInvalid; + char str[32]; /* Set up the HID Manager if it hasn't been done */ if (hid_init() < 0) { - register_global_error("hid_open_path: Call to hid_init failed."); goto return_error; } + /* register_global_error: global error is set/reset by hid_init */ dev = new_hid_device(); + if (!dev) { + register_global_error("Couldn't allocate memory"); + return NULL; + } /* Get the IORegistry entry for the given path */ entry = hid_open_service_registry_from_path(path); if (entry == MACH_PORT_NULL) { /* Path wasn't valid (maybe device was removed?) */ - register_global_error("hid_open_path: device not found at path."); + register_global_error("hid_open_path: device mach entry not found with the given path"); goto return_error; } @@ -941,44 +968,41 @@ hid_device * HID_API_EXPORT hid_open_path(const char *path) dev->device_handle = IOHIDDeviceCreate(kCFAllocatorDefault, entry); if (dev->device_handle == NULL) { /* Error creating the HID device */ - register_global_error("hid_open_path: failed to open device."); + register_global_error("hid_open_path: failed to create IOHIDDevice from the mach entry"); goto return_error; } /* Open the IOHIDDevice */ ret = IOHIDDeviceOpen(dev->device_handle, dev->open_options); - if (ret == kIOReturnSuccess) { - char str[32]; + if (ret != kIOReturnSuccess) { + register_global_error_format("hid_open_path: failed to open IOHIDDevice from mach entry: (0x%08X) %s", ret, mach_error_string(ret)); + goto return_error; + } - /* Create the buffers for receiving data */ - dev->max_input_report_len = (CFIndex) get_max_report_length(dev->device_handle); - dev->input_report_buf = (uint8_t*) calloc(dev->max_input_report_len, sizeof(uint8_t)); + /* Create the buffers for receiving data */ + dev->max_input_report_len = (CFIndex) get_max_report_length(dev->device_handle); + dev->input_report_buf = (uint8_t*) calloc(dev->max_input_report_len, sizeof(uint8_t)); - /* Create the Run Loop Mode for this device. - printing the reference seems to work. */ - sprintf(str, "HIDAPI_%p", (void*) dev->device_handle); - dev->run_loop_mode = - CFStringCreateWithCString(NULL, str, kCFStringEncodingASCII); + /* Create the Run Loop Mode for this device. + printing the reference seems to work. */ + sprintf(str, "HIDAPI_%p", (void*) dev->device_handle); + dev->run_loop_mode = + CFStringCreateWithCString(NULL, str, kCFStringEncodingASCII); - /* Attach the device to a Run Loop */ - IOHIDDeviceRegisterInputReportCallback( - dev->device_handle, dev->input_report_buf, dev->max_input_report_len, - &hid_report_callback, dev); - IOHIDDeviceRegisterRemovalCallback(dev->device_handle, hid_device_removal_callback, dev); + /* Attach the device to a Run Loop */ + IOHIDDeviceRegisterInputReportCallback( + dev->device_handle, dev->input_report_buf, dev->max_input_report_len, + &hid_report_callback, dev); + IOHIDDeviceRegisterRemovalCallback(dev->device_handle, hid_device_removal_callback, dev); - /* Start the read thread */ - pthread_create(&dev->thread, NULL, read_thread, dev); + /* Start the read thread */ + pthread_create(&dev->thread, NULL, read_thread, dev); - /* Wait here for the read thread to be initialized. */ - pthread_barrier_wait(&dev->barrier); + /* Wait here for the read thread to be initialized. */ + pthread_barrier_wait(&dev->barrier); - IOObjectRelease(entry); - return dev; - } - else { - register_global_error_format("0x%08X: %s", ret, mach_error_string(ret)); - goto return_error; - } + IOObjectRelease(entry); + return dev; return_error: if (dev->device_handle != NULL) @@ -1016,7 +1040,7 @@ static int set_report(hid_device *dev, IOHIDReportType type, const unsigned char /* Avoid crash if the device has been unplugged. */ if (dev->disconnected) { - register_device_error(dev, "Device has disconnected."); + register_device_error(dev, "Device is disconnected"); return -1; } @@ -1026,7 +1050,7 @@ static int set_report(hid_device *dev, IOHIDReportType type, const unsigned char data_to_send, length_to_send); if (res != kIOReturnSuccess) { - register_device_error_format(dev, "0x%08X: %s", res, mach_error_string(res)); + register_device_error_format(dev, "IOHIDDeviceSetReport failed: (0x%08X) %s", res, mach_error_string(res)); return -1; } @@ -1051,7 +1075,7 @@ static int get_report(hid_device *dev, IOHIDReportType type, unsigned char *data /* Avoid crash if the device has been unplugged. */ if (dev->disconnected) { - register_device_error(dev, "Device has disconnected."); + register_device_error(dev, "Device is disconnected"); return -1; } @@ -1061,7 +1085,7 @@ static int get_report(hid_device *dev, IOHIDReportType type, unsigned char *data report, &report_length); if (res != kIOReturnSuccess) { - register_device_error_format(dev, "0x%08X: %s", res, mach_error_string(res)); + register_device_error_format(dev, "IOHIDDeviceGetReport failed: (0x%08X) %s", res, mach_error_string(res)); return -1; } @@ -1105,7 +1129,6 @@ static int cond_wait(hid_device *dev, pthread_cond_t *cond, pthread_mutex_t *mut details. */ if (dev->shutdown_thread || dev->disconnected) { - register_device_error(dev, "cond_wait: Device may have been disconnected or thread stopped."); return -1; } } @@ -1127,7 +1150,6 @@ static int cond_timedwait(hid_device *dev, pthread_cond_t *cond, pthread_mutex_t details. */ if (dev->shutdown_thread || dev->disconnected) { - register_device_error(dev, "cond_timedwait: Device may have been disconnected or thread stopped."); return -1; } } @@ -1153,7 +1175,7 @@ int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t /* Return if the device has been disconnected. */ if (dev->disconnected) { bytes_read = -1; - register_device_error(dev, "hid_read_timeout: Device disconnected."); + register_device_error(dev, "hid_read_timeout: device disconnected"); goto ret; } @@ -1162,7 +1184,7 @@ int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t has been an error. An error code of -1 should be returned. */ bytes_read = -1; - register_device_error(dev, "hid_read_timeout: thread shutdown."); + register_device_error(dev, "hid_read_timeout: thread shutdown"); goto ret; } @@ -1176,7 +1198,7 @@ int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t bytes_read = return_data(dev, data, length); else { /* There was an error, or a device disconnection. */ - register_device_error(dev, "hid_read_timeout: Error reading or device disconnected."); + register_device_error(dev, "hid_read_timeout: error waiting for more data"); bytes_read = -1; } } @@ -1195,12 +1217,14 @@ int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t } res = cond_timedwait(dev, &dev->condition, &dev->mutex, &ts); - if (res == 0) + if (res == 0) { bytes_read = return_data(dev, data, length); - else if (res == ETIMEDOUT) + } else if (res == ETIMEDOUT) { bytes_read = 0; - else + } else { + register_device_error(dev, "hid_read_timeout: error waiting for more data"); bytes_read = -1; + } } else { /* Purely non-blocking */ @@ -1299,7 +1323,7 @@ int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *st { if (!string || !maxlen) { - // register_device_error(dev, "Zero buffer/length"); + register_device_error(dev, "Zero buffer/length"); return -1; } @@ -1318,15 +1342,13 @@ int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *st int HID_API_EXPORT_CALL hid_get_product_string(hid_device *dev, wchar_t *string, size_t maxlen) { - if (!string || !maxlen) - { - // register_device_error(dev, "Zero buffer/length"); + if (!string || !maxlen) { + register_device_error(dev, "Zero buffer/length"); return -1; } struct hid_device_info *info = hid_get_device_info(dev); - if (!info) - { + if (!info) { // hid_get_device_info will have set an error already return -1; } @@ -1339,15 +1361,13 @@ int HID_API_EXPORT_CALL hid_get_product_string(hid_device *dev, wchar_t *string, int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *string, size_t maxlen) { - if (!string || !maxlen) - { - // register_device_error(dev, "Zero buffer/length"); + if (!string || !maxlen) { + register_device_error(dev, "Zero buffer/length"); return -1; } struct hid_device_info *info = hid_get_device_info(dev); - if (!info) - { + if (!info) { // hid_get_device_info will have set an error already return -1; } @@ -1359,9 +1379,11 @@ int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *s } HID_API_EXPORT struct hid_device_info *HID_API_CALL hid_get_device_info(hid_device *dev) { - if (!dev->device_info) - { + if (!dev->device_info) { dev->device_info = create_device_info(dev->device_handle); + if (!dev->device_info) { + register_device_error(dev, "Failed to create hid_device_info"); + } } return dev->device_info; @@ -1374,9 +1396,8 @@ int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *dev, int string_index (void) string; (void) maxlen; - /* TODO: */ - - return 0; + register_device_error(dev, "hid_get_indexed_string: not available on this platform"); + return -1; } int HID_API_EXPORT_CALL hid_darwin_get_location_id(hid_device *dev, uint32_t *location_id) @@ -1386,6 +1407,7 @@ int HID_API_EXPORT_CALL hid_darwin_get_location_id(hid_device *dev, uint32_t *lo *location_id = (uint32_t) res; return 0; } else { + register_device_error(dev, "Failed to get IOHIDLocationID property"); return -1; } }