Hi,

The attached patch enables the Fn key on Macbooks which is required to get Home, End, [..] keys to work.

Now I need some input on a good way to detect if a keyboard has that Fn key. Currently I'm using the quirk approach, possible would also be to use hid_locate() as Rui Paulo did in http://fnop.net/~rpaulo/priv/freebsd/macbook-aug-1.diff and defining a option named UKBD_HAS_FN or something would work too. So what's the way to go for?

To all Macbook (Pro) users, if you can afford some spare time and test the patch, feedback welcome. :)



Regards,
Bernhard Schmidt
diff -ur /usr/src.orig/sys/dev/usb/ukbd.c /usr/src/sys/dev/usb/ukbd.c
--- /usr/src.orig/sys/dev/usb/ukbd.c    2008-04-26 18:40:35.000000000 +0200
+++ /usr/src/sys/dev/usb/ukbd.c 2008-04-26 18:50:23.000000000 +0200
@@ -110,6 +110,9 @@
 
 typedef struct ukbd_softc {
        device_t                sc_dev;         /* base device */
+       int                     sc_flags;
+#define UKBD_FNKEY             0x01
+#define UKBD_HASFN             0x01
 } ukbd_softc_t;
 
 #define        UKBD_CHUNK      128     /* chunk size for read */
@@ -191,6 +194,11 @@
 
        id = usbd_get_interface_descriptor(iface);
 
+       if (usbd_get_quirks(uaa->device)->uq_flags & UQ_APPLE_HAS_FN) {
+               device_printf(self, "Apple Macbook Fn key detected\n.");
+               sc->sc_flags |= UKBD_HASFN;
+       }
+
        arg[0] = (void *)uaa;
        arg[1] = (void *)ukbd_intr;
        kbd = NULL;
@@ -206,6 +214,8 @@
 #endif
        if (bootverbose)
                (*sw->diag)(kbd, bootverbose);
+       if (sc->sc_flags & UKBD_HASFN)
+                kbd->kb_flags |= UKBD_HASFN;
 
        return 0;
 }
@@ -364,6 +374,7 @@
        int             ks_mode;        /* input mode (K_XLATE,K_RAW,K_CODE) */
        int             ks_flags;       /* flags */
 #define COMPOSE                (1 << 0)
+#define FNKEY          (2 << 0)
        int             ks_polling;
        int             ks_state;       /* shift/lock key state */
        int             ks_accents;     /* accent key index (> 0) */
@@ -866,6 +877,7 @@
                c = -1;
        } else {
                c = state->ks_input[state->ks_inputhead];
+               DPRINTF(("ukbd_getc: read %04x\n", c));
                --state->ks_inputs;
                state->ks_inputhead = (state->ks_inputhead + 1)%INPUTBUFSIZE;
        }
@@ -1031,6 +1043,53 @@
                return NOKEY;
        ++kbd->kb_count;
 
+       if (!(kbd->kb_flags & UKBD_HASFN))
+               goto no_fn_key;
+
+       /* fn key pressed */
+       if (usbcode == UKBD_FNKEY) {
+               if (!(state->ks_flags & FNKEY)) {
+                       state->ks_flags |= FNKEY;
+                       DPRINTFN(1, ("ukbd_read_char: fn key pressed\n"));
+               }
+               --kbd->kb_count;
+               goto next_code;
+       }
+
+       /* fn key released */
+       else if (KEY_INDEX(usbcode) == UKBD_FNKEY) {
+               if (state->ks_flags & FNKEY) {
+                       state->ks_flags &= ~FNKEY;
+                       DPRINTFN(1, ("ukbd_read_char: fn key released\n"));
+               }
+               --kbd->kb_count;
+               goto next_code;
+       }
+
+       /* translate scancodes while fn key is pressed */
+       else if (state->ks_flags & FNKEY) {
+               DPRINTFN(2, ("ukbd_read_char: translate: %04x\n", usbcode));
+               switch (KEY_INDEX(usbcode)) {
+               case 0x2a:              /* delete */
+                       usbcode = 0x4c | (usbcode & KEY_RELEASE ? KEY_RELEASE : 
0x0);
+                       break;
+               case 0x4f:              /* end */
+                       usbcode = 0x4d | (usbcode & KEY_RELEASE ? KEY_RELEASE : 
0x0);
+                       break;
+               case 0x50:              /* home */
+                       usbcode = 0x4a | (usbcode & KEY_RELEASE ? KEY_RELEASE : 
0x0);
+                       break;
+               case 0x51:              /* pagedown */
+                       usbcode = 0x4e | (usbcode & KEY_RELEASE ? KEY_RELEASE : 
0x0);
+                       break;
+               case 0x52:              /* pageup */
+                       usbcode = 0x4b | (usbcode & KEY_RELEASE ? KEY_RELEASE : 
0x0);
+                       break;
+               }
+               DPRINTFN(2, ("ukbd_read_char: translated to %04x\n", usbcode));
+       }
+no_fn_key:
+
 #ifdef UKBD_EMULATE_ATSCANCODE
        /* USB key index -> key code -> AT scan code */
        keycode = ukbd_trtab[KEY_INDEX(usbcode)];
