Search code examples
pythonusbbarcodehidevdev

Python, evdev, usb barcode reader: how to decode the input data


I have Datalogic Gryphon GFS4400 2D Barcode-scanner. I have put into Raspberry pi and it works as USB HID device. I can read barcodes and the output goes to default TTY.

I want to create a serivce that handles the output when the barcode is read. I am using python and evdev.

Can someone point me to the right direction how to convert the output to correct characters?

The Python script looks like this:

from evdev import InputDevice, categorize, ecodes

device = InputDevice("/dev/input/by-id/usb-Datalogic_ADC__Inc._Handheld_Barcode_Scanner_S_N_G17A58010-event-kbd") # my keyboard
for event in device.read_loop():
    if event.type == ecodes.EV_KEY:
        print(categorize(event))

When I run the script and read one barcode 487800017702297980000411000000000000702407088651000000, I get the following output:

key event at 1491586389.048072, 69 (KEY_NUMLOCK), down
key event at 1491586389.049084, 69 (KEY_NUMLOCK), up
key event at 1491586389.050085, 56 (KEY_LEFTALT), down
key event at 1491586389.051081, 82 (KEY_KP0), down
key event at 1491586389.052082, 82 (KEY_KP0), up
key event at 1491586389.052082, 76 (KEY_KP5), down
key event at 1491586389.053084, 76 (KEY_KP5), up
key event at 1491586389.053084, 80 (KEY_KP2), down
key event at 1491586389.054079, 80 (KEY_KP2), up
key event at 1491586389.055084, 56 (KEY_LEFTALT), up
key event at 1491586389.056080, 56 (KEY_LEFTALT), down
key event at 1491586389.057088, 82 (KEY_KP0), down
key event at 1491586389.058079, 82 (KEY_KP0), up
key event at 1491586389.058079, 76 (KEY_KP5), down
key event at 1491586389.059087, 76 (KEY_KP5), up
key event at 1491586389.059087, 77 (KEY_KP6), down
key event at 1491586389.060041, 77 (KEY_KP6), up
key event at 1491586389.061046, 56 (KEY_LEFTALT), up
key event at 1491586389.062036, 56 (KEY_LEFTALT), down
key event at 1491586389.063100, 82 (KEY_KP0), down
key event at 1491586389.098114, 56 (KEY_LEFTALT), up
key event at 1491586389.099104, 56 (KEY_LEFTALT), down
key event at 1491586389.100126, 82 (KEY_KP0), down
key event at 1491586389.101125, 82 (KEY_KP0), up
key event at 1491586389.101125, 76 (KEY_KP5), down
key event at 1491586389.102114, 76 (KEY_KP5), up
key event at 1491586389.103118, 76 (KEY_KP5), down
key event at 1491586389.104115, 76 (KEY_KP5), up
key event at 1491586389.105114, 56 (KEY_LEFTALT), up
key event at 1491586389.106111, 56 (KEY_LEFTALT), down
key event at 1491586389.107127, 82 (KEY_KP0), down
key event at 1491586389.108134, 82 (KEY_KP0), up
key event at 1491586389.108134, 76 (KEY_KP5), down
key event at 1491586389.109121, 76 (KEY_KP5), up
key event at 1491586389.128128, 76 (KEY_KP5), up
key event at 1491586389.128128, 82 (KEY_KP0), down
key event at 1491586389.129121, 82 (KEY_KP0), up
key event at 1491586389.130107, 56 (KEY_LEFTALT), up
key event at 1491586389.131113, 56 (KEY_LEFTALT), down
key event at 1491586389.132127, 82 (KEY_KP0), down
key event at 1491586389.133126, 82 (KEY_KP0), up
key event at 1491586389.133126, 76 (KEY_KP5), down
key event at 1491586389.134126, 76 (KEY_KP5), up
key event at 1491586389.134126, 71 (KEY_KP7), down
key event at 1491586389.135125, 71 (KEY_KP7), up
key event at 1491586389.136104, 56 (KEY_LEFTALT), up
key event at 1491586389.137125, 56 (KEY_LEFTALT), down
key event at 1491586389.138119, 82 (KEY_KP0), down
key event at 1491586389.139117, 82 (KEY_KP0), up
key event at 1491586389.139117, 76 (KEY_KP5), down
key event at 1491586389.175126, 82 (KEY_KP0), down
key event at 1491586389.176117, 82 (KEY_KP0), up
key event at 1491586389.176117, 75 (KEY_KP4), down
key event at 1491586389.177134, 75 (KEY_KP4), up
key event at 1491586389.177134, 72 (KEY_KP8), down
key event at 1491586389.178129, 72 (KEY_KP8), up
key event at 1491586389.179136, 56 (KEY_LEFTALT), up
key event at 1491586389.180126, 56 (KEY_LEFTALT), down
key event at 1491586389.181122, 82 (KEY_KP0), down
key event at 1491586389.182130, 82 (KEY_KP0), up
key event at 1491586389.182130, 76 (KEY_KP5), down
key event at 1491586389.183130, 76 (KEY_KP5), up
key event at 1491586389.183130, 80 (KEY_KP2), down
key event at 1491586389.184116, 80 (KEY_KP2), up
key event at 1491586389.185122, 56 (KEY_LEFTALT), up
key event at 1491586389.186116, 56 (KEY_LEFTALT), down
key event at 1491586389.187134, 82 (KEY_KP0), down
key event at 1491586389.188125, 82 (KEY_KP0), up
key event at 1491586389.188125, 75 (KEY_KP4), down
key event at 1491586389.189137, 75 (KEY_KP4), up
key event at 1491586389.189137, 73 (KEY_KP9), down
key event at 1491586389.190129, 73 (KEY_KP9), up
key event at 1491586389.191129, 56 (KEY_LEFTALT), up
key event at 1491586389.192116, 56 (KEY_LEFTALT), down
key event at 1491586389.193122, 82 (KEY_KP0), down
key event at 1491586389.194118, 82 (KEY_KP0), up
key event at 1491586389.194118, 75 (KEY_KP4), down
key event at 1491586389.195127, 75 (KEY_KP4), up
key event at 1491586389.195127, 73 (KEY_KP9), down
key event at 1491586389.248120, 82 (KEY_KP0), up
key event at 1491586389.248120, 75 (KEY_KP4), down
key event at 1491586389.249143, 75 (KEY_KP4), up
key event at 1491586389.249143, 72 (KEY_KP8), down
key event at 1491586389.250109, 72 (KEY_KP8), up
key event at 1491586389.251147, 56 (KEY_LEFTALT), up
key event at 1491586389.252130, 56 (KEY_LEFTALT), down
key event at 1491586389.253137, 82 (KEY_KP0), down
key event at 1491586389.254141, 82 (KEY_KP0), up
key event at 1491586389.254141, 75 (KEY_KP4), down
key event at 1491586389.255155, 75 (KEY_KP4), up
key event at 1491586389.255155, 72 (KEY_KP8), down
key event at 1491586389.256129, 72 (KEY_KP8), up
key event at 1491586389.257119, 56 (KEY_LEFTALT), up
key event at 1491586389.258122, 56 (KEY_LEFTALT), down
key event at 1491586389.259125, 82 (KEY_KP0), down
key event at 1491586389.260129, 82 (KEY_KP0), up
key event at 1491586389.260129, 75 (KEY_KP4), down
key event at 1491586389.261136, 75 (KEY_KP4), up
key event at 1491586389.261136, 72 (KEY_KP8), down
key event at 1491586389.262124, 72 (KEY_KP8), up
key event at 1491586389.263140, 56 (KEY_LEFTALT), up
key event at 1491586389.264135, 56 (KEY_LEFTALT), down
key event at 1491586389.265133, 82 (KEY_KP0), down
key event at 1491586389.266125, 82 (KEY_KP0), up
key event at 1491586389.266125, 75 (KEY_KP4), down
key event at 1491586389.267131, 75 (KEY_KP4), up
key event at 1491586389.267131, 72 (KEY_KP8), down
key event at 1491586389.303143, 76 (KEY_KP5), down
key event at 1491586389.304127, 76 (KEY_KP5), up
key event at 1491586389.305146, 76 (KEY_KP5), down
key event at 1491586389.306139, 76 (KEY_KP5), up
key event at 1491586389.307145, 56 (KEY_LEFTALT), up
key event at 1491586389.308130, 56 (KEY_LEFTALT), down
key event at 1491586389.309137, 82 (KEY_KP0), down
key event at 1491586389.310127, 82 (KEY_KP0), up
key event at 1491586389.310127, 75 (KEY_KP4), down
key event at 1491586389.311131, 75 (KEY_KP4), up
key event at 1491586389.311131, 72 (KEY_KP8), down
key event at 1491586389.312144, 72 (KEY_KP8), up
key event at 1491586389.313135, 56 (KEY_LEFTALT), up
key event at 1491586389.349137, 72 (KEY_KP8), up
key event at 1491586389.350136, 56 (KEY_LEFTALT), up
key event at 1491586389.351123, 56 (KEY_LEFTALT), down
key event at 1491586389.352150, 82 (KEY_KP0), down
key event at 1491586389.370200, 82 (KEY_KP0), down
key event at 1491586389.371148, 82 (KEY_KP0), up
key event at 1491586389.371148, 75 (KEY_KP4), down
key event at 1491586389.372156, 75 (KEY_KP4), up
key event at 1491586389.372156, 72 (KEY_KP8), down
key event at 1491586389.373147, 72 (KEY_KP8), up
key event at 1491586389.374121, 56 (KEY_LEFTALT), up
key event at 1491586389.375140, 56 (KEY_LEFTALT), down
key event at 1491586389.376138, 82 (KEY_KP0), down
key event at 1491586389.377147, 82 (KEY_KP0), up
key event at 1491586389.377147, 75 (KEY_KP4), down
key event at 1491586389.378058, 75 (KEY_KP4), up
key event at 1491586389.378058, 72 (KEY_KP8), down
key event at 1491586389.379141, 72 (KEY_KP8), up
key event at 1491586389.380119, 56 (KEY_LEFTALT), up
key event at 1491586389.381159, 28 (KEY_ENTER), down
key event at 1491586389.382118, 28 (KEY_ENTER), up
key event at 1491586389.384121, 69 (KEY_NUMLOCK), down
key event at 1491586389.385115, 69 (KEY_NUMLOCK), up

