svn commit: r268668 - in user/jceel/soc2014_evdev/head/sys/dev: atkbdc kbdmux
Jakub Wojciech Klama
jceel at FreeBSD.org
Tue Jul 15 10:39:15 UTC 2014
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);
More information about the svn-src-user
mailing list