Configuration of Honeywell Barcode Scanners
enI had recently obtained an used USB barcode scanner: A Honeywell Hyperion 1300G. These scanners can be configured to use one of multiple USB operation modes:
- USB Keyboard mode: The scanner emulates a keyboard and "types" the digits of scanned barcodes.
- USB Serial mode: The scanner emulates a serial console to which it writes scanned barcodes.
- USB HID mode: The scanner shows up as a a USB HID POS device to be used by applications.
For my use case, I needed the scanner to be in USB HID mode, however, when I obtained it, it was configured to USB Keyboard mode. Configuration of barcode scanners is usually done in-band, meaning by scanning special configuration barcodes. In the case of this scanner, these barcodes can be found in the user manual.
Unfortunately it seemed that in-band configuration had been disabled on this scanner, so that it could only be configured via USB. (The in-band configuration is usually disabled for security reasons in scenarios where potential adversaries might attempt to inject unexpected input via barcodes.)
Factory Reset & USB Traffic Logging
There is a Windows-only utility from Honeywell called «EZConfig» that can be used to configure, upgrade and factory-reset barcode scanners. So I set up a Windows VM, installed EZConfig in it and forwarded the host USB device to the VM. This way, the factory reset was only a matter of a few mouse clicks, and this is where this story could have ended.
Could have. However, since I had already set up the Windows VM and config utility, I wanted to see whether I could figure out how the configuration of these scanners actually worked. So I fired up Wireshark, set up USB capture and did another factory reset:
$ sudo modprobe usbmon
$ sudo setfacl -m u:s3lph:r /dev/usbmon*
With this, I was able to obtain a packet capture of the USB traffic between the EZConfig utility and the barcode scanner.
USB Traffic Analysis
From the user manual I knew that an in-band factory reset could be done by scanning the commands DEFOVR
and DEFALT
.
The same was documented to be applicable out-of-band configuration of barcode scanners that are connected via RS232 instead of USB.
So I hoped that the same could be assumed for USB configuration as well.
And indeed, the packet capture contained a USB control transfer packet with the DEFALT
command:
0000 fd 0a 16 4d 0d 44 45 46 41 4c 54 2e 00 00 00 00 |...M.DEFALT.....|
0010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
0020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
0030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
So, let's try to break this down:
fd 0a 16 4d 0d
: This appears to be a header of some sorts. It appears in all outgoing control transfer messages, however the second byte (0a
) is changing with every message. Upon closer inspection, it appears to indicate the length of the payload, starting at the following byte.- The header is followed by the command,
DEFALT.
in this case. The.
indicates termination of the command string. - The rest of the 64 bytes is filled with zeroes.
The respose to this control transfer was read from interrupt endpoint 0x83
and looked fairly similar:
0000 02 08 5d 58 30 44 45 46 41 4c 54 06 2e 00 00 00 |..]X0DEFALT.....|
0010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
0020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
0030 00 00 00 00 00 00 00 00 00 00 00 00 00 3f 00 00 |.............?..|
Here I could make a lot more sense from the headers, as the response appears to be similar to a USB HID «Scanned Data Report», which is emitted by USB HID POS barcode scanners when they scanned a barcode, and which is fairly well defined in the USB HID standard:
02
again appears to be some kind of header.08
is the length of the barcode's payload.]X0
is an AIM ID, which indicates which type of barcode was scanned;]X0
corresponds to Code 39.DEFALT
is the command that was executed.06
(ASCIIACK
) is the status report for this command, in this case a successful response..
again terminates the message, and the rest is filled with zeroes.- There is a
?
character at position 0x3d`. I couldn't figure out its purpose, and it seems to be there in every single response.
A few more things I learned from analyzing the packet dump:
- The entire chapter Serial Programming Commands of the manual is applicable via USB as well, especially:
- The documented concatenation of multiple commands with semicolons (e.g.
DEFOVR;DEFALT.
) is supported via USB as well. - The status code in the response is indicated through ASCII control characters
ACK
(0x06
),NAK
(0x15
) andENQ
(0x05
). - EZConfig uses some undocumented configuration commands.
For example, it uses the
P_INFO.
command to retrieve detailed information such as software version numbers from the scanner.
Writing a Configuration Utility
With the things I had learned, I decided to attempt to write my own small configuration utility for these scanners. Since I had never worked with USB before, I approached this as a learning opportunity to gain a deeper understanding of the USB protocol.
However, the main challenge turned out to not be learning USB, but to make the config tool work independently from the device's configuration. Depending on the operation mode the barcode scanner was in, it presented itself differently to the host.
Here is an example in USB HID POS mode:
0c2e:0b07 Metrologic Instruments 1300 Linear Imager
- configuration 0: Default
- interface 0
- altsetting 0: interface=0, desc=HID POS class=3 subclass=0 protocol=0
- endpoint 81: type=interrupt
- interface 1
- altsetting 0: interface=1, desc=REM class=3 subclass=0 protocol=0
- endpoint 83: type=interrupt
Here is the same device, but in PC Keyboard mode:
0c2e:0b01 Metrologic Instruments 1300 Linear Imager
- configuration 0: Default
- interface 0
- altsetting 0: interface=0, desc=HID Keyboard Emulation class=3 subclass=1 protocol=1
- endpoint 87: type=interrupt
- interface 1
- altsetting 0: interface=1, desc=REM class=3 subclass=0 protocol=0
- endpoint 81: type=interrupt
There's two relevant differences in here:
- The USB product ID changes depending on the configuration. In HID POS mode, it is
0b07
, in PC Keyboard mode, it is0b01
. - The USB endpoint addresses change as well; in HID POS mode, endpoint
0x81
is the HID POS endpoint, and0x83
is the configuration endpoint. In keyboard mode, endpoint0x81
(the same address that was the HID POS endpoint before) becomes the configuration endpoint, whereas the keyboard endpoint is0x87
.
I solved the first issue by hard-coding all vendor and product IDs I had encountered with this device, and having the config tool try all known combinations until a device is found. In a future version I may choose to enumerate all devices on the USB bus and probe all of them for the configuration endpoint.
And this is where the second issue comes in:
How to reliably identify the configuration endpoint if its address changes depending on the device's configuration?
As it turned out, the description of the interface with this endpoint always was REM
(after some digging, I assume this is an abbreviation for Honeywell's «Remote MasterMind» application), and only ever has a single endpoint.
Through this description, I was able to correctly identify the configuration endpoint in all device configurations that I was able to try.
With these issues resolved, my configuration tool was now finally working reliably. With this tool, a factory reset (what I had originally set out to perform), as as easy as this:
$ honeywell-config DEFOVR DEFALT
DEFOVR.
DEFALT.
Apart from applying configuration, the tool can also be used to backup and restore the configuration of a barcode scanner:
$ honeywell-config -c -o backup.conf
$ honeywell-config -i backup.conf
The tool and instructions for compilation and usage can be found here.