xref: /plan9/sys/src/9/omap/mouse.c (revision 9363102901f027b4c277460d9c65669202d4ae69)
1 #include "u.h"
2 #include "../port/lib.h"
3 #include "mem.h"
4 #include "dat.h"
5 #include "fns.h"
6 #include "../port/error.h"
7 #include "io.h"
8 
9 #define	Image	IMAGE
10 #include <draw.h>
11 #include <memdraw.h>
12 #include <cursor.h>
13 #include "screen.h"
14 
15 /*
16  *  mouse types
17  */
18 enum
19 {
20 	Mouseother=	0,
21 	Mouseserial=	1,
22 	MousePS2=	2,
23 };
24 
25 extern int mouseshifted;
26 
27 static QLock mousectlqlock;
28 static int mousetype;
29 static int intellimouse;
30 static int packetsize;
31 static int resolution;
32 static int accelerated;
33 static int mousehwaccel;
34 static char mouseport[5];
35 
36 enum
37 {
38 	CMaccelerated,
39 	CMhwaccel,
40 	CMintellimouse,
41 	CMlinear,
42 	CMps2,
43 	CMps2intellimouse,
44 	CMres,
45 	CMreset,
46 	CMserial,
47 };
48 
49 static Cmdtab mousectlmsg[] =
50 {
51 	CMaccelerated,		"accelerated",		0,
52 	CMhwaccel,		"hwaccel",		2,
53 	CMintellimouse,		"intellimouse",		1,
54 	CMlinear,		"linear",		1,
55 	CMps2,			"ps2",			1,
56 	CMps2intellimouse,	"ps2intellimouse",	1,
57 	CMres,			"res",			0,
58 	CMreset,		"reset",		1,
59 	CMserial,		"serial",		0,
60 };
61 
62 /*
63  *  ps/2 mouse message is three bytes
64  *
65  *	byte 0 -	0 0 SDY SDX 1 M R L
66  *	byte 1 -	DX
67  *	byte 2 -	DY
68  *
69  *  shift & right button is the same as middle button
70  *
71  * Intellimouse and AccuPoint with extra buttons deliver
72  *	byte 3 -	00 or 01 or FF according to extra button state.
73  * extra buttons are mapped in this code to buttons 4 and 5.
74  * AccuPoint generates repeated events for these buttons;
75 *  it and Intellimouse generate 'down' events only, so
76  * user-level code is required to generate button 'up' events
77  * if they are needed by the application.
78  * Also on laptops with AccuPoint AND external mouse, the
79  * controller may deliver 3 or 4 bytes according to the type
80  * of the external mouse; code must adapt.
81  *
82  * On the NEC Versa series (and perhaps others?) we seem to
83  * lose a byte from the packet every once in a while, which
84  * means we lose where we are in the instruction stream.
85  * To resynchronize, if we get a byte more than two seconds
86  * after the previous byte, we assume it's the first in a packet.
87  */
88 static void
ps2mouseputc(int c,int shift)89 ps2mouseputc(int c, int shift)
90 {
91 	static short msg[4];
92 	static int nb;
93 	static uchar b[] = {0, 1, 4, 5, 2, 3, 6, 7, 0, 1, 2, 3, 2, 3, 6, 7 };
94 	static ulong lasttick;
95 	ulong m;
96 	int buttons, dx, dy;
97 
98 	shift |= mouseshifted;
99 	m = MACHP(0)->ticks;
100 	if(TK2SEC(m - lasttick) > 2)
101 		nb = 0;
102 	lasttick = m;
103 	if(nb==0 && (c&0xc8)!=0x08)
104 		if(intellimouse && (c==0x00 || c==0x01 || c==0xFF)){
105 			packetsize = 4;
106 			return;
107 		}
108 
109 	msg[nb] = c;
110 	if(++nb == packetsize){
111 		nb = 0;
112 		if(msg[0] & 0x10)
113 			msg[1] |= 0xFF00;
114 		if(msg[0] & 0x20)
115 			msg[2] |= 0xFF00;
116 
117 		buttons = b[(msg[0]&7) | (shift ? 8 : 0)];
118 		if(intellimouse && packetsize==4){
119 			if((msg[3]&0xc8) == 0x08){
120 				packetsize = 3;
121 				msg[0] = msg[3];
122 				nb = 1;
123 			}else{
124 				if((msg[3] >> 3) & 1)
125 					buttons |= 1<<3;
126 				else if(msg[3] & 0x7)
127 					buttons |= 1<<4;
128 			}
129 		}
130 		dx = msg[1];
131 		dy = -msg[2];
132 		mousetrack(dx, dy, buttons, TK2MS(MACHP(0)->ticks));
133 	}
134 }
135 
136 /*
137  *  set up a ps2 mouse
138  */
139 static void
ps2mouse(void)140 ps2mouse(void)
141 {
142 	if(mousetype == MousePS2)
143 		return;
144 
145 //	i8042auxenable(ps2mouseputc);
146 //	i8042auxcmd(0xEA);	// TODO
147 //	i8042auxcmd(0xF4);
148 
149 	mousetype = MousePS2;
150 	packetsize = 3;
151 	mousehwaccel = 1;
152 }
153 
154 /*
155  * The PS/2 Trackpoint multiplexor on the IBM Thinkpad T23 ignores
156  * acceleration commands.  It is supposed to pass them on
157  * to the attached device, but my Logitech mouse is simply
158  * not behaving any differently.  For such devices, we allow
159  * the user to use "hwaccel off" to tell us to back off to
160  * software acceleration even if we're using the PS/2 port.
161  * (Serial mice are always software accelerated.)
162  * For more information on the Thinkpad multiplexor, see
163  * http://wwwcssrv.almaden.ibm.com/trackpoint/
164  */
165 static void
setaccelerated(int x)166 setaccelerated(int x)
167 {
168 	accelerated = x;
169 	mouseaccelerate(x);
170 }
171 
172 static void
setlinear(void)173 setlinear(void)
174 {
175 	accelerated = 0;
176 	mouseaccelerate(0);
177 }
178 
179 static void
setres(int n)180 setres(int n)
181 {
182 	resolution = n;
183 }
184 
185 static void
setintellimouse(void)186 setintellimouse(void)
187 {
188 	intellimouse = 1;
189 	packetsize = 4;
190 }
191 
192 static void
resetmouse(void)193 resetmouse(void)
194 {
195 	packetsize = 3;
196 }
197 
198 void
mousectl(Cmdbuf * cb)199 mousectl(Cmdbuf *cb)
200 {
201 	Cmdtab *ct;
202 
203 	qlock(&mousectlqlock);
204 	if(waserror()){
205 		qunlock(&mousectlqlock);
206 		nexterror();
207 	}
208 
209 	ct = lookupcmd(cb, mousectlmsg, nelem(mousectlmsg));
210 	switch(ct->index){
211 	case CMaccelerated:
212 		setaccelerated(cb->nf == 1? 1: atoi(cb->f[1]));
213 		break;
214 	case CMintellimouse:
215 		setintellimouse();
216 		break;
217 	case CMlinear:
218 		setlinear();
219 		break;
220 	case CMps2:
221 		intellimouse = 0;
222 		break;
223 	case CMps2intellimouse:
224 		setintellimouse();
225 		break;
226 	case CMres:
227 		if(cb->nf >= 2)
228 			setres(atoi(cb->f[1]));
229 		else
230 			setres(1);
231 		break;
232 	case CMreset:
233 		resetmouse();
234 		if(accelerated)
235 			setaccelerated(accelerated);
236 		if(resolution)
237 			setres(resolution);
238 		if(intellimouse)
239 			setintellimouse();
240 		break;
241 	case CMserial:
242 		error("serial mice not supported");
243 		break;
244 	case CMhwaccel:
245 		if(strcmp(cb->f[1], "on")==0)
246 			mousehwaccel = 1;
247 		else if(strcmp(cb->f[1], "off")==0)
248 			mousehwaccel = 0;
249 		else
250 			cmderror(cb, "bad mouse control message");
251 	}
252 
253 	qunlock(&mousectlqlock);
254 	poperror();
255 }
256