Saturday, October 06, 2012

German iBook G4 Keyboard

I currently have a iBook-G4 on my desk, running Linux. Everything is dandy, only a few things with the keyboard are odd. Two keys are swapped: “°^” (to the left of the number 1-key on a German keyboard) and “<>” (to the left of “Y” on a German keyboard)". And the right ALT key seems to be mapped to the “Enter” function. I got it running after messing around with the Xorg xkb settings (which is a nightmare, btw.) but it is clear that the problem is somewhere deeper.

There’s some serious mapping error for this keyboard in the kernel’s table stored in adbhid.c.

Key ADB Code Key is… Key should…
<> 0x32 KEY_GRAVE KEY_102ND
°^ 0x0a KEY_102ND KEY_GRAVE
R-Alt 0x34 KEY_KPENTER KEY_RIGHTALT

Here’s a patch that makes this keyboard behave:

$ cat ~/adbhid_c.patch
--- ./drivers/macintosh/adbhid.c.orig   2012-10-06 15:52:16.032673677 +0200
+++ ./drivers/macintosh/adbhid.c        2012-10-06 16:23:23.708911092 +0200
@@ -798,7 +798,7 @@

                memcpy(hid->keycode, adb_to_linux_keycodes, sizeof(adb_to_linux_keycodes));

-               printk(KERN_INFO "Detected ADB keyboard, type ");
+               printk(KERN_INFO "Detected ADB keyboard, type (%x) ",original_handler_id);
                switch (original_handler_id) {
                default:
                        printk("<unknown>.\n");
@@ -807,11 +807,19 @@

                case 0x01: case 0x02: case 0x03: case 0x06: case 0x08:
                case 0x0C: case 0x10: case 0x18: case 0x1B: case 0x1C:
-               case 0xC0: case 0xC3: case 0xC6:
+               case 0xC0: case 0xC6:
                        printk("ANSI.\n");
                        input_dev->id.version = ADB_KEYBOARD_ANSI;
                        break;

+               case 0xC3:
+                       printk("ANSI (iBook G4 German).\n");
+                       input_dev->id.version = ADB_KEYBOARD_ANSI;
+                       hid->keycode[0x32] = KEY_102ND; /* German: left of Y, less/greater */
+                       hid->keycode[0x0a] = KEY_GRAVE; /* German: left of 1 */
+                       hid->keycode[0x34] = KEY_RIGHTALT;
+                       break;
+
                case 0x04: case 0x05: case 0x07: case 0x09: case 0x0D:
                case 0x11: case 0x14: case 0x19: case 0x1D: case 0xC1:
                case 0xC4: case 0xC7:

No comments: