]>
Commit | Line | Data |
---|---|---|
93afd047 MT |
1 | #include <stdio.h> |
2 | #include <stdlib.h> | |
3 | #include <string.h> | |
4 | #include <unistd.h> | |
5 | #include <fcntl.h> | |
6 | #include <errno.h> | |
7 | #include <termios.h> | |
8 | #include <sys/stat.h> | |
9 | #include <sys/types.h> | |
10 | #include <sys/time.h> | |
11 | #include <sys/ioctl.h> | |
12 | ||
13 | #include "hd.h" | |
14 | #include "hd_int.h" | |
15 | #include "mouse.h" | |
16 | ||
17 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
18 | * mouse info | |
19 | * | |
20 | * TODO: reset serial lines to old values (cf. modem.c) | |
21 | * | |
22 | * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
23 | */ | |
24 | ||
25 | #ifndef LIBHD_TINY | |
26 | ||
27 | #if 0 | |
28 | static unsigned read_data(hd_data_t *hd_data, int fd, unsigned char *buf, unsigned buf_size); | |
29 | static void get_ps2_mouse(hd_data_t *hd_data); | |
30 | static void test_ps2_open(void *arg); | |
31 | #endif | |
32 | ||
33 | static void get_serial_mouse(hd_data_t* hd_data); | |
34 | static void add_serial_mouse(hd_data_t* hd_data); | |
35 | static int _setspeed(int fd, int old, int new, int needtowrite, unsigned short flags); | |
36 | static void setspeed(int fd, int new, int needtowrite, unsigned short flags); | |
37 | static unsigned chk4id(ser_device_t *mi); | |
38 | static ser_device_t *add_ser_mouse_entry(ser_device_t **sm, ser_device_t *new_sm); | |
39 | static void dump_ser_mouse_data(hd_data_t *hd_data); | |
40 | #if 0 | |
41 | static void get_sunmouse(hd_data_t *hd_data); | |
42 | #endif | |
43 | ||
44 | void hd_scan_mouse(hd_data_t *hd_data) | |
45 | { | |
46 | ser_device_t *sm, *sm_next; | |
47 | ||
48 | if(!hd_probe_feature(hd_data, pr_mouse)) return; | |
49 | ||
50 | hd_data->module = mod_mouse; | |
51 | ||
52 | /* some clean-up */ | |
53 | remove_hd_entries(hd_data); | |
54 | hd_data->ser_mouse = NULL; | |
55 | ||
56 | #if 0 | |
57 | PROGRESS(1, 0, "ps/2"); | |
58 | ||
59 | get_ps2_mouse(hd_data); | |
60 | #endif | |
61 | ||
62 | PROGRESS(2, 0, "serial"); | |
63 | ||
64 | hd_fork(hd_data, 20, 20); | |
65 | ||
66 | if(hd_data->flags.forked) { | |
67 | get_serial_mouse(hd_data); | |
68 | hd_move_to_shm(hd_data); | |
69 | if((hd_data->debug & HD_DEB_MOUSE)) dump_ser_mouse_data(hd_data); | |
70 | } | |
71 | else { | |
72 | /* take data from shm */ | |
73 | hd_data->ser_mouse = ((hd_data_t *) (hd_data->shm.data))->ser_mouse; | |
74 | if((hd_data->debug & HD_DEB_MOUSE)) dump_ser_mouse_data(hd_data); | |
75 | } | |
76 | ||
77 | hd_fork_done(hd_data); | |
78 | ||
79 | add_serial_mouse(hd_data); | |
80 | ||
81 | hd_shm_clean(hd_data); | |
82 | ||
83 | for(sm = hd_data->ser_mouse; sm; sm = sm_next) { | |
84 | sm_next = sm->next; | |
85 | ||
86 | free_mem(sm->dev_name); | |
87 | free_mem(sm); | |
88 | } | |
89 | hd_data->ser_mouse = NULL; | |
90 | ||
91 | #if 0 | |
92 | PROGRESS(3, 0, "sunmouse"); | |
93 | ||
94 | get_sunmouse(hd_data); | |
95 | #endif | |
96 | } | |
97 | ||
98 | ||
99 | #if 0 | |
100 | unsigned read_data(hd_data_t *hd_data, int fd, unsigned char *buf, unsigned buf_size) | |
101 | { | |
102 | int k, len = 0; | |
103 | unsigned char *bp; | |
104 | ||
105 | while( | |
106 | (unsigned) len < buf_size && | |
107 | (k = read(fd, buf + len, buf_size - len)) >= 0 | |
108 | ) len += k; | |
109 | ||
110 | bp = buf; | |
111 | if(len && (*bp == 0xfe || *bp == 0xfa)) { bp++; len--; } | |
112 | ||
113 | for(k = 0; k < len; k++) buf[k] = bp[k]; | |
114 | ||
115 | if((hd_data->debug & HD_DEB_MOUSE)) { | |
116 | ADD2LOG("ps/2[%d]: ", len); | |
117 | hexdump(&hd_data->log, 1, len, buf); | |
118 | ADD2LOG("\n"); | |
119 | } | |
120 | ||
121 | return len; | |
122 | } | |
123 | ||
124 | ||
125 | /* | |
126 | * How it works: | |
127 | * | |
128 | * 1. There must exist a PS/2 controller entry (-> there is a PS/2 port). | |
129 | * 2. If there are PS/2 mouse irq events, assume a PS/2 mouse is attached. | |
130 | * 3. Otherwise: | |
131 | * - open /dev/psaux | |
132 | * - write the "get mouse info" command (0xe9) | |
133 | * - read back the response, which should be either 0xfe "resend data" | |
134 | * or, e.g. (0xfa) 0x20 0x02 0x3c (0xfa = "ACK" (should be swallowed | |
135 | * by the psaux driver, but isn't), the rest are settings) | |
136 | * - ignore the first byte if it is 0xfa or 0xfe | |
137 | * - if there are at least 2 bytes left, assume a mouse is attached. | |
138 | * | |
139 | * Note1: we could use the command 0xfe "get mouse ID" instead. But that turned | |
140 | * out to be less reliable, as this command returns only one byte, which | |
141 | * is even 0. | |
142 | * Note2: step 2 is mainly relevant if the mouse is already in use. In that | |
143 | * case we would have problems reading back the respose of our command. | |
144 | * (Typically the mouse driver will get it (and choke on it).) | |
145 | */ | |
146 | ||
147 | static void get_ps2_mouse(hd_data_t *hd_data) | |
148 | { | |
149 | hd_t *hd, *hd1; | |
150 | hd_res_t *res; | |
151 | int fd; | |
152 | fd_set set; | |
153 | struct timeval tv; | |
154 | unsigned char cmd_mouse_info = 0xe9; /* read mouse info (3 bytes) */ | |
155 | unsigned char cmd_mouse_id = 0xf2; /* read mouse id (1 byte) */ | |
156 | unsigned char buf[100]; | |
157 | unsigned mouse_id = -1; | |
158 | static unsigned char intelli_init[] = { 0xf3, 200, 0xf3, 100, 0xf3, 80 }; | |
159 | int buf_len = 0; | |
160 | #ifdef __PPC__ | |
161 | int always_ps2_mouse = 0; | |
162 | #endif | |
163 | ||
164 | for(hd1 = hd_data->hd; hd1; hd1 = hd1->next) { | |
165 | /* look for a PS/2 controller entry... */ | |
166 | if(hd1->base_class.id == bc_ps2) { | |
167 | /* ...and see if there were irq events... */ | |
168 | for(res = hd1->res; res; res = res->next) { | |
169 | if(res->irq.type == res_irq && res->irq.triggered) break; | |
170 | } | |
171 | ||
172 | #ifdef __PPC__ | |
173 | /* | |
174 | * On PReP & CHRP, assume a PS/2 mouse to be attached. | |
175 | * There seems to be no way to actually *detect* it. | |
176 | */ | |
177 | if(!res) { | |
178 | hd_t *hd; | |
179 | sys_info_t *st; | |
180 | ||
181 | if((hd = hd_list(hd_data, hw_sys, 0, NULL))) { | |
182 | if( | |
183 | hd->detail && | |
184 | hd->detail->type == hd_detail_sys && | |
185 | (st = hd->detail->sys.data) && | |
186 | ( | |
187 | !strcmp(st->system_type, "PReP") || | |
188 | strstr(st->system_type, "CHRP") == st->system_type /* CHRP && CHRP64 */ | |
189 | ) | |
190 | ) { | |
191 | always_ps2_mouse = 1; | |
192 | } | |
193 | } | |
194 | } | |
195 | #endif | |
196 | ||
197 | PROGRESS(1, 1, "ps/2"); | |
198 | ||
199 | /* open the mouse device... */ | |
200 | if(hd_timeout(test_ps2_open, NULL, 2) > 0) { | |
201 | ADD2LOG("ps/2: open(%s) timed out\n", DEV_PSAUX); | |
202 | fd = -2; | |
203 | } | |
204 | else { | |
205 | fd = open(DEV_PSAUX, O_RDWR | O_NONBLOCK); | |
206 | } | |
207 | ||
208 | PROGRESS(1, 2, "ps/2"); | |
209 | ||
210 | if(fd >= 0) { | |
211 | /* ...write the id command... */ | |
212 | ||
213 | PROGRESS(1, 3, "ps/2"); | |
214 | ||
215 | write(fd, intelli_init, sizeof intelli_init); | |
216 | usleep(25000); | |
217 | read_data(hd_data, fd, buf, sizeof buf); | |
218 | ||
219 | if(write(fd, &cmd_mouse_id, 1) == 1) { | |
220 | ||
221 | PROGRESS(1, 4, "ps/2"); | |
222 | usleep(50000); /* ...give it a chance to react... */ | |
223 | ||
224 | /* ...read the response... */ | |
225 | buf_len = read_data(hd_data, fd, buf, sizeof buf); | |
226 | ||
227 | if(buf_len >= 1) mouse_id = buf[buf_len - 1]; | |
228 | ||
229 | // if we didn't get any response, try this | |
230 | if(buf_len == 0 || (hd_data->debug & HD_DEB_MOUSE)) { | |
231 | PROGRESS(1, 5, "ps/2"); | |
232 | if(write(fd, &cmd_mouse_info, 1) == 1) { | |
233 | usleep(50000); | |
234 | buf_len = read_data(hd_data, fd, buf, sizeof buf); | |
235 | /* | |
236 | * Assume a mouse to be attached if at least 2 bytes are | |
237 | * returned. | |
238 | */ | |
239 | if(mouse_id == -1u && buf_len >= 2) mouse_id = 0; | |
240 | } | |
241 | } | |
242 | ||
243 | PROGRESS(1, 6, "ps/2"); | |
244 | } | |
245 | close(fd); | |
246 | ||
247 | PROGRESS(1, 7, "ps/2"); | |
248 | ||
249 | /* | |
250 | * The following code is apparently necessary on some board/mouse | |
251 | * combinations. Otherwise the PS/2 mouse won't work. | |
252 | */ | |
253 | if((fd = open(DEV_PSAUX, O_RDONLY | O_NONBLOCK)) >= 0) { | |
254 | PROGRESS(1, 8, "ps/2"); | |
255 | ||
256 | FD_ZERO(&set); | |
257 | FD_SET(fd, &set); | |
258 | tv.tv_sec = 0; tv.tv_usec = 1; | |
259 | if(select(fd + 1, &set, NULL, NULL, &tv) == 1) { | |
260 | PROGRESS(1, 9, "ps/2"); | |
261 | ||
262 | read(fd, buf, sizeof buf); | |
263 | ||
264 | PROGRESS(1, 10, "ps/2"); | |
265 | } | |
266 | PROGRESS(1, 11, "ps/2"); | |
267 | ||
268 | close(fd); | |
269 | ||
270 | PROGRESS(1, 12, "ps/2"); | |
271 | } | |
272 | } | |
273 | else { | |
274 | ADD2LOG("open(" DEV_PSAUX "): %s\n", fd == -1 ? strerror(errno) : "timeout"); | |
275 | } | |
276 | ||
277 | if(mouse_id == -1u) { | |
278 | ||
279 | /* | |
280 | * Assume a PS/2 mouse is attached if the ps/2 controller has | |
281 | * genetrated some events. | |
282 | */ | |
283 | ||
284 | if( | |
285 | res | |
286 | #ifdef __PPC__ | |
287 | || always_ps2_mouse | |
288 | #endif | |
289 | ) { | |
290 | PROGRESS(1, 13, "ps/2"); | |
291 | mouse_id = 0; | |
292 | } | |
293 | } | |
294 | ||
295 | if(mouse_id != -1u) { | |
296 | PROGRESS(1, 14, "ps/2"); | |
297 | ||
298 | hd = add_hd_entry(hd_data, __LINE__, 0); | |
299 | hd->base_class.id = bc_mouse; | |
300 | hd->sub_class.id = sc_mou_ps2; | |
301 | hd->bus.id = bus_ps2; | |
302 | hd->unix_dev_name = new_str(DEV_MICE); | |
303 | hd->attached_to = hd1->idx; | |
304 | ||
305 | hd->vendor.id = MAKE_ID(TAG_SPECIAL, 0x0200); | |
306 | switch(mouse_id) { | |
307 | case 3: /* 3 buttons + wheel */ | |
308 | hd->device.id = MAKE_ID(TAG_SPECIAL, 0x0004); | |
309 | break; | |
310 | ||
311 | case 4: /* 5 buttons + wheel */ | |
312 | hd->device.id = MAKE_ID(TAG_SPECIAL, 0x0005); | |
313 | break; | |
314 | ||
315 | default: /* 0 */ | |
316 | hd->device.id = MAKE_ID(TAG_SPECIAL, 0x0002); | |
317 | } | |
318 | } | |
319 | ||
320 | /* there can only be one... */ | |
321 | break; | |
322 | } | |
323 | } | |
324 | } | |
325 | ||
326 | void test_ps2_open(void *arg) | |
327 | { | |
328 | open(DEV_PSAUX, O_RDWR | O_NONBLOCK); | |
329 | } | |
330 | #endif | |
331 | ||
332 | #if 0 | |
333 | static void get_sunmouse(hd_data_t *hd_data) | |
334 | { | |
335 | hd_t *hd; | |
336 | int fd; | |
337 | int found; | |
338 | ||
339 | found = 0; | |
340 | ||
341 | /* Only search for Sun mouse if we have a Sun keyboard */ | |
342 | for(hd = hd_data->hd; hd; hd = hd->next) | |
343 | { | |
344 | if(hd->base_class.id == bc_keyboard && | |
345 | hd->sub_class.id == sc_keyboard_kbd && | |
346 | ID_TAG(hd->vendor.id) == TAG_SPECIAL && ID_VALUE(hd->vendor.id) == 0x0202) | |
347 | found = 1; | |
348 | } | |
349 | ||
350 | if (found) | |
351 | { | |
352 | if ((fd = open(DEV_SUNMOUSE, O_RDONLY)) != -1) | |
353 | { | |
354 | /* FIXME: Should probably talk to the mouse to see | |
355 | if the connector is not empty. */ | |
356 | close (fd); | |
357 | ||
358 | PROGRESS(1, 1, "Sun Mouse"); | |
359 | ||
360 | hd = add_hd_entry (hd_data, __LINE__, 0); | |
361 | hd->base_class.id = bc_mouse; | |
362 | hd->sub_class.id = sc_mou_sun; | |
363 | hd->bus.id = bus_serial; | |
364 | hd->unix_dev_name = new_str(DEV_SUNMOUSE); | |
365 | ||
366 | hd->vendor.id = MAKE_ID(TAG_SPECIAL, 0x0202); | |
367 | hd->device.id = MAKE_ID(TAG_SPECIAL, 0x0000); | |
368 | } | |
369 | } | |
370 | } | |
371 | #endif | |
372 | ||
373 | /* | |
374 | * Gather serial mouse data and put it into hd_data->ser_mouse. | |
375 | */ | |
376 | void get_serial_mouse(hd_data_t *hd_data) | |
377 | { | |
378 | hd_t *hd; | |
379 | int j, fd, fd_max = 0, sel, max_len; | |
380 | unsigned modem_info; | |
381 | fd_set set, set0; | |
382 | struct timeval to; | |
383 | ser_device_t *sm; | |
384 | struct termios tio; | |
385 | ||
386 | FD_ZERO(&set); | |
387 | ||
388 | for(hd = hd_data->hd; hd; hd = hd->next) { | |
389 | if( | |
390 | hd->base_class.id == bc_comm && | |
391 | hd->sub_class.id == sc_com_ser && | |
392 | hd->unix_dev_name && | |
393 | !hd->tag.ser_skip && | |
394 | !has_something_attached(hd_data, hd) | |
395 | ) { | |
396 | if((fd = open(hd->unix_dev_name, O_RDWR | O_NONBLOCK)) >= 0) { | |
397 | if(tcgetattr(fd, &tio)) continue; | |
398 | sm = add_ser_mouse_entry(&hd_data->ser_mouse, new_mem(sizeof *sm)); | |
399 | sm->dev_name = new_str(hd->unix_dev_name); | |
400 | sm->fd = fd; | |
401 | sm->tio = tio; | |
402 | sm->hd_idx = hd->idx; | |
403 | if(fd > fd_max) fd_max = fd; | |
404 | FD_SET(fd, &set); | |
405 | ||
406 | /* | |
407 | * PnP COM spec black magic... | |
408 | */ | |
409 | setspeed(fd, 1200, 1, CS7); | |
410 | modem_info = TIOCM_DTR | TIOCM_RTS; | |
411 | ioctl(fd, TIOCMBIC, &modem_info); | |
412 | } | |
413 | } | |
414 | } | |
415 | ||
416 | if(!hd_data->ser_mouse) return; | |
417 | ||
418 | /* | |
419 | * 200 ms seems to be too fast for some mice... | |
420 | */ | |
421 | usleep(300000); /* PnP protocol */ | |
422 | ||
423 | for(sm = hd_data->ser_mouse; sm; sm = sm->next) { | |
424 | modem_info = TIOCM_DTR | TIOCM_RTS; | |
425 | ioctl(sm->fd, TIOCMBIS, &modem_info); | |
426 | } | |
427 | ||
428 | /* smaller buffer size, otherwise we might wait really long... */ | |
429 | max_len = sizeof sm->buf < 128 ? sizeof sm->buf : 128; | |
430 | ||
431 | to.tv_sec = 0; to.tv_usec = 300000; | |
432 | ||
433 | set0 = set; | |
434 | for(;;) { | |
435 | to.tv_sec = 0; to.tv_usec = 300000; | |
436 | set = set0; | |
437 | if((sel = select(fd_max + 1, &set, NULL, NULL, &to)) > 0) { | |
438 | for(sm = hd_data->ser_mouse; sm; sm = sm->next) { | |
439 | if(FD_ISSET(sm->fd, &set)) { | |
440 | if((j = read(sm->fd, sm->buf + sm->buf_len, max_len - sm->buf_len)) > 0) | |
441 | sm->buf_len += j; | |
442 | if(j <= 0) FD_CLR(sm->fd, &set0); // ##### | |
443 | } | |
444 | } | |
445 | } | |
446 | else { | |
447 | break; | |
448 | } | |
449 | } | |
450 | ||
451 | for(sm = hd_data->ser_mouse; sm; sm = sm->next) { | |
452 | chk4id(sm); | |
453 | /* reset serial lines */ | |
454 | tcflush(sm->fd, TCIOFLUSH); | |
455 | tcsetattr(sm->fd, TCSAFLUSH, &sm->tio); | |
456 | close(sm->fd); | |
457 | } | |
458 | } | |
459 | ||
460 | ||
461 | /* | |
462 | * Go through serial mouse data and add hd entries. | |
463 | */ | |
464 | void add_serial_mouse(hd_data_t *hd_data) | |
465 | { | |
466 | hd_t *hd; | |
467 | char buf[4]; | |
468 | ser_device_t *sm; | |
469 | ||
470 | for(sm = hd_data->ser_mouse; sm; sm = sm->next) { | |
471 | if(sm->is_mouse) { | |
472 | hd = add_hd_entry(hd_data, __LINE__, 0); | |
473 | hd->base_class.id = bc_mouse; | |
474 | hd->sub_class.id = sc_mou_ser; | |
475 | hd->bus.id = bus_serial; | |
476 | hd->unix_dev_name = new_str(sm->dev_name); | |
477 | hd->attached_to = sm->hd_idx; | |
478 | if(*sm->pnp_id) { | |
479 | strncpy(buf, sm->pnp_id, 3); | |
480 | buf[3] = 0; | |
481 | hd->vendor.id = name2eisa_id(buf); | |
482 | if(!hd->vendor.id) { /* in case it's a really strange one... */ | |
483 | hd->vendor.name = new_str(buf); | |
484 | } | |
485 | hd->device.id = MAKE_ID(TAG_EISA, strtol(sm->pnp_id + 3, NULL, 16)); | |
486 | ||
487 | hd->serial = new_str(sm->serial); | |
488 | if(sm->user_name) hd->device.name = new_str(sm->user_name); | |
489 | if(sm->vend) { | |
490 | free_mem(hd->vendor.name); | |
491 | hd->vendor.name = new_str(sm->vend); | |
492 | } | |
493 | ||
494 | if(sm->dev_id && strlen(sm->dev_id) >= 7) { | |
495 | char buf[5], *s; | |
496 | unsigned u1, u2; | |
497 | ||
498 | u1 = name2eisa_id(sm->dev_id); | |
499 | if(u1) { | |
500 | strncpy(buf, sm->dev_id + 3, 4); | |
501 | buf[4] = 0; | |
502 | u2 = strtol(sm->dev_id + 3, &s, 16); | |
503 | if(!*s) { | |
504 | hd->compat_vendor.id = u1; | |
505 | hd->compat_device.id = MAKE_ID(TAG_EISA, u2); | |
506 | } | |
507 | } | |
508 | } | |
509 | } | |
510 | else { | |
511 | hd->vendor.id = MAKE_ID(TAG_SPECIAL, 0x0200); | |
512 | hd->device.id = MAKE_ID(TAG_SPECIAL, 0x0003); | |
513 | } | |
514 | } | |
515 | } | |
516 | } | |
517 | ||
518 | ||
519 | /* | |
520 | * Baud setting magic taken from gpm. | |
521 | */ | |
522 | ||
523 | int _setspeed(int fd, int old, int new, int needtowrite, unsigned short flags) | |
524 | { | |
525 | struct termios tty; | |
526 | char *c; | |
527 | int err = 0; | |
528 | ||
529 | flags |= CREAD | CLOCAL | HUPCL; | |
530 | ||
531 | if(tcgetattr(fd, &tty)) return errno; | |
532 | ||
533 | tty.c_iflag = IGNBRK | IGNPAR; | |
534 | tty.c_oflag = 0; | |
535 | tty.c_lflag = 0; | |
536 | tty.c_line = 0; | |
537 | tty.c_cc[VTIME] = 0; | |
538 | tty.c_cc[VMIN] = 1; | |
539 | ||
540 | switch (old) | |
541 | { | |
542 | case 9600: tty.c_cflag = flags | B9600; break; | |
543 | case 4800: tty.c_cflag = flags | B4800; break; | |
544 | case 2400: tty.c_cflag = flags | B2400; break; | |
545 | case 1200: | |
546 | default: tty.c_cflag = flags | B1200; break; | |
547 | } | |
548 | ||
549 | if(tcsetattr(fd, TCSAFLUSH, &tty)) return errno; | |
550 | ||
551 | switch (new) | |
552 | { | |
553 | case 9600: c = "*q"; tty.c_cflag = flags | B9600; break; | |
554 | case 4800: c = "*p"; tty.c_cflag = flags | B4800; break; | |
555 | case 2400: c = "*o"; tty.c_cflag = flags | B2400; break; | |
556 | case 1200: | |
557 | default: c = "*n"; tty.c_cflag = flags | B1200; break; | |
558 | } | |
559 | ||
560 | if(needtowrite) { | |
561 | err = 2 - write(fd, c, 2); | |
562 | } | |
563 | ||
564 | usleep(100000); | |
565 | ||
566 | if(tcsetattr(fd, TCSAFLUSH, &tty)) return errno; | |
567 | ||
568 | return err; | |
569 | } | |
570 | ||
571 | ||
572 | void setspeed(int fd, int new, int needtowrite, unsigned short flags) | |
573 | { | |
574 | int i, err; | |
575 | ||
576 | for(i = 9600; i >= 1200; i >>= 1) { | |
577 | err = _setspeed(fd, i, new, needtowrite, flags); | |
578 | #if 0 | |
579 | if(err) { | |
580 | fprintf(stderr, "%d, %d ", i, err); | |
581 | perror(""); | |
582 | } | |
583 | #endif | |
584 | } | |
585 | } | |
586 | ||
587 | ||
588 | #if 0 | |
589 | /* | |
590 | * Check for a PnP info field starting at ofs; | |
591 | * returns either the length of the field or 0 if none was found. | |
592 | * | |
593 | * the minfo_t struct is updated with the PnP data | |
594 | */ | |
595 | int is_pnpinfo(ser_device_t *mi, int ofs) | |
596 | { | |
597 | int i; | |
598 | unsigned char *s = mi->buf + ofs; | |
599 | int len = mi->buf_len - ofs; | |
600 | ||
601 | if(len <= 0) return 0; | |
602 | ||
603 | switch(*s) { | |
604 | case 0x08: | |
605 | mi->bits = 6; break; | |
606 | case 0x28: | |
607 | mi->bits = 7; break; | |
608 | default: | |
609 | return 0; | |
610 | } | |
611 | ||
612 | if(len < 11) return 0; | |
613 | ||
614 | /* six bit values */ | |
615 | if((s[1] & ~0x3f) || (s[2] & ~0x3f)) return 0; | |
616 | mi->pnp_rev = (s[1] << 6) + s[2]; | |
617 | ||
618 | /* the eisa id */ | |
619 | for(i = 0; i < 7; i++) { | |
620 | mi->pnp_id[i] = s[i + 3]; | |
621 | if(mi->bits == 6) mi->pnp_id[i] += 0x20; | |
622 | } | |
623 | mi->pnp_id[7] = 0; | |
624 | ||
625 | /* now check the id */ | |
626 | for(i = 0; i < 3; i++) { | |
627 | if( | |
628 | (mi->pnp_id[i] < 'A' || mi->pnp_id[i] > 'Z') && | |
629 | mi->pnp_id[i] != '_' | |
630 | ) return 0; | |
631 | } | |
632 | ||
633 | for(i = 3; i < 7; i++) { | |
634 | if( | |
635 | (mi->pnp_id[i] < '0' || mi->pnp_id[i] > '9') && | |
636 | (mi->pnp_id[i] < 'A' || mi->pnp_id[i] > 'F') | |
637 | ) return 0; | |
638 | } | |
639 | ||
640 | if( | |
641 | (mi->bits == 6 && s[10] == 0x09) || | |
642 | (mi->bits == 7 && s[10] == 0x29) | |
643 | ) { | |
644 | return 11; | |
645 | } | |
646 | ||
647 | if( | |
648 | (mi->bits != 6 || s[10] != 0x3c) && | |
649 | (mi->bits != 7 || s[10] != 0x5c) | |
650 | ) { | |
651 | return 0; | |
652 | } | |
653 | ||
654 | /* skip extended info */ | |
655 | for(i = 11; i < len; i++) { | |
656 | if( | |
657 | (mi->bits == 6 && s[i] == 0x09) || | |
658 | (mi->bits == 7 && s[i] == 0x29) | |
659 | ) { | |
660 | return i + 1; | |
661 | } | |
662 | } | |
663 | ||
664 | /* | |
665 | * some mice have problems providing the extended info -> return ok in | |
666 | * these cases too | |
667 | */ | |
668 | if( | |
669 | (mi->bits == 6 && s[10] == 0x3c) || | |
670 | (mi->bits == 7 && s[10] == 0x5c) | |
671 | ) { | |
672 | return 11; | |
673 | } | |
674 | ||
675 | /* no end token... */ | |
676 | ||
677 | return 0; | |
678 | } | |
679 | #endif | |
680 | ||
681 | unsigned chk4id(ser_device_t *mi) | |
682 | { | |
683 | int i; | |
684 | ||
685 | #if 0 | |
686 | unsigned char fake[] = | |
687 | { | |
688 | // fake pnp data | |
689 | }; | |
690 | ||
691 | mi->buf_len = sizeof fake; | |
692 | memcpy(mi->buf, fake, mi->buf_len); | |
693 | // for(i = 0; i < mi->buf_len; i++) mi->buf[i] += ' '; | |
694 | #endif | |
695 | ||
696 | if(!mi->buf_len) return 0; | |
697 | ||
698 | for(i = 0; i < mi->buf_len; i++) { | |
699 | if((mi->pnp = is_pnpinfo(mi, i))) break; | |
700 | } | |
701 | if(i == mi->buf_len) { | |
702 | /* non PnP, but MS compatible */ | |
703 | if(*mi->buf == 'M') | |
704 | mi->non_pnp = mi->buf_len - 1; | |
705 | else | |
706 | return 0; | |
707 | } | |
708 | ||
709 | mi->garbage = i; | |
710 | ||
711 | for(i = 0; i < mi->garbage; i++) { | |
712 | if(mi->buf[i] == 'M') { | |
713 | mi->non_pnp = mi->garbage - i; | |
714 | mi->garbage = i; | |
715 | break; | |
716 | } | |
717 | } | |
718 | ||
719 | if(mi->non_pnp || mi->bits == 6) mi->is_mouse = 1; | |
720 | ||
721 | return mi->is_mouse; | |
722 | } | |
723 | ||
724 | ser_device_t *add_ser_mouse_entry(ser_device_t **sm, ser_device_t *new_sm) | |
725 | { | |
726 | while(*sm) sm = &(*sm)->next; | |
727 | return *sm = new_sm; | |
728 | } | |
729 | ||
730 | ||
731 | void dump_ser_mouse_data(hd_data_t *hd_data) | |
732 | { | |
733 | int j; | |
734 | ser_device_t *sm; | |
735 | ||
736 | if(!(sm = hd_data->ser_mouse)) return; | |
737 | ||
738 | ADD2LOG("----- serial mice -----\n"); | |
739 | ||
740 | for(; sm; sm = sm->next) { | |
741 | ADD2LOG("%s\n", sm->dev_name); | |
742 | if(sm->serial) ADD2LOG("serial: \"%s\"\n", sm->serial); | |
743 | if(sm->class_name) ADD2LOG("class_name: \"%s\"\n", sm->class_name); | |
744 | if(sm->dev_id) ADD2LOG("dev_id: \"%s\"\n", sm->dev_id); | |
745 | if(sm->user_name) ADD2LOG("user_name: \"%s\"\n", sm->user_name); | |
746 | ||
747 | if(sm->garbage) { | |
748 | ADD2LOG(" garbage[%u]: ", sm->garbage); | |
749 | hexdump(&hd_data->log, 1, sm->garbage, sm->buf); | |
750 | ADD2LOG("\n"); | |
751 | } | |
752 | ||
753 | if(sm->non_pnp) { | |
754 | ADD2LOG(" non-pnp[%u]: ", sm->non_pnp); | |
755 | hexdump(&hd_data->log, 1, sm->non_pnp, sm->buf + sm->garbage); | |
756 | ADD2LOG("\n"); | |
757 | } | |
758 | ||
759 | if(sm->pnp) { | |
760 | ADD2LOG(" pnp[%u]: ", sm->pnp); | |
761 | hexdump(&hd_data->log, 1, sm->pnp, sm->buf + sm->garbage + sm->non_pnp); | |
762 | ADD2LOG("\n"); | |
763 | } | |
764 | ||
765 | if((j = sm->buf_len - (sm->garbage + sm->non_pnp + sm->pnp))) { | |
766 | ADD2LOG(" moves[%u]: ", j); | |
767 | hexdump(&hd_data->log, 1, j, sm->buf + sm->garbage + sm->non_pnp + sm->pnp); | |
768 | ADD2LOG("\n"); | |
769 | } | |
770 | ||
771 | if(sm->is_mouse) ADD2LOG(" is mouse\n"); | |
772 | ||
773 | if(sm->pnp) { | |
774 | ADD2LOG(" bits: %u\n", sm->bits); | |
775 | ADD2LOG(" PnP Rev: %u.%02u\n", sm->pnp_rev / 100, sm->pnp_rev % 100); | |
776 | ADD2LOG(" PnP ID: \"%s\"\n", sm->pnp_id); | |
777 | } | |
778 | ||
779 | if(sm->next) ADD2LOG("\n"); | |
780 | } | |
781 | ||
782 | ADD2LOG("----- serial mice end -----\n"); | |
783 | } | |
784 | ||
785 | #endif /* !defined(LIBHD_TINY) */ |