]> git.ipfire.org Git - people/teissler/ipfire-2.x.git/blame - src/hwinfo/src/hd/mouse.c
Kleiner netter neuer Versuch.
[people/teissler/ipfire-2.x.git] / src / hwinfo / src / hd / mouse.c
CommitLineData
a6316ce4
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
28static unsigned read_data(hd_data_t *hd_data, int fd, unsigned char *buf, unsigned buf_size);
29static void get_ps2_mouse(hd_data_t *hd_data);
30static void test_ps2_open(void *arg);
31#endif
32
33static void get_serial_mouse(hd_data_t* hd_data);
34static void add_serial_mouse(hd_data_t* hd_data);
35static int _setspeed(int fd, int old, int new, int needtowrite, unsigned short flags);
36static void setspeed(int fd, int new, int needtowrite, unsigned short flags);
37static unsigned chk4id(ser_device_t *mi);
38static ser_device_t *add_ser_mouse_entry(ser_device_t **sm, ser_device_t *new_sm);
39static void dump_ser_mouse_data(hd_data_t *hd_data);
40#if 0
41static void get_sunmouse(hd_data_t *hd_data);
42#endif
43
44void 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
100unsigned 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
147static 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
326void test_ps2_open(void *arg)
327{
328 open(DEV_PSAUX, O_RDWR | O_NONBLOCK);
329}
330#endif
331
332#if 0
333static 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 */
376void 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 */
464void 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
523int _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
572void 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 */
595int 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
681unsigned 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
724ser_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
731void 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) */