I don't understand how to convert the KEY_xxx to correct characters. If I filter only down-events I still don't understand what are KEY_KPn's etc. Evetest gives this:

$ evtest /dev/input/event0
Input driver version is 1.0.1
Input device ID: bus 0x3 vendor 0x5f9 product 0x2216 version 0x110
Input device name: "Datalogic ADC, Inc. Handheld Barcode Scanner"
Supported events:
  Event type 0 (EV_SYN)
  Event type 1 (EV_KEY)
    Event code 1 (KEY_ESC)
    Event code 2 (KEY_1)
    Event code 3 (KEY_2)
    Event code 4 (KEY_3)
    Event code 5 (KEY_4)
    Event code 6 (KEY_5)
    Event code 7 (KEY_6)
    Event code 8 (KEY_7)
    Event code 9 (KEY_8)
    Event code 10 (KEY_9)
    Event code 11 (KEY_0)
    Event code 12 (KEY_MINUS)
    Event code 13 (KEY_EQUAL)
    Event code 14 (KEY_BACKSPACE)
    Event code 15 (KEY_TAB)
    Event code 16 (KEY_Q)
    Event code 17 (KEY_W)
    Event code 18 (KEY_E)
    Event code 19 (KEY_R)
    Event code 20 (KEY_T)
    Event code 21 (KEY_Y)
    Event code 22 (KEY_U)
    Event code 23 (KEY_I)
    Event code 24 (KEY_O)
    Event code 25 (KEY_P)
    Event code 26 (KEY_LEFTBRACE)
    Event code 27 (KEY_RIGHTBRACE)
    Event code 28 (KEY_ENTER)
    Event code 29 (KEY_LEFTCTRL)
    Event code 30 (KEY_A)
    Event code 31 (KEY_S)
    Event code 32 (KEY_D)
    Event code 33 (KEY_F)
    Event code 34 (KEY_G)
    Event code 35 (KEY_H)
    Event code 36 (KEY_J)
    Event code 37 (KEY_K)
    Event code 38 (KEY_L)
    Event code 39 (KEY_SEMICOLON)
    Event code 40 (KEY_APOSTROPHE)
    Event code 41 (KEY_GRAVE)
    Event code 42 (KEY_LEFTSHIFT)
    Event code 43 (KEY_BACKSLASH)
    Event code 44 (KEY_Z)
    Event code 45 (KEY_X)
    Event code 46 (KEY_C)
    Event code 47 (KEY_V)
    Event code 48 (KEY_B)
    Event code 49 (KEY_N)
    Event code 50 (KEY_M)
    Event code 51 (KEY_COMMA)
    Event code 52 (KEY_DOT)
    Event code 53 (KEY_SLASH)
    Event code 54 (KEY_RIGHTSHIFT)
    Event code 55 (KEY_KPASTERISK)
    Event code 56 (KEY_LEFTALT)
    Event code 57 (KEY_SPACE)
    Event code 58 (KEY_CAPSLOCK)
    Event code 59 (KEY_F1)
    Event code 60 (KEY_F2)
    Event code 61 (KEY_F3)
    Event code 62 (KEY_F4)
    Event code 63 (KEY_F5)
    Event code 64 (KEY_F6)
    Event code 65 (KEY_F7)
    Event code 66 (KEY_F8)
    Event code 67 (KEY_F9)
    Event code 68 (KEY_F10)
    Event code 69 (KEY_NUMLOCK)
    Event code 70 (KEY_SCROLLLOCK)
    Event code 71 (KEY_KP7)
    Event code 72 (KEY_KP8)
    Event code 73 (KEY_KP9)
    Event code 74 (KEY_KPMINUS)
    Event code 75 (KEY_KP4)
    Event code 76 (KEY_KP5)
    Event code 77 (KEY_KP6)
    Event code 78 (KEY_KPPLUS)
    Event code 79 (KEY_KP1)
    Event code 80 (KEY_KP2)
    Event code 81 (KEY_KP3)
    Event code 82 (KEY_KP0)
    Event code 83 (KEY_KPDOT)
    Event code 85 (KEY_ZENKAKUHANKAKU)
    Event code 86 (KEY_102ND)
    Event code 87 (KEY_F11)
    Event code 88 (KEY_F12)
    Event code 89 (KEY_RO)
    Event code 90 (KEY_KATAKANA)
    Event code 91 (KEY_HIRAGANA)
    Event code 92 (KEY_HENKAN)
    Event code 93 (KEY_KATAKANAHIRAGANA)
    Event code 94 (KEY_MUHENKAN)
    Event code 95 (KEY_KPJPCOMMA)
    Event code 96 (KEY_KPENTER)
    Event code 97 (KEY_RIGHTCTRL)
    Event code 98 (KEY_KPSLASH)
    Event code 99 (KEY_SYSRQ)
    Event code 100 (KEY_RIGHTALT)
    Event code 102 (KEY_HOME)
    Event code 103 (KEY_UP)
    Event code 104 (KEY_PAGEUP)
    Event code 105 (KEY_LEFT)
    Event code 106 (KEY_RIGHT)
    Event code 107 (KEY_END)
    Event code 108 (KEY_DOWN)
    Event code 109 (KEY_PAGEDOWN)
    Event code 110 (KEY_INSERT)
    Event code 111 (KEY_DELETE)
    Event code 113 (KEY_MUTE)
    Event code 114 (KEY_VOLUMEDOWN)
    Event code 115 (KEY_VOLUMEUP)
    Event code 116 (KEY_POWER)
    Event code 117 (KEY_KPEQUAL)
    Event code 119 (KEY_PAUSE)
    Event code 121 (KEY_KPCOMMA)
    Event code 122 (KEY_HANGUEL)
    Event code 123 (KEY_HANJA)
    Event code 124 (KEY_YEN)
    Event code 125 (KEY_LEFTMETA)
    Event code 126 (KEY_RIGHTMETA)
    Event code 127 (KEY_COMPOSE)
    Event code 128 (KEY_STOP)
    Event code 129 (KEY_AGAIN)
    Event code 130 (KEY_PROPS)
    Event code 131 (KEY_UNDO)
    Event code 132 (KEY_FRONT)
    Event code 133 (KEY_COPY)
    Event code 134 (KEY_OPEN)
    Event code 135 (KEY_PASTE)
    Event code 136 (KEY_FIND)
    Event code 137 (KEY_CUT)
    Event code 138 (KEY_HELP)
    Event code 140 (KEY_CALC)
    Event code 142 (KEY_SLEEP)
    Event code 150 (KEY_WWW)
    Event code 152 (KEY_SCREENLOCK)
    Event code 158 (KEY_BACK)
    Event code 159 (KEY_FORWARD)
    Event code 161 (KEY_EJECTCD)
    Event code 163 (KEY_NEXTSONG)
    Event code 164 (KEY_PLAYPAUSE)
    Event code 165 (KEY_PREVIOUSSONG)
    Event code 166 (KEY_STOPCD)
    Event code 173 (KEY_REFRESH)
    Event code 176 (KEY_EDIT)
    Event code 177 (KEY_SCROLLUP)
    Event code 178 (KEY_SCROLLDOWN)
    Event code 179 (KEY_KPLEFTPAREN)
    Event code 180 (KEY_KPRIGHTPAREN)
    Event code 183 (KEY_F13)
    Event code 184 (KEY_F14)
    Event code 185 (KEY_F15)
    Event code 186 (KEY_F16)
    Event code 187 (KEY_F17)
    Event code 188 (KEY_F18)
    Event code 189 (KEY_F19)
    Event code 190 (KEY_F20)
    Event code 191 (KEY_F21)
    Event code 192 (KEY_F22)
    Event code 193 (KEY_F23)
    Event code 194 (KEY_F24)
    Event code 240 (KEY_UNKNOWN)
  Event type 4 (EV_MSC)
    Event code 4 (MSC_SCAN)
  Event type 17 (EV_LED)
    Event code 0 (LED_NUML)
    Event code 1 (LED_CAPSL)
    Event code 2 (LED_SCROLLL)
    Event code 3 (LED_COMPOSE)
    Event code 4 (LED_KANA)
  Event type 20 (EV_REP)
