blob: 6df21aecc7dbc61d6642af5d3ac33773e608819f [file] [log] [blame]
/* lsusb.c - list available USB devices
*
* Copyright 2013 Andre Renaud <andre@bluewatersys.com>
USE_LSUSB(NEWTOY(lsusb, NULL, TOYFLAG_USR|TOYFLAG_BIN))
config LSUSB
bool "lsusb"
default y
help
usage: lsusb
List USB hosts/devices.
*/
#define FOR_lsusb
#include "toys.h"
GLOBALS(
void *ids;
)
struct ids {
struct ids *next, *child;
int id;
char name[];
};
static int list_device(struct dirtree *new)
{
FILE *file;
char *name;
struct ids *ids;
int busnum = 0, devnum = 0, pid = 0, vid = 0, count = 0;
if (!new->parent) return DIRTREE_RECURSE;
if (new->name[0] == '.') return 0;
// Read data from proc file
sprintf(toybuf, "%s/uevent", name = dirtree_path(new, 0));
if (!(file = fopen(toybuf, "r"))) return 0;
while (fgets(toybuf, sizeof(toybuf), file))
if (sscanf(toybuf, "BUSNUM=%u\n", &busnum)
|| sscanf(toybuf, "DEVNUM=%u\n", &devnum)
|| sscanf(toybuf, "PRODUCT=%x/%x/", &pid, &vid)) count++;
fclose(file);
// Output with any matching ids data
if (count == 3) {
printf("Bus %03d Device %03d: ID %04x:%04x", busnum, devnum, pid, vid);
for (ids = TT.ids; ids; ids = ids->next) {
if (pid != ids->id) continue;
printf("%s", ids->name);
for (ids = ids->child; ids; ids = ids->next) {
if (vid != ids->id) continue;
printf("%s", ids->name);
break;
}
break;
}
xputc('\n');
}
free(name);
return 0;
}
void lsusb_main(void)
{
int fd;
// Parse http://www.linux-usb.org/usb.ids file (if available)
if (-1 != (fd = open("/etc/usb.ids", O_RDONLY))) {
FILE *fp = fdopen(fd, "r");
char *s, *ss;
struct ids *ids, *tids;
while ((s = xgetline(fp))) {
fd = estrtol(s, &ss, 16);
if (ss == s+4+(*s=='\t') && *ss++==' ') {
ids = xmalloc(sizeof(*ids)+strlen(ss)+1);
ids->child = 0;
ids->id = fd;
strcpy(ids->name, ss);
if (!TT.ids || *s!='\t') {
ids->next = TT.ids;
TT.ids = ids;
} else {
tids = TT.ids;
ids->next = tids->child;
tids->child = ids;
}
}
free(s);
}
fclose(fp);
}
dirtree_read("/sys/bus/usb/devices/", list_device);
}