-static int match_filter(const struct USBAutoFilter *f1,
- const struct USBAutoFilter *f2)
-{
- return f1->bus_num == f2->bus_num &&
- f1->addr == f2->addr &&
- f1->vendor_id == f2->vendor_id &&
- f1->product_id == f2->product_id;
-}
-
-static int usb_host_auto_add(const char *spec)
-{
- struct USBAutoFilter filter, *f;
-
- if (parse_filter(spec, &filter) < 0)
- return -1;
-
- f = qemu_mallocz(sizeof(*f));
- if (!f) {
- fprintf(stderr, "husb: failed to allocate auto filter\n");
- return -1;
- }
-
- *f = filter;
-
- if (!usb_auto_filter) {
- /*
- * First entry. Init and start the monitor.
- * Right now we're using timer to check for new devices.
- * If this turns out to be too expensive we can move that into a
- * separate thread.
- */
- usb_auto_timer = qemu_new_timer(rt_clock, usb_host_auto_timer, NULL);
- if (!usb_auto_timer) {
- fprintf(stderr, "husb: failed to allocate auto scan timer\n");
- qemu_free(f);
- return -1;
- }
-
- /* Check for new devices every two seconds */
- qemu_mod_timer(usb_auto_timer, qemu_get_clock(rt_clock) + 2000);
- }
-
- dprintf("husb: added auto filter: bus_num %d addr %d vid %d pid %d\n",
- f->bus_num, f->addr, f->vendor_id, f->product_id);
-
- f->next = usb_auto_filter;
- usb_auto_filter = f;
-
- return 0;
-}
-
-static int usb_host_auto_del(const char *spec)
-{
- struct USBAutoFilter *pf = usb_auto_filter;
- struct USBAutoFilter **prev = &usb_auto_filter;
- struct USBAutoFilter filter;
-
- if (parse_filter(spec, &filter) < 0)
- return -1;
-
- while (pf) {
- if (match_filter(pf, &filter)) {
- dprintf("husb: removed auto filter: bus_num %d addr %d vid %d pid %d\n",
- pf->bus_num, pf->addr, pf->vendor_id, pf->product_id);
-
- *prev = pf->next;
-
- if (!usb_auto_filter) {
- /* No more filters. Stop scanning. */
- qemu_del_timer(usb_auto_timer);
- qemu_free_timer(usb_auto_timer);
- }
-
- return 0;
- }
-
- prev = &pf->next;
- pf = pf->next;
- }
-
- return -1;
-}
-
-typedef struct FindDeviceState {
- int vendor_id;
- int product_id;
- int bus_num;
- int addr;
- char product_name[PRODUCT_NAME_SZ];
-} FindDeviceState;
-
-static int usb_host_find_device_scan(void *opaque, int bus_num, int addr,
- int class_id,
- int vendor_id, int product_id,
- const char *product_name, int speed)
-{
- FindDeviceState *s = opaque;
- if ((vendor_id == s->vendor_id &&
- product_id == s->product_id) ||
- (bus_num == s->bus_num &&
- addr == s->addr)) {
- pstrcpy(s->product_name, PRODUCT_NAME_SZ, product_name);
- s->bus_num = bus_num;
- s->addr = addr;
- return 1;
- } else {
- return 0;
- }
-}
-
-/* the syntax is :
- 'bus.addr' (decimal numbers) or
- 'vendor_id:product_id' (hexa numbers) */
-static int usb_host_find_device(int *pbus_num, int *paddr,
- char *product_name, int product_name_size,
- const char *devname)
-{
- const char *p;
- int ret;
- FindDeviceState fs;
-
- p = strchr(devname, '.');
- if (p) {
- *pbus_num = strtoul(devname, NULL, 0);
- *paddr = strtoul(p + 1, NULL, 0);
- fs.bus_num = *pbus_num;
- fs.addr = *paddr;
- ret = usb_host_scan(&fs, usb_host_find_device_scan);
- if (ret)
- pstrcpy(product_name, product_name_size, fs.product_name);
- return 0;
- }
-
- p = strchr(devname, ':');
- if (p) {
- fs.vendor_id = strtoul(devname, NULL, 16);
- fs.product_id = strtoul(p + 1, NULL, 16);
- ret = usb_host_scan(&fs, usb_host_find_device_scan);
- if (ret) {
- *pbus_num = fs.bus_num;
- *paddr = fs.addr;
- pstrcpy(product_name, product_name_size, fs.product_name);
- return 0;
- }
- }
- return -1;
-}
-