summaryrefslogtreecommitdiff
path: root/read-dev-usbmon.c
diff options
context:
space:
mode:
authorPeter Wu <lekensteyn@gmail.com>2013-04-08 17:00:42 +0200
committerPeter Wu <lekensteyn@gmail.com>2013-04-08 17:02:24 +0200
commit99bcaad18aad5c41997b94a66862e19c841c2986 (patch)
tree94c3d3568dda0082a6d665595687041f038d21b5 /read-dev-usbmon.c
downloadltunify-99bcaad18aad5c41997b94a66862e19c841c2986.tar.gz
Initial commit of RE/debug programs/notes
Diffstat (limited to 'read-dev-usbmon.c')
-rw-r--r--read-dev-usbmon.c150
1 files changed, 150 insertions, 0 deletions
diff --git a/read-dev-usbmon.c b/read-dev-usbmon.c
new file mode 100644
index 0000000..916bf37
--- /dev/null
+++ b/read-dev-usbmon.c
@@ -0,0 +1,150 @@
+/*
+ * Tool for reading usbmon messages and writing non-empty data to stdout.
+ * Because of limitations of a single output stream, there is currently a hack
+ * that directly includes hidraw.c.
+ *
+ * Copyright (C) 2013 Peter Wu <lekensteyn@gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <sys/ioctl.h>
+#include <string.h>
+#include <stdint.h>
+#include <stdlib.h> /* getenv */
+
+typedef uint16_t u16;
+typedef int32_t s32;
+typedef uint64_t u64;
+typedef int64_t s64;
+#define SETUP_LEN 8
+
+/* taken from Linux, Documentation/usb/usbmon.txt */
+struct usbmon_packet {
+ u64 id; /* 0: URB ID - from submission to callback */
+ unsigned char type; /* 8: Same as text; extensible. */
+ unsigned char xfer_type; /* ISO (0), Intr, Control, Bulk (3) */
+ unsigned char epnum; /* Endpoint number and transfer direction */
+ unsigned char devnum; /* Device address */
+ u16 busnum; /* 12: Bus number */
+ char flag_setup; /* 14: Same as text */
+ char flag_data; /* 15: Same as text; Binary zero is OK. */
+ s64 ts_sec; /* 16: gettimeofday */
+ s32 ts_usec; /* 24: gettimeofday */
+ int status; /* 28: */
+ unsigned int length; /* 32: Length of data (submitted or actual) */
+ unsigned int len_cap; /* 36: Delivered length */
+ union { /* 40: */
+ unsigned char setup[SETUP_LEN]; /* Only for Control S-type */
+ struct iso_rec { /* Only for ISO */
+ int error_count;
+ int numdesc;
+ } iso;
+ } s;
+ int interval; /* 48: Only for Interrupt and ISO */
+ int start_frame; /* 52: For ISO */
+ unsigned int xfer_flags; /* 56: copy of URB's transfer_flags */
+ unsigned int ndesc; /* 60: Actual number of ISO descriptors */
+};
+
+struct mon_get_arg {
+ struct usbmon_packet *hdr;
+ void *data;
+ size_t alloc; /* Length of data (can be zero) */
+};
+
+#define MON_IOC_MAGIC 0x92
+#define MON_IOCQ_URB_LEN _IO(MON_IOC_MAGIC, 1)
+#define MON_IOCX_GET _IOW(MON_IOC_MAGIC, 6, struct mon_get_arg)
+
+#define NO_MAIN
+// HACK - otherwise there is no easy wat to tell whether a packet is read or
+// written from the usbmon
+#include "hidraw.c"
+#undef NO_MAIN
+
+int main(int argc, char ** argv) {
+ unsigned char data[1024];
+ struct usbmon_packet hdr;
+ struct mon_get_arg event;
+ int fd, r;
+
+ if (argc < 2) {
+ fprintf(stderr, "Usage: %s /dev/usbmonX\n", argv[0]);
+ return 1;
+ }
+
+ fd = open(argv[1], O_RDONLY);
+ if (fd < 0) {
+ perror(argv[1]);
+ return 1;
+ }
+
+ memset(&hdr, 0, sizeof hdr);
+ event.hdr = &hdr; // hopefully it is OK to use stack for this
+ event.data = &data;
+ event.alloc = sizeof data;
+
+ //r = ioctl(fd, MON_IOCQ_URB_LEN);
+ //printf("%i\n", r);
+ for (;;) {
+ memset(&data, 0xCC, sizeof data); // for debugging purposes
+ r = ioctl(fd, MON_IOCX_GET, &event);
+ if (r < 0) {
+ perror("ioctl");
+ break;
+ }
+
+ // ignore non-data packets
+ if (hdr.len_cap) {
+ if (getenv("HEX")) {
+ unsigned int i;
+ printf("Type=%c\n", hdr.type);
+ for (i=0; i<hdr.len_cap; i++) {
+ printf("%02X%c", data[i],
+ i + 1 == hdr.len_cap ? '\n' : ' ');
+ }
+ } else {
+ struct report *report = (struct report *)&data;
+ if (hdr.len_cap < 3) {
+ fprintf(stderr, "Short data len: %i\n", hdr.len_cap);
+ continue;
+ }
+#define COLOR(c, cstr) "\033[" c "m" cstr "\033[m"
+ if (hdr.type == 'C') {
+ printf(COLOR("1;32", "Recv\t"));
+ } else if (hdr.type == 'S') {
+ printf(COLOR("1;31", "Send\t"));
+ } else {
+ printf(COLOR("1;35", "Type=%c\t") "\n", hdr.type);
+ }
+ process_msg(report, hdr.len_cap);
+ fflush(NULL);
+#if 0
+ if (write(STDOUT_FILENO, &data, hdr.len_cap) < 0) {
+ perror("write");
+ break;
+ }
+#endif
+ }
+ }
+ }
+
+ close(fd);
+
+ return 0;
+}