Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 15 Jul 2014 10:39:14 +0000 (UTC)
From:      Jakub Wojciech Klama <jceel@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-user@freebsd.org
Subject:   svn commit: r268668 - in user/jceel/soc2014_evdev/head/sys/dev: atkbdc kbdmux
Message-ID:  <201407151039.s6FAdEgL085433@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jceel
Date: Tue Jul 15 10:39:14 2014
New Revision: 268668
URL: http://svnweb.freebsd.org/changeset/base/268668

Log:
  Add evdev support for AT keyboards, PS/2 mices and keyboard mutiplexer.

Modified:
  user/jceel/soc2014_evdev/head/sys/dev/atkbdc/atkbd.c
  user/jceel/soc2014_evdev/head/sys/dev/atkbdc/psm.c
  user/jceel/soc2014_evdev/head/sys/dev/kbdmux/kbdmux.c

Modified: user/jceel/soc2014_evdev/head/sys/dev/atkbdc/atkbd.c
==============================================================================
--- user/jceel/soc2014_evdev/head/sys/dev/atkbdc/atkbd.c	Tue Jul 15 10:38:22 2014	(r268667)
+++ user/jceel/soc2014_evdev/head/sys/dev/atkbdc/atkbd.c	Tue Jul 15 10:39:14 2014	(r268668)
@@ -31,6 +31,7 @@ __FBSDID("$FreeBSD$");
 #include "opt_compat.h"
 #include "opt_kbd.h"
 #include "opt_atkbd.h"
+#include "opt_evdev.h"
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -62,14 +63,26 @@ __FBSDID("$FreeBSD$");
 #include <dev/atkbdc/atkbdreg.h>
 #include <dev/atkbdc/atkbdcreg.h>
 
+#ifdef EVDEV
+#include <dev/evdev/evdev.h>
+#include <dev/evdev/input.h>
+#endif
+
 static timeout_t	atkbd_timeout;
 static void		atkbd_shutdown_final(void *v);
 
