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.
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.
38 #include <sys/ioctl.h>
47 #define __unused __attribute__((unused))
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 */
64 int64_t ts_sec
; /* gettimeofday */
65 int32_t ts_usec
; /* gettimeofday */
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 */
81 int64_t ts_sec
; /* gettimeofday */
82 int32_t ts_usec
; /* gettimeofday */
84 unsigned int length
; /* Length of data (submitted or actual) */
85 unsigned int len_cap
; /* Delivered length */
87 unsigned char setup
[8]; /* Only for Control S-type */
90 int numdesc
; /* Number from the URB */
95 unsigned int xfer_flags
;
96 unsigned int ndesc
; /* Actual number of ISO descriptors */
99 struct usbmon_isodesc
{
101 unsigned int iso_off
;
102 unsigned int iso_len
;
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
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. */
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)
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. */
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) */
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
;
172 enum { DATA_MAX
= 32 }; /* Old limit used with 1t format (print_48) */
174 struct print_cursor
{
177 int count
; /* without the terminating nul */
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);
201 int main(int argc __unused
, char **argv
)
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
];
210 struct usbmon_mfetch_arg mfb
;
211 unsigned char *data_buff
;
212 unsigned int toflush
;
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");
237 if ((fd
= open(par
.devname
, O_RDWR
)) == -1) {
238 if (errno
== ENOENT
) {
240 fd
= open(par
.devname
, O_RDWR
);
243 if (errno
== ENODEV
&& par
.ifnum
== 0) {
245 ": Can't open pseudo-bus zero at %s"
246 " (probably not supported by kernel)\n",
249 fprintf(stderr
, TAG
": Can't open %s: %s\n",
250 par
.devname
, strerror(errno
));
257 if (par
.api
== API_B1M
) {
258 rc
= ioctl(fd
, MON_IOCQ_RING_SIZE
, 0);
260 fprintf(stderr
, TAG
": Cannot get ring size: %s\n",
264 printf("Ring size: %d\n", rc
); /* P3 */
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",
273 if ((data_buff
= malloc(par
.data_size
)) == NULL
) {
274 fprintf(stderr
, TAG
": No core\n");
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
));
286 * Make uninitialized fields visible.
288 memset(&hdrb
, 0xdb, sizeof(struct usbmon_packet_1
));
293 if (par
.api
== API_B0
) {
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",
302 print(&par
, &hdrb
, data_buff
);
303 } else if (par
.api
== API_B1
) {
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",
312 print(&par
, &hdrb
, data_buff
);
313 } else if (par
.api
== API_B1M
) {
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",
322 for (i
= 0; i
< mfb
.nfetch
; i
++) {
324 if (off
>= par
.map_size
) {
325 fprintf(stderr
, TAG
": offset\n");
328 hdr
= (struct usbmon_packet_1
*)(data_buff
+ off
);
329 if (hdr
->type
== '@')
331 print(&par
, hdr
, (const unsigned char *)(hdr
+ 1));
333 toflush
= mfb
.nfetch
;
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
) {
341 rc
= ioctl(fd
, MON_IOCX_GET
, &getb
);
344 ": MON_IOCX_GET: %s\n",
350 ": MON_IOCX_GETX: %s\n",
355 print(&par
, &hdrb
, data_buff
);
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
) {
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
);
376 print_1u(&par
, ep
, data
);
378 default: /* TFMT_HUMAN */
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
;
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';
404 "%llx %u %c %c%c:%03u:%02u",
406 (unsigned int)(ep
->ts_sec
& 0xFFF) * 1000000 + ep
->ts_usec
,
408 utype
, udir
, ep
->devnum
, ep
->epnum
& 0x7f);
410 if (ep
->flag_setup
== 0) { /* Setup packet is present and captured */
412 " s %02x %02x %04x %04x %04x",
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 */
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
)
431 for (i
= 0; i
< data_len
; i
++) {
433 print_safe(&pcur
, " ");
435 print_safe(&pcur
, "%02x", data
[i
]);
437 print_safe(&pcur
, "\n");
439 print_safe(&pcur
, " %c\n", ep
->flag_data
);
442 print_safe(&pcur
, "\n");
445 cnt
= print_done(&pcur
);
446 if ((rc
= write(1, prm
->print_buf
, cnt
)) < cnt
) {
448 fprintf(stderr
, TAG
": Write error: %s\n",
451 fprintf(stderr
, TAG
": Short write\n");
457 void print_1u(const struct params
*prm
, const struct usbmon_packet_1
*ep
,
458 const unsigned char *data
)
460 struct print_cursor pcur
;
463 int ndesc
; /* Display this many */
464 const struct usbmon_isodesc
*dp
;
468 print_start(&pcur
, prm
->print_buf
, prm
->print_size
);
470 if ((data_len
= ep
->len_cap
) < 0) { /* Overflow */
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';
482 "%llx %u %c %c%c:%u:%03u:%u",
484 (unsigned int)(ep
->ts_sec
& 0xFFF) * 1000000 + ep
->ts_usec
,
486 utype
, udir
, ep
->busnum
, ep
->devnum
, ep
->epnum
& 0x7f);
488 if (ep
->type
== 'E') {
489 print_safe(&pcur
, " %d", ep
->status
);
491 if (ep
->flag_setup
== 0) {
492 /* Setup packet is present and captured */
494 " s %02x %02x %04x %04x %04x",
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 */
503 " %c __ __ ____ ____ ____", ep
->flag_setup
);
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') {
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.
529 if (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
++) {
539 dp
->iso_stat
, dp
->iso_off
, dp
->iso_len
);
544 * The number of descriptors captured is used to
545 * find where the data starts.
548 if (ndesc
* sizeof(struct usbmon_isodesc
) > data_len
) {
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
++) {
566 print_safe(&pcur
, " ");
568 print_safe(&pcur
, "%02x", data
[i
]);
570 print_safe(&pcur
, "\n");
572 print_safe(&pcur
, " %c\n", ep
->flag_data
);
575 print_safe(&pcur
, "\n");
578 cnt
= print_done(&pcur
);
579 if ((rc
= write(1, prm
->print_buf
, cnt
)) < cnt
) {
581 fprintf(stderr
, TAG
": Write error: %s\n",
584 fprintf(stderr
, TAG
": Short write\n");
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
;
596 int ndesc
; /* Display this many */
597 const struct usbmon_isodesc
*dp
;
601 print_start(&pcur
, prm
->print_buf
, prm
->print_size
);
603 if ((data_len
= ep
->len_cap
) < 0) { /* Overflow */
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
);
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';
626 " %u.%06u %c %c%c:%u:%03u:%u",
627 (unsigned int)(ep
->ts_sec
- start_sec
), ep
->ts_usec
,
629 utype
, udir
, ep
->busnum
, ep
->devnum
, ep
->epnum
& 0x7f);
631 if (ep
->type
== 'E') {
632 print_safe(&pcur
, " %d", ep
->status
);
634 if (ep
->flag_setup
== 0) {
635 /* Setup packet is present and captured */
637 " s %02x %02x %04x %04x %04x",
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 */
646 " %c __ __ ____ ____ ____", ep
->flag_setup
);
648 /* No setup for this kind of URB */
649 if (ep
->type
== 'S' && ep
->status
== -EINPROGRESS
) {
650 print_safe(&pcur
, " -");
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') {
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.
676 if (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
++) {
686 dp
->iso_stat
, dp
->iso_off
, dp
->iso_len
);
691 * The number of descriptors captured is used to
692 * find where the data starts.
695 if (ndesc
* sizeof(struct usbmon_isodesc
) > data_len
) {
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
);
713 print_safe(&pcur
, " %c\n", ep
->flag_data
);
716 print_safe(&pcur
, "\n");
719 cnt
= print_done(&pcur
);
720 if ((rc
= write(1, prm
->print_buf
, cnt
)) < cnt
) {
722 fprintf(stderr
, TAG
": Write error: %s\n",
725 fprintf(stderr
, TAG
": Short write\n");
731 static void print_human_data(struct print_cursor
*curs
,
732 const struct usbmon_packet_1
*ep
, const unsigned char *data
, int data_len
)
736 for (i
= 0; i
< data_len
; i
++) {
737 print_safe(curs
, " ");
739 for (j
= 0; j
< 16; j
++) {
741 print_safe(curs
, "%02x ", data
[i
+j
]);
743 print_safe(curs
, " ");
745 print_safe(curs
, " ");
748 print_safe(curs
, " ");
750 for (j
= 0; j
< 16; j
++, i
++) {
752 print_safe(curs
, "%c",
753 isprint(data
[i
]) ? data
[i
] : '.');
755 print_safe(curs
, " ");
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.
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
;
791 "..%%0%dllx", (64 - p
->mask_length
) / 4);
795 if ((ep
->id
& mask
) != (p
->common_bits
& mask
)) {
796 while ((ep
->id
& mask
) != (p
->common_bits
& mask
) &&
797 p
->mask_length
!= 0) {
801 if (p
->mask_length
!= 0) {
803 "..%%0%dllx", (64 - p
->mask_length
) / 4);
805 strcpy(p
->format
, "%016llx");
808 snprintf(tag_buf
, tag_buf_size
, p
->format
, (long long) ep
->id
& ~mask
);
812 static void print_start(struct print_cursor
*t
, char *buf
, int size0
)
819 static void print_safe(struct print_cursor
*t
, const char *fmt
, ...)
824 if (t
->count
+1 >= t
->size
)
828 len
= vsnprintf(t
->pbuf
+ t
->count
, t
->size
- t
->count
, fmt
, ap
);
833 static int print_done(struct print_cursor
*t
)
838 void parse_params(struct params
*p
, char **argv
)
843 memset(p
, 0, sizeof(struct params
));
844 p
->data_max
= DATA_MAX
; /* Same as 1t text API. */
845 p
->format
= TFMT_HUMAN
;
848 while ((arg
= *argv
++) != NULL
) {
856 if ((arg
= *argv
++) == NULL
)
858 if (strncmp(arg
, "usb", 3) == 0)
860 if (!isdigit(arg
[0]))
863 num
= strtol(arg
, NULL
, 10);
866 if (num
< 0 || num
>= 128) {
867 fprintf(stderr
, TAG
": Bus number %ld"
868 " is out of bounds\n", num
);
876 p
->format
= TFMT_OLD
;
882 p
->format
= TFMT_HUMAN
;
906 if ((arg
= *argv
++) == NULL
)
908 if (!isdigit(arg
[0]))
911 num
= strtol(arg
, NULL
, 10);
916 ": negative size %ld\n", num
);
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");
938 snprintf(p
->devname
, 100, "/dev/usbmon%d", p
->ifnum
);
941 if (p
->format
== TFMT_1U
)
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");
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");
966 void make_device(const struct params
*p
)
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
));
985 char buff
[LEN
], c
, *p
;
988 if ((df
= fopen("/proc/devices", "r")) == NULL
) {
989 fprintf(stderr
, TAG
": Can't open /proc/devices\n");
993 while (fgets(buff
, LEN
, df
) != NULL
) {
997 for (p
= buff
; (c
= *p
) != 0; p
++) {
1002 } else if (mname
== NULL
) {
1003 if (!isdigit(c
) && c
!= ' ') {
1013 if (major
!= NULL
&& mname
!= NULL
) {
1014 if (strcmp(mname
, "usbmon") == 0) {
1016 num
= strtol(major
, NULL
, 10);
1018 fprintf(stderr
, TAG
": Syntax error "
1019 "in /proc/devices\n");
1029 fprintf(stderr
, TAG
": Can't find usbmon in /proc/devices\n");
1033 if (num
<= 0 || num
> INT_MAX
) {
1034 fprintf(stderr
, TAG
": Weird major %ld in /proc/devices\n",
1044 fprintf(stderr
, "Usage: "
1045 "usbmon [-i usbN] [-f0|-fu|-fh] [-a0|-a1|-am] [-s len]\n");