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/AppleUSBKeyboardand 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:
0xe0 | control left |
0xe1 | shift left |
0xe2 | option/alt left |
0xe3 | comand left |
0xe4 | control right |
0xe5 | shift right |
0xe6 | option/alt right |
0xe7 | comand right |
0x65 | Windows 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:
0x3b | control |
0x38 | shift |
0x3a | option/alt |
0x37 | command |
0x34 | enter (not return...) |
0x32 | the adb code for usb 0x64 above |
0x0a | the adb code for usb 0x35 above |
0x75 | delete |
What to do:
sudo su ./usbkbpatch.pl 0xe6 0x37 0xe7 0x3a |
open /Applications/Utilities/Key\ Caps.app |
(how could that ever happen?)
The original driver was saved in
System/Library/Extensions/IOUSBFamily.kext/Contents/PlugIns/AppleUSBKeyboard.kext/Contents/MacOS/ |
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.
Author:
Heiko Hellweg,
modified: Novmber 2003