81 lines
5.0 KiB
Markdown
81 lines
5.0 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: `〰㘀 ㌀ 㘀㔀㜀㔀`
|
|
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 gibberish values.
|
|
|
|
The physical labels found on the Dymo 450 include "1740021750110" and another "1750110". The physical labels on the Dymo-TT are "93085-2053234" and "06440293085". It seems the digital "serial" numbers don't match the physical serial numbers marked. However, the digital serial ID is still unique for each device.
|
|
|
|
A second Dymo-TT connected previously reports `〰㘀 㠀\xe3\x84\x80㈀\xe3\x84\x80㐀㐀㔀㔀㌀㔀㤀` as the device SerialNumber as recorded in the kernel log. It's unknown what the actual binary value should be from this.
|
|
|
|
```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'
|
|
```
|
|
|
|
The Twin-Turbo serial is supposed to be 006103010161575. Due to the extra 0 byte `b'\x30'`, the rest of the return data becomes shifted and is interpreted like
|
|
`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'.decode('utf-16-le')` or literally unicode values `\x3500\x3700\x3500\x3100\x3600\x3100\x3000\x3100\x3000\x3300\x3000\x3100\x3600\x3030`
|
|
|
|
Dymo 450 GET_DEVICE_ID example string:
|
|
```
|
|
'MFG:DYMO;CMD: ;MDL:LabelWriter 450;CLASS:PRINTER;DESCRIPTION:DYMO LabelWriter 450;SERN:01010112345600;'
|
|
```
|
|
|
|
Dymo Twin Turbo GET_DEVICE_ID example string (note the null byte before ERN:):
|
|
```
|
|
'MFG:DYMO;CMD: ;MDL:LabelWriter Twin Turbo;CLASS:PRINTER;DESCRIPTION:DYMO LabelWriter Twin Turbo;\x00ERN:006103010161575'
|
|
```
|
|
|
|
Note: Linux Mint 22.1 <- Ubuntu 24.04 Noble <- Debian Trixie/sid <- Kernel 6.8.0-71-generic; pyusb version 1.3.1; python version 3.12.3
|
|
|
|
References
|
|
|
|
https://www.beyondlogic.org/usbnutshell/usb5.shtml#StringDescriptors
|
|
|
|
https://github.com/pyusb/pyusb/issues/154
|
|
|
|
https://github.com/pyusb/pyusb/blob/master/usb/util.py#L320
|
|
|
|
https://github.com/torvalds/linux/blob/master/drivers/usb/core/quirks.c
|
|
|
|
https://docs.kernel.org/admin-guide/reporting-issues.html
|
|
|
|
https://kernel.org/category/faq.html
|
|
|
|
https://bugzilla.kernel.org/show_bug.cgi?id=220422
|
|
|
|
https://ww1.microchip.com/downloads/aemDocuments/documents/OTH/ProductDocuments/LegacyCollaterals/01233a.pdf
|
|
|