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 suppliers Python code I still dont 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)
[code]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)
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 thats 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 suppliers 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 dont 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))
mDevice.BulkTransfer(Qmini.ReadPipe, result, result.Size, actLength, timeout)
If actLength >= 4 Then
RaiseEvent Error(mdevice.lasterror, "No bytes read")
Lets say I want to read the devices 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:
raise ValueError(“Error code " + str(data_buffer) + " received from device.”)
value = struct.unpack("<i", data_buffer[4:]) # return signed integer _logger.debug("%d received from Command 0x%04x", value, command) return value[/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]  libusb: debug [get_endpoints] interface: 0 pipe 1: dir: 1 number: 2
[1568811376.551716]  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 devices 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.