|
Lines 26-33
Link Here
|
| 26 |
#if defined(__linux__) |
26 |
#if defined(__linux__) |
| 27 |
#include <dirent.h> |
27 |
#include <dirent.h> |
| 28 |
#include <sys/ioctl.h> |
28 |
#include <sys/ioctl.h> |
| 29 |
#include <linux/usbdevice_fs.h> |
29 |
struct usbdevfs_bulktransfer { |
| 30 |
#include <linux/version.h> |
30 |
unsigned int ep; |
|
|
31 |
unsigned int len; |
| 32 |
unsigned int timeout; /* in milliseconds */ |
| 33 |
void *data; |
| 34 |
}; |
| 35 |
struct usbdevfs_connectinfo { |
| 36 |
unsigned int devnum; |
| 37 |
unsigned char slow; |
| 38 |
}; |
| 31 |
|
39 |
|
| 32 |
/* We redefine it to avoid version problems */ |
40 |
/* We redefine it to avoid version problems */ |
| 33 |
struct usb_ctrltransfer { |
41 |
struct usb_ctrltransfer { |
|
Lines 49-55
Link Here
|
| 49 |
|
57 |
|
| 50 |
//#define DEBUG |
58 |
//#define DEBUG |
| 51 |
|
59 |
|
| 52 |
#define USBDEVFS_PATH "/proc/bus/usb" |
60 |
#define USBDEVFS_PATH "/dev/bus/usb" |
| 53 |
#define PRODUCT_NAME_SZ 32 |
61 |
#define PRODUCT_NAME_SZ 32 |
| 54 |
|
62 |
|
| 55 |
typedef struct USBHostDevice { |
63 |
typedef struct USBHostDevice { |
|
Lines 99-105
Link Here
|
| 99 |
ct.wLength = length; |
107 |
ct.wLength = length; |
| 100 |
ct.timeout = 50; |
108 |
ct.timeout = 50; |
| 101 |
ct.data = data; |
109 |
ct.data = data; |
| 102 |
ret = ioctl(s->fd, USBDEVFS_CONTROL, &ct); |
110 |
//ret = ioctl(s->fd, USBDEVFS_CONTROL, &ct); |
|
|
111 |
ret = ioctl(s->fd, _IOWR('U', 0, struct usb_ctrltransfer), &ct); |
| 103 |
if (ret < 0) { |
112 |
if (ret < 0) { |
| 104 |
switch(errno) { |
113 |
switch(errno) { |
| 105 |
case ETIMEDOUT: |
114 |
case ETIMEDOUT: |
|
Lines 128-134
Link Here
|
| 128 |
bt.len = p->len; |
137 |
bt.len = p->len; |
| 129 |
bt.timeout = 50; |
138 |
bt.timeout = 50; |
| 130 |
bt.data = p->data; |
139 |
bt.data = p->data; |
| 131 |
ret = ioctl(s->fd, USBDEVFS_BULK, &bt); |
140 |
//ret = ioctl(s->fd, USBDEVFS_BULK, &bt); |
|
|
141 |
ret = ioctl(s->fd, _IOWR('U', 2, struct usbdevfs_bulktransfer), &bt); |
| 132 |
if (ret < 0) { |
142 |
if (ret < 0) { |
| 133 |
switch(errno) { |
143 |
switch(errno) { |
| 134 |
case ETIMEDOUT: |
144 |
case ETIMEDOUT: |
|
Lines 208-214
Link Here
|
| 208 |
|
218 |
|
| 209 |
/* XXX: only grab if all interfaces are free */ |
219 |
/* XXX: only grab if all interfaces are free */ |
| 210 |
interface = 0; |
220 |
interface = 0; |
| 211 |
ret = ioctl(fd, USBDEVFS_CLAIMINTERFACE, &interface); |
221 |
//ret = ioctl(fd, USBDEVFS_CLAIMINTERFACE, &interface); |
|
|
222 |
ret = ioctl(fd, _IOR('U', 15, unsigned int), &interface); |
| 212 |
if (ret < 0) { |
223 |
if (ret < 0) { |
| 213 |
if (errno == EBUSY) { |
224 |
if (errno == EBUSY) { |
| 214 |
fprintf(stderr, "usb_host: device already grabbed\n"); |
225 |
fprintf(stderr, "usb_host: device already grabbed\n"); |
|
Lines 220-226
Link Here
|
| 220 |
return NULL; |
231 |
return NULL; |
| 221 |
} |
232 |
} |
| 222 |
|
233 |
|
| 223 |
ret = ioctl(fd, USBDEVFS_CONNECTINFO, &ci); |
234 |
//ret = ioctl(fd, USBDEVFS_CONNECTINFO, &ci); |
|
|
235 |
ret = ioctl(fd, _IOW('U', 17, struct usbdevfs_connectinfo), &ci); |
| 224 |
if (ret < 0) { |
236 |
if (ret < 0) { |
| 225 |
perror("USBDEVFS_CONNECTINFO"); |
237 |
perror("USBDEVFS_CONNECTINFO"); |
| 226 |
goto fail; |
238 |
goto fail; |
|
Lines 255-356
Link Here
|
| 255 |
return (USBDevice *)dev; |
267 |
return (USBDevice *)dev; |
| 256 |
} |
268 |
} |
| 257 |
|
269 |
|
| 258 |
static int get_tag_value(char *buf, int buf_size, |
|
|
| 259 |
const char *str, const char *tag, |
| 260 |
const char *stopchars) |
| 261 |
{ |
| 262 |
const char *p; |
| 263 |
char *q; |
| 264 |
p = strstr(str, tag); |
| 265 |
if (!p) |
| 266 |
return -1; |
| 267 |
p += strlen(tag); |
| 268 |
while (isspace(*p)) |
| 269 |
p++; |
| 270 |
q = buf; |
| 271 |
while (*p != '\0' && !strchr(stopchars, *p)) { |
| 272 |
if ((q - buf) < (buf_size - 1)) |
| 273 |
*q++ = *p; |
| 274 |
p++; |
| 275 |
} |
| 276 |
*q = '\0'; |
| 277 |
return q - buf; |
| 278 |
} |
| 279 |
|
| 280 |
static int usb_host_scan(void *opaque, USBScanFunc *func) |
270 |
static int usb_host_scan(void *opaque, USBScanFunc *func) |
| 281 |
{ |
271 |
{ |
| 282 |
FILE *f; |
272 |
FILE *f; |
| 283 |
char line[1024]; |
273 |
char line[1024]; |
| 284 |
char buf[1024]; |
274 |
int bus_num, addr, speed, class_id, product_id, vendor_id; |
| 285 |
int bus_num, addr, speed, device_count, class_id, product_id, vendor_id; |
|
|
| 286 |
int ret; |
275 |
int ret; |
| 287 |
char product_name[512]; |
276 |
char product_name[512]; |
|
|
277 |
DIR* d; |
| 278 |
struct dirent* de; |
| 288 |
|
279 |
|
| 289 |
f = fopen(USBDEVFS_PATH "/devices", "r"); |
280 |
d = opendir("/sys/bus/usb/devices"); |
| 290 |
if (!f) { |
281 |
if (!d) { |
| 291 |
term_printf("Could not open %s\n", USBDEVFS_PATH "/devices"); |
282 |
term_printf("Could not open /sys/bus/usb/devices\n"); |
| 292 |
return 0; |
283 |
return 0; |
| 293 |
} |
284 |
} |
| 294 |
device_count = 0; |
285 |
while ((de = readdir(d))) { |
| 295 |
bus_num = addr = speed = class_id = product_id = vendor_id = 0; |
286 |
if (de->d_name[0] != '.' && ! strchr(de->d_name, ':')) { |
| 296 |
ret = 0; |
287 |
char filename[PATH_MAX]; |
| 297 |
for(;;) { |
288 |
char* tmpstr = de->d_name; |
| 298 |
if (fgets(line, sizeof(line), f) == NULL) |
289 |
if (!strncmp(de->d_name, "usb", 3)) |
| 299 |
break; |
290 |
tmpstr += 3; |
| 300 |
if (strlen(line) > 0) |
291 |
bus_num = atoi(tmpstr); |
| 301 |
line[strlen(line) - 1] = '\0'; |
292 |
snprintf(filename, PATH_MAX, "/sys/bus/usb/devices/%s/devnum", de->d_name); |
| 302 |
if (line[0] == 'T' && line[1] == ':') { |
293 |
f = fopen(filename, "r"); |
| 303 |
if (device_count && (vendor_id || product_id)) { |
294 |
if (!f) { |
| 304 |
/* New device. Add the previously discovered device. */ |
295 |
term_printf("Could not open %s\n", filename); |
| 305 |
ret = func(opaque, bus_num, addr, class_id, vendor_id, |
296 |
return 0; |
| 306 |
product_id, product_name, speed); |
297 |
} |
| 307 |
if (ret) |
298 |
fgets(line, sizeof(line), f); |
| 308 |
goto the_end; |
299 |
fclose(f); |
| 309 |
} |
300 |
addr = atoi(line); |
| 310 |
if (get_tag_value(buf, sizeof(buf), line, "Bus=", " ") < 0) |
301 |
snprintf(filename, PATH_MAX, "/sys/bus/usb/devices/%s/bDeviceClass", de->d_name); |
| 311 |
goto fail; |
302 |
f = fopen(filename, "r"); |
| 312 |
bus_num = atoi(buf); |
303 |
if (!f) { |
| 313 |
if (get_tag_value(buf, sizeof(buf), line, "Dev#=", " ") < 0) |
304 |
term_printf("Could not open %s\n", filename); |
| 314 |
goto fail; |
305 |
return 0; |
| 315 |
addr = atoi(buf); |
306 |
} |
| 316 |
if (get_tag_value(buf, sizeof(buf), line, "Spd=", " ") < 0) |
307 |
fgets(line, sizeof(line), f); |
| 317 |
goto fail; |
308 |
fclose(f); |
| 318 |
if (!strcmp(buf, "480")) |
309 |
class_id = strtoul(line, NULL, 16); |
|
|
310 |
snprintf(filename, PATH_MAX, "/sys/bus/usb/devices/%s/idVendor", de->d_name); |
| 311 |
f = fopen(filename, "r"); |
| 312 |
if (!f) { |
| 313 |
term_printf("Could not open %s\n", filename); |
| 314 |
return 0; |
| 315 |
} |
| 316 |
fgets(line, sizeof(line), f); |
| 317 |
fclose(f); |
| 318 |
vendor_id = strtoul(line, NULL, 16); |
| 319 |
snprintf(filename, PATH_MAX, "/sys/bus/usb/devices/%s/idProduct", de->d_name); |
| 320 |
f = fopen(filename, "r"); |
| 321 |
if (!f) { |
| 322 |
term_printf("Could not open %s\n", filename); |
| 323 |
return 0; |
| 324 |
} |
| 325 |
fgets(line, sizeof(line), f); |
| 326 |
fclose(f); |
| 327 |
product_id = strtoul(line, NULL, 16); |
| 328 |
snprintf(filename, PATH_MAX, "/sys/bus/usb/devices/%s/product", de->d_name); |
| 329 |
f = fopen(filename, "r"); |
| 330 |
if (!f) { |
| 331 |
term_printf("Could not open %s\n", filename); |
| 332 |
return 0; |
| 333 |
} |
| 334 |
fgets(line, sizeof(line), f); |
| 335 |
fclose(f); |
| 336 |
if (strlen(line) > 0) |
| 337 |
line[strlen(line) - 1] = '\0'; |
| 338 |
pstrcpy(product_name, sizeof(product_name), line); |
| 339 |
snprintf(filename, PATH_MAX, "/sys/bus/usb/devices/%s/speed", de->d_name); |
| 340 |
f = fopen(filename, "r"); |
| 341 |
if (!f) { |
| 342 |
term_printf("Could not open %s\n", filename); |
| 343 |
return 0; |
| 344 |
} |
| 345 |
fgets(line, sizeof(line), f); |
| 346 |
fclose(f); |
| 347 |
if (!strcmp(line, "480\n")) |
| 319 |
speed = USB_SPEED_HIGH; |
348 |
speed = USB_SPEED_HIGH; |
| 320 |
else if (!strcmp(buf, "1.5")) |
349 |
else if (!strcmp(line, "1.5\n")) |
| 321 |
speed = USB_SPEED_LOW; |
350 |
speed = USB_SPEED_LOW; |
| 322 |
else |
351 |
else |
| 323 |
speed = USB_SPEED_FULL; |
352 |
speed = USB_SPEED_FULL; |
| 324 |
product_name[0] = '\0'; |
353 |
ret = func(opaque, bus_num, addr, class_id, vendor_id, |
| 325 |
class_id = 0xff; |
354 |
product_id, product_name, speed); |
| 326 |
device_count++; |
355 |
if (ret) |
| 327 |
product_id = 0; |
356 |
goto the_end; |
| 328 |
vendor_id = 0; |
357 |
} |
| 329 |
} else if (line[0] == 'P' && line[1] == ':') { |
|
|
| 330 |
if (get_tag_value(buf, sizeof(buf), line, "Vendor=", " ") < 0) |
| 331 |
goto fail; |
| 332 |
vendor_id = strtoul(buf, NULL, 16); |
| 333 |
if (get_tag_value(buf, sizeof(buf), line, "ProdID=", " ") < 0) |
| 334 |
goto fail; |
| 335 |
product_id = strtoul(buf, NULL, 16); |
| 336 |
} else if (line[0] == 'S' && line[1] == ':') { |
| 337 |
if (get_tag_value(buf, sizeof(buf), line, "Product=", "") < 0) |
| 338 |
goto fail; |
| 339 |
pstrcpy(product_name, sizeof(product_name), buf); |
| 340 |
} else if (line[0] == 'D' && line[1] == ':') { |
| 341 |
if (get_tag_value(buf, sizeof(buf), line, "Cls=", " (") < 0) |
| 342 |
goto fail; |
| 343 |
class_id = strtoul(buf, NULL, 16); |
| 344 |
} |
| 345 |
fail: ; |
| 346 |
} |
| 347 |
if (device_count && (vendor_id || product_id)) { |
| 348 |
/* Add the last device. */ |
| 349 |
ret = func(opaque, bus_num, addr, class_id, vendor_id, |
| 350 |
product_id, product_name, speed); |
| 351 |
} |
358 |
} |
| 352 |
the_end: |
359 |
the_end: |
| 353 |
fclose(f); |
360 |
closedir(d); |
| 354 |
return ret; |
361 |
return ret; |
| 355 |
} |
362 |
} |
| 356 |
|
363 |
|