50 lines
3.1 KiB
Markdown
50 lines
3.1 KiB
Markdown
It appears the Dymo 400 Twin Turbo does not report the correct device serial number. This prevents us from using more than one of these devices on a system because the device URI is not properly formed.
|
|
|
|
This will possibly need a USB device quirk added to the Linux kernel.
|
|
|
|
An alternative is to possibly implement a fix in dymo-cups-drivers. However, I think the problem occurs higher up the software stack.
|
|
|
|
How to identify the problem
|
|
1. Load wireshark and start recording packets from the master USB bus (bus:0) just prior to connecting the printer
|
|
2. Connect a Dymo 400 Twin Turbo printer to the system with USB
|
|
3. Stop logging USB packets after a minute
|
|
4. Review packet data and notice a packet received from the device has a malformed string
|
|
- The packet will be a GET DESCRIPTOR Response STRING with bLength: 30, bDescriptorType: 0x03 (String), and malformed bString: [malformed]
|
|
5. In terminal, `lsusb -v -d 0922:0018`
|
|
6. Notice the gibberish value in the iSerial field.
|
|
7. When setting up the printer, notice the device URI is `usb://DYMO/LabelWriter%20Twin%20Turbo?serial=??????????????`
|
|
|
|
The problem occurs because the default format for USB device descriptor STRINGs is uint-16-le. However, the Dymo-TT includes an extra byte at the start of the data returned from the device.
|
|
|
|
For example, the serial bString from a Dymo 450 is received as `b'\x31\x00\x37\x00\x31\x00\x30\x00\x30\x00\x36\x00\x31\x00\x36\x00\x31\x00\x38\x00\x34\x00\x32\x00\x33\x00\x30\x00'`.
|
|
However, an example from the Dymo-TT is `b'\x30\x30\x00\x36\x00\x31\x00\x30\x00\x33\x00\x30\x00\x31\x00\x30\x00\x31\x00\x36\x00\x31\x00\x35\x00\x37\x00\x35'`.
|
|
|
|
Decoding the Dymo 450 string using uint-16-le yields "17100616184230", whereas the Dymo-TT string yields `b''`
|
|
|
|
|
|
```python
|
|
# from pyUSB
|
|
import usb.core
|
|
import usb.util
|
|
|
|
vid = 0x0922 # Dymo VID
|
|
pid450 = 0x0020 # Dymo 450 PID
|
|
pidtt = 0x0018 # Dymo Twin Turbo PID
|
|
|
|
dymo450 = usb.core.find(idVendor=vid, idProduct=pid450)
|
|
dymott = usb.core.find(idVendor=vid, idProduct=pidtt)
|
|
|
|
print(f"Dymo 450 Serial: {dymo450.serial_number}") # yields 17100616184230
|
|
print(f"Dymo-Twin-Turbo Serial: {dymott.serial_number}") # yields gibberish
|
|
print(f"Dymo 450 Raw Serial value: {usb.control.get_descriptor(dymo450,254,0x03,dymo450.iSerialNumber,dymo450.langids[0])[2:30].tobytes().decode('utf-16-le')}") # returns 17100616184230
|
|
print(f"Dymo-TT Raw Serial value: {usb.control.get_descriptor(dymott,254,0x03,dymott.iSerialNumber,dymott.langids[0])[2:30].tobytes().decode('utf-16-le')}") # returns gibberish
|
|
print(f"Dymo 450 string result as bytes: {usb.control.get_descriptor(dymo450,254,0x03,dymo450.iSerialNumber,dymo450.langids[0])[2:30].tobytes().decode('utf-16-le').encode('utf-8')}") # returns b'17100616184230'
|
|
print(f"Dymo 450 string result as bytes: {usb.control.get_descriptor(dymott,254,0x03,dymott.iSerialNumber,dymott.langids[0])[2:30].tobytes().decode('utf-16-le').encode('utf-8')}") # returns b'\xe3\x80\xb0\xe3\x98\x80\xe3\x84\x80\xe3\x80\x80\xe3\x8c\x80\xe3\x80\x80\xe3\x84\x80\xe3\x80\x80\xe3\x84\x80\xe3\x98\x80\xe3\x84\x80\xe3\x94\x80\xe3\x9c\x80\xe3\x94\x80'
|
|
|
|
|
|
```
|
|
|
|
References
|
|
|
|
https://www.beyondlogic.org/usbnutshell/usb5.shtml#StringDescriptors
|