Properties:
Testing ... (interrupt to exit)

Any help is appreciated! Thank you.


Solution

  • In order to get driverless, USB barcode readers emulate HID devices (keyboards, actually). This has some neat features:

    • it works out of the box,
    • it works in any app,
    • it works in any OS.

    Default behavior for readers is simply to emulate keystrokes. They read the code, decode it, convert it to text, then convert text to key strokes. The only thing your computer sees is USB keyboard scan codes, your OS converts the keystrokes back to text. This has one major drawback: it is dependent on keyboard language mapping settings, so the reader has to know what keymap to use (there is no universal way to send text rather than keys in HID).

    To overcome this issue, some barcodes scanner can (ab)use a feature of Windows input subsystem where user can enter ASCII codes directly. When feature is enabled, reader emulates typing decimal ASCII code number while holding left Alt key. This way, there is no dependency on current keyboard mapping (but this makes another dependency on Windows input layer).

    Here, this is what happens. First, barcode issues a press on NumLock key, to retrieve the current state of Num Lock (it will receive a toggle on Num Lock LED status) to be sure to enable it. Then it issues a series of Alt press + numbers press/release + Alt release. If you decode it, it is: 052, 056, 055, 050, etc. 52 is decimal ASCII code for 4, 56 for 8, 55 for 7, 50 for 2, etc.

    If you change configuration of your reader, you can probably disable this feature to get back to usual input keys using a given keymap. Configuration of barcodes typically goes through scanning of special barcodes found in the manual. Manual for your barcode should be available on the web if you dont have it. Most of the time, configuration codes are interoperable within a given brand.