jnweiger / led-name-badge-ls32

Upload tool for an led name tag with USB-HID interface
GNU General Public License v2.0
235 stars 88 forks source link

usb.core.USBTimeoutError on Linux (Fedora 38) #41

Open KaeTuuN opened 1 year ago

KaeTuuN commented 1 year ago

I get the following Error Message for every String that is longer than 6 Characters. The workaround from #40 doesn't work.

Note: Had to implement the Workaround from #36 to be able to write to the badge anyway.

sudo python3 ./led-badge-11x44.py "123456789"
using [wch.cn CH546] bus=1 dev=19
Type: 11x44
Traceback (most recent call last):
  File "/home/phil/git/led-name-badge-ls32/./led-badge-11x44.py", line 523, in <module>
    dev.write(2, buf[i*64:i*64+64])
  File "/usr/lib/python3.11/site-packages/usb/core.py", line 989, in write
    return fn(
           ^^^
  File "/usr/lib/python3.11/site-packages/usb/backend/libusb1.py", line 855, in intr_write
    return self.__write(self.lib.libusb_interrupt_transfer,
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/usb/backend/libusb1.py", line 938, in __write
    _check(retval)
  File "/usr/lib/python3.11/site-packages/usb/backend/libusb1.py", line 602, in _check
    raise USBTimeoutError(_strerror(ret), ret, _libusb_errno[ret])
usb.core.USBTimeoutError: [Errno 110] Operation timed out
dirkhillbrecht commented 1 year ago

I faced the same problem on Ubuntu 23.04 with a current hardware revision of the display (purchased August 2023). I was not able to make it operational using the usb.core code path.

I managed, however, to send data reliably to the display through the pyhidapi code path in the script - after fixing it, see my forked branch in https://github.com/dirkhillbrecht/led-name-badge-ls32/tree/fixhidapi . I already issued a pull request here. Note that unfortunately making the pyhidapi access operational on modern Linux seems to be a bit complicated as libraries are not always found.

Hope this helps!

KaeTuuN commented 1 year ago

Sounds like a Maker Faire guest too. :)

I will test your fix tomorrow.

jwich71 commented 1 year ago

I found a solution for me!

I got the same error under Fedora 38 but also https://github.com/dirkhillbrecht/led-name-badge-ls32/tree/fixhidapi did not solve my problem.

I realized that the script was not using pyhidapi at all. I then started the script in debug mode and in the line "pyhidapi.hid_init()" I got the following error:

OSError: /usr/local/lib/libhidapi-libusb.so.0: cannot open shared object file: No such file or directory

I fixed the problem by creating a symlink to my shared object file:

sudo ln -s /usr/lib64/libhidapi-libusb.so.0 /usr/local/lib/libhidapi-libusb.so.0

After that I could use the script without any problems. Note that it now displays the message "via pyHIDAPI" when running.

ngkz commented 1 year ago

I have managed to make it work you need to read from IN endpoint after write a chunk

diff --git a/led-nameplate-11x44-hrkz.py b/led-nameplate-11x44-hrkz.py
index a7ae7f3..4b9d1f2 100644
--- a/led-nameplate-11x44-hrkz.py
+++ b/led-nameplate-11x44-hrkz.py
@@ -17,6 +17,7 @@ except:
   have_pyhidapi = False
   try:
     import usb.core
+    import usb.util
   except:
     print("ERROR: Need the pyhidapi or usb.core module.")
     if sys.platform == "darwin":
@@ -385,6 +386,7 @@ else:
     print("No led tag with vendorID 0x0416 and productID 0x5020 found.")
     print("Connect the led tag and run this tool as root.")
     sys.exit(1)
+  dev.reset()
   try:
     # win32: NotImplementedError: is_kernel_driver_active
     if dev.is_kernel_driver_active(0):
@@ -432,12 +434,33 @@ if len(buf) > 8192:
   print ("Writing more than 8192 bytes damages the display!")
   sys.exit(1)

+cfg = dev.get_active_configuration()
+intf = cfg[(0,0)]
+
+ep_out = usb.util.find_descriptor(
+     intf,
+     # match the first OUT endpoint
+     custom_match = \
+       lambda e:
+           usb.util.endpoint_direction(e.bEndpointAddress) == \
+           usb.util.ENDPOINT_OUT)
+
+ep_in = usb.util.find_descriptor(
+     intf,
+     # match the first IN endpoint
+     custom_match = \
+       lambda e:
+           usb.util.endpoint_direction(e.bEndpointAddress) == \
+           usb.util.ENDPOINT_IN)
+
 if have_pyhidapi:
   pyhidapi.hid_write(dev, buf)
 else:
   for i in range(int(len(buf)/64)):
-    time.sleep(0.1)
-    dev.write(1, buf[i*64:i*64+64])
+    ep_out.write(buf[i*64:i*64+64])
+    ep_in.read(64)

 if have_pyhidapi:
   pyhidapi.hid_close(dev)
+else:
+  usb.util.dispose_resources(dev)
Mnemonic78 commented 6 months ago

I got the same error (after fixing different endpoint address on this device "1 -> 2"), but only on "using wch.cn CH546] bus=1 dev=54" devices. I using Kubuntu 24.04. but I got the same error on the previous Kubuntu version.

Current version of drizzt/led-name-badge-ls32 works for me without any changes to solve my problem. Why this fixes are not included to this origin repository?