Subject: zs mouse driver on IP12/IP20
To: None <port-sgimips@NetBSD.org>
From: Izumi Tsutsui <tsutsui@ceres.dti.ne.jp>
List: port-sgimips
Date: 10/18/2005 01:09:26
Does anyone test zs mouse driver on IP12/IP20?

I'm still working on ews4800mips port and
its mouse has the similar protocol with sgimips one.
I just take sgimips/dev/zs_ms.c, but the zsms driver
seems to pass wrong values to MI wsmouse(4) layer:
- Packets for delta X and delta Y should be signed
- 1 is DOWN, and 0 is UP for buttons on wsmouse(4) 
- The most left button is LSB on wsmouse(4)

Is it okay to commit attached patch?
(my dumb test program is attached too)
---
Izumi Tsutsui

---
Index: sys/arch/sgimips/dev/zs_ms.c
===================================================================
RCS file: /cvsroot/src/sys/arch/sgimips/dev/zs_ms.c,v
retrieving revision 1.1
diff -u -r1.1 zs_ms.c
--- sys/arch/sgimips/dev/zs_ms.c	8 Jul 2004 22:30:53 -0000	1.1
+++ sys/arch/sgimips/dev/zs_ms.c	17 Oct 2005 15:50:12 -0000
@@ -75,7 +75,7 @@
 #define	ZSMS_PACKET_Y1		2
 #define	ZSMS_PACKET_X2		3
 #define	ZSMS_PACKET_Y2		4
-	u_char		packet[5];
+	int8_t		packet[5];
 
 #define ZSMS_STATE_SYNC	0x01
 #define ZSMS_STATE_X1	0x02
@@ -220,7 +220,7 @@
 	 * then let wsmouse know what has happened.
 	 */
 	while (sc->rxq_head != sc->rxq_tail) {
-		u_char c = sc->rxq[sc->rxq_head];
+		int8_t c = sc->rxq[sc->rxq_head];
 
 		switch (sc->state) {
 		case ZSMS_STATE_SYNC:
@@ -265,16 +265,21 @@
 static void
 zsms_wsmouse_input(struct zsms_softc *sc)
 {
-	int	x, y;
 	u_int	btns;
+	int bl, bm, br;
+	int	x, y;
 
-	btns = sc->packet[ZSMS_PACKET_SYNC] & ZSMS_SYNC_BTN_MASK;
-	x = sc->packet[ZSMS_PACKET_X1] + sc->packet[ZSMS_PACKET_X2];
-	y = sc->packet[ZSMS_PACKET_Y1] + sc->packet[ZSMS_PACKET_Y2];
+	btns = (uint8_t)sc->packet[ZSMS_PACKET_SYNC] & ZSMS_SYNC_BTN_MASK;
 
-	/*
-	 * XXX - how does wsmouse want the buttons represented???
-	 */
+	bl = (btns & ZSMS_SYNC_BTN_L) == 0;
+	bm = (btns & ZSMS_SYNC_BTN_M) == 0;
+	br = (btns & ZSMS_SYNC_BTN_R) == 0;
+
+	/* for wsmouse(4), 1 is down, 0 is up, the most left button is LSB */
+	btns = (bl ? (1 << 0) : 0) | (bm ? (1 << 1) : 0) | (br ? (1 << 2) : 0);
+
+	x = (int)sc->packet[ZSMS_PACKET_X1] + (int)sc->packet[ZSMS_PACKET_X2];
+	y = (int)sc->packet[ZSMS_PACKET_Y1] + (int)sc->packet[ZSMS_PACKET_Y2];
 
 	wsmouse_input(sc->wsmousedev, btns, x, y, 0, WSMOUSE_INPUT_DELTA);	
 }

---
#include <stdio.h>
#include <sys/types.h>
#include <sys/time.h>
#include <dev/wscons/wsconsio.h>

#define	CLIP(v, l)	do { if (v > l) v = l; if (v < -l) v = -l;} while (0)

main()
{
        int fd, nread;
        unsigned int type;
        struct wscons_event ev;
	int x, y, z, b0, b1, b2, b3, btn;

	x = y = z = b0 = b1 = b2 = b3 = btn = 0;

        fd = open("/dev/wsmouse0", 2);
        if (fd < 0) {
                perror("/dev/wsmouse0");
                exit(1);
        }

	fprintf(stderr, "   X    Y    Z   B0   B1   B2   B3  btn\n");
        while ((nread = read(fd, &ev, sizeof(ev))) > 0) {
                switch (ev.type) {
                case WSCONS_EVENT_MOUSE_DOWN:
			btn = ev.value;
			if (btn == 0)
				b0 = 1;
			else if (btn == 1)
				b1 = 1;
			else if (btn == 2)
				b2 = 1;
			else if (btn == 3)
				b3 = 1;
                        break;
                case WSCONS_EVENT_MOUSE_UP:
			btn = ev.value;
			if (btn == 0)
				b0 = 0;
			else if (btn == 1)
				b1 = 0;
			else if (btn == 2)
				b2 = 0;
			else if (btn == 3)
				b3 = 0;
                        break;
                case WSCONS_EVENT_MOUSE_DELTA_X:
			x += ev.value;
                        break;
                case WSCONS_EVENT_MOUSE_DELTA_Y:
			y += ev.value;
                        break;
                case WSCONS_EVENT_MOUSE_DELTA_Z:
			z += ev.value;
                        break;
                case WSCONS_EVENT_MOUSE_ABSOLUTE_X:
			x = ev.value;
                        break;
                case WSCONS_EVENT_MOUSE_ABSOLUTE_Y:
			y = ev.value;
                        break;
                case WSCONS_EVENT_MOUSE_ABSOLUTE_Z:
			z = ev.value;
                        break;
                default:
			break;
                }
		CLIP(x, 999);
		CLIP(y, 999);
		CLIP(z, 999);
		fprintf(stderr, "%4d %4d %4d  %s  %s  %s  %s   %d\r",
		    x, y, z,
		    b0 ? " ON" : "OFF",
		    b1 ? " ON" : "OFF",
		    b2 ? " ON" : "OFF",
		    b3 ? " ON" : "OFF",
		    btn);
        }
        if (nread < 0) 
                perror("read");
        exit(0);
}

---