diff options
-rw-r--r-- | UPDATING | 7 | ||||
-rw-r--r-- | share/man/man4/psm.4 | 6 | ||||
-rw-r--r-- | sys/dev/atkbdc/psm.c | 60 | ||||
-rw-r--r-- | sys/sys/param.h | 2 |
4 files changed, 65 insertions, 10 deletions
@@ -22,6 +22,13 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 8.x IS SLOW: to maximize performance. (To disable malloc debugging, run ln -s aj /etc/malloc.conf.) +20080408: + psm(4) has gained write(2) support in native operation level. + Arbitrary commands can be written to /dev/psm%d and status can + be read back from it. Therefore, an application is responsible + for status validation and error recovery. It is a no-op in + other operation levels. + 20080312: Support for KSE threading has been removed from the kernel. To run legacy applications linked against KSE libmap.conf may diff --git a/share/man/man4/psm.4 b/share/man/man4/psm.4 index 39ae333..01cbd9c 100644 --- a/share/man/man4/psm.4 +++ b/share/man/man4/psm.4 @@ -26,7 +26,7 @@ .\" .\" $FreeBSD$ .\" -.Dd September 29, 2004 +.Dd April 8, 2008 .Dt PSM 4 .Os .Sh NAME @@ -110,7 +110,9 @@ The movement of the roller is reported as movement along the Z axis. 8 byte data packets are sent to the user program at this level. .Pp At the operation level two, data from the pointing device is passed to the -user program as is. +user program as is. Conversely, command from the user program is passed +to the pointing device as is and the user program is responsible for +status validation and error recovery. Modern PS/2 type pointing devices often use proprietary data format. Therefore, the user program is expected to have intimate knowledge about the format from a particular device when operating diff --git a/sys/dev/atkbdc/psm.c b/sys/dev/atkbdc/psm.c index 4db8e2f..b4b27a2 100644 --- a/sys/dev/atkbdc/psm.c +++ b/sys/dev/atkbdc/psm.c @@ -290,6 +290,7 @@ static int psmresume(device_t); static d_open_t psmopen; static d_close_t psmclose; static d_read_t psmread; +static d_write_t psmwrite; static d_ioctl_t psmioctl; static d_poll_t psmpoll; @@ -397,6 +398,7 @@ static struct cdevsw psm_cdevsw = { .d_open = psmopen, .d_close = psmclose, .d_read = psmread, + .d_write = psmwrite, .d_ioctl = psmioctl, .d_poll = psmpoll, .d_name = PSM_DRIVER_NAME, @@ -1711,6 +1713,37 @@ unblock_mouse_data(struct psm_softc *sc, int c) } static int +psmwrite(struct cdev *dev, struct uio *uio, int flag) +{ + register struct psm_softc *sc = PSM_SOFTC(PSM_UNIT(dev)); + u_char buf[PSM_SMALLBUFSIZE]; + int error = 0, i, l; + + if ((sc->state & PSM_VALID) == 0) + return (EIO); + + if (sc->mode.level < PSM_LEVEL_NATIVE) + return (ENODEV); + + /* copy data from the user land */ + while (uio->uio_resid > 0) { + l = imin(PSM_SMALLBUFSIZE, uio->uio_resid); + error = uiomove(buf, l, uio); + if (error) + break; + for (i = 0; i < l; i++) { + VLOG(4, (LOG_DEBUG, "psm: cmd 0x%x\n", buf[i])); + if (!write_aux_command(sc->kbdc, buf[i])) { + VLOG(2, (LOG_DEBUG, "psm: cmd 0x%x failed.\n", buf[i])); + return (reinitialize(sc, FALSE)); + } + } + } + + return (error); +} + +static int psmioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td) { struct psm_softc *sc = PSM_SOFTC(PSM_UNIT(dev)); @@ -2092,12 +2125,20 @@ psmintr(void *arg) timevaladd(&sc->inputtimeout, &now); pb->ipacket[pb->inputbytes++] = c; - if (pb->inputbytes < sc->mode.packetsize) - continue; - VLOG(4, (LOG_DEBUG, "psmintr: %02x %02x %02x %02x %02x %02x\n", - pb->ipacket[0], pb->ipacket[1], pb->ipacket[2], - pb->ipacket[3], pb->ipacket[4], pb->ipacket[5])); + if (sc->mode.level == PSM_LEVEL_NATIVE) { + VLOG(4, (LOG_DEBUG, "psmintr: %02x\n", pb->ipacket[0])); + sc->syncerrors = 0; + sc->pkterrors = 0; + goto NEXT; + } else { + if (pb->inputbytes < sc->mode.packetsize) + continue; + + VLOG(4, (LOG_DEBUG, "psmintr: %02x %02x %02x %02x %02x %02x\n", + pb->ipacket[0], pb->ipacket[1], pb->ipacket[2], + pb->ipacket[3], pb->ipacket[4], pb->ipacket[5])); + } c = pb->ipacket[0]; @@ -2180,6 +2221,7 @@ psmintr(void *arg) sc->pkterrors = 0; sc->cmdcount++; +NEXT: if (++sc->pqueue_end >= PSM_PACKETQUEUE) sc->pqueue_end = 0; /* @@ -2246,6 +2288,10 @@ psmsoftintr(void *arg) do { pb = &sc->pqueue[sc->pqueue_start]; + + if (sc->mode.level == PSM_LEVEL_NATIVE) + goto NEXT_NATIVE; + c = pb->ipacket[0]; /* * A kludge for Kensington device! @@ -2806,8 +2852,7 @@ psmsoftintr(void *arg) ms.flags = ((x || y || z) ? MOUSE_POSCHANGED : 0) | (ms.obutton ^ ms.button); - if (sc->mode.level < PSM_LEVEL_NATIVE) - pb->inputbytes = tame_mouse(sc, pb, &ms, pb->ipacket); + pb->inputbytes = tame_mouse(sc, pb, &ms, pb->ipacket); sc->status.flags |= ms.flags; sc->status.dx += ms.dx; @@ -2816,6 +2861,7 @@ psmsoftintr(void *arg) sc->status.button = ms.button; sc->button = ms.button; +NEXT_NATIVE: sc->watchdog = FALSE; /* queue data */ diff --git a/sys/sys/param.h b/sys/sys/param.h index 8389bfa..6a82581 100644 --- a/sys/sys/param.h +++ b/sys/sys/param.h @@ -57,7 +57,7 @@ * is created, otherwise 1. */ #undef __FreeBSD_version -#define __FreeBSD_version 800032 /* Master, propagated to newvers */ +#define __FreeBSD_version 800033 /* Master, propagated to newvers */ #ifndef LOCORE #include <sys/types.h> |