Author Topic: Communication with multiple WinUSB devices.  (Read 35115 times)

lcpoon

  • Frequent Contributor
  • ****
  • Posts: 58
Communication with multiple WinUSB devices.
« on: July 19, 2012, 01:03:02 am »
I have more than two WinUSB devices connected to the PC where each has dedicated serial number. What is the function used to communicate with dedicated device at one time?

Jan Axelson

  • Administrator
  • Frequent Contributor
  • *****
  • Posts: 3033
    • Lakeview Research
Re: Communication with multiple WinUSB devices.
« Reply #1 on: July 19, 2012, 10:28:21 am »

lcpoon

  • Frequent Contributor
  • ****
  • Posts: 58
Re: Communication with multiple WinUSB devices.
« Reply #2 on: July 24, 2012, 01:23:22 am »
Hi,

From FindDeviceFromGuid function:

                        'Call SetupDiGetDeviceInterfaceDetail again.
                        'This time, pass a pointer to DetailDataBuffer
                        'and the returned required buffer size.

                        success = SetupDiGetDeviceInterfaceDetail _
                         (deviceInfoSet, _
                         myDeviceInterfaceData, _
                         detailDataBuffer, _
                         bufferSize, _
                         bufferSize, _
                         IntPtr.Zero)

                        'Skip over cbsize (4 bytes) to get the address of the devicePathName.

                        pdevicePathName = New IntPtr(detailDataBuffer.ToInt32 + 4)

                        'Get the String containing the devicePathName.

                        devicePathName = Marshal.PtrToStringAuto(pdevicePathName)

devicePathName = "\\?\usb#vid_0957&pid_a118#my87654321#{400b501e-5a37-472d-b4a7-998bf4e9a7cd}"

I am using this to detect the device s/n to communicate with.

If I am using Microsoft USB device viewer to check the USB information, I can iManufacturer, iProduct and iSerialNumber. What is the WinUSB function used to read the iProduct info?

Jan Axelson

  • Administrator
  • Frequent Contributor
  • *****
  • Posts: 3033
    • Lakeview Research
Re: Communication with multiple WinUSB devices.
« Reply #3 on: July 24, 2012, 09:18:20 am »
Use WinUsb_ControlTransfer to request the device descriptor.

Jan

lcpoon

  • Frequent Contributor
  • ****
  • Posts: 58
Re: Communication with multiple WinUSB devices.
« Reply #4 on: July 26, 2012, 03:08:01 am »
Can you show me how to add WinUsb_ControlTransfer codes into FindDeviceFromGuid in order to retrieve the device descriptor info?

Jan Axelson

  • Administrator
  • Frequent Contributor
  • *****
  • Posts: 3033
    • Lakeview Research

lcpoon

  • Frequent Contributor
  • ****
  • Posts: 58
Re: Communication with multiple WinUSB devices.
« Reply #6 on: August 10, 2012, 06:52:20 am »
I still not manage to read the USB product name using WinUSB API, hope you can help.

Jan Axelson

  • Administrator
  • Frequent Contributor
  • *****
  • Posts: 3033
    • Lakeview Research
Re: Communication with multiple WinUSB devices.
« Reply #7 on: August 10, 2012, 02:50:20 pm »
Post a code excerpt of what you've tried.

lcpoon

  • Frequent Contributor
  • ****
  • Posts: 58
Re: Communication with multiple WinUSB devices.
« Reply #8 on: August 16, 2012, 10:47:08 pm »
   I added in these codes to     
 
<DllImport("winusb.dll", SetLastError:=True)> Friend Shared Function WinUsb_GetDescriptor _
         (ByVal InterfaceHandle As IntPtr, _
         ByVal DescriptorType As Byte, _
         ByVal Index As Byte, _
         ByVal LanguageID As UShort, _
         ByVal bufferptr As IntPtr, _
         ByVal BufferLength As Integer, _
         ByRef DescriptorLengthptr As Integer) _
         As Boolean
        End Function

lcpoon

  • Frequent Contributor
  • ****
  • Posts: 58
Re: Communication with multiple WinUSB devices.
« Reply #9 on: August 16, 2012, 10:47:58 pm »
I am not familiar with WinUSB and do not know how to proceed then.

lcpoon

  • Frequent Contributor
  • ****
  • Posts: 58
