usbreset: rewrite to not rely on /proc/bus/usb anymore
SVN-Revision: 37893
This commit is contained in:
		@@ -1,5 +1,5 @@
 | 
				
			|||||||
#
 | 
					#
 | 
				
			||||||
# Copyright (C) 2011-2012 OpenWrt.org
 | 
					# Copyright (C) 2011-2013 OpenWrt.org
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# This is free software, licensed under the GNU General Public License v2.
 | 
					# This is free software, licensed under the GNU General Public License v2.
 | 
				
			||||||
# See /LICENSE for more information.
 | 
					# See /LICENSE for more information.
 | 
				
			||||||
@@ -8,7 +8,7 @@
 | 
				
			|||||||
include $(TOPDIR)/rules.mk
 | 
					include $(TOPDIR)/rules.mk
 | 
				
			||||||
 | 
					
 | 
				
			||||||
PKG_NAME:=usbreset
 | 
					PKG_NAME:=usbreset
 | 
				
			||||||
PKG_RELEASE:=2
 | 
					PKG_RELEASE:=3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
include $(INCLUDE_DIR)/package.mk
 | 
					include $(INCLUDE_DIR)/package.mk
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -42,7 +42,11 @@ Alan Stern
 | 
				
			|||||||
#include <fcntl.h>
 | 
					#include <fcntl.h>
 | 
				
			||||||
#include <errno.h>
 | 
					#include <errno.h>
 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					#include <ctype.h>
 | 
				
			||||||
 | 
					#include <limits.h>
 | 
				
			||||||
 | 
					#include <dirent.h>
 | 
				
			||||||
