diff options
Diffstat (limited to 'sys/dev/usb/input')
| -rw-r--r-- | sys/dev/usb/input/uep.c | 4 | ||||
| -rw-r--r-- | sys/dev/usb/input/ukbd.c | 174 | ||||
| -rw-r--r-- | sys/dev/usb/input/wsp.c | 17 |
3 files changed, 161 insertions, 34 deletions
diff --git a/sys/dev/usb/input/uep.c b/sys/dev/usb/input/uep.c index 25eeb450491d..d54efe9cea2c 100644 --- a/sys/dev/usb/input/uep.c +++ b/sys/dev/usb/input/uep.c @@ -517,9 +517,9 @@ uep_close(struct usb_fifo *fifo, int fflags) static device_method_t uep_methods[] = { DEVMETHOD(device_probe, uep_probe), - DEVMETHOD(device_attach, uep_attach), + DEVMETHOD(device_attach, uep_attach), DEVMETHOD(device_detach, uep_detach), - { 0, 0 }, + DEVMETHOD_END }; static driver_t uep_driver = { diff --git a/sys/dev/usb/input/ukbd.c b/sys/dev/usb/input/ukbd.c index 57e9beac34b6..104e51c082c3 100644 --- a/sys/dev/usb/input/ukbd.c +++ b/sys/dev/usb/input/ukbd.c @@ -95,18 +95,29 @@ #ifdef USB_DEBUG static int ukbd_debug = 0; +#endif static int ukbd_no_leds = 0; static int ukbd_pollrate = 0; +static int ukbd_apple_fn_mode = 0; +static int ukbd_apple_swap_cmd_ctl = 0; +static int ukbd_apple_swap_cmd_opt = 0; static SYSCTL_NODE(_hw_usb, OID_AUTO, ukbd, CTLFLAG_RW | CTLFLAG_MPSAFE, 0, "USB keyboard"); +#ifdef USB_DEBUG SYSCTL_INT(_hw_usb_ukbd, OID_AUTO, debug, CTLFLAG_RWTUN, &ukbd_debug, 0, "Debug level"); +#endif SYSCTL_INT(_hw_usb_ukbd, OID_AUTO, no_leds, CTLFLAG_RWTUN, &ukbd_no_leds, 0, "Disables setting of keyboard leds"); SYSCTL_INT(_hw_usb_ukbd, OID_AUTO, pollrate, CTLFLAG_RWTUN, &ukbd_pollrate, 0, "Force this polling rate, 1-1000Hz"); -#endif +SYSCTL_INT(_hw_usb_ukbd, OID_AUTO, apple_fn_mode, CTLFLAG_RWTUN, + &ukbd_apple_fn_mode, 0, "0 = Fn + F1..12 -> media, 1 = F1..F12 -> media"); +SYSCTL_INT(_hw_usb_ukbd, OID_AUTO, apple_swap_cmd_ctl, CTLFLAG_RWTUN, + &ukbd_apple_swap_cmd_ctl, 0, "Swap Command & Control keys"); +SYSCTL_INT(_hw_usb_ukbd, OID_AUTO, apple_swap_cmd_opt, CTLFLAG_RWTUN, + &ukbd_apple_swap_cmd_opt, 0, "Swap Command & Option keys"); #define UKBD_EMULATE_ATSCANCODE 1 #define UKBD_DRIVER_NAME "ukbd" @@ -123,6 +134,10 @@ SYSCTL_INT(_hw_usb_ukbd, OID_AUTO, pollrate, CTLFLAG_RWTUN, #define MOD_EJECT 0x01 #define MOD_FN 0x02 +/* check evdev_usb_scancodes[] for names */ +#define APPLE_FN_KEY 0xff +#define APPLE_EJECT_KEY 0xec + struct ukbd_data { uint64_t bitmap[howmany(UKBD_NKEYCODE, 64)]; }; @@ -198,6 +213,7 @@ struct ukbd_softc { uint16_t sc_inputs; uint16_t sc_inputhead; uint16_t sc_inputtail; + uint16_t sc_vendor_id; uint8_t sc_leds; /* store for async led requests */ uint8_t sc_iface_index; @@ -282,9 +298,9 @@ static const uint8_t ukbd_trtab[256] = { NN, NN, NN, NN, NN, NN, NN, NN, /* D0 - D7 */ NN, NN, NN, NN, NN, NN, NN, NN, /* D8 - DF */ 29, 42, 56, 105, 90, 54, 93, 106, /* E0 - E7 */ - NN, NN, NN, NN, NN, NN, NN, NN, /* E8 - EF */ + NN, NN, NN, NN, 254, NN, NN, NN, /* E8 - EF */ NN, NN, NN, NN, NN, NN, NN, NN, /* F0 - F7 */ - NN, NN, NN, NN, NN, NN, NN, NN, /* F8 - FF */ + NN, NN, NN, NN, NN, NN, NN, 255, /* F8 - FF */ }; static const uint8_t ukbd_boot_desc[] = { @@ -582,14 +598,14 @@ ukbd_interrupt(struct ukbd_softc *sc) sc->sc_repeat_key = 0; } else { ukbd_put_key(sc, key | KEY_PRESS); - - sc->sc_co_basetime = sbinuptime(); - sc->sc_delay = sc->sc_kbd.kb_delay1; - ukbd_start_timer(sc); - - /* set repeat time for last key */ - sc->sc_repeat_time = now + sc->sc_kbd.kb_delay1; - sc->sc_repeat_key = key; + if (key != APPLE_FN_KEY) { + sc->sc_co_basetime = sbinuptime(); + sc->sc_delay = sc->sc_kbd.kb_delay1; + ukbd_start_timer(sc); + /* set repeat time for last key */ + sc->sc_repeat_time = now + sc->sc_kbd.kb_delay1; + sc->sc_repeat_key = key; + } } } } @@ -669,6 +685,16 @@ static uint32_t ukbd_apple_fn(uint32_t keycode) { switch (keycode) { + case 0x0b: return 0x50; /* H -> LEFT ARROW */ + case 0x0d: return 0x51; /* J -> DOWN ARROW */ + case 0x0e: return 0x52; /* K -> UP ARROW */ + case 0x0f: return 0x4f; /* L -> RIGHT ARROW */ + case 0x36: return 0x4a; /* COMMA -> HOME */ + case 0x37: return 0x4d; /* DOT -> END */ + case 0x18: return 0x4b; /* U -> PGUP */ + case 0x07: return 0x4e; /* D -> PGDN */ + case 0x16: return 0x47; /* S -> SCROLLLOCK */ + case 0x13: return 0x46; /* P -> SYSRQ/PRTSC */ case 0x28: return 0x49; /* RETURN -> INSERT */ case 0x2a: return 0x4c; /* BACKSPACE -> DEL */ case 0x50: return 0x4a; /* LEFT ARROW -> HOME */ @@ -679,6 +705,51 @@ ukbd_apple_fn(uint32_t keycode) } } +/* separate so the sysctl doesn't butcher non-fn keys */ +static uint32_t +ukbd_apple_fn_media(uint32_t keycode) +{ + switch (keycode) { + case 0x3a: return 0xc0; /* F1 -> BRIGHTNESS DOWN */ + case 0x3b: return 0xc1; /* F2 -> BRIGHTNESS UP */ + case 0x3c: return 0xc2; /* F3 -> SCALE (MISSION CTRL)*/ + case 0x3d: return 0xc3; /* F4 -> DASHBOARD (LAUNCHPAD) */ + case 0x3e: return 0xc4; /* F5 -> KBD BACKLIGHT DOWN */ + case 0x3f: return 0xc5; /* F6 -> KBD BACKLIGHT UP */ + case 0x40: return 0xea; /* F7 -> MEDIA PREV */ + case 0x41: return 0xe8; /* F8 -> PLAY/PAUSE */ + case 0x42: return 0xeb; /* F9 -> MEDIA NEXT */ + case 0x43: return 0xef; /* F10 -> MUTE */ + case 0x44: return 0xee; /* F11 -> VOLUME DOWN */ + case 0x45: return 0xed; /* F12 -> VOLUME UP */ + default: return keycode; + } +} + +static uint32_t +ukbd_apple_doswap_cmd_ctl(uint32_t keycode) +{ + switch (keycode) { + case 0xe3: return 0xe0; /* LCMD -> LCTL */ + case 0xe7: return 0xe4; /* RCMD -> RCTL */ + case 0xe0: return 0xe3; /* LCTL -> LCMD */ + case 0xe4: return 0xe7; /* RCTL -> RCMD */ + default: return keycode; + } +} + +static uint32_t +ukbd_apple_doswap_cmd_opt(uint32_t keycode) +{ + switch (keycode) { + case 0xe3: return 0xe2; /* LCMD -> ROPT */ + case 0xe7: return 0xe6; /* RCMD -> ROPT */ + case 0xe2: return 0xe3; /* LOPT -> LCMD */ + case 0xe6: return 0xe7; /* ROPT -> RCMD */ + default: return keycode; + } +} + static uint32_t ukbd_apple_swap(uint32_t keycode) { @@ -740,18 +811,34 @@ ukbd_intr_callback(struct usb_xfer *xfer, usb_error_t error) /* clear modifiers */ modifiers = 0; - /* scan through HID data */ + /* scan through HID data and expose magic apple keys */ if ((sc->sc_flags & UKBD_FLAG_APPLE_EJECT) && (id == sc->sc_id_apple_eject)) { - if (hid_get_data(sc->sc_buffer, len, &sc->sc_loc_apple_eject)) + if (hid_get_data(sc->sc_buffer, len, &sc->sc_loc_apple_eject)) { + sc->sc_ndata.bitmap[APPLE_EJECT_KEY / 64] |= + 1ULL << (APPLE_EJECT_KEY % 64); modifiers |= MOD_EJECT; + } else { + sc->sc_ndata.bitmap[APPLE_EJECT_KEY / 64] &= + ~(1ULL << (APPLE_EJECT_KEY % 64)); + } } if ((sc->sc_flags & UKBD_FLAG_APPLE_FN) && (id == sc->sc_id_apple_fn)) { - if (hid_get_data(sc->sc_buffer, len, &sc->sc_loc_apple_fn)) + if (hid_get_data(sc->sc_buffer, len, &sc->sc_loc_apple_fn)) { + sc->sc_ndata.bitmap[APPLE_FN_KEY / 64] |= + 1ULL << (APPLE_FN_KEY % 64); modifiers |= MOD_FN; + } else { + sc->sc_ndata.bitmap[APPLE_FN_KEY / 64] &= + ~(1ULL << (APPLE_FN_KEY % 64)); + } } + int apply_apple_fn_media = (modifiers & MOD_FN) ? 1 : 0; + if (ukbd_apple_fn_mode) /* toggle from sysctl value */ + apply_apple_fn_media = !apply_apple_fn_media; + for (i = 0; i != UKBD_NKEYCODE; i++) { const uint64_t valid = sc->sc_loc_key_valid[i / 64]; const uint64_t mask = 1ULL << (i % 64); @@ -780,6 +867,12 @@ ukbd_intr_callback(struct usb_xfer *xfer, usb_error_t error) } if (modifiers & MOD_FN) key = ukbd_apple_fn(key); + if (apply_apple_fn_media) + key = ukbd_apple_fn_media(key); + if (ukbd_apple_swap_cmd_ctl) + key = ukbd_apple_doswap_cmd_ctl(key); + if (ukbd_apple_swap_cmd_opt) + key = ukbd_apple_doswap_cmd_opt(key); if (sc->sc_flags & UKBD_FLAG_APPLE_SWAP) key = ukbd_apple_swap(key); if (key == KEY_NONE || key >= UKBD_NKEYCODE) @@ -792,6 +885,12 @@ ukbd_intr_callback(struct usb_xfer *xfer, usb_error_t error) if (modifiers & MOD_FN) key = ukbd_apple_fn(key); + if (apply_apple_fn_media) + key = ukbd_apple_fn_media(key); + if (ukbd_apple_swap_cmd_ctl) + key = ukbd_apple_doswap_cmd_ctl(key); + if (ukbd_apple_swap_cmd_opt) + key = ukbd_apple_doswap_cmd_opt(key); if (sc->sc_flags & UKBD_FLAG_APPLE_SWAP) key = ukbd_apple_swap(key); if (key == KEY_NONE || key == KEY_ERROR || key >= UKBD_NKEYCODE) @@ -1045,21 +1144,37 @@ ukbd_parse_hid(struct ukbd_softc *sc, const uint8_t *ptr, uint32_t len) hid_input, &sc->sc_kbd_id); /* investigate if this is an Apple Keyboard */ - if (hid_locate(ptr, len, - HID_USAGE2(HUP_CONSUMER, HUG_APPLE_EJECT), - hid_input, 0, &sc->sc_loc_apple_eject, &flags, - &sc->sc_id_apple_eject)) { - if (flags & HIO_VARIABLE) - sc->sc_flags |= UKBD_FLAG_APPLE_EJECT; - DPRINTFN(1, "Found Apple eject-key\n"); - } - if (hid_locate(ptr, len, - HID_USAGE2(0xFFFF, 0x0003), - hid_input, 0, &sc->sc_loc_apple_fn, &flags, - &sc->sc_id_apple_fn)) { - if (flags & HIO_VARIABLE) - sc->sc_flags |= UKBD_FLAG_APPLE_FN; - DPRINTFN(1, "Found Apple FN-key\n"); + if (sc->sc_vendor_id == USB_VENDOR_APPLE) { + if (hid_locate(ptr, len, + HID_USAGE2(HUP_CONSUMER, HUG_APPLE_EJECT), + hid_input, 0, &sc->sc_loc_apple_eject, &flags, + &sc->sc_id_apple_eject)) { + if (flags & HIO_VARIABLE) + sc->sc_flags |= UKBD_FLAG_APPLE_EJECT; + DPRINTFN(1, "Found Apple eject-key\n"); + } + /* + * check the same vendor pages that linux does to find the one + * apple uses for the function key. + */ + static const uint16_t apple_pages[] = { + HUP_APPLE, /* HID_UP_CUSTOM in linux */ + HUP_MICROSOFT, /* HID_UP_MSVENDOR in linux */ + HUP_HP, /* HID_UP_HPVENDOR2 in linux */ + 0xFFFF /* Original FreeBSD check (Remove?) */ + }; + for (int i = 0; i < (int)nitems(apple_pages); i++) { + if (hid_locate(ptr, len, + HID_USAGE2(apple_pages[i], 0x0003), + hid_input, 0, &sc->sc_loc_apple_fn, &flags, + &sc->sc_id_apple_fn)) { + if (flags & HIO_VARIABLE) + sc->sc_flags |= UKBD_FLAG_APPLE_FN; + DPRINTFN(1, "Found Apple FN-key on page 0x%04x\n", + apple_pages[i]); + break; + } + } } /* figure out event buffer */ @@ -1147,6 +1262,7 @@ ukbd_attach(device_t dev) sc->sc_udev = uaa->device; sc->sc_iface = uaa->iface; + sc->sc_vendor_id = uaa->info.idVendor; sc->sc_iface_index = uaa->info.bIfaceIndex; sc->sc_iface_no = uaa->info.bIfaceNum; sc->sc_mode = K_XLATE; diff --git a/sys/dev/usb/input/wsp.c b/sys/dev/usb/input/wsp.c index f78d64f69c08..2d7e3b796b17 100644 --- a/sys/dev/usb/input/wsp.c +++ b/sys/dev/usb/input/wsp.c @@ -231,6 +231,7 @@ enum tp_type { /* list of device capability bits */ #define HAS_INTEGRATED_BUTTON 1 +#define SUPPORTS_FORCETOUCH 2 /* trackpad finger data block size */ #define FSIZE_TYPE1 (14 * 2) @@ -285,7 +286,7 @@ struct wsp_tp { .delta = 0, }, [TYPE4] = { - .caps = HAS_INTEGRATED_BUTTON, + .caps = HAS_INTEGRATED_BUTTON | SUPPORTS_FORCETOUCH, .button = BUTTON_TYPE4, .offset = FINGER_TYPE4, .fsize = FSIZE_TYPE4, @@ -896,7 +897,8 @@ wsp_attach(device_t dev) WSP_SUPPORT_ABS(sc->sc_evdev, ABS_MT_POSITION_X, sc->sc_params->x); WSP_SUPPORT_ABS(sc->sc_evdev, ABS_MT_POSITION_Y, sc->sc_params->y); /* finger pressure */ - WSP_SUPPORT_ABS(sc->sc_evdev, ABS_MT_PRESSURE, sc->sc_params->p); + if ((sc->sc_params->tp->caps & SUPPORTS_FORCETOUCH) != 0) + WSP_SUPPORT_ABS(sc->sc_evdev, ABS_MT_PRESSURE, sc->sc_params->p); /* finger major/minor axis */ WSP_SUPPORT_ABS(sc->sc_evdev, ABS_MT_TOUCH_MAJOR, sc->sc_params->w); WSP_SUPPORT_ABS(sc->sc_evdev, ABS_MT_TOUCH_MINOR, sc->sc_params->w); @@ -1066,6 +1068,10 @@ wsp_intr_callback(struct usb_xfer *xfer, usb_error_t error) if (evdev_rcpt_mask & EVDEV_RCPT_HW_MOUSE) { evdev_push_key(sc->sc_evdev, BTN_LEFT, ibt); evdev_sync(sc->sc_evdev); + if ((sc->sc_fflags & FREAD) == 0 || + usb_fifo_put_bytes_max( + sc->sc_fifo.fp[USB_FIFO_RX]) == 0) + goto tr_setup; } #endif sc->sc_status.flags &= ~MOUSE_POSCHANGED; @@ -1355,7 +1361,12 @@ wsp_intr_callback(struct usb_xfer *xfer, usb_error_t error) case USB_ST_SETUP: tr_setup: /* check if we can put more data into the FIFO */ - if (usb_fifo_put_bytes_max( + if ( +#ifdef EVDEV_SUPPORT + ((evdev_rcpt_mask & EVDEV_RCPT_HW_MOUSE) != 0 && + (sc->sc_state & WSP_EVDEV_OPENED) != 0) || +#endif + usb_fifo_put_bytes_max( sc->sc_fifo.fp[USB_FIFO_RX]) != 0) { usbd_xfer_set_frame_len(xfer, 0, sc->tp_datalen); |
