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>