#include <sys/ioctl.h>
 | 
					#include <sys/ioctl.h>
 | 
				
			||||||
 | 
					#include <sys/types.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <linux/usbdevice_fs.h>
 | 
					#include <linux/usbdevice_fs.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -59,86 +63,70 @@ struct usbentry {
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool find_usbfs(void)
 | 
					static char *sysfs_attr(const char *dev, const char *attr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	FILE *mtab;
 | 
						int fd, len;
 | 
				
			||||||
 | 
						char path[PATH_MAX];
 | 
				
			||||||
 | 
						static char buf[129];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	char buf[1024], type[32];
 | 
						memset(buf, 0, sizeof(buf));
 | 
				
			||||||
	static char path[1024];
 | 
						snprintf(path, sizeof(path) - 1, "/sys/bus/usb/devices/%s/%s", dev, attr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ((mtab = fopen("/proc/mounts", "r")) != NULL)
 | 
						if ((fd = open(path, O_RDONLY)) >= 0)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		while (fgets(buf, sizeof(buf), mtab))
 | 
							len = read(fd, buf, sizeof(buf) - 1);
 | 
				
			||||||
		{
 | 
							close(fd);
 | 
				
			||||||
			if (sscanf(buf, "%*s %1023s %31s ", path, type) == 2 &&
 | 
					 | 
				
			||||||
				!strncmp(type, "usbfs", 5))
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				usbfs = path;
 | 
					 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		fclose(mtab);
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return !!usbfs;
 | 
						while (--len > 0 && isspace(buf[len]))
 | 
				
			||||||
 | 
							buf[len] = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return (len >= 0) ? buf : NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static FILE * open_devlist(void)
 | 
					static struct usbentry * parse_devlist(DIR *d)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	char buf[1024];
 | 
						char *attr;
 | 
				
			||||||
	snprintf(buf, sizeof(buf), "%s/devices", usbfs);
 | 
						struct dirent *e;
 | 
				
			||||||
	return fopen(buf, "r");
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void close_devlist(FILE *devs)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	fclose(devs);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static struct usbentry * parse_devlist(FILE *devs)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	char buf[1024];
 | 
					 | 
				
			||||||
	static struct usbentry dev;
 | 
						static struct usbentry dev;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						do {
 | 
				
			||||||
 | 
							e = readdir(d);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (!e)
 | 
				
			||||||
 | 
								return NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						while(!isdigit(e->d_name[0]) || strchr(e->d_name, ':'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	memset(&dev, 0, sizeof(dev));
 | 
						memset(&dev, 0, sizeof(dev));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	while (fgets(buf, sizeof(buf), devs))
 | 
						if ((attr = sysfs_attr(e->d_name, "busnum")) != NULL)
 | 
				
			||||||
	{
 | 
							dev.bus_num = strtoul(attr, NULL, 10);
 | 
				
			||||||
		buf[strlen(buf)-1] = 0;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		switch (buf[0])
 | 
						if ((attr = sysfs_attr(e->d_name, "devnum")) != NULL)
 | 
				
			||||||
		{
 | 
							dev.dev_num = strtoul(attr, NULL, 10);
 | 
				
			||||||
		case 'T':
 | 
					 | 
				
			||||||
			sscanf(buf, "T: Bus=%d Lev=%*d Prnt=%*d Port=%*d Cnt=%*d Dev#=%d",
 | 
					 | 
				
			||||||
				   &dev.bus_num, &dev.dev_num);
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		case 'P':
 | 
						if ((attr = sysfs_attr(e->d_name, "idVendor")) != NULL)
 | 
				
			||||||
			sscanf(buf, "P: Vendor=%x ProdID=%x",
 | 
							dev.vendor_id = strtoul(attr, NULL, 16);
 | 
				
			||||||
				   &dev.vendor_id, &dev.product_id);
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		case 'S':
 | 
						if ((attr = sysfs_attr(e->d_name, "idProduct")) != NULL)
 | 
				
			||||||
			if (!strncmp(buf, "S:  Manufacturer=", 17))
 | 
							dev.product_id = strtoul(attr, NULL, 16);
 | 
				
			||||||
				snprintf(dev.vendor_name, sizeof(dev.vendor_name),
 | 
					 | 
				
			||||||
				         "%s", buf+17);
 | 
					 | 
				
			||||||
			else if (!strncmp(buf, "S:  Product=", 12))
 | 
					 | 
				
			||||||
				snprintf(dev.product_name, sizeof(dev.product_name),
 | 
					 | 
				
			||||||
				         "%s", buf+12);
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (dev.product_name[0])
 | 
						if ((attr = sysfs_attr(e->d_name, "manufacturer")) != NULL)
 | 
				
			||||||
			return &dev;
 | 
							strcpy(dev.vendor_name, attr);
 | 
				
			||||||
	}
 | 
					
 | 
				
			||||||
 | 
						if ((attr = sysfs_attr(e->d_name, "product")) != NULL)
 | 
				
			||||||
 | 
							strcpy(dev.product_name, attr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (dev.bus_num && dev.dev_num && dev.vendor_id && dev.product_id)
 | 
				
			||||||
 | 
							return &dev;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return NULL;
 | 
						return NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void list_devices(void)
 | 
					static void list_devices(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	FILE *devs = open_devlist();
 | 
						DIR *devs = opendir("/sys/bus/usb/devices");
 | 
				
			||||||
	struct usbentry *dev;
 | 
						struct usbentry *dev;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!devs)
 | 
						if (!devs)
 | 
				
			||||||
@@ -152,14 +140,14 @@ static void list_devices(void)
 | 
				
			|||||||
			   dev->product_name);
 | 
								   dev->product_name);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	close_devlist(devs);
 | 
						closedir(devs);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct usbentry * find_device(int *bus, int *dev,
 | 
					struct usbentry * find_device(int *bus, int *dev,
 | 
				
			||||||
                              int *vid, int *pid,
 | 
					                              int *vid, int *pid,
 | 
				
			||||||
                              const char *product)
 | 
					                              const char *product)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	FILE *devs = open_devlist();
 | 
						DIR *devs = opendir("/sys/bus/usb/devices");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct usbentry *e, *match = NULL;
 | 
						struct usbentry *e, *match = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -177,7 +165,7 @@ struct usbentry * find_device(int *bus, int *dev,
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	close_devlist(devs);
 | 
						closedir(devs);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return match;
 | 
						return match;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -185,10 +173,10 @@ struct usbentry * find_device(int *bus, int *dev,
 | 
				
			|||||||
static void reset_device(struct usbentry *dev)
 | 
					static void reset_device(struct usbentry *dev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int fd;
 | 
						int fd;
 | 
				
			||||||
	char path[1024];
 | 
						char path[PATH_MAX];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	snprintf(path, sizeof(path), "%s/%03d/%03d",
 | 
						snprintf(path, sizeof(path) - 1, "/dev/bus/usb/%03d/%03d",
 | 
				
			||||||
			 usbfs, dev->bus_num, dev->dev_num);
 | 
						         dev->bus_num, dev->dev_num);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	printf("Resetting %s ... ", dev->product_name);
 | 
						printf("Resetting %s ... ", dev->product_name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -213,12 +201,6 @@ int main(int argc, char **argv)
 | 
				
			|||||||
	int id1, id2;
 | 
						int id1, id2;
 | 
				
			||||||
	struct usbentry *dev;
 | 
						struct usbentry *dev;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!find_usbfs())
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		fprintf(stderr, "Unable to find usbfs, is it mounted?\n");
 | 
					 | 
				
			||||||
		return 1;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if ((argc == 2) && (sscanf(argv[1], "%3d/%3d", &id1, &id2) == 2))
 | 
						if ((argc == 2) && (sscanf(argv[1], "%3d/%3d", &id1, &id2) == 2))
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		dev = find_device(&id1, &id2, NULL, NULL, NULL);
 | 
							dev = find_device(&id1, &id2, NULL, NULL, NULL);
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user