How can I get the product string from USB Device Descriptor (device is not the hard drive, it is external device like headset) on C# or C++? I need to get "My Headset" string.
======================== USB Device ========================
+++++++++++++++++ Device Information ++++++++++++++++++
Device Description : USB Composite Device
Device Path : \\?\usb#vid_2ae2&pid_1388#abcdef0123456789#{a5dcbf10-6530-11d2-901f-00c04fb951ed}
Device ID : USB\VID_2AE2&PID_1388\ABCDEF0123456789
Driver KeyName : {36fc9e60-c465-11cf-8056-444553540000}\0018 (GUID_DEVCLASS_USB)
Driver : C:\Windows\System32\drivers\usbccgp.sys (Version: 6.3.9600.17238 Date: 2014-07-24)
Driver Inf : C:\Windows\inf\usb.inf
Legacy BusType : PNPBus
Class : USB
Service : usbccgp
Enumerator : USB
Location Info : Port_#0006.Hub_#0003
Location IDs : PCIROOT(0)#PCI(1400)#USBROOT(0)#USB(6), ACPI(_SB_)#ACPI(PCI0)#ACPI(XHC_)#ACPI(RHUB)#ACPI(HS06)
Container ID : {acb9ebb8-b976-57c5-b90d-5ecc5e96e487}
Manufacturer Info : (Standard USB Host Controller)
Capabilities : 0x94 (Removable, UniqueID, SurpriseRemovalOK)
Address : 6
Problem Code : 0
Power State : D0 (supported: D0, D3, wake from D0)
Child Device 1 : USB Input Device
Device ID : USB\VID_2AE2&PID_1388&MI_03\6&12E75DA&0&0003
Class : HIDClass
Child Device 1 : HID-compliant consumer control device
Device ID : HID\VID_2AE2&PID_1388&MI_03\7&178A021A&0&0000
Class : HIDClass
Child Device 2 : USB Audio Device
Device ID : USB\VID_2AE2&PID_1388&MI_00\6&12E75DA&0&0000
Class : MEDIA
Child Device 1 : Audio Endpoint
Device ID : SWD\MMDEVAPI\{0.0.1.00000000}.{0B0B6598-290C-495B-A4E1-D6A633F61574}
Class : AudioEndpoint
Child Device 2 : Audio Endpoint
Device ID : SWD\MMDEVAPI\{0.0.0.00000000}.{E3ADC851-586E-4FF8-BBF3-0EBF7E72FBDA}
Class : AudioEndpoint
------------------ Device Descriptor ------------------
bLength : 0x12 (18 bytes)
bDescriptorType : 0x01 (Device Descriptor)
bcdUSB : 0x200 (USB Version 2.00)
bDeviceClass : 0x00 (defined by the interface descriptors)
bDeviceSubClass : 0x00
bDeviceProtocol : 0x00
bMaxPacketSize0 : 0x40 (64 bytes)
idVendor : 0x2AE2
idProduct : 0x1388
bcdDevice : 0x1393
iManufacturer : 0x00 (No String Descriptor)
iProduct : 0x02 (String Descriptor 2)
Language 0x0409 : "My Headset"
iSerialNumber : 0x03 (String Descriptor 3)
Language 0x0409 : "ABCDEF0123456789"
bNumConfigurations : 0x01
Currently I use this code sample to get product string, I open the hub and call DeviceIoControl with IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION to get product string of my device connected to this hub, but this code works from time to time because sometimes hub is opened by someone else and CreateFile(hubPath ..) fails:
// Open Hub
IntPtr handle = CreateFile(hubPath, FileAccess.ReadWrite, FileShare.ReadWrite,
IntPtr.Zero, FileMode.Open, FileAttributes.Normal, IntPtr.Zero);
if (handle.ToInt32() != INVALID_HANDLE_VALUE)
{
// 1. Load connection properties to get Device descriptor indexes
LogWriter.Debug("checking device, load hub connection properties...");
USB_NODE_CONNECTION_INFORMATION_EX connectionInfo = new USB_NODE_CONNECTION_INFORMATION_EX();
connectionInfo.ConnectionIndex = port;
// memset
string NullString = new string((char)0, nBytes / Marshal.SystemDefaultCharSize);
IntPtr connectionInfoBuffer = Marshal.StringToHGlobalAuto(NullString);
Marshal.StructureToPtr(connectionInfo, connectionInfoBuffer, true);
int iProductIndex = -1;
int ioBytes = Marshal.SizeOf(connectionInfo);
int nBytesReturned = 0;
if (DeviceIoControl(handle,
IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX,
connectionInfoBuffer,
ioBytes,
connectionInfoBuffer,
ioBytes,
out nBytesReturned,
IntPtr.Zero) != 0)
{
LogWriter.Debug("checking device, hub connection properties loaded");
USB_NODE_CONNECTION_INFORMATION_EX nodeConnection = (USB_NODE_CONNECTION_INFORMATION_EX)Marshal.PtrToStructure(connectionInfoBuffer, typeof(USB_NODE_CONNECTION_INFORMATION_EX));
if (nodeConnection.DeviceIsHub == 0)
{
iProductIndex = nodeConnection.DeviceDescriptor.iProduct;
LogWriter.Debug(String.Format("GetDeviceProperties() Checking device, iProductIndex = {0}", iProductIndex));
}
}
else
{
CheckError("DeviceIoControl");
}
// 2. Load iProduct descriptor
USB_DESCRIPTOR_REQUEST stringDescReq = new USB_DESCRIPTOR_REQUEST();
int bufSize = Marshal.SizeOf(stringDescReq) + MAXIMUM_USB_STRING_LENGTH;
stringDescReq.ConnectionIndex = port;
stringDescReq.SetupPacket.wValue = (short)((USB_STRING_DESCRIPTOR_TYPE << 8) | iProductIndex);
stringDescReq.SetupPacket.wIndex = 1033; // Language code
stringDescReq.SetupPacket.wLength = (short)(bufSize - Marshal.SizeOf(stringDescReq));
// типа memset
IntPtr ptrRequest = Marshal.StringToHGlobalAuto(NullString);
Marshal.StructureToPtr(stringDescReq, ptrRequest, true);
int nBytesRet = 0;
LogWriter.Debug(String.Format("checking device, load USB descriptor({0}, {1}, {2})",
stringDescReq.SetupPacket.wValue,
stringDescReq.SetupPacket.wIndex,
stringDescReq.SetupPacket.wLength));
if (DeviceIoControl(handle,
IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION,
ptrRequest,
bufSize,
ptrRequest,
bufSize,
out nBytesRet,
IntPtr.Zero) != 0)
{
int ptrSize = ptrRequest.ToInt32();
LogWriter.Debug(String.Format("checking device, USB descriptor loaded({0}, {1})",
ptrSize,
Marshal.SizeOf(stringDescReq)));
IntPtr ptrStringDesc = new IntPtr(ptrSize + Marshal.SizeOf(stringDescReq));
USB_STRING_DESCRIPTOR StringDesc = (USB_STRING_DESCRIPTOR)Marshal.PtrToStructure(ptrStringDesc, typeof(USB_STRING_DESCRIPTOR));
prop.ProductName = StringDesc.bString;
if (prop.ProductName != null)
{
LogWriter.Debug("ProductName = " + prop.ProductName);
}
}
else
{
LogWriter.Warn("DeviceIoControl failed");
CheckError("DeviceIoControl");
}
CloseHandle(handle);
}
So I need other way to get product string that will work stable.
One note: the current device is HID, so using the functions for HID will be allowed, but I have also non-HID USB devices and it would be great if solution can work with HID and non-HID at the same time. I tried HidD_GetProductString routine year ago and as I remember it returned empty buffer (the problem can be the incorrect device path because HID has child devices and in this case the problem is how to get correct device path).