Hacking the Qoder

This project is currently dead. My Qoder has physically died so I can't continue development work, my original source code was lost in a horrible backup/restore fiasco and attempting to connect to a keyboard wedge device in a platform independent way seems to be so difficult as to not be worth the effort. When I finish working on my resume and two other sub projects I've got going, I'll come back and clean up the information on this page since I do have a litte more information available that isn't posted here. Hopefully it'll be of use to someone out there. My Symbol CS 1504 project will probably work much better since it's more robust and has a serial port connection:).

General Qoder Info

The Qoder is a barcode scanner that is small enough to put on your keychain. Unfortunately, the software that comes with it is Windows only... an all too common occurance these days. I'm working on hacking the Qoder to figure out how it works so it can be ported to other platforms. For more information on the Qoder see:

Related Links:

Hack Status

My Qoder died! One night I noticed it was blinking red and green wildly, but I didn't have a cradle handy and pushing the only button available didn't stop it. By the morning, the battery had died. After almost a month, I finally got a replacement back from Qode so I can continue on my development work. :) Unfortunately, I've picked up some new projects since then, so don't hold your breath waiting for me go get back to this particular project.

I FINALLY got JNI working on my machine, but my attempts to use it effectively have failed so far. See Source Code below for more details.

I also got my Cross-Convergence pen. in the mail. An email to their tech support asking about the connection protocol garnered a response about proprietary information, but in a subsequent email they claimed that they want to be as open as possible and the only reason they're not (...yet) is that their SDK is still in progress. I saw the Symbol CyberPen at the CA World the other day and it seems to be exacly the same as the Cross Convergence Pen. Unfortunately, it also seems to have the same design flaw where the barcoder section of the pen cracks at the metal threads and the button can stick down, keeping the device on continually and draining the battery. I also, just got a replacement for the broken pen. I have more confidence that I'll get that working than the Qoder because it uses a nearly conventional serial interface.

Protocol

Since the Qoder sends more than a single bar code and it has to be able to verify that the codes have been received before it erases its' cache, some handshaking is required. Handshaking with a keyboard is, unfortunately, VERY platform dependent. So much for my desire to make a Java driver. For now I have to suffer with the indignity of using qBasic to mess with the Qoder.

Keyboard Control

The handshaking is done using the various modifier and lock keys. On a PC, these can be found at address 0040:0017H. By reading this address, you can find out the status of the keys and by setting this address, the status can be changed. During communication, the Qoder cradle can detect these changes and respond to them. A second keyboard address is available at 0040:0018H, but doesn't seem to be required to operate the Qoder.

Bit Key
0040:0017H 0040:0018H
7 Insert Insert
6 Caps Lock Caps Lock
5 Num Lock Num Lock
4 Scroll Lock Scroll Lock
3 Alt Hold State
2 Ctrl Sys Req
1 Left Shift Left Alt
0 Right Shift Left Ctrl
Coloured column is the address actually used. Pink background shows keys that actually get sent to the Qoder.

Control Sequences

The start of a transaction is signaled by the Qoder cradle with three left-shift presses and a ctrl press. Setting the Num Lock status will prompt the Qoder to respond with, what I think is a status string and a hex representation of how many barcodes are being stored. It is terminated with a carriage return. Setting the Ctrl, Alt and then Num Lock in sequence will prompt the Qoder to disgourge all sorts of information, which appear to be the actual barcodes. I haven't actually decoded all of these yet, but it looks like the data is is mostly numeric and the code separators include some sort of barcode type information. Also, the data is definitely encoded. More to come as I figure it out...

