Date: Sat, 26 Apr 2008 22:40:00 +0200 From: Bernhard Schmidt <scb@techwires.net> To: freebsd-usb@freebsd.org Subject: Macbook Fn key, ukbd Message-ID: <48139320.5040905@techwires.net>
next in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format. --------------000208050209040703010703 Content-Type: text/plain; charset=ISO-8859-15; format=flowed Content-Transfer-Encoding: 7bit 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 --------------000208050209040703010703 Content-Type: text/plain; x-mac-type="0"; x-mac-creator="0"; name="macbookfnkey.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="macbookfnkey.diff" 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 --------------000208050209040703010703--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?48139320.5040905>