|
Lines 50-56
Link Here
|
| 50 |
|
50 |
|
| 51 |
//#define DEBUG |
51 |
//#define DEBUG |
| 52 |
|
52 |
|
| 53 |
#define USBDEVFS_PATH "/proc/bus/usb" |
53 |
#define USBDEVFS_PATH "/dev/bus/usb" |
| 54 |
#define PRODUCT_NAME_SZ 32 |
54 |
#define PRODUCT_NAME_SZ 32 |
| 55 |
|
55 |
|
| 56 |
typedef struct USBHostDevice { |
56 |
typedef struct USBHostDevice { |
|
Lines 257-358
Link Here
|
| 257 |
return (USBDevice *)dev; |
257 |
return (USBDevice *)dev; |
| 258 |
} |
258 |
} |
| 259 |
|
259 |
|
| 260 |
static int get_tag_value(char *buf, int buf_size, |
|
|
| 261 |
const char *str, const char *tag, |
| 262 |
const char *stopchars) |
| 263 |
{ |
| 264 |
const char *p; |
| 265 |
char *q; |
| 266 |
p = strstr(str, tag); |
| 267 |
if (!p) |
| 268 |
return -1; |
| 269 |
p += strlen(tag); |
| 270 |
while (isspace(*p)) |
| 271 |
p++; |
| 272 |
q = buf; |
| 273 |
while (*p != '\0' && !strchr(stopchars, *p)) { |
| 274 |
if ((q - buf) < (buf_size - 1)) |
| 275 |
*q++ = *p; |
| 276 |
p++; |
| 277 |
} |
| 278 |
*q = '\0'; |
| 279 |
return q - buf; |
| 280 |
} |
| 281 |
|
| 282 |
static int usb_host_scan(void *opaque, USBScanFunc *func) |
260 |
static int usb_host_scan(void *opaque, USBScanFunc *func) |
| 283 |
{ |
261 |
{ |
| 284 |
FILE *f; |
262 |
FILE *f; |
| 285 |
char line[1024]; |
263 |
char line[1024]; |
| 286 |
char buf[1024]; |
264 |
int bus_num, addr, speed, class_id, product_id, vendor_id; |
| 287 |
int bus_num, addr, speed, device_count, class_id, product_id, vendor_id; |
|
|
| 288 |
int ret; |
265 |
int ret; |
| 289 |
char product_name[512]; |
266 |
char product_name[512]; |
|
|
267 |
DIR* d; |
| 268 |
struct dirent* de; |
| 290 |
|
269 |
|
| 291 |
f = fopen(USBDEVFS_PATH "/devices", "r"); |
270 |
d = opendir("/sys/bus/usb/devices"); |
| 292 |
if (!f) { |
271 |
if (!d) { |
| 293 |
term_printf("Could not open %s\n", USBDEVFS_PATH "/devices"); |
272 |
term_printf("Could not open /sys/bus/usb/devices\n"); |
| 294 |
return 0; |
273 |
return 0; |
| 295 |
} |
274 |
} |
| 296 |
device_count = 0; |
275 |
while ((de = readdir(d))) { |
| 297 |
bus_num = addr = speed = class_id = product_id = vendor_id = 0; |
276 |
if (de->d_name[0] != '.' && ! strchr(de->d_name, ':')) { |
| 298 |
ret = 0; |
277 |
char filename[PATH_MAX]; |
| 299 |
for(;;) { |
278 |
char* tmpstr = de->d_name; |
| 300 |
if (fgets(line, sizeof(line), f) == NULL) |
279 |
if (!strncmp(de->d_name, "usb", 3)) |
| 301 |
break; |
280 |
tmpstr += 3; |
| 302 |
if (strlen(line) > 0) |
281 |
bus_num = atoi(tmpstr); |
| 303 |
line[strlen(line) - 1] = '\0'; |
282 |
snprintf(filename, PATH_MAX, "/sys/bus/usb/devices/%s/devnum", de->d_name); |
| 304 |
if (line[0] == 'T' && line[1] == ':') { |
283 |
f = fopen(filename, "r"); |
| 305 |
if (device_count && (vendor_id || product_id)) { |
284 |
if (!f) { |
| 306 |
/* New device. Add the previously discovered device. */ |
285 |
term_printf("Could not open %s\n", filename); |
| 307 |
ret = func(opaque, bus_num, addr, class_id, vendor_id, |
286 |
return 0; |
| 308 |
product_id, product_name, speed); |
287 |
} |
| 309 |
if (ret) |
288 |
fgets(line, sizeof(line), f); |
| 310 |
goto the_end; |
289 |
fclose(f); |
| 311 |
} |
290 |
addr = atoi(line); |
| 312 |
if (get_tag_value(buf, sizeof(buf), line, "Bus=", " ") < 0) |
291 |
snprintf(filename, PATH_MAX, "/sys/bus/usb/devices/%s/bDeviceClass", de->d_name); |
| 313 |
goto fail; |
292 |
f = fopen(filename, "r"); |
| 314 |
bus_num = atoi(buf); |
293 |
if (!f) { |
| 315 |
if (get_tag_value(buf, sizeof(buf), line, "Dev#=", " ") < 0) |
294 |
term_printf("Could not open %s\n", filename); |
| 316 |
goto fail; |
295 |
return 0; |
| 317 |
addr = atoi(buf); |
296 |
} |
| 318 |
if (get_tag_value(buf, sizeof(buf), line, "Spd=", " ") < 0) |
297 |
fgets(line, sizeof(line), f); |
| 319 |
goto fail; |
298 |
fclose(f); |
| 320 |
if (!strcmp(buf, "480")) |
299 |
class_id = strtoul(line, NULL, 16); |
|
|
300 |
snprintf(filename, PATH_MAX, "/sys/bus/usb/devices/%s/idVendor", de->d_name); |
| 301 |
f = fopen(filename, "r"); |
| 302 |
if (!f) { |
| 303 |
term_printf("Could not open %s\n", filename); |
| 304 |
return 0; |
| 305 |
} |
| 306 |
fgets(line, sizeof(line), f); |
| 307 |
fclose(f); |
| 308 |
vendor_id = strtoul(line, NULL, 16); |
| 309 |
snprintf(filename, PATH_MAX, "/sys/bus/usb/devices/%s/idProduct", de->d_name); |
| 310 |
f = fopen(filename, "r"); |
| 311 |
if (!f) { |
| 312 |
term_printf("Could not open %s\n", filename); |
| 313 |
return 0; |
| 314 |
} |
| 315 |
fgets(line, sizeof(line), f); |
| 316 |
fclose(f); |
| 317 |
product_id = strtoul(line, NULL, 16); |
| 318 |
snprintf(filename, PATH_MAX, "/sys/bus/usb/devices/%s/product", de->d_name); |
| 319 |
f = fopen(filename, "r"); |
| 320 |
if (f) { |
| 321 |
fgets(line, sizeof(line), f); |
| 322 |
fclose(f); |
| 323 |
if (strlen(line) > 0) |
| 324 |
line[strlen(line) - 1] = '\0'; |
| 325 |
pstrcpy(product_name, sizeof(product_name), line); |
| 326 |
} else |
| 327 |
*product_name = 0; |
| 328 |
snprintf(filename, PATH_MAX, "/sys/bus/usb/devices/%s/speed", 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 (!strcmp(line, "480\n")) |
| 321 |
speed = USB_SPEED_HIGH; |
337 |
speed = USB_SPEED_HIGH; |
| 322 |
else if (!strcmp(buf, "1.5")) |
338 |
else if (!strcmp(line, "1.5\n")) |
| 323 |
speed = USB_SPEED_LOW; |
339 |
speed = USB_SPEED_LOW; |
| 324 |
else |
340 |
else |
| 325 |
speed = USB_SPEED_FULL; |
341 |
speed = USB_SPEED_FULL; |
| 326 |
product_name[0] = '\0'; |
342 |
ret = func(opaque, bus_num, addr, class_id, vendor_id, |
| 327 |
class_id = 0xff; |
343 |
product_id, product_name, speed); |
| 328 |
device_count++; |
344 |
if (ret) |
| 329 |
product_id = 0; |
345 |
goto the_end; |
| 330 |
vendor_id = 0; |
346 |
} |
| 331 |
} else if (line[0] == 'P' && line[1] == ':') { |
|
|
| 332 |
if (get_tag_value(buf, sizeof(buf), line, "Vendor=", " ") < 0) |
| 333 |
goto fail; |
| 334 |
vendor_id = strtoul(buf, NULL, 16); |
| 335 |
if (get_tag_value(buf, sizeof(buf), line, "ProdID=", " ") < 0) |
| 336 |
goto fail; |
| 337 |
product_id = strtoul(buf, NULL, 16); |
| 338 |
} else if (line[0] == 'S' && line[1] == ':') { |
| 339 |
if (get_tag_value(buf, sizeof(buf), line, "Product=", "") < 0) |
| 340 |
goto fail; |
| 341 |
pstrcpy(product_name, sizeof(product_name), buf); |
| 342 |
} else if (line[0] == 'D' && line[1] == ':') { |
| 343 |
if (get_tag_value(buf, sizeof(buf), line, "Cls=", " (") < 0) |
| 344 |
goto fail; |
| 345 |
class_id = strtoul(buf, NULL, 16); |
| 346 |
} |
| 347 |
fail: ; |
| 348 |
} |
| 349 |
if (device_count && (vendor_id || product_id)) { |
| 350 |
/* Add the last device. */ |
| 351 |
ret = func(opaque, bus_num, addr, class_id, vendor_id, |
| 352 |
product_id, product_name, speed); |
| 353 |
} |
347 |
} |
| 354 |
the_end: |
348 |
the_end: |
| 355 |
fclose(f); |
349 |
closedir(d); |
| 356 |
return ret; |
350 |
return ret; |
| 357 |
} |
351 |
} |
| 358 |
|
352 |
|