Description Sequence
Ready for Handshake Left Shift, Left Shift, Left Shift, Ctrl
Acknowledge Num Lock
Status info numerical data + Num Lock, (repeated 14x)
number of stored barcodes hex data + Num Lock, (repeated 2x)
Status/barcode count terminator Carriage Return + Num Lock
Ready for Data Ctrl, Ctrl + Alt, Ctrl + Alt + Num Lock
Data (repeated) Start (numeric A) Ctrl + Alt + Left Shift,
j + Ctrl + Alt + Left Shift,
Ctrl + Alt,
Ctrl + Alt + Left Shift,
p + Ctrl + Alt + Left Shift,
Ctrl + Alt
Barcode (numeric A) key code for a digit + Ctrl + Alt,
repeated 14 times
Start (numeric B) Ctrl + Alt + Left Shift,
j + Ctrl + Alt + Left Shift,
Ctrl + Alt,
Ctrl + Alt + Left Shift,
q Ctrl + Alt + Left Shift,
Ctrl + Alt,
9 + Ctrl + Alt,
Ctrl + Alt + Left Shift,
t + Ctrl + Alt + Left Shift,
Ctrl + Alt
Barcode (numeric B) key code for a digit + Ctrl + Alt,
repeated 10 times
Start (Alpha) Ctrl + Alt + Left Shift,
j + Ctrl + Alt + Left Shift,
Ctrl + Alt,
Ctrl + Alt + Left Shift,
d + Ctrl + Alt + Left Shift,
Ctrl + Alt,
Barcode (Alpha) key code for a letter + Ctrl + Alt,
repeated n times *
Start (Unknown) Ctrl + Alt + Left Shift,
j + Ctrl + Alt + Left Shift,
Ctrl + Alt,
Ctrl + Alt + Left Shift,
q + Ctrl + Alt,
Ctrl + Alt,
9 + Ctrl + Alt,
Ctrl + Alt + Left Shift,
w + Ctrl + Alt,
Ctrl + Alt
Barcode (Unknown) Ctrl + Alt + Left Shift,
key code for a letter + Ctrl + Alt + Left Shift,
Ctrl + Alt,
repeated n times
Clear Cache? ????
Acknowledge Cache Cleared? ????
Green background is sent by the Qoder, Pink by the computer.
* There appears to be a limit on the number of digits in the code! The Qoder will read the URL barcode I have on my business card, but it won't store the whole thing.

As you can see, this is fairly tentative. I'm not sure if the intermediate keystrokes are really important. For example, most of the lines where Ctrl + Alt are listed alone. Those are probably just the equivalent of what was left "down" before the next keypress. However, on the "Ready for Data" sequence that the computer has to send to the Qoder, it was very specific about the order of the key presses (ie: setting Ctrl + Alt + Num Lock all at once didn't work. The sequence had to be Ctrl, then Ctrl + Alt, then Ctrl + Alt + Num Lock, exactly.).

Digit Decoding

The digits listed above are encoded in a simple replacement algorithm. For some reason the Qode folks didn't want to have a 0 in a barcode to be stored as a 0. Instead, a 0 is stored as 9 + ctrl + Alt combination.

Qoder Sequence Corresponds to Really Means
Key Modifier
128 44 9 + Ctrl + Alt + Num Lock 0
126 44 7 + Ctrl + Alt + Num Lock 1
124 44 5 + Ctrl + Alt + Num Lock 2
120 44 1 + Ctrl + Alt + Num Lock 3
122 44 3 + Ctrl + Alt + Num Lock 4
129 44 0 + Ctrl + Alt + Num Lock 5
121 44 2 + Ctrl + Alt + Num Lock 6
123 44 4 + Ctrl + Alt + Num Lock 7
125 44 6 + Ctrl + Alt + Num Lock 8
127 44 8 + Ctrl + Alt + Num Lock 9
Note the values of the keycodes are as defined by QBasic. The modifier values are defined in the Keyboard Control table above. Your application may return different codes for the same information.

Alphabetic Decoding

The letters listed above are also encoded in a simple replacement algorithm. Notice how the first four letters of both the upper and lower case alphabets are "qode". I don't know what's up with the "g" and the "k", but I get the same results consistently. I wounldn't mind if these two letters had strange codes, but the fact that they're the same is somewhat disturbing. Perhaps if I try generating the barcodes from a laser printer instead of my ink jet, maybe I'll get better results.