+struct atkbd_args
+{
+	int unit;
+	int irq;
+	device_t dev;
+};
+
 int
 atkbd_probe_unit(device_t dev, int irq, int flags)
 {
 	keyboard_switch_t *sw;
-	int args[2];
+	int args[3];
 	int error;
 
 	sw = kbd_get_switch(ATKBD_DRIVER_NAME);
@@ -78,6 +91,7 @@ atkbd_probe_unit(device_t dev, int irq, 
 
 	args[0] = device_get_unit(device_get_parent(dev));
 	args[1] = irq;
+	args[2] = (int)dev;
 	error = (*sw->probe)(device_get_unit(dev), args, flags);
 	if (error)
 		return error;
@@ -88,7 +102,7 @@ int
 atkbd_attach_unit(device_t dev, keyboard_t **kbd, int irq, int flags)
 {
 	keyboard_switch_t *sw;
-	int args[2];
+	struct atkbd_args args;
 	int error;
 	int unit;
 
@@ -98,13 +112,14 @@ atkbd_attach_unit(device_t dev, keyboard
 
 	/* reset, initialize and enable the device */
 	unit = device_get_unit(dev);
-	args[0] = device_get_unit(device_get_parent(dev));
-	args[1] = irq;
+	args.unit = device_get_unit(device_get_parent(dev));
+	args.irq = irq;
+	args.dev = dev;
 	*kbd = NULL;
-	error = (*sw->probe)(unit, args, flags);
+	error = (*sw->probe)(unit, &args, flags);
 	if (error)
 		return error;
-	error = (*sw->init)(unit, kbd, args, flags);
+	error = (*sw->init)(unit, kbd, &args, flags);
 	if (error)
 		return error;
 	(*sw->enable)(*kbd);
@@ -192,6 +207,11 @@ typedef struct atkbd_state {
 	int		ks_accents;	/* accent key index (> 0) */
 	u_int		ks_composed_char; /* composed char code (> 0) */
 	u_char		ks_prefix;	/* AT scan code prefix */
+#ifdef EVDEV
+	struct evdev_dev *ks_evdev;
+	bool		ks_evdev_opened;
+	int		ks_evdev_state;
+#endif
 } atkbd_state_t;
 
 /* keyboard driver declaration */
@@ -250,6 +270,16 @@ static int		typematic(int delay, int rat
 static int		typematic_delay(int delay);
 static int		typematic_rate(int rate);
 
+#ifdef EVDEV
+static int		atkbd_ev_open(struct evdev_dev *, void *);
+static void		atkbd_ev_close(struct evdev_dev *, void *);
+
+struct evdev_methods atkbd_evdev_methods = {
+	.ev_open = atkbd_ev_open,
+	.ev_close = atkbd_ev_close,
+};
+#endif
+
 /* local variables */
 
 /* the initial key map, accent map and fkey strings */
@@ -279,7 +309,7 @@ static int
 atkbd_configure(int flags)
 {
 	keyboard_t *kbd;
-	int arg[2];
+	struct atkbd_args args;
 	int i;
 
 	/*
@@ -302,12 +332,13 @@ atkbd_configure(int flags)
 		flags |= i;
 
 	/* probe the default keyboard */
-	arg[0] = -1;
-	arg[1] = -1;
+	args.unit = -1;
+	args.irq = -1;
+	args.dev = NULL;
 	kbd = NULL;
-	if (atkbd_probe(ATKBD_DEFAULT, arg, flags))
+	if (atkbd_probe(ATKBD_DEFAULT, &args, flags))
 		return 0;
-	if (atkbd_init(ATKBD_DEFAULT, &kbd, arg, flags))
+	if (atkbd_init(ATKBD_DEFAULT, &kbd, &args, flags))
 		return 0;
 
 	/* return the number of found keyboards */
@@ -321,7 +352,7 @@ static int
 atkbd_probe(int unit, void *arg, int flags)
 {
 	KBDC kbdc;
-	int *data = (int *)arg;	/* data[0]: controller, data[1]: irq */
+	struct atkbd_args *data = (struct atkbd_args *)arg;
 
 	/* XXX */
 	if (unit == ATKBD_DEFAULT) {
@@ -329,7 +360,7 @@ atkbd_probe(int unit, void *arg, int fla
 			return 0;
 	}
 
-	kbdc = atkbdc_open(data[0]);
+	kbdc = atkbdc_open(data->unit);
 	if (kbdc == NULL)
 		return ENXIO;
 	if (probe_keyboard(kbdc, flags)) {
@@ -348,10 +379,15 @@ atkbd_init(int unit, keyboard_t **kbdp, 
 	keymap_t *keymap;
 	accentmap_t *accmap;
 	fkeytab_t *fkeymap;
+	struct atkbd_args *data = (struct atkbd_args *)arg;
 	int fkeymap_size;
 	int delay[2];
-	int *data = (int *)arg;	/* data[0]: controller, data[1]: irq */
 	int error, needfree;
+#ifdef EVDEV
+	struct evdev_dev *evdev;
+	int i;
+	device_t dev = data->dev;
+#endif
 
 	/* XXX */
 	if (unit == ATKBD_DEFAULT) {
@@ -393,7 +429,7 @@ atkbd_init(int unit, keyboard_t **kbdp, 
 	}
 
 	if (!KBD_IS_PROBED(kbd)) {
-		state->kbdc = atkbdc_open(data[0]);
+		state->kbdc = atkbdc_open(data->unit);
 		if (state->kbdc == NULL) {
 			error = ENXIO;
 			goto bad;
@@ -437,6 +473,27 @@ atkbd_init(int unit, keyboard_t **kbdp, 
 		delay[0] = kbd->kb_delay1;
 		delay[1] = kbd->kb_delay2;
 		atkbd_ioctl(kbd, KDSETREPEAT, (caddr_t)delay);
+
+#ifdef EVDEV
+		/* register as evdev provider */
+		if (dev != NULL) {
+			evdev = evdev_alloc();
+			evdev_set_name(evdev, device_get_desc(dev));
+			evdev_set_serial(evdev, "0");
+			evdev_set_methods(evdev, &atkbd_evdev_methods);
+			evdev_set_softc(evdev, state);
+			evdev_support_event(evdev, EV_SYN);
+			evdev_support_event(evdev, EV_KEY);
+
+			for (i = KEY_RESERVED; i <= KEY_KPDOT; i++)
+				evdev_support_key(evdev, i);
+
+			evdev_register(dev, evdev);
+			state->ks_evdev = evdev;
+			state->ks_evdev_state = 0;
+		}
+#endif
+
 		KBD_INIT_DONE(kbd);
 	}
 	if (!KBD_IS_CONFIGURED(kbd)) {
@@ -444,6 +501,7 @@ atkbd_init(int unit, keyboard_t **kbdp, 
 			error = ENXIO;
 			goto bad;
 		}
+
 		KBD_CONFIG_DONE(kbd);
 	}
 
@@ -618,6 +676,20 @@ next_code:
 	printf("atkbd_read_char(): scancode:0x%x\n", scancode);
 #endif
 
+#ifdef EVDEV
+	/* push evdev event */
+	if (state->ks_evdev != NULL && state->ks_evdev_opened) {
+		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)
 		return scancode;
@@ -767,7 +839,7 @@ next_code:
 			break;
 		}
 	}
-
+	
 	/* return the key code in the K_CODE mode */
 	if (state->ks_mode == K_CODE)
 		return (keycode | (scancode & 0x80));
@@ -997,6 +1069,25 @@ atkbd_ioctl(keyboard_t *kbd, u_long cmd,
 	return 0;
 }
 
+#ifdef EVDEV
+static int
+atkbd_ev_open(struct evdev_dev *evdev, void *softc)
+{
+ 	struct atkbd_state *state = (struct atkbd_state *)softc;
+
+	state->ks_evdev_opened = true;
+	return (0);
+}
+
+static void
+atkbd_ev_close(struct evdev_dev *evdev, void *softc)
+{
+	struct atkbd_state *state = (struct atkbd_state *)softc;
+
+	state->ks_evdev_opened = false;
+}
+#endif /* EVDEV */
+
 /* lock the access to the keyboard */
 static int
 atkbd_lock(keyboard_t *kbd, int lock)

Modified: user/jceel/soc2014_evdev/head/sys/dev/atkbdc/psm.c
==============================================================================
--- user/jceel/soc2014_evdev/head/sys/dev/atkbdc/psm.c	Tue Jul 15 10:38:22 2014	(r268667)
+++ user/jceel/soc2014_evdev/head/sys/dev/atkbdc/psm.c	Tue Jul 15 10:39:14 2014	(r268668)
@@ -63,6 +63,7 @@ __FBSDID("$FreeBSD$");
 
 #include "opt_isa.h"
 #include "opt_psm.h"
+#include "opt_evdev.h"
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -90,6 +91,11 @@ __FBSDID("$FreeBSD$");
 #include <isa/isavar.h>
 #endif
 
+#ifdef EVDEV
+#include <dev/evdev/evdev.h>
+#include <dev/evdev/input.h>
+#endif
+
 #include <dev/atkbdc/atkbdcreg.h>
 #include <dev/atkbdc/psm.h>
 
@@ -336,6 +342,7 @@ struct psm_softc {		/* Driver status inf
 	int		lasterr;
 	int		cmdcount;
 	struct sigio	*async;		/* Processes waiting for SIGIO */
+	struct evdev_dev *evdev;
 };
 static devclass_t psm_devclass;
 
@@ -345,6 +352,7 @@ static devclass_t psm_devclass;
 #define	PSM_ASLP		2	/* Waiting for mouse data */
 #define	PSM_SOFTARMED		4	/* Software interrupt armed */
 #define	PSM_NEED_SYNCBITS	8	/* Set syncbits using next data pkt */
+#define	PSM_EV_OPEN		16
 
 /* driver configuration flags (config) */
 #define	PSM_CONFIG_RESOLUTION	0x000f	/* resolution */
@@ -414,13 +422,21 @@ static int	psmattach(device_t);
 static int	psmdetach(device_t);
 static int	psmresume(device_t);
 
-static d_open_t		psmopen;
-static d_close_t	psmclose;
+static d_open_t		psm_cdev_open;
+static d_close_t	psm_cdev_close;
 static d_read_t		psmread;
 static d_write_t	psmwrite;
 static d_ioctl_t	psmioctl;
 static d_poll_t		psmpoll;
 
+static int	psmopen(struct psm_softc *);
+static int	psmclose(struct psm_softc *);
+
+#ifdef EVDEV
+static evdev_open_t	psm_ev_open;
+static evdev_close_t	psm_ev_close;
+#endif
+
 static int	enable_aux_dev(KBDC);
 static int	disable_aux_dev(KBDC);
 static int	get_mouse_status(KBDC, int *, int, int);
@@ -533,8 +549,8 @@ static driver_t psm_driver = {
 static struct cdevsw psm_cdevsw = {
 	.d_version =	D_VERSION,
 	.d_flags =	D_NEEDGIANT,
-	.d_open =	psmopen,
-	.d_close =	psmclose,
+	.d_open =	psm_cdev_open,
+	.d_close =	psm_cdev_close,
 	.d_read =	psmread,
 	.d_write =	psmwrite,
 	.d_ioctl =	psmioctl,
@@ -542,6 +558,24 @@ static struct cdevsw psm_cdevsw = {
 	.d_name =	PSM_DRIVER_NAME,
 };
 
+#ifdef EVDEV
+static struct evdev_methods psm_ev_methods = {
+	.ev_open = &psm_ev_open,
+	.ev_close = &psm_ev_close,
+};
+
+static uint16_t evdev_btnmap[] = {
+	BTN_LEFT,
+	BTN_MIDDLE,
+	BTN_RIGHT,
+	BTN_SIDE,
+	BTN_EXTRA,
+	BTN_FORWARD,
+	BTN_BACK,
+	BTN_TASK,
+};
+#endif
+
 /* device I/O routines */
 static int
 enable_aux_dev(KBDC kbdc)
@@ -1461,6 +1495,9 @@ psmattach(device_t dev)
 	struct psm_softc *sc = device_get_softc(dev);
 	int error;
 	int rid;
+#ifdef EVDEV
+	int i;
+#endif
 
 	/* Setup initial state */
 	sc->state = PSM_VALID;
@@ -1485,6 +1522,26 @@ psmattach(device_t dev)
 	sc->bdev = make_dev(&psm_cdevsw, 0, 0, 0, 0666, "bpsm%d", unit);
 	sc->bdev->si_drv1 = sc;
 
+#ifdef EVDEV
+	sc->evdev = evdev_alloc();
+	evdev_set_name(sc->evdev, model_name(sc->hw.model));
+	evdev_set_serial(sc->evdev, "0");
+	evdev_set_softc(sc->evdev, sc);
+	evdev_set_methods(sc->evdev, &psm_ev_methods);
+	evdev_support_event(sc->evdev, EV_SYN);
+	evdev_support_event(sc->evdev, EV_REL);
+	evdev_support_event(sc->evdev, EV_KEY);
+	evdev_support_rel(sc->evdev, REL_X);
+	evdev_support_rel(sc->evdev, REL_Y);
+
+	for (i = 0; i < sc->hw.buttons; i++)
+		evdev_support_key(sc->evdev, BTN_MOUSE + i);
+
+	error = evdev_register(dev, sc->evdev);
+	if (error)
+		return (error);
+#endif
+
 	/* Some touchpad devices need full reinitialization after suspend. */
 	switch (sc->hw.model) {
 	case MOUSE_MODEL_SYNAPTICS:
@@ -1524,7 +1581,7 @@ psmdetach(device_t dev)
 	int rid;
 
 	sc = device_get_softc(dev);
-	if (sc->state & PSM_OPEN)
+	if (sc->state & (PSM_OPEN | PSM_EV_OPEN))
 		return (EBUSY);
 
 	rid = KBDC_RID_AUX;
@@ -1540,13 +1597,41 @@ psmdetach(device_t dev)
 	return (0);
 }
 
+#ifdef EVDEV
 static int
-psmopen(struct cdev *dev, int flag, int fmt, struct thread *td)
+psm_ev_open(struct evdev_dev *evdev, void *ev_softc)
+{
+	struct psm_softc *sc = (struct psm_softc *)ev_softc;
+
+	printf("psm_ev_open()\n");
+
+	sc->state |= PSM_EV_OPEN;
+
+	if (sc->state & PSM_OPEN)
+		return (0);
+
+	return (psmopen(sc));
+}
+
+static void
+psm_ev_close(struct evdev_dev *evdev, void *ev_softc)
+{
+	struct psm_softc *sc = (struct psm_softc *)ev_softc;
+
+	sc->state &= ~PSM_EV_OPEN;
+
+	if (sc->state & PSM_OPEN)
+		return;
+
+	psmclose(sc);
+}
+#endif
+
+static int
+psm_cdev_open(struct cdev *dev, int flag, int fmt, struct thread *td)
 {
 	struct psm_softc *sc;
-	int command_byte;
 	int err;
-	int s;
 
 	/* Get device data */
 	sc = dev->si_drv1;
@@ -1559,6 +1644,52 @@ psmopen(struct cdev *dev, int flag, int 
 	if (sc->state & PSM_OPEN)
 		return (EBUSY);
 
+#ifdef EVDEV
+	/* Already opened by evdev */
+	if (sc->state & PSM_EV_OPEN)
+		return (0);
+#endif
+
+	err = psmopen(sc);
+	if (err == 0)
+		sc->state |= PSM_OPEN;
+
+	return (err);
+}
+
+static int
+psm_cdev_close(struct cdev *dev, int flag, int fmt, struct thread *td)
+{
+	struct psm_softc *sc;
+	int err;
+
+	/* Get device data */
+	sc = dev->si_drv1;
+	if ((sc == NULL) || (sc->state & PSM_VALID) == 0) {
+		/* the device is no longer valid/functioning */
+		return (ENXIO);
+	}
+
+#ifdef EVDEV
+	/* Still opened by evdev */
+	if (sc->state & PSM_EV_OPEN)
+		return (0);
+#endif
+
+	err = psmclose(sc);
+	if (err == 0)
+		sc->state &= ~PSM_OPEN;
+
+	return (err);
+}
+
+static int
+psmopen(struct psm_softc *sc)
+{
+	int command_byte;
+	int err;
+	int s;
+
 	device_busy(devclass_get_device(psm_devclass, sc->unit));
 
 	/* Initialize state */
@@ -1619,17 +1750,13 @@ psmopen(struct cdev *dev, int flag, int 
 	/* enable the mouse device */
 	err = doopen(sc, command_byte);
 
-	/* done */
-	if (err == 0)
-		sc->state |= PSM_OPEN;
 	kbdc_lock(sc->kbdc, FALSE);
 	return (err);
 }
 
 static int
-psmclose(struct cdev *dev, int flag, int fmt, struct thread *td)
+psmclose(struct psm_softc *sc)
 {
-	struct psm_softc *sc = dev->si_drv1;
 	int stat[3];
 	int command_byte;
 	int s;
@@ -1713,7 +1840,6 @@ psmclose(struct cdev *dev, int flag, int
 	}
 
 	/* close is almost always successful */
-	sc->state &= ~PSM_OPEN;
 	kbdc_lock(sc->kbdc, FALSE);
 	device_unbusy(devclass_get_device(psm_devclass, sc->unit));
 	return (0);
@@ -2356,7 +2482,7 @@ psmintr(void *arg)
 		pb = &sc->pqueue[sc->pqueue_end];
 
 		/* discard the byte if the device is not open */
-		if ((sc->state & PSM_OPEN) == 0)
+		if ((sc->state & (PSM_OPEN | PSM_EV_OPEN)) == 0)
 			continue;
 
 		getmicrouptime(&now);
@@ -3537,6 +3663,31 @@ psmsoftintr(void *arg)
 		}
 	}
 
+#ifdef EVDEV
+	if (sc->flags & PSM_EV_OPEN) {
+		if (x != 0 || y != 0) {
+			evdev_push_event(sc->evdev, EV_REL, REL_X, x);
+			evdev_push_event(sc->evdev, EV_REL, REL_Y, y);
+		}
+
+		if (ms.obutton ^ ms.button) {
+			int i;
+
+			for (i = 0; i < 8; i++) {
+				if (((ms.button & (1 << i)) ^
+				    (ms.obutton & (1 << i))) == 0)
+					continue;
+
+				evdev_push_event(sc->evdev, EV_KEY,
+				    evdev_btnmap[i], !!(ms.button & (1 << i)));
+
+			}
+		}
+
+		evdev_sync(sc->evdev);
+	}
+#endif
+
 	ms.dx = x;
 	ms.dy = y;
 	ms.dz = z;

Modified: user/jceel/soc2014_evdev/head/sys/dev/kbdmux/kbdmux.c
==============================================================================
--- user/jceel/soc2014_evdev/head/sys/dev/kbdmux/kbdmux.c	Tue Jul 15 10:38:22 2014	(r268667)
+++ user/jceel/soc2014_evdev/head/sys/dev/kbdmux/kbdmux.c	Tue Jul 15 10:39:14 2014	(r268668)
@@ -33,6 +33,7 @@
 
 #include "opt_compat.h"
 #include "opt_kbd.h"
+#include "opt_evdev.h"
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -56,6 +57,11 @@
 #include <dev/kbd/kbdreg.h>
 #include <dev/kbd/kbdtables.h>
 
+#ifdef EVDEV
+#include <dev/evdev/evdev.h>
+#include <dev/evdev/input.h>
+#endif
+
 #define KEYBOARD_NAME	"kbdmux"
 
 MALLOC_DECLARE(M_KBDMUX);
@@ -151,6 +157,12 @@ struct kbdmux_state
 	u_int			 ks_composed_char; /* composed char code */
 	u_char			 ks_prefix;	/* AT scan code prefix */
 
+#ifdef EVDEV
+	struct evdev_dev *	 ks_evdev;
+	bool			 ks_evdev_opened;
+	int			 ks_evdev_state;
+#endif
+
 	SLIST_HEAD(, kbdmux_kbd) ks_kbds;	/* keyboards */
 
 	KBDMUX_LOCK_DECL_GLOBAL;
@@ -363,6 +375,33 @@ static keyboard_switch_t kbdmuxsw = {
 	.diag =		genkbd_diag,
 };
 
+#ifdef EVDEV
+static int kbdmux_ev_open(struct evdev_dev *, void *);
+static void kbdmux_ev_close(struct evdev_dev *, void *);
+
+struct evdev_methods kbdmux_evdev_methods = {
+	.ev_open = kbdmux_ev_open,
+	.ev_close = kbdmux_ev_close,
+};
+
+static int
+kbdmux_ev_open(struct evdev_dev *evdev, void *softc)
+{
+ 	struct kbdmux_state *state = (struct kbdmux_state *)softc;
+
+	state->ks_evdev_opened = true;
+	return (0);
+}
+
+static void
+kbdmux_ev_close(struct evdev_dev *evdev, void *softc)
+{
+	struct kbdmux_state *state = (struct kbdmux_state *)softc;
+
+	state->ks_evdev_opened = false;
+}
+#endif
+
 /*
  * Return the number of found keyboards
  */
@@ -396,6 +435,10 @@ kbdmux_init(int unit, keyboard_t **kbdp,
         accentmap_t	*accmap = NULL;
         fkeytab_t	*fkeymap = NULL;
 	int		 error, needfree, fkeymap_size, delay[2];
+#ifdef EVDEV
+	struct evdev_dev *evdev;
+	int i;
+#endif
 
 	if (*kbdp == NULL) {
 		*kbdp = kbd = malloc(sizeof(*kbd), M_KBDMUX, M_NOWAIT | M_ZERO);
@@ -456,6 +499,25 @@ kbdmux_init(int unit, keyboard_t **kbdp,
 		delay[1] = kbd->kb_delay2;
 		kbdmux_ioctl(kbd, KDSETREPEAT, (caddr_t)delay);
 
+#ifdef EVDEV
+		/* register as evdev provider */
+		evdev = evdev_alloc();
+		evdev_set_name(evdev, "System keyboard multiplexer");
+		evdev_set_phys(evdev, KEYBOARD_NAME);
+		evdev_set_serial(evdev, "0");
+		evdev_set_methods(evdev, &kbdmux_evdev_methods);
+		evdev_set_softc(evdev, state);
+		evdev_support_event(evdev, EV_SYN);
+		evdev_support_event(evdev, EV_KEY);
+
+		for (i = KEY_RESERVED; i <= KEY_KPDOT; i++)
+			evdev_support_key(evdev, i);
+
+		evdev_register(NULL, evdev);
+		state->ks_evdev = evdev;
+		state->ks_evdev_state = 0;
+#endif
+
 		KBD_INIT_DONE(kbd);
 	}
 
@@ -686,6 +748,20 @@ next_code:
 
 	kbd->kb_count ++;
 
+#ifdef EVDEV
+	/* push evdev event */
+	if (state->ks_evdev != NULL && state->ks_evdev_opened) {
+		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);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201407151039.s6FAdEgL085433>