Revision 1f3870ab usb-linux.c
b/usb-linux.c | ||
---|---|---|
22 | 22 |
* THE SOFTWARE. |
23 | 23 |
*/ |
24 | 24 |
#include "qemu-common.h" |
25 |
#include "qemu-timer.h" |
|
25 | 26 |
#include "hw/usb.h" |
26 | 27 |
#include "console.h" |
27 | 28 |
|
... | ... | |
77 | 78 |
uint8_t descr[1024]; |
78 | 79 |
int descr_len; |
79 | 80 |
int urbs_ready; |
81 |
QEMUTimer *timer; |
|
80 | 82 |
} USBHostDevice; |
81 | 83 |
|
82 | 84 |
typedef struct PendingURB { |
... | ... | |
165 | 167 |
} |
166 | 168 |
config_descr_len = dev->descr[i]; |
167 | 169 |
|
168 |
if (configuration == dev->descr[i + 5]) |
|
170 |
#ifdef DEBUG |
|
171 |
printf("config #%d need %d\n", dev->descr[i + 5], configuration); |
|
172 |
#endif |
|
173 |
|
|
174 |
if (configuration < 0 || configuration == dev->descr[i + 5]) |
|
169 | 175 |
break; |
170 | 176 |
|
171 | 177 |
i += config_descr_len; |
... | ... | |
230 | 236 |
{ |
231 | 237 |
USBHostDevice *s = (USBHostDevice *)dev; |
232 | 238 |
|
239 |
qemu_del_timer(s->timer); |
|
240 |
|
|
233 | 241 |
if (s->fd >= 0) |
234 | 242 |
close(s->fd); |
243 |
|
|
235 | 244 |
qemu_free(s); |
236 | 245 |
} |
237 | 246 |
|
... | ... | |
594 | 603 |
return 0; |
595 | 604 |
} |
596 | 605 |
|
606 |
static void usb_host_device_check(void *priv) |
|
607 |
{ |
|
608 |
USBHostDevice *s = priv; |
|
609 |
struct usbdevfs_connectinfo ci; |
|
610 |
int err; |
|
611 |
|
|
612 |
err = ioctl(s->fd, USBDEVFS_CONNECTINFO, &ci); |
|
613 |
if (err < 0) { |
|
614 |
printf("usb device %d.%d disconnected\n", 0, s->dev.addr); |
|
615 |
usb_device_del_addr(0, s->dev.addr); |
|
616 |
return; |
|
617 |
} |
|
618 |
|
|
619 |
qemu_mod_timer(s->timer, qemu_get_clock(rt_clock) + 1000); |
|
620 |
} |
|
621 |
|
|
597 | 622 |
/* XXX: exclude high speed devices or implement EHCI */ |
598 | 623 |
USBDevice *usb_host_device_open(const char *devname) |
599 | 624 |
{ |
... | ... | |
604 | 629 |
int bus_num, addr; |
605 | 630 |
char product_name[PRODUCT_NAME_SZ]; |
606 | 631 |
|
632 |
if (usb_host_find_device(&bus_num, &addr, |
|
633 |
product_name, sizeof(product_name), |
|
634 |
devname) < 0) |
|
635 |
return NULL; |
|
636 |
|
|
637 |
|
|
607 | 638 |
dev = qemu_mallocz(sizeof(USBHostDevice)); |
608 | 639 |
if (!dev) |
609 | 640 |
goto fail; |
610 | 641 |
|
611 |
#ifdef DEBUG_ISOCH |
|
642 |
dev->timer = qemu_new_timer(rt_clock, usb_host_device_check, (void *) dev); |
|
643 |
if (!dev->timer) |
|
644 |
goto fail; |
|
645 |
|
|
646 |
#ifdef DEBUG |
|
612 | 647 |
printf("usb_host_device_open %s\n", devname); |
613 | 648 |
#endif |
614 |
if (usb_host_find_device(&bus_num, &addr, |
|
615 |
product_name, sizeof(product_name), |
|
616 |
devname) < 0) |
|
617 |
return NULL; |
|
618 | 649 |
|
619 | 650 |
snprintf(buf, sizeof(buf), USBDEVFS_PATH "/%03d/%03d", |
620 | 651 |
bus_num, addr); |
621 | 652 |
fd = open(buf, O_RDWR | O_NONBLOCK); |
622 | 653 |
if (fd < 0) { |
623 | 654 |
perror(buf); |
624 |
return NULL;
|
|
655 |
goto fail;
|
|
625 | 656 |
} |
626 | 657 |
|
627 | 658 |
/* read the device description */ |
... | ... | |
645 | 676 |
dev->configuration = 1; |
646 | 677 |
|
647 | 678 |
/* XXX - do something about initial configuration */ |
648 |
if (!usb_host_update_interfaces(dev, 1)) |
|
679 |
if (!usb_host_update_interfaces(dev, -1))
|
|
649 | 680 |
goto fail; |
650 | 681 |
|
651 | 682 |
ret = ioctl(fd, USBDEVFS_CONNECTINFO, &ci); |
... | ... | |
700 | 731 |
fcntl(dev->pipe_fds[1], F_SETFL, O_NONBLOCK); |
701 | 732 |
qemu_set_fd_handler(dev->pipe_fds[0], urb_completion_pipe_read, NULL, dev); |
702 | 733 |
#endif |
734 |
|
|
735 |
/* Start the timer to detect disconnect */ |
|
736 |
qemu_mod_timer(dev->timer, qemu_get_clock(rt_clock) + 1000); |
|
737 |
|
|
703 | 738 |
dev->urbs_ready = 0; |
704 | 739 |
return (USBDevice *)dev; |
705 | 740 |
fail: |
706 |
if (dev) |
|
741 |
if (dev) { |
|
742 |
if (dev->timer) |
|
743 |
qemu_del_timer(dev->timer); |
|
707 | 744 |
qemu_free(dev); |
745 |
} |
|
708 | 746 |
close(fd); |
709 | 747 |
return NULL; |
710 | 748 |
} |
Also available in: Unified diff