summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjkim <jkim@FreeBSD.org>2008-04-08 17:55:26 +0000
committerjkim <jkim@FreeBSD.org>2008-04-08 17:55:26 +0000
commite9e1875fbf3d6d229e50e6020f407677e79706c4 (patch)
treeda9835390a68539c2f7d1d9e7e9991898cff6a76
parent7979f5eff2d34bce4b109e6b3468d2150de74b5e (diff)
downloadFreeBSD-src-e9e1875fbf3d6d229e50e6020f407677e79706c4.zip
FreeBSD-src-e9e1875fbf3d6d229e50e6020f407677e79706c4.tar.gz
- Add write(2) support for psm(4) in native operation level. Now arbitrary
commands can be written to /dev/psm%d and status can be read back from it. - Reflect the change in psm(4) and bump version for ports. MFC after: 1 week
-rw-r--r--UPDATING7
-rw-r--r--share/man/man4/psm.46
-rw-r--r--sys/dev/atkbdc/psm.c60
-rw-r--r--sys/sys/param.h2
4 files changed, 65 insertions, 10 deletions
diff --git a/UPDATING b/UPDATING
index dd68913..173d73e 100644
--- a/UPDATING
+++ b/UPDATING
@@ -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>
OpenPOWER on IntegriCloud