From: Michal Nazarewicz <m.nazarewicz@samsung.com>
To: linux-usb@vger.kernel.org
Cc: Michal Nazarewicz <mina86@mina86.com>,
Michal Nazarewicz <m.nazarewicz@samsung.com>,
Greg KH <greg@kroah.com>,
Kyungmin Park <kyungmin.park@samsung.com>,
Marek Szyprowski <m.szyprowski@samsung.com>,
linux-kernel@vger.kernel.org,
David Brownell <dbrownell@users.sourceforge.net>
Subject: [PATCHv2 8/8] USB: testusb: testusb compatibility with FunctionFS gadget
Date: Fri, 09 Apr 2010 21:21:25 +0200 [thread overview]
Message-ID: <b6a514337954b5f8372e5808556a3c5f4dadaf98.1270835924.git.mina86@mina86.com> (raw)
In-Reply-To: <bc9d1ab4bd3fc9a3dfa3792054cfb410cf9c6411.1270835924.git.mina86@mina86.com>
The FunctionFS gadget may provide the source/sink interface
not as the first interface (with id == 0) but some different
interface hence a code to find the interface number is
required.
(Note that you will still configure the gadget to report
idProduct == 0xa4a4 (an "echo 0xa4a4
>/sys/module/g_ffs/parameters/usb_product" should suffice) or
configure host to handle 0x0525:0xa4ac devices using the
usbtest driver.)
Signed-off-by: Michal Nazarewicz <m.nazarewicz@samsung.com>
Cc: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Marek Szyprowski <m.szyprowski@samsung.com>
---
tools/usb/testusb.c | 252 ++++++++++++++++++++++++++++++++++++--------------
1 files changed, 181 insertions(+), 71 deletions(-)
diff --git a/tools/usb/testusb.c b/tools/usb/testusb.c
index 28e25ca..0a1a5b5 100644
--- a/tools/usb/testusb.c
+++ b/tools/usb/testusb.c
@@ -1,8 +1,10 @@
-/* $(CROSS_COMPILE)cc -Wall -g -lpthread -o testusb testusb.c */
+/* $(CROSS_COMPILE)cc -Wall -Wextra -g -lpthread -o testusb testusb.c */
/*
* Copyright (c) 2002 by David Brownell
- *
+ * Copyright (c) 2010 by Samsung Electronics
+ * Author: Michal Nazarewicz <m.nazarewicz@samsung.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 2 of the License, or (at your
@@ -25,6 +27,7 @@
#include <pthread.h>
#include <unistd.h>
#include <errno.h>
+#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -56,6 +59,13 @@ struct usbtest_param {
/* #include <linux/usb_ch9.h> */
+#define USB_DT_DEVICE 0x01
+#define USB_DT_INTERFACE 0x04
+
+#define USB_CLASS_PER_INTERFACE 0 /* for DeviceClass */
+#define USB_CLASS_VENDOR_SPEC 0xff
+
+
struct usb_device_descriptor {
__u8 bLength;
__u8 bDescriptorType;
@@ -73,6 +83,19 @@ struct usb_device_descriptor {
__u8 bNumConfigurations;
} __attribute__ ((packed));
+struct usb_interface_descriptor {
+ __u8 bLength;
+ __u8 bDescriptorType;
+
+ __u8 bInterfaceNumber;
+ __u8 bAlternateSetting;
+ __u8 bNumEndpoints;
+ __u8 bInterfaceClass;
+ __u8 bInterfaceSubClass;
+ __u8 bInterfaceProtocol;
+ __u8 iInterface;
+} __attribute__ ((packed));
+
enum usb_device_speed {
USB_SPEED_UNKNOWN = 0, /* enumerating */
USB_SPEED_LOW, USB_SPEED_FULL, /* usb 1.1 */
@@ -105,11 +128,42 @@ struct testdev {
};
static struct testdev *testdevs;
-static int is_testdev (struct usb_device_descriptor *dev)
+static int testdev_ffs_ifnum(FILE *fd)
{
+ union {
+ char buf[255];
+ struct usb_interface_descriptor intf;
+ } u;
+
+ for (;;) {
+ if (fread(u.buf, 1, 1, fd) != 1)
+ return -1;
+ if (fread(u.buf + 1, (unsigned char)u.buf[0] - 1, 1, fd) != 1)
+ return -1;
+
+ if (u.intf.bLength == sizeof u.intf
+ && u.intf.bDescriptorType == USB_DT_INTERFACE
+ && u.intf.bNumEndpoints == 2
+ && u.intf.bInterfaceClass == USB_CLASS_VENDOR_SPEC
+ && u.intf.bInterfaceSubClass == 0
+ && u.intf.bInterfaceProtocol == 0)
+ return (unsigned char)u.intf.bInterfaceNumber;
+ }
+}
+
+static int testdev_ifnum(FILE *fd)
+{
+ struct usb_device_descriptor dev;
+
+ if (fread(&dev, sizeof dev, 1, fd) != 1)
+ return -1;
+
+ if (dev.bLength != sizeof dev || dev.bDescriptorType != USB_DT_DEVICE)
+ return -1;
+
/* FX2 with (tweaked) bulksrc firmware */
- if (dev->idVendor == 0x0547 && dev->idProduct == 0x1002)
- return 1;
+ if (dev.idVendor == 0x0547 && dev.idProduct == 0x1002)
+ return 0;
/*----------------------------------------------------*/
@@ -124,95 +178,108 @@ static int is_testdev (struct usb_device_descriptor *dev)
*/
/* generic EZ-USB FX controller */
- if (dev->idVendor == 0x0547 && dev->idProduct == 0x2235)
- return 1;
+ if (dev.idVendor == 0x0547 && dev.idProduct == 0x2235)
+ return 0;
/* generic EZ-USB FX2 controller */
- if (dev->idVendor == 0x04b4 && dev->idProduct == 0x8613)
- return 1;
+ if (dev.idVendor == 0x04b4 && dev.idProduct == 0x8613)
+ return 0;
/* CY3671 development board with EZ-USB FX */
- if (dev->idVendor == 0x0547 && dev->idProduct == 0x0080)
- return 1;
+ if (dev.idVendor == 0x0547 && dev.idProduct == 0x0080)
+ return 0;
/* Keyspan 19Qi uses an21xx (original EZ-USB) */
- if (dev->idVendor == 0x06cd && dev->idProduct == 0x010b)
- return 1;
+ if (dev.idVendor == 0x06cd && dev.idProduct == 0x010b)
+ return 0;
/*----------------------------------------------------*/
/* "gadget zero", Linux-USB test software */
- if (dev->idVendor == 0x0525 && dev->idProduct == 0xa4a0)
- return 1;
+ if (dev.idVendor == 0x0525 && dev.idProduct == 0xa4a0)
+ return 0;
/* user mode subset of that */
- if (dev->idVendor == 0x0525 && dev->idProduct == 0xa4a4)
- return 1;
+ if (dev.idVendor == 0x0525 && dev.idProduct == 0xa4a4)
+ return testdev_ffs_ifnum(fd);
+ /* return 0; */
/* iso version of usermode code */
- if (dev->idVendor == 0x0525 && dev->idProduct == 0xa4a3)
- return 1;
+ if (dev.idVendor == 0x0525 && dev.idProduct == 0xa4a3)
+ return 0;
/* some GPL'd test firmware uses these IDs */
- if (dev->idVendor == 0xfff0 && dev->idProduct == 0xfff0)
- return 1;
+ if (dev.idVendor == 0xfff0 && dev.idProduct == 0xfff0)
+ return 0;
/*----------------------------------------------------*/
/* iBOT2 high speed webcam */
- if (dev->idVendor == 0x0b62 && dev->idProduct == 0x0059)
- return 1;
+ if (dev.idVendor == 0x0b62 && dev.idProduct == 0x0059)
+ return 0;
- return 0;
+ /*----------------------------------------------------*/
+
+ /* the FunctionFS gadget can have the source/sink interface
+ * anywhere. We look for an interface descriptor that match
+ * what we expect. We ignore configuratiens thou. */
+
+ if (dev.idVendor == 0x0525 && dev.idProduct == 0xa4ac
+ && (dev.bDeviceClass == USB_CLASS_PER_INTERFACE
+ || dev.bDeviceClass == USB_CLASS_VENDOR_SPEC))
+ return testdev_ffs_ifnum(fd);
+
+ return -1;
}
-static int find_testdev (const char *name, const struct stat *sb, int flag)
+static int find_testdev(const char *name, const struct stat *sb, int flag)
{
- int fd;
- struct usb_device_descriptor dev;
+ FILE *fd;
+ int ifnum;
+ struct testdev *entry;
+
+ (void)sb; /* unused */
if (flag != FTW_F)
return 0;
/* ignore /proc/bus/usb/{devices,drivers} */
- if (strrchr (name, '/')[1] == 'd')
+ if (strrchr(name, '/')[1] == 'd')
return 0;
- if ((fd = open (name, O_RDONLY)) < 0) {
- perror ("can't open dev file r/o");
+ fd = fopen(name, "rb");
+ if (!fd) {
+ perror(name);
return 0;
}
- if (read (fd, &dev, sizeof dev) != sizeof dev)
- fputs ("short devfile read!\n", stderr);
- else if (is_testdev (&dev)) {
- struct testdev *entry;
-
- if ((entry = calloc (1, sizeof *entry)) == 0) {
- fputs ("no mem!\n", stderr);
- goto done;
- }
- entry->name = strdup (name);
- if (!entry->name) {
- free (entry);
- goto done;
- }
-
- // FIXME better to look at each interface and ask if it's
- // bound to 'usbtest', rather than assume interface 0
- entry->ifnum = 0;
- // FIXME ask usbfs what speed; update USBDEVFS_CONNECTINFO
- // so it tells about high speed etc
+ ifnum = testdev_ifnum(fd);
+ fclose(fd);
+ if (ifnum < 0)
+ return 0;
- fprintf (stderr, "%s speed\t%s\n",
- speed (entry->speed), entry->name);
+ entry = calloc(1, sizeof *entry);
+ if (!entry)
+ goto nomem;
- entry->next = testdevs;
- testdevs = entry;
+ entry->name = strdup(name);
+ if (!entry->name) {
+ free(entry);
+nomem:
+ perror("malloc");
+ return 0;
}
-done:
- close (fd);
+ entry->ifnum = ifnum;
+
+ /* FIXME ask usbfs what speed; update USBDEVFS_CONNECTINFO so
+ * it tells about high speed etc */
+
+ fprintf(stderr, "%s speed\t%s\t%u\n",
+ speed(entry->speed), entry->name, entry->ifnum);
+
+ entry->next = testdevs;
+ testdevs = entry;
return 0;
}
@@ -277,11 +344,51 @@ restart:
return arg;
}
+static const char *usbfs_dir_find(void)
+{
+ static char usbfs_path_0[] = "/dev/bus/usb/devices";
+ static char usbfs_path_1[] = "/proc/bus/usb/devices";
+
+ static char *const usbfs_paths[] = {
+ usbfs_path_0, usbfs_path_1
+ };
+
+ static char *const *
+ end = usbfs_paths + sizeof usbfs_paths / sizeof *usbfs_paths;
+
+ char *const *it = usbfs_paths;
+ do {
+ int fd = open(*it, O_RDONLY);
+ close(fd);
+ if (fd >= 0) {
+ strrchr(*it, '/')[0] = '\0';
+ return *it;
+ }
+ } while (++it != end);
+
+ return NULL;
+}
+
+static int parse_num(unsigned *num, const char *str)
+{
+ unsigned long val;
+ char *end;
+
+ errno = 0;
+ val = strtoul(str, &end, 0);
+ if (errno || *end || val > UINT_MAX)
+ return -1;
+ *num = val;
+ return 0;
+}
+
int main (int argc, char **argv)
{
+
int c;
struct testdev *entry;
char *device;
+ const char *usbfs_dir = NULL;
int all = 0, forever = 0, not = 0;
int test = -1 /* all */;
struct usbtest_param param;
@@ -303,23 +410,24 @@ int main (int argc, char **argv)
/* for easy use when hotplugging */
device = getenv ("DEVICE");
- while ((c = getopt (argc, argv, "D:ac:g:hns:t:v:")) != EOF)
+ while ((c = getopt (argc, argv, "D:aA:c:g:hns:t:v:")) != EOF)
switch (c) {
case 'D': /* device, if only one */
device = optarg;
continue;
+ case 'A': /* use all devices with specified usbfs dir */
+ usbfs_dir = optarg;
+ /* FALL THROUGH */
case 'a': /* use all devices */
- device = 0;
+ device = NULL;
all = 1;
continue;
case 'c': /* count iterations */
- param.iterations = atoi (optarg);
- if (param.iterations < 0)
+ if (parse_num(¶m.iterations, optarg))
goto usage;
continue;
case 'g': /* scatter/gather entries */
- param.sglen = atoi (optarg);
- if (param.sglen < 0)
+ if (parse_num(¶m.sglen, optarg))
goto usage;
continue;
case 'l': /* loop forever */
@@ -329,8 +437,7 @@ int main (int argc, char **argv)
not = 1;
continue;
case 's': /* size of packet */
- param.length = atoi (optarg);
- if (param.length < 0)
+ if (parse_num(¶m.length, optarg))
goto usage;
continue;
case 't': /* run just one test */
@@ -339,15 +446,14 @@ int main (int argc, char **argv)
goto usage;
continue;
case 'v': /* vary packet size by ... */
- param.vary = atoi (optarg);
- if (param.vary < 0)
+ if (parse_num(¶m.vary, optarg))
goto usage;
continue;
case '?':
case 'h':
default:
usage:
- fprintf (stderr, "usage: %s [-an] [-D dev]\n"
+ fprintf (stderr, "usage: %s [-n] [-D dev | -a | -A usbfs-dir]\n"
"\t[-c iterations] [-t testnum]\n"
"\t[-s packetsize] [-g sglen] [-v vary]\n",
argv [0]);
@@ -361,13 +467,17 @@ usage:
goto usage;
}
- if ((c = open ("/proc/bus/usb/devices", O_RDONLY)) < 0) {
- fputs ("usbfs files are missing\n", stderr);
- return -1;
+ /* Find usbfs mount point */
+ if (!usbfs_dir) {
+ usbfs_dir = usbfs_dir_find();
+ if (!usbfs_dir) {
+ fputs ("usbfs files are missing\n", stderr);
+ return -1;
+ }
}
/* collect and list the test devices */
- if (ftw ("/proc/bus/usb", find_testdev, 3) != 0) {
+ if (ftw (usbfs_dir, find_testdev, 3) != 0) {
fputs ("ftw failed; is usbfs missing?\n", stderr);
return -1;
}
--
1.7.0
next prev parent reply other threads:[~2010-04-09 19:22 UTC|newest]
Thread overview: 47+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-04-07 13:41 [PATCH 0/7] The FunctionFS composite function Michal Nazarewicz
2010-04-07 13:41 ` [PATCH 1/8] USB: composite: allow optional removal of __init and __exit tags Michal Nazarewicz
2010-04-07 13:41 ` [PATCH 2/8] sched: __wake_up_locked() exported Michal Nazarewicz
2010-04-07 13:41 ` [PATCH 3/8] USB: f_fs: the FunctionFS driver Michal Nazarewicz
2010-04-07 13:41 ` [PATCH 4/8] USB: Ethernet: allow optional removal of __init and __init_data tags Michal Nazarewicz
2010-04-07 13:41 ` [PATCH 5/8] USB: g_ffs: the FunctionFS gadget driver Michal Nazarewicz
2010-04-07 13:41 ` [PATCH 6/8] USB: ffs-test: FunctionFS testing program Michal Nazarewicz
2010-04-07 13:41 ` [PATCH 7/8] USB: testusb: imported David Brownell's USB testing application Michal Nazarewicz
2010-04-07 13:41 ` [PATCH 8/8] USB: testusb: testusb compatibility with FunctionFS gadget Michal Nazarewicz
2010-04-08 0:30 ` Greg KH
2010-04-08 0:29 ` [PATCH 7/8] USB: testusb: imported David Brownell's USB testing application Greg KH
2010-04-09 19:21 ` [PATCHv2 7/8] USB: testusb: an " Michal Nazarewicz
2010-04-09 19:21 ` Michal Nazarewicz [this message]
2010-04-10 22:51 ` David Brownell
2010-04-14 9:30 ` [PATCH 7/8] USB: testusb: imported David Brownell's " David Brownell
2010-04-14 16:46 ` Greg KH
2010-04-14 16:47 ` Greg KH
2010-04-08 6:10 ` Heikki Krogerus
2010-04-08 6:18 ` Greg KH
2010-04-08 6:34 ` Heikki Krogerus
2010-04-14 9:41 ` David Brownell
2010-04-14 12:50 ` Michał Nazarewicz
2010-04-14 16:47 ` Greg KH
2010-04-07 17:11 ` [PATCH 3/8] USB: f_fs: the FunctionFS driver Michał Nazarewicz
2010-04-07 15:29 ` [PATCH 2/8] sched: __wake_up_locked() exported Greg KH
2010-04-07 17:11 ` Michał Nazarewicz
2010-04-08 0:28 ` Greg KH
2010-04-07 15:28 ` [PATCH 1/8] USB: composite: allow optional removal of __init and __exit tags Greg KH
2010-04-07 15:39 ` Michał Nazarewicz
2010-04-08 0:26 ` Greg KH
2010-04-09 19:21 [PATCH 0/7] The FunctionFS composite function Michal Nazarewicz
2010-04-09 19:21 ` [PATCHv2 1/8] wait_event_interruptible_locked() interface Michal Nazarewicz
2010-04-09 19:21 ` [PATCHv2 2/8] fs/timerfd.c: make use of wait_event_interruptible_locked_irq() Michal Nazarewicz
2010-04-09 19:21 ` [PATCHv2 3/8] USB: gadget: __init and __exit tags removed Michal Nazarewicz
2010-04-09 19:21 ` [PATCHv2 4/8] USB: f_fs: the FunctionFS driver Michal Nazarewicz
2010-04-09 19:21 ` [PATCHv2 5/8] USB: g_ffs: the FunctionFS gadget driver Michal Nazarewicz
2010-04-09 19:21 ` [PATCHv2 6/8] USB: ffs-test: FunctionFS testing program Michal Nazarewicz
2010-04-29 22:15 ` [PATCHv2 3/8] USB: gadget: __init and __exit tags removed Greg KH
2010-04-29 23:02 ` Michal Nazarewicz
2010-04-29 23:22 ` Greg KH
2010-04-30 5:41 ` Michal Nazarewicz
2010-04-11 14:31 ` [PATCHv2 2/8] fs/timerfd.c: make use of wait_event_interruptible_locked_irq() Thomas Gleixner
2010-04-11 19:16 ` Michal Nazarewicz
2010-04-11 19:16 ` Michal Nazarewicz
2010-04-11 15:02 ` [PATCHv2 1/8] wait_event_interruptible_locked() interface Thomas Gleixner
2010-04-11 15:02 ` Thomas Gleixner
2010-04-11 19:27 ` Michal Nazarewicz
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=b6a514337954b5f8372e5808556a3c5f4dadaf98.1270835924.git.mina86@mina86.com \
--to=m.nazarewicz@samsung.com \
--cc=dbrownell@users.sourceforge.net \
--cc=greg@kroah.com \
--cc=kyungmin.park@samsung.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-usb@vger.kernel.org \
--cc=m.szyprowski@samsung.com \
--cc=mina86@mina86.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.