ITCKeyboard: a class to manage ITC keyboard mappings

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 produce abc depending on how often you press is)
  • 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.

As an example on how the the USB codes are layed out on a device. Unfortunately I only have mappings of this device and not for the others. Therefor 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 this keys thru 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 familar 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 thru 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 splits 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

In insight view with the dumpscreen

Sample usage

            //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/

Leave a Reply