Revision a229c053
b/hw/usb/host-linux.c | ||
---|---|---|
111 | 111 |
uint32_t iso_urb_count; |
112 | 112 |
uint32_t options; |
113 | 113 |
Notifier exit; |
114 |
QEMUBH *bh; |
|
114 | 115 |
|
115 | 116 |
struct endp_data ep_in[USB_MAX_ENDPOINTS]; |
116 | 117 |
struct endp_data ep_out[USB_MAX_ENDPOINTS]; |
... | ... | |
1421 | 1422 |
} |
1422 | 1423 |
} |
1423 | 1424 |
|
1425 |
/* |
|
1426 |
* This is *NOT* about restoring state. We have absolutely no idea |
|
1427 |
* what state the host device is in at the moment and whenever it is |
|
1428 |
* still present in the first place. Attemping to contine where we |
|
1429 |
* left off is impossible. |
|
1430 |
* |
|
1431 |
* What we are going to to to here is emulate a surprise removal of |
|
1432 |
* the usb device passed through, then kick host scan so the device |
|
1433 |
* will get re-attached (and re-initialized by the guest) in case it |
|
1434 |
* is still present. |
|
1435 |
* |
|
1436 |
* As the device removal will change the state of other devices (usb |
|
1437 |
* host controller, most likely interrupt controller too) we have to |
|
1438 |
* wait with it until *all* vmstate is loaded. Thus post_load just |
|
1439 |
* kicks a bottom half which then does the actual work. |
|
1440 |
*/ |
|
1441 |
static void usb_host_post_load_bh(void *opaque) |
|
1442 |
{ |
|
1443 |
USBHostDevice *dev = opaque; |
|
1444 |
|
|
1445 |
if (dev->fd != -1) { |
|
1446 |
usb_host_close(dev); |
|
1447 |
} |
|
1448 |
if (dev->dev.attached) { |
|
1449 |
usb_device_detach(&dev->dev); |
|
1450 |
} |
|
1451 |
usb_host_auto_check(NULL); |
|
1452 |
} |
|
1453 |
|
|
1454 |
static int usb_host_post_load(void *opaque, int version_id) |
|
1455 |
{ |
|
1456 |
USBHostDevice *dev = opaque; |
|
1457 |
|
|
1458 |
qemu_bh_schedule(dev->bh); |
|
1459 |
return 0; |
|
1460 |
} |
|
1461 |
|
|
1424 | 1462 |
static int usb_host_initfn(USBDevice *dev) |
1425 | 1463 |
{ |
1426 | 1464 |
USBHostDevice *s = DO_UPCAST(USBHostDevice, dev, dev); |
... | ... | |
1432 | 1470 |
QTAILQ_INSERT_TAIL(&hostdevs, s, next); |
1433 | 1471 |
s->exit.notify = usb_host_exit_notifier; |
1434 | 1472 |
qemu_add_exit_notifier(&s->exit); |
1473 |
s->bh = qemu_bh_new(usb_host_post_load_bh, s); |
|
1435 | 1474 |
usb_host_auto_check(NULL); |
1436 | 1475 |
|
1437 | 1476 |
if (s->match.bus_num != 0 && s->match.port != NULL) { |
... | ... | |
1443 | 1482 |
|
1444 | 1483 |
static const VMStateDescription vmstate_usb_host = { |
1445 | 1484 |
.name = "usb-host", |
1446 |
.unmigratable = 1, |
|
1485 |
.version_id = 1, |
|
1486 |
.minimum_version_id = 1, |
|
1487 |
.post_load = usb_host_post_load, |
|
1488 |
.fields = (VMStateField[]) { |
|
1489 |
VMSTATE_USB_DEVICE(dev, USBHostDevice), |
|
1490 |
VMSTATE_END_OF_LIST() |
|
1491 |
} |
|
1447 | 1492 |
}; |
1448 | 1493 |
|
1449 | 1494 |
static Property usb_host_dev_properties[] = { |
Also available in: Unified diff