diff -ur /usr/src.orig/sys/dev/usb/usb_quirks.c 
/usr/src/sys/dev/usb/usb_quirks.c
--- /usr/src.orig/sys/dev/usb/usb_quirks.c      2008-04-26 18:40:35.000000000 
+0200
+++ /usr/src/sys/dev/usb/usb_quirks.c   2008-04-26 18:45:03.000000000 +0200
@@ -90,6 +90,8 @@
    ANY, { UQ_MS_BAD_CLASS | UQ_MS_LEADING_BYTE }},
  { USB_VENDOR_MICROSOFT, USB_PRODUCT_MICROSOFT_WLINTELLIMOUSE,
    ANY, { UQ_MS_LEADING_BYTE }},
+/* Apple Macbook Keyboard */
+ { USB_VENDOR_APPLE, USB_PRODUCT_APPLE_INT_KBD,     ANY,   { UQ_APPLE_HAS_FN 
}},
 
  /* Devices which should be ignored by uhid */
  { USB_VENDOR_APC, USB_PRODUCT_APC_UPS,
diff -ur /usr/src.orig/sys/dev/usb/usb_quirks.h 
/usr/src/sys/dev/usb/usb_quirks.h
--- /usr/src.orig/sys/dev/usb/usb_quirks.h      2008-04-26 18:40:35.000000000 
+0200
+++ /usr/src/sys/dev/usb/usb_quirks.h   2008-04-26 18:45:03.000000000 +0200
@@ -57,6 +57,7 @@
 #define UQ_KBD_IGNORE  0x00018000 /* device should be ignored by both kbd and 
hid class */
 #define        UQ_MS_BAD_CLASS 0x00020000 /* doesn't identify properly */
 #define        UQ_MS_LEADING_BYTE 0x40000 /* mouse sends an unknown leading 
byte. */
+#define UQ_APPLE_HAS_FN 0x00080000 /* keyboard has fn key */
 };
 
 extern const struct usbd_quirks usbd_no_quirk;
diff -ur /usr/src.orig/sys/dev/usb/usbdevs /usr/src/sys/dev/usb/usbdevs
--- /usr/src.orig/sys/dev/usb/usbdevs   2008-04-26 18:40:35.000000000 +0200
+++ /usr/src/sys/dev/usb/usbdevs        2008-04-26 18:45:03.000000000 +0200
@@ -838,6 +838,7 @@
 
 /* Apple Computer products */
 product APPLE EXT_KBD          0x020c  Apple Extended USB Keyboard
+product APPLE INT_KBD          0x021b  Apple Macbook Internal Keyboard
 product APPLE OPTMOUSE         0x0302  Optical mouse
 product APPLE MIGHTYMOUSE      0x0304  Mighty Mouse
 product APPLE EXT_KBD_HUB      0x1003  Hub in Apple Extended USB Keyboard
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-usb
To unsubscribe, send any mail to "[EMAIL PROTECTED]"

Reply via email to