summaryrefslogtreecommitdiffstats
path: root/sys/dev/kbdmux
diff options
context:
space:
mode:
authorgonzo <gonzo@FreeBSD.org>2016-12-03 17:40:26 +0000
committergonzo <gonzo@FreeBSD.org>2016-12-03 17:40:26 +0000
commit76a9d7a96992c3bfcb08ce5c14768c44cd943fc1 (patch)
treea4dde85c32fb09aea51c531262a23d1d5f304055 /sys/dev/kbdmux
parent1e91a5a4ca7106dc7a754883d2f4369a5e63c193 (diff)
downloadFreeBSD-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.c79
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
OpenPOWER on IntegriCloud