diff options
author | gonzo <gonzo@FreeBSD.org> | 2016-12-03 17:40:26 +0000 |
---|---|---|
committer | gonzo <gonzo@FreeBSD.org> | 2016-12-03 17:40:26 +0000 |
commit | 76a9d7a96992c3bfcb08ce5c14768c44cd943fc1 (patch) | |
tree | a4dde85c32fb09aea51c531262a23d1d5f304055 /sys/dev/kbdmux | |
parent | 1e91a5a4ca7106dc7a754883d2f4369a5e63c193 (diff) | |
download | FreeBSD-src-76a9d7a96992c3bfcb08ce5c14768c44cd943fc1.zip FreeBSD-src-76a9d7a96992c3bfcb08ce5c14768c44cd943fc1.tar.gz |
MFC r308668:
[evdev] Add evdev support to kbdmux(4) driver
To enable event sourcing from kbdmux(4) kern.evdev.rcpt_mask value
should have bit 1 set (this is default)
Submitted by: Vladimir Kondratiev <wulf@cicgroup.ru>
Differential Revision: https://reviews.freebsd.org/D8437
Diffstat (limited to 'sys/dev/kbdmux')
-rw-r--r-- | sys/dev/kbdmux/kbdmux.c | 79 |
1 files changed, 76 insertions, 3 deletions
diff --git a/sys/dev/kbdmux/kbdmux.c b/sys/dev/kbdmux/kbdmux.c index 0dce120..9f4978d 100644 --- a/sys/dev/kbdmux/kbdmux.c +++ b/sys/dev/kbdmux/kbdmux.c @@ -32,6 +32,7 @@ */ #include "opt_compat.h" +#include "opt_evdev.h" #include "opt_kbd.h" #include "opt_kbdmux.h" @@ -64,6 +65,11 @@ #include <dev/kbd/kbdtables.h> +#ifdef EVDEV_SUPPORT +#include <dev/evdev/evdev.h> +#include <dev/evdev/input.h> +#endif + #define KEYBOARD_NAME "kbdmux" MALLOC_DECLARE(M_KBDMUX); @@ -159,6 +165,11 @@ struct kbdmux_state u_int ks_composed_char; /* composed char code */ u_char ks_prefix; /* AT scan code prefix */ +#ifdef EVDEV_SUPPORT + struct evdev_dev * ks_evdev; + int ks_evdev_state; +#endif + SLIST_HEAD(, kbdmux_kbd) ks_kbds; /* keyboards */ KBDMUX_LOCK_DECL_GLOBAL; @@ -371,6 +382,12 @@ static keyboard_switch_t kbdmuxsw = { .diag = genkbd_diag, }; +#ifdef EVDEV_SUPPORT +static const struct evdev_methods kbdmux_evdev_methods = { + .ev_event = evdev_ev_kbd_event, +}; +#endif + /* * Return the number of found keyboards */ @@ -404,6 +421,10 @@ kbdmux_init(int unit, keyboard_t **kbdp, void *arg, int flags) accentmap_t *accmap = NULL; fkeytab_t *fkeymap = NULL; int error, needfree, fkeymap_size, delay[2]; +#ifdef EVDEV_SUPPORT + struct evdev_dev *evdev; + char phys_loc[NAMELEN]; +#endif if (*kbdp == NULL) { *kbdp = kbd = malloc(sizeof(*kbd), M_KBDMUX, M_NOWAIT | M_ZERO); @@ -464,6 +485,30 @@ kbdmux_init(int unit, keyboard_t **kbdp, void *arg, int flags) delay[1] = kbd->kb_delay2; kbdmux_ioctl(kbd, KDSETREPEAT, (caddr_t)delay); +#ifdef EVDEV_SUPPORT + /* register as evdev provider */ + evdev = evdev_alloc(); + evdev_set_name(evdev, "System keyboard multiplexer"); + snprintf(phys_loc, NAMELEN, KEYBOARD_NAME"%d", unit); + evdev_set_phys(evdev, phys_loc); + evdev_set_id(evdev, BUS_VIRTUAL, 0, 0, 0); + evdev_set_methods(evdev, kbd, &kbdmux_evdev_methods); + evdev_support_event(evdev, EV_SYN); + evdev_support_event(evdev, EV_KEY); + evdev_support_event(evdev, EV_LED); + evdev_support_event(evdev, EV_REP); + evdev_support_all_known_keys(evdev); + evdev_support_led(evdev, LED_NUML); + evdev_support_led(evdev, LED_CAPSL); + evdev_support_led(evdev, LED_SCROLLL); + + if (evdev_register(evdev)) + evdev_free(evdev); + else + state->ks_evdev = evdev; + state->ks_evdev_state = 0; +#endif + KBD_INIT_DONE(kbd); } @@ -532,6 +577,10 @@ kbdmux_term(keyboard_t *kbd) kbd_unregister(kbd); +#ifdef EVDEV_SUPPORT + evdev_free(state->ks_evdev); +#endif + KBDMUX_LOCK_DESTROY(state); bzero(state, sizeof(*state)); free(state, M_KBDMUX); @@ -694,6 +743,20 @@ next_code: kbd->kb_count ++; +#ifdef EVDEV_SUPPORT + /* push evdev event */ + if (evdev_rcpt_mask & EVDEV_RCPT_KBDMUX && state->ks_evdev != NULL) { + uint16_t key = evdev_scancode2key(&state->ks_evdev_state, + scancode); + + if (key != KEY_RESERVED) { + evdev_push_event(state->ks_evdev, EV_KEY, + key, scancode & 0x80 ? 0 : 1); + evdev_sync(state->ks_evdev); + } + } +#endif + /* return the byte as is for the K_RAW mode */ if (state->ks_mode == K_RAW) { KBDMUX_UNLOCK(state); @@ -1120,7 +1183,11 @@ kbdmux_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg) } KBD_LED_VAL(kbd) = *(int *)arg; - +#ifdef EVDEV_SUPPORT + if (state->ks_evdev != NULL && + evdev_rcpt_mask & EVDEV_RCPT_KBDMUX) + evdev_push_leds(state->ks_evdev, *(int *)arg); +#endif /* KDSETLED on all slave keyboards */ SLIST_FOREACH(k, &state->ks_kbds, next) (void)kbdd_ioctl(k->kbd, KDSETLED, arg); @@ -1197,7 +1264,11 @@ kbdmux_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg) kbd->kb_delay1 = delays[(mode >> 5) & 3]; kbd->kb_delay2 = rates[mode & 0x1f]; - +#ifdef EVDEV_SUPPORT + if (state->ks_evdev != NULL && + evdev_rcpt_mask & EVDEV_RCPT_KBDMUX) + evdev_push_repeats(state->ks_evdev, kbd); +#endif /* perform command on all slave keyboards */ SLIST_FOREACH(k, &state->ks_kbds, next) (void)kbdd_ioctl(k->kbd, cmd, arg); @@ -1395,4 +1466,6 @@ kbdmux_modevent(module_t mod, int type, void *data) } DEV_MODULE(kbdmux, kbdmux_modevent, NULL); - +#ifdef EVDEV_SUPPORT +MODULE_DEPEND(kbdmux, evdev, 1, 1, 1); +#endif |