Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C++

ITCKeyboard: A Class to Manage ITC Keyboard Mappings

0.00/5 (No votes)
8 Nov 2010CPOL2 min read 10.1K  
A class to manage remapping of USB and direct keys on intermec mobile computers

Although Intermec provides a control panel and an API to remap keys for Intermec Mobile Computers, these tools only support normal remappings. This means, for example, you can remap a hardware key to produce a virtual key code. But you cannot map a key to the other great possibilities of the keyboard driver:

  • Switch the keyboard plane (shiftkey)
  • Map as modifier key
  • Map as rotate key (one that produces abc depending on how often you press it)
  • Multikey that produces a sequence of key strokes
  • Event key, one that fires a named event pair (like the scan button does)
  • A function key that executes a function inside a DLL

I also added classes to manage the used tables as for example MultiKeys, ShiftKeys, RotateKeys, ModifierKeys, and so on.

This is an example on how the USB codes are laid out on a device. Unfortunately, I only have mappings of this device and not for the others. Therefore, you can only suggest the key to remap by the printing on the key.

There is no support in the Intermec tools to remap directKeys. For example, the side buttons of a CN3 or CN4 or the PTT button of the CK3 are not managed via the USB keyboard driver, these are managed by a direct keyboard driver. ITCKEYBOARD enables you to remap these keys through an API.

The ITCKEYBOARD namespace and the CUsbKeys and CDirectKeys classes are still in development and I started a Google code project to invite you to collaborate. You are free to download and use the classes, the code is released under GPL v3 license. As this is a project in development, there is no warranty for anything.

The other reason I started to use googlecode was to get familiar with a version control system. So forgive me, if I do or did something wrong with svn.

The classes are documented inline and an offline documentation is generated with Doxygen. On my Windows developer PC, I use AnkhSVN and on an Ubuntu PC (documentation only), I use the svn command line tool. On Windows, you may also use TortoiseSVN, which integrates into the file explorer whereas AnkhSVN integrates into Visual Studio.

Both keyboard driver mappings are controlled through the registry of the intermec device (see community.intermec.com for a doc called reprogramming the USB keypad). The ITCKEYBOARD namespace provides you managed, strongly typed access to these registry tables. For example, the USB keyboard mappings are controlled by a sequence of 6 bytes for every key. These bytes define the key function and are concatenated in the registry into one binary registry value. The ITCKEYBOARD classes take this binary value and split it into the single key sequences for easy managing.

Screenshots of a Small Demo

The Demo Start and DirectKeys Screen

DirectKey Event Management and USBKey Demo Form

Insight View with the Dumpscreen

Sample Usage

C++
//create a new, empty usbkey
CUSBkeys.usbKeyStruct _theKey = new CUSBkeys.usbKeyStruct();
_theKey.bHID = 0x07;
_theKey.bFlagHigh = CUsbKeyTypes.usbFlagsHigh.NoFlag;      // UsbKeyFlags3.NoFlag;
_theKey.bFlagMid = CUsbKeyTypes.usbFlagsMid.NoRepeat;      // UsbKeyFlags2.NoRepeat;
_theKey.bFlagLow = CUsbKeyTypes.usbFlagsLow.RotateKeyIndex;// UsbKeyFlags3.RotateKeyIndex;

//initialize a new usbkey object
CUSBkeys _cusb = new CUSBkeys();

//ShiftPlane 1 ####################################################
//CAPS lock on "1"
// 'ModKey2' = 00,02,08,58                                 //caps lock
_theKey.bFlagHigh = CUsbKeyTypes.usbFlagsHigh.NoFlag;      // UsbKeyFlags3.NoFlag;
_theKey.bFlagMid = CUsbKeyTypes.usbFlagsMid.NoRepeat;      // UsbKeyFlags2.NoRepeat;
_theKey.bFlagLow = CUsbKeyTypes.usbFlagsLow.ModifierIndex; // UsbKeyFlags3.ModifierIndex;
_theKey.bIntScan = 0x02;                                   //ModKey index at 2 is caps lock
_theKey.bScanKey =  (CUsbKeyTypes.HWkeys)0x1E;
if (_cusb.setKey(2, _theKey.bScanKey, _theKey) != 0)
    _cusb.addKey(2, _theKey);
    
