From ff0661a86513aacda2c9c167f309faea4da00ef1 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Tue, 8 Dec 2015 20:08:49 +0000 Subject: [PATCH 01/14] windows: Handle ERROR_IO_PENDING from ReadFile in sp_nonblocking_read(). --- serialport.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/serialport.c b/serialport.c index 2f7618e..520d27e 100644 --- a/serialport.c +++ b/serialport.c @@ -1234,10 +1234,11 @@ SP_API enum sp_return sp_nonblocking_read(struct sp_port *port, void *buf, /* Do read. */ if (ReadFile(port->hdl, buf, count, NULL, &port->read_ovl) == 0) - RETURN_FAIL("ReadFile() failed"); + if (GetLastError() != ERROR_IO_PENDING) + RETURN_FAIL("ReadFile() failed"); /* Get number of bytes read. */ - if (GetOverlappedResult(port->hdl, &port->read_ovl, &bytes_read, TRUE) == 0) + if (GetOverlappedResult(port->hdl, &port->read_ovl, &bytes_read, FALSE) == 0) RETURN_FAIL("GetOverlappedResult() failed"); TRY(restart_wait_if_needed(port, bytes_read)); From 0a2d940c6e02b91e3b6e29109f7e931dcc65c692 Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Wed, 16 Dec 2015 19:07:49 +0100 Subject: [PATCH 02/14] fix iSerial on windows for composite devices --- libserialport_internal.h | 2 +- windows.c | 28 +++++++++++++++++++--------- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/libserialport_internal.h b/libserialport_internal.h index a0d872b..0f41d98 100644 --- a/libserialport_internal.h +++ b/libserialport_internal.h @@ -56,7 +56,7 @@ #endif #ifdef __APPLE__ #include -#include +#include #include #include #include diff --git a/windows.c b/windows.c index b411918..644a701 100644 --- a/windows.c +++ b/windows.c @@ -26,7 +26,7 @@ #define MAX_USB_PATH ((8 * 3) + (7 * 1) + 1) static void enumerate_hub(struct sp_port *port, const char *hub_name, - const char *parent_path); + const char *parent_path, DEVINST dev_inst); static char *wc_to_utf8(PWCHAR wc_buffer, ULONG size) { @@ -149,7 +149,7 @@ static char *get_string_descriptor(HANDLE hub_device, ULONG connection_index, } static void enumerate_hub_ports(struct sp_port *port, HANDLE hub_device, - ULONG nb_ports, const char *parent_path) + ULONG nb_ports, const char *parent_path, DEVINST dev_inst) { char path[MAX_USB_PATH]; ULONG index = 0; @@ -200,7 +200,7 @@ static void enumerate_hub_ports(struct sp_port *port, HANDLE hub_device, if ((ext_hub_name = get_external_hub_name(hub_device, index))) { snprintf(path, sizeof(path), "%s%ld.", parent_path, connection_info_ex->ConnectionIndex); - enumerate_hub(port, ext_hub_name, path); + enumerate_hub(port, ext_hub_name, path, dev_inst); } free(connection_info_ex); } else { @@ -224,9 +224,18 @@ static void enumerate_hub_ports(struct sp_port *port, HANDLE hub_device, if (connection_info_ex->DeviceDescriptor.iProduct) port->usb_product = get_string_descriptor(hub_device, index, connection_info_ex->DeviceDescriptor.iProduct); - if (connection_info_ex->DeviceDescriptor.iSerialNumber) + if (connection_info_ex->DeviceDescriptor.iSerialNumber) { port->usb_serial = get_string_descriptor(hub_device, index, connection_info_ex->DeviceDescriptor.iSerialNumber); + if (port->usb_serial == NULL) { + //composite device, get the parent's serial number + char device_id[MAX_DEVICE_ID_LEN]; + if (CM_Get_Parent(&dev_inst, dev_inst, 0) == CR_SUCCESS) { + if (CM_Get_Device_IDA(dev_inst, device_id, sizeof(device_id), 0) == CR_SUCCESS) + port->usb_serial = strdup(strrchr(device_id, '\\')+1); + } + } + } free(connection_info_ex); break; @@ -235,7 +244,7 @@ static void enumerate_hub_ports(struct sp_port *port, HANDLE hub_device, } static void enumerate_hub(struct sp_port *port, const char *hub_name, - const char *parent_path) + const char *parent_path, DEVINST dev_inst) { USB_NODE_INFORMATION hub_info; HANDLE hub_device; @@ -258,18 +267,19 @@ static void enumerate_hub(struct sp_port *port, const char *hub_name, &hub_info, size, &hub_info, size, &size, NULL)) /* Enumerate the ports of the hub. */ enumerate_hub_ports(port, hub_device, - hub_info.u.HubInformation.HubDescriptor.bNumberOfPorts, parent_path); + hub_info.u.HubInformation.HubDescriptor.bNumberOfPorts, parent_path, dev_inst); CloseHandle(hub_device); } static void enumerate_host_controller(struct sp_port *port, - HANDLE host_controller_device) + HANDLE host_controller_device, + DEVINST dev_inst) { char *root_hub_name; if ((root_hub_name = get_root_hub_name(host_controller_device))) { - enumerate_hub(port, root_hub_name, ""); + enumerate_hub(port, root_hub_name, "", dev_inst); free(root_hub_name); } } @@ -324,7 +334,7 @@ static void get_usb_details(struct sp_port *port, DEVINST dev_inst_match) GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if (host_controller_device != INVALID_HANDLE_VALUE) { - enumerate_host_controller(port, host_controller_device); + enumerate_host_controller(port, host_controller_device, dev_inst_match); CloseHandle(host_controller_device); } free(device_detail_data); From 8a4cda0c07c03b34986df2ea4d8329ca3b52b506 Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Fri, 18 Dec 2015 12:40:58 +0100 Subject: [PATCH 03/14] fix OSX on ElCapitan --- libserialport_internal.h | 2 +- macosx.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libserialport_internal.h b/libserialport_internal.h index 0f41d98..a0d872b 100644 --- a/libserialport_internal.h +++ b/libserialport_internal.h @@ -56,7 +56,7 @@ #endif #ifdef __APPLE__ #include -#include +#include #include #include #include diff --git a/macosx.c b/macosx.c index f5f1944..b0f2d02 100644 --- a/macosx.c +++ b/macosx.c @@ -64,7 +64,7 @@ SP_PRIV enum sp_return get_port_details(struct sp_port *port) IORegistryEntryGetParentEntry(ioport, kIOServicePlane, &ioparent); if ((cf_property=IORegistryEntrySearchCFProperty(ioparent,kIOServicePlane, - CFSTR("IOProviderClass"), kCFAllocatorDefault, + CFSTR("IOClass"), kCFAllocatorDefault, kIORegistryIterateRecursively | kIORegistryIterateParents))) { if (CFStringGetCString(cf_property, class, sizeof(class), kCFStringEncodingASCII) && From 89446e92f622de595cb13deb0d1c8b33e2c8a4e7 Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Mon, 21 Dec 2015 22:13:23 +0000 Subject: [PATCH 04/14] fix OSX port recognition --- macosx.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/macosx.c b/macosx.c index b0f2d02..a0df84e 100644 --- a/macosx.c +++ b/macosx.c @@ -74,6 +74,17 @@ SP_PRIV enum sp_return get_port_details(struct sp_port *port) } CFRelease(cf_property); } + if ((cf_property=IORegistryEntrySearchCFProperty(ioparent,kIOServicePlane, + CFSTR("IOProviderClass"), kCFAllocatorDefault, + kIORegistryIterateRecursively | kIORegistryIterateParents))) { + if (CFStringGetCString(cf_property, class, sizeof(class), + kCFStringEncodingASCII) && + strstr(class, "USB")) { + DEBUG("Found USB class device"); + port->transport = SP_TRANSPORT_USB; + } + CFRelease(cf_property); + } IOObjectRelease(ioparent); if ((cf_property = IORegistryEntrySearchCFProperty(ioport,kIOServicePlane, From 6c96f3cc41ca73f6f5672a60ef5f2e234fc50353 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Tue, 29 Dec 2015 02:36:04 +0000 Subject: [PATCH 05/14] Change debug message to "Port not open" when a closed port is used. Fixes bug #710. --- serialport.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/serialport.c b/serialport.c index 520d27e..c4a0e1b 100644 --- a/serialport.c +++ b/serialport.c @@ -389,12 +389,12 @@ SP_API void sp_free_port_list(struct sp_port **list) #ifdef _WIN32 #define CHECK_PORT_HANDLE() do { \ if (port->hdl == INVALID_HANDLE_VALUE) \ - RETURN_ERROR(SP_ERR_ARG, "Invalid port handle"); \ + RETURN_ERROR(SP_ERR_ARG, "Port not open"); \ } while (0) #else #define CHECK_PORT_HANDLE() do { \ if (port->fd < 0) \ - RETURN_ERROR(SP_ERR_ARG, "Invalid port fd"); \ + RETURN_ERROR(SP_ERR_ARG, "Port not open"); \ } while (0) #endif #define CHECK_OPEN_PORT() do { \ From f8ed8a6a289b7d1289cc3fec6a000fc0c4ee1a4e Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Thu, 7 Jan 2016 14:46:30 +0100 Subject: [PATCH 06/14] force memcpy to link against glibc2.2.5 implementation --- libserialport_internal.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libserialport_internal.h b/libserialport_internal.h index 669152b..636e0c0 100644 --- a/libserialport_internal.h +++ b/libserialport_internal.h @@ -65,6 +65,9 @@ #endif #ifdef __linux__ #include +#ifdef __amd64__ +__asm__(".symver memcpy,memcpy@GLIBC_2.2.5"); +#endif #ifndef __ANDROID__ #include "linux/serial.h" #endif From 658f2124144bca5ef033e0e5308c2434da27bee4 Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Fri, 15 Jan 2016 15:51:43 +0100 Subject: [PATCH 07/14] add get_port_details variant (faster/less info) --- freebsd.c | 2 +- libserialport_internal.h | 3 ++- linux.c | 2 +- macosx.c | 57 +++++++++++++++++++++------------------- serialport.c | 11 +++++--- windows.c | 55 ++++++++++++++++++++------------------ 6 files changed, 71 insertions(+), 59 deletions(-) diff --git a/freebsd.c b/freebsd.c index b5cd91a..e2b6c59 100644 --- a/freebsd.c +++ b/freebsd.c @@ -234,7 +234,7 @@ static int populate_port_struct_from_libusb_desc(struct sp_port *const port, return 0; } -SP_PRIV enum sp_return get_port_details(struct sp_port *port) +SP_PRIV enum sp_return get_port_details(struct sp_port *port, bool fetchDescriptors) { int rc; struct libusb20_backend *be; diff --git a/libserialport_internal.h b/libserialport_internal.h index 636e0c0..0e46bbe 100644 --- a/libserialport_internal.h +++ b/libserialport_internal.h @@ -38,6 +38,7 @@ #include #include #include +#include #ifdef _WIN32 #include #include @@ -234,7 +235,7 @@ extern void (*sp_debug_handler)(const char *format, ...); SP_PRIV struct sp_port **list_append(struct sp_port **list, const char *portname); /* OS-specific Helper functions. */ -SP_PRIV enum sp_return get_port_details(struct sp_port *port); +SP_PRIV enum sp_return get_port_details(struct sp_port *port, bool fetchDescriptors); SP_PRIV enum sp_return list_ports(struct sp_port ***list); #endif diff --git a/linux.c b/linux.c index 9016489..d931687 100644 --- a/linux.c +++ b/linux.c @@ -22,7 +22,7 @@ #include "libserialport.h" #include "libserialport_internal.h" -SP_PRIV enum sp_return get_port_details(struct sp_port *port) +SP_PRIV enum sp_return get_port_details(struct sp_port *port, bool fetchDescriptors) { /* * Description limited to 127 char, anything longer diff --git a/macosx.c b/macosx.c index a0df84e..a2b4424 100644 --- a/macosx.c +++ b/macosx.c @@ -22,7 +22,7 @@ #include "libserialport.h" #include "libserialport_internal.h" -SP_PRIV enum sp_return get_port_details(struct sp_port *port) +SP_PRIV enum sp_return get_port_details(struct sp_port *port, bool fetchDescriptors) { /* * Description limited to 127 char, anything longer @@ -152,37 +152,40 @@ SP_PRIV enum sp_return get_port_details(struct sp_port *port) if (cf_product) CFRelease(cf_product); - if ((cf_property = IORegistryEntrySearchCFProperty(ioport,kIOServicePlane, - CFSTR("USB Vendor Name"), kCFAllocatorDefault, - kIORegistryIterateRecursively | kIORegistryIterateParents))) { - if (CFStringGetCString(cf_property, manufacturer, sizeof(manufacturer), - kCFStringEncodingASCII)) { - DEBUG_FMT("Found manufacturer %s", manufacturer); - port->usb_manufacturer = strdup(manufacturer); + if (fetchDescriptors == true) { + + if ((cf_property = IORegistryEntrySearchCFProperty(ioport,kIOServicePlane, + CFSTR("USB Vendor Name"), kCFAllocatorDefault, + kIORegistryIterateRecursively | kIORegistryIterateParents))) { + if (CFStringGetCString(cf_property, manufacturer, sizeof(manufacturer), + kCFStringEncodingASCII)) { + DEBUG_FMT("Found manufacturer %s", manufacturer); + port->usb_manufacturer = strdup(manufacturer); + } + CFRelease(cf_property); } - CFRelease(cf_property); - } - if ((cf_property = IORegistryEntrySearchCFProperty(ioport,kIOServicePlane, - CFSTR("USB Product Name"), kCFAllocatorDefault, - kIORegistryIterateRecursively | kIORegistryIterateParents))) { - if (CFStringGetCString(cf_property, product, sizeof(product), - kCFStringEncodingASCII)) { - DEBUG_FMT("Found product name %s", product); - port->usb_product = strdup(product); + if ((cf_property = IORegistryEntrySearchCFProperty(ioport,kIOServicePlane, + CFSTR("USB Product Name"), kCFAllocatorDefault, + kIORegistryIterateRecursively | kIORegistryIterateParents))) { + if (CFStringGetCString(cf_property, product, sizeof(product), + kCFStringEncodingASCII)) { + DEBUG_FMT("Found product name %s", product); + port->usb_product = strdup(product); + } + CFRelease(cf_property); } - CFRelease(cf_property); - } - if ((cf_property = IORegistryEntrySearchCFProperty(ioport,kIOServicePlane, - CFSTR("USB Serial Number"), kCFAllocatorDefault, - kIORegistryIterateRecursively | kIORegistryIterateParents))) { - if (CFStringGetCString(cf_property, serial, sizeof(serial), - kCFStringEncodingASCII)) { - DEBUG_FMT("Found serial number %s", serial); - port->usb_serial = strdup(serial); + if ((cf_property = IORegistryEntrySearchCFProperty(ioport,kIOServicePlane, + CFSTR("USB Serial Number"), kCFAllocatorDefault, + kIORegistryIterateRecursively | kIORegistryIterateParents))) { + if (CFStringGetCString(cf_property, serial, sizeof(serial), + kCFStringEncodingASCII)) { + DEBUG_FMT("Found serial number %s", serial); + port->usb_serial = strdup(serial); + } + CFRelease(cf_property); } - CFRelease(cf_property); } IOObjectRelease(ioport); diff --git a/serialport.c b/serialport.c index c4a0e1b..e2e4a90 100644 --- a/serialport.c +++ b/serialport.c @@ -55,7 +55,7 @@ static enum sp_return get_config(struct sp_port *port, struct port_data *data, static enum sp_return set_config(struct sp_port *port, struct port_data *data, const struct sp_port_config *config); -SP_API enum sp_return sp_get_port_by_name(const char *portname, struct sp_port **port_ptr) +SP_API enum sp_return sp_get_port_by_name_desc(const char *portname, struct sp_port **port_ptr, bool fetchDescriptors) { struct sp_port *port; #ifndef NO_PORT_METADATA @@ -106,7 +106,7 @@ SP_API enum sp_return sp_get_port_by_name(const char *portname, struct sp_port * port->bluetooth_address = NULL; #ifndef NO_PORT_METADATA - if ((ret = get_port_details(port)) != SP_OK) { + if ((ret = get_port_details(port, fetchDescriptors)) != SP_OK) { sp_free_port(port); return ret; } @@ -117,6 +117,11 @@ SP_API enum sp_return sp_get_port_by_name(const char *portname, struct sp_port * RETURN_OK(); } +SP_API enum sp_return sp_get_port_by_name(const char *portname, struct sp_port **port_ptr) +{ + return sp_get_port_by_name_desc(portname, port_ptr, true); +} + SP_API char *sp_get_port_name(const struct sp_port *port) { TRACE("%p", port); @@ -313,7 +318,7 @@ SP_PRIV struct sp_port **list_append(struct sp_port **list, if (!(tmp = realloc(list, sizeof(struct sp_port *) * (count + 2)))) goto fail; list = tmp; - if (sp_get_port_by_name(portname, &list[count]) != SP_OK) + if (sp_get_port_by_name_desc(portname, &list[count], false) != SP_OK) goto fail; list[count + 1] = NULL; return list; diff --git a/windows.c b/windows.c index 644a701..ab57f8b 100644 --- a/windows.c +++ b/windows.c @@ -26,7 +26,7 @@ #define MAX_USB_PATH ((8 * 3) + (7 * 1) + 1) static void enumerate_hub(struct sp_port *port, const char *hub_name, - const char *parent_path, DEVINST dev_inst); + const char *parent_path, DEVINST dev_inst, bool fetchDescriptors); static char *wc_to_utf8(PWCHAR wc_buffer, ULONG size) { @@ -149,7 +149,7 @@ static char *get_string_descriptor(HANDLE hub_device, ULONG connection_index, } static void enumerate_hub_ports(struct sp_port *port, HANDLE hub_device, - ULONG nb_ports, const char *parent_path, DEVINST dev_inst) + ULONG nb_ports, const char *parent_path, DEVINST dev_inst, bool fetchDescriptors) { char path[MAX_USB_PATH]; ULONG index = 0; @@ -200,7 +200,7 @@ static void enumerate_hub_ports(struct sp_port *port, HANDLE hub_device, if ((ext_hub_name = get_external_hub_name(hub_device, index))) { snprintf(path, sizeof(path), "%s%ld.", parent_path, connection_info_ex->ConnectionIndex); - enumerate_hub(port, ext_hub_name, path, dev_inst); + enumerate_hub(port, ext_hub_name, path, dev_inst, fetchDescriptors); } free(connection_info_ex); } else { @@ -218,21 +218,24 @@ static void enumerate_hub_ports(struct sp_port *port, HANDLE hub_device, port->usb_vid = connection_info_ex->DeviceDescriptor.idVendor; port->usb_pid = connection_info_ex->DeviceDescriptor.idProduct; - if (connection_info_ex->DeviceDescriptor.iManufacturer) - port->usb_manufacturer = get_string_descriptor(hub_device,index, - connection_info_ex->DeviceDescriptor.iManufacturer); - if (connection_info_ex->DeviceDescriptor.iProduct) - port->usb_product = get_string_descriptor(hub_device, index, - connection_info_ex->DeviceDescriptor.iProduct); - if (connection_info_ex->DeviceDescriptor.iSerialNumber) { - port->usb_serial = get_string_descriptor(hub_device, index, - connection_info_ex->DeviceDescriptor.iSerialNumber); - if (port->usb_serial == NULL) { - //composite device, get the parent's serial number - char device_id[MAX_DEVICE_ID_LEN]; - if (CM_Get_Parent(&dev_inst, dev_inst, 0) == CR_SUCCESS) { - if (CM_Get_Device_IDA(dev_inst, device_id, sizeof(device_id), 0) == CR_SUCCESS) - port->usb_serial = strdup(strrchr(device_id, '\\')+1); + if (fetchDescriptors) { + + if (connection_info_ex->DeviceDescriptor.iManufacturer) + port->usb_manufacturer = get_string_descriptor(hub_device,index, + connection_info_ex->DeviceDescriptor.iManufacturer); + if (connection_info_ex->DeviceDescriptor.iProduct) + port->usb_product = get_string_descriptor(hub_device, index, + connection_info_ex->DeviceDescriptor.iProduct); + if (connection_info_ex->DeviceDescriptor.iSerialNumber) { + port->usb_serial = get_string_descriptor(hub_device, index, + connection_info_ex->DeviceDescriptor.iSerialNumber); + if (port->usb_serial == NULL) { + //composite device, get the parent's serial number + char device_id[MAX_DEVICE_ID_LEN]; + if (CM_Get_Parent(&dev_inst, dev_inst, 0) == CR_SUCCESS) { + if (CM_Get_Device_IDA(dev_inst, device_id, sizeof(device_id), 0) == CR_SUCCESS) + port->usb_serial = strdup(strrchr(device_id, '\\')+1); + } } } } @@ -244,7 +247,7 @@ static void enumerate_hub_ports(struct sp_port *port, HANDLE hub_device, } static void enumerate_hub(struct sp_port *port, const char *hub_name, - const char *parent_path, DEVINST dev_inst) + const char *parent_path, DEVINST dev_inst, bool fetchDescriptors) { USB_NODE_INFORMATION hub_info; HANDLE hub_device; @@ -267,24 +270,24 @@ static void enumerate_hub(struct sp_port *port, const char *hub_name, &hub_info, size, &hub_info, size, &size, NULL)) /* Enumerate the ports of the hub. */ enumerate_hub_ports(port, hub_device, - hub_info.u.HubInformation.HubDescriptor.bNumberOfPorts, parent_path, dev_inst); + hub_info.u.HubInformation.HubDescriptor.bNumberOfPorts, parent_path, dev_inst, fetchDescriptors); CloseHandle(hub_device); } static void enumerate_host_controller(struct sp_port *port, HANDLE host_controller_device, - DEVINST dev_inst) + DEVINST dev_inst, bool fetchDescriptors) { char *root_hub_name; if ((root_hub_name = get_root_hub_name(host_controller_device))) { - enumerate_hub(port, root_hub_name, "", dev_inst); + enumerate_hub(port, root_hub_name, "", dev_inst, fetchDescriptors); free(root_hub_name); } } -static void get_usb_details(struct sp_port *port, DEVINST dev_inst_match) +static void get_usb_details(struct sp_port *port, DEVINST dev_inst_match, bool fetchDescriptors) { HDEVINFO device_info; SP_DEVINFO_DATA device_info_data; @@ -334,7 +337,7 @@ static void get_usb_details(struct sp_port *port, DEVINST dev_inst_match) GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if (host_controller_device != INVALID_HANDLE_VALUE) { - enumerate_host_controller(port, host_controller_device, dev_inst_match); + enumerate_host_controller(port, host_controller_device, dev_inst_match, fetchDescriptors); CloseHandle(host_controller_device); } free(device_detail_data); @@ -344,7 +347,7 @@ static void get_usb_details(struct sp_port *port, DEVINST dev_inst_match) return; } -SP_PRIV enum sp_return get_port_details(struct sp_port *port) +SP_PRIV enum sp_return get_port_details(struct sp_port *port, bool fetchDescriptors) { /* * Description limited to 127 char, anything longer @@ -465,7 +468,7 @@ SP_PRIV enum sp_return get_port_details(struct sp_port *port) CloseHandle(handle); /* Retrieve USB device details from the device descriptor. */ - get_usb_details(port, device_info_data.DevInst); + get_usb_details(port, device_info_data.DevInst, fetchDescriptors); } break; } From f6e3136156e984403fad51844a2a86bb0fcdac90 Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Tue, 5 Apr 2016 13:01:40 +0200 Subject: [PATCH 08/14] don't wakeup device to avoid FTDI reset --- windows.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/windows.c b/windows.c index ab57f8b..6939f6e 100644 --- a/windows.c +++ b/windows.c @@ -455,18 +455,6 @@ SP_PRIV enum sp_return get_port_details(struct sp_port *port, bool fetchDescript port->usb_path = strdup(usb_path); - /* Wake up the USB device to be able to read string descriptor. */ - char *escaped_port_name; - HANDLE handle; - if (!(escaped_port_name = malloc(strlen(port->name) + 5))) - RETURN_ERROR(SP_ERR_MEM, "Escaped port name malloc failed"); - sprintf(escaped_port_name, "\\\\.\\%s", port->name); - handle = CreateFile(escaped_port_name, GENERIC_READ, 0, 0, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED, 0); - free(escaped_port_name); - CloseHandle(handle); - /* Retrieve USB device details from the device descriptor. */ get_usb_details(port, device_info_data.DevInst, fetchDescriptors); } From d24994c5cefb4103e3d70b589ccc507116df6b15 Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Wed, 18 May 2016 20:50:54 +0200 Subject: [PATCH 09/14] [WIN] handle composite ports in a saner way --- libserialport_internal.h | 1 + windows.c | 14 +++++++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/libserialport_internal.h b/libserialport_internal.h index 0e46bbe..cf256bd 100644 --- a/libserialport_internal.h +++ b/libserialport_internal.h @@ -116,6 +116,7 @@ struct sp_port { BYTE pending_byte; BOOL writing; BOOL wait_running; + BOOL composite; #else int fd; #endif diff --git a/windows.c b/windows.c index 6939f6e..074143a 100644 --- a/windows.c +++ b/windows.c @@ -281,6 +281,13 @@ static void enumerate_host_controller(struct sp_port *port, { char *root_hub_name; + if (port->composite) { + //remove last part of the path + char * pch; + pch=strrchr(port->usb_path,'.'); + port->usb_path[pch-port->usb_path] = '\0'; + } + if ((root_hub_name = get_root_hub_name(host_controller_device))) { enumerate_hub(port, root_hub_name, "", dev_inst, fetchDescriptors); free(root_hub_name); @@ -369,6 +376,7 @@ SP_PRIV enum sp_return get_port_details(struct sp_port *port, bool fetchDescript char value[8], class[16]; DWORD size, type; CONFIGRET cr; + port->composite = FALSE; /* Check if this is the device we are looking for. */ device_key = SetupDiOpenDevRegKey(device_info, &device_info_data, @@ -430,12 +438,12 @@ SP_PRIV enum sp_return get_port_details(struct sp_port *port, bool fetchDescript &compat_ids, &size, 0) == CR_SUCCESS) { while (*p) { - if (!strncmp(p, "USB\\COMPOSITE", 13)) + if (!strncmp(p, "USB\\COMPOSITE", 13)) { + port->composite = TRUE; break; + } p += strlen(p) + 1; } - if (*p) - continue; } /* Stop the recursion when reaching the USB root. */ From 70af63f12ae290a20a05e71d933d72d0db85b93a Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Thu, 21 Jul 2016 16:22:06 +0200 Subject: [PATCH 10/14] [WINDOWS] replace unreliable wc_to_utf8 routine --- windows.c | 48 ++++++++++++++++-------------------------------- 1 file changed, 16 insertions(+), 32 deletions(-) diff --git a/windows.c b/windows.c index 074143a..4952dce 100644 --- a/windows.c +++ b/windows.c @@ -28,32 +28,12 @@ static void enumerate_hub(struct sp_port *port, const char *hub_name, const char *parent_path, DEVINST dev_inst, bool fetchDescriptors); -static char *wc_to_utf8(PWCHAR wc_buffer, ULONG size) -{ - WCHAR wc_str[(size / sizeof(WCHAR)) + 1]; - char *utf8_str; - - /* Zero-terminate the wide char string. */ - memcpy(wc_str, wc_buffer, size); - wc_str[sizeof(wc_str) - 1] = 0; - - /* Compute the size of the UTF-8 converted string. */ - if (!(size = WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, wc_str, -1, - NULL, 0, NULL, NULL))) - return NULL; - - /* Allocate UTF-8 output buffer. */ - if (!(utf8_str = malloc(size))) - return NULL; - - /* Actually converted to UTF-8. */ - if (!WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, wc_str, -1, - utf8_str, size, NULL, NULL)) { - free(utf8_str); - return NULL; - } - - return utf8_str; +static char* wc_to_utf8(const wchar_t* wc, ULONG size) { + int ulen = WideCharToMultiByte(CP_UTF8, 0, wc, -1, NULL, 0, NULL, NULL); + char * ubuf = malloc(ulen + 1); + WideCharToMultiByte(CP_UTF8, 0, wc, -1, ubuf, ulen, NULL, NULL); + ubuf[ulen] = 0; + return ubuf; } static char *get_root_hub_name(HANDLE host_controller) @@ -220,26 +200,30 @@ static void enumerate_hub_ports(struct sp_port *port, HANDLE hub_device, if (fetchDescriptors) { - if (connection_info_ex->DeviceDescriptor.iManufacturer) + if (connection_info_ex->DeviceDescriptor.iManufacturer) { port->usb_manufacturer = get_string_descriptor(hub_device,index, connection_info_ex->DeviceDescriptor.iManufacturer); - if (connection_info_ex->DeviceDescriptor.iProduct) + } + if (connection_info_ex->DeviceDescriptor.iProduct) { port->usb_product = get_string_descriptor(hub_device, index, connection_info_ex->DeviceDescriptor.iProduct); + } if (connection_info_ex->DeviceDescriptor.iSerialNumber) { port->usb_serial = get_string_descriptor(hub_device, index, connection_info_ex->DeviceDescriptor.iSerialNumber); - if (port->usb_serial == NULL) { + if (port->usb_serial == NULL && port->composite) { //composite device, get the parent's serial number char device_id[MAX_DEVICE_ID_LEN]; if (CM_Get_Parent(&dev_inst, dev_inst, 0) == CR_SUCCESS) { - if (CM_Get_Device_IDA(dev_inst, device_id, sizeof(device_id), 0) == CR_SUCCESS) - port->usb_serial = strdup(strrchr(device_id, '\\')+1); + if (CM_Get_Device_IDA(dev_inst, device_id, sizeof(device_id), 0) == CR_SUCCESS) { + if (strlen(device_id) > 0) { + port->usb_serial = strdup(strrchr(device_id, '\\')+1); + } + } } } } } - free(connection_info_ex); break; } From b5cc9c4f031aee54e8be8f0abb569454213ccad0 Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Fri, 21 Oct 2016 16:02:55 +0200 Subject: [PATCH 11/14] Avoid math operations with NULL pointer strrchr() can return NULL if the character is not found. Since "composite" is true in some special cases with only one level of nesting, the math operation was failing badly. This should solve a couple of bugs about Arduino IDE crashing due to libListSerialJ --- windows.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/windows.c b/windows.c index 4952dce..006dee8 100644 --- a/windows.c +++ b/windows.c @@ -269,7 +269,9 @@ static void enumerate_host_controller(struct sp_port *port, //remove last part of the path char * pch; pch=strrchr(port->usb_path,'.'); - port->usb_path[pch-port->usb_path] = '\0'; + if (pch != NULL) { + port->usb_path[pch-port->usb_path] = '\0'; + } } if ((root_hub_name = get_root_hub_name(host_controller_device))) { From 6c406689b6018dd0da0acde76b6db1bad9351cb3 Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Tue, 6 Dec 2016 10:24:55 +0100 Subject: [PATCH 12/14] [TEMP] avoid searching for USB bus and address on osx if this feature becomes necessary, borrow it from libusb (https://github.com/libusb/libusb/blob/master/libusb/os/darwin_usb.c) Solves https://github.com/arduino/Arduino/issues/5210 --- macosx.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/macosx.c b/macosx.c index a2b4424..fa4a9a5 100644 --- a/macosx.c +++ b/macosx.c @@ -107,7 +107,7 @@ SP_PRIV enum sp_return get_port_details(struct sp_port *port, bool fetchDescript } else { DEBUG("No description for this device"); } - +#if 0 cf_bus = IORegistryEntrySearchCFProperty(ioport, kIOServicePlane, CFSTR("USBBusNumber"), kCFAllocatorDefault, @@ -118,9 +118,11 @@ SP_PRIV enum sp_return get_port_details(struct sp_port *port, bool fetchDescript kCFAllocatorDefault, kIORegistryIterateRecursively | kIORegistryIterateParents); - if (cf_bus && cf_address && - CFNumberGetValue(cf_bus , kCFNumberIntType, &bus) && - CFNumberGetValue(cf_address, kCFNumberIntType, &address)) { + if (cf_bus && cf_address) { + DEBUG_FMT("CFTypeRef type is: %s\n",CFStringGetCStringPtr(CFCopyTypeIDDescription(CFGetTypeID(cf_bus)),kCFStringEncodingUTF8)); + DEBUG_FMT("CFTypeRef type is: %s\n",CFStringGetCStringPtr(CFCopyTypeIDDescription(CFGetTypeID(cf_address)),kCFStringEncodingUTF8)); + CFNumberGetValue(cf_bus , kCFNumberIntType, &bus); + CFNumberGetValue(cf_address, kCFNumberIntType, &address); DEBUG_FMT("Found matching USB bus:address %03d:%03d", bus, address); port->usb_bus = bus; port->usb_address = address; @@ -129,7 +131,7 @@ SP_PRIV enum sp_return get_port_details(struct sp_port *port, bool fetchDescript CFRelease(cf_bus); if (cf_address) CFRelease(cf_address); - +#endif cf_vendor = IORegistryEntrySearchCFProperty(ioport, kIOServicePlane, CFSTR("idVendor"), kCFAllocatorDefault, From 6bb62ff2156fa1a51f4dcd686bf3f8ed1540455c Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Mon, 12 Dec 2016 12:13:04 +0100 Subject: [PATCH 13/14] [OSX] Bail out if wwan serial port --- macosx.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/macosx.c b/macosx.c index fa4a9a5..2a063f7 100644 --- a/macosx.c +++ b/macosx.c @@ -56,7 +56,7 @@ SP_PRIV enum sp_return get_port_details(struct sp_port *port, bool fetchDescript result = CFStringGetCString(cf_property, path, sizeof(path), kCFStringEncodingASCII); CFRelease(cf_property); - if (!result || strcmp(path, port->name)) { + if (!result || strcmp(path, port->name) || strstr(path, "wwan")) { IOObjectRelease(ioport); continue; } @@ -107,7 +107,6 @@ SP_PRIV enum sp_return get_port_details(struct sp_port *port, bool fetchDescript } else { DEBUG("No description for this device"); } -#if 0 cf_bus = IORegistryEntrySearchCFProperty(ioport, kIOServicePlane, CFSTR("USBBusNumber"), kCFAllocatorDefault, @@ -119,8 +118,6 @@ SP_PRIV enum sp_return get_port_details(struct sp_port *port, bool fetchDescript kIORegistryIterateRecursively | kIORegistryIterateParents); if (cf_bus && cf_address) { - DEBUG_FMT("CFTypeRef type is: %s\n",CFStringGetCStringPtr(CFCopyTypeIDDescription(CFGetTypeID(cf_bus)),kCFStringEncodingUTF8)); - DEBUG_FMT("CFTypeRef type is: %s\n",CFStringGetCStringPtr(CFCopyTypeIDDescription(CFGetTypeID(cf_address)),kCFStringEncodingUTF8)); CFNumberGetValue(cf_bus , kCFNumberIntType, &bus); CFNumberGetValue(cf_address, kCFNumberIntType, &address); DEBUG_FMT("Found matching USB bus:address %03d:%03d", bus, address); @@ -131,7 +128,7 @@ SP_PRIV enum sp_return get_port_details(struct sp_port *port, bool fetchDescript CFRelease(cf_bus); if (cf_address) CFRelease(cf_address); -#endif + cf_vendor = IORegistryEntrySearchCFProperty(ioport, kIOServicePlane, CFSTR("idVendor"), kCFAllocatorDefault, From 16e35cfa29ecf4292f19f07141c6b112a6848c69 Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Wed, 14 Dec 2016 18:02:49 +0100 Subject: [PATCH 14/14] Add interface descriptor to Linux port --- linux.c | 20 +++++++++++++++++--- serialport.c | 2 +- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/linux.c b/linux.c index d931687..c081072 100644 --- a/linux.c +++ b/linux.c @@ -31,7 +31,7 @@ SP_PRIV enum sp_return get_port_details(struct sp_port *port, bool fetchDescript char description[128]; int bus, address; unsigned int vid, pid; - char manufacturer[128], product[128], serial[128]; + char manufacturer[128], product[128], serial[128], interface[128]; char baddr[32]; const char dir_name[] = "/sys/class/tty/%s/device/%s%s"; char sub_dir[32] = "", file_name[PATH_MAX]; @@ -40,6 +40,8 @@ SP_PRIV enum sp_return get_port_details(struct sp_port *port, bool fetchDescript int i, count; struct stat statbuf; + interface[0] = '\0'; + if (strncmp(port->name, "/dev/", 5)) RETURN_ERROR(SP_ERR_ARG, "Device name not recognized"); @@ -59,6 +61,18 @@ SP_PRIV enum sp_return get_port_details(struct sp_port *port, bool fetchDescript if (port->transport == SP_TRANSPORT_USB) { for (i = 0; i < 5; i++) { + + snprintf(file_name, sizeof(file_name), dir_name, dev, sub_dir, "interface"); + if ((file = fopen(file_name, "r"))) { + if ((ptr = fgets(interface, sizeof(interface), file))) { + ptr = interface + strlen(interface) - 1; + if (ptr >= interface && *ptr == '\n') + *ptr = 0; + port->description = strdup(interface); + } + fclose(file); + } + strcat(sub_dir, "../"); snprintf(file_name, sizeof(file_name), dir_name, dev, sub_dir, "busnum"); @@ -145,9 +159,9 @@ SP_PRIV enum sp_return get_port_details(struct sp_port *port, bool fetchDescript } /* If present, add serial to description for better identification. */ - if (port->usb_serial && strlen(port->usb_serial)) { + if (strlen(interface) > 0) { snprintf(description, sizeof(description), - "%s - %s", port->description, port->usb_serial); + "%s - %s", port->description, interface); if (port->description) free(port->description); port->description = strdup(description); diff --git a/serialport.c b/serialport.c index e2e4a90..ad03249 100644 --- a/serialport.c +++ b/serialport.c @@ -55,7 +55,7 @@ static enum sp_return get_config(struct sp_port *port, struct port_data *data, static enum sp_return set_config(struct sp_port *port, struct port_data *data, const struct sp_port_config *config); -SP_API enum sp_return sp_get_port_by_name_desc(const char *portname, struct sp_port **port_ptr, bool fetchDescriptors) +static enum sp_return sp_get_port_by_name_desc(const char *portname, struct sp_port **port_ptr, bool fetchDescriptors) { struct sp_port *port; #ifndef NO_PORT_METADATA