usbmon.c (3237B)
1 /* usbmon.c 2 * 3 * Copyright 2011 Brian Swetland <swetland@frotz.net> 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 #include <stdio.h> 19 #include <stdlib.h> 20 #include <unistd.h> 21 #include <fcntl.h> 22 #include <string.h> 23 #include <errno.h> 24 25 #include <sys/ioctl.h> 26 #include <linux/ioctl.h> 27 28 typedef unsigned long long u64; 29 typedef signed long long s64; 30 typedef int s32; 31 typedef unsigned short u16; 32 33 #include "usbmon.h" 34 35 static char _xfer[4] = "SICB"; 36 37 int main(int argc, char **argv) 38 { 39 unsigned char data[4096]; 40 struct usbmon_packet hdr; 41 struct usbmon_get arg; 42 unsigned char filter_dev[128]; 43 int fd, r, n; 44 unsigned busmask = 0; 45 46 memset(filter_dev, 0, sizeof(filter_dev)); 47 48 fd = open("/dev/usbmon0", O_RDONLY); 49 if (fd < 0) 50 return -1; 51 52 argc--; 53 argv++; 54 while (argc--) { 55 if (argv[0][0] == '-') { 56 switch(argv[0][1]) { 57 case 'x': /* eXclude device */ 58 r = atoi(argv[0] + 2); 59 if ((r < 0) || (r > 127)) 60 continue; 61 filter_dev[r] = 1; 62 break; 63 case 'b': /* limit to Bus */ 64 r = atoi(argv[0] + 2); 65 busmask = ~(1 << r); 66 break; 67 case 'd': /* limit to Device */ 68 memset(filter_dev, 0x01, sizeof(filter_dev)); 69 r = atoi(argv[0] + 2); 70 if ((r < 0) || (r > 127)) 71 continue; 72 filter_dev[r] = 0; 73 break; 74 } 75 } 76 argv++; 77 } 78 79 arg.hdr = &hdr; 80 arg.data = data; 81 for (;;) { 82 arg.alloc = sizeof(data); 83 r = ioctl(fd, MON_IOCX_GET, &arg); 84 if (r < 0) 85 break; 86 if (filter_dev[hdr.devnum]) 87 continue; 88 if (busmask & (1 << hdr.busnum)) 89 continue; 90 printf("%d.%03d.%03d %c %c%c %04x", 91 hdr.busnum, hdr.devnum, hdr.epnum & 0x7F, 92 hdr.type, 93 _xfer[hdr.xfer], (hdr.epnum & 0x80) ? 'i' : 'o', 94 #if 0 95 hdr.flag_setup ? hdr.flag_setup : ' ', 96 hdr.flag_data ? hdr.flag_data : ' ', 97 #endif 98 hdr.length); 99 if (hdr.type == 'S') { 100 if (hdr.xfer == 2) { 101 printf(" %02x %02x %02x%02x %02x%02x %02x%02x\n", 102 hdr.s.setup[0], hdr.s.setup[1], 103 hdr.s.setup[3], hdr.s.setup[2], 104 hdr.s.setup[5], hdr.s.setup[4], 105 hdr.s.setup[7], hdr.s.setup[6]); 106 } else { 107 goto dumpdata; 108 } 109 110 } else { 111 switch (hdr.status) { 112 case 0: 113 printf(" OK\n"); 114 break; 115 case -EPIPE: 116 printf(" STALLED\n"); 117 break; 118 case -ENODEV: 119 printf(" DISCONNECTED\n"); 120 break; 121 case -ETIMEDOUT: 122 printf(" TIMEDOUT\n"); 123 break; 124 case -EREMOTEIO: 125 printf(" OK (SHORT)\n"); 126 break; 127 default: 128 printf(" %s (%d)\n", strerror(-hdr.status),-hdr.status); 129 } 130 } 131 if (!hdr.len_cap) 132 continue; 133 printf(" "); 134 dumpdata: 135 if (hdr.len_cap > sizeof(data)) 136 hdr.len_cap = sizeof(data); 137 for (n = 0; n < hdr.len_cap; n++) 138 printf((n & 3) ? " %02x" : " %02x",data[n]); 139 printf("\n"); 140 fflush(stdout); 141 } 142 return 0; 143 } 144