Qoder Sequence Corresponds to Really Means
Key Modifier
46 Ctrl + Alt + Left Shift + Num Lock A
16 46 q + Ctrl + Alt + Left Shift + Num Lock
44 Ctrl + Alt + Num Lock
46 Ctrl + Alt + Left Shift + Num Lock B
24 46 o + Ctrl + Alt + Left Shift + Num Lock
44 Ctrl + Alt + Num Lock
46 Ctrl + Alt + Left Shift + Num Lock C
32 46 d + Ctrl + Alt + Left Shift + Num Lock
44 Ctrl + Alt + Num Lock
46 Ctrl + Alt + Left Shift + Num Lock D
18 46 e + Ctrl + Alt + Left Shift + Num Lock
44 Ctrl + Alt + Num Lock
46 Ctrl + Alt + Left Shift + Num Lock E
25 46 p + Ctrl + Alt + Left Shift + Num Lock
44 Ctrl + Alt
46 Ctrl + Alt + Left Shift + Num Lock F
47 46 v + Ctrl + Alt + Left Shift + Num Lock
44 Ctrl + Alt + Num Lock
46 Ctrl + Alt + Left Shift + Num Lock G
33 46 f + Ctrl + Alt + Left Shift + Num Lock
44 Ctrl + Alt
46 Ctrl + Alt + Left Shift + Num Lock H
17 46 w + Ctrl + Alt + Left Shift + Num Lock
44 Ctrl + Alt
46 Ctrl + Alt + Left Shift + Num Lock I
49 46 n + Ctrl + Alt + Left Shift + Num Lock
44 Ctrl + Alt
46 Ctrl + Alt + Left Shift + Num Lock J
36 46 j + Ctrl + Alt + Left Shift + Num Lock
44 Ctrl + Alt
46 Ctrl + Alt + Left Shift + Num Lock K
21 46 y + Ctrl + Alt + Left Shift + Num Lock
44 Ctrl + Alt
46 Ctrl + Alt + Left Shift + Num Lock L
30 46 a + Ctrl + Alt + Left Shift + Num Lock
44 Ctrl + Alt
46 Ctrl + Alt + Left Shift + Num Lock M
20 46 t + Ctrl + Alt + Left Shift + Num Lock
44 Ctrl + Alt
46 Ctrl + Alt + Left Shift + Num Lock N
38 46 l + Ctrl + Alt + Left Shift + Num Lock
44 Ctrl + Alt
46 Ctrl + Alt + Left Shift + Num Lock O
22 46 u + Ctrl + Alt + Left Shift + Num Lock
44 Ctrl + Alt
46 Ctrl + Alt + Left Shift + Num Lock P
34 46 g + Ctrl + Alt + Left Shift + Num Lock
44 Ctrl + Alt
46 Ctrl + Alt + Left Shift + Num Lock Q
45 46 x + Ctrl + Alt + Left Shift + Num Lock
44 Ctrl + Alt
46 Ctrl + Alt + Left Shift + Num Lock R
44 46 z + Ctrl + Alt + Left Shift + Num Lock
44 Ctrl + Alt
46 Ctrl + Alt + Left Shift + Num Lock S
46 46 c + Ctrl + Alt + Left Shift + Num Lock
44 Ctrl + Alt
46 Ctrl + Alt + Left Shift + Num Lock T
36 46 j + Ctrl + Alt + Left Shift + Num Lock
44 Ctrl + Alt
46 Ctrl + Alt + Left Shift + Num Lock U
19 46 r + Ctrl + Alt + Left Shift + Num Lock
44 Ctrl + Alt
46 Ctrl + Alt + Left Shift + Num Lock V
37 46 k + Ctrl + Alt + Left Shift + Num Lock
44 Ctrl + Alt
46 Ctrl + Alt + Left Shift + Num Lock W
31 46 s + Ctrl + Alt + Left Shift + Num Lock
44 Ctrl + Alt
46 Ctrl + Alt + Left Shift + Num Lock X
50 46 m + Ctrl + Alt + Left Shift + Num Lock
44 Ctrl + Alt
46 Ctrl + Alt + Left Shift + Num Lock Y
48 46 b + Ctrl + Alt + Left Shift + Num Lock
44 Ctrl + Alt
46 Ctrl + Alt + Left Shift + Num Lock Z
23 46 i + Ctrl + Alt + Left Shift + Num Lock
44 Ctrl + Alt
32 44 d + Ctrl + Alt + Num Lock space
16 44 q + Ctrl + Alt + Num Lock a
24 44 o + Ctrl + Alt + Num Lock b
32 44 d + Ctrl + Alt + Num Lock c
18 44 e + Ctrl + Alt + Num Lock d
20 44 t + Ctrl + Alt + Num Lock e
35 44 h + Ctrl + Alt + Num Lock f
46 Ctrl + Alt + Left Shift + Num Lock g
44 Ctrl + Alt + Num Lock
37 44 k + Ctrl + Alt + Num Lock h
31 44 s + Ctrl + Alt + Num Lock i
44 44 z + Ctrl + Alt + Num Lock j
46 Ctrl + Alt + Left Shift + Num Lock k
44 Ctrl + Alt + Num Lock
17 44 w + Ctrl + Alt + Num Lock l
36 44 j + Ctrl + Alt + Num Lock m
48 44 b + Ctrl + Alt + Num Lock n
19 44 r + Ctrl + Alt + Num Lock o
50 44 m + Ctrl + Alt + Num Lock p
45 44 x + Ctrl + Alt + Num Lock q
33 44 f + Ctrl + Alt + Num Lock r
46 44 c + Ctrl + Alt + Num Lock s
22 44 u + Ctrl + Alt + Num Lock t
49 44 n + Ctrl + Alt + Num Lock u
25 44 p + Ctrl + Alt + Num Lock v
30 44 a + Ctrl + Alt + Num Lock w
38 44 l + Ctrl + Alt + Num Lock x
47 44 v + Ctrl + Alt + Num Lock y
34 44 g + Ctrl + Alt + Num Lock z
Note the values of the keycodes are as defined by QBasic. The modifier values are defined in the Keyboard Control table above. Your application may return different codes for the same information.