//space on "0"
_theKey.bFlagHigh = CUsbKeyTypes.usbFlagsHigh.NoFlag;      // UsbKeyFlags3.NoFlag;
_theKey.bFlagMid = CUsbKeyTypes.usbFlagsMid.VKEY;          // UsbKeyFlags2.VKEY;
_theKey.bFlagLow = CUsbKeyTypes.usbFlagsLow.NormalKey;     // UsbKeyFlags3.NormalKey;
_theKey.bIntScan = 0x20;
_theKey.bScanKey = (CUsbKeyTypes.HWkeys)0x27;
if (_cusb.setKey(2, _theKey.bScanKey, _theKey) != 0)
    _cusb.addKey(2, _theKey);
    
//remap (OK) to "@" (Shifted-Space)
_theKey.bFlagHigh = CUsbKeyTypes.usbFlagsHigh.NoFlag;      // UsbKeyFlags3.NoFlag;
_theKey.bFlagMid = CUsbKeyTypes.usbFlagsMid.VKEY | 
	CUsbKeyTypes.usbFlagsMid.Shifted;                      // UsbKeyFlags2.Shifted;
_theKey.bFlagLow = CUsbKeyTypes.usbFlagsLow.NormalKey;     // UsbKeyFlags3.NormalKey;
_theKey.bIntScan = 0x32;
_theKey.bScanKey = CUsbKeyTypes.HWkeys.Right_GUI;
if (_cusb.setKey(2, _theKey.bScanKey, _theKey) != 0)
    _cusb.addKey(2, _theKey);
    
//ShiftPlane 1 ####################################################
//VKLWIN='Left GUI' on "0", 07,27,00,01,00,1F (07,E3,00,01,00,1F)
//remap "0" on shift plane 1 to VK_LWIN (windows key)
_theKey.bFlagHigh = CUsbKeyTypes.usbFlagsHigh.NoFlag;      // UsbKeyFlags3.NoFlag;
_theKey.bFlagMid = CUsbKeyTypes.usbFlagsMid.Extended;      // UsbKeyFlags2.Extended;
_theKey.bFlagLow = CUsbKeyTypes.usbFlagsLow.NormalKey;     // UsbKeyFlags3.NormalKey;
_theKey.bIntScan = 0x1F;
_theKey.bScanKey = (CUsbKeyTypes.HWkeys)0x27;
if (_cusb.setKey(1, _theKey.bScanKey, _theKey) != 0)
    _cusb.addKey(1, _theKey);
    
//change the top row of keys to F1 to F4
_theKey.bHID = 0x07;
_theKey.bScanKey = CUsbKeyTypes.HWkeys.Left_GUI;
_theKey.bFlagHigh = CUsbKeyTypes.usbFlagsHigh.NoFlag;      // UsbKeyFlags3.NoFlag;
_theKey.bFlagMid = CUsbKeyTypes.usbFlagsMid.VKEY;          // UsbKeyFlags2.VKEY;
_theKey.bFlagLow = CUsbKeyTypes.usbFlagsLow.NormalKey;     // UsbKeyFlags3.NormalKey;
_theKey.bIntScan = 0x70;                                   //F1
if (_cusb.setKey(0, _theKey.bScanKey, _theKey) != 0)
    _cusb.addKey(0, _theKey);
    
_theKey.bScanKey = CUsbKeyTypes.HWkeys.F1;
_theKey.bIntScan = (byte)VKEY.VK_PRIOR;                    //PageUp // 0x71; //F2
if (_cusb.setKey(0, _theKey.bScanKey, _theKey) != 0)
    _cusb.addKey(0, _theKey);
    
_theKey.bScanKey = CUsbKeyTypes.HWkeys.F2;
_theKey.bIntScan = (byte)VKEY.VK_NEXT;                     //PgDwn 0x72; //F3
if (_cusb.setKey(0, _theKey.bScanKey, _theKey) != 0)
    _cusb.addKey(0, _theKey);
    
_theKey.bScanKey = CUsbKeyTypes.HWkeys.Right_GUI;
_theKey.bIntScan = 0x73;                                   //F3
if (_cusb.setKey(0, _theKey.bScanKey, _theKey) != 0)
    _cusb.addKey(0, _theKey);
    
_cusb.writeKeyTables();                                    //save the changes

// DIRECT Keys stuff
//remap PTT to @
CDirectKeys _directKeys = new CDirectKeys();               //create a new directkey object
_directKeys.setKey(0x02, VKEY.VK_SPACE, CDirectKeys.directKeyType.kTypeShiftdVirtualKey);
_directKeys.saveKeyTable();                                //save the changes
_directKeys = null;

Source code (Visual Studio 2005, Windows Mobile 6 Prof. SDK) (Work in progress)
http://code.google.com/p/itc-keyboard/

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)