diff options
Diffstat (limited to 'hw/usb')
-rw-r--r-- | hw/usb/bus.c | 91 | ||||
-rw-r--r-- | hw/usb/dev-audio.c | 5 | ||||
-rw-r--r-- | hw/usb/dev-bluetooth.c | 6 | ||||
-rw-r--r-- | hw/usb/dev-hid.c | 27 | ||||
-rw-r--r-- | hw/usb/dev-hub.c | 9 | ||||
-rw-r--r-- | hw/usb/dev-mtp.c | 5 | ||||
-rw-r--r-- | hw/usb/dev-network.c | 9 | ||||
-rw-r--r-- | hw/usb/dev-serial.c | 24 | ||||
-rw-r--r-- | hw/usb/dev-smartcard-reader.c | 5 | ||||
-rw-r--r-- | hw/usb/dev-storage.c | 48 | ||||
-rw-r--r-- | hw/usb/dev-uas.c | 17 | ||||
-rw-r--r-- | hw/usb/dev-wacom.c | 5 | ||||
-rw-r--r-- | hw/usb/hcd-ehci-pci.c | 12 | ||||
-rw-r--r-- | hw/usb/hcd-ehci.c | 8 | ||||
-rw-r--r-- | hw/usb/hcd-ehci.h | 1 | ||||
-rw-r--r-- | hw/usb/hcd-ohci.c | 222 | ||||
-rw-r--r-- | hw/usb/hcd-uhci.c | 16 | ||||
-rw-r--r-- | hw/usb/hcd-xhci.c | 1 | ||||
-rw-r--r-- | hw/usb/host-libusb.c | 33 | ||||
-rw-r--r-- | hw/usb/redirect.c | 21 |
20 files changed, 291 insertions, 274 deletions
diff --git a/hw/usb/bus.c b/hw/usb/bus.c index c7c4dadedd..da1eba9fbd 100644 --- a/hw/usb/bus.c +++ b/hw/usb/bus.c @@ -9,7 +9,7 @@ static void usb_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent); static char *usb_get_dev_path(DeviceState *dev); static char *usb_get_fw_dev_path(DeviceState *qdev); -static int usb_qdev_exit(DeviceState *qdev); +static void usb_qdev_unrealize(DeviceState *qdev, Error **errp); static Property usb_props[] = { DEFINE_PROP_STRING("port", USBDevice, port_path), @@ -107,13 +107,13 @@ USBBus *usb_bus_find(int busnr) return NULL; } -static int usb_device_init(USBDevice *dev) +static void usb_device_realize(USBDevice *dev, Error **errp) { USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev); - if (klass->init) { - return klass->init(dev); + + if (klass->realize) { + klass->realize(dev, errp); } - return 0; } USBDevice *usb_device_find_device(USBDevice *dev, uint8_t addr) @@ -232,36 +232,41 @@ void usb_device_free_streams(USBDevice *dev, USBEndpoint **eps, int nr_eps) } } -static int usb_qdev_init(DeviceState *qdev) +static void usb_qdev_realize(DeviceState *qdev, Error **errp) { USBDevice *dev = USB_DEVICE(qdev); - int rc; + Error *local_err = NULL; pstrcpy(dev->product_desc, sizeof(dev->product_desc), usb_device_get_product_desc(dev)); dev->auto_attach = 1; QLIST_INIT(&dev->strings); usb_ep_init(dev); - rc = usb_claim_port(dev); - if (rc != 0) { - return rc; + + usb_claim_port(dev, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; } - rc = usb_device_init(dev); - if (rc != 0) { + + usb_device_realize(dev, &local_err); + if (local_err) { usb_release_port(dev); - return rc; + error_propagate(errp, local_err); + return; } + if (dev->auto_attach) { - rc = usb_device_attach(dev); - if (rc != 0) { - usb_qdev_exit(qdev); - return rc; + usb_device_attach(dev, &local_err); + if (local_err) { + usb_qdev_unrealize(qdev, NULL); + error_propagate(errp, local_err); + return; } } - return 0; } -static int usb_qdev_exit(DeviceState *qdev) +static void usb_qdev_unrealize(DeviceState *qdev, Error **errp) { USBDevice *dev = USB_DEVICE(qdev); @@ -272,7 +277,6 @@ static int usb_qdev_exit(DeviceState *qdev) if (dev->port) { usb_release_port(dev); } - return 0; } typedef struct LegacyUSBFactory @@ -392,7 +396,7 @@ void usb_unregister_port(USBBus *bus, USBPort *port) bus->nfree--; } -int usb_claim_port(USBDevice *dev) +void usb_claim_port(USBDevice *dev, Error **errp) { USBBus *bus = usb_bus_from_device(dev); USBPort *port; @@ -406,9 +410,9 @@ int usb_claim_port(USBDevice *dev) } } if (port == NULL) { - error_report("Error: usb port %s (bus %s) not found (in use?)", - dev->port_path, bus->qbus.name); - return -1; + error_setg(errp, "Error: usb port %s (bus %s) not found (in use?)", + dev->port_path, bus->qbus.name); + return; } } else { if (bus->nfree == 1 && strcmp(object_get_typename(OBJECT(dev)), "usb-hub") != 0) { @@ -416,9 +420,9 @@ int usb_claim_port(USBDevice *dev) usb_create_simple(bus, "usb-hub"); } if (bus->nfree == 0) { - error_report("Error: tried to attach usb device %s to a bus " - "with no free ports", dev->product_desc); - return -1; + error_setg(errp, "Error: tried to attach usb device %s to a bus " + "with no free ports", dev->product_desc); + return; } port = QTAILQ_FIRST(&bus->free); } @@ -432,7 +436,6 @@ int usb_claim_port(USBDevice *dev) QTAILQ_INSERT_TAIL(&bus->used, port, next); bus->nused++; - return 0; } void usb_release_port(USBDevice *dev) @@ -475,7 +478,7 @@ static void usb_mask_to_str(char *dest, size_t size, } } -int usb_device_attach(USBDevice *dev) +void usb_check_attach(USBDevice *dev, Error **errp) { USBBus *bus = usb_bus_from_device(dev); USBPort *port = dev->port; @@ -489,18 +492,28 @@ int usb_device_attach(USBDevice *dev) devspeed, portspeed); if (!(port->speedmask & dev->speedmask)) { - error_report("Warning: speed mismatch trying to attach" - " usb device \"%s\" (%s speed)" - " to bus \"%s\", port \"%s\" (%s speed)", - dev->product_desc, devspeed, - bus->qbus.name, port->path, portspeed); - return -1; + error_setg(errp, "Warning: speed mismatch trying to attach" + " usb device \"%s\" (%s speed)" + " to bus \"%s\", port \"%s\" (%s speed)", + dev->product_desc, devspeed, + bus->qbus.name, port->path, portspeed); + return; + } +} + +void usb_device_attach(USBDevice *dev, Error **errp) +{ + USBPort *port = dev->port; + Error *local_err = NULL; + + usb_check_attach(dev, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; } dev->attached++; usb_attach(port); - - return 0; } int usb_device_detach(USBDevice *dev) @@ -688,9 +701,9 @@ static void usb_device_class_init(ObjectClass *klass, void *data) { DeviceClass *k = DEVICE_CLASS(klass); k->bus_type = TYPE_USB_BUS; - k->init = usb_qdev_init; k->unplug = qdev_simple_unplug_cb; - k->exit = usb_qdev_exit; + k->realize = usb_qdev_realize; + k->unrealize = usb_qdev_unrealize; k->props = usb_props; } diff --git a/hw/usb/dev-audio.c b/hw/usb/dev-audio.c index 7b9957b3c3..67deffebcf 100644 --- a/hw/usb/dev-audio.c +++ b/hw/usb/dev-audio.c @@ -628,7 +628,7 @@ static void usb_audio_handle_destroy(USBDevice *dev) streambuf_fini(&s->out.buf); } -static int usb_audio_initfn(USBDevice *dev) +static void usb_audio_realize(USBDevice *dev, Error **errp) { USBAudioState *s = DO_UPCAST(USBAudioState, dev, dev); @@ -651,7 +651,6 @@ static int usb_audio_initfn(USBDevice *dev) s, output_callback, &s->out.as); AUD_set_volume_out(s->out.voice, s->out.mute, s->out.vol[0], s->out.vol[1]); AUD_set_active_out(s->out.voice, 0); - return 0; } static const VMStateDescription vmstate_usb_audio = { @@ -676,7 +675,7 @@ static void usb_audio_class_init(ObjectClass *klass, void *data) set_bit(DEVICE_CATEGORY_SOUND, dc->categories); k->product_desc = "QEMU USB Audio Interface"; k->usb_desc = &desc_audio; - k->init = usb_audio_initfn; + k->realize = usb_audio_realize; k->handle_reset = usb_audio_handle_reset; k->handle_control = usb_audio_handle_control; k->handle_data = usb_audio_handle_data; diff --git a/hw/usb/dev-bluetooth.c b/hw/usb/dev-bluetooth.c index a76e58191e..390d475c16 100644 --- a/hw/usb/dev-bluetooth.c +++ b/hw/usb/dev-bluetooth.c @@ -501,7 +501,7 @@ static void usb_bt_handle_destroy(USBDevice *dev) s->hci->acl_recv = NULL; } -static int usb_bt_initfn(USBDevice *dev) +static void usb_bt_realize(USBDevice *dev, Error **errp) { struct USBBtState *s = DO_UPCAST(struct USBBtState, dev, dev); @@ -516,8 +516,6 @@ static int usb_bt_initfn(USBDevice *dev) s->hci->acl_recv = usb_bt_out_hci_packet_acl; usb_bt_handle_reset(&s->dev); s->intr = usb_ep_get(dev, USB_TOKEN_IN, USB_EVT_EP); - - return 0; } static USBDevice *usb_bt_init(USBBus *bus, const char *cmdline) @@ -560,7 +558,7 @@ static void usb_bt_class_initfn(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); USBDeviceClass *uc = USB_DEVICE_CLASS(klass); - uc->init = usb_bt_initfn; + uc->realize = usb_bt_realize; uc->product_desc = "QEMU BT dongle"; uc->usb_desc = &desc_bluetooth; uc->handle_reset = usb_bt_handle_reset; diff --git a/hw/usb/dev-hid.c b/hw/usb/dev-hid.c index 67a57f1dcd..467ec86da6 100644 --- a/hw/usb/dev-hid.c +++ b/hw/usb/dev-hid.c @@ -566,7 +566,7 @@ static void usb_hid_handle_destroy(USBDevice *dev) hid_free(&us->hid); } -static int usb_hid_initfn(USBDevice *dev, int kind) +static void usb_hid_initfn(USBDevice *dev, int kind) { USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev); @@ -579,10 +579,9 @@ static int usb_hid_initfn(USBDevice *dev, int kind) if (us->display && us->hid.s) { qemu_input_handler_bind(us->hid.s, us->display, us->head, NULL); } - return 0; } -static int usb_tablet_initfn(USBDevice *dev) +static void usb_tablet_realize(USBDevice *dev, Error **errp) { USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev); @@ -594,22 +593,22 @@ static int usb_tablet_initfn(USBDevice *dev) dev->usb_desc = &desc_tablet2; break; default: - error_report("Invalid usb version %d for usb-tabler (must be 1 or 2)", - us->usb_version); - return -1; + error_setg(errp, "Invalid usb version %d for usb-tablet " + "(must be 1 or 2)", us->usb_version); + return; } - return usb_hid_initfn(dev, HID_TABLET); + usb_hid_initfn(dev, HID_TABLET); } -static int usb_mouse_initfn(USBDevice *dev) +static void usb_mouse_realize(USBDevice *dev, Error **errp) { - return usb_hid_initfn(dev, HID_MOUSE); + usb_hid_initfn(dev, HID_MOUSE); } -static int usb_keyboard_initfn(USBDevice *dev) +static void usb_keyboard_realize(USBDevice *dev, Error **errp) { - return usb_hid_initfn(dev, HID_KEYBOARD); + usb_hid_initfn(dev, HID_KEYBOARD); } static int usb_ptr_post_load(void *opaque, int version_id) @@ -669,7 +668,7 @@ static void usb_tablet_class_initfn(ObjectClass *klass, void *data) USBDeviceClass *uc = USB_DEVICE_CLASS(klass); usb_hid_class_initfn(klass, data); - uc->init = usb_tablet_initfn; + uc->realize = usb_tablet_realize; uc->product_desc = "QEMU USB Tablet"; dc->vmsd = &vmstate_usb_ptr; dc->props = usb_tablet_properties; @@ -689,7 +688,7 @@ static void usb_mouse_class_initfn(ObjectClass *klass, void *data) USBDeviceClass *uc = USB_DEVICE_CLASS(klass); usb_hid_class_initfn(klass, data); - uc->init = usb_mouse_initfn; + uc->realize = usb_mouse_realize; uc->product_desc = "QEMU USB Mouse"; uc->usb_desc = &desc_mouse; dc->vmsd = &vmstate_usb_ptr; @@ -714,7 +713,7 @@ static void usb_keyboard_class_initfn(ObjectClass *klass, void *data) USBDeviceClass *uc = USB_DEVICE_CLASS(klass); usb_hid_class_initfn(klass, data); - uc->init = usb_keyboard_initfn; + uc->realize = usb_keyboard_realize; uc->product_desc = "QEMU USB Keyboard"; uc->usb_desc = &desc_keyboard; dc->vmsd = &vmstate_usb_kbd; diff --git a/hw/usb/dev-hub.c b/hw/usb/dev-hub.c index 749217497a..0482f58719 100644 --- a/hw/usb/dev-hub.c +++ b/hw/usb/dev-hub.c @@ -511,15 +511,15 @@ static USBPortOps usb_hub_port_ops = { .complete = usb_hub_complete, }; -static int usb_hub_initfn(USBDevice *dev) +static void usb_hub_realize(USBDevice *dev, Error **errp) { USBHubState *s = DO_UPCAST(USBHubState, dev, dev); USBHubPort *port; int i; if (dev->port->hubcount == 5) { - error_report("usb hub chain too deep"); - return -1; + error_setg(errp, "usb hub chain too deep"); + return; } usb_desc_create_serial(dev); @@ -533,7 +533,6 @@ static int usb_hub_initfn(USBDevice *dev) usb_port_location(&port->port, dev->port, i+1); } usb_hub_handle_reset(dev); - return 0; } static const VMStateDescription vmstate_usb_hub_port = { @@ -564,7 +563,7 @@ static void usb_hub_class_initfn(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); USBDeviceClass *uc = USB_DEVICE_CLASS(klass); - uc->init = usb_hub_initfn; + uc->realize = usb_hub_realize; uc->product_desc = "QEMU USB Hub"; uc->usb_desc = &desc_hub; uc->find_device = usb_hub_find_device; diff --git a/hw/usb/dev-mtp.c b/hw/usb/dev-mtp.c index 0820046906..108ece8190 100644 --- a/hw/usb/dev-mtp.c +++ b/hw/usb/dev-mtp.c @@ -1060,7 +1060,7 @@ static void usb_mtp_handle_data(USBDevice *dev, USBPacket *p) } } -static int usb_mtp_initfn(USBDevice *dev) +static void usb_mtp_realize(USBDevice *dev, Error **errp) { MTPState *s = DO_UPCAST(MTPState, dev, dev); @@ -1075,7 +1075,6 @@ static int usb_mtp_initfn(USBDevice *dev) s->desc = g_strdup("none"); } } - return 0; } static const VMStateDescription vmstate_usb_mtp = { @@ -1100,7 +1099,7 @@ static void usb_mtp_class_initfn(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); USBDeviceClass *uc = USB_DEVICE_CLASS(klass); - uc->init = usb_mtp_initfn; + uc->realize = usb_mtp_realize; uc->product_desc = "QEMU USB MTP"; uc->usb_desc = &desc; uc->cancel_packet = usb_mtp_cancel_packet; diff --git a/hw/usb/dev-network.c b/hw/usb/dev-network.c index 518d5366d1..23e3c45b5f 100644 --- a/hw/usb/dev-network.c +++ b/hw/usb/dev-network.c @@ -27,7 +27,7 @@ #include "hw/usb.h" #include "hw/usb/desc.h" #include "net/net.h" -#include "qapi/qmp/qerror.h" +#include "qemu/error-report.h" #include "qemu/queue.h" #include "qemu/config-file.h" #include "sysemu/sysemu.h" @@ -1341,7 +1341,7 @@ static NetClientInfo net_usbnet_info = { .cleanup = usbnet_cleanup, }; -static int usb_net_initfn(USBDevice *dev) +static void usb_net_realize(USBDevice *dev, Error **errrp) { USBNetState *s = DO_UPCAST(USBNetState, dev, dev); @@ -1373,7 +1373,6 @@ static int usb_net_initfn(USBDevice *dev) usb_desc_set_string(dev, STRING_ETHADDR, s->usbstring_mac); add_boot_device_path(s->conf.bootindex, &dev->qdev, "/ethernet@0"); - return 0; } static USBDevice *usb_net_init(USBBus *bus, const char *cmdline) @@ -1392,7 +1391,7 @@ static USBDevice *usb_net_init(USBBus *bus, const char *cmdline) idx = net_client_init(opts, 0, &local_err); if (local_err) { - qerror_report_err(local_err); + error_report("%s", error_get_pretty(local_err)); error_free(local_err); return NULL; } @@ -1421,7 +1420,7 @@ static void usb_net_class_initfn(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); USBDeviceClass *uc = USB_DEVICE_CLASS(klass); - uc->init = usb_net_initfn; + uc->realize = usb_net_realize; uc->product_desc = "QEMU USB Network Interface"; uc->usb_desc = &desc_net; uc->handle_reset = usb_net_handle_reset; diff --git a/hw/usb/dev-serial.c b/hw/usb/dev-serial.c index d3606142c9..1cee450259 100644 --- a/hw/usb/dev-serial.c +++ b/hw/usb/dev-serial.c @@ -9,7 +9,7 @@ */ #include "qemu-common.h" -#include "qemu/error-report.h" +#include "monitor/monitor.h" #include "hw/usb.h" #include "hw/usb/desc.h" #include "sysemu/char.h" @@ -460,7 +460,7 @@ static void usb_serial_event(void *opaque, int event) break; case CHR_EVENT_OPENED: if (!s->dev.attached) { - usb_device_attach(&s->dev); + usb_device_attach(&s->dev, &error_abort); } break; case CHR_EVENT_CLOSED: @@ -471,17 +471,24 @@ static void usb_serial_event(void *opaque, int event) } } -static int usb_serial_initfn(USBDevice *dev) +static void usb_serial_realize(USBDevice *dev, Error **errp) { USBSerialState *s = DO_UPCAST(USBSerialState, dev, dev); + Error *local_err = NULL; usb_desc_create_serial(dev); usb_desc_init(dev); dev->auto_attach = 0; if (!s->cs) { - error_report("Property chardev is required"); - return -1; + error_setg(errp, "Property chardev is required"); + return; + } + + usb_check_attach(dev, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; } qemu_chr_add_handlers(s->cs, usb_serial_can_read, usb_serial_read, @@ -489,9 +496,8 @@ static int usb_serial_initfn(USBDevice *dev) usb_serial_handle_reset(dev); if (s->cs->be_open && !dev->attached) { - usb_device_attach(dev); + usb_device_attach(dev, &error_abort); } - return 0; } static USBDevice *usb_serial_init(USBBus *bus, const char *filename) @@ -582,7 +588,7 @@ static void usb_serial_class_initfn(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); USBDeviceClass *uc = USB_DEVICE_CLASS(klass); - uc->init = usb_serial_initfn; + uc->realize = usb_serial_realize; uc->product_desc = "QEMU USB Serial"; uc->usb_desc = &desc_serial; uc->handle_reset = usb_serial_handle_reset; @@ -610,7 +616,7 @@ static void usb_braille_class_initfn(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); USBDeviceClass *uc = USB_DEVICE_CLASS(klass); - uc->init = usb_serial_initfn; + uc->realize = usb_serial_realize; uc->product_desc = "QEMU USB Braille"; uc->usb_desc = &desc_braille; uc->handle_reset = usb_serial_handle_reset; diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c index 470e69ffc8..d37ed02d2e 100644 --- a/hw/usb/dev-smartcard-reader.c +++ b/hw/usb/dev-smartcard-reader.c @@ -1304,7 +1304,7 @@ static int ccid_card_init(DeviceState *qdev) return ret; } -static int ccid_initfn(USBDevice *dev) +static void ccid_realize(USBDevice *dev, Error **errp) { USBCCIDState *s = DO_UPCAST(USBCCIDState, dev, dev); @@ -1332,7 +1332,6 @@ static int ccid_initfn(USBDevice *dev) ccid_reset_parameters(s); ccid_reset(s); s->debug = parse_debug_env("QEMU_CCID_DEBUG", D_VERBOSE, s->debug); - return 0; } static int ccid_post_load(void *opaque, int version_id) @@ -1441,7 +1440,7 @@ static void ccid_class_initfn(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); USBDeviceClass *uc = USB_DEVICE_CLASS(klass); - uc->init = ccid_initfn; + uc->realize = ccid_realize; uc->product_desc = "QEMU USB CCID"; uc->usb_desc = &desc_ccid; uc->handle_reset = ccid_handle_reset; diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c index ae4efcbd2d..bd7cc53e07 100644 --- a/hw/usb/dev-storage.c +++ b/hw/usb/dev-storage.c @@ -409,19 +409,19 @@ static void usb_msd_handle_data(USBDevice *dev, USBPacket *p) switch (s->mode) { case USB_MSDM_CBW: if (p->iov.size != 31) { - fprintf(stderr, "usb-msd: Bad CBW size"); + error_report("usb-msd: Bad CBW size"); goto fail; } usb_packet_copy(p, &cbw, 31); if (le32_to_cpu(cbw.sig) != 0x43425355) { - fprintf(stderr, "usb-msd: Bad signature %08x\n", - le32_to_cpu(cbw.sig)); + error_report("usb-msd: Bad signature %08x", + le32_to_cpu(cbw.sig)); goto fail; } DPRINTF("Command on LUN %d\n", cbw.lun); scsi_dev = scsi_device_find(&s->bus, 0, 0, cbw.lun); if (scsi_dev == NULL) { - fprintf(stderr, "usb-msd: Bad LUN %d\n", cbw.lun); + error_report("usb-msd: Bad LUN %d", cbw.lun); goto fail; } tag = le32_to_cpu(cbw.tag); @@ -549,12 +549,17 @@ static void usb_msd_handle_data(USBDevice *dev, USBPacket *p) static void usb_msd_password_cb(void *opaque, int err) { MSDState *s = opaque; + Error *local_err = NULL; - if (!err) - err = usb_device_attach(&s->dev); + if (!err) { + usb_device_attach(&s->dev, &local_err); + } - if (err) + if (local_err) { + qerror_report_err(local_err); + error_free(local_err); qdev_unplug(&s->dev.qdev, NULL); + } } static void *usb_msd_load_request(QEMUFile *f, SCSIRequest *req) @@ -590,7 +595,7 @@ static const struct SCSIBusInfo usb_msd_scsi_info_bot = { .load_request = usb_msd_load_request, }; -static int usb_msd_initfn_storage(USBDevice *dev) +static void usb_msd_realize_storage(USBDevice *dev, Error **errp) { MSDState *s = DO_UPCAST(MSDState, dev, dev); BlockDriverState *bs = s->conf.bs; @@ -598,8 +603,8 @@ static int usb_msd_initfn_storage(USBDevice *dev) Error *err = NULL; if (!bs) { - error_report("drive property not set"); - return -1; + error_setg(errp, "drive property not set"); + return; } blkconf_serial(&s->conf, &dev->serial); @@ -624,7 +629,8 @@ static int usb_msd_initfn_storage(USBDevice *dev) s->conf.bootindex, dev->serial, &err); if (!scsi_dev) { - return -1; + error_propagate(errp, err); + return; } s->bus.qbus.allow_hotplug = 0; usb_msd_handle_reset(dev); @@ -637,11 +643,9 @@ static int usb_msd_initfn_storage(USBDevice *dev) autostart = 0; } } - - return 0; } -static int usb_msd_initfn_bot(USBDevice *dev) +static void usb_msd_realize_bot(USBDevice *dev, Error **errp) { MSDState *s = DO_UPCAST(MSDState, dev, dev); @@ -651,8 +655,6 @@ static int usb_msd_initfn_bot(USBDevice *dev) &usb_msd_scsi_info_bot, NULL); s->bus.qbus.allow_hotplug = 0; usb_msd_handle_reset(dev); - - return 0; } static USBDevice *usb_msd_init(USBBus *bus, const char *filename) @@ -666,8 +668,10 @@ static USBDevice *usb_msd_init(USBBus *bus, const char *filename) char fmt[32]; /* parse -usbdevice disk: syntax into drive opts */ - snprintf(id, sizeof(id), "usb%d", nr++); - opts = qemu_opts_create(qemu_find_opts("drive"), id, 0, NULL); + do { + snprintf(id, sizeof(id), "usb%d", nr++); + opts = qemu_opts_create(qemu_find_opts("drive"), id, 1, NULL); + } while (!opts); p1 = strchr(filename, ':'); if (p1++) { @@ -678,13 +682,13 @@ static USBDevice *usb_msd_init(USBBus *bus, const char *filename) pstrcpy(fmt, len, p2); qemu_opt_set(opts, "format", fmt); } else if (*filename != ':') { - printf("unrecognized USB mass-storage option %s\n", filename); + error_report("unrecognized USB mass-storage option %s", filename); return NULL; } filename = p1; } if (!*filename) { - printf("block device specification needed\n"); + error_report("block device specification needed"); return NULL; } qemu_opt_set(opts, "file", filename); @@ -758,7 +762,7 @@ static void usb_msd_class_initfn_storage(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); USBDeviceClass *uc = USB_DEVICE_CLASS(klass); - uc->init = usb_msd_initfn_storage; + uc->realize = usb_msd_realize_storage; dc->props = msd_properties; usb_msd_class_initfn_common(klass); } @@ -767,7 +771,7 @@ static void usb_msd_class_initfn_bot(ObjectClass *klass, void *data) { USBDeviceClass *uc = USB_DEVICE_CLASS(klass); - uc->init = usb_msd_initfn_bot; + uc->realize = usb_msd_realize_bot; usb_msd_class_initfn_common(klass); } diff --git a/hw/usb/dev-uas.c b/hw/usb/dev-uas.c index 9832385119..04fc515dbe 100644 --- a/hw/usb/dev-uas.c +++ b/hw/usb/dev-uas.c @@ -13,6 +13,7 @@ #include "qemu/option.h" #include "qemu/config-file.h" #include "trace.h" +#include "qemu/error-report.h" #include "hw/usb.h" #include "hw/usb/desc.h" @@ -648,7 +649,7 @@ static void usb_uas_handle_control(USBDevice *dev, USBPacket *p, if (ret >= 0) { return; } - fprintf(stderr, "%s: unhandled control request\n", __func__); + error_report("%s: unhandled control request", __func__); p->status = USB_RET_STALL; } @@ -814,8 +815,8 @@ static void usb_uas_handle_data(USBDevice *dev, USBPacket *p) usb_uas_task(uas, &iu); break; default: - fprintf(stderr, "%s: unknown command iu: id 0x%x\n", - __func__, iu.hdr.id); + error_report("%s: unknown command iu: id 0x%x", + __func__, iu.hdr.id); p->status = USB_RET_STALL; break; } @@ -861,7 +862,7 @@ static void usb_uas_handle_data(USBDevice *dev, USBPacket *p) p->status = USB_RET_ASYNC; break; } else { - fprintf(stderr, "%s: no inflight request\n", __func__); + error_report("%s: no inflight request", __func__); p->status = USB_RET_STALL; break; } @@ -879,7 +880,7 @@ static void usb_uas_handle_data(USBDevice *dev, USBPacket *p) usb_uas_start_next_transfer(uas); break; default: - fprintf(stderr, "%s: invalid endpoint %d\n", __func__, p->ep->nr); + error_report("%s: invalid endpoint %d", __func__, p->ep->nr); p->status = USB_RET_STALL; break; } @@ -892,7 +893,7 @@ static void usb_uas_handle_destroy(USBDevice *dev) qemu_bh_delete(uas->status_bh); } -static int usb_uas_init(USBDevice *dev) +static void usb_uas_realize(USBDevice *dev, Error **errp) { UASDevice *uas = DO_UPCAST(UASDevice, dev, dev); @@ -905,8 +906,6 @@ static int usb_uas_init(USBDevice *dev) scsi_bus_new(&uas->bus, sizeof(uas->bus), DEVICE(dev), &usb_uas_scsi_info, NULL); - - return 0; } static const VMStateDescription vmstate_usb_uas = { @@ -928,7 +927,7 @@ static void usb_uas_class_initfn(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); USBDeviceClass *uc = USB_DEVICE_CLASS(klass); - uc->init = usb_uas_init; + uc->realize = usb_uas_realize; uc->product_desc = desc_strings[STR_PRODUCT]; uc->usb_desc = &desc; uc->cancel_packet = usb_uas_cancel_io; diff --git a/hw/usb/dev-wacom.c b/hw/usb/dev-wacom.c index 1b73fd0aab..844eafadf7 100644 --- a/hw/usb/dev-wacom.c +++ b/hw/usb/dev-wacom.c @@ -335,14 +335,13 @@ static void usb_wacom_handle_destroy(USBDevice *dev) } } -static int usb_wacom_initfn(USBDevice *dev) +static void usb_wacom_realize(USBDevice *dev, Error **errp) { USBWacomState *s = DO_UPCAST(USBWacomState, dev, dev); usb_desc_create_serial(dev); usb_desc_init(dev); s->intr = usb_ep_get(dev, USB_TOKEN_IN, 1); s->changed = 1; - return 0; } static const VMStateDescription vmstate_usb_wacom = { @@ -357,7 +356,7 @@ static void usb_wacom_class_init(ObjectClass *klass, void *data) uc->product_desc = "QEMU PenPartner Tablet"; uc->usb_desc = &desc_wacom; - uc->init = usb_wacom_initfn; + uc->realize = usb_wacom_realize; uc->handle_reset = usb_wacom_handle_reset; uc->handle_control = usb_wacom_handle_control; uc->handle_data = usb_wacom_handle_data; diff --git a/hw/usb/hcd-ehci-pci.c b/hw/usb/hcd-ehci-pci.c index 289ca3b853..490f2b6af9 100644 --- a/hw/usb/hcd-ehci-pci.c +++ b/hw/usb/hcd-ehci-pci.c @@ -23,6 +23,7 @@ typedef struct EHCIPCIInfo { uint16_t vendor_id; uint16_t device_id; uint8_t revision; + bool companion; } EHCIPCIInfo; static int usb_ehci_pci_initfn(PCIDevice *dev) @@ -71,6 +72,7 @@ static int usb_ehci_pci_initfn(PCIDevice *dev) static void usb_ehci_pci_init(Object *obj) { + DeviceClass *dc = OBJECT_GET_CLASS(DeviceClass, obj, TYPE_DEVICE); EHCIPCIState *i = PCI_EHCI(obj); EHCIState *s = &i->ehci; @@ -81,6 +83,10 @@ static void usb_ehci_pci_init(Object *obj) s->portscbase = 0x44; s->portnr = NB_PORTS; + if (!dc->hotpluggable) { + s->companion_enable = true; + } + usb_ehci_init(s, DEVICE(obj)); } @@ -137,7 +143,6 @@ static void ehci_class_init(ObjectClass *klass, void *data) k->exit = usb_ehci_pci_exit; k->class_id = PCI_CLASS_SERIAL_USB; k->config_write = usb_ehci_pci_write_config; - dc->hotpluggable = false; dc->vmsd = &vmstate_ehci_pci; dc->props = ehci_pci_properties; } @@ -161,6 +166,9 @@ static void ehci_data_class_init(ObjectClass *klass, void *data) k->device_id = i->device_id; k->revision = i->revision; set_bit(DEVICE_CATEGORY_USB, dc->categories); + if (i->companion) { + dc->hotpluggable = false; + } } static struct EHCIPCIInfo ehci_pci_info[] = { @@ -174,11 +182,13 @@ static struct EHCIPCIInfo ehci_pci_info[] = { .vendor_id = PCI_VENDOR_ID_INTEL, .device_id = PCI_DEVICE_ID_INTEL_82801I_EHCI1, .revision = 0x03, + .companion = true, },{ .name = "ich9-usb-ehci2", /* 00:1a.7 */ .vendor_id = PCI_VENDOR_ID_INTEL, .device_id = PCI_DEVICE_ID_INTEL_82801I_EHCI2, .revision = 0x03, + .companion = true, } }; diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index bacb7ceac9..1cc0fc116d 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -2347,10 +2347,13 @@ static USBPortOps ehci_port_ops = { .complete = ehci_async_complete_packet, }; -static USBBusOps ehci_bus_ops = { +static USBBusOps ehci_bus_ops_companion = { .register_companion = ehci_register_companion, .wakeup_endpoint = ehci_wakeup_endpoint, }; +static USBBusOps ehci_bus_ops_standalone = { + .wakeup_endpoint = ehci_wakeup_endpoint, +}; static void usb_ehci_pre_save(void *opaque) { @@ -2456,7 +2459,8 @@ void usb_ehci_realize(EHCIState *s, DeviceState *dev, Error **errp) return; } - usb_bus_new(&s->bus, sizeof(s->bus), &ehci_bus_ops, dev); + usb_bus_new(&s->bus, sizeof(s->bus), s->companion_enable ? + &ehci_bus_ops_companion : &ehci_bus_ops_standalone, dev); for (i = 0; i < s->portnr; i++) { usb_register_port(&s->bus, &s->ports[i], s, i, &ehci_port_ops, USB_SPEED_MASK_HIGH); diff --git a/hw/usb/hcd-ehci.h b/hw/usb/hcd-ehci.h index 4858b7e80c..2bc259c9b4 100644 --- a/hw/usb/hcd-ehci.h +++ b/hw/usb/hcd-ehci.h @@ -262,6 +262,7 @@ struct EHCIState { MemoryRegion mem_opreg; MemoryRegion mem_ports; int companion_count; + bool companion_enable; uint16_t capsbase; uint16_t opregbase; uint16_t portscbase; diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c index 83bec34185..7ea871ddf2 100644 --- a/hw/usb/hcd-ohci.c +++ b/hw/usb/hcd-ohci.c @@ -31,20 +31,11 @@ #include "hw/pci/pci.h" #include "hw/sysbus.h" #include "hw/qdev-dma.h" +#include "trace.h" -//#define DEBUG_OHCI -/* Dump packet contents. */ -//#define DEBUG_PACKET -//#define DEBUG_ISOCH /* This causes frames to occur 1000x slower */ //#define OHCI_TIME_WARP 1 -#ifdef DEBUG_OHCI -#define DPRINTF printf -#else -#define DPRINTF(...) -#endif - /* Number of Downstream Ports on the root hub. */ #define OHCI_MAX_PORTS 15 @@ -350,7 +341,7 @@ static void ohci_attach(USBPort *port1) ohci_set_interrupt(s, OHCI_INTR_RD); } - DPRINTF("usb-ohci: Attached port %d\n", port1->index); + trace_usb_ohci_port_attach(port1->index); if (old_state != port->ctrl) { ohci_set_interrupt(s, OHCI_INTR_RHSC); @@ -375,7 +366,7 @@ static void ohci_detach(USBPort *port1) port->ctrl &= ~OHCI_PORT_PES; port->ctrl |= OHCI_PORT_PESC; } - DPRINTF("usb-ohci: Detached port %d\n", port1->index); + trace_usb_ohci_port_detach(port1->index); if (old_state != port->ctrl) { ohci_set_interrupt(s, OHCI_INTR_RHSC); @@ -388,14 +379,14 @@ static void ohci_wakeup(USBPort *port1) OHCIPort *port = &s->rhport[port1->index]; uint32_t intr = 0; if (port->ctrl & OHCI_PORT_PSS) { - DPRINTF("usb-ohci: port %d: wakeup\n", port1->index); + trace_usb_ohci_port_wakeup(port1->index); port->ctrl |= OHCI_PORT_PSSC; port->ctrl &= ~OHCI_PORT_PSS; intr = OHCI_INTR_RHSC; } /* Note that the controller can be suspended even if this port is not */ if ((s->ctl & OHCI_CTL_HCFS) == OHCI_USB_SUSPEND) { - DPRINTF("usb-ohci: remote-wakeup: SUSPEND->RESUME\n"); + trace_usb_ohci_remote_wakeup(s->name); /* This is the one state transition the controller can do by itself */ s->ctl &= ~OHCI_CTL_HCFS; s->ctl |= OHCI_USB_RESUME; @@ -497,7 +488,7 @@ static void ohci_reset(void *opaque) ohci->async_td = 0; } ohci_stop_endpoints(ohci); - DPRINTF("usb-ohci: Reset %s\n", ohci->name); + trace_usb_ohci_reset(ohci->name); } /* Get an array of dwords from main memory */ @@ -690,9 +681,8 @@ static void ohci_process_lists(OHCIState *ohci, int completion); static void ohci_async_complete_packet(USBPort *port, USBPacket *packet) { OHCIState *ohci = container_of(packet, OHCIState, usb_packet); -#ifdef DEBUG_PACKET - DPRINTF("Async packet complete\n"); -#endif + + trace_usb_ohci_async_complete(); ohci->async_complete = true; ohci_process_lists(ohci, 1); } @@ -704,9 +694,7 @@ static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed, { int dir; size_t len = 0; -#ifdef DEBUG_ISOCH const char *str = NULL; -#endif int pid; int ret; int i; @@ -723,7 +711,7 @@ static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed, addr = ed->head & OHCI_DPTR_MASK; if (ohci_read_iso_td(ohci, addr, &iso_td)) { - printf("usb-ohci: ISO_TD read error at %x\n", addr); + trace_usb_ohci_iso_td_read_failed(addr); ohci_die(ohci); return 0; } @@ -732,14 +720,7 @@ static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed, frame_count = OHCI_BM(iso_td.flags, TD_FC); relative_frame_number = USUB(ohci->frame_number, starting_frame); -#ifdef DEBUG_ISOCH - printf("--- ISO_TD ED head 0x%.8x tailp 0x%.8x\n" - "0x%.8x 0x%.8x 0x%.8x 0x%.8x\n" - "0x%.8x 0x%.8x 0x%.8x 0x%.8x\n" - "0x%.8x 0x%.8x 0x%.8x 0x%.8x\n" - "frame_number 0x%.8x starting_frame 0x%.8x\n" - "frame_count 0x%.8x relative %d\n" - "di 0x%.8x cc 0x%.8x\n", + trace_usb_ohci_iso_td_head( ed->head & OHCI_DPTR_MASK, ed->tail & OHCI_DPTR_MASK, iso_td.flags, iso_td.bp, iso_td.next, iso_td.be, iso_td.offset[0], iso_td.offset[1], iso_td.offset[2], iso_td.offset[3], @@ -747,16 +728,15 @@ static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed, ohci->frame_number, starting_frame, frame_count, relative_frame_number, OHCI_BM(iso_td.flags, TD_DI), OHCI_BM(iso_td.flags, TD_CC)); -#endif if (relative_frame_number < 0) { - DPRINTF("usb-ohci: ISO_TD R=%d < 0\n", relative_frame_number); + trace_usb_ohci_iso_td_relative_frame_number_neg(relative_frame_number); return 1; } else if (relative_frame_number > frame_count) { /* ISO TD expired - retire the TD to the Done Queue and continue with the next ISO TD of the same ED */ - DPRINTF("usb-ohci: ISO_TD R=%d > FC=%d\n", relative_frame_number, - frame_count); + trace_usb_ohci_iso_td_relative_frame_number_big(relative_frame_number, + frame_count); OHCI_SET_BM(iso_td.flags, TD_CC, OHCI_CC_DATAOVERRUN); ed->head &= ~OHCI_DPTR_MASK; ed->head |= (iso_td.next & OHCI_DPTR_MASK); @@ -775,30 +755,24 @@ static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed, dir = OHCI_BM(ed->flags, ED_D); switch (dir) { case OHCI_TD_DIR_IN: -#ifdef DEBUG_ISOCH str = "in"; -#endif pid = USB_TOKEN_IN; break; case OHCI_TD_DIR_OUT: -#ifdef DEBUG_ISOCH str = "out"; -#endif pid = USB_TOKEN_OUT; break; case OHCI_TD_DIR_SETUP: -#ifdef DEBUG_ISOCH str = "setup"; -#endif pid = USB_TOKEN_SETUP; break; default: - printf("usb-ohci: Bad direction %d\n", dir); + trace_usb_ohci_iso_td_bad_direction(dir); return 1; } if (!iso_td.bp || !iso_td.be) { - printf("usb-ohci: ISO_TD bp 0x%.8x be 0x%.8x\n", iso_td.bp, iso_td.be); + trace_usb_ohci_iso_td_bad_bp_be(iso_td.bp, iso_td.be); return 1; } @@ -808,14 +782,12 @@ static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed, if (!(OHCI_BM(start_offset, TD_PSW_CC) & 0xe) || ((relative_frame_number < frame_count) && !(OHCI_BM(next_offset, TD_PSW_CC) & 0xe))) { - printf("usb-ohci: ISO_TD cc != not accessed 0x%.8x 0x%.8x\n", - start_offset, next_offset); + trace_usb_ohci_iso_td_bad_cc_not_accessed(start_offset, next_offset); return 1; } if ((relative_frame_number < frame_count) && (start_offset > next_offset)) { - printf("usb-ohci: ISO_TD start_offset=0x%.8x > next_offset=0x%.8x\n", - start_offset, next_offset); + trace_usb_ohci_iso_td_bad_cc_overrun(start_offset, next_offset); return 1; } @@ -875,10 +847,8 @@ static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed, ret = ohci->usb_packet.status; } -#ifdef DEBUG_ISOCH - printf("so 0x%.8x eo 0x%.8x\nsa 0x%.8x ea 0x%.8x\ndir %s len %zu ret %d\n", - start_offset, end_offset, start_addr, end_addr, str, len, ret); -#endif + trace_usb_ohci_iso_td_so(start_offset, end_offset, start_addr, end_addr, + str, len, ret); /* Writeback */ if (dir == OHCI_TD_DIR_IN && ret >= 0 && ret <= len) { @@ -898,13 +868,13 @@ static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed, OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE, 0); } else { if (ret > (ssize_t) len) { - printf("usb-ohci: DataOverrun %d > %zu\n", ret, len); + trace_usb_ohci_iso_td_data_overrun(ret, len); OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC, OHCI_CC_DATAOVERRUN); OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE, len); } else if (ret >= 0) { - printf("usb-ohci: DataUnderrun %d\n", ret); + trace_usb_ohci_iso_td_data_underrun(ret); OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC, OHCI_CC_DATAUNDERRUN); } else { @@ -918,14 +888,14 @@ static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed, break; case USB_RET_NAK: case USB_RET_STALL: - printf("usb-ohci: got NAK/STALL %d\n", ret); + trace_usb_ohci_iso_td_nak(ret); OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC, OHCI_CC_STALL); OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE, 0); break; default: - printf("usb-ohci: Bad device response %d\n", ret); + trace_usb_ohci_iso_td_bad_response(ret); OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC, OHCI_CC_UNDEXPETEDPID); break; @@ -950,6 +920,43 @@ static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed, return 1; } +#ifdef trace_event_get_state +static void ohci_td_pkt(const char *msg, const uint8_t *buf, size_t len) +{ + bool print16 = !!trace_event_get_state(TRACE_USB_OHCI_TD_PKT_SHORT); + bool printall = !!trace_event_get_state(TRACE_USB_OHCI_TD_PKT_FULL); + const int width = 16; + int i; + char tmp[3 * width + 1]; + char *p = tmp; + + if (!printall && !print16) { + return; + } + + for (i = 0; ; i++) { + if (i && (!(i % width) || (i == len))) { + if (!printall) { + trace_usb_ohci_td_pkt_short(msg, tmp); + break; + } + trace_usb_ohci_td_pkt_full(msg, tmp); + p = tmp; + *p = 0; + } + if (i == len) { + break; + } + + p += sprintf(p, " %.2x", buf[i]); + } +} +#else +static void ohci_td_pkt(const char *msg, const uint8_t *buf, size_t len) +{ +} +#endif + /* Service a transport descriptor. Returns nonzero to terminate processing of this endpoint. */ @@ -957,9 +964,7 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed) { int dir; size_t len = 0, pktlen = 0; -#ifdef DEBUG_PACKET const char *str = NULL; -#endif int pid; int ret; int i; @@ -974,13 +979,11 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed) /* See if this TD has already been submitted to the device. */ completion = (addr == ohci->async_td); if (completion && !ohci->async_complete) { -#ifdef DEBUG_PACKET - DPRINTF("Skipping async TD\n"); -#endif + trace_usb_ohci_td_skip_async(); return 1; } if (ohci_read_td(ohci, addr, &td)) { - fprintf(stderr, "usb-ohci: TD read error at %x\n", addr); + trace_usb_ohci_td_read_error(addr); ohci_die(ohci); return 0; } @@ -998,25 +1001,19 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed) switch (dir) { case OHCI_TD_DIR_IN: -#ifdef DEBUG_PACKET str = "in"; -#endif pid = USB_TOKEN_IN; break; case OHCI_TD_DIR_OUT: -#ifdef DEBUG_PACKET str = "out"; -#endif pid = USB_TOKEN_OUT; break; case OHCI_TD_DIR_SETUP: -#ifdef DEBUG_PACKET str = "setup"; -#endif pid = USB_TOKEN_SETUP; break; default: - fprintf(stderr, "usb-ohci: Bad direction\n"); + trace_usb_ohci_td_bad_direction(dir); return 1; } if (td.cbp && td.be) { @@ -1043,19 +1040,10 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed) } flag_r = (td.flags & OHCI_TD_R) != 0; -#ifdef DEBUG_PACKET - DPRINTF(" TD @ 0x%.8x %" PRId64 " of %" PRId64 - " bytes %s r=%d cbp=0x%.8x be=0x%.8x\n", - addr, (int64_t)pktlen, (int64_t)len, str, flag_r, td.cbp, td.be); - - if (pktlen > 0 && dir != OHCI_TD_DIR_IN) { - DPRINTF(" data:"); - for (i = 0; i < pktlen; i++) { - printf(" %.2x", ohci->usb_buf[i]); - } - DPRINTF("\n"); - } -#endif + trace_usb_ohci_td_pkt_hdr(addr, (int64_t)pktlen, (int64_t)len, str, + flag_r, td.cbp, td.be); + ohci_td_pkt("OUT", ohci->usb_buf, pktlen); + if (completion) { ohci->async_td = 0; ohci->async_complete = false; @@ -1066,9 +1054,7 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed) This should be sufficient as long as devices respond in a timely manner. */ -#ifdef DEBUG_PACKET - DPRINTF("Too many pending packets\n"); -#endif + trace_usb_ohci_td_too_many_pending(); return 1; } dev = ohci_find_device(ohci, OHCI_BM(ed->flags, ED_FA)); @@ -1077,9 +1063,8 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed) OHCI_BM(td.flags, TD_DI) == 0); usb_packet_addbuf(&ohci->usb_packet, ohci->usb_buf, pktlen); usb_handle_packet(dev, &ohci->usb_packet); -#ifdef DEBUG_PACKET - DPRINTF("status=%d\n", ohci->usb_packet.status); -#endif + trace_usb_ohci_td_packet_status(ohci->usb_packet.status); + if (ohci->usb_packet.status == USB_RET_ASYNC) { usb_device_flush_ep_queue(dev, ep); ohci->async_td = addr; @@ -1098,12 +1083,7 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed) DMA_DIRECTION_FROM_DEVICE)) { ohci_die(ohci); } -#ifdef DEBUG_PACKET - DPRINTF(" data:"); - for (i = 0; i < ret; i++) - printf(" %.2x", ohci->usb_buf[i]); - DPRINTF("\n"); -#endif + ohci_td_pkt("IN", ohci->usb_buf, pktlen); } else { ret = pktlen; } @@ -1137,28 +1117,28 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed) ed->head |= OHCI_ED_C; } else { if (ret >= 0) { - DPRINTF("usb-ohci: Underrun\n"); + trace_usb_ohci_td_underrun(); OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_DATAUNDERRUN); } else { switch (ret) { case USB_RET_IOERROR: case USB_RET_NODEV: - DPRINTF("usb-ohci: got DEV ERROR\n"); + trace_usb_ohci_td_dev_error(); OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_DEVICENOTRESPONDING); break; case USB_RET_NAK: - DPRINTF("usb-ohci: got NAK\n"); + trace_usb_ohci_td_nak(); return 1; case USB_RET_STALL: - DPRINTF("usb-ohci: got STALL\n"); + trace_usb_ohci_td_stall(); OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_STALL); break; case USB_RET_BABBLE: - DPRINTF("usb-ohci: got BABBLE\n"); + trace_usb_ohci_td_babble(); OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_DATAOVERRUN); break; default: - fprintf(stderr, "usb-ohci: Bad device response %d\n", ret); + trace_usb_ohci_td_bad_device_response(ret); OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_UNDEXPETEDPID); OHCI_SET_BM(td.flags, TD_EC, 3); break; @@ -1198,7 +1178,7 @@ static int ohci_service_ed_list(OHCIState *ohci, uint32_t head, int completion) for (cur = head; cur; cur = next_ed) { if (ohci_read_ed(ohci, cur, &ed)) { - fprintf(stderr, "usb-ohci: ED read error at %x\n", cur); + trace_usb_ohci_ed_read_error(cur); ohci_die(ohci); return 0; } @@ -1219,16 +1199,14 @@ static int ohci_service_ed_list(OHCIState *ohci, uint32_t head, int completion) } while ((ed.head & OHCI_DPTR_MASK) != ed.tail) { -#ifdef DEBUG_PACKET - DPRINTF("ED @ 0x%.8x fa=%u en=%u d=%u s=%u k=%u f=%u mps=%u " - "h=%u c=%u\n head=0x%.8x tailp=0x%.8x next=0x%.8x\n", cur, + trace_usb_ohci_ed_pkt(cur, OHCI_BM(ed.flags, ED_FA), OHCI_BM(ed.flags, ED_EN), OHCI_BM(ed.flags, ED_D), (ed.flags & OHCI_ED_S)!= 0, (ed.flags & OHCI_ED_K) != 0, (ed.flags & OHCI_ED_F) != 0, OHCI_BM(ed.flags, ED_MPS), (ed.head & OHCI_ED_H) != 0, (ed.head & OHCI_ED_C) != 0, ed.head & OHCI_DPTR_MASK, ed.tail & OHCI_DPTR_MASK, ed.next & OHCI_DPTR_MASK); -#endif + active = 1; if ((ed.flags & OHCI_ED_F) == 0) { @@ -1263,8 +1241,7 @@ static void ohci_process_lists(OHCIState *ohci, int completion) { if ((ohci->ctl & OHCI_CTL_CLE) && (ohci->status & OHCI_STATUS_CLF)) { if (ohci->ctrl_cur && ohci->ctrl_cur != ohci->ctrl_head) { - DPRINTF("usb-ohci: head %x, cur %x\n", - ohci->ctrl_head, ohci->ctrl_cur); + trace_usb_ohci_process_lists(ohci->ctrl_head, ohci->ctrl_cur); } if (!ohci_service_ed_list(ohci, ohci->ctrl_head, completion)) { ohci->ctrl_cur = 0; @@ -1287,7 +1264,7 @@ static void ohci_frame_boundary(void *opaque) struct ohci_hcca hcca; if (ohci_read_hcca(ohci, ohci->hcca, &hcca)) { - fprintf(stderr, "usb-ohci: HCCA read error at %x\n", ohci->hcca); + trace_usb_ohci_hcca_read_error(ohci->hcca); ohci_die(ohci); return; } @@ -1356,12 +1333,12 @@ static int ohci_bus_start(OHCIState *ohci) ohci); if (ohci->eof_timer == NULL) { - fprintf(stderr, "usb-ohci: %s: timer_new_ns failed\n", ohci->name); + trace_usb_ohci_bus_eof_timer_failed(ohci->name); ohci_die(ohci); return 0; } - DPRINTF("usb-ohci: %s: USB Operational\n", ohci->name); + trace_usb_ohci_start(ohci->name); ohci_sof(ohci); @@ -1371,6 +1348,7 @@ static int ohci_bus_start(OHCIState *ohci) /* Stop sending SOF tokens on the bus */ static void ohci_bus_stop(OHCIState *ohci) { + trace_usb_ohci_stop(ohci->name); if (ohci->eof_timer) { timer_del(ohci->eof_timer); timer_free(ohci->eof_timer); @@ -1416,8 +1394,7 @@ static void ohci_set_frame_interval(OHCIState *ohci, uint16_t val) val &= OHCI_FMI_FI; if (val != ohci->fi) { - DPRINTF("usb-ohci: %s: FrameInterval = 0x%x (%u)\n", - ohci->name, ohci->fi, ohci->fi); + trace_usb_ohci_set_frame_interval(ohci->name, ohci->fi, ohci->fi); } ohci->fi = val; @@ -1449,20 +1426,19 @@ static void ohci_set_ctl(OHCIState *ohci, uint32_t val) if (old_state == new_state) return; + trace_usb_ohci_set_ctl(ohci->name, new_state); switch (new_state) { case OHCI_USB_OPERATIONAL: ohci_bus_start(ohci); break; case OHCI_USB_SUSPEND: ohci_bus_stop(ohci); - DPRINTF("usb-ohci: %s: USB Suspended\n", ohci->name); break; case OHCI_USB_RESUME: - DPRINTF("usb-ohci: %s: USB Resume\n", ohci->name); + trace_usb_ohci_resume(ohci->name); break; case OHCI_USB_RESET: ohci_reset(ohci); - DPRINTF("usb-ohci: %s: USB Reset\n", ohci->name); break; } } @@ -1507,7 +1483,7 @@ static void ohci_set_hub_status(OHCIState *ohci, uint32_t val) for (i = 0; i < ohci->num_ports; i++) ohci_port_power(ohci, i, 0); - DPRINTF("usb-ohci: powered down all ports\n"); + trace_usb_ohci_hub_power_down(); } if (val & OHCI_RHS_LPSC) { @@ -1515,7 +1491,7 @@ static void ohci_set_hub_status(OHCIState *ohci, uint32_t val) for (i = 0; i < ohci->num_ports; i++) ohci_port_power(ohci, i, 1); - DPRINTF("usb-ohci: powered up all ports\n"); + trace_usb_ohci_hub_power_up(); } if (val & OHCI_RHS_DRWE) @@ -1547,11 +1523,11 @@ static void ohci_port_set_status(OHCIState *ohci, int portnum, uint32_t val) ohci_port_set_if_connected(ohci, portnum, val & OHCI_PORT_PES); if (ohci_port_set_if_connected(ohci, portnum, val & OHCI_PORT_PSS)) { - DPRINTF("usb-ohci: port %d: SUSPEND\n", portnum); + trace_usb_ohci_port_suspend(portnum); } if (ohci_port_set_if_connected(ohci, portnum, val & OHCI_PORT_PRS)) { - DPRINTF("usb-ohci: port %d: RESET\n", portnum); + trace_usb_ohci_port_reset(portnum); usb_device_reset(port->port.dev); port->ctrl &= ~OHCI_PORT_PRS; /* ??? Should this also set OHCI_PORT_PESC. */ @@ -1579,7 +1555,7 @@ static uint64_t ohci_mem_read(void *opaque, /* Only aligned reads are allowed on OHCI */ if (addr & 3) { - fprintf(stderr, "usb-ohci: Mis-aligned read\n"); + trace_usb_ohci_mem_read_unaligned(addr); return 0xffffffff; } else if (addr >= 0x54 && addr < 0x54 + ohci->num_ports * 4) { /* HcRhPortStatus */ @@ -1685,7 +1661,7 @@ static uint64_t ohci_mem_read(void *opaque, break; default: - fprintf(stderr, "ohci_read: Bad offset %x\n", (int)addr); + trace_usb_ohci_mem_read_bad_offset(addr); retval = 0xffffffff; } } @@ -1702,7 +1678,7 @@ static void ohci_mem_write(void *opaque, /* Only aligned reads are allowed on OHCI */ if (addr & 3) { - fprintf(stderr, "usb-ohci: Mis-aligned write\n"); + trace_usb_ohci_mem_write_unaligned(addr); return; } @@ -1816,7 +1792,7 @@ static void ohci_mem_write(void *opaque, break; default: - fprintf(stderr, "ohci_write: Bad offset %x\n", (int)addr); + trace_usb_ohci_mem_write_bad_offset(addr); break; } } @@ -1869,8 +1845,7 @@ static int usb_ohci_init(OHCIState *ohci, DeviceState *dev, usb_bit_time = 1; } #endif - DPRINTF("usb-ohci: usb_bit_time=%" PRId64 " usb_frame_time=%" PRId64 "\n", - usb_frame_time, usb_bit_time); + trace_usb_ohci_init_time(usb_frame_time, usb_bit_time); } ohci->num_ports = num_ports; @@ -1928,7 +1903,7 @@ static void ohci_die(OHCIState *ohci) { OHCIPCIState *dev = container_of(ohci, OHCIPCIState, state); - fprintf(stderr, "%s: DMA error\n", __func__); + trace_usb_ohci_die(); ohci_set_interrupt(ohci, OHCI_INTR_UE); ohci_bus_stop(ohci); @@ -1959,6 +1934,7 @@ static void usb_ohci_exit(PCIDevice *dev) OHCIPCIState *ohci = PCI_OHCI(dev); OHCIState *s = &ohci->state; + trace_usb_ohci_exit(s->name); ohci_bus_stop(s); if (s->async_td) { diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c index 3b3ebcda8b..5b88f3070f 100644 --- a/hw/usb/hcd-uhci.c +++ b/hw/usb/hcd-uhci.c @@ -1279,13 +1279,18 @@ static void usb_uhci_exit(PCIDevice *dev) } } -static Property uhci_properties[] = { +static Property uhci_properties_companion[] = { DEFINE_PROP_STRING("masterbus", UHCIState, masterbus), DEFINE_PROP_UINT32("firstport", UHCIState, firstport, 0), DEFINE_PROP_UINT32("bandwidth", UHCIState, frame_bandwidth, 1280), DEFINE_PROP_UINT32("maxframes", UHCIState, maxframes, 128), DEFINE_PROP_END_OF_LIST(), }; +static Property uhci_properties_standalone[] = { + DEFINE_PROP_UINT32("bandwidth", UHCIState, frame_bandwidth, 1280), + DEFINE_PROP_UINT32("maxframes", UHCIState, maxframes, 128), + DEFINE_PROP_END_OF_LIST(), +}; static void uhci_class_init(ObjectClass *klass, void *data) { @@ -1300,9 +1305,14 @@ static void uhci_class_init(ObjectClass *klass, void *data) k->device_id = info->device_id; k->revision = info->revision; k->class_id = PCI_CLASS_SERIAL_USB; - dc->hotpluggable = false; dc->vmsd = &vmstate_uhci; - dc->props = uhci_properties; + if (!info->unplug) { + /* uhci controllers in companion setups can't be hotplugged */ + dc->hotpluggable = false; + dc->props = uhci_properties_companion; + } else { + dc->props = uhci_properties_standalone; + } set_bit(DEVICE_CATEGORY_USB, dc->categories); u->info = *info; } diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index 73ced1f5f8..c556367cb1 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -3874,7 +3874,6 @@ static void xhci_class_init(ObjectClass *klass, void *data) dc->vmsd = &vmstate_xhci; dc->props = xhci_properties; dc->reset = xhci_reset; - dc->hotpluggable = false; set_bit(DEVICE_CATEGORY_USB, dc->categories); k->init = usb_xhci_initfn; k->exit = usb_xhci_exit; diff --git a/hw/usb/host-libusb.c b/hw/usb/host-libusb.c index c189147f91..45b74e5307 100644 --- a/hw/usb/host-libusb.c +++ b/hw/usb/host-libusb.c @@ -275,7 +275,7 @@ static void usb_host_libusb_error(const char *func, int rc) } else { errname = "?"; } - fprintf(stderr, "%s: %d [%s]\n", func, rc, errname); + error_report("%s: %d [%s]", func, rc, errname); } /* ------------------------------------------------------------------------ */ @@ -834,6 +834,7 @@ static int usb_host_open(USBHostDevice *s, libusb_device *dev) int bus_num = libusb_get_bus_number(dev); int addr = libusb_get_device_address(dev); int rc; + Error *local_err = NULL; trace_usb_host_open_started(bus_num, addr); @@ -869,8 +870,10 @@ static int usb_host_open(USBHostDevice *s, libusb_device *dev) "host:%d.%d", bus_num, addr); } - rc = usb_device_attach(udev); - if (rc) { + usb_device_attach(udev, &local_err); + if (local_err) { + error_report("%s", error_get_pretty(local_err)); + error_free(local_err); goto fail; } @@ -948,21 +951,21 @@ static void usb_host_exit_notifier(struct Notifier *n, void *data) } } -static int usb_host_initfn(USBDevice *udev) +static void usb_host_realize(USBDevice *udev, Error **errp) { USBHostDevice *s = USB_HOST_DEVICE(udev); if (s->match.vendor_id > 0xffff) { - error_report("vendorid out of range"); - return -1; + error_setg(errp, "vendorid out of range"); + return; } if (s->match.product_id > 0xffff) { - error_report("productid out of range"); - return -1; + error_setg(errp, "productid out of range"); + return; } if (s->match.addr > 127) { - error_report("hostaddr out of range"); - return -1; + error_setg(errp, "hostaddr out of range"); + return; } loglevel = s->loglevel; @@ -977,7 +980,6 @@ static int usb_host_initfn(USBDevice *udev) QTAILQ_INSERT_TAIL(&hostdevs, s, next); add_boot_device_path(s->bootindex, &udev->qdev, NULL); usb_host_auto_check(NULL); - return 0; } static void usb_host_handle_destroy(USBDevice *udev) @@ -1374,14 +1376,13 @@ static int usb_host_alloc_streams(USBDevice *udev, USBEndpoint **eps, if (rc < 0) { usb_host_libusb_error("libusb_alloc_streams", rc); } else if (rc != streams) { - fprintf(stderr, - "libusb_alloc_streams: got less streams then requested %d < %d\n", - rc, streams); + error_report("libusb_alloc_streams: got less streams " + "then requested %d < %d", rc, streams); } return (rc == streams) ? 0 : -1; #else - fprintf(stderr, "libusb_alloc_streams: error not implemented\n"); + error_report("libusb_alloc_streams: error not implemented"); return -1; #endif } @@ -1477,7 +1478,7 @@ static void usb_host_class_initfn(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); USBDeviceClass *uc = USB_DEVICE_CLASS(klass); - uc->init = usb_host_initfn; + uc->realize = usb_host_realize; uc->product_desc = "USB Host Device"; uc->cancel_packet = usb_host_cancel_packet; uc->handle_data = usb_host_handle_data; diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c index 44522d9005..e2c98962a2 100644 --- a/hw/usb/redirect.c +++ b/hw/usb/redirect.c @@ -1256,6 +1256,7 @@ static void usbredir_device_reject_bh(void *opaque) static void usbredir_do_attach(void *opaque) { USBRedirDevice *dev = opaque; + Error *local_err = NULL; /* In order to work properly with XHCI controllers we need these caps */ if ((dev->dev.port->speedmask & USB_SPEED_MASK_SUPER) && !( @@ -1270,7 +1271,10 @@ static void usbredir_do_attach(void *opaque) return; } - if (usb_device_attach(&dev->dev) != 0) { + usb_device_attach(&dev->dev, &local_err); + if (local_err) { + error_report("%s", error_get_pretty(local_err)); + error_free(local_err); WARNING("rejecting device due to speed mismatch\n"); usbredir_reject_device(dev); } @@ -1357,14 +1361,14 @@ static void usbredir_init_endpoints(USBRedirDevice *dev) } } -static int usbredir_initfn(USBDevice *udev) +static void usbredir_realize(USBDevice *udev, Error **errp) { USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev); int i; if (dev->cs == NULL) { - qerror_report(QERR_MISSING_PARAMETER, "chardev"); - return -1; + error_set(errp, QERR_MISSING_PARAMETER, "chardev"); + return; } if (dev->filter_str) { @@ -1372,9 +1376,9 @@ static int usbredir_initfn(USBDevice *udev) &dev->filter_rules, &dev->filter_rules_count); if (i) { - qerror_report(QERR_INVALID_PARAMETER_VALUE, "filter", - "a usb device filter string"); - return -1; + error_set(errp, QERR_INVALID_PARAMETER_VALUE, "filter", + "a usb device filter string"); + return; } } @@ -1398,7 +1402,6 @@ static int usbredir_initfn(USBDevice *udev) qemu_add_vm_change_state_handler(usbredir_vm_state_change, dev); add_boot_device_path(dev->bootindex, &udev->qdev, NULL); - return 0; } static void usbredir_cleanup_device_queues(USBRedirDevice *dev) @@ -2477,7 +2480,7 @@ static void usbredir_class_initfn(ObjectClass *klass, void *data) USBDeviceClass *uc = USB_DEVICE_CLASS(klass); DeviceClass *dc = DEVICE_CLASS(klass); - uc->init = usbredir_initfn; + uc->realize = usbredir_realize; uc->product_desc = "USB Redirection Device"; uc->handle_destroy = usbredir_handle_destroy; uc->cancel_packet = usbredir_cancel_packet; |