Communication to USB devices drives me crazy. It's now at least the third USB device creating problems:
- the first device (OWON oscilloscope) had erroneous software and wrong documentation and I couldn't get it to run on another PC.
- the second device (Trinamic stepper motor controller) seemed to be a different type of USB device
- now, Agilent E4980A. The adapted script which worked for the OWON oscilloscope doesn't work for Agilent E4980A.
pyusb
and libusb
are installed and apparently found. My configuration:
Windows 10, Python 3.11.3, libusb-1.0 (v1.0.26.11724), pyUSB (v1.2.1)
Script:
import usb.core
import usb.util
from usb.backend import libusb1
backend = libusb1.get_backend(find_library=lambda x: r'C:\Users\Lab\AppData\Local\Programs\Python\Python311\Lib\site-packages\libusb\_platform\_windows\x64\libusb-1.0.dll')
dev = usb.core.find(idVendor=2391, idProduct=2313, backend=backend) # Agilent E4980A
print(dev)
Output: (well, device is apparently found)
DEVICE ID 0957:0909 on Bus 001 Address 012 =================
bLength : 0x12 (18 bytes)
bDescriptorType : 0x1 Device
bcdUSB : 0x200 USB 2.0
bDeviceClass : 0x0 Specified at interface
bDeviceSubClass : 0x0
bDeviceProtocol : 0x0
bMaxPacketSize0 : 0x40 (64 bytes)
idVendor : 0x0957
idProduct : 0x0909
bcdDevice : 0x100 Device 1.0
iManufacturer : 0x1 Error Accessing String
iProduct : 0x2 Error Accessing String
iSerialNumber : 0x3 Error Accessing String
bNumConfigurations : 0x1
CONFIGURATION 1: 0 mA ====================================
bLength : 0x9 (9 bytes)
bDescriptorType : 0x2 Configuration
wTotalLength : 0x27 (39 bytes)
bNumInterfaces : 0x1
bConfigurationValue : 0x1
iConfiguration : 0x0
bmAttributes : 0xc0 Self Powered
bMaxPower : 0x0 (0 mA)
INTERFACE 0: Application Specific ======================
bLength : 0x9 (9 bytes)
bDescriptorType : 0x4 Interface
bInterfaceNumber : 0x0
bAlternateSetting : 0x0
bNumEndpoints : 0x3
bInterfaceClass : 0xfe Application Specific
bInterfaceSubClass : 0x3
bInterfaceProtocol : 0x1
iInterface : 0x4 Error Accessing String
ENDPOINT 0x2: Bulk OUT ===============================
bLength : 0x7 (7 bytes)
bDescriptorType : 0x5 Endpoint
bEndpointAddress : 0x2 OUT
bmAttributes : 0x2 Bulk
wMaxPacketSize : 0x200 (512 bytes)
bInterval : 0x0
ENDPOINT 0x86: Bulk IN ===============================
bLength : 0x7 (7 bytes)
bDescriptorType : 0x5 Endpoint
bEndpointAddress : 0x86 IN
bmAttributes : 0x2 Bulk
wMaxPacketSize : 0x200 (512 bytes)
bInterval : 0x0
ENDPOINT 0x88: Interrupt IN ==========================
bLength : 0x7 (7 bytes)
bDescriptorType : 0x5 Endpoint
bEndpointAddress : 0x88 IN
bmAttributes : 0x3 Interrupt
wMaxPacketSize : 0x2 (2 bytes)
bInterval : 0x1
However, as soon as I try to send a command (it doesn't matter if with or w/o newline characters \r
or \n
),
cmd = '*IDN?'+'\r'
dev.write(2,cmd)
I will get an error:
Traceback (most recent call last):
File "C:\Users\Lab\AppData\Local\Programs\Python\Python311\Lib\site-packages\usb\core.py", line 236, in get_interface_and_endpoint
return self._ep_info[endpoint_address]
~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^
KeyError: 2
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "C:\Users\Lab\Scripts\tbUSB.py", line 12, in <module>
dev.write(2,'*IDN?'+'\r')
File "C:\Users\Lab\AppData\Local\Programs\Python\Python311\Lib\site-packages\usb\core.py", line 986, in write
intf, ep = self._ctx.setup_request(self, endpoint)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\Lab\AppData\Local\Programs\Python\Python311\Lib\site-packages\usb\core.py", line 113, in wrapper
return f(self, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\Lab\AppData\Local\Programs\Python\Python311\Lib\site-packages\usb\core.py", line 228, in setup_request
intf, ep = self.get_interface_and_endpoint(device, endpoint_address)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\Lab\AppData\Local\Programs\Python\Python311\Lib\site-packages\usb\core.py", line 113, in wrapper
return f(self, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\Lab\AppData\Local\Programs\Python\Python311\Lib\site-packages\usb\core.py", line 238, in get_interface_and_endpoint
for intf in self.get_active_configuration(device):
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\Lab\AppData\Local\Programs\Python\Python311\Lib\site-packages\usb\core.py", line 113, in wrapper
return f(self, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\Lab\AppData\Local\Programs\Python\Python311\Lib\site-packages\usb\core.py", line 249, in get_active_configuration
self.managed_open()
File "C:\Users\Lab\AppData\Local\Programs\Python\Python311\Lib\site-packages\usb\core.py", line 113, in wrapper
return f(self, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\Lab\AppData\Local\Programs\Python\Python311\Lib\site-packages\usb\core.py", line 131, in managed_open
self.handle = self.backend.open_device(self.dev)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\Lab\AppData\Local\Programs\Python\Python311\Lib\site-packages\usb\backend\libusb1.py", line 804, in open_device
return _DeviceHandle(dev)
^^^^^^^^^^^^^^^^^^
File "C:\Users\Lab\AppData\Local\Programs\Python\Python311\Lib\site-packages\usb\backend\libusb1.py", line 652, in __init__
_check(_lib.libusb_open(self.devid, byref(self.handle)))
File "C:\Users\Lab\AppData\Local\Programs\Python\Python311\Lib\site-packages\usb\backend\libusb1.py", line 600, in _check
raise NotImplementedError(_strerror(ret))
NotImplementedError: Operation not supported or unimplemented on this platform
If I do first a set configuration()
as recommended in the PyUSB tutorial, I get the following error:
Traceback (most recent call last):
File "C:\Users\Lab\Scripts\tbUSB.py", line 10, in <module>
dev.set_configuration()
File "C:\Users\Lab\AppData\Local\Programs\Python\Python311\Lib\site-packages\usb\core.py", line 915, in set_configuration
self._ctx.managed_set_configuration(self, configuration)
File "C:\Users\Lab\AppData\Local\Programs\Python\Python311\Lib\site-packages\usb\core.py", line 113, in wrapper
return f(self, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\Lab\AppData\Local\Programs\Python\Python311\Lib\site-packages\usb\core.py", line 158, in managed_set_configuration
self.managed_open()
File "C:\Users\Lab\AppData\Local\Programs\Python\Python311\Lib\site-packages\usb\core.py", line 113, in wrapper
return f(self, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\Lab\AppData\Local\Programs\Python\Python311\Lib\site-packages\usb\core.py", line 131, in managed_open
self.handle = self.backend.open_device(self.dev)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\Lab\AppData\Local\Programs\Python\Python311\Lib\site-packages\usb\backend\libusb1.py", line 804, in open_device
return _DeviceHandle(dev)
^^^^^^^^^^^^^^^^^^
File "C:\Users\Lab\AppData\Local\Programs\Python\Python311\Lib\site-packages\usb\backend\libusb1.py", line 652, in __init__
_check(_lib.libusb_open(self.devid, byref(self.handle)))
File "C:\Users\Lab\AppData\Local\Programs\Python\Python311\Lib\site-packages\usb\backend\libusb1.py", line 600, in _check
raise NotImplementedError(_strerror(ret))
NotImplementedError: Operation not supported or unimplemented on this platform
Similar posts on StackOverflow with the same error message were not helpful:
- Pyusb Read error: NotImplementedError: Operation not supported or unimplemented on this platform
- pyusb: NotImplementedError: Operation not supported or unimplemented on this platform
- PyUSB 1.0: NotImplementedError: Operation not supported or unimplemented on this platform
There is a I/O suite from Keysight/Agilent which seems to work, however, I wanted to avoid the installation of about 266 MB or 1.33 GB on every PC if I could do it with a simple driver of about a few hundred Kilobytes.
I'm also aware that there are other Python libraries (e.g. pyMeasure, even with some code for Agilent E4980A), which I also unsuccessfully tried because of (at least for me) insufficient documentation without minimal working examples. But, I don't want to use these libraries, but simply send some commands and receive some data via PyUSB.
Apparently, the PC can get some information of the device via Python, but I can't write and read anything. Am I missing another driver or something?
Update: (progress?)
In an old post from 2012 in the PyUSB mailing list I read that PyUSB requires special drivers for the device which can be installed via Zadig.
The original driver of the Keysight(Agilent) IO Library Suite Usbtmc (v16.3.17614.0
) was replaced by libusbK (v3.1.0.0).
Now, the Windows Device Manager indicates that the Oscilloscope P1337 and the AgilentE4980A use libusbK
as driver.
As a negative side effect, the KeysightIOLibSuite doesn't work anymore and even not after a re-installation and I don't know to get it back. But well, for me it is more important that it will run with PyUSB.
If I run the following script, the P1337 works fine, but the E4980A always stops with an timeout error.
Script:
import usb.core
import usb.util
from usb.backend import libusb1
backend = libusb1.get_backend(find_library=lambda x: r'C:\Users\User\AppData\Local\Programs\Python\Python311\Lib\site-packages\libusb\_platform\_windows\x64\libusb-1.0.dll')
devs = usb.core.find(find_all=True, backend=backend)
id_e4980a = (0x0957,0x0909) # Agilent E4980A
id_p1337 = (0x5345,0x1234) # OWON/Peaktech P1337
def get_device(devs, id_dev):
dev = None
for x in devs:
# print("idVendor: 0x{:04x}, idProduct: 0x{:04x}, Manufacturer: {}".format(x.idVendor, x.idProduct, x.iManufacturer))
if id_dev == (x.idVendor, x.idProduct): dev = x
return dev
def check_dev(id_dev,ep1,ep2):
dev = get_device(devs, id_dev)
print(dev)
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)
print(ep)
print(dev.write(ep1,'*IDN?'))
print(dev.read(ep2, 100).tobytes().decode('utf-8'))
check_dev(id_p1337,0x3,0x81)
check_dev(id_e4980a,0x2,0x86)
Result: (for P1337, all ok)
DEVICE ID 5345:1234 on Bus 002 Address 003 =================
bLength : 0x12 (18 bytes)
bDescriptorType : 0x1 Device
bcdUSB : 0x200 USB 2.0
bDeviceClass : 0x0 Specified at interface
bDeviceSubClass : 0x0
bDeviceProtocol : 0x0
bMaxPacketSize0 : 0x40 (64 bytes)
idVendor : 0x5345
idProduct : 0x1234
bcdDevice : 0x294 Device 2.94
iManufacturer : 0x1 System CPU
iProduct : 0x2 Oscilloscope
iSerialNumber : 0x3 SERIAL
bNumConfigurations : 0x1
CONFIGURATION 1: 500 mA ==================================
bLength : 0x9 (9 bytes)
bDescriptorType : 0x2 Configuration
wTotalLength : 0x20 (32 bytes)
bNumInterfaces : 0x1
bConfigurationValue : 0x1
iConfiguration : 0x5 Bulk Data Configuration
bmAttributes : 0xc0 Self Powered
bMaxPower : 0xfa (500 mA)
INTERFACE 0: Physical ==================================
bLength : 0x9 (9 bytes)
bDescriptorType : 0x4 Interface
bInterfaceNumber : 0x0
bAlternateSetting : 0x0
bNumEndpoints : 0x2
bInterfaceClass : 0x5 Physical
bInterfaceSubClass : 0x6
bInterfaceProtocol : 0x50
iInterface : 0x4 Bulk Data Interface
ENDPOINT 0x81: Bulk IN ===============================
bLength : 0x7 (7 bytes)
bDescriptorType : 0x5 Endpoint
bEndpointAddress : 0x81 IN
bmAttributes : 0x2 Bulk
wMaxPacketSize : 0x200 (512 bytes)
bInterval : 0x0
ENDPOINT 0x3: Bulk OUT ===============================
bLength : 0x7 (7 bytes)
bDescriptorType : 0x5 Endpoint
bEndpointAddress : 0x3 OUT
bmAttributes : 0x2 Bulk
wMaxPacketSize : 0x200 (512 bytes)
bInterval : 0x0
ENDPOINT 0x3: Bulk OUT ===============================
bLength : 0x7 (7 bytes)
bDescriptorType : 0x5 Endpoint
bEndpointAddress : 0x3 OUT
bmAttributes : 0x2 Bulk
wMaxPacketSize : 0x200 (512 bytes)
bInterval : 0x0
5
,P1337,1842237,V2.4.0->
Result: (for E4980A, timeout error)
DEVICE ID 0957:0909 on Bus 002 Address 007 =================
bLength : 0x12 (18 bytes)
bDescriptorType : 0x1 Device
bcdUSB : 0x200 USB 2.0
bDeviceClass : 0x0 Specified at interface
bDeviceSubClass : 0x0
bDeviceProtocol : 0x0
bMaxPacketSize0 : 0x40 (64 bytes)
idVendor : 0x0957
idProduct : 0x0909
bcdDevice : 0x100 Device 1.0
iManufacturer : 0x1 Agilent Technologies
iProduct : 0x2 E4980A
iSerialNumber : 0x3 MY46203491
bNumConfigurations : 0x1
CONFIGURATION 1: 0 mA ====================================
bLength : 0x9 (9 bytes)
bDescriptorType : 0x2 Configuration
wTotalLength : 0x27 (39 bytes)
bNumInterfaces : 0x1
bConfigurationValue : 0x1
iConfiguration : 0x0
bmAttributes : 0xc0 Self Powered
bMaxPower : 0x0 (0 mA)
INTERFACE 0: Application Specific ======================
bLength : 0x9 (9 bytes)
bDescriptorType : 0x4 Interface
bInterfaceNumber : 0x0
bAlternateSetting : 0x0
bNumEndpoints : 0x3
bInterfaceClass : 0xfe Application Specific
bInterfaceSubClass : 0x3
bInterfaceProtocol : 0x1
iInterface : 0x4 tmc48挸
ENDPOINT 0x2: Bulk OUT ===============================
bLength : 0x7 (7 bytes)
bDescriptorType : 0x5 Endpoint
bEndpointAddress : 0x2 OUT
bmAttributes : 0x2 Bulk
wMaxPacketSize : 0x200 (512 bytes)
bInterval : 0x0
ENDPOINT 0x86: Bulk IN ===============================
bLength : 0x7 (7 bytes)
bDescriptorType : 0x5 Endpoint
bEndpointAddress : 0x86 IN
bmAttributes : 0x2 Bulk
wMaxPacketSize : 0x200 (512 bytes)
bInterval : 0x0
ENDPOINT 0x88: Interrupt IN ==========================
bLength : 0x7 (7 bytes)
bDescriptorType : 0x5 Endpoint
bEndpointAddress : 0x88 IN
bmAttributes : 0x3 Interrupt
wMaxPacketSize : 0x2 (2 bytes)
bInterval : 0x1
ENDPOINT 0x2: Bulk OUT ===============================
bLength : 0x7 (7 bytes)
bDescriptorType : 0x5 Endpoint
bEndpointAddress : 0x2 OUT
bmAttributes : 0x2 Bulk
wMaxPacketSize : 0x200 (512 bytes)
bInterval : 0x0
Error:
Traceback (most recent call last):
File "C:\Users\Lab\Scripts\tbUSB.py", line 31, in <module>
check_dev(id_e4980a,0x2,0x86)
File "C:\Users\Lab\Scripts\tbUSB.py", line 27, in check_dev
print(dev.write(ep1,'*IDN?'))
^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\Lab\AppData\Local\Programs\Python\Python311\Lib\site-packages\usb\core.py", line 989, in write
return fn(
^^^
File "C:\Users\Lab\AppData\Local\Programs\Python\Python311\Lib\site-packages\usb\backend\libusb1.py", line 837, in bulk_write
return self.__write(self.lib.libusb_bulk_transfer,
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\Lab\AppData\Local\Programs\Python\Python311\Lib\site-packages\usb\backend\libusb1.py", line 938, in __write
_check(retval)
File "C:\Users\Lab\AppData\Local\Programs\Python\Python311\Lib\site-packages\usb\backend\libusb1.py", line 602, in _check
raise USBTimeoutError(_strerror(ret), ret, _libusb_errno[ret])
usb.core.USBTimeoutError: [Errno 10060] Operation timed out
So, at least with the libusbK
driver the dev.set_configuration()
doesn't lead to an error, but now there is a timeout error.
Why this? How to solve this? What else is missing?
It's important to understand a few things here...
PyUSB uses libusb which is a way to write user-mode USB device drivers. You correctly identified that there still has to be a kernel-mode driver (e.g. installed by Zadig) but I think maybe you were choosing the wrong one. For my projects I'm using libusb-win32 rather than libusbK.
The we come to another point which is that Zadig replaces the original kernel-mode driver with libusb, which will stop the original software from working. There's not much you can easily do about that: the user-mode and kernel-mode parts need to match.
Finally, way back at the top of your very detailed explaination you appeared to be trying to send an ASCII string to a USB BULK OUT endpoint. Since the Interface descriptor says "Application Specific" there are no guarantees about what format commands might have on this endpoint. It might be serial (with CR, LF etc) or it might not. I'd suggest installing a software sniffer and having a look at what the original software is doing, if you've not done so already.