Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – planix.SVN – Blame – /os/branches/feature_fixcpp/sys/src/cmd/aux/mouse.c – Rev 2

Subversion Repositories planix.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include <u.h>
2
#include <libc.h>
3
 
4
enum
5
{
6
	Sleep500	= 500,
7
	Sleep1000	= 1000,
8
	Sleep2000	= 2000,
9
 
10
	TIMEOUT		= 5000,		/* timeout for writes */
11
};
12
 
13
char *speeds[] =
14
{
15
	"b1200",
16
	"b2400",
17
	"b4800",
18
	"b9600",
19
	0,
20
};
21
 
22
int	button2; 
23
 
24
#define DEBUG if(debug)
25
 
26
int can9600;	/* true if type W mouse can be set to 9600 */
27
int debug;
28
int dontset;	/* true if we shouldn't try to set the mouse type */
29
 
30
static void
31
usage(void)
32
{
33
	fprint(2, "%s: usage: %s [device]\n", argv0, argv0);
34
	exits("usage");
35
}
36
 
37
static void
38
catch(void *a, char *msg)
39
{
40
	USED(a, msg);
41
	if(strstr(msg, "alarm"))
42
		noted(NCONT);
43
	noted(NDFLT);
44
}
45
 
46
static void
47
dumpbuf(char *buf, int nbytes, char *s)
48
{
49
	print(s);
50
	while(nbytes-- > 0)
51
		print("#%ux ", *buf++ & 0xFF);
52
	print("\n");
53
}
54
 
55
static long
56
timedwrite(int fd, void *p, int n)
57
{
58
	long rv;
59
 
60
	alarm(TIMEOUT);
61
	rv = write(fd, p, n);
62
	alarm(0);
63
	if(rv < 0){
64
		fprint(2, "%s: timed out\n", argv0);
65
		exits("timeout");
66
	}
67
	return rv;
68
}
69
 
70
static int
71
readbyte(int fd)
72
{
73
	uchar c;
74
	char buf[ERRMAX];
75
 
76
	alarm(200);
77
	if(read(fd, &c, sizeof(c)) == -1){
78
		alarm(0);
79
		errstr(buf, sizeof buf);
80
		if(strcmp(buf, "interrupted") == 0)
81
			return -1;
82
		fprint(2, "%s: readbyte failed - %s\n", argv0, buf);
83
		exits("read");
84
	}
85
	alarm(0);
86
	return c;
87
}
88
 
89
static int
90
slowread(int fd, char *buf, int nbytes, char *msg)
91
{
92
	char *p;
93
	int c;
94
 
95
	for(p = buf; nbytes > 1 && (c = readbyte(fd)) != -1; *p++ = c, nbytes--)
96
		;
97
	*p = 0;
98
	DEBUG dumpbuf(buf, p-buf, msg);
99
	return p-buf;
100
}
101
 
102
static void
103
toggleRTS(int fd)
104
{
105
	/*
106
	 *
107
	 * reset the mouse (toggle RTS)
108
	 * must be >100mS
109
	 */
110
	timedwrite(fd, "d1", 2);
111
	timedwrite(fd, "r1", 2);
112
	sleep(Sleep500);
113
	timedwrite(fd, "d0", 2);
114
	timedwrite(fd, "r0", 2);
115
	sleep(Sleep500);
116
	timedwrite(fd, "d1", 2);
117
	timedwrite(fd, "r1", 2);
118
	sleep(Sleep500);
119
}
120
 
121
static void
122
setupeia(int fd, char *baud, char *bits)
123
{
124
	alarm(TIMEOUT);
125
	/*
126
	 * set the speed to 1200/2400/4800/9600 baud,
127
	 * 7/8-bit data, one stop bit and no parity
128
	 */
129
	DEBUG print("setupeia(%s,%s)\n", baud, bits);
130
	timedwrite(fd, baud, strlen(baud));
131
	timedwrite(fd, bits, strlen(bits));
132
	timedwrite(fd, "s1", 2);
133
	timedwrite(fd, "pn", 2);
134
	timedwrite(fd, "i1", 2);
135
	alarm(0);
136
}
137
 