Re: Communication with multiple WinUSB devices.
« Reply #10 on: August 17, 2012, 01:42:11 am »
I added this to the WinUsbDeviceApi too:
        Friend Structure USB_DEVICE_DESCRIPTOR
            Friend bLength As Byte
            Friend bDescriptorType As Byte
            Friend bcdUSB As UInt16
            Friend bDeviceClass As Byte
            Friend bDeviceSubClass As Byte
            Friend bDeviceProtocol As Byte
            Friend bMaxPacketSize0 As Byte
            Friend idVendor As UInt16
            Friend idProduct As UInt16
            Friend bcdDevice As UInt16
            Friend iManufacturer As Byte
            Friend iProduct As Byte
            Friend iSerialNumber As Byte
            Friend bNumConfigurations As Byte
        End Structure

I added in some lines after SetupDiGetDeviceInterfaceDetail to see if I managed to run WinUsb_GetDescriptor. However, WinUsbDevice.WinUsb_GetDescriptor returns false.

                        'Skip over cbsize (4 bytes) to get the address of the devicePathName.

                        pdevicePathName = New IntPtr(detailDataBuffer.ToInt32 + 4)

                        'Get the String containing the devicePathName.

                        DevicePathName = Marshal.PtrToStringAuto(pdevicePathName)

                        'Free the memory allocated previously by AllocHGlobal.

                        Marshal.FreeHGlobal(detailDataBuffer)
                        deviceFound = True

                        Dim mydevicedescriptor As New WinUsbDevice.USB_DEVICE_DESCRIPTOR
                        Dim ReadDescriptorLength As Integer
                        Dim DescriptorBufferSize As Integer = Marshal.SizeOf(mydevicedescriptor)
                        Dim bufferptr As IntPtr = Marshal.AllocHGlobal(DescriptorBufferSize)
                        Dim myWinUsbDevice As New WinUsbDevice()
                        Marshal.AllocHGlobal(Marshal.SizeOf(mydevicedescriptor))
                        success = WinUsbDevice.WinUsb_GetDescriptor(pdevicePathName, _
                                                       Convert.ToByte(1), _
                                                       Convert.ToByte(0), _
                                                       Convert.ToUInt16(&H409), _
                                                       bufferptr, _
                                                       DescriptorBufferSize, _
                                                       ReadDescriptorLength)
                        mydevicedescriptor = CType(Marshal.PtrToStructure(bufferptr, GetType(WinUsbDevice.USB_DEVICE_DESCRIPTOR)), WinUsbDevice.USB_DEVICE_DESCRIPTOR)
                        Marshal.FreeHGlobal(bufferptr)

Jan Axelson

  • Administrator
  • Frequent Contributor
  • *****
  • Posts: 3033
    • Lakeview Research
Re: Communication with multiple WinUSB devices.
« Reply #11 on: August 17, 2012, 08:52:51 pm »

lcpoon

  • Frequent Contributor
  • ****
  • Posts: 58
Re: Communication with multiple WinUSB devices.
« Reply #12 on: August 23, 2012, 09:50:47 pm »
I tried to leverage the C# codes from the given link to VB.net but not working.

I added in these codes into WinUsbDeviceApi.vb:

        Structure USB_DEVICE_DESCRIPTOR
            Public bLength As Byte
            Public bDescriptorType As Byte
            Public bcdUSB As UShort
            Public bDeviceClass As Byte
            Public bDeviceSubClass As Byte
            Public bDeviceProtocol As Byte
            Public bMaxPacketSize0 As Byte
            Public idVendor As UShort
            Public idProduct As UShort
            Public bcdDevice As UShort
            Public iManufacturer As Byte
            Public iProduct As Byte
            Public iSerialNumber As Byte
            Public bNumConfigurations As Byte
        End Structure

        <DllImport("winusb.dll", SetLastError:=True)> Private Shared Function WinUsb_GetDescriptor _
        (ByVal InterfaceHandle As IntPtr, _
         ByVal DescriptorType As Byte, _
         ByVal Index As Byte, _
         ByVal LanguageID As Byte, _
         ByRef deviceDesc As USB_DEVICE_DESCRIPTOR, _
         ByVal BufferLength As UInt32, _
         ByRef LengthTransfered As UInt32) _
         As Boolean
        End Function

I added these codes into WinUsbDevice.vb

