LibUSB users?

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.

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

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

[code]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
rx_data_buffer = self.usbRead(self.__max_rx_data_length)

    return rx_data_buffer[/code]


[code]def usbRead(self, size): # size_or_buffer
if not self._isopen:
raise IOError(“USB connection is closed.”)
rxBuf =, self.__max_rx_data_length, self.__timeout)

    return rxBuf[/code]

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.

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)


[code]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][/code]


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 …

Endianness of the memoryblock maybe ?

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

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 @Christian Schmitz

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.

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: @Christian Schmitz, what would an endpoint direction of 2 mean? I do only see the values 0 and 128 as constants.

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?

I’m going to give it a try on linux. No luck yet. Perhaps your code will help me along. I wish I could find a project example for the LibUSBDeviceMBS.OpenDevice etc.

I’ll let you know.