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
v19.07.3_mercusys_ac12_duma
Jo-Philipp Wich 12 years ago
parent ec770abd0d
commit b29239d9f0

@ -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.
# See /LICENSE for more information.
@ -8,7 +8,7 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=usbreset
PKG_RELEASE:=1
PKG_RELEASE:=2
include $(INCLUDE_DIR)/package.mk

@ -8,16 +8,16 @@ and needs mounted usbfs filesystem
sudo mount -t usbfs none /proc/bus/usb
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
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
suspend a device, do (as root):
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.
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.
> To reset a
@ -37,40 +37,217 @@ Alan Stern
*/
#include <stdio.h>
#include <stdbool.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <sys/ioctl.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 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) {
fprintf(stderr, "Usage: usbreset device-filename\n");
close(fd);
}
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;
}
filename = argv[1];
fd = open(filename, O_WRONLY);
if (fd < 0) {
perror("Error opening output file");
if ((argc == 2) && (sscanf(argv[1], "%3d/%3d", &id1, &id2) == 2))
{
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;
}
printf("Resetting USB device %s\n", filename);
rc = ioctl(fd, USBDEVFS_RESET, 0);
if (rc < 0) {
perror("Error in ioctl");
if (!dev)
{
fprintf(stderr, "No such device found\n");
return 1;
}
printf("Reset successful\n");
close(fd);
reset_device(dev);
return 0;
}

Loading…
Cancel
Save