r3093 - in trunk/src/host: . usbpath
werner at sita.openmoko.org
werner at sita.openmoko.org
Sat Oct 6 17:03:37 CEST 2007
Author: werner
Date: 2007-10-06 17:03:26 +0200 (Sat, 06 Oct 2007)
New Revision: 3093
Added:
trunk/src/host/usbpath/
trunk/src/host/usbpath/Makefile
trunk/src/host/usbpath/README
trunk/src/host/usbpath/devnum2path.c
trunk/src/host/usbpath/path2devnum.c
trunk/src/host/usbpath/portinfo.c
trunk/src/host/usbpath/usbpath.c
trunk/src/host/usbpath/usbpath.h
Log:
Library and utility to convert between USB device numbers and physical paths
to devices.
Added: trunk/src/host/usbpath/Makefile
===================================================================
--- trunk/src/host/usbpath/Makefile 2007-10-06 09:47:25 UTC (rev 3092)
+++ trunk/src/host/usbpath/Makefile 2007-10-06 15:03:26 UTC (rev 3093)
@@ -0,0 +1,28 @@
+CFLAGS=-Wall -g
+LDLIBS=-L. -lusbpath -lusb
+
+PREFIX=/usr/local
+
+
+.PHONY: all install uninstall clean spotless
+
+all: usbpath libusbpath.a
+
+usbpath: libusbpath.a
+
+libusbpath.a: path2devnum.o devnum2path.o portinfo.o
+ $(AR) crv $@ $^
+
+install: libusbpath.a
+ install -m 555 usbpath $(PREFIX)/bin
+ install -m 444 libusbpath.a $(PREFIX)/lib
+
+uninstall:
+ rm -f $(PREFIX)/bin/usbpath
+ rm -f $(PREFIX)/lib/libusbpath.a
+
+clean:
+ rm -f *.o
+
+spotless: clean
+ rm -f libusbpath.a usbpath
Added: trunk/src/host/usbpath/README
===================================================================
--- trunk/src/host/usbpath/README 2007-10-06 09:47:25 UTC (rev 3092)
+++ trunk/src/host/usbpath/README 2007-10-06 15:03:26 UTC (rev 3093)
@@ -0,0 +1,28 @@
+usbpath - Convert the physical locations of a USB device to/from its number
+===========================================================================
+
+A device number is represented by the following syntax:
+
+bus/devnum
+
+where "bus" is the number of the USB bus, using the numbering scheme
+employed by lsusb et al., and "devnum" is the number of the device on
+that bus.
+
+The physical location of a USB device is represented by the following
+syntax:
+
+bus+port+...+port
+
+where "bus" is again the number of the USB bus, and "port" is the number
+of the port on the respective next hub, counting from zero.
+
+
+usbport converts between the two representations.
+
+Example:
+usbport 1/19
+1+1+2
+
+usbport 1+1+2
+1/19
Added: trunk/src/host/usbpath/devnum2path.c
===================================================================
--- trunk/src/host/usbpath/devnum2path.c 2007-10-06 09:47:25 UTC (rev 3092)
+++ trunk/src/host/usbpath/devnum2path.c 2007-10-06 15:03:26 UTC (rev 3093)
@@ -0,0 +1,133 @@
+/*
+ * devnum2path.c - Translate a USB device number to the bus/port/... path
+ *
+ * (C) 2007 by OpenMoko, Inc.
+ * Written by Werner Almesberger <werner at openmoko.org>
+ *
+ * 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.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+#include <usb.h>
+#include <linux/usbdevice_fs.h>
+
+#include "usbpath.h"
+
+
+#define MAX_LEVELS 10
+
+
+static int port_by_devnum(const struct usb_device *hub, int devnum)
+{
+ struct usbdevfs_hub_portinfo portinfo;
+ int i;
+
+ usb_get_portinfo(hub, &portinfo);
+ for (i = 0; i != portinfo.nports; i++)
+ if (portinfo.port[i] == devnum)
+ return i;
+ return -1;
+}
+
+
+static int recurse_dev(const struct usb_device *devs, int *ports,
+ int num_ports, const struct usb_device *child)
+{
+ const struct usb_device *dev;
+ int n = 0, i;
+
+ for (dev = devs; dev; dev = dev->next)
+ for (i = 0; i != dev->num_children; i++)
+ if (dev->children[i] == child)
+ goto found;
+ return 0;
+
+found:
+ n = recurse_dev(devs, ports, num_ports, dev);
+ if (n < 0)
+ return i;
+ if (n == num_ports)
+ return -1;
+ ports[n] = port_by_devnum(dev, child->devnum);
+ assert(ports[n] >= 0);
+ return n+1;
+}
+
+
+int usb_devnum2portlist(const struct usb_bus *bus, int devnum, int *ports,
+ int num_ports)
+{
+ const struct usb_device *dev;
+
+ for (dev = bus->devices; dev; dev = dev->next)
+ if (dev->devnum == devnum)
+ break;
+ if (!dev)
+ return 0;
+ return recurse_dev(bus->devices, ports, num_ports, dev)+1;
+}
+
+
+static int add_int(char **path, int *path_size, int value)
+{
+ int v, n = 0;
+
+ for (v = value; v; v /= 10)
+ n++;
+ if (!n)
+ n++;
+ if (*path_size < n-1)
+ return -1;
+ n = sprintf(*path, "%d", value);
+ (*path) += n;
+ (*path_size) += n;
+ return n;
+}
+
+
+int usb_devnum2path(int busnum, int devnum, char *path, int path_size)
+{
+ const struct usb_bus *bus;
+ int ports[MAX_LEVELS];
+ int n, i, len, res;
+
+ for (bus = usb_get_busses(); bus; bus = bus->next)
+ if (atoi(bus->dirname) == busnum)
+ break;
+ n = usb_devnum2portlist(bus, devnum, ports, MAX_LEVELS);
+ if (n < 0)
+ return -1;
+ if (!n) {
+ if (path_size)
+ *path = 0;
+ return 0;
+ }
+ len = add_int(&path, &path_size, atoi(bus->dirname));
+ for (i = 0; i != n-1; i++) {
+ if (!path_size--)
+ return -1;
+ *path++ = '+';
+ res = add_int(&path, &path_size, ports[i]);
+ if (res < 0)
+ return -1;
+ len += res+1;
+ }
+ return len+1;
+}
Added: trunk/src/host/usbpath/path2devnum.c
===================================================================
--- trunk/src/host/usbpath/path2devnum.c 2007-10-06 09:47:25 UTC (rev 3092)
+++ trunk/src/host/usbpath/path2devnum.c 2007-10-06 15:03:26 UTC (rev 3093)
@@ -0,0 +1,148 @@
+/*
+ * path2devnum.c - Translate a bus/port/... path to the USB device number
+ *
+ * (C) 2007 by OpenMoko, Inc.
+ * Written by Werner Almesberger <werner at openmoko.org>
+ *
+ * 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.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+#include <usb.h>
+#include <linux/usbdevice_fs.h>
+
+#include "usbpath.h"
+
+
+static int devnum_by_port(const struct usb_device *hub, int port)
+{
+ struct usbdevfs_hub_portinfo portinfo;
+
+ usb_get_portinfo(hub, &portinfo);
+ if (port >= portinfo.nports)
+ return 0;
+ return portinfo.port[port];
+}
+
+
+static int find_hub_port(const struct usb_device *hub, const int *ports,
+ int num_ports)
+{
+ const struct usb_device *dev = NULL;
+ int devnum, i;
+
+ devnum = devnum_by_port(hub, *ports);
+ if (!devnum)
+ return 0;
+ if (num_ports == 1)
+ return devnum;
+ for (i = 0; i != hub->num_children; i++) {
+ dev = hub->children[i];
+ if (dev->devnum == devnum)
+ break;
+ }
+ assert(dev);
+ if (dev->descriptor.bDeviceClass != USB_CLASS_HUB)
+ return 0;
+ return find_hub_port(dev, ports+1, num_ports-1);
+}
+
+
+static int is_child(const struct usb_device *devs,
+ const struct usb_device *child)
+{
+ while (devs) {
+ int i;
+
+ for (i = 0; i != devs->num_children; i++)
+ if (devs->children[i] == child)
+ return 1;
+ devs = devs->next;
+ }
+ return 0;
+}
+
+
+static const struct usb_device *find_root_hub(struct usb_device *devs)
+{
+ const struct usb_device *hub;
+
+ for (hub = devs; hub; hub = hub->next) {
+ if (hub->descriptor.bDeviceClass != USB_CLASS_HUB)
+ continue;
+ if (!is_child(devs, hub))
+ break;
+ }
+ return hub;
+}
+
+
+int usb_portlist2devnum(const struct usb_bus *bus, const int *ports,
+ int num_ports)
+{
+ const struct usb_device *root;
+
+ root = find_root_hub(bus->devices);
+ if (!num_ports)
+ return root->devnum;
+ return find_hub_port(root, ports, num_ports);
+}
+
+
+int usb_path2devnum(const char *path)
+{
+ const struct usb_bus *bus;
+ const char *p;
+ int nums = 1, n = 0, res;
+ int *num;
+
+ if (!*path)
+ return -1;
+ for (p = path; *p; p++)
+ if (*p == '+')
+ nums++;
+ num = malloc(sizeof(int)*nums);
+ if (!num) {
+ perror("malloc");
+ exit(1);
+ }
+ while (1) {
+ char *end;
+
+ num[n++] = strtoul(path, &end, 10);
+ if (!*end && n == nums)
+ break;
+ if (*end != '+') {
+ free(num);
+ return -1;
+ }
+ path = end+1;
+ }
+ for (bus = usb_get_busses(); bus; bus = bus->next)
+ if (atoi(bus->dirname) == num[0])
+ break;
+ if (!bus) {
+ free(num);
+ return 0;
+ }
+ res = usb_portlist2devnum(bus, num+1, nums-1);
+ free(num);
+ return res;
+}
Added: trunk/src/host/usbpath/portinfo.c
===================================================================
--- trunk/src/host/usbpath/portinfo.c 2007-10-06 09:47:25 UTC (rev 3092)
+++ trunk/src/host/usbpath/portinfo.c 2007-10-06 15:03:26 UTC (rev 3093)
@@ -0,0 +1,62 @@
+/*
+ * portinfo.c - Obtain the port to device mapping of a USB hub
+ *
+ * (C) 2007 by OpenMoko, Inc.
+ * Written by Werner Almesberger <werner at openmoko.org>
+ *
+ * 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.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+
+#include <usb.h>
+#include <linux/usbdevice_fs.h>
+
+
+#define USBDEVFS_PREFIX "/proc/bus/usb"
+#define MAXPATH 256
+
+
+void usb_get_portinfo(const struct usb_device *hub,
+ struct usbdevfs_hub_portinfo *portinfo)
+{
+ struct usbdevfs_ioctl command;
+ char buf[MAXPATH];
+ int fd, ret;
+
+ snprintf(buf, MAXPATH, "%s/%s/%s", USBDEVFS_PREFIX, hub->bus->dirname,
+ hub->filename);
+ fd = open(buf, O_RDWR);
+ if (fd < 0) {
+ perror(buf);
+ exit(1);
+ }
+ command.ifno = 0;
+ command.ioctl_code = USBDEVFS_HUB_PORTINFO;
+ command.data = portinfo;
+ ret = ioctl(fd, USBDEVFS_IOCTL, &command);
+ if (ret < 0) {
+ perror("ioctl(USBDEVFS_IOCTL)");
+ exit(1);
+ }
+ if (close(fd) < 0) {
+ perror("close");
+ exit(1);
+ }
+}
Added: trunk/src/host/usbpath/usbpath.c
===================================================================
--- trunk/src/host/usbpath/usbpath.c 2007-10-06 09:47:25 UTC (rev 3092)
+++ trunk/src/host/usbpath/usbpath.c 2007-10-06 15:03:26 UTC (rev 3093)
@@ -0,0 +1,95 @@
+/*
+ * usbpath.c - Look up the number of a USB device by its physical location
+ *
+ * (C) 2007 by OpenMoko, Inc.
+ * Written by Werner Almesberger <werner at openmoko.org>
+ *
+ * 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.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <usb.h>
+#include "usbpath.h"
+
+
+#define MAX_PATH 256
+
+
+static void usage(const char *name)
+{
+ fprintf(stderr, "usage: %s bus+port+...\n", name);
+ fprintf(stderr, " %s bus/dev\n", name);
+ exit(1);
+}
+
+
+static void do_path(const char *path)
+{
+ int res;
+
+ res = usb_path2devnum(path);
+ if (res < 0) {
+ fprintf(stderr, "invalid path syntax\n");
+ exit(1);
+ }
+ if (!res) {
+ fprintf(stderr, "no such device\n");
+ exit(1);
+ }
+ printf("%d/%d\n", atoi(path), res);
+}
+
+
+static void do_devnum(const char *spec)
+{
+ char path[MAX_PATH];
+ int bus, devnum, res;
+
+ if (sscanf(spec, "%d/%d", &bus, &devnum) != 2) {
+ fprintf(stderr," invalid bus/devnum syntax\n");
+ exit(1);
+ }
+ res = usb_devnum2path(bus, devnum, path, MAX_PATH);
+ if (res < 0) {
+ fprintf(stderr, "buffer overflow\n");
+ exit(1);
+ }
+ if (!res) {
+ fprintf(stderr, "no such device\n");
+ exit(1);
+ }
+ printf("%s\n", path);
+}
+
+
+int main(int argc, char **argv)
+{
+ if (argc != 2)
+ usage(*argv);
+
+ usb_init();
+ usb_find_busses();
+ usb_find_devices();
+
+ if (strchr(argv[1], '/'))
+ do_devnum(argv[1]);
+ else
+ do_path(argv[1]);
+ return 0;
+}
Added: trunk/src/host/usbpath/usbpath.h
===================================================================
--- trunk/src/host/usbpath/usbpath.h 2007-10-06 09:47:25 UTC (rev 3092)
+++ trunk/src/host/usbpath/usbpath.h 2007-10-06 15:03:26 UTC (rev 3093)
@@ -0,0 +1,78 @@
+/*
+ * usbpath.h - Functions to convert the physical location of a device to its
+ * USB device number
+ *
+ * (C) 2007 by OpenMoko, Inc.
+ * Written by Werner Almesberger <werner at openmoko.org>
+ *
+ * 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.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef USBPATH_H
+#define USBPATH_H
+
+#include <usb.h>
+#include <linux/usbdevice_fs.h>
+
+/* portinfo.c */
+
+void usb_get_portinfo(const struct usb_device *hub,
+ struct usbdevfs_hub_portinfo *portinfo);
+
+
+/* path2devnum.c */
+
+/*
+ * Return codes:
+ * 0 device not found
+ * N device number
+ */
+
+int usb_portlist2devnum(const struct usb_bus *bus, const int *ports,
+ int num_ports);
+
+/*
+ * Return codes:
+ * -1 invalid path specification
+ * 0 device not found
+ * N device number
+ */
+
+int usb_path2devnum(const char *path);
+
+
+/* devnum2path.c */
+
+/*
+ * Return codes:
+ * -1 buffer overflow
+ * 0 device not found
+ * N N-1 ports placed into "ports"
+ */
+
+int usb_devnum2portlist(const struct usb_bus *bus, int devnum, int *ports,
+ int num_ports);
+
+/*
+ * Return codes:
+ * -1 buffer overflow
+ * 0 device not found
+ * N returned N characters (including the trailing NUL)
+ */
+
+int usb_devnum2path(int busnum, int devnum, char *path, int path_size);
+
+#endif /* !USBPATH_H */
More information about the commitlog
mailing list