LibUSB users?

  1. last week

    Ulrich B

    Sep 9 Pre-Release Testers, Xojo Pro Europe (Germany, Berlin) · xo...

    Anyone here who uses LibUSB(MBS) successfully? I am stuck with a device that somehow seems to return the same data for each property, or none at all. After hours of reading into USB basics and deciphering the supplier’s Python code I still don’t have a clue what I am doing incorrectly.

  2. Derk J

    Sep 9 Pre-Release Testers, Xojo Pro

    Have you tried the examples of MBS?
    USB can be a pita but it should work if the device is configured right.

  3. Ulrich B

    Sep 9 Pre-Release Testers, Xojo Pro Europe (Germany, Berlin) · xo...
    Edited last week

    Thank you, Derk.
    As I wrote, this device comes with a Python example, and the base communication is built around

    def __send_receive_data(self, tx_data, length):
            """In principal this method is an abstraction of the 'transport layer'.
            tx_data and rx_data_buffer can be the same."""
            if not self._isopen:
                raise IOError("Device connection is closed.")
            # ToDo: later support also other serial interfaces
            self.usbWrite(tx_data)
            rx_data_buffer = self.usbRead(self.__max_rx_data_length)
    
            return rx_data_buffer

    with

    def usbRead(self, size): # size_or_buffer
            if not self._isopen:
                raise IOError("USB connection is closed.")
            rxBuf = self.dev.read(self.__readPipe, self.__max_rx_data_length, self.__timeout)
    
            return rxBuf

    and usbWrite the same for the writePipe.
    readPipe is &h81 and WritePipe is &h01.

    I rebuilt this code with libusbMBS.BulkTransfer, and it is working. If I just use it to send an init or SystemReset (a UInt32 that’s encoded bitwisely), the device is responding like it should. If I use it to read a property, ReadPipe returns 4 Bytes. But the memory block stays empty.

    I tried a controlTransfer, but I am really unsure how to translate the supplier’s documentation to that format. Anyway, I made it to return a value, but no matter what data I send to the device, it returns exactly the same data.

    Do you have any working example whose USB handling you could share? Maybe that helps to figure out why I don’t get the results I want.

  4. Ulrich B

    Sep 10 Pre-Release Testers, Xojo Pro Europe (Germany, Berlin) · xo...
    Edited last week

    Addition, to clarify what I use as an equivalent for send_receive_data:

    Protected Function BulkReadWrite(data as MemoryBlock, timeout as integer = 500) as MemoryBlock
      If mDevice <> Nil Then
        Dim actLength As Integer
        Dim Result As New MemoryBlock(qmini.MaxDataLength)
        mDevice.BulkTransfer(Qmini.WritePipe, data, data.Size, actLength, timeout)
        If actLength <> data.Size Then
          RaiseEvent Error(mdevice.lasterror, str(actlength) + " Bytes sent instead of " + str(data.Size))
        End If
        mDevice.BulkTransfer(Qmini.ReadPipe, result, result.Size, actLength, timeout)
        If actLength >= 4 Then
          Return result
        Else
          RaiseEvent Error(mdevice.lasterror, "No bytes read")
        End If
      End If 
    End Function

    Let’s say I want to read the device’s software version property. Python code is

    versioncode = self.__read_integer(_CommandCodes.GetSoftwareVersion)

    with

    def __read_integer(self, command):
            data_buffer = struct.pack("<I", command)
            data_buffer = self.__send_receive_data(data_buffer, 4)
            if len(data_buffer) < 4:
                raise IOError("Only " + str(len(data_buffer)) + " bytes received.")
            if data_buffer[0] != 0:
                raise ValueError("Error code " + str(data_buffer[0]) + " received from device.")
    
            value = struct.unpack("<i", data_buffer[4:]) # return signed integer
            _logger.debug("%d received from Command 0x%04x", value[0], command)
            return value[0]

    and

    GetSoftwareVersion = _Cmd.DeviceProperty | _Cmd.Get | _Cmd.SoftwareVersion,
            DeviceProperty = 0x2000,
            Get = 0x000,
            SoftwareVersion = 0x05,

    So I am sending a Memoryblock with &h0000 2005 to the device with BulkTransfer, addressing the Write Pipe.
    It returns 4 bytes sent successfully, and the ReadPipe returns an ActLength of 4 bytes too when I now read the data.
    Which are all 00, meaning success. By the Python code I should read the following 4 bytes now and return the Int32 value, but this value is completely random and does not reflect any meaningful value.

    Do you see what I might be doing wrong? Everything looks very ok, except for the values …

  5. Norman P

    Sep 10 Pre-Release Testers, Xojo Pro great-white-software.com/blog

    Endianness of the memoryblock maybe ?

  6. Ulrich B

    Sep 10 Pre-Release Testers, Xojo Pro Europe (Germany, Berlin) · xo...

    @Norman P Endianness of the memoryblock maybe ?

    Changing it creates the same result. Which is very weird – I would suspect a device error.

  7. Derk J

    Sep 10 Pre-Release Testers, Xojo Pro

    I suspect you need to read some fixed length and as norman suggests you should know the endianess.

    For now it may be better to ask @ChristianSchmitz

  8. Christian S

    Sep 10 Pre-Release Testers, Xojo Pro, XDC Speakers, Third Party Store Germany

    I have not much to comment.
    If it works in Python, maybe you can compare the bytes, e.g. output in python as hex string.

  9. yesterday

    Ulrich B

    yesterday Pre-Release Testers, Xojo Pro Europe (Germany, Berlin) · xo...
    Edited yesterday

    I fail in getting Python to work. But I made some success. Still I wonder if libusbMBS is giving me the right information.
    With two devices I tested, both endpoints I could find in the Active Config Description are always exactly the same, including the direction and their address. This cannot be right, can it?

    libusb itself is giving me different endpoints when I set it to full debug mode:

    [1568811376.551711] [00000307] libusb: debug [get_endpoints] interface: 0 pipe 1: dir: 1 number: 2
    [1568811376.551716] [00000307] libusb: debug [get_endpoints] interface: 0 pipe 2: dir: 0 number: 2

    libusbMBS says both endpoints are at address 2, with a direction of 2 – they are both identical.

    ADDITION: @ChristianSchmitz, what would an endpoint direction of 2 mean? I do only see the values 0 and 128 as constants.

  10. Ulrich B

    yesterday Pre-Release Testers, Xojo Pro Europe (Germany, Berlin) · xo...

    And another addition: In a desperate attempt to find a solution, I used MacUSBMBS instead of libusbMBS.

    When I send the device code for the firmware revision with WritePacket to Pipe 2, I can successfully perform a ReadRaw on Pipe 1 and get the string as described in the device’s documentation.
    Trying to address pipe 1 with libUSBMBS results in an error.

    Can anyone of you read data successfully with LibusbMBS?

or Sign Up to reply!