On Mon, Sep 27, 2010 at 11:42:35PM +0600, Alexandr Shadchin wrote:
> On Fri, Sep 24, 2010 at 05:40:37PM +0400, Alexandr Shadchin wrote:
> > Hi!
> >
> > Paul Irofti proposed to split the diff in a few easy steps.
> > Step 1 - merge drivers pms and pmsi.
> >
>
> Step 2 - cleanup, standardization of interfaces and preparation
> for easy addition of new devices. Now the resume of work in polling mode.
>
Regen for -current. Also small improvements:
1) add function pms_dev_reset()
2) in struct pms_protocol add function sync() - for check synchronization,
proc () - for processing packet.
--
Alexandr Shadchin
Index: pms.c
===================================================================
RCS file: /cvs/src/sys/dev/pckbc/pms.c,v
retrieving revision 1.5
diff -u -p -r1.5 pms.c
--- pms.c 27 Sep 2010 18:16:25 -0000 1.5
+++ pms.c 29 Sep 2010 14:41:51 -0000
@@ -38,41 +38,100 @@
#include <dev/wscons/wsconsio.h>
#include <dev/wscons/wsmousevar.h>
+#ifdef PMS_DEBUG
+#define DPRINTF(...) do { if (pmsdebug) printf(__VA_ARGS__); } while(0)
+#define DPRINTFN(n, ...) do { \
+ if (pmsdebug > (n)) printf(__VA_ARGS__); \
+} while(0)
+int pmsdebug = 1;
+#else
+#define DPRINTF(...)
+#define DPRINTFN(n, ...)
+#endif
+
+#define DEVNAME(sc) ((sc)->sc_dev.dv_xname)
+
+/* PS/2 mouse data packet */
+#define PMS_PS2_BUTTONSMASK 0x07
+#define PMS_PS2_BUTTON1 0x01 /* left */
+#define PMS_PS2_BUTTON2 0x04 /* middle */
+#define PMS_PS2_BUTTON3 0x02 /* right */
+#define PMS_PS2_XNEG 0x10
+#define PMS_PS2_YNEG 0x20
+
+#define PMS_BUTTON1DOWN 0x01 /* left */
+#define PMS_BUTTON2DOWN 0x02 /* middle */
+#define PMS_BUTTON3DOWN 0x04 /* right */
+
+struct pms_softc;
+
+struct pms_protocol {
+ int type;
+#define PMS_STANDARD 0
+#define PMS_INTELLI 1
+ int packetsize;
+ int syncmask;
+ int syncval;
+ int (*enable)(struct pms_softc *);
+ int (*sync)(struct pms_softc *, int);
+ void (*proc)(struct pms_softc *, int *, int *, int *, u_int *);
+};
+
struct pms_softc { /* driver status information */
struct device sc_dev;
pckbc_tag_t sc_kbctag;
int sc_kbcslot;
+ int poll;
int sc_state;
#define PMS_STATE_DISABLED 0
#define PMS_STATE_ENABLED 1
#define PMS_STATE_SUSPENDED 2
- int intelli;
+ struct pms_protocol protocol;
+ unsigned char packet[8];
+
int inputstate;
- u_int buttons, oldbuttons; /* mouse button status */
- signed char dx, dy;
+ u_int buttons; /* mouse button status */
struct device *sc_wsmousedev;
};
-int pmsprobe(struct device *, void *, void *);
-void pmsattach(struct device *, struct device *, void *);
-int pmsactivate(struct device *, int);
-void pmsinput(void *, int);
+int pmsprobe(struct device *, void *, void *);
+void pmsattach(struct device *, struct device *, void *);
+int pmsactivate(struct device *, int);
-struct cfattach pms_ca = {
- sizeof(struct pms_softc), pmsprobe, pmsattach, NULL,
- pmsactivate
-};
+void pmsinput(void *, int);
int pms_change_state(struct pms_softc *, int);
int pms_ioctl(void *, u_long, caddr_t, int, struct proc *);
int pms_enable(void *);
void pms_disable(void *);
-int pms_setintellimode(pckbc_tag_t, pckbc_slot_t);
+int pms_cmd(struct pms_softc *, u_char *, int, u_char *, int);
+int pms_get_devid(struct pms_softc *, u_char *);
+int pms_get_status(struct pms_softc *, u_char *);
+int pms_set_rate(struct pms_softc *, int);
+int pms_set_resolution(struct pms_softc *, int);
+int pms_set_scaling(struct pms_softc *, int);
+void pms_dev_reset(struct pms_softc *);
+void pms_dev_disable(struct pms_softc *);
+void pms_dev_enable(struct pms_softc *);
+
+int pms_enable_intelli(struct pms_softc *);
+
+int pms_sync_generic(struct pms_softc *, int);
+void pms_proc_generic(struct pms_softc *, int *, int *, int *, u_int *);
+
+struct cfattach pms_ca = {
+ sizeof(struct pms_softc), pmsprobe, pmsattach, NULL,
+ pmsactivate
+};
+
+struct cfdriver pms_cd = {
+ NULL, "pms", DV_DULL
+};
const struct wsmouse_accessops pms_accessops = {
pms_enable,
@@ -80,104 +139,54 @@ const struct wsmouse_accessops pms_acces
pms_disable,
};
-int
-pms_setintellimode(pckbc_tag_t tag, pckbc_slot_t slot)
-{
- u_char cmd[2], resp[1];
- int i, res;
- static const u_char rates[] = {200, 100, 80};
-
- cmd[0] = PMS_SET_SAMPLE;
- for (i = 0; i < 3; i++) {
- cmd[1] = rates[i];
- res = pckbc_enqueue_cmd(tag, slot, cmd, 2, 0, 0, NULL);
- if (res)
- return (0);
- }
-
- cmd[0] = PMS_SEND_DEV_ID;
- res = pckbc_enqueue_cmd(tag, slot, cmd, 1, 1, 1, resp);
- if (res || resp[0] != 3)
- return (0);
-
- return (1);
-}
+const struct pms_protocol pms_protocols[] = {
+ /* Generic PS/2 mouse */
+ {PMS_STANDARD, 3, 0xc0, 0x00,
+ NULL, pms_sync_generic, pms_proc_generic},
+ /* Microsoft IntelliMouse */
+ {PMS_INTELLI, 4, 0x08, 0x08,
+ pms_enable_intelli, pms_sync_generic, pms_proc_generic}
+};
int
-pmsprobe(parent, match, aux)
- struct device *parent;
- void *match;
- void *aux;
+pmsprobe(struct device *parent, void *match, void *aux)
{
struct pckbc_attach_args *pa = aux;
- u_char cmd[1], resp[2];
int res;
+ u_char cmd[1], resp[2];
if (pa->pa_slot != PCKBC_AUX_SLOT)
- return (0);
+ return 0;
- /* Flush any garbage. */
+ /* flush any garbage */
pckbc_flush(pa->pa_tag, pa->pa_slot);
/* reset the device */
cmd[0] = PMS_RESET;
res = pckbc_poll_cmd(pa->pa_tag, pa->pa_slot, cmd, 1, 2, resp, 1);
- if (res) {
-#ifdef DEBUG
- printf("pmsprobe: reset error %d\n", res);
-#endif
- return (0);
- }
- if (resp[0] != PMS_RSTDONE) {
- printf("pmsprobe: reset response 0x%x\n", resp[0]);
- return (0);
- }
-
- /* get type number (0 = mouse) */
- if (resp[1] != 0) {
-#ifdef DEBUG
- printf("pmsprobe: type 0x%x\n", resp[1]);
-#endif
- return (0);
+ if (res || resp[0] != PMS_RSTDONE || resp[1] != 0) {
+ DPRINTF("pms: reset error (%d, response 0x%x, type 0x%x)\n",
+ res, resp[0], resp[1]);
+ return 0;
}
- return (10);
+ return 1;
}
void
-pmsattach(parent, self, aux)
- struct device *parent, *self;
- void *aux;
+pmsattach(struct device *parent, struct device *self, void *aux)
{
struct pms_softc *sc = (void *)self;
struct pckbc_attach_args *pa = aux;
struct wsmousedev_attach_args a;
- u_char cmd[1], resp[2];
- int res;
sc->sc_kbctag = pa->pa_tag;
sc->sc_kbcslot = pa->pa_slot;
printf("\n");
- /* Flush any garbage. */
- pckbc_flush(pa->pa_tag, pa->pa_slot);
-
- /* reset the device */
- cmd[0] = PMS_RESET;
- res = pckbc_poll_cmd(pa->pa_tag, pa->pa_slot, cmd, 1, 2, resp, 1);
-#ifdef DEBUG
- if (res || resp[0] != PMS_RSTDONE || resp[1] != 0) {
- printf("pmsattach: reset error\n");
- return;
- }
-#endif
-
- sc->inputstate = 0;
- sc->oldbuttons = 0;
-
pckbc_set_inputhandler(sc->sc_kbctag, sc->sc_kbcslot,
- pmsinput, sc, sc->sc_dev.dv_xname);
+ pmsinput, sc, DEVNAME(sc));
a.accessops = &pms_accessops;
a.accesscookie = sc;
@@ -191,11 +200,8 @@ pmsattach(parent, self, aux)
sc->sc_wsmousedev = config_found(self, &a, wsmousedevprint);
/* no interrupts until enabled */
- cmd[0] = PMS_DEV_DISABLE;
- res = pckbc_poll_cmd(pa->pa_tag, pa->pa_slot, cmd, 1, 0, NULL, 0);
- if (res)
- printf("pmsattach: disable error\n");
- pckbc_slot_enable(sc->sc_kbctag, sc->sc_kbcslot, 0);
+ sc->poll = 1;
+ pms_change_state(sc, PMS_STATE_DISABLED);
}
int
@@ -213,197 +219,304 @@ pmsactivate(struct device *self, int act
pms_change_state(sc, PMS_STATE_ENABLED);
break;
}
- return (0);
+ return 0;
}
int
-pms_change_state(struct pms_softc *sc, int newstate)
+pms_cmd(struct pms_softc *sc, u_char *cmd, int len, u_char *resp, int resplen)
+{
+ if (sc->poll) {
+ return pckbc_poll_cmd(sc->sc_kbctag, sc->sc_kbcslot,
+ cmd, len, resplen, resp, 1);
+ } else {
+ return pckbc_enqueue_cmd(sc->sc_kbctag, sc->sc_kbcslot,
+ cmd, len, resplen, 1, resp);
+ }
+}
+
+int
+pms_get_devid(struct pms_softc *sc, u_char *resp)
+{
+ u_char cmd[1];
+
+ cmd[0] = PMS_SEND_DEV_ID;
+ return pms_cmd(sc, cmd, 1, resp, 1);
+}
+
+int
+pms_get_status(struct pms_softc *sc, u_char *resp)
{
u_char cmd[1];
+
+ cmd[0] = PMS_SEND_DEV_STATUS;
+ return pms_cmd(sc, cmd, 1, resp, 3);
+}
+
+int
+pms_set_rate(struct pms_softc *sc, int value)
+{
+ u_char cmd[2];
+
+ cmd[0] = PMS_SET_SAMPLE;
+ cmd[1] = value;
+ return pms_cmd(sc, cmd, 2, NULL, 0);
+}
+
+int
+pms_set_resolution(struct pms_softc *sc, int value)
+{
+ u_char cmd[2];
+
+ cmd[0] = PMS_SET_RES;
+ cmd[1] = value;
+ return pms_cmd(sc, cmd, 2, NULL, 0);
+}
+
+int
+pms_set_scaling(struct pms_softc *sc, int scale)
+{
+ u_char cmd[1];
+
+ switch (scale) {
+ case 1:
+ default:
+ cmd[0] = PMS_SET_SCALE11;
+ break;
+ case 2:
+ cmd[0] = PMS_SET_SCALE21;
+ break;
+ }
+ return pms_cmd(sc, cmd, 1, NULL, 0);
+}
+
+void
+pms_dev_reset(struct pms_softc *sc)
+{
int res;
+ u_char cmd[1], resp[2];
+
+ cmd[0] = PMS_RESET;
+ res = pms_cmd(sc, cmd, 1, resp, 2);
+#ifdef PMS_DEBUG
+ if (res || resp[0] != PMS_RSTDONE || resp[1] != 0) {
+ DPRINTF("%s: reset error (%d, response 0x%x, type 0x%x)\n",
+ DEVNAME(sc), res, resp[0], resp[1]);
+ }
+#endif
+}
+
+void
+pms_dev_disable(struct pms_softc *sc)
+{
+ int res;
+ u_char cmd[1];
+
+ cmd[0] = PMS_DEV_DISABLE;
+ res = pms_cmd(sc, cmd, 1, NULL, 0);
+#ifdef PMS_DEBUG
+ if (res)
+ DPRINTF("%s: disable error (%d)\n", DEVNAME(sc), res);
+#endif
+ pckbc_slot_enable(sc->sc_kbctag, sc->sc_kbcslot, 0);
+}
+
+void
+pms_dev_enable(struct pms_softc *sc)
+{
+ int i, res;
+ u_char cmd[1];
+
+ pckbc_slot_enable(sc->sc_kbctag, sc->sc_kbcslot, 1);
+
+ pms_dev_reset(sc);
+
+ sc->protocol = pms_protocols[0];
+ for (i = 1; i < nitems(pms_protocols); i++)
+ if (pms_protocols[i].enable(sc))
+ sc->protocol = pms_protocols[i];
+
+ DPRINTF("%s: protocol type %d\n", DEVNAME(sc), sc->protocol.type);
+ cmd[0] = PMS_DEV_ENABLE;
+ res = pms_cmd(sc, cmd, 1, NULL, 0);
+#ifdef PMS_DEBUG
+ if (res)
+ DPRINTF("%s: enable error (%d)\n", DEVNAME(sc), res);
+#endif
+}
+
+int
+pms_enable_intelli(struct pms_softc *sc)
+{
+ static const int rates[] = {200, 100, 80};
+ int res, i;
+ u_char resp;
+
+ for (i = 0; i < nitems(rates); i++)
+ if (pms_set_rate(sc, rates[i]))
+ return 0;
+
+ res = pms_get_devid(sc, &resp);
+ if (res || (resp != 0x03))
+ return 0;
+
+ return 1;
+}
+
+int
+pms_change_state(struct pms_softc *sc, int newstate)
+{
switch (newstate) {
case PMS_STATE_ENABLED:
if (sc->sc_state == PMS_STATE_ENABLED)
return EBUSY;
- sc->inputstate = 0;
- sc->oldbuttons = 0;
-
- pckbc_slot_enable(sc->sc_kbctag, sc->sc_kbcslot, 1);
- pckbc_flush(sc->sc_kbctag, sc->sc_kbcslot);
- sc->intelli = pms_setintellimode(sc->sc_kbctag, sc->sc_kbcslot);
+ sc->inputstate = 0;
+ sc->buttons = 0;
- cmd[0] = PMS_DEV_ENABLE;
- res = pckbc_enqueue_cmd(sc->sc_kbctag, sc->sc_kbcslot,
- cmd, 1, 0, 1, 0);
- if (res)
- printf("pms_enable: command error\n");
-#if 0
- {
- u_char scmd[2];
-
- scmd[0] = PMS_SET_RES;
- scmd[1] = 3; /* 8 counts/mm */
- res = pckbc_enqueue_cmd(sc->sc_kbctag, sc->sc_kbcslot,
scmd,
- 2, 0, 1, 0);
- if (res)
- printf("pms_enable: setup error1 (%d)\n", res);
-
- scmd[0] = PMS_SET_SCALE21;
- res = pckbc_enqueue_cmd(sc->sc_kbctag, sc->sc_kbcslot,
scmd,
- 1, 0, 1, 0);
- if (res)
- printf("pms_enable: setup error2 (%d)\n", res);
-
- scmd[0] = PMS_SET_SAMPLE;
- scmd[1] = 100; /* 100 samples/sec */
- res = pckbc_enqueue_cmd(sc->sc_kbctag, sc->sc_kbcslot,
scmd,
- 2, 0, 1, 0);
- if (res)
- printf("pms_enable: setup error3 (%d)\n", res);
- }
-#endif
- sc->sc_state = newstate;
+ pms_dev_enable(sc);
+ sc->poll = 0;
break;
case PMS_STATE_DISABLED:
-
- /* FALLTHROUGH */
case PMS_STATE_SUSPENDED:
- cmd[0] = PMS_DEV_DISABLE;
- res = pckbc_enqueue_cmd(sc->sc_kbctag, sc->sc_kbcslot,
- cmd, 1, 0, 1, 0);
- if (res)
- printf("pms_disable: command error\n");
- pckbc_slot_enable(sc->sc_kbctag, sc->sc_kbcslot, 0);
- sc->sc_state = newstate;
+ pms_dev_disable(sc);
+ sc->poll = (newstate == PMS_STATE_SUSPENDED) ? 1 : 0;
break;
}
+ sc->sc_state = newstate;
return 0;
}
int
-pms_enable(v)
- void *v;
+pms_enable(void *vsc)
{
- struct pms_softc *sc = v;
+ struct pms_softc *sc = vsc;
return pms_change_state(sc, PMS_STATE_ENABLED);
}
void
-pms_disable(v)
- void *v;
+pms_disable(void *vsc)
{
- struct pms_softc *sc = v;
+ struct pms_softc *sc = vsc;
pms_change_state(sc, PMS_STATE_DISABLED);
}
int
-pms_ioctl(v, cmd, data, flag, p)
- void *v;
- u_long cmd;
- caddr_t data;
- int flag;
- struct proc *p;
+pms_ioctl(void *vsc, u_long cmd, caddr_t data, int flag, struct proc *p)
{
- struct pms_softc *sc = v;
- u_char kbcmd[2];
+ struct pms_softc *sc = vsc;
int i;
switch (cmd) {
case WSMOUSEIO_GTYPE:
*(u_int *)data = WSMOUSE_TYPE_PS2;
break;
-
case WSMOUSEIO_SRES:
- i = ((int) *(u_int *)data - 12) / 25;
+ i = ((int) *(u_int *)data - 12) / 25;
/* valid values are {0,1,2,3} */
if (i < 0)
i = 0;
if (i > 3)
i = 3;
-
- kbcmd[0] = PMS_SET_RES;
- kbcmd[1] = (unsigned char) i;
- i = pckbc_enqueue_cmd(sc->sc_kbctag, sc->sc_kbcslot, kbcmd,
- 2, 0, 1, 0);
-
- if (i)
- printf("pms_ioctl: SET_RES command error\n");
+
+ if (pms_set_resolution(sc, i)) {
+ DPRINTF("%s: ioctl: set resolution error\n",
+ DEVNAME(sc));
+ }
break;
-
default:
- return (-1);
+ return -1;
}
- return (0);
+ return 0;
}
-/* Masks for the first byte of a packet */
-#define PS2LBUTMASK 0x01
-#define PS2RBUTMASK 0x02
-#define PS2MBUTMASK 0x04
+int
+pms_sync_generic(struct pms_softc *sc, int data)
+{
+ if ((sc->inputstate == 0) &&
+ ((data & sc->protocol.syncmask) != sc->protocol.syncval)) {
+ return -1;
+ }
+ return 0;
+}
-void pmsinput(vsc, data)
-void *vsc;
-int data;
+void
+pms_proc_generic(struct pms_softc *sc, int *dx, int *dy, int *dz, u_int
*buttons)
+{
+ static const u_int butmap[8] = {
+ 0,
+ PMS_BUTTON1DOWN,
+ PMS_BUTTON3DOWN,
+ PMS_BUTTON1DOWN | PMS_BUTTON3DOWN,
+ PMS_BUTTON2DOWN,
+ PMS_BUTTON1DOWN | PMS_BUTTON2DOWN,
+ PMS_BUTTON2DOWN | PMS_BUTTON3DOWN,
+ PMS_BUTTON1DOWN | PMS_BUTTON2DOWN | PMS_BUTTON3DOWN
+ };
+
+ *buttons = butmap[sc->packet[0] & PMS_PS2_BUTTONSMASK];
+ *dx = (sc->packet[0] & PMS_PS2_XNEG) ?
+ sc->packet[1] - 256 : sc->packet[1];
+ *dy = (sc->packet[0] & PMS_PS2_YNEG) ?
+ sc->packet[2] - 256 : sc->packet[2];
+
+ switch (sc->protocol.type) {
+ case PMS_STANDARD:
+ *dz = 0;
+ break;
+ case PMS_INTELLI:
+ *dz = (char)sc->packet[3];
+ break;
+ }
+}
+
+void pmsinput(void *vsc, int data)
{
struct pms_softc *sc = vsc;
- signed char dz = 0;
- u_int changed;
+ u_int changed, newbuttons;
+ int dx, dy, dz;
if (sc->sc_state != PMS_STATE_ENABLED) {
/* Interrupts are not expected. Discard the byte. */
return;
}
- switch (sc->inputstate) {
+ if (sc->protocol.sync(sc, data)) {
+ DPRINTF("%s: not in sync yet, discard input\n", DEVNAME(sc));
+ sc->inputstate = 0;
+ return;
+ }
- case 0:
- if ((data & 0xc0) == 0) { /* no ovfl, bit 3 == 1 too? */
- sc->buttons = ((data & PS2LBUTMASK) ? 0x1 : 0) |
- ((data & PS2MBUTMASK) ? 0x2 : 0) |
- ((data & PS2RBUTMASK) ? 0x4 : 0);
- ++sc->inputstate;
- }
- break;
+ if (sc->inputstate < sc->protocol.packetsize) {
+ sc->packet[sc->inputstate++] = data & 0xff;
+ if (sc->inputstate != sc->protocol.packetsize)
+ return;
+ }
- case 1:
- sc->dx = data;
- /* Bounding at -127 avoids a bug in XFree86. */
- sc->dx = (sc->dx == -128) ? -127 : sc->dx;
- ++sc->inputstate;
- break;
+ sc->protocol.proc(sc, &dx, &dy, &dz, &newbuttons);
- case 2:
- sc->dy = data;
- sc->dy = (sc->dy == -128) ? -127 : sc->dy;
- ++sc->inputstate;
- break;
+ changed = (sc->buttons ^ newbuttons);
+ sc->buttons = newbuttons;
+ sc->inputstate = 0;
- case 3:
- dz = data;
- dz = (dz == -128) ? -127 : dz;
- ++sc->inputstate;
- break;
- }
+#ifdef PMS_DEBUG
+ int i;
- if ((sc->inputstate == 3 && sc->intelli == 0) || sc->inputstate == 4) {
- sc->inputstate = 0;
+ DPRINTFN(3, "%s: packet 0x", DEVNAME(sc));
+ for (i = 0; i < sc->protocol.packetsize; i++)
+ DPRINTFN(3, "%02x", sc->packet[i]);
+ DPRINTFN(3, "\n");
- changed = (sc->buttons ^ sc->oldbuttons);
- sc->oldbuttons = sc->buttons;
+ DPRINTFN(2, "%s: dx %+03d dy %+03d dz %+03d buttons 0x%02x\n",
+ DEVNAME(sc), dx, dy, dz, newbuttons);
+#endif
- if (sc->dx || sc->dy || dz || changed)
- wsmouse_input(sc->sc_wsmousedev,
- sc->buttons, sc->dx, sc->dy, dz, 0,
- WSMOUSE_INPUT_DELTA);
+ if (dx || dy || dz || changed) {
+ wsmouse_input(sc->sc_wsmousedev,
+ newbuttons, dx, dy, dz, 0, WSMOUSE_INPUT_DELTA);
}
- return;
+ memset(sc->packet, 0, sc->protocol.packetsize);
}
-
-struct cfdriver pms_cd = {
- NULL, "pms", DV_DULL
-};
Index: pmsreg.h
===================================================================
RCS file: /cvs/src/sys/dev/pckbc/pmsreg.h,v
retrieving revision 1.1
diff -u -p -r1.1 pmsreg.h
--- pmsreg.h 1 Aug 2007 12:16:59 -0000 1.1
+++ pmsreg.h 29 Sep 2010 14:41:51 -0000
@@ -2,19 +2,21 @@
/* $NetBSD: psmreg.h,v 1.1 1998/03/22 15:41:28 drochner Exp $ */
/* mouse commands */
-#define PMS_SET_SCALE11 0xe6 /* set scaling 1:1 */
-#define PMS_SET_SCALE21 0xe7 /* set scaling 2:1 */
-#define PMS_SET_RES 0xe8 /* set resolution (0..3) */
-#define PMS_GET_SCALE 0xe9 /* get scaling factor */
-#define PMS_SEND_DEV_STATUS 0xe9
-#define PMS_SET_STREAM 0xea /* set streaming mode */
-#define PMS_SEND_DEV_DATA 0xeb
+#define PMS_SET_SCALE11 0xe6 /* set scaling 1:1 */
+#define PMS_SET_SCALE21 0xe7 /* set scaling 2:1 */
+#define PMS_SET_RES 0xe8 /* set resolution (0..3) */
+#define PMS_SEND_DEV_STATUS 0xe9 /* status request */
+#define PMS_SET_STREAM_MODE 0xea
+#define PMS_SEND_DEV_DATA 0xeb /* read data */
+#define PMS_RESET_WRAP_MODE 0xec
+#define PMS_SET_WRAP_MODE 0xed
#define PMS_SET_REMOTE_MODE 0xf0
-#define PMS_SEND_DEV_ID 0xf2
-#define PMS_SET_SAMPLE 0xf3 /* set sampling rate */
-#define PMS_DEV_ENABLE 0xf4 /* mouse on */
-#define PMS_DEV_DISABLE 0xf5 /* mouse off */
+#define PMS_SEND_DEV_ID 0xf2 /* read device type */
+#define PMS_SET_SAMPLE 0xf3 /* set sampling rate */
+#define PMS_DEV_ENABLE 0xf4 /* mouse on */
+#define PMS_DEV_DISABLE 0xf5 /* mouse off */
#define PMS_SET_DEFAULTS 0xf6
-#define PMS_RESET 0xff /* reset */
+#define PMS_RESEND 0xfe
+#define PMS_RESET 0xff /* reset */
-#define PMS_RSTDONE 0xaa
+#define PMS_RSTDONE 0xaa