usbreset: improve usability - add device list in usage screen - support resetting by bus/device number, by produc:vendor id or by device name

SVN-Revision: 32741
master
Jo-Philipp Wich 12 years ago
parent ec770abd0d
commit b29239d9f0
  1. 4
      package/usbreset/Makefile
  2. 215
      package/usbreset/src/usbreset.c

@ -1,5 +1,5 @@
# #
# Copyright (C) 2011 OpenWrt.org # Copyright (C) 2011-2012 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:=1 PKG_RELEASE:=2
include $(INCLUDE_DIR)/package.mk include $(INCLUDE_DIR)/package.mk

@ -8,16 +8,16 @@ and needs mounted usbfs filesystem
sudo mount -t usbfs none /proc/bus/usb sudo mount -t usbfs none /proc/bus/usb
There is a way to suspend a USB device. In order to use it, There is a way to suspend a USB device. In order to use it,
you must have a kernel with CONFIG_PM_SYSFS_DEPRECATED turned on. To you must have a kernel with CONFIG_PM_SYSFS_DEPRECATED turned on. To
suspend a device, do (as root): suspend a device, do (as root):
echo -n 2 >/sys/bus/usb/devices/.../power/state echo -n 2 >/sys/bus/usb/devices/.../power/state
where the "..." is the ID for your device. To unsuspend, do the same where the "..." is the ID for your device. To unsuspend, do the same
thing but with a "0" instead of the "2" above. thing but with a "0" instead of the "2" above.
Note that this mechanism is slated to be removed from the kernel within Note that this mechanism is slated to be removed from the kernel within
the next year. Hopefully some other mechanism will take its place. the next year. Hopefully some other mechanism will take its place.
> To reset a > To reset a
@ -37,40 +37,217 @@ Alan Stern
*/ */
#include <stdio.h> #include <stdio.h>
#include <stdbool.h>
#include <unistd.h> #include <unistd.h>
#include <fcntl.h> #include <fcntl.h>
#include <errno.h> #include <errno.h>
#include <string.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <linux/usbdevice_fs.h> #include <linux/usbdevice_fs.h>
int main(int argc, char **argv) static char *usbfs = NULL;
struct usbentry {
int bus_num;
int dev_num;
int vendor_id;
int product_id;
char vendor_name[128];
char product_name[128];
};
static bool find_usbfs(void)
{
FILE *mtab;
char buf[1024], type[32];
static char path[1024];
if ((mtab = fopen("/proc/mounts", "r")) != NULL)
{
while (fgets(buf, sizeof(buf), mtab))
{
if (sscanf(buf, "%*s %1023s %31s ", path, type) == 2 &&
!strncmp(type, "usbfs", 5))
{
usbfs = path;
break;
}
}
fclose(mtab);
}
return !!usbfs;
}
static FILE * open_devlist(void)
{
char buf[1024];
snprintf(buf, sizeof(buf), "%s/devices", usbfs);
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;
memset(&dev, 0, sizeof(dev));
while (fgets(buf, sizeof(buf), devs))
{
buf[strlen(buf)-1] = 0;
switch (buf[0])
{
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':
sscanf(buf, "P: Vendor=%x ProdID=%x",
&dev.vendor_id, &dev.product_id);
break;
case 'S':
if (!strncmp(buf, "S: Manufacturer=", 17))
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])
return &dev;
}
return NULL;
}
static void list_devices(void)
{
FILE *devs = open_devlist();
struct usbentry *dev;
if (!devs)
return;
while ((dev = parse_devlist(devs)) != NULL)
{
printf(" Number %03d/%03d ID %04x:%04x %s\n",
dev->bus_num, dev->dev_num,
dev->vendor_id, dev->product_id,
dev->product_name);
}
close_devlist(devs);
}
struct usbentry * find_device(int *bus, int *dev,
int *vid, int *pid,
const char *product)
{
FILE *devs = open_devlist();
struct usbentry *e, *match = NULL;
if (!devs)
return NULL;
while ((e = parse_devlist(devs)) != NULL)
{
if ((bus && (e->bus_num == *bus) && (e->dev_num == *dev)) ||
(vid && (e->vendor_id == *vid) && (e->product_id == *pid)) ||
(product && !strcasecmp(e->product_name, product)))
{
match = e;
break;
}
}
close_devlist(devs);
return match;
}
static void reset_device(struct usbentry *dev)
{ {
const char *filename;
int fd; int fd;
int rc; char path[1024];
snprintf(path, sizeof(path), "%s/%03d/%03d",
usbfs, dev->bus_num, dev->dev_num);
printf("Resetting %s ... ", dev->product_name);
if ((fd = open(path, O_WRONLY)) > -1)
{
if (ioctl(fd, USBDEVFS_RESET, 0) < 0)
printf("failed [%s]\n", strerror(errno));
else
printf("ok\n");
if (argc != 2) { close(fd);
fprintf(stderr, "Usage: usbreset device-filename\n"); }
else
{
printf("can't open [%s]\n", strerror(errno));
}
}
int main(int argc, char **argv)
{
int id1, id2;
struct usbentry *dev;
if (!find_usbfs())
{
fprintf(stderr, "Unable to find usbfs, is it mounted?\n");
return 1; return 1;
} }
filename = argv[1];
fd = open(filename, O_WRONLY); if ((argc == 2) && (sscanf(argv[1], "%3d/%3d", &id1, &id2) == 2))
if (fd < 0) { {
perror("Error opening output file"); dev = find_device(&id1, &id2, NULL, NULL, NULL);
}
else if ((argc == 2) && (sscanf(argv[1], "%4x:%4x", &id1, &id2) == 2))
{
dev = find_device(NULL, NULL, &id1, &id2, NULL);
}
else if ((argc == 2) && strlen(argv[1]) < 128)
{
dev = find_device(NULL, NULL, NULL, NULL, argv[1]);
}
else
{
printf("Usage:\n"
" usbreset PPPP:VVVV - reset by product and vendor id\n"
" usbreset BBB/DDD - reset by bus and device number\n"
" usbreset \"Product\" - reset by product name\n\n"
"Devices:\n");
list_devices();
return 1; return 1;
} }
printf("Resetting USB device %s\n", filename); if (!dev)
rc = ioctl(fd, USBDEVFS_RESET, 0); {
if (rc < 0) { fprintf(stderr, "No such device found\n");
perror("Error in ioctl");
return 1; return 1;
} }
printf("Reset successful\n");
close(fd); reset_device(dev);
return 0; return 0;
} }

Loading…
Cancel
Save