diff --git a/tools/usbperf/Makefile b/tools/usbperf/Makefile new file mode 100644 index 0000000..2e8d5a9 --- /dev/null +++ b/tools/usbperf/Makefile @@ -0,0 +1,40 @@ +# +# usbperf/Makefile - Wait for an USB device to appear +# +# Written 2011 by Werner Almesberger +# Copyright 2011 Werner Almesberger +# +# 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 2 of the License, or +# (at your option) any later version. +# + + +MAIN = usbperf + +ifeq ($(TARGET),) +TARGET = host +endif + +ifeq ($(TARGET),host) + +include ../Makefile.common + +else + +.PHONY: all install uninstall clean spotless + +all: + +install: + +uninstall: + +clean: + rm -f $(MAIN).o + +spotless: clean + rm -f $(MAIN) + +endif diff --git a/tools/usbperf/usbperf.c b/tools/usbperf/usbperf.c new file mode 100644 index 0000000..f32cc44 --- /dev/null +++ b/tools/usbperf/usbperf.c @@ -0,0 +1,132 @@ +/* + * usbperf/usbperf.c - Measure the rate of control transfers a device can do + * + * Written 2011 by Werner Almesberger + * Copyright 2011 Werner Almesberger + * + * 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 2 of the License, or + * (at your option) any later version. + */ + + +#include +#include +#include +#include +#include + +#include + +#include "usbopen.h" + + +#define SYSFS_USB_BASE "/sys/bus/usb/devices" + + +static void speed(usb_dev_handle *dev) +{ + struct usb_device *device = usb_device(dev); + struct usb_bus *bus = device->bus; + DIR *dir; + const struct dirent *de; + char buf[1000]; /* @@@ plenty :) */ + FILE *file; + int res, devnum; + float speed; + + dir = opendir(SYSFS_USB_BASE); + if (!dir) { + perror(SYSFS_USB_BASE); + exit(1); + } + + while ((de = readdir(dir))) { + if (atoi(de->d_name) != atoi(bus->dirname)) + continue; + + sprintf(buf, SYSFS_USB_BASE "/%s/devnum", de->d_name); + file = fopen(buf, "r"); + if (!file) + continue; + res = fscanf(file, "%d", &devnum); + fclose(file); + + if (res != 1 || devnum != atoi(device->filename)) + continue; + + sprintf(buf, SYSFS_USB_BASE "/%s/speed", de->d_name); + file = fopen(buf, "r"); + if (!file) + continue; + res = fscanf(file, "%f", &speed); + fclose(file); + + printf("%g Mbps\n", speed); + } + closedir(dir); +} + + +static void rounds(usb_dev_handle *dev, int n) +{ + struct timeval t0, t1, t2; + double s = 0, d; + char buf; + int i, res; + + gettimeofday(&t0, NULL); + for (i = 0; i != n; i++) { + gettimeofday(&t1, NULL); + /* GET_CONFIGURATION */ + res = usb_control_msg(dev, USB_ENDPOINT_IN | USB_RECIP_DEVICE, + USB_REQ_GET_CONFIGURATION, 0, 0, &buf, 1, 1000); + if (res < 0) + fprintf(stderr, "usb_control_msg returns %d\n", res); + gettimeofday(&t2, NULL); + s += (t2.tv_sec-t1.tv_sec)+(t2.tv_usec-t1.tv_usec)*1e-6; + + } + d = (t2.tv_sec-t0.tv_sec)+(t2.tv_usec-t0.tv_usec)*1e-6; + printf("Overall: %.3f ms/req\n", d/n*1000.0); + printf("Each: %.3f ms/req\n", s/n*1000.0); +} + + +static void usage(const char *name) +{ + fprintf(stderr, +"usage: %s [vendor]:[product] [rounds]\n" + , name); + exit(1); +} + + +int main(int argc, char **argv) +{ + usb_dev_handle *dev; + int n = 1000; + + switch (argc) { + case 2: + break; + case 3: + n = atoi(argv[2]); + if (n <= 0) + usage(*argv); + break; + default: + usage(*argv); + } + + parse_usb_id(argv[1]); + dev = open_usb(0, 0); + if (!dev) + return 1; + + speed(dev); + rounds(dev, n); + + return 0; +}