winusbnet patch to handle language id


winusbnet throws an exception when reading string descriptors using the WinUsb_GetDescriptor call. Basically, that WinUsb call returns false as it is called with a Language ID of 0, a reserved value.

Patch GetStringDescriptor in WinUSBDevice.cs

The GetStringDescriptor method does not accept a language ID, so we need to patch it to fix that. That change is reproduced below.

public string GetStringDescriptor(byte index, ushort languageID)
{
    byte[] buffer = new byte[256];
    uint transfered;
    bool success = WinUsb_GetDescriptor(_winUsbHandle, USB_STRING_DESCRIPTOR_TYPE,
                index, languageID, buffer, (uint)buffer.Length, out transfered);
    if (!success)
        throw APIException.Win32("Failed to get USB string descriptor ("  + index + ").");
           
    int length = buffer[0] - 2;
    if (length <= 0)
        return null;
    char[] chars = System.Text.Encoding.Unicode.GetChars(buffer, 2, length);
    return new string(chars);
}

Patch GetDeviceDescriptor in USBDevice.cs

Tha patched GetDeviceDescriptor queries the available languages by calling GetStringDescriptor with an index of 0. It then uses the first language ID to recover other string descriptors.

private static USBDeviceDescriptor GetDeviceDescriptor(string devicePath)
{
    try
    {
        USBDeviceDescriptor descriptor;
        using (API.WinUSBDevice wuDevice = new API.WinUSBDevice())
        {
            wuDevice.OpenDevice(devicePath);
            API.USB_DEVICE_DESCRIPTOR deviceDesc = wuDevice.GetDeviceDescriptor();
            string q = wuDevice.GetStringDescriptor(0, 0);
            if (q.Length == 0)
                throw new USBException("Failed to get USB string descriptor (0).");
            // TODO: Using the first language id. Need to improve API.
            ushort langID = q[0];
            string manufacturer = null, product = null, serialNumber = null;
            byte idx = 0;
            idx = deviceDesc.iManufacturer;
            if (idx > 0)
                manufacturer = wuDevice.GetStringDescriptor(idx, langID);

            idx = deviceDesc.iProduct;
            if (idx > 0)
                product = wuDevice.GetStringDescriptor(idx, langID);

            idx = deviceDesc.iSerialNumber;
            if (idx > 0)
                serialNumber = wuDevice.GetStringDescriptor(idx, langID);
            descriptor = new USBDeviceDescriptor(devicePath, deviceDesc, manufacturer, product, serialNumber);
        }
        return descriptor;

    }
    catch (API.APIException e)
    {
        throw new USBException("Failed to retrieve device descriptor.", e);
    }
}

Patch can now be obtained from GitHub.

3 thoughts on “winusbnet patch to handle language id

  1. I think I need this patch. I pulled the source, patched as directed and re-built it. Great. Now for the painful part: I can’t figure out how to get this into my C# app. The Library Package Manager in VS2012 keeps installing the old version (1.0.1.0?). Sorry for such a newb question. I guess I need to do some reading.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s