mirror of https://github.com/hak5/openwrt-owl.git
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: 32741owl
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.
|
# 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>
|
||||||
|
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
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");
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("can't open [%s]\n", strerror(errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
const char *filename;
|
int id1, id2;
|
||||||
int fd;
|
struct usbentry *dev;
|
||||||
int rc;
|
|
||||||
|
|
||||||
if (argc != 2) {
|
if (!find_usbfs())
|
||||||
fprintf(stderr, "Usage: usbreset device-filename\n");
|
{
|
||||||
return 1;
|
fprintf(stderr, "Unable to find usbfs, is it mounted?\n");
|
||||||
}
|
|
||||||
filename = argv[1];
|
|
||||||
|
|
||||||
fd = open(filename, O_WRONLY);
|
|
||||||
if (fd < 0) {
|
|
||||||
perror("Error opening output file");
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Resetting USB device %s\n", filename);
|
if ((argc == 2) && (sscanf(argv[1], "%3d/%3d", &id1, &id2) == 2))
|
||||||
rc = ioctl(fd, USBDEVFS_RESET, 0);
|
{
|
||||||
if (rc < 0) {
|
dev = find_device(&id1, &id2, NULL, NULL, NULL);
|
||||||
perror("Error in ioctl");
|
}
|
||||||
|
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("Reset successful\n");
|
|
||||||
|
|
||||||
close(fd);
|
if (!dev)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "No such device found\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
reset_device(dev);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue