diff --git a/libusb/hid.c b/libusb/hid.c index 29df4ce8a..a5384e147 100644 --- a/libusb/hid.c +++ b/libusb/hid.c @@ -139,6 +139,9 @@ static int return_data(hid_device *dev, unsigned char *data, size_t length); static hid_device *new_hid_device(void) { hid_device *dev = (hid_device*) calloc(1, sizeof(hid_device)); + if (!dev) + return NULL; + dev->blocking = 1; hidapi_thread_state_init(&dev->thread_state); @@ -148,6 +151,9 @@ static hid_device *new_hid_device(void) static void free_hid_device(hid_device *dev) { + if (!dev) + return; + /* Clean up the thread objects */ hidapi_thread_state_destroy(&dev->thread_state); @@ -169,6 +175,9 @@ static void register_error(hid_device *dev, const char *op) Only call with a num_bytes of 0, 1, 2, or 4. */ static uint32_t get_bytes(uint8_t *rpt, size_t len, size_t num_bytes, size_t cur) { + if (!rpt) + return 0; + /* Return if there aren't enough bytes. */ if (cur + num_bytes >= len) return 0; @@ -198,6 +207,9 @@ static uint32_t get_bytes(uint8_t *rpt, size_t len, size_t num_bytes, size_t cur static int get_usage(uint8_t *report_descriptor, size_t size, unsigned short *usage_page, unsigned short *usage) { + if (!report_descriptor || !usage_page || !usage) + return -1; + unsigned int i = 0; int size_code; int data_len, key_size; @@ -536,6 +548,9 @@ static int hid_get_report_descriptor_libusb(libusb_device_handle *handle, int in */ static void fill_device_info_usage(struct hid_device_info *cur_dev, libusb_device_handle *handle, int interface_num, uint16_t expected_report_descriptor_size) { + if (!cur_dev) + return; + unsigned char hid_report_descriptor[HID_API_MAX_REPORT_DESCRIPTOR_SIZE]; unsigned short page = 0, usage = 0; @@ -632,6 +647,9 @@ static struct hid_device_info * create_device_info_for_device(libusb_device *dev static uint16_t get_report_descriptor_size_from_interface_descriptors(const struct libusb_interface_descriptor *intf_desc) { + if (!intf_desc) + return 0; + int i = 0; int found_hid_report_descriptor = 0; uint16_t result = HID_API_MAX_REPORT_DESCRIPTOR_SIZE; @@ -685,6 +703,9 @@ static uint16_t get_report_descriptor_size_from_interface_descriptors(const stru static int is_xbox360(unsigned short vendor_id, const struct libusb_interface_descriptor *intf_desc) { + if (!intf_desc) + return 0; + static const int xb360_iface_subclass = 93; static const int xb360_iface_protocol = 1; /* Wired */ static const int xb360w_iface_protocol = 129; /* Wireless */ @@ -733,6 +754,9 @@ static int is_xbox360(unsigned short vendor_id, const struct libusb_interface_de static int is_xboxone(unsigned short vendor_id, const struct libusb_interface_descriptor *intf_desc) { + if (!intf_desc) + return 0; + static const int xb1_iface_subclass = 71; static const int xb1_iface_protocol = 208; static const int supported_vendors[] = { @@ -769,6 +793,8 @@ static int should_enumerate_interface(unsigned short vendor_id, const struct lib #if 0 printf("Checking interface 0x%x %d/%d/%d/%d\n", vendor_id, intf_desc->bInterfaceNumber, intf_desc->bInterfaceClass, intf_desc->bInterfaceSubClass, intf_desc->bInterfaceProtocol); #endif + if (!intf_desc) + return 0; if (intf_desc->bInterfaceClass == LIBUSB_CLASS_HID) return 1; @@ -950,6 +976,9 @@ hid_device * hid_open(unsigned short vendor_id, unsigned short product_id, const static void LIBUSB_CALL read_callback(struct libusb_transfer *transfer) { + if (!transfer) + return; + hid_device *dev = transfer->user_data; int res; @@ -1018,6 +1047,9 @@ static void LIBUSB_CALL read_callback(struct libusb_transfer *transfer) static void *read_thread(void *param) { + if (!param) + return NULL; + int res; hid_device *dev = param; uint8_t *buf; @@ -1118,6 +1150,9 @@ static void init_xboxone(libusb_device_handle *device_handle, unsigned short idV (void)idProduct; + if (!conf_desc) + return; + for (j = 0; j < conf_desc->bNumInterfaces; j++) { const struct libusb_interface *intf = &conf_desc->interface[j]; for (k = 0; k < intf->num_altsetting; k++) { @@ -1158,6 +1193,9 @@ static void init_xboxone(libusb_device_handle *device_handle, unsigned short idV static int hidapi_initialize_device(hid_device *dev, const struct libusb_interface_descriptor *intf_desc, const struct libusb_config_descriptor *conf_desc) { + if (!conf_desc) + return 0; + int i =0; int res = 0; struct libusb_device_descriptor desc; @@ -1413,6 +1451,9 @@ HID_API_EXPORT hid_device * HID_API_CALL hid_libusb_wrap_sys_device(intptr_t sys int HID_API_EXPORT hid_write(hid_device *dev, const unsigned char *data, size_t length) { + if (!dev) + return -1; + int res; int report_number; int skipped_report_id = 0; @@ -1455,6 +1496,9 @@ int HID_API_EXPORT hid_write(hid_device *dev, const unsigned char *data, size_t This should be called with dev->mutex locked. */ static int return_data(hid_device *dev, unsigned char *data, size_t length) { + if (!dev || !data) + return 0; + /* Copy the data out of the linked list item (rpt) into the return buffer (data), and delete the liked list item. */ struct input_report *rpt = dev->input_reports; @@ -1469,6 +1513,9 @@ static int return_data(hid_device *dev, unsigned char *data, size_t length) static void cleanup_mutex(void *param) { + if (!param) + return; + hid_device *dev = param; hidapi_thread_mutex_unlock(&dev->thread_state); } @@ -1476,6 +1523,9 @@ static void cleanup_mutex(void *param) int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds) { + if (!dev) + return -1; + #if 0 int transferred; int res = libusb_interrupt_transfer(dev->device_handle, dev->input_endpoint, data, length, &transferred, 5000); @@ -1564,6 +1614,9 @@ int HID_API_EXPORT hid_read(hid_device *dev, unsigned char *data, size_t length) int HID_API_EXPORT hid_set_nonblocking(hid_device *dev, int nonblock) { + if (!dev) + return -1; + dev->blocking = !nonblock; return 0; @@ -1572,6 +1625,9 @@ int HID_API_EXPORT hid_set_nonblocking(hid_device *dev, int nonblock) int HID_API_EXPORT hid_send_feature_report(hid_device *dev, const unsigned char *data, size_t length) { + if (!dev || !data) + return -1; + int res = -1; int skipped_report_id = 0; int report_number = data[0]; @@ -1602,6 +1658,9 @@ int HID_API_EXPORT hid_send_feature_report(hid_device *dev, const unsigned char int HID_API_EXPORT hid_get_feature_report(hid_device *dev, unsigned char *data, size_t length) { + if (!dev || !data) + return -1; + int res = -1; int skipped_report_id = 0; int report_number = data[0]; @@ -1632,6 +1691,9 @@ int HID_API_EXPORT hid_get_feature_report(hid_device *dev, unsigned char *data, int HID_API_EXPORT hid_send_output_report(hid_device *dev, const unsigned char *data, size_t length) { + if (!dev || !data) + return -1; + int res = -1; int skipped_report_id = 0; int report_number = data[0]; @@ -1662,6 +1724,9 @@ int HID_API_EXPORT hid_send_output_report(hid_device *dev, const unsigned char * int HID_API_EXPORT HID_API_CALL hid_get_input_report(hid_device *dev, unsigned char *data, size_t length) { + if (!dev || !data) + return -1; + int res = -1; int skipped_report_id = 0; int report_number = data[0]; @@ -1735,20 +1800,32 @@ void HID_API_EXPORT hid_close(hid_device *dev) int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *string, size_t maxlen) { + if (!dev) + return -1; + return hid_get_indexed_string(dev, dev->manufacturer_index, string, maxlen); } int HID_API_EXPORT_CALL hid_get_product_string(hid_device *dev, wchar_t *string, size_t maxlen) { + if (!dev) + return -1; + return hid_get_indexed_string(dev, dev->product_index, string, maxlen); } int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *string, size_t maxlen) { + if (!dev) + return -1; + return hid_get_indexed_string(dev, dev->serial_index, string, maxlen); } HID_API_EXPORT struct hid_device_info *HID_API_CALL hid_get_device_info(hid_device *dev) { + if (!dev) + return NULL; + if (!dev->device_info) { struct libusb_device_descriptor desc; libusb_device *usb_device = libusb_get_device(dev->device_handle); @@ -1767,6 +1844,9 @@ HID_API_EXPORT struct hid_device_info *HID_API_CALL hid_get_device_info(hid_devi int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *dev, int string_index, wchar_t *string, size_t maxlen) { + if (!dev || !string) + return -1; + wchar_t *str; str = get_usb_string(dev->device_handle, string_index); @@ -1783,6 +1863,9 @@ int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *dev, int string_index int HID_API_EXPORT_CALL hid_get_report_descriptor(hid_device *dev, unsigned char *buf, size_t buf_size) { + if (!dev) + return -1; + return hid_get_report_descriptor_libusb(dev->device_handle, dev->interface, dev->report_descriptor_size, buf, buf_size); } diff --git a/linux/hid.c b/linux/hid.c index 228fdeeca..c9c09d8f9 100644 --- a/linux/hid.c +++ b/linux/hid.c @@ -177,6 +177,9 @@ static void register_device_error(hid_device *dev, const char *msg) /* Similar to 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, ...) { + if (!dev) + return; + va_list args; va_start(args, format); register_error_str_vformat(&dev->last_error_str, format, args); @@ -197,6 +200,9 @@ static wchar_t *copy_udev_string(struct udev_device *dev, const char *udev_name) */ static int get_hid_item_size(const __u8 *report_descriptor, __u32 size, unsigned int pos, int *data_len, int *key_size) { + if (!report_descriptor || !data_len || !key_size) + return 0; + int key = report_descriptor[pos]; int size_code; @@ -253,6 +259,9 @@ static int get_hid_item_size(const __u8 *report_descriptor, __u32 size, unsigned */ static __u32 get_hid_report_bytes(const __u8 *rpt, size_t len, size_t num_bytes, size_t cur) { + if (!rpt) + return 0; + /* Return if there aren't enough bytes. */ if (cur + num_bytes >= len) return 0; @@ -347,6 +356,9 @@ struct hid_usage_iterator { */ static int get_next_hid_usage(const __u8 *report_descriptor, __u32 size, struct hid_usage_iterator *ctx, unsigned short *usage_page, unsigned short *usage) { + if (!report_descriptor || !ctx || !usage || !usage_page) + return -1; + int data_len, key_size; int initial = ctx->pos == 0; /* Used to handle case where no top-level application collection is defined */ @@ -370,6 +382,7 @@ static int get_next_hid_usage(const __u8 *report_descriptor, __u32 size, struct if (data_len == 4) { /* Usages 5.5 / Usage Page 6.2.2.7 */ ctx->usage_page = get_hid_report_bytes(report_descriptor, size, 2, ctx->pos + 2); ctx->usage_page_found = 1; + *usage = get_hid_report_bytes(report_descriptor, size, 2, ctx->pos); usage_found = 1; } @@ -400,8 +413,8 @@ static int get_next_hid_usage(const __u8 *report_descriptor, __u32 size, struct /* 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 && ctx->usage_page_found) { - *usage_page = ctx->usage_page; - return 0; /* success */ + *usage_page = ctx->usage_page; + return 0; /* success */ } return 1; /* finished processing */ @@ -413,6 +426,9 @@ static int get_next_hid_usage(const __u8 *report_descriptor, __u32 size, struct */ static int get_hid_report_descriptor(const char *rpt_path, struct hidraw_report_descriptor *rpt_desc) { + if (!rpt_path || !rpt_desc) + return -1; + int rpt_handle; ssize_t res; @@ -443,6 +459,10 @@ static int get_hid_report_descriptor(const char *rpt_path, struct hidraw_report_ static int get_hid_report_descriptor_from_sysfs(const char *sysfs_path, struct hidraw_report_descriptor *rpt_desc) { int res = -1; + + if (!sysfs_path) + return res; + /* Construct /device/report_descriptor */ size_t rpt_path_len = strlen(sysfs_path) + 25 + 1; char* rpt_path = (char*) calloc(1, rpt_path_len); @@ -457,6 +477,9 @@ static int get_hid_report_descriptor_from_sysfs(const char *sysfs_path, struct h /* return non-zero if successfully parsed */ static int parse_hid_vid_pid_from_uevent(const char *uevent, unsigned *bus_type, unsigned short *vendor_id, unsigned short *product_id) { + if (!uevent) + return 0; + char tmp[1024]; size_t uevent_len = strlen(uevent); if (uevent_len > sizeof(tmp) - 1) @@ -528,6 +551,10 @@ static int parse_hid_vid_pid_from_uevent_path(const char *uevent_path, unsigned static int parse_hid_vid_pid_from_sysfs(const char *sysfs_path, unsigned *bus_type, unsigned short *vendor_id, unsigned short *product_id) { int res = 0; + + if (!sysfs_path) + return res; + /* Construct /device/uevent */ size_t uevent_path_len = strlen(sysfs_path) + 14 + 1; char* uevent_path = (char*) calloc(1, uevent_path_len); @@ -541,6 +568,9 @@ static int parse_hid_vid_pid_from_sysfs(const char *sysfs_path, unsigned *bus_ty static int get_hid_report_descriptor_from_hidraw(hid_device *dev, struct hidraw_report_descriptor *rpt_desc) { + if (!dev) + return -1; + int desc_size = 0; /* Get Report Descriptor Size */ @@ -834,6 +864,9 @@ static struct hid_device_info * create_device_info_for_device(struct udev_device } static struct hid_device_info * create_device_info_for_hid_device(hid_device *dev) { + if (!dev) + return NULL; + struct udev *udev; struct udev_device *udev_dev; struct stat s; @@ -1089,6 +1122,11 @@ hid_device * HID_API_EXPORT hid_open_path(const char *path) int HID_API_EXPORT hid_write(hid_device *dev, const unsigned char *data, size_t length) { + if (!dev) { + register_global_error("Device is NULL"); + return -1; + } + int bytes_written; if (!data || (length == 0)) { @@ -1107,6 +1145,11 @@ int HID_API_EXPORT hid_write(hid_device *dev, const unsigned char *data, size_t int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds) { + if (!dev) { + register_global_error("Device is NULL"); + return -1; + } + /* Set device error to none */ register_device_error(dev, NULL); @@ -1159,11 +1202,21 @@ int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t int HID_API_EXPORT hid_read(hid_device *dev, unsigned char *data, size_t length) { + if (!dev) { + register_global_error("Device is NULL"); + return -1; + } + return hid_read_timeout(dev, data, length, (dev->blocking)? -1: 0); } int HID_API_EXPORT hid_set_nonblocking(hid_device *dev, int nonblock) { + if (!dev) { + register_global_error("Device is NULL"); + return -1; + } + /* Do all non-blocking in userspace using poll(), since it looks like there's a bug in the kernel in some versions where read() will not return -1 on disconnection of the USB device */ @@ -1175,6 +1228,11 @@ int HID_API_EXPORT hid_set_nonblocking(hid_device *dev, int nonblock) int HID_API_EXPORT hid_send_feature_report(hid_device *dev, const unsigned char *data, size_t length) { + if (!dev) { + register_global_error("Device is NULL"); + return -1; + } + int res; register_device_error(dev, NULL); @@ -1188,6 +1246,11 @@ int HID_API_EXPORT hid_send_feature_report(hid_device *dev, const unsigned char int HID_API_EXPORT hid_get_feature_report(hid_device *dev, unsigned char *data, size_t length) { + if (!dev) { + register_global_error("Device is NULL"); + return -1; + } + int res; register_device_error(dev, NULL); @@ -1203,6 +1266,11 @@ int HID_API_EXPORT HID_API_CALL hid_send_output_report(hid_device *dev, const un { int res; + if (!dev) { + register_global_error("Device is NULL"); + return -1; + } + register_device_error(dev, NULL); res = ioctl(dev->device_handle, HIDIOCSOUTPUT(length), data); @@ -1214,6 +1282,11 @@ int HID_API_EXPORT HID_API_CALL hid_send_output_report(hid_device *dev, const un int HID_API_EXPORT HID_API_CALL hid_get_input_report(hid_device *dev, unsigned char *data, size_t length) { + if (!dev) { + register_global_error("Device is NULL"); + return -1; + } + int res; register_device_error(dev, NULL); @@ -1315,6 +1388,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) { + register_global_error("Device is NULL"); + return NULL; + } + if (!dev->device_info) { // Lazy initialize device_info dev->device_info = create_device_info_for_hid_device(dev); @@ -1326,6 +1404,11 @@ HID_API_EXPORT struct hid_device_info *HID_API_CALL hid_get_device_info(hid_devi int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *dev, int string_index, wchar_t *string, size_t maxlen) { + if (!dev) { + register_global_error("Device is NULL"); + return -1; + } + (void)string_index; (void)string; (void)maxlen; diff --git a/mac/hid.c b/mac/hid.c index e2b365c4f..8e4c926a6 100644 --- a/mac/hid.c +++ b/mac/hid.c @@ -282,6 +282,9 @@ static void register_device_error(hid_device *dev, const char *msg) /* Similar to 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, ...) { + if (!dev) + return; + va_list args; va_start(args, format); register_error_str_vformat(&dev->last_error_str, format, args); @@ -868,6 +871,9 @@ static void hid_report_callback(void *context, IOReturn result, void *sender, IOHIDReportType report_type, uint32_t report_id, uint8_t *report, CFIndex report_length) { + if (!context) + return; + (void) result; (void) sender; (void) report_type; @@ -921,12 +927,18 @@ static void hid_report_callback(void *context, IOReturn result, void *sender, hid_close(), and serves to stop the read_thread's run loop. */ static void perform_signal_callback(void *context) { + if (!context) + return; + hid_device *dev = (hid_device*) context; CFRunLoopStop(dev->run_loop); /*TODO: CFRunLoopGetCurrent()*/ } static void *read_thread(void *param) { + if (!param) + return NULL; + hid_device *dev = (hid_device*) param; SInt32 code; @@ -1096,6 +1108,11 @@ hid_device * HID_API_EXPORT hid_open_path(const char *path) static int set_report(hid_device *dev, IOHIDReportType type, const unsigned char *data, size_t length) { + if (!dev) { + register_global_error("Device is NULL"); + return -1; + } + const unsigned char *data_to_send = data; CFIndex length_to_send = length; IOReturn res; @@ -1138,6 +1155,16 @@ static int set_report(hid_device *dev, IOHIDReportType type, const unsigned char static int get_report(hid_device *dev, IOHIDReportType type, unsigned char *data, size_t length) { + if (!dev) { + register_global_error("Device is NULL"); + return -1; + } + + if (!data) { + register_device_error(dev, "Data is NULL"); + return -1; + } + unsigned char *report = data; CFIndex report_length = length; IOReturn res = kIOReturnSuccess; @@ -1183,6 +1210,9 @@ int HID_API_EXPORT hid_write(hid_device *dev, const unsigned char *data, size_t /* Helper function, so that this isn't duplicated in hid_read(). */ static int return_data(hid_device *dev, unsigned char *data, size_t length) { + if (!dev || !data) + return -1; + /* Copy the data out of the linked list item (rpt) into the return buffer (data), and delete the liked list item. */ struct input_report *rpt = dev->input_reports; @@ -1198,6 +1228,9 @@ static int return_data(hid_device *dev, unsigned char *data, size_t length) static int cond_wait(hid_device *dev, pthread_cond_t *cond, pthread_mutex_t *mutex) { + if (!dev) + return -1; + while (!dev->input_reports) { int res = pthread_cond_wait(cond, mutex); if (res != 0) @@ -1219,6 +1252,9 @@ static int cond_wait(hid_device *dev, pthread_cond_t *cond, pthread_mutex_t *mut static int cond_timedwait(hid_device *dev, pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime) { + if (!dev) + return -1; + while (!dev->input_reports) { int res = pthread_cond_timedwait(cond, mutex, abstime); if (res != 0) @@ -1236,13 +1272,17 @@ static int cond_timedwait(hid_device *dev, pthread_cond_t *cond, pthread_mutex_t } return 0; - } int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds) { int bytes_read = -1; + if (!dev) { + register_global_error("Device is NULL"); + return bytes_read; + } + /* Lock the access to the report list. */ pthread_mutex_lock(&dev->mutex); @@ -1320,11 +1360,21 @@ int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t int HID_API_EXPORT hid_read(hid_device *dev, unsigned char *data, size_t length) { + if (!dev) { + register_global_error("Device is NULL"); + return -1; + } + return hid_read_timeout(dev, data, length, (dev->blocking)? -1: 0); } int HID_API_EXPORT hid_set_nonblocking(hid_device *dev, int nonblock) { + if (!dev) { + register_global_error("Device is NULL"); + return -1; + } + /* All Nonblocking operation is handled by the library. */ dev->blocking = !nonblock; @@ -1465,6 +1515,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) { + register_global_error("Device is NULL"); + return NULL; + } + if (!dev->device_info) { dev->device_info = create_device_info(dev->device_handle); if (!dev->device_info) { @@ -1488,6 +1543,16 @@ int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *dev, int string_index int HID_API_EXPORT_CALL hid_darwin_get_location_id(hid_device *dev, uint32_t *location_id) { + if (!dev) { + register_global_error("Device is NULL"); + return -1; + } + + if (!location_id) { + register_device_error(dev, "Location ID is NULL"); + return -1; + } + int res = get_int_property(dev->device_handle, CFSTR(kIOHIDLocationIDKey)); if (res != 0) { *location_id = (uint32_t) res; @@ -1510,19 +1575,31 @@ int HID_API_EXPORT_CALL hid_darwin_get_open_exclusive(void) int HID_API_EXPORT_CALL hid_darwin_is_device_open_exclusive(hid_device *dev) { - if (!dev) + if (!dev) { + register_global_error("Device is NULL"); return -1; + } return (dev->open_options == kIOHIDOptionsTypeSeizeDevice) ? 1 : 0; } int HID_API_EXPORT_CALL hid_get_report_descriptor(hid_device *dev, unsigned char *buf, size_t buf_size) { + if (!dev) { + register_global_error("Device is NULL"); + return -1; + } + + if (!buf) { + register_device_error(dev, "Buffer is NULL"); + return -1; + } + CFTypeRef ref = IOHIDDeviceGetProperty(dev->device_handle, CFSTR(kIOHIDReportDescriptorKey)); if (ref != NULL && CFGetTypeID(ref) == CFDataGetTypeID()) { CFDataRef report_descriptor = (CFDataRef) ref; const UInt8 *descriptor_buf = CFDataGetBytePtr(report_descriptor); - CFIndex descriptor_buf_len = CFDataGetLength(report_descriptor); + const CFIndex descriptor_buf_len = CFDataGetLength(report_descriptor); size_t copy_len = (size_t) descriptor_buf_len; if (descriptor_buf == NULL || descriptor_buf_len < 0) { diff --git a/windows/hid.c b/windows/hid.c index 343cdb7c0..41382dd9c 100644 --- a/windows/hid.c +++ b/windows/hid.c @@ -227,6 +227,9 @@ static hid_device *new_hid_device() static void free_hid_device(hid_device *dev) { + if (!dev) + return; + CloseHandle(dev->ol.hEvent); CloseHandle(dev->write_ol.hEvent); CloseHandle(dev->device_handle); @@ -306,6 +309,9 @@ static void register_winapi_error_to_buffer(wchar_t **error_buffer, const WCHAR static void register_string_error_to_buffer(wchar_t **error_buffer, const WCHAR *string_error) { + if (!error_buffer) + return; + free(*error_buffer); *error_buffer = NULL; @@ -320,11 +326,17 @@ static void register_string_error_to_buffer(wchar_t **error_buffer, const WCHAR static void register_winapi_error(hid_device *dev, const WCHAR *op) { + if (!dev) + return; + register_winapi_error_to_buffer(&dev->last_error_str, op); } static void register_string_error(hid_device *dev, const WCHAR *string_error) { + if (!dev) + return; + register_string_error_to_buffer(&dev->last_error_str, string_error); } @@ -458,6 +470,9 @@ static int hid_internal_extract_int_token_value(wchar_t* string, const wchar_t* static void hid_internal_get_usb_info(struct hid_device_info* dev, DEVINST dev_node) { + if (!dev) + return; + wchar_t *device_id = NULL, *hardware_ids = NULL; device_id = hid_internal_get_devnode_property(dev_node, &DEVPKEY_Device_InstanceId, DEVPROP_TYPE_STRING); @@ -566,6 +581,9 @@ static void hid_internal_get_usb_info(struct hid_device_info* dev, DEVINST dev_n */ static void hid_internal_get_ble_info(struct hid_device_info* dev, DEVINST dev_node) { + if (!dev) + return; + if (wcslen(dev->manufacturer_string) == 0) { /* Manufacturer Name String (UUID: 0x2A29) */ wchar_t* manufacturer_string = hid_internal_get_devnode_property(dev_node, (const DEVPROPKEY*)&PKEY_DeviceInterface_Bluetooth_Manufacturer, DEVPROP_TYPE_STRING); @@ -1071,6 +1089,11 @@ int HID_API_EXPORT HID_API_CALL hid_write(hid_device *dev, const unsigned char * unsigned char *buf; + if (!dev) { + register_global_error(L"Device is NULL"); + return function_result; + } + if (!data || !length) { register_string_error(dev, L"Zero buffer/length"); return function_result; @@ -1143,9 +1166,13 @@ int HID_API_EXPORT HID_API_CALL hid_write(hid_device *dev, const unsigned char * return function_result; } - int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds) { + if (!dev) { + register_global_error(L"Device is NULL"); + return -1; + } + DWORD bytes_read = 0; size_t copy_len = 0; BOOL res = FALSE; @@ -1237,12 +1264,22 @@ int HID_API_EXPORT HID_API_CALL hid_read(hid_device *dev, unsigned char *data, s int HID_API_EXPORT HID_API_CALL hid_set_nonblocking(hid_device *dev, int nonblock) { + if (!dev) { + register_global_error(L"Device is NULL"); + return -1; + } + dev->blocking = !nonblock; return 0; /* Success */ } int HID_API_EXPORT HID_API_CALL hid_send_feature_report(hid_device *dev, const unsigned char *data, size_t length) { + if (!dev) { + register_global_error(L"Device is NULL"); + return -1; + } + BOOL res = FALSE; unsigned char *buf; size_t length_to_send; @@ -1290,6 +1327,11 @@ int HID_API_EXPORT HID_API_CALL hid_send_feature_report(hid_device *dev, const u static int hid_get_report(hid_device *dev, DWORD report_type, unsigned char *data, size_t length) { + if (!dev) { + register_global_error(L"Device is NULL"); + return -1; + } + BOOL res; DWORD bytes_returned = 0; @@ -1344,6 +1386,11 @@ int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *dev, unsigned int HID_API_EXPORT HID_API_CALL hid_send_output_report(hid_device* dev, const unsigned char* data, size_t length) { + if (!dev) { + register_global_error(L"Device is NULL"); + return -1; + } + BOOL res = FALSE; unsigned char *buf; size_t length_to_send; @@ -1405,6 +1452,11 @@ void HID_API_EXPORT HID_API_CALL hid_close(hid_device *dev) int HID_API_EXPORT_CALL HID_API_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *string, size_t maxlen) { + if (!dev) { + register_global_error(L"Device is NULL"); + return -1; + } + if (!string || !maxlen) { register_string_error(dev, L"Zero buffer/length"); return -1; @@ -1425,6 +1477,11 @@ int HID_API_EXPORT_CALL HID_API_CALL hid_get_manufacturer_string(hid_device *dev int HID_API_EXPORT_CALL HID_API_CALL hid_get_product_string(hid_device *dev, wchar_t *string, size_t maxlen) { + if (!dev) { + register_global_error(L"Device is NULL"); + return -1; + } + if (!string || !maxlen) { register_string_error(dev, L"Zero buffer/length"); return -1; @@ -1445,6 +1502,11 @@ int HID_API_EXPORT_CALL HID_API_CALL hid_get_product_string(hid_device *dev, wch int HID_API_EXPORT_CALL HID_API_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *string, size_t maxlen) { + if (!dev) { + register_global_error(L"Device is NULL"); + return -1; + } + if (!string || !maxlen) { register_string_error(dev, L"Zero buffer/length"); return -1; @@ -1464,6 +1526,11 @@ int HID_API_EXPORT_CALL HID_API_CALL hid_get_serial_number_string(hid_device *de } HID_API_EXPORT struct hid_device_info * HID_API_CALL hid_get_device_info(hid_device *dev) { + if (!dev) { + register_global_error(L"Device is NULL"); + return NULL; + } + if (!dev->device_info) { register_string_error(dev, L"NULL device info"); @@ -1475,6 +1542,11 @@ HID_API_EXPORT struct hid_device_info * HID_API_CALL hid_get_device_info(hid_dev int HID_API_EXPORT_CALL HID_API_CALL hid_get_indexed_string(hid_device *dev, int string_index, wchar_t *string, size_t maxlen) { + if (!dev) { + register_global_error(L"Device is NULL"); + return -1; + } + BOOL res; if (dev->device_info && dev->device_info->bus_type == HID_API_BUS_USB && maxlen > MAX_STRING_WCHARS_USB) { @@ -1495,6 +1567,11 @@ int HID_API_EXPORT_CALL HID_API_CALL hid_get_indexed_string(hid_device *dev, int int HID_API_EXPORT_CALL hid_winapi_get_container_id(hid_device *dev, GUID *container_id) { + if (!dev) { + register_global_error(L"Device is NULL"); + return -1; + } + wchar_t *interface_path = NULL, *device_id = NULL; CONFIGRET cr = CR_FAILURE; DEVINST dev_node; @@ -1547,6 +1624,11 @@ int HID_API_EXPORT_CALL hid_winapi_get_container_id(hid_device *dev, GUID *conta int HID_API_EXPORT_CALL hid_get_report_descriptor(hid_device *dev, unsigned char *buf, size_t buf_size) { + if (!dev) { + register_global_error(L"Device is NULL"); + return -1; + } + PHIDP_PREPARSED_DATA pp_data = NULL; if (!HidD_GetPreparsedData(dev->device_handle, &pp_data) || pp_data == NULL) {