Date: Sat, 16 May 2009 17:56:37 GMT From: Hans Petter Selasky <hselasky@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 162165 for review Message-ID: <200905161756.n4GHub4e055534@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=162165 Change 162165 by hselasky@hselasky_laptop001 on 2009/05/16 17:55:40 USB input: - improve patch for Apple MacBook Pro keyboard. Reported by: Christoph Langguth Affected files ... .. //depot/projects/usb/src/sys/dev/usb/input/ukbd.c#6 edit .. //depot/projects/usb/src/sys/dev/usb/usbhid.h#8 edit Differences ... ==== //depot/projects/usb/src/sys/dev/usb/input/ukbd.c#6 (text+ko) ==== @@ -113,12 +113,13 @@ #define MOD_WIN_R 0x80 uint8_t reserved; uint8_t keycode[UKBD_NKEYCODE]; -} __packed; + uint8_t exten[8]; +}; enum { UKBD_INTR_DT, UKBD_CTRL_LED, - UKBD_N_TRANSFER = 3, + UKBD_N_TRANSFER, }; struct ukbd_softc { @@ -126,6 +127,8 @@ keymap_t sc_keymap; accentmap_t sc_accmap; fkeytab_t sc_fkeymap[UKBD_NFKEY]; + struct hid_location sc_loc_apple_eject; + struct hid_location sc_loc_apple_fn; struct usb2_callout sc_callout; struct ukbd_data sc_ndata; struct ukbd_data sc_odata; @@ -143,11 +146,14 @@ uint32_t sc_buffered_char[2]; #endif uint32_t sc_flags; /* flags */ -#define UKBD_FLAG_COMPOSE 0x0001 -#define UKBD_FLAG_POLLING 0x0002 -#define UKBD_FLAG_SET_LEDS 0x0004 -#define UKBD_FLAG_ATTACHED 0x0010 -#define UKBD_FLAG_GONE 0x0020 +#define UKBD_FLAG_COMPOSE 0x0001 +#define UKBD_FLAG_POLLING 0x0002 +#define UKBD_FLAG_SET_LEDS 0x0004 +#define UKBD_FLAG_ATTACHED 0x0010 +#define UKBD_FLAG_GONE 0x0020 +#define UKBD_FLAG_APPLE_EJECT 0x0040 +#define UKBD_FLAG_APPLE_FN 0x0080 +#define UKBD_FLAG_APPLE_SWAP 0x0100 int32_t sc_mode; /* input mode (K_XLATE,K_RAW,K_CODE) */ int32_t sc_state; /* shift/lock key state */ @@ -450,6 +456,28 @@ usb2_callout_reset(&sc->sc_callout, hz / 40, &ukbd_timeout, sc); } +static uint8_t +ukbd_apple_fn(uint8_t keycode) { + switch (keycode) { + case 0x2a: return 0x4c; /* BACKSPACE -> DEL */ + case 0x2c: return 0x49; /* SPACE -> INSERT */ + case 0x50: return 0x4a; /* LEFT ARROW -> HOME */ + case 0x4f: return 0x4d; /* RIGHT ARROW -> END */ + case 0x52: return 0x4b; /* UP ARROW -> PGUP */ + case 0x51: return 0x4e; /* DOWN ARROW -> PGDN */ + default: return keycode; + } +} + +static uint8_t +ukbd_apple_swap(uint8_t keycode) { + switch (keycode) { + case 0x35: return 0x64; /* 5 -> d */ + case 0x64: return 0x35; /* d -> 5 */ + default: return keycode; + } +} + static void ukbd_intr_callback(struct usb2_xfer *xfer) { @@ -457,26 +485,58 @@ uint16_t len = xfer->actlen; uint8_t i; uint8_t offset; + uint8_t id; + uint8_t apple_fn; + uint8_t apple_eject; switch (USB_GET_STATE(xfer)) { case USB_ST_TRANSFERRED: DPRINTF("actlen=%d bytes\n", len); - if ((sc->sc_hid_id != 0) && (len != 0)) { - /* remove HID ID byte */ + if (len == 0) { + DPRINTF("zero length data\n"); + goto tr_setup; + } + + if (sc->sc_hid_id != 0) { + /* check and remove HID ID byte */ + usb2_copy_out(xfer->frbuffers, 0, &id, 1); + if (id != sc->sc_hid_id) { + DPRINTF("wrong HID ID\n"); + goto tr_setup; + } offset = 1; len--; } else { offset = 0; } + if (len > sizeof(sc->sc_ndata)) { len = sizeof(sc->sc_ndata); } + if (len) { memset(&sc->sc_ndata, 0, sizeof(sc->sc_ndata)); usb2_copy_out(xfer->frbuffers, offset, &sc->sc_ndata, len); + + if ((sc->sc_flags & UKBD_FLAG_APPLE_EJECT) && + hid_get_data((uint8_t *)&sc->sc_ndata, + len, &sc->sc_loc_apple_eject)) + apple_eject = 1; + else + apple_eject = 0; + + if ((sc->sc_flags & UKBD_FLAG_APPLE_FN) && + hid_get_data((uint8_t *)&sc->sc_ndata, + len, &sc->sc_loc_apple_fn)) + apple_fn = 1; + else + apple_fn = 0; #if USB_DEBUG + DPRINTF("apple_eject=%u apple_fn=%u\n", + apple_eject, apple_fn); + if (sc->sc_ndata.modifiers) { DPRINTF("mod: 0x%04x\n", sc->sc_ndata.modifiers); } @@ -486,6 +546,21 @@ } } #endif /* USB_DEBUG */ + + if (apple_fn) { + for (i = 0; i < UKBD_NKEYCODE; i++) { + sc->sc_ndata.keycode[i] = + ukbd_apple_fn(sc->sc_ndata.keycode[i]); + } + } + + if (sc->sc_flags & UKBD_FLAG_APPLE_SWAP) { + for (i = 0; i < UKBD_NKEYCODE; i++) { + sc->sc_ndata.keycode[i] = + ukbd_apple_swap(sc->sc_ndata.keycode[i]); + } + } + ukbd_interrupt(sc); } case USB_ST_SETUP: @@ -604,6 +679,7 @@ keyboard_t *kbd = &sc->sc_kbd; void *hid_ptr = NULL; usb2_error_t err; + uint32_t flags; uint16_t n; uint16_t hid_len; @@ -657,7 +733,30 @@ err = usb2_req_get_hid_desc(uaa->device, NULL, &hid_ptr, &hid_len, M_TEMP, uaa->info.bIfaceIndex); if (err == 0) { - hid_report_size(hid_ptr, hid_len, hid_input, &sc->sc_hid_id); + /* investigate if this is an Apple Keyboard */ + if (hid_locate(hid_ptr, hid_len, + HID_USAGE2(HUP_CONSUMER, HUG_APPLE_EJECT), + hid_input, 0, &sc->sc_loc_apple_eject, &flags, + &sc->sc_hid_id)) { + if (flags & HIO_VARIABLE) + sc->sc_flags |= UKBD_FLAG_APPLE_EJECT | + UKBD_FLAG_APPLE_SWAP; + if (hid_locate(hid_ptr, hid_len, + HID_USAGE2(0xFFFF, 0x0003), + hid_input, 0, &sc->sc_loc_apple_fn, &flags, + &sc->sc_hid_id)) { + if (flags & HIO_VARIABLE) + sc->sc_flags |= UKBD_FLAG_APPLE_FN | + UKBD_FLAG_APPLE_SWAP; + } + } else { + /* + * Assume the first HID ID contains the + * keyboard data + */ + hid_report_size(hid_ptr, hid_len, + hid_input, &sc->sc_hid_id); + } free(hid_ptr, M_TEMP); } ==== //depot/projects/usb/src/sys/dev/usb/usbhid.h#8 (text+ko) ==== @@ -128,6 +128,7 @@ #define HUG_SYSTEM_MENU_LEFT 0x008b #define HUG_SYSTEM_MENU_UP 0x008c #define HUG_SYSTEM_MENU_DOWN 0x008d +#define HUG_APPLE_EJECT 0x00b8 /* Usages Digitizers */ #define HUD_UNDEFINED 0x0000
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200905161756.n4GHub4e055534>