Updated debian and rpm binary packages for Desktop evolution dependency
[barry/progweb.git] / usbmon-6 / usbmon.c
blob5261a359d6d412d3e3ea62b0b930c7c4ca3e75a2
1 /*
2 * usbmon-6, from http://people.redhat.com/zaitcev/linux/
3 * Modified by Chris Frey to comment out the root requirement
4 * and change the human hex dump format.
5 */
7 /*
8 * usbmon: Front-end for usbmon
10 * Copyright (C) 2005 Pete Zaitcev (zaitcev@redhat.com)
11 * Copyright (c) 2007 Red Hat, Inc.
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License version 2 as
15 * published by the Free Software Foundation.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License along
23 * with this program; if not, write to the Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 * The function print_48 is a fork of mon_text_read from ancient kernels
27 * (thus we are perfectly compatible with '1t' format), so we use GPL v2.
28 * If someone rewrites print_foo from scratch, we can use any GPL >= 2.
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <string.h>
33 #include <errno.h>
34 #include <fcntl.h>
35 #include <limits.h>
36 #include <ctype.h>
37 #include <unistd.h>
38 #include <sys/ioctl.h>
39 #include <sys/stat.h>
40 #include <sys/mman.h>
41 #include <inttypes.h>
42 #include <stdarg.h>
44 #define TAG "usbmon"
46 #ifdef __GNUC__
47 #define __unused __attribute__((unused))
48 #else
49 #define __unused /**/
50 #endif
52 #define usb_typeint(type) (((type)&0x3) == PIPE_INTERRUPT)
53 #define usb_typeisoc(type) (((type)&0x3) == PIPE_ISOCHRONOUS)
55 struct usbmon_packet {
56 uint64_t id; /* URB ID - from submission to callback */
57 unsigned char type; /* Same as in text API; extensible. */
58 unsigned char xfer_type; /* ISO, Intr, Control, Bulk */
59 unsigned char epnum; /* Endpoint number; 0x80 IN */
60 unsigned char devnum; /* Device address */
61 unsigned short busnum; /* Bus number */
62 char flag_setup;
63 char flag_data;
64 int64_t ts_sec; /* gettimeofday */
65 int32_t ts_usec; /* gettimeofday */
66 int status;
67 unsigned int length; /* Length of data (submitted or actual) */
68 unsigned int len_cap; /* Delivered length */
69 unsigned char setup[8]; /* Only for Control S-type */
72 struct usbmon_packet_1 {
73 uint64_t id; /* URB ID - from submission to callback */
74 unsigned char type; /* Same as in text API; extensible. */
75 unsigned char xfer_type; /* ISO, Intr, Control, Bulk */
76 unsigned char epnum; /* Endpoint number; 0x80 IN */
77 unsigned char devnum; /* Device address */
78 unsigned short busnum; /* Bus number */
79 char flag_setup;
80 char flag_data;
81 int64_t ts_sec; /* gettimeofday */
82 int32_t ts_usec; /* gettimeofday */
83 int status;
84 unsigned int length; /* Length of data (submitted or actual) */
85 unsigned int len_cap; /* Delivered length */
86 union {
87 unsigned char setup[8]; /* Only for Control S-type */
88 struct iso_rec {
89 int error_count;
90 int numdesc; /* Number from the URB */
91 } iso;
92 } s;
93 int interval;
94 int start_frame;
95 unsigned int xfer_flags;
96 unsigned int ndesc; /* Actual number of ISO descriptors */
99 struct usbmon_isodesc {
100 int iso_stat;
101 unsigned int iso_off;
102 unsigned int iso_len;
103 int iso_pad;
107 * Size this so that we see data even if many descriptors are used.
108 * Notice that we reserve enough print buffer for all of them.
110 #define ISODESC_MAX 8
112 #define PIPE_ISOCHRONOUS 0
113 #define PIPE_INTERRUPT 1
114 #define PIPE_CONTROL 2
115 #define PIPE_BULK 3
117 #define MON_IOC_MAGIC 0x92
119 #define MON_IOCG_STATS _IOR(MON_IOC_MAGIC, 3, struct usbmon_stats)
121 #define MON_IOCT_RING_SIZE _IO(MON_IOC_MAGIC, 4)
123 #define MON_IOCQ_RING_SIZE _IO(MON_IOC_MAGIC, 5)
125 struct usbmon_get_arg {
126 struct usbmon_packet_1 *hdr; /* Only 48 bytes, not 64. */
127 void *data;
128 size_t alloc; /* Length of data (can be zero) */
131 #define MON_IOCX_GET _IOW(MON_IOC_MAGIC, 6, struct usbmon_get_arg)
133 #define MON_IOCX_GETX _IOW(MON_IOC_MAGIC, 10, struct usbmon_get_arg)
135 struct usbmon_mfetch_arg {
136 unsigned int *offvec; /* Vector of events fetched */
137 unsigned int nfetch; /* Num. of events to fetch / fetched */
138 unsigned int nflush; /* Number of events to flush */
141 #define MON_IOCX_MFETCH _IOWR(MON_IOC_MAGIC, 7, struct usbmon_mfetch_arg)
145 enum text_format {
146 TFMT_OLD, /* The v0 text API aka "1t" */
147 TFMT_1U, /* The "1u" text format */
148 TFMT_HUMAN /* Human-oriented format, changes over time. */
151 enum usbmon_api {
152 API_ANY,
153 API_B0, /* Old binary (48 bytes usbmon_packet) */
154 API_B1, /* New binary (64 bytes usbmon_packet_1) */
155 API_B1M /* New binary (64 bytes usbmon_packet_1) + mmap(2) */
158 struct params {
159 int ifnum; /* USB bus number */
160 char *devname; /* /dev/usbmonN */
161 int data_size; /* How many bytes to fetch, including ISO descriptors */
162 int data_max; /* How many bytes to print as data (<= data_size) */
163 enum text_format format;
164 enum usbmon_api api;
166 int map_size;
168 char *print_buf;
169 int print_size;
172 enum { DATA_MAX = 32 }; /* Old limit used with 1t format (print_48) */
174 struct print_cursor {
175 char *pbuf;
176 int size;
177 int count; /* without the terminating nul */
180 void Usage(void);
182 void print(const struct params *, const struct usbmon_packet_1 *ep,
183 const unsigned char *data);
184 void print_48(const struct params *, const struct usbmon_packet *ep,
185 const unsigned char *data);
186 void print_1u(const struct params *, const struct usbmon_packet_1 *ep,
187 const unsigned char *data);
188 void print_human(const struct params *, const struct usbmon_packet_1 *ep,
189 const unsigned char *data, uint64_t start_sec);
190 static void print_human_data(struct print_cursor *curp,
191 const struct usbmon_packet_1 *ep, const unsigned char *data, int data_len);
192 static void print_start(struct print_cursor *, char *buf, int size0);
193 static void print_safe(struct print_cursor *, const char *fmt, ...);
194 static int print_done(struct print_cursor *);
195 void parse_params(struct params *p, char **argv);
196 void make_device(const struct params *p);
197 int find_major(void);
199 struct params par;
201 int main(int argc __unused, char **argv)
203 int fd;
204 struct usbmon_packet_1 hdrb;
205 struct usbmon_packet_1 *hdr;
206 struct usbmon_get_arg getb;
207 enum { MFETCH_NM = 3 };
208 unsigned int offs[MFETCH_NM];
209 unsigned int off;
210 struct usbmon_mfetch_arg mfb;
211 unsigned char *data_buff;
212 unsigned int toflush;
213 int i;
214 int rc;
216 if (sizeof(struct usbmon_packet) != 48) {
217 extern void usbmon_packet_size_is_bolixed(void);
218 usbmon_packet_size_is_bolixed(); /* link-time error */
220 if (sizeof(struct usbmon_packet_1) != 64) {
221 extern void usbmon_packet_1_size_is_bolixed(void);
222 usbmon_packet_1_size_is_bolixed(); /* link-time error */
225 parse_params(&par, argv+1);
228 * Two reasons to do this:
229 * 1. Reduce weird error messages.
230 * 2. If we create device nodes, we want them owned by root.
232 // if (geteuid() != 0) {
233 // fprintf(stderr, TAG ": Must run as root\n");
234 // exit(1);
235 // }
237 if ((fd = open(par.devname, O_RDWR)) == -1) {
238 if (errno == ENOENT) {
239 make_device(&par);
240 fd = open(par.devname, O_RDWR);
242 if (fd == -1) {
243 if (errno == ENODEV && par.ifnum == 0) {
244 fprintf(stderr, TAG
245 ": Can't open pseudo-bus zero at %s"
246 " (probably not supported by kernel)\n",
247 par.devname);
248 } else {
249 fprintf(stderr, TAG ": Can't open %s: %s\n",
250 par.devname, strerror(errno));
252 exit(1);
257 if (par.api == API_B1M) {
258 rc = ioctl(fd, MON_IOCQ_RING_SIZE, 0);
259 if (rc == -1) {
260 fprintf(stderr, TAG ": Cannot get ring size: %s\n",
261 strerror(errno));
262 exit(1);
264 printf("Ring size: %d\n", rc); /* P3 */
265 par.map_size = rc;
266 data_buff = mmap(0, par.map_size, PROT_READ, MAP_SHARED, fd, 0);
267 if (data_buff == MAP_FAILED) {
268 fprintf(stderr, TAG ": Cannot mmap: %s\n",
269 strerror(errno));
270 exit(1);
272 } else {
273 if ((data_buff = malloc(par.data_size)) == NULL) {
274 fprintf(stderr, TAG ": No core\n");
275 exit(1);
279 if (par.format == TFMT_HUMAN && par.api == API_B0) {
281 * Zero fields which are not present in old (zero) API
283 memset(&hdrb, 0, sizeof(struct usbmon_packet_1));
284 } else {
286 * Make uninitialized fields visible.
288 memset(&hdrb, 0xdb, sizeof(struct usbmon_packet_1));
291 toflush = 0;
292 for (;;) {
293 if (par.api == API_B0) {
294 getb.hdr = &hdrb;
295 getb.data = data_buff;
296 getb.alloc = par.data_size;
297 if ((rc = ioctl(fd, MON_IOCX_GET, &getb)) != 0) {
298 fprintf(stderr, TAG ": MON_IOCX_GET: %s\n",
299 strerror(errno));
300 exit(1);
302 print(&par, &hdrb, data_buff);
303 } else if (par.api == API_B1) {
304 getb.hdr = &hdrb;
305 getb.data = data_buff;
306 getb.alloc = par.data_size;
307 if ((rc = ioctl(fd, MON_IOCX_GETX, &getb)) != 0) {
308 fprintf(stderr, TAG ": MON_IOCX_GETX: %s\n",
309 strerror(errno));
310 exit(1);
312 print(&par, &hdrb, data_buff);
313 } else if (par.api == API_B1M) {
314 mfb.offvec = offs;
315 mfb.nfetch = MFETCH_NM;
316 mfb.nflush = toflush;
317 if ((rc = ioctl(fd, MON_IOCX_MFETCH, &mfb)) != 0) {
318 fprintf(stderr, TAG ": MON_IOCX_MFETCH: %s\n",
319 strerror(errno));
320 exit(1);
322 for (i = 0; i < mfb.nfetch; i++) {
323 off = offs[i];
324 if (off >= par.map_size) {
325 fprintf(stderr, TAG ": offset\n");
326 continue;
328 hdr = (struct usbmon_packet_1 *)(data_buff + off);
329 if (hdr->type == '@')
330 continue;
331 print(&par, hdr, (const unsigned char *)(hdr + 1));
333 toflush = mfb.nfetch;
334 } else {
335 getb.hdr = &hdrb;
336 getb.data = data_buff;
337 getb.alloc = par.data_size;
338 if ((rc = ioctl(fd, MON_IOCX_GETX, &getb)) != 0) {
339 if (errno == ENOTTY) {
340 par.api = API_B0;
341 rc = ioctl(fd, MON_IOCX_GET, &getb);
342 if (rc != 0) {
343 fprintf(stderr, TAG
344 ": MON_IOCX_GET: %s\n",
345 strerror(errno));
346 exit(1);
348 } else {
349 fprintf(stderr, TAG
350 ": MON_IOCX_GETX: %s\n",
351 strerror(errno));
352 exit(1);
355 print(&par, &hdrb, data_buff);
359 // return 0;
362 void print(const struct params *prm, const struct usbmon_packet_1 *ep,
363 const unsigned char *data)
365 static uint64_t start_sec = 0;
367 switch (par.format) {
368 case TFMT_OLD:
370 * Old and new APIs are made compatible just so we
371 * can cast like this.
373 print_48(&par, (struct usbmon_packet *) ep, data);
374 break;
375 case TFMT_1U:
376 print_1u(&par, ep, data);
377 break;
378 default: /* TFMT_HUMAN */
379 if (start_sec == 0)
380 start_sec = ep->ts_sec;
381 print_human(&par, ep, data, start_sec);
385 void print_48(const struct params *prm, const struct usbmon_packet *ep,
386 const unsigned char *data)
388 struct print_cursor pcur;
389 char udir, utype;
390 int data_len, i;
391 int cnt;
392 ssize_t rc;
394 print_start(&pcur, prm->print_buf, prm->print_size);
396 udir = ((ep->epnum & 0x80) != 0) ? 'i' : 'o';
397 switch (ep->xfer_type & 0x3) {
398 case PIPE_ISOCHRONOUS: utype = 'Z'; break;
399 case PIPE_INTERRUPT: utype = 'I'; break;
400 case PIPE_CONTROL: utype = 'C'; break;
401 default: /* PIPE_BULK */ utype = 'B';
403 print_safe(&pcur,
404 "%llx %u %c %c%c:%03u:%02u",
405 (long long) ep->id,
406 (unsigned int)(ep->ts_sec & 0xFFF) * 1000000 + ep->ts_usec,
407 ep->type,
408 utype, udir, ep->devnum, ep->epnum & 0x7f);
410 if (ep->flag_setup == 0) { /* Setup packet is present and captured */
411 print_safe(&pcur,
412 " s %02x %02x %04x %04x %04x",
413 ep->setup[0],
414 ep->setup[1],
415 (ep->setup[3] << 8) | ep->setup[2],
416 (ep->setup[5] << 8) | ep->setup[4],
417 (ep->setup[7] << 8) | ep->setup[6]);
418 } else if (ep->flag_setup != '-') { /* Unable to capture setup packet */
419 print_safe(&pcur,
420 " %c __ __ ____ ____ ____", ep->flag_setup);
421 } else { /* No setup for this kind of URB */
422 print_safe(&pcur, " %d", ep->status);
424 print_safe(&pcur, " %d", ep->length);
426 if (ep->length > 0) {
427 if (ep->flag_data == 0) {
428 print_safe(&pcur, " =");
429 if ((data_len = ep->len_cap) >= DATA_MAX)
430 data_len = DATA_MAX;
431 for (i = 0; i < data_len; i++) {
432 if (i % 4 == 0) {
433 print_safe(&pcur, " ");
435 print_safe(&pcur, "%02x", data[i]);
437 print_safe(&pcur, "\n");
438 } else {
439 print_safe(&pcur, " %c\n", ep->flag_data);
441 } else {
442 print_safe(&pcur, "\n");
445 cnt = print_done(&pcur);
446 if ((rc = write(1, prm->print_buf, cnt)) < cnt) {
447 if (rc < 0) {
448 fprintf(stderr, TAG ": Write error: %s\n",
449 strerror(errno));
450 } else {
451 fprintf(stderr, TAG ": Short write\n");
453 exit(1);
457 void print_1u(const struct params *prm, const struct usbmon_packet_1 *ep,
458 const unsigned char *data)
460 struct print_cursor pcur;
461 char udir, utype;
462 int data_len, i;
463 int ndesc; /* Display this many */
464 const struct usbmon_isodesc *dp;
465 int cnt;
466 ssize_t rc;
468 print_start(&pcur, prm->print_buf, prm->print_size);
470 if ((data_len = ep->len_cap) < 0) { /* Overflow */
471 data_len = 0;
474 udir = ((ep->epnum & 0x80) != 0) ? 'i' : 'o';
475 switch (ep->xfer_type & 0x3) {
476 case PIPE_ISOCHRONOUS: utype = 'Z'; break;
477 case PIPE_INTERRUPT: utype = 'I'; break;
478 case PIPE_CONTROL: utype = 'C'; break;
479 default: /* PIPE_BULK */ utype = 'B';
481 print_safe(&pcur,
482 "%llx %u %c %c%c:%u:%03u:%u",
483 (long long) ep->id,
484 (unsigned int)(ep->ts_sec & 0xFFF) * 1000000 + ep->ts_usec,
485 ep->type,
486 utype, udir, ep->busnum, ep->devnum, ep->epnum & 0x7f);
488 if (ep->type == 'E') {
489 print_safe(&pcur, " %d", ep->status);
490 } else {
491 if (ep->flag_setup == 0) {
492 /* Setup packet is present and captured */
493 print_safe(&pcur,
494 " s %02x %02x %04x %04x %04x",
495 ep->s.setup[0],
496 ep->s.setup[1],
497 (ep->s.setup[3] << 8) | ep->s.setup[2],
498 (ep->s.setup[5] << 8) | ep->s.setup[4],
499 (ep->s.setup[7] << 8) | ep->s.setup[6]);
500 } else if (ep->flag_setup != '-') {
501 /* Unable to capture setup packet */
502 print_safe(&pcur,
503 " %c __ __ ____ ____ ____", ep->flag_setup);
504 } else {
505 /* No setup for this kind of URB */
506 print_safe(&pcur, " %d", ep->status);
507 if (usb_typeisoc(ep->xfer_type) ||
508 usb_typeint(ep->xfer_type)) {
509 print_safe(&pcur, ":%d", ep->interval);
511 if (usb_typeisoc(ep->xfer_type)) {
512 print_safe(&pcur, ":%d", ep->start_frame);
513 if (ep->type == 'C') {
514 print_safe(&pcur,
515 ":%d", ep->s.iso.error_count);
519 if (usb_typeisoc(ep->xfer_type)) {
521 * This is the number of descriptors used by HC.
523 print_safe(&pcur, " %d", ep->s.iso.numdesc);
526 * This is the number of descriptors which we print.
528 ndesc = ep->ndesc;
529 if (ndesc > ISODESC_MAX)
530 ndesc = ISODESC_MAX;
531 if (ndesc * sizeof(struct usbmon_isodesc) > data_len) {
532 ndesc = data_len / sizeof(struct usbmon_isodesc);
534 /* This is aligned by malloc */
535 dp = (struct usbmon_isodesc *) data;
536 for (i = 0; i < ndesc; i++) {
537 print_safe(&pcur,
538 " %d:%u:%u",
539 dp->iso_stat, dp->iso_off, dp->iso_len);
540 dp++;
544 * The number of descriptors captured is used to
545 * find where the data starts.
547 ndesc = ep->ndesc;
548 if (ndesc * sizeof(struct usbmon_isodesc) > data_len) {
549 data_len = 0;
550 } else {
551 data += ndesc * sizeof(struct usbmon_isodesc);
552 data_len -= ndesc * sizeof(struct usbmon_isodesc);
557 print_safe(&pcur, " %d", ep->length);
559 if (ep->length > 0) {
560 if (ep->flag_data == 0) {
561 print_safe(&pcur, " =");
562 if (data_len >= prm->data_max)
563 data_len = prm->data_max;
564 for (i = 0; i < data_len; i++) {
565 if (i % 4 == 0) {
566 print_safe(&pcur, " ");
568 print_safe(&pcur, "%02x", data[i]);
570 print_safe(&pcur, "\n");
571 } else {
572 print_safe(&pcur, " %c\n", ep->flag_data);
574 } else {
575 print_safe(&pcur, "\n");
578 cnt = print_done(&pcur);
579 if ((rc = write(1, prm->print_buf, cnt)) < cnt) {
580 if (rc < 0) {
581 fprintf(stderr, TAG ": Write error: %s\n",
582 strerror(errno));
583 } else {
584 fprintf(stderr, TAG ": Short write\n");
586 exit(1);
590 void print_human(const struct params *prm, const struct usbmon_packet_1 *ep,
591 const unsigned char *data, uint64_t start_sec)
593 struct print_cursor pcur;
594 char udir, utype;
595 int data_len, i;
596 int ndesc; /* Display this many */
597 const struct usbmon_isodesc *dp;
598 int cnt;
599 ssize_t rc;
601 print_start(&pcur, prm->print_buf, prm->print_size);
603 if ((data_len = ep->len_cap) < 0) { /* Overflow */
604 data_len = 0;
607 #if 0
608 enum { TAG_BUF_SIZE = 17 };
609 char tag_buf[TAG_BUF_SIZE];
610 print_human_tag(tag_buf, TAG_BUF_SIZE, prm->tagp, ep);
611 #endif
613 * We cast into a truncated type for readability.
614 * The danger of collisions is negligible.
616 print_safe(&pcur, "%08x", (unsigned int) ep->id);
618 udir = ((ep->epnum & 0x80) != 0) ? 'i' : 'o';
619 switch (ep->xfer_type & 0x3) {
620 case PIPE_ISOCHRONOUS: utype = 'Z'; break;
621 case PIPE_INTERRUPT: utype = 'I'; break;
622 case PIPE_CONTROL: utype = 'C'; break;
623 default: /* PIPE_BULK */ utype = 'B';
625 print_safe(&pcur,
626 " %u.%06u %c %c%c:%u:%03u:%u",
627 (unsigned int)(ep->ts_sec - start_sec), ep->ts_usec,
628 ep->type,
629 utype, udir, ep->busnum, ep->devnum, ep->epnum & 0x7f);
631 if (ep->type == 'E') {
632 print_safe(&pcur, " %d", ep->status);
633 } else {
634 if (ep->flag_setup == 0) {
635 /* Setup packet is present and captured */
636 print_safe(&pcur,
637 " s %02x %02x %04x %04x %04x",
638 ep->s.setup[0],
639 ep->s.setup[1],
640 (ep->s.setup[3] << 8) | ep->s.setup[2],
641 (ep->s.setup[5] << 8) | ep->s.setup[4],
642 (ep->s.setup[7] << 8) | ep->s.setup[6]);
643 } else if (ep->flag_setup != '-') {
644 /* Unable to capture setup packet */
645 print_safe(&pcur,
646 " %c __ __ ____ ____ ____", ep->flag_setup);
647 } else {
648 /* No setup for this kind of URB */
649 if (ep->type == 'S' && ep->status == -EINPROGRESS) {
650 print_safe(&pcur, " -");
651 } else {
652 print_safe(&pcur, " %d", ep->status);
654 if (usb_typeisoc(ep->xfer_type) ||
655 usb_typeint(ep->xfer_type)) {
656 print_safe(&pcur, ":%d", ep->interval);
658 if (usb_typeisoc(ep->xfer_type)) {
659 print_safe(&pcur, ":%d", ep->start_frame);
660 if (ep->type == 'C') {
661 print_safe(&pcur,
662 ":%d", ep->s.iso.error_count);
666 if (usb_typeisoc(ep->xfer_type)) {
668 * This is the number of descriptors used by HC.
670 print_safe(&pcur, " %d", ep->s.iso.numdesc);
673 * This is the number of descriptors which we print.
675 ndesc = ep->ndesc;
676 if (ndesc > ISODESC_MAX)
677 ndesc = ISODESC_MAX;
678 if (ndesc * sizeof(struct usbmon_isodesc) > data_len) {
679 ndesc = data_len / sizeof(struct usbmon_isodesc);
681 /* This is aligned by malloc */
682 dp = (struct usbmon_isodesc *) data;
683 for (i = 0; i < ndesc; i++) {
684 print_safe(&pcur,
685 " %d:%u:%u",
686 dp->iso_stat, dp->iso_off, dp->iso_len);
687 dp++;
691 * The number of descriptors captured is used to
692 * find where the data starts.
694 ndesc = ep->ndesc;
695 if (ndesc * sizeof(struct usbmon_isodesc) > data_len) {
696 data_len = 0;
697 } else {
698 data += ndesc * sizeof(struct usbmon_isodesc);
699 data_len -= ndesc * sizeof(struct usbmon_isodesc);
704 print_safe(&pcur, " %d", ep->length);
706 if (ep->length > 0) {
707 if (ep->flag_data == 0) {
708 print_safe(&pcur, " =\n");
709 if (data_len >= prm->data_max)
710 data_len = prm->data_max;
711 print_human_data(&pcur, ep, data, data_len);
712 } else {
713 print_safe(&pcur, " %c\n", ep->flag_data);
715 } else {
716 print_safe(&pcur, "\n");
719 cnt = print_done(&pcur);
720 if ((rc = write(1, prm->print_buf, cnt)) < cnt) {
721 if (rc < 0) {
722 fprintf(stderr, TAG ": Write error: %s\n",
723 strerror(errno));
724 } else {
725 fprintf(stderr, TAG ": Short write\n");
727 exit(1);
731 static void print_human_data(struct print_cursor *curs,
732 const struct usbmon_packet_1 *ep, const unsigned char *data, int data_len)
734 int i, j;
736 for (i = 0; i < data_len; i++) {
737 print_safe(curs, " ");
739 for (j = 0; j < 16; j++) {
740 if (i+j < data_len)
741 print_safe(curs, "%02x ", data[i+j]);
742 else
743 print_safe(curs, " ");
744 if (j == 7)
745 print_safe(curs, " ");
748 print_safe(curs, " ");
750 for (j = 0; j < 16; j++, i++) {
751 if (i < data_len)
752 print_safe(curs, "%c",
753 isprint(data[i]) ? data[i] : '.');
754 else
755 print_safe(curs, " ");
756 if (j == 7)
757 print_safe(curs, " ");
759 print_safe(curs, "\n");
761 print_safe(curs, "\n");
765 * This code works perfectly, but it's a stupendously bad idea. The reason is,
766 * everyone doing any serious investigation uses a text editor. And in such
767 * a case, omitting a variable size prefix from a tag makes searching hard.
768 * Hit "*" in vim to highlight identical tags.
770 #if 0
772 struct tag_state {
773 uint64_t common_bits;
774 unsigned int mask_length; /* Mask for common_bits */
775 char format[sizeof("..%0NNllx")];
779 * Print a usbmon event tag into a buffer.
781 static void print_human_tag(char *tag_buf, int tag_buf_size,
782 struct tag_state *p, const struct usbmon_packet_1 *ep)
784 uint64_t mask = (~(uint64_t)0) << (64 - p->mask_length);
786 if (p->common_bits == 0) {
787 snprintf(tag_buf, tag_buf_size, "%016llx", (long long) ep->id);
788 p->common_bits = ep->id;
789 p->mask_length = 48;
790 sprintf(p->format,
791 "..%%0%dllx", (64 - p->mask_length) / 4);
792 return;
795 if ((ep->id & mask) != (p->common_bits & mask)) {
796 while ((ep->id & mask) != (p->common_bits & mask) &&
797 p->mask_length != 0) {
798 mask <<= 8;
799 p->mask_length -= 8;
801 if (p->mask_length != 0) {
802 sprintf(p->format,
803 "..%%0%dllx", (64 - p->mask_length) / 4);
804 } else {
805 strcpy(p->format, "%016llx");
808 snprintf(tag_buf, tag_buf_size, p->format, (long long) ep->id & ~mask);
810 #endif
812 static void print_start(struct print_cursor *t, char *buf, int size0)
814 t->pbuf = buf;
815 t->size = size0;
816 t->count = 0;
819 static void print_safe(struct print_cursor *t, const char *fmt, ...)
821 va_list ap;
822 int len;
824 if (t->count+1 >= t->size)
825 return;
827 va_start(ap, fmt);
828 len = vsnprintf(t->pbuf + t->count, t->size - t->count, fmt, ap);
829 t->count += len;
830 va_end(ap);
833 static int print_done(struct print_cursor *t)
835 return t->count;
838 void parse_params(struct params *p, char **argv)
840 char *arg;
841 long num;
843 memset(p, 0, sizeof(struct params));
844 p->data_max = DATA_MAX; /* Same as 1t text API. */
845 p->format = TFMT_HUMAN;
846 p->api = API_ANY;
848 while ((arg = *argv++) != NULL) {
849 if (arg[0] == '-') {
850 if (arg[1] == 0)
851 Usage();
852 switch (arg[1]) {
853 case 'i':
854 if (arg[2] != 0)
855 Usage();
856 if ((arg = *argv++) == NULL)
857 Usage();
858 if (strncmp(arg, "usb", 3) == 0)
859 arg += 3;
860 if (!isdigit(arg[0]))
861 Usage();
862 errno = 0;
863 num = strtol(arg, NULL, 10);
864 if (errno != 0)
865 Usage();
866 if (num < 0 || num >= 128) {
867 fprintf(stderr, TAG ": Bus number %ld"
868 " is out of bounds\n", num);
869 exit(2);
871 p->ifnum = num;
872 break;
873 case 'f':
874 switch (arg[2]) {
875 case '0':
876 p->format = TFMT_OLD;
877 break;
878 case 'u':
879 p->format = TFMT_1U;
880 break;
881 case 'h':
882 p->format = TFMT_HUMAN;
883 break;
884 default:
885 Usage();
887 break;
888 case 'a':
889 switch (arg[2]) {
890 case '0':
891 p->api = API_B0;
892 break;
893 case '1':
894 p->api = API_B1;
895 break;
896 case 'm':
897 p->api = API_B1M;
898 break;
899 default:
900 Usage();
902 break;
903 case 's':
904 if (arg[2] != 0)
905 Usage();
906 if ((arg = *argv++) == NULL)
907 Usage();
908 if (!isdigit(arg[0]))
909 Usage();
910 errno = 0;
911 num = strtol(arg, NULL, 10);
912 if (errno != 0)
913 Usage();
914 if (num < 0) {
915 fprintf(stderr, TAG
916 ": negative size %ld\n", num);
917 exit(1);
919 p->data_max = num;
920 break;
921 default:
922 Usage();
924 } else {
925 Usage();
929 if (p->data_size == 0) {
930 p->data_size = p->data_max + 96;
933 if (p->devname == NULL) {
934 if ((p->devname = malloc(100)) == NULL) {
935 fprintf(stderr, TAG ": No core\n");
936 exit(1);
938 snprintf(p->devname, 100, "/dev/usbmon%d", p->ifnum);
941 if (p->format == TFMT_1U)
942 p->api = API_B1;
945 * This is somewhat approximate, but seems like not overflowing.
946 * We cannot rely on print_safe, because when it triggers it violates
947 * the documented output format. It only exists to prevent crashes.
949 if (p->format == TFMT_OLD) {
950 if (p->data_max != DATA_MAX) {
951 fprintf(stderr, TAG ": -f0 requires -s 32\n");
952 exit(1);
954 p->print_size = 160;
955 } else {
956 p->print_size = 100;
957 p->print_size += (((p->data_max+3)/4 * 9) + 5) * 2;
958 p->print_size += 10 + ISODESC_MAX*26; /* " %d:%u:%u" */
960 if ((p->print_buf = malloc(p->print_size)) == NULL) {
961 fprintf(stderr, TAG ": No core\n");
962 exit(1);
966 void make_device(const struct params *p)
968 int major;
969 dev_t dev;
971 major = find_major();
972 dev = makedev(major, p->ifnum);
973 if (mknod(p->devname, S_IFCHR|S_IRUSR|S_IWUSR, dev) != 0) {
974 fprintf(stderr, TAG ": Can't make device %s: %s\n",
975 p->devname, strerror(errno));
976 exit(1);
980 int find_major(void)
982 long num;
983 FILE *df;
984 enum { LEN = 50 };
985 char buff[LEN], c, *p;
986 char *major, *mname;
988 if ((df = fopen("/proc/devices", "r")) == NULL) {
989 fprintf(stderr, TAG ": Can't open /proc/devices\n");
990 exit(1);
992 num = -1;
993 while (fgets(buff, LEN, df) != NULL) {
994 p = buff;
995 major = NULL;
996 mname = NULL;
997 for (p = buff; (c = *p) != 0; p++) {
998 if (major == NULL) {
999 if (c != ' ') {
1000 major = p;
1002 } else if (mname == NULL) {
1003 if (!isdigit(c) && c != ' ') {
1004 mname = p;
1006 } else {
1007 if (c == '\n') {
1008 *p = 0;
1009 break;
1013 if (major != NULL && mname != NULL) {
1014 if (strcmp(mname, "usbmon") == 0) {
1015 errno = 0;
1016 num = strtol(major, NULL, 10);
1017 if (errno != 0) {
1018 fprintf(stderr, TAG ": Syntax error "
1019 "in /proc/devices\n");
1020 exit(1);
1022 break;
1026 fclose(df);
1028 if (num == -1) {
1029 fprintf(stderr, TAG ": Can't find usbmon in /proc/devices\n");
1030 exit(1);
1033 if (num <= 0 || num > INT_MAX) {
1034 fprintf(stderr, TAG ": Weird major %ld in /proc/devices\n",
1035 num);
1036 exit(1);
1039 return (int) num;
1042 void Usage(void)
1044 fprintf(stderr, "Usage: "
1045 "usbmon [-i usbN] [-f0|-fu|-fh] [-a0|-a1|-am] [-s len]\n");
1046 exit(2);