mirror of
git://sigrok.org/libserialport
synced 2023-08-10 21:13:24 +03:00
windows: Fix iSerial for composite devices.
USB composite devices can contain an ACM serial interface. On Windows, the correct iSerial descriptor field is assigned to the parent (composite) device instead of to the actual serial interface. A bogus value is returned if the serial interface is asked to provide the S/N. This patch provides a fallback for this kind of device (tested on Android with adb + cdc gadgets and on Arduino Zero Programming Port)
This commit is contained in:
parent
aacba60dca
commit
02c8a1424d
28
windows.c
28
windows.c
@ -26,7 +26,7 @@
|
|||||||
#define MAX_USB_PATH ((8 * 3) + (7 * 1) + 1)
|
#define MAX_USB_PATH ((8 * 3) + (7 * 1) + 1)
|
||||||
|
|
||||||
static void enumerate_hub(struct sp_port *port, const char *hub_name,
|
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)
|
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,
|
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];
|
char path[MAX_USB_PATH];
|
||||||
ULONG index = 0;
|
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))) {
|
if ((ext_hub_name = get_external_hub_name(hub_device, index))) {
|
||||||
snprintf(path, sizeof(path), "%s%ld.",
|
snprintf(path, sizeof(path), "%s%ld.",
|
||||||
parent_path, connection_info_ex->ConnectionIndex);
|
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);
|
free(connection_info_ex);
|
||||||
} else {
|
} else {
|
||||||
@ -224,9 +224,18 @@ static void enumerate_hub_ports(struct sp_port *port, HANDLE hub_device,
|
|||||||
if (connection_info_ex->DeviceDescriptor.iProduct)
|
if (connection_info_ex->DeviceDescriptor.iProduct)
|
||||||
port->usb_product = get_string_descriptor(hub_device, index,
|
port->usb_product = get_string_descriptor(hub_device, index,
|
||||||
connection_info_ex->DeviceDescriptor.iProduct);
|
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,
|
port->usb_serial = get_string_descriptor(hub_device, index,
|
||||||
connection_info_ex->DeviceDescriptor.iSerialNumber);
|
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);
|
free(connection_info_ex);
|
||||||
break;
|
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,
|
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;
|
USB_NODE_INFORMATION hub_info;
|
||||||
HANDLE hub_device;
|
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))
|
&hub_info, size, &hub_info, size, &size, NULL))
|
||||||
/* Enumerate the ports of the hub. */
|
/* Enumerate the ports of the hub. */
|
||||||
enumerate_hub_ports(port, hub_device,
|
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);
|
CloseHandle(hub_device);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void enumerate_host_controller(struct sp_port *port,
|
static void enumerate_host_controller(struct sp_port *port,
|
||||||
HANDLE host_controller_device)
|
HANDLE host_controller_device,
|
||||||
|
DEVINST dev_inst)
|
||||||
{
|
{
|
||||||
char *root_hub_name;
|
char *root_hub_name;
|
||||||
|
|
||||||
if ((root_hub_name = get_root_hub_name(host_controller_device))) {
|
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);
|
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,
|
GENERIC_WRITE, FILE_SHARE_WRITE,
|
||||||
NULL, OPEN_EXISTING, 0, NULL);
|
NULL, OPEN_EXISTING, 0, NULL);
|
||||||
if (host_controller_device != INVALID_HANDLE_VALUE) {
|
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);
|
CloseHandle(host_controller_device);
|
||||||
}
|
}
|
||||||
free(device_detail_data);
|
free(device_detail_data);
|
||||||
|
Loading…
Reference in New Issue
Block a user