[libhid-discuss] reading from a barcode scanner that acts like a
keyboard
Charles Lepple
clepple at ghz.cc
Mon Nov 6 12:26:47 CET 2006
On Nov 5, 2006, at 9:53 PM, Brice Rebsamen wrote:
> $ test_libhid
> parse tree of HIDInterface 002/004[0]:
> path: 0x00010006.0x00000000; type: 0x80
Unfortunately, the HIDParser portion of libhid does not properly dump
descriptors with ranges of Usage codes, hence the zeroes in the last
position. The 0x0001 is the "Generic Desktop Controls" page, and
0x0006 is the Keyboard collection.
> $ lsusb -s 2:4 -vvv
[...]
> Report Descriptor: (length is 65)
> Item(Global): Usage Page, data= [ 0x01 ] 1
> Generic Desktop Controls
> Item(Local ): Usage, data= [ 0x06 ] 6
> Keyboard
> Item(Main ): Collection, data= [ 0x01 ] 1
> Application
> Item(Global): Usage Page, data= [ 0x07 ] 7
> Keyboard
> Item(Local ): Usage Minimum, data= [ 0xe0 ] 224
> Control Left
> Item(Local ): Usage Maximum, data= [ 0xe7 ] 231
> GUI Right
> Item(Global): Logical Minimum, data= [ 0x00 ] 0
> Item(Global): Logical Maximum, data= [ 0x01 ] 1
> Item(Global): Report Size, data= [ 0x01 ] 1
> Item(Global): Report Count, data= [ 0x08 ] 8
> Item(Main ): Input, data= [ 0x02 ] 2
> Data Variable Absolute No_Wrap Linear
> Preferred_State No_Null_Position
> Non_Volatile Bitfield
The preceding portion represents the state of modifier keys ranging
from Control Left to GUI Right (probably the Windows key), and each
modifier key gets a bit. So the first byte you read is probably not
going to change, unless the barcode scanner sends mixed upper- and
lower-case letters or something.
> Item(Global): Report Count, data= [ 0x01 ] 1
> Item(Global): Report Size, data= [ 0x08 ] 8
> Item(Main ): Input, data= [ 0x01 ] 1
> Constant Array Absolute No_Wrap Linear
> Preferred_State No_Null_Position
> Non_Volatile Bitfield
8 bits of padding.
> Item(Global): Report Count, data= [ 0x05 ] 5
> Item(Global): Report Size, data= [ 0x01 ] 1
> Item(Global): Usage Page, data= [ 0x08 ] 8
> LEDs
> Item(Local ): Usage Minimum, data= [ 0x01 ] 1
> NumLock
> Item(Local ): Usage Maximum, data= [ 0x05 ] 5
> Kana
> Item(Main ): Output, data= [ 0x02 ] 2
> Data Variable Absolute No_Wrap Linear
> Preferred_State No_Null_Position
> Non_Volatile Bitfield
5 LEDs that you can set; not sure if these will correspond to actual
LEDs or if they are just emulated so that keyboard drivers feel at
home with this device.
> Item(Global): Report Count, data= [ 0x01 ] 1
> Item(Global): Report Size, data= [ 0x03 ] 3
> Item(Main ): Output, data= [ 0x01 ] 1
> Constant Array Absolute No_Wrap Linear
> Preferred_State No_Null_Position
> Non_Volatile Bitfield
3 bits of padding
> Item(Global): Report Count, data= [ 0x06 ] 6
> Item(Global): Report Size, data= [ 0x08 ] 8
> Item(Global): Logical Minimum, data= [ 0x00 ] 0
> Item(Global): Logical Maximum, data= [ 0xff 0x00 ] 255
> Item(Global): Usage Page, data= [ 0x07 ] 7
> Keyboard
> Item(Local ): Usage Minimum, data= [ 0x00 ] 0
> No Event
> Item(Local ): Usage Maximum, data= [ 0xff 0x00 ] 255
> (null)
> Item(Main ): Input, data= [ 0x00 ] 0
> Data Array Absolute No_Wrap Linear
> Preferred_State No_Null_Position
> Non_Volatile Bitfield
This portion represents which "keys" are down, up to a maximum of six
total.
Usage codes are basically page 0x0007, with the lower bits being the
scan code. So you will need to find a table of PC keyboard scan codes
and map these to ASCII based on the state of the shift bit earlier in
the report.
Have you had a chance to read the HID spec yet? It's not too hard to
read, and it is freely available from the USB Forum web site.
http://www.usb.org/developers/hidpage/ (see the Device Class
Definition, and possibly the HID Usage Tables for the scan code tables)
> Item(Main ): End Collection, data=none
> Endpoint Descriptor:
> bLength 7
> bDescriptorType 5
> bEndpointAddress 0x81 EP 1 IN
> bmAttributes 3
> Transfer Type Interrupt
> Synch Type None
> Usage Type Data
> wMaxPacketSize 0x0008 1x 8 bytes
> bInterval 10
>
bInterval suggests that you poll the device every 10 milliseconds.
Sometimes, you need to send a SET_IDLE request to start the data
flowing:
http://www.ghz.cc/~clepple/libhid/doc/html/
hid__exchange_8c.html#c96f8781c3ce92199eda3d18c98406e3
Then, you can use hid_interrupt_read() to read reports.
Unfortunately, this function does not integrate well with the rest of
libhid, so you will need to calculate byte offsets by hand as I have
done above.
--
Charles Lepple
clepple at ghz.cc
More information about the libhid-discuss
mailing list