VB.net does not allow me to convert buffer to USB_DEVICE_DESCRIPTOR, how to solve this?
Error      1              Value of type '1-dimensional array of Byte' cannot be converted to 'WinUsbDemo.WinUsbDemo.WinUsbDevice.USB_DEVICE_DESCRIPTOR'.             D:\Visual Basic Stuffs\VB 2008\U7227 - WinUSB\WinUsbDevice.vb          619



        Private Function GetDeviceDescriptor() As USB_DEVICE_DESCRIPTOR
            Dim deviceDesc As USB_DEVICE_DESCRIPTOR
            Dim transfered As UInteger
            Dim size As UInteger = CUInt(Marshal.SizeOf(GetType(USB_DEVICE_DESCRIPTOR)))
            Dim success As Boolean = WinUsb_GetDescriptor(myDevInfo.winUsbHandle, 1, 0, 0, deviceDesc, size, transfered)
            Return deviceDesc
        End Function

        Public Function GetStringDescriptor(ByVal index As Byte) As String
            Dim buffer As Byte() = New Byte(255) {}
            Dim transfered As UInteger
            Dim success As Boolean = WinUsb_GetDescriptor(myDevInfo.winUsbHandle, 1, index, 0, buffer, CUInt(buffer.Length), transfered)

            Dim length As Integer = buffer(0) - 2
            If length <= 0 Then
                Return Nothing
            End If
            Dim chars As Char() = System.Text.Encoding.Unicode.GetChars(buffer, 2, length)
            Return New String(chars)
        End Function


lcpoon

  • Frequent Contributor
  • ****
  • Posts: 58
Re: Communication with multiple WinUSB devices.
« Reply #13 on: August 23, 2012, 10:32:05 pm »
I fixed the VB error by adding in 2 more WinUsb_GetDescriptor functions.

        <DllImport("winusb.dll", SetLastError:=True)> Private Shared Function WinUsb_GetDescriptor _
        (ByVal InterfaceHandle As IntPtr, _
        ByVal DescriptorType As Byte, _
        ByVal Index As Byte, _
        ByVal LanguageID As Byte, _
        ByVal Buffer As Byte(), _
        ByVal BufferLength As UInt32, _
        ByRef LengthTransfered As UInt32) _
        As Boolean
        End Function

        <DllImport("winusb.dll", SetLastError:=True)> Private Shared Function WinUsb_GetDescriptor _
        (ByVal InterfaceHandle As IntPtr, _
         ByVal DescriptorType As Byte, _
         ByVal Index As Byte, _
         ByVal LanguageID As Byte, _
         ByRef deviceDesc As USB_DEVICE_DESCRIPTOR, _
         ByVal BufferLength As UInt32, _
         ByRef LengthTransfered As UInt32) _
         As Boolean
        End Function

        <DllImport("winusb.dll", SetLastError:=True)> Private Shared Function WinUsb_GetDescriptor _
        (ByVal InterfaceHandle As IntPtr, _
         ByVal DescriptorType As Byte, _
         ByVal Index As Byte, _
         ByVal LanguageID As Byte, _
         ByRef deviceDesc As USB_CONFIGURATION_DESCRIPTOR, _
         ByVal BufferLength As UInt32, _
         ByRef LengthTransfered As UInt32) _
         As Boolean
        End Function

Now, I need to leverage the subroutine below to the VB codes.

        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);
                    // TODO: use language id properly
                    string manufacturer = null, product = null, serialNumber = null;
                    byte idx = 0;
                    idx = deviceDesc.iManufacturer;
                    if (idx > 0)
                        manufacturer = wuDevice.GetStringDescriptor(idx);

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

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

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

Jan Axelson

  • Administrator
  • Frequent Contributor
  • *****
  • Posts: 3033
    • Lakeview Research
Re: Communication with multiple WinUSB devices.
« Reply #14 on: August 27, 2012, 09:38:49 pm »
Here is what http://www.carlosag.net/Tools/CodeTranslator gives:


 
Code: [Select]
   Private Shared Function GetDeviceDescriptor(ByVal devicePath As String) As USBDeviceDescriptor
        Try
            Dim descriptor As USBDeviceDescriptor
            Dim wuDevice As API.WinUSBDevice = New API.WinUSBDevice
            wuDevice.OpenDevice(devicePath)
            Dim deviceDesc As API.USB_DEVICE_DESCRIPTOR = wuDevice.GetDeviceDescriptor
            ' string q = wuDevice.GetStringDescriptor(0);
            ' TODO: use language id properly
            Dim serialNumber As String = Nothing
            Dim manufacturer As String = Nothing
            Dim product As String = Nothing
            Dim idx As Byte = 0
            idx = deviceDesc.iManufacturer
            If (idx > 0) Then
                manufacturer = wuDevice.GetStringDescriptor(idx)
            End If
            idx = deviceDesc.iProduct
            If (idx > 0) Then
                product = wuDevice.GetStringDescriptor(idx)
            End If
            idx = deviceDesc.iSerialNumber
            If (idx > 0) Then
                serialNumber = wuDevice.GetStringDescriptor(idx)
            End If
            descriptor = New USBDeviceDescriptor(devicePath, deviceDesc, manufacturer, product, serialNumber)
            Return descriptor
        Catch e As API.APIException
            Throw New USBException("Failed to retrieve device descriptor.", e)
        End Try
    End Function