Patching the Mac OS X USB keyboard driver

Deutsche Version

Playing around with keyboard layouts and even the additional uConrol hacks still did not make me happy...

On those levels, Mac OS X basically works with ADB key codes. That means, a lot of information from external USB keyboards has already been lost. The left and right modifier keys (cmd, alt, shift) for example can not be distinguished anymore because they send the same key codes...

So i started searching - and behold: i found something in the OpenDarwin CVS. That is, where Apple provides large parts of the OS X Kernel sources. Especially the AppleUSBKeyboard drivers. And here i actually found a hard coded table which contains the ADB key code to use for every USB key code that is recieved.

The compiled driver can be found in every Mac OS X setup in

/System/Library/Extensions/IOUSBFamily.kext/Contents/PlugIns/AppleUSBKeyboard.kext/Contents/MacOS/AppleUSBKeyboard
and the mapping table can be found (almost) identically in the drivers binary. (almost meaning: above key code 107 the binary driver contains some additional mappings.Apple seems not to have published the code mappings for some asian keyboards to opendarwin - but that does not really bother me...)

Even better: patching new values into this table works! I get alternate (ADB) codes for the (USB) keys whose table cell i alter. To the rest of the system it looks, like the keyboard had be resoldered.

So coded along one more day and wrote a little command line tool to make this binary patching a bit more comfortable.: usbkbpatch.pl neeeds to be called as root in the terminal. It creates a backup copy of the original driver, patches some entries in the USB to ADB table - defined on the command line - and then loads the modified driver. Since it modifies the driver in place, the change will be persistent.

The command line parameters are pairs of numbers.
the first one tells us which place in the table to change (the USB key code).
The second one is the new value to write there (the ADB key code).
Numbers can be written in decimal or (preceeded by '0x') in hex.

Here are some interesting USB codes:
0xe0control left
0xe1shift left
0xe2option/alt left
0xe3comand left
0xe4control right
0xe5shift right
0xe6option/alt right
0xe7comand right
0x65Windows Context-Menu (Wintel USB keyboards)
0x64^ (on german keyboards at least...
i mean the key left of the digit 1 on the top left)
on wintel-usb it's swapped with the lower left key between shift and 'z' (code 0x35)
0x35< (on german keyboards at least...
i mean the key between the left shift and the 'z'
on wintel usb it's swapped with the key left of digit 1 (code 0x64))
0x53 insert - on iMac keyboards my hand allways searches for delete in that place

And here are some suitable ADB codes:
0x3bcontrol
0x38shift
0x3aoption/alt
0x37command
0x34enter (not return...)
0x32the adb code for usb 0x64 above
0x0athe adb code for usb 0x35 above
0x75delete


What to do:

what if something went wrong...

(how could that ever happen?)

The original driver was saved in
System/Library/Extensions/IOUSBFamily.kext/Contents/PlugIns/AppleUSBKeyboard.kext/Contents/MacOS/
with the uname of the current OS version (e.g. Darwin_6.6). In order to reactivate it, You need to do the following (replace the 6.6 version number with what you find when you ls the directory)
 kextunload /System/Library/Extensions/IOUSBFamily.kext/Contents/PlugIns/AppleUSBKeyboard.kext
 cd /System/Library/Extensions/IOUSBFamily.kext/Contents/PlugIns/AppleUSBKeyboard.kext/Contents/MacOS/
 ls
 cp AppleUSBKeyboard.Darwin_6.6 AppleUSBKeyboard 
 kextload /System/Library/Extensions/IOUSBFamily.kext/Contents/PlugIns/AppleUSBKeyboard.kext

Since it messes aryound with the kernel in a rather brutal way, you can really shoot yourself in the foot whith this patch tool. For example you can make sure, none of your keys ever generates a return keycode anymore. So you won't be able to do anything in Terminal.app anymore. So you won't be able to easily undo the changes... And single user mode uses the very same driver too..

Allways remember, that you can copy and paste into the Treminal. Also, you can use 'Key Caps.app' to type-click some text snippets together. It your Terminal with root access is still open, you can try to copy and paste the following from this page:
 kextunload /System/Library/Extensions/IOUSBFamily.kext/Contents/PlugIns/AppleUSBKeyboard.kext
 cd /System/Library/Extensions/IOUSBFamily.kext/Contents/PlugIns/AppleUSBKeyboard.kext/Contents/MacOS/
 cp AppleUSBKeyboard.Darwin_* AppleUSBKeyboard 
 kextload /System/Library/Extensions/IOUSBFamily.kext/Contents/PlugIns/AppleUSBKeyboard.kext

On my iBook, i was rather safe however: the patching only affected the external USB keyboard and i could allways rely on the builtin ADB keyboard to undo the changes.

Update 19. November 2003:
Adaption to Panther: the affected kernel module is now IOHIDFamily.kext and the table has also changed a bit. Also, it now takes a reboot to activate the changes since IOHIDFamily is not an unloadable module.


 up

 Author:
Heiko Hellweg, modified: Novmber 2003