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