1
0
mirror of git://projects.qi-hardware.com/ben-wpan.git synced 2024-11-26 11:50:36 +02:00

tools/lib: atusb can now be selected by bus/device or by bus-port path

Examples:

  usb:1/6	select logical device 6 on bus 1
  usb:1-3.1.4	starting at bus 1, choose ports 3, 1, and 4

- usbopen.c (initialize, open_usb): moved libusb initialization to
  separate function, to allow for sharing
- usbopen.h (restrict_usb_path), usbopen.c (restricted_path, open_usb,
  restrict_usb_dev, restrict_usb_by_dev, read_num, restrict_usb_by_port,
  restrict_usb_path): added mechanism to restrict USB path
- atusb.c (atusb_open): if an argument is given, call restrict_usb_path
  with it
This commit is contained in:
Werner Almesberger 2011-04-10 09:51:30 -03:00
parent a75edf0cc0
commit fc1ad9fffd
3 changed files with 139 additions and 7 deletions

View File

@ -54,6 +54,8 @@ static void *atusb_open(const char *arg)
{ {
usb_dev_handle *dev; usb_dev_handle *dev;
if (arg)
restrict_usb_path(arg);
dev = open_usb(USB_VENDOR, USB_PRODUCT); dev = open_usb(USB_VENDOR, USB_PRODUCT);
if (dev) { if (dev) {
error = 0; error = 0;

View File

@ -1,8 +1,8 @@
/* /*
* lib/usbopen.c - Common USB device lookup and open code * lib/usbopen.c - Common USB device lookup and open code
* *
* Written 2008-2010 by Werner Almesberger * Written 2008-2011 by Werner Almesberger
* Copyright 2008-2010 Werner Almesberger * Copyright 2008-2011 Werner Almesberger
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -12,16 +12,37 @@
#include <stdarg.h>
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <string.h>
#include <usb.h> #include <usb.h>
#include "usbopen.h" #include "usbopen.h"
#define USB_PATH_ROOT "/sys/bus/usb/devices/"
#define USB_BUS_LEAF "/busnum"
#define USB_DEV_LEAF "/devnum"
static uint16_t vendor = 0; static uint16_t vendor = 0;
static uint16_t product = 0; static uint16_t product = 0;
static const struct usb_device *restricted_path = NULL;
static void initialize(void)
{
static int initialized = 0;
if (initialized)
return;
initialized = 1;
usb_init();
usb_find_busses();
usb_find_devices();
}
usb_dev_handle *open_usb(uint16_t default_vendor, uint16_t default_product) usb_dev_handle *open_usb(uint16_t default_vendor, uint16_t default_product)
@ -33,12 +54,12 @@ usb_dev_handle *open_usb(uint16_t default_vendor, uint16_t default_product)
int res; int res;
#endif #endif
usb_init(); initialize();
usb_find_busses();
usb_find_devices();
for (bus = usb_get_busses(); bus; bus = bus->next) for (bus = usb_get_busses(); bus; bus = bus->next)
for (dev = bus->devices; dev; dev = dev->next) { for (dev = bus->devices; dev; dev = dev->next) {
if (restricted_path && restricted_path != dev)
continue;
if (dev->descriptor.idVendor != if (dev->descriptor.idVendor !=
(vendor ? vendor : default_vendor)) (vendor ? vendor : default_vendor))
continue; continue;
@ -99,3 +120,111 @@ void parse_usb_id(const char *id)
bad_id(id); bad_id(id);
product = tmp; product = tmp;
} }
static void restrict_usb_dev(int bus_num, int dev_num)
{
const struct usb_bus *bus;
const struct usb_device *dev;
initialize();
for (bus = usb_busses; bus; bus = bus->next) {
if (atoi(bus->dirname) != bus_num)
continue;
for (dev = bus->devices; dev; dev = dev->next)
if (dev->devnum == dev_num) {
restricted_path = dev;
return;
}
}
fprintf(stderr, "no device %d/%d\n", bus_num, dev_num);
exit(1);
}
static void restrict_usb_by_dev(const char *path)
{
int bus_num, dev_num;
if (sscanf(path, "%d/%d", &bus_num, &dev_num) != 2) {
fprintf(stderr, "invalid device syntax \"%s\"\n", path);
exit(1);
}
restrict_usb_dev(bus_num, dev_num);
}
static int read_num(const char *fmt, ...)
{
va_list ap;
FILE *file;
char *buf;
int n, num;
va_start(ap, fmt);
n = vsnprintf(NULL, 0, fmt, ap);
va_end(ap);
buf = malloc(n+1);
if (!buf) {
perror("malloc");
exit(1);
}
va_start(ap, fmt);
vsprintf(buf, fmt, ap);
va_end(ap);
file = fopen(buf, "r");
if (!file) {
perror(buf);
exit(1);
}
n = fscanf(file, "%d", &num);
if (n <0) {
perror(buf);
exit(1);
}
if (n != 1) {
fprintf(stderr, "%s: can't read number\n", buf);
exit(1);
}
fclose(file);
free(buf);
return num;
}
static void restrict_usb_by_port(const char *path)
{
const char *p;
int bus_num, dev_num;
/*
* We sanitize the path, in case we're part of a program running with
* suid.
*/
for (p = path; *p; p++)
if (!strchr("0123456789-.", *p)) {
fprintf(stderr,
"invalid character \'%c\' in USB path\n", *p);
exit(1);
}
bus_num = read_num("%s%s%s", USB_PATH_ROOT, path, USB_BUS_LEAF);
dev_num = read_num("%s%s%s", USB_PATH_ROOT, path, USB_DEV_LEAF);
restrict_usb_dev(bus_num, dev_num);
}
void restrict_usb_path(const char *path)
{
if (strchr(path, '/'))
restrict_usb_by_dev(path);
else
restrict_usb_by_port(path);
}

View File

@ -1,8 +1,8 @@
/* /*
* lib/usbopen.h - Common USB device lookup and open code * lib/usbopen.h - Common USB device lookup and open code
* *
* Written 2008-2010 by Werner Almesberger * Written 2008-2011 by Werner Almesberger
* Copyright 2008-2010 Werner Almesberger * Copyright 2008-2011 Werner Almesberger
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -20,5 +20,6 @@
usb_dev_handle *open_usb(uint16_t default_vendor, uint16_t default_product); usb_dev_handle *open_usb(uint16_t default_vendor, uint16_t default_product);
void parse_usb_id(const char *id); void parse_usb_id(const char *id);
void restrict_usb_path(const char *path);
#endif /* !USB_OPEN_H */ #endif /* !USB_OPEN_H */