Source Code

I haven't got anything that I feel comfortable releasing yet.

I did have some success with some code derived from a Java Key Event Demo program in the Java JFC/Swing tutorial under the section on How To Write A Key Listener. Unfortunately, since this is written in Java, it can't set the Num Lock, Ctrl or Alt so it can't be used to interface wtih the Qoder directly. However, it can be used to see what the Qoder is sending to the computer and I have created a simple keyboard reader in Java that does just that.

I'm hoping to create a JNI interface so that Java can be used with the Qoder. It's not an ideal solution because it won't be cross platform. On the other hand, having only a small part of the code that is platform specific should make porting relatively easy.

Recently, I have managed to get JNI working on my machine. There was some difficulty because I was trying to use GCC to compile my code, but IBM's JNI.h file assumes that you're using VisualAge C++. After much frustration with my attempts to get it working with GCC, I borrowed a copy of VisualAge C++ for OS/2. I've gotten several simple JNI app to compile. should be able to create a "POKE" DLL that will allow me to make a real Java Application that can read and control the Qoder.

My current program is written in QBasic. Yeah, I know, yuck! Well, it does the job for now and I haven't figured out how to do it in Rexx or Perl. I know that Perl has an IOCTL function that should be able to do it, but I can't find any decent documentation on how to use it and TERM::ReadKey can only read the keyboard, it can't set it. The Perl documentation does have an example that supposedly works in DOS, but it doesn't work in OS/2. I did find some documentation indicating that OS/2 uses a four term IOCTL function call, so maybe that's the root of the problem. Any help on this topic would be appreciated as I would really like to use anything other than QBasic to do my coding. In particular, help with creating a JNI interface to the keyboard would be ideal.

Other Barcode Related Links

Valid HTML 4.01!

This is a Tomcat-Gentoo powered web server. Thanks for using Apache Tomcat and Gentoo GNU/Linux!

Mark Crocker's Apache Tomcat web server home page link & Gentoo GNU/Linux home page link This page is browser independent
Copyright© 2000-6, Mark Crocker. All rights reserved.
Comments or Suggestions? email: webmaster@markcrocker.com
The Gentoo "g" logo is a trademark of the Gentoo Foundation, Inc. This site is not endorsed by, or affiliated with Gentoo.
This page last updated 2005-Oct-05 01:35 EDT (Wednesday) by Mark Crocker