Why can't I call the PyUSB function dev.read() repeatedly without getting a timeout error?

dimachidy picture dimachidy · Oct 23, 2014 · Viewed 9.5k times · Source

I have a USB connection between a Macbook Air and a microcontroller sensor that streams hex data continuously. I'm trying to use PyUSB in Python to acquire the data. I used PyUSB to connect to microcontroller like so:

import usb 
dev = usb.core.find(idVendor=0xXXXX, idProduct=0xXXXX)
dev.set_configuration()
cfg = dev.get_active_configuration()
intf = cfg[(0,0)]
ep = usb.util.find_descriptor(intf,custom_match = lambda e: usb.util.endpoint_direction(e.bEndpointAddress) == usb.util.ENDPOINT_OUT)

I then tried to read data from the device into an array using the dev.read() method, which worked the first time:

dev.read(0x1,100,100)

This produced an array of length 100, but after I called dev.read(0x1,100,100) several more times (and got several more arrays) I started getting this error:

dev.read(0x1,100,100)

Traceback (most recent call last):

File "stdin", line 1, in <module>

File "/Users/dimachy/anaconda/lib/python2.7/site-packages/usb/core.py", line 918, in read
self.__get_timeout(timeout))

File "/Users/dimachy/anaconda/lib/python2.7/site-packages/usb/backend/libusb1.py", line 777, in bulk_read
timeout)

File "/Users/dimachy/anaconda/lib/python2.7/site-packages/usb/backend/libusb1.py", line 880, in __read
_check(retval)

File "/Users/dimachy/anaconda/lib/python2.7/site-packages/usb/backend/libusb1.py", line 560, in _check
raise USBError(_str_error[ret], ret, _libusb_errno[ret])

usb.core.USBError: [Errno 60] Operation timed out

Why does this happen? I suspect I'm not understanding something about how buffers store data at various places during data transfer, but haven't been able to find a clear explanation of what's going on.

Answer

eh_whatever picture eh_whatever · Oct 23, 2014

What is the length of the response you get back? The way you are structuring dev.read you are telling PyUSB that the response should be 100 bytes long and if you don't get 100 bytes in 100 ms, throw a timeout exception. If your device responds with a smaller message, you will get an error after 100ms is reached, even if that message length is correct. So, you can do 1 of 2 things:

1) remove the timeout variable. In this case PyUSB will wait a default amount of time and the report response without an error. If you need to timeout quicker than the default, this won't help

2)Better yet, if you know the length of the responses you are getting in (sounds like you got some data, so this may be the case), use this value instead of the 100 bytes. This will give you the data back without an error and still allow you to set the timeout variable.