138
/*
139
 *  check for a types M, M3, & W
140
 *
141
 *  we talk to all these mice using 1200 baud
142
 */
143
int
144
MorW(int ctl, int data)
145
{
146
	char buf[256];
147
	int c;
148
 
149
	/*
150
	 * set up for type M, V or W
151
	 * flush any pending data
152
	 */
153
	setupeia(ctl, "b1200", "l7");
154
	toggleRTS(ctl);
155
	while(slowread(data, buf, sizeof(buf), "flush: ") > 0)
156
		;
157
	toggleRTS(ctl);
158
 
159
	/*
160
	 * see if there's any data from the mouse
161
	 * (type M, V and W mice)
162
	 */
163
	c = slowread(data, buf, sizeof(buf), "check M: ");
164
 
165
	/*
166
	 * type M, V and W mice return "M" or "M3" after reset.
167
	 * check for type W by sending a 'Send Standard Configuration'
168
	 * command, "*?".
169
	 *
170
	 * the second check is a kludge for some type W mice on next's
171
	 * that send a garbage character back before the "M3".
172
	 */
173
	if((c > 0 && buf[0] == 'M') || (c > 1 && buf[1] == 'M')){
174
		timedwrite(data, "*?", 2);
175
		c = slowread(data, buf, sizeof(buf), "check W: ");
176
		/*
177
		 * 4 bytes back
178
		 * indicates a type W mouse
179
		 */
180
		if(c == 4){
181
			if(buf[1] & (1<<4))
182
				can9600 = 1;
183
			setupeia(ctl, "b1200", "l8");
184
			timedwrite(data, "*U", 2);
185
			slowread(data, buf, sizeof(buf), "check W: ");
186
			return 'W';
187
		}
188
		return 'M';
189
	}
190
	return 0;
191
}
192
 
193
/*
194
 *  check for type C by seeing if it responds to the status
195
 *  command "s".  the mouse is at an unknown speed so we
196
 *  have to check all possible speeds.
197
 */
198
int
199
C(int ctl, int data)
200
{
201
	char **s;
202
	int c;
203
	char buf[256];
204
 
205
	sleep(100);
206
	for(s = speeds; *s; s++){
207
		DEBUG print("%s\n", *s);
208
		setupeia(ctl, *s, "l8");
209
		timedwrite(data, "s", 1);
210
		c = slowread(data, buf, sizeof(buf), "check C: ");
211
		if(c >= 1 && (*buf & 0xBF) == 0x0F){
212
			sleep(100);
213
			timedwrite(data, "*n", 2);
214
			sleep(100);
215
			setupeia(ctl, "b1200", "l8");
216
			timedwrite(data, "s", 1);
217
			c = slowread(data, buf, sizeof(buf), "recheck C: ");
218
			if(c >= 1 && (*buf & 0xBF) == 0x0F){
219
				timedwrite(data, "U", 1);
220
				return 'C';
221
			}
222
		}
223
		sleep(100);
224
	}
225
 
226
	return 0;
227
}
228
 
229
char *bauderr = "mouse: can't set baud rate, mouse at 1200\n";
230
 
231
void
232
Cbaud(int ctl, int data, int baud)
233
{
234
	char buf[32];
235
 
236
	switch(baud){
237
	case 0:
238
	case 1200:
239
		return;
240
	case 2400:
241
		buf[1] = 'o';
242
		break;
243
	case 4800:
244
		buf[1] = 'p';
245
		break;
246
	case 9600:
247
		buf[1] = 'q';
248
		break;
249
	default:
250
		fprint(2, bauderr);
251
		return;
252
	}
253
 
254
	buf[0] = '*';
255
	buf[2] = 0;
256
	sleep(100);
257
	timedwrite(data, buf, 2);
258
	sleep(100);
259
	timedwrite(data, buf, 2);
260
	sprint(buf, "b%d", baud);
261
	setupeia(ctl, buf, "l8");
262
}
263
 
264
void
265
Wbaud(int ctl, int data, int baud)
266
{
267
	char buf[32];
268
 
269
	switch(baud){
270
	case 0:
271
	case 1200:
272
		return;
273
	case 9600:
274
		if(can9600)
275
			break;
276
		/* fall through */
277
	default:
278
		fprint(2, bauderr);
279
		return;
280
	}
281
	timedwrite(data, "*q", 2);
282
	setupeia(ctl, "b9600", "l8");
283
	slowread(data, buf, sizeof(buf), "setbaud: ");
284
}
285
 
286
void
287
main(int argc, char *argv[])
288
{
289
	char *p;
290
	int baud;
291
	int tries, conf, ctl, data, def, type;
292
	char buf[256];
293
 
294
	def = 0;
295
	baud = 0;
296
	ARGBEGIN{
297
	case 'b':
298
		baud = atoi(ARGF());
299
		break;
300
	case 'd':
301
		p = ARGF();
302
		def = *p;
303
		break;
304
	case 'n':
305
		dontset = 1;
306
		break;
307
	case 'D':
308
		debug = 1;
309
		break;
310
	default:
311
		usage();
312
	}ARGEND
313
 
314
	p = "0";
315
	if(argc)
316
		p = *argv;
317
 
318
	if((conf = open("/dev/mousectl", OWRITE)) == -1){
319
		fprint(2, "%s: can't open /dev/mousectl - %r\n", argv0);
320
		if(dontset == 0)
321
			exits("open /dev/mousectl");
322
	}
323
 
324
	if(strncmp(p, "ps2", 3) == 0){
325
		if(write(conf, p, strlen(p)) < 0){
326
			fprint(2, "%s: error setting mouse type - %r\n", argv0);
327
			exits("write conf");
328
		}
329
		exits(0);
330
	}
331
 
332
	type = 0;
333
	for(tries = 0; type == 0 && tries < 6; tries++){
334
		if(tries)
335
			fprint(2, "%s: Unknown mouse type, retrying...\n", argv0);
336
		sprint(buf, "#t/eia%sctl", p);
337
		if((ctl = open(buf, ORDWR)) == -1){
338
			fprint(2, "%s: can't open %s - %r\n", argv0, buf);
339
			exits("open ctl");
340
		}
341
		sprint(buf, "#t/eia%s", p);
342
		if((data = open(buf, ORDWR)) == -1){
343
			fprint(2, "%s: can't open %s - %r\n", argv0, buf);
344
			exits("open data");
345
		}
346
 
347
		notify(catch);
348
 
349
		type = MorW(ctl, data);
350
		if(type == 0)
351
			type = C(ctl, data);
352
		if(type == 0){
353
			/* with the default we can't assume anything */
354
			baud = 0;
355
 
356
			/* try the default */
357
			switch(def){
358
			case 'C':
359
				setupeia(ctl, "b1200", "l8");
360
				break;
361
			case 'M':
362
				setupeia(ctl, "b1200", "l7");
363
				break;
364
			}
365
 
366
			type = def;
367
		}
368
 
369
		sprint(buf, "serial %s", p);
370
		switch(type){
371
		case 0:
372
			close(data);
373
			close(ctl);
374
			continue;
375
		case 'C':
376
			DEBUG print("Logitech 5 byte mouse\n");
377
			Cbaud(ctl, data, baud);
378
			break;
379
		case 'W':
380
			DEBUG print("Type W mouse\n");
381
			Wbaud(ctl, data, baud);
382
			break;
383
		case 'M':
384
			DEBUG print("Microsoft compatible mouse\n");
385
			strcat(buf, " M");
386
			break;
387
		}
388
	}
389
 
390
	if(type == 0){
391
		fprint(2, "%s: Unknown mouse type, giving up\n", argv0);
392
		exits("no mouse");
393
	}
394
 
395
	DEBUG fprint(2, "mouse configured as '%s'\n", buf);
396
	if(dontset == 0 && write(conf, buf, strlen(buf)) < 0){
397
		fprint(2, "%s: error setting mouse type - %r\n", argv0);
398
		exits("write conf");
399
	}
400
 
401
	exits(0);
402
}