summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--Makefile6
-rw-r--r--lib/Makefile16
-rw-r--r--read-dev-usbmon.c167
4 files changed, 139 insertions, 52 deletions
diff --git a/.gitignore b/.gitignore
index c7f2583..a295850 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,3 +2,5 @@
read-dev-usbmon
hidraw
ltunify
+*.o
+*.a
diff --git a/Makefile b/Makefile
index 8116950..666f323 100644
--- a/Makefile
+++ b/Makefile
@@ -9,6 +9,9 @@ udevrulesdir ?= /etc/udev/rules.d
udevrule = 42-logitech-unify-permissions.rules
+# Whether to support reading pcap files in read-dev-usbmon
+WITH_PCAP ?= 1
+
PACKAGE_VERSION ?= $(shell git describe --dirty 2>/dev/null | sed s/^v//)
ifeq (PACKAGE_VERSION, "")
LTUNIFY_DEFINES :=
@@ -22,6 +25,9 @@ endif
all: ltunify read-dev-usbmon
read-dev-usbmon: read-dev-usbmon.c hidraw.c
+ifeq ($(WITH_PCAP), 1)
+ $(CC) $(CFLAGS) -o $(OUTDIR)$@ $< -lpcap -DWITH_PCAP=1
+endif
ltunify: ltunify.c hidpp20.c
$(CC) $(CFLAGS) -o $(OUTDIR)$@ $< -lrt $(LTUNIFY_DEFINES)
diff --git a/lib/Makefile b/lib/Makefile
new file mode 100644
index 0000000..8d1bdaf
--- /dev/null
+++ b/lib/Makefile
@@ -0,0 +1,16 @@
+
+CFLAGS ?= -O2 -g -DENABLE_TRACING
+WFLAGS ?= -Wall -Wextra -Wmissing-prototypes
+
+SOURCES := $(wildcard *.c)
+OBJECTS := $(SOURCES:%.c=%.o)
+
+libltunify.a: $(OBJECTS)
+ #$(CC) $(WFLAGS) $(CFLAGS) -o $@ $^ -lrt -c
+ ar rcs $@ $^
+
+clean:
+ $(RM) libltunify.a $(OBJECTS)
+
+%.o: %.c
+ $(CC) -c $(WFLAGS) $(CFLAGS) -o $@ $<
diff --git a/read-dev-usbmon.c b/read-dev-usbmon.c
index bd1c1a6..ba6c296 100644
--- a/read-dev-usbmon.c
+++ b/read-dev-usbmon.c
@@ -3,7 +3,7 @@
* 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>
+ * Copyright (C) 2013-2014 Peter Wu <peter@lekensteyn.nl>
*
* 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
@@ -20,6 +20,11 @@
*/
#include <fcntl.h>
+#ifdef WITH_PCAP
+# include <pcap/pcap.h>
+# include <sys/types.h>
+# include <sys/stat.h>
+#endif
#include <unistd.h>
#include <stdio.h>
#include <sys/ioctl.h>
@@ -80,34 +85,64 @@ struct mon_get_arg {
#include "hidraw.c"
#undef NO_MAIN
-void print_time(void) {
- struct timeval tval;
+void print_time(const struct timeval *tval) {
struct tm *tm;
- if (gettimeofday(&tval, NULL)) {
- perror("gettimeofday");
- return;
- }
- tm = localtime(&tval.tv_sec);
+ tm = localtime(&tval->tv_sec);
printf("%02d:%02d:%02d.%03ld ",
tm->tm_hour, tm->tm_min, tm->tm_sec,
- tval.tv_usec / 1000);
+ tval->tv_usec / 1000);
+}
+
+void process_usbpkt(const struct usbmon_packet *hdr, const unsigned char *data,
+ const struct timeval *tval);
+
+#ifdef WITH_PCAP
+static void packet_callback(u_char *user, const struct pcap_pkthdr *h,
+ const u_char *bytes) {
+ const struct usbmon_packet *hdr;
+ const unsigned char *data;
+ (void) user;
+
+ if (h->caplen < sizeof(struct usbmon_packet)) {
+ return;
+ }
+
+ hdr = (struct usbmon_packet *) bytes;
+ data = bytes + sizeof(*hdr);
+ process_usbpkt(hdr, data, &h->ts);
}
-int main(int argc, char ** argv) {
+int main_pcap(char *filename) {
+ pcap_t *p;
+ char errbuf[PCAP_ERRBUF_SIZE];
+ int r;
+
+ p = pcap_open_offline(filename, errbuf);
+ if (p == NULL) {
+ fprintf(stderr, "%s\n", errbuf);
+ return 1;
+ }
+
+ r = pcap_loop(p, -1, packet_callback, NULL);
+ if (r == -1) {
+ pcap_perror(p, filename);
+ }
+ pcap_close(p);
+ return 0;
+}
+#endif
+
+int main_usbmon(char *filename) {
unsigned char data[1024];
struct usbmon_packet hdr;
struct mon_get_arg event;
int fd, r;
+ struct timeval tval = { 0, 0 };
- if (argc < 2) {
- fprintf(stderr, "Usage: %s /dev/usbmonX\n", argv[0]);
- return 1;
- }
-
- fd = open(argv[1], O_RDONLY);
+ fd = open(filename, O_RDONLY);
if (fd < 0) {
- perror(argv[1]);
+ perror(filename);
return 1;
}
@@ -129,45 +164,73 @@ int main(int argc, char ** argv) {
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 if (hdr.len_cap > sizeof (struct report)) {
- fprintf(stderr, "Discarding too large packet of length %u!\n", hdr.len_cap);
- } 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"
- print_time();
- 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
- }
+ if (gettimeofday(&tval, NULL)) {
+ perror("gettimeofday");
}
+ process_usbpkt(&hdr, data, &tval);
}
close(fd);
return 0;
}
+
+int main(int argc, char **argv) {
+ char *filename;
+ if (argc < 2) {
+ fprintf(stderr, "Usage: %s </dev/usbmonX | - | foo.pcap>\n",
+ argv[0]);
+ return 1;
+ }
+ filename = argv[1];
+#ifdef WITH_PCAP
+ struct stat sbuf;
+ /* assume that usbmon files are devices, and pcap are files.
+ * "-" does not exist, so assume pcap if file cannot be stat()ed. */
+ if (stat(filename, &sbuf) != 0 || !S_ISCHR(sbuf.st_mode)) {
+ return main_pcap(filename);
+ }
+#endif
+ return main_usbmon(filename);
+}
+
+void process_usbpkt(const struct usbmon_packet *hdr, const unsigned char *data,
+ const struct timeval *tval) {
+ // ignore non-data packets
+ if (!hdr->len_cap) {
+ return;
+ }
+ 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 if (hdr->len_cap > sizeof (struct report)) {
+ fprintf(stderr, "Discarding too large packet of length %u!\n", hdr->len_cap);
+ } else {
+ struct report *report = (struct report *)data;
+ if (hdr->len_cap < 3) {
+ fprintf(stderr, "Short data len: %i\n", hdr->len_cap);
+ return;
+ }
+#define COLOR(c, cstr) "\033[" c "m" cstr "\033[m"
+ print_time(tval);
+ 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
+ }
+}