Macbook Fn key, ukbd
Bernhard Schmidt
scb at techwires.net
Sat Apr 26 20:51:26 UTC 2008
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
-------------- next part --------------
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
More information about the freebsd-usb
mailing list