mirror of https://gitee.com/openkylin/qemu.git
Merge remote-tracking branch 'kraxel/usb.33' into staging
* kraxel/usb.33: usb-ohci: td.cbp incorrectly updated near page end usb-host: properly release port on unplug & exit usb-storage: cancel I/O on reset Fix parse of usb device description with multiple configurations
This commit is contained in:
commit
f3e8275f49
12
hw/usb-msd.c
12
hw/usb-msd.c
|
@ -278,6 +278,18 @@ static void usb_msd_handle_reset(USBDevice *dev)
|
|||
MSDState *s = (MSDState *)dev;
|
||||
|
||||
DPRINTF("Reset\n");
|
||||
if (s->req) {
|
||||
scsi_req_cancel(s->req);
|
||||
}
|
||||
assert(s->req == NULL);
|
||||
|
||||
if (s->packet) {
|
||||
USBPacket *p = s->packet;
|
||||
s->packet = NULL;
|
||||
p->result = USB_RET_STALL;
|
||||
usb_packet_complete(dev, p);
|
||||
}
|
||||
|
||||
s->mode = USB_MSDM_CBW;
|
||||
}
|
||||
|
||||
|
|
|
@ -1025,10 +1025,10 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed)
|
|||
if (ret == len) {
|
||||
td.cbp = 0;
|
||||
} else {
|
||||
td.cbp += ret;
|
||||
if ((td.cbp & 0xfff) + ret > 0xfff) {
|
||||
td.cbp &= 0xfff;
|
||||
td.cbp |= td.be & ~0xfff;
|
||||
td.cbp = (td.be & ~0xfff) + ((td.cbp + ret) & 0xfff);
|
||||
} else {
|
||||
td.cbp += ret;
|
||||
}
|
||||
}
|
||||
td.flags |= OHCI_TD_T1;
|
||||
|
|
47
usb-linux.c
47
usb-linux.c
|
@ -116,6 +116,7 @@ typedef struct USBHostDevice {
|
|||
USBDevice dev;
|
||||
int fd;
|
||||
int hub_fd;
|
||||
int hub_port;
|
||||
|
||||
uint8_t descr[8192];
|
||||
int descr_len;
|
||||
|
@ -434,7 +435,7 @@ static int usb_host_claim_port(USBHostDevice *s)
|
|||
{
|
||||
#ifdef USBDEVFS_CLAIM_PORT
|
||||
char *h, hub_name[64], line[1024];
|
||||
int hub_addr, portnr, ret;
|
||||
int hub_addr, ret;
|
||||
|
||||
snprintf(hub_name, sizeof(hub_name), "%d-%s",
|
||||
s->match.bus_num, s->match.port);
|
||||
|
@ -442,13 +443,13 @@ static int usb_host_claim_port(USBHostDevice *s)
|
|||
/* try strip off last ".$portnr" to get hub */
|
||||
h = strrchr(hub_name, '.');
|
||||
if (h != NULL) {
|
||||
portnr = atoi(h+1);
|
||||
s->hub_port = atoi(h+1);
|
||||
*h = '\0';
|
||||
} else {
|
||||
/* no dot in there -> it is the root hub */
|
||||
snprintf(hub_name, sizeof(hub_name), "usb%d",
|
||||
s->match.bus_num);
|
||||
portnr = atoi(s->match.port);
|
||||
s->hub_port = atoi(s->match.port);
|
||||
}
|
||||
|
||||
if (!usb_host_read_file(line, sizeof(line), "devnum",
|
||||
|
@ -469,20 +470,32 @@ static int usb_host_claim_port(USBHostDevice *s)
|
|||
return -1;
|
||||
}
|
||||
|
||||
ret = ioctl(s->hub_fd, USBDEVFS_CLAIM_PORT, &portnr);
|
||||
ret = ioctl(s->hub_fd, USBDEVFS_CLAIM_PORT, &s->hub_port);
|
||||
if (ret < 0) {
|
||||
close(s->hub_fd);
|
||||
s->hub_fd = -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
trace_usb_host_claim_port(s->match.bus_num, hub_addr, portnr);
|
||||
trace_usb_host_claim_port(s->match.bus_num, hub_addr, s->hub_port);
|
||||
return 0;
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void usb_host_release_port(USBHostDevice *s)
|
||||
{
|
||||
if (s->hub_fd == -1) {
|
||||
return;
|
||||
}
|
||||
#ifdef USBDEVFS_RELEASE_PORT
|
||||
ioctl(s->hub_fd, USBDEVFS_RELEASE_PORT, &s->hub_port);
|
||||
#endif
|
||||
close(s->hub_fd);
|
||||
s->hub_fd = -1;
|
||||
}
|
||||
|
||||
static int usb_host_disconnect_ifaces(USBHostDevice *dev, int nb_interfaces)
|
||||
{
|
||||
/* earlier Linux 2.4 do not support that */
|
||||
|
@ -635,10 +648,8 @@ static void usb_host_handle_destroy(USBDevice *dev)
|
|||
{
|
||||
USBHostDevice *s = (USBHostDevice *)dev;
|
||||
|
||||
usb_host_release_port(s);
|
||||
usb_host_close(s);
|
||||
if (s->hub_fd != -1) {
|
||||
close(s->hub_fd);
|
||||
}
|
||||
QTAILQ_REMOVE(&hostdevs, s, next);
|
||||
qemu_remove_exit_notifier(&s->exit);
|
||||
}
|
||||
|
@ -1141,15 +1152,18 @@ static int usb_linux_update_endp_table(USBHostDevice *s)
|
|||
length = s->descr_len - 18;
|
||||
i = 0;
|
||||
|
||||
if (descriptors[i + 1] != USB_DT_CONFIG ||
|
||||
descriptors[i + 5] != s->configuration) {
|
||||
fprintf(stderr, "invalid descriptor data - configuration %d\n",
|
||||
s->configuration);
|
||||
return 1;
|
||||
}
|
||||
i += descriptors[i];
|
||||
|
||||
while (i < length) {
|
||||
if (descriptors[i + 1] != USB_DT_CONFIG) {
|
||||
fprintf(stderr, "invalid descriptor data\n");
|
||||
return 1;
|
||||
} else if (descriptors[i + 5] != s->configuration) {
|
||||
DPRINTF("not requested configuration %d\n", s->configuration);
|
||||
i += (descriptors[i + 3] << 8) + descriptors[i + 2];
|
||||
continue;
|
||||
}
|
||||
|
||||
i += descriptors[i];
|
||||
|
||||
if (descriptors[i + 1] != USB_DT_INTERFACE ||
|
||||
(descriptors[i + 1] == USB_DT_INTERFACE &&
|
||||
descriptors[i + 4] == 0)) {
|
||||
|
@ -1399,6 +1413,7 @@ static void usb_host_exit_notifier(struct Notifier *n, void *data)
|
|||
{
|
||||
USBHostDevice *s = container_of(n, USBHostDevice, exit);
|
||||
|
||||
usb_host_release_port(s);
|
||||
if (s->fd != -1) {
|
||||
usb_host_do_reset(s);;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue