summary refs log tree commit diff stats
path: root/hw/usb
diff options
context:
space:
mode:
Diffstat (limited to 'hw/usb')
-rw-r--r--hw/usb/dev-audio.c23
-rw-r--r--hw/usb/dev-bluetooth.c13
-rw-r--r--hw/usb/dev-hid.c34
-rw-r--r--hw/usb/dev-hub.c11
-rw-r--r--hw/usb/dev-mtp.c15
-rw-r--r--hw/usb/dev-network.c15
-rw-r--r--hw/usb/dev-serial.c43
-rw-r--r--hw/usb/dev-smartcard-reader.c50
-rw-r--r--hw/usb/dev-storage.c32
-rw-r--r--hw/usb/dev-uas.c15
-rw-r--r--hw/usb/dev-wacom.c9
-rw-r--r--hw/usb/hcd-uhci.c45
-rw-r--r--hw/usb/hcd-xhci.c25
-rw-r--r--hw/usb/redirect.c25
14 files changed, 219 insertions, 136 deletions
diff --git a/hw/usb/dev-audio.c b/hw/usb/dev-audio.c
index 67deffebcf..f092bb8496 100644
--- a/hw/usb/dev-audio.c
+++ b/hw/usb/dev-audio.c
@@ -361,6 +361,9 @@ typedef struct USBAudioState {
     uint32_t buffer;
 } USBAudioState;
 
+#define TYPE_USB_AUDIO "usb-audio"
+#define USB_AUDIO(obj) OBJECT_CHECK(USBAudioState, (obj), TYPE_USB_AUDIO)
+
 static void output_callback(void *opaque, int avail)
 {
     USBAudioState *s = opaque;
@@ -506,7 +509,7 @@ static void usb_audio_handle_control(USBDevice *dev, USBPacket *p,
                                     int request, int value, int index,
                                     int length, uint8_t *data)
 {
-    USBAudioState *s = DO_UPCAST(USBAudioState, dev, dev);
+    USBAudioState *s = USB_AUDIO(dev);
     int ret = 0;
 
     if (s->debug) {
@@ -565,7 +568,7 @@ fail:
 static void usb_audio_set_interface(USBDevice *dev, int iface,
                                     int old, int value)
 {
-    USBAudioState *s = DO_UPCAST(USBAudioState, dev, dev);
+    USBAudioState *s = USB_AUDIO(dev);
 
     if (iface == 1) {
         usb_audio_set_output_altset(s, value);
@@ -574,7 +577,7 @@ static void usb_audio_set_interface(USBDevice *dev, int iface,
 
 static void usb_audio_handle_reset(USBDevice *dev)
 {
-    USBAudioState *s = DO_UPCAST(USBAudioState, dev, dev);
+    USBAudioState *s = USB_AUDIO(dev);
 
     if (s->debug) {
         fprintf(stderr, "usb-audio: reset\n");
@@ -615,7 +618,7 @@ static void usb_audio_handle_data(USBDevice *dev, USBPacket *p)
 
 static void usb_audio_handle_destroy(USBDevice *dev)
 {
-    USBAudioState *s = DO_UPCAST(USBAudioState, dev, dev);
+    USBAudioState *s = USB_AUDIO(dev);
 
     if (s->debug) {
         fprintf(stderr, "usb-audio: destroy\n");
@@ -630,12 +633,12 @@ static void usb_audio_handle_destroy(USBDevice *dev)
 
 static void usb_audio_realize(USBDevice *dev, Error **errp)
 {
-    USBAudioState *s = DO_UPCAST(USBAudioState, dev, dev);
+    USBAudioState *s = USB_AUDIO(dev);
 
     usb_desc_create_serial(dev);
     usb_desc_init(dev);
     s->dev.opaque = s;
-    AUD_register_card("usb-audio", &s->card);
+    AUD_register_card(TYPE_USB_AUDIO, &s->card);
 
     s->out.altset        = ALTSET_OFF;
     s->out.mute          = false;
@@ -647,14 +650,14 @@ static void usb_audio_realize(USBDevice *dev, Error **errp)
     s->out.as.endianness = 0;
     streambuf_init(&s->out.buf, s->buffer);
 
-    s->out.voice = AUD_open_out(&s->card, s->out.voice, "usb-audio",
+    s->out.voice = AUD_open_out(&s->card, s->out.voice, TYPE_USB_AUDIO,
                                 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);
 }
 
 static const VMStateDescription vmstate_usb_audio = {
-    .name = "usb-audio",
+    .name = TYPE_USB_AUDIO,
     .unmigratable = 1,
 };
 
@@ -684,7 +687,7 @@ static void usb_audio_class_init(ObjectClass *klass, void *data)
 }
 
 static const TypeInfo usb_audio_info = {
-    .name          = "usb-audio",
+    .name          = TYPE_USB_AUDIO,
     .parent        = TYPE_USB_DEVICE,
     .instance_size = sizeof(USBAudioState),
     .class_init    = usb_audio_class_init,
@@ -693,7 +696,7 @@ static const TypeInfo usb_audio_info = {
 static void usb_audio_register_types(void)
 {
     type_register_static(&usb_audio_info);
-    usb_legacy_register("usb-audio", "audio", NULL);
+    usb_legacy_register(TYPE_USB_AUDIO, "audio", NULL);
 }
 
 type_init(usb_audio_register_types)
diff --git a/hw/usb/dev-bluetooth.c b/hw/usb/dev-bluetooth.c
index 9bf673057a..b19ec76b00 100644
--- a/hw/usb/dev-bluetooth.c
+++ b/hw/usb/dev-bluetooth.c
@@ -49,6 +49,9 @@ struct USBBtState {
     } outcmd, outacl, outsco;
 };
 
+#define TYPE_USB_BT "usb-bt-dongle"
+#define USB_BT(obj) OBJECT_CHECK(struct USBBtState, (obj), TYPE_USB_BT)
+
 #define USB_EVT_EP	1
 #define USB_ACL_EP	2
 #define USB_SCO_EP	3
@@ -503,7 +506,7 @@ static void usb_bt_handle_destroy(USBDevice *dev)
 
 static void usb_bt_realize(USBDevice *dev, Error **errp)
 {
-    struct USBBtState *s = DO_UPCAST(struct USBBtState, dev, dev);
+    struct USBBtState *s = USB_BT(dev);
 
     usb_desc_create_serial(dev);
     usb_desc_init(dev);
@@ -523,7 +526,7 @@ static USBDevice *usb_bt_init(USBBus *bus, const char *cmdline)
     USBDevice *dev;
     struct USBBtState *s;
     HCIInfo *hci;
-    const char *name = "usb-bt-dongle";
+    const char *name = TYPE_USB_BT;
 
     if (*cmdline) {
         hci = hci_init(cmdline);
@@ -534,7 +537,7 @@ static USBDevice *usb_bt_init(USBBus *bus, const char *cmdline)
         return NULL;
 
     dev = usb_create(bus, name);
-    s = DO_UPCAST(struct USBBtState, dev, dev);
+    s = USB_BT(dev);
     s->hci = hci;
     return dev;
 }
@@ -561,7 +564,7 @@ static void usb_bt_class_initfn(ObjectClass *klass, void *data)
 }
 
 static const TypeInfo bt_info = {
-    .name          = "usb-bt-dongle",
+    .name          = TYPE_USB_BT,
     .parent        = TYPE_USB_DEVICE,
     .instance_size = sizeof(struct USBBtState),
     .class_init    = usb_bt_class_initfn,
@@ -570,7 +573,7 @@ static const TypeInfo bt_info = {
 static void usb_bt_register_types(void)
 {
     type_register_static(&bt_info);
-    usb_legacy_register("usb-bt-dongle", "bt", usb_bt_init);
+    usb_legacy_register(TYPE_USB_BT, "bt", usb_bt_init);
 }
 
 type_init(usb_bt_register_types)
diff --git a/hw/usb/dev-hid.c b/hw/usb/dev-hid.c
index 507c9663c5..2e7dcd96cb 100644
--- a/hw/usb/dev-hid.c
+++ b/hw/usb/dev-hid.c
@@ -51,6 +51,9 @@ typedef struct USBHIDState {
     uint32_t head;
 } USBHIDState;
 
+#define TYPE_USB_HID "usb-hid"
+#define USB_HID(obj) OBJECT_CHECK(USBHIDState, (obj), TYPE_USB_HID)
+
 enum {
     STR_MANUFACTURER = 1,
     STR_PRODUCT_MOUSE,
@@ -564,7 +567,7 @@ static void usb_hid_changed(HIDState *hs)
 
 static void usb_hid_handle_reset(USBDevice *dev)
 {
-    USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev);
+    USBHIDState *us = USB_HID(dev);
 
     hid_reset(&us->hid);
 }
@@ -572,7 +575,7 @@ static void usb_hid_handle_reset(USBDevice *dev)
 static void usb_hid_handle_control(USBDevice *dev, USBPacket *p,
                int request, int value, int index, int length, uint8_t *data)
 {
-    USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev);
+    USBHIDState *us = USB_HID(dev);
     HIDState *hs = &us->hid;
     int ret;
 
@@ -651,7 +654,7 @@ static void usb_hid_handle_control(USBDevice *dev, USBPacket *p,
 
 static void usb_hid_handle_data(USBDevice *dev, USBPacket *p)
 {
-    USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev);
+    USBHIDState *us = USB_HID(dev);
     HIDState *hs = &us->hid;
     uint8_t buf[p->iov.size];
     int len = 0;
@@ -687,7 +690,7 @@ static void usb_hid_handle_data(USBDevice *dev, USBPacket *p)
 
 static void usb_hid_handle_destroy(USBDevice *dev)
 {
-    USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev);
+    USBHIDState *us = USB_HID(dev);
 
     hid_free(&us->hid);
 }
@@ -696,7 +699,7 @@ static void usb_hid_initfn(USBDevice *dev, int kind,
                            const USBDesc *usb1, const USBDesc *usb2,
                            Error **errp)
 {
-    USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev);
+    USBHIDState *us = USB_HID(dev);
     switch (us->usb_version) {
     case 1:
         dev->usb_desc = usb1;
@@ -784,6 +787,14 @@ static void usb_hid_class_initfn(ObjectClass *klass, void *data)
     uc->handle_attach  = usb_desc_attach;
 }
 
+static const TypeInfo usb_hid_type_info = {
+    .name = TYPE_USB_HID,
+    .parent = TYPE_USB_DEVICE,
+    .instance_size = sizeof(USBHIDState),
+    .abstract = true,
+    .class_init = usb_hid_class_initfn,
+};
+
 static Property usb_tablet_properties[] = {
         DEFINE_PROP_UINT32("usb_version", USBHIDState, usb_version, 2),
         DEFINE_PROP_STRING("display", USBHIDState, display),
@@ -796,7 +807,6 @@ static void usb_tablet_class_initfn(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
     USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
 
-    usb_hid_class_initfn(klass, data);
     uc->realize        = usb_tablet_realize;
     uc->product_desc   = "QEMU USB Tablet";
     dc->vmsd = &vmstate_usb_ptr;
@@ -806,8 +816,7 @@ static void usb_tablet_class_initfn(ObjectClass *klass, void *data)
 
 static const TypeInfo usb_tablet_info = {
     .name          = "usb-tablet",
-    .parent        = TYPE_USB_DEVICE,
-    .instance_size = sizeof(USBHIDState),
+    .parent        = TYPE_USB_HID,
     .class_init    = usb_tablet_class_initfn,
 };
 
@@ -821,7 +830,6 @@ static void usb_mouse_class_initfn(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
     USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
 
-    usb_hid_class_initfn(klass, data);
     uc->realize        = usb_mouse_realize;
     uc->product_desc   = "QEMU USB Mouse";
     dc->vmsd = &vmstate_usb_ptr;
@@ -831,8 +839,7 @@ static void usb_mouse_class_initfn(ObjectClass *klass, void *data)
 
 static const TypeInfo usb_mouse_info = {
     .name          = "usb-mouse",
-    .parent        = TYPE_USB_DEVICE,
-    .instance_size = sizeof(USBHIDState),
+    .parent        = TYPE_USB_HID,
     .class_init    = usb_mouse_class_initfn,
 };
 
@@ -847,7 +854,6 @@ static void usb_keyboard_class_initfn(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
     USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
 
-    usb_hid_class_initfn(klass, data);
     uc->realize        = usb_keyboard_realize;
     uc->product_desc   = "QEMU USB Keyboard";
     dc->vmsd = &vmstate_usb_kbd;
@@ -857,13 +863,13 @@ static void usb_keyboard_class_initfn(ObjectClass *klass, void *data)
 
 static const TypeInfo usb_keyboard_info = {
     .name          = "usb-kbd",
-    .parent        = TYPE_USB_DEVICE,
-    .instance_size = sizeof(USBHIDState),
+    .parent        = TYPE_USB_HID,
     .class_init    = usb_keyboard_class_initfn,
 };
 
 static void usb_hid_register_types(void)
 {
+    type_register_static(&usb_hid_type_info);
     type_register_static(&usb_tablet_info);
     usb_legacy_register("usb-tablet", "tablet", NULL);
     type_register_static(&usb_mouse_info);
diff --git a/hw/usb/dev-hub.c b/hw/usb/dev-hub.c
index 0482f58719..c8c6855505 100644
--- a/hw/usb/dev-hub.c
+++ b/hw/usb/dev-hub.c
@@ -41,6 +41,9 @@ typedef struct USBHubState {
     USBHubPort ports[NUM_PORTS];
 } USBHubState;
 
+#define TYPE_USB_HUB "usb-hub"
+#define USB_HUB(obj) OBJECT_CHECK(USBHubState, (obj), TYPE_USB_HUB)
+
 #define ClearHubFeature		(0x2000 | USB_REQ_CLEAR_FEATURE)
 #define ClearPortFeature	(0x2300 | USB_REQ_CLEAR_FEATURE)
 #define GetHubDescriptor	(0xa000 | USB_REQ_GET_DESCRIPTOR)
@@ -227,7 +230,7 @@ static void usb_hub_complete(USBPort *port, USBPacket *packet)
 
 static USBDevice *usb_hub_find_device(USBDevice *dev, uint8_t addr)
 {
-    USBHubState *s = DO_UPCAST(USBHubState, dev, dev);
+    USBHubState *s = USB_HUB(dev);
     USBHubPort *port;
     USBDevice *downstream;
     int i;
@@ -247,7 +250,7 @@ static USBDevice *usb_hub_find_device(USBDevice *dev, uint8_t addr)
 
 static void usb_hub_handle_reset(USBDevice *dev)
 {
-    USBHubState *s = DO_UPCAST(USBHubState, dev, dev);
+    USBHubState *s = USB_HUB(dev);
     USBHubPort *port;
     int i;
 
@@ -513,7 +516,7 @@ static USBPortOps usb_hub_port_ops = {
 
 static void usb_hub_realize(USBDevice *dev, Error **errp)
 {
-    USBHubState *s = DO_UPCAST(USBHubState, dev, dev);
+    USBHubState *s = USB_HUB(dev);
     USBHubPort *port;
     int i;
 
@@ -577,7 +580,7 @@ static void usb_hub_class_initfn(ObjectClass *klass, void *data)
 }
 
 static const TypeInfo hub_info = {
-    .name          = "usb-hub",
+    .name          = TYPE_USB_HUB,
     .parent        = TYPE_USB_DEVICE,
     .instance_size = sizeof(USBHubState),
     .class_init    = usb_hub_class_initfn,
diff --git a/hw/usb/dev-mtp.c b/hw/usb/dev-mtp.c
index 108ece8190..809b1cb118 100644
--- a/hw/usb/dev-mtp.c
+++ b/hw/usb/dev-mtp.c
@@ -130,6 +130,9 @@ struct MTPState {
     QTAILQ_HEAD(, MTPObject) objects;
 };
 
+#define TYPE_USB_MTP "usb-mtp"
+#define USB_MTP(obj) OBJECT_CHECK(MTPState, (obj), TYPE_USB_MTP)
+
 #define QEMU_STORAGE_ID 0x00010001
 
 #define MTP_FLAG_WRITABLE 0
@@ -878,7 +881,7 @@ static void usb_mtp_command(MTPState *s, MTPControl *c)
 
 static void usb_mtp_handle_reset(USBDevice *dev)
 {
-    MTPState *s = DO_UPCAST(MTPState, dev, dev);
+    MTPState *s = USB_MTP(dev);
 
     trace_usb_mtp_reset(s->dev.addr);
 
@@ -914,7 +917,7 @@ static void usb_mtp_cancel_packet(USBDevice *dev, USBPacket *p)
 
 static void usb_mtp_handle_data(USBDevice *dev, USBPacket *p)
 {
-    MTPState *s = DO_UPCAST(MTPState, dev, dev);
+    MTPState *s = USB_MTP(dev);
     MTPControl cmd;
     mtp_container container;
     uint32_t params[5];
@@ -1062,12 +1065,16 @@ static void usb_mtp_handle_data(USBDevice *dev, USBPacket *p)
 
 static void usb_mtp_realize(USBDevice *dev, Error **errp)
 {
-    MTPState *s = DO_UPCAST(MTPState, dev, dev);
+    MTPState *s = USB_MTP(dev);
 
     usb_desc_create_serial(dev);
     usb_desc_init(dev);
     QTAILQ_INIT(&s->objects);
     if (s->desc == NULL) {
+        if (s->root == NULL) {
+            error_setg(errp, "usb-mtp: x-root property must be configured");
+            return;
+        }
         s->desc = strrchr(s->root, '/');
         if (s->desc && s->desc[0]) {
             s->desc = g_strdup(s->desc + 1);
@@ -1113,7 +1120,7 @@ static void usb_mtp_class_initfn(ObjectClass *klass, void *data)
 }
 
 static TypeInfo mtp_info = {
-    .name          = "usb-mtp",
+    .name          = TYPE_USB_MTP,
     .parent        = TYPE_USB_DEVICE,
     .instance_size = sizeof(MTPState),
     .class_init    = usb_mtp_class_initfn,
diff --git a/hw/usb/dev-network.c b/hw/usb/dev-network.c
index 18669917f5..743c231d6b 100644
--- a/hw/usb/dev-network.c
+++ b/hw/usb/dev-network.c
@@ -648,6 +648,9 @@ typedef struct USBNetState {
     QTAILQ_HEAD(rndis_resp_head, rndis_response) rndis_resp;
 } USBNetState;
 
+#define TYPE_USB_NET "usb-net"
+#define USB_NET(obj) OBJECT_CHECK(USBNetState, (obj), TYPE_USB_NET)
+
 static int is_rndis(USBNetState *s)
 {
     return s->dev.config->bConfigurationValue == DEV_RNDIS_CONFIG_VALUE;
@@ -1310,6 +1313,10 @@ static int usbnet_can_receive(NetClientState *nc)
 {
     USBNetState *s = qemu_get_nic_opaque(nc);
 
+    if (!s->dev.config) {
+        return 0;
+    }
+
     if (is_rndis(s) && s->rndis_state != RNDIS_DATA_INITIALIZED) {
         return 1;
     }
@@ -1343,7 +1350,7 @@ static NetClientInfo net_usbnet_info = {
 
 static void usb_net_realize(USBDevice *dev, Error **errrp)
 {
-    USBNetState *s = DO_UPCAST(USBNetState, dev, dev);
+    USBNetState *s = USB_NET(dev);
 
     usb_desc_create_serial(dev);
     usb_desc_init(dev);
@@ -1376,7 +1383,7 @@ static void usb_net_realize(USBDevice *dev, Error **errrp)
 static void usb_net_instance_init(Object *obj)
 {
     USBDevice *dev = USB_DEVICE(obj);
-    USBNetState *s = DO_UPCAST(USBNetState, dev, dev);
+    USBNetState *s = USB_NET(dev);
 
     device_add_bootindex_property(obj, &s->conf.bootindex,
                                   "bootindex", "/ethernet-phy@0",
@@ -1437,7 +1444,7 @@ static void usb_net_class_initfn(ObjectClass *klass, void *data)
 }
 
 static const TypeInfo net_info = {
-    .name          = "usb-net",
+    .name          = TYPE_USB_NET,
     .parent        = TYPE_USB_DEVICE,
     .instance_size = sizeof(USBNetState),
     .class_init    = usb_net_class_initfn,
@@ -1447,7 +1454,7 @@ static const TypeInfo net_info = {
 static void usb_net_register_types(void)
 {
     type_register_static(&net_info);
-    usb_legacy_register("usb-net", "net", usb_net_init);
+    usb_legacy_register(TYPE_USB_NET, "net", usb_net_init);
 }
 
 type_init(usb_net_register_types)
diff --git a/hw/usb/dev-serial.c b/hw/usb/dev-serial.c
index 67c2072ce7..6ca3da9727 100644
--- a/hw/usb/dev-serial.c
+++ b/hw/usb/dev-serial.c
@@ -103,6 +103,9 @@ typedef struct {
     CharDriverState *cs;
 } USBSerialState;
 
+#define TYPE_USB_SERIAL "usb-serial-dev"
+#define USB_SERIAL_DEV(obj) OBJECT_CHECK(USBSerialState, (obj), TYPE_USB_SERIAL)
+
 enum {
     STR_MANUFACTURER = 1,
     STR_PRODUCT_SERIAL,
@@ -473,7 +476,7 @@ static void usb_serial_event(void *opaque, int event)
 
 static void usb_serial_realize(USBDevice *dev, Error **errp)
 {
-    USBSerialState *s = DO_UPCAST(USBSerialState, dev, dev);
+    USBSerialState *s = USB_SERIAL_DEV(dev);
     Error *local_err = NULL;
 
     usb_desc_create_serial(dev);
@@ -576,26 +579,40 @@ static Property serial_properties[] = {
     DEFINE_PROP_END_OF_LIST(),
 };
 
-static void usb_serial_class_initfn(ObjectClass *klass, void *data)
+static void usb_serial_dev_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
     USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
 
-    uc->realize = usb_serial_realize;
-    uc->product_desc   = "QEMU USB Serial";
-    uc->usb_desc       = &desc_serial;
+    uc->realize        = usb_serial_realize;
     uc->handle_reset   = usb_serial_handle_reset;
     uc->handle_control = usb_serial_handle_control;
     uc->handle_data    = usb_serial_handle_data;
     dc->vmsd = &vmstate_usb_serial;
-    dc->props = serial_properties;
     set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
 }
 
+static const TypeInfo usb_serial_dev_type_info = {
+    .name = TYPE_USB_SERIAL,
+    .parent = TYPE_USB_DEVICE,
+    .instance_size = sizeof(USBSerialState),
+    .abstract = true,
+    .class_init = usb_serial_dev_class_init,
+};
+
+static void usb_serial_class_initfn(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
+
+    uc->product_desc   = "QEMU USB Serial";
+    uc->usb_desc       = &desc_serial;
+    dc->props = serial_properties;
+}
+
 static const TypeInfo serial_info = {
     .name          = "usb-serial",
-    .parent        = TYPE_USB_DEVICE,
-    .instance_size = sizeof(USBSerialState),
+    .parent        = TYPE_USB_SERIAL,
     .class_init    = usb_serial_class_initfn,
 };
 
@@ -609,26 +626,20 @@ static void usb_braille_class_initfn(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
     USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
 
-    uc->realize        = usb_serial_realize;
     uc->product_desc   = "QEMU USB Braille";
     uc->usb_desc       = &desc_braille;
-    uc->handle_reset   = usb_serial_handle_reset;
-    uc->handle_control = usb_serial_handle_control;
-    uc->handle_data    = usb_serial_handle_data;
-    dc->vmsd = &vmstate_usb_serial;
     dc->props = braille_properties;
-    set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
 }
 
 static const TypeInfo braille_info = {
     .name          = "usb-braille",
-    .parent        = TYPE_USB_DEVICE,
-    .instance_size = sizeof(USBSerialState),
+    .parent        = TYPE_USB_SERIAL,
     .class_init    = usb_braille_class_initfn,
 };
 
 static void usb_serial_register_types(void)
 {
+    type_register_static(&usb_serial_dev_type_info);
     type_register_static(&serial_info);
     usb_legacy_register("usb-serial", "serial", usb_serial_init);
     type_register_static(&braille_info);
diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c
index 78ce681671..2d29367ae7 100644
--- a/hw/usb/dev-smartcard-reader.c
+++ b/hw/usb/dev-smartcard-reader.c
@@ -55,7 +55,7 @@ do { \
 #define D_VERBOSE 4
 
 #define CCID_DEV_NAME "usb-ccid"
-
+#define USB_CCID_DEV(obj) OBJECT_CHECK(USBCCIDState, (obj), CCID_DEV_NAME)
 /*
  * The two options for variable sized buffers:
  * make them constant size, for large enough constant,
@@ -649,7 +649,7 @@ static void ccid_detach(USBCCIDState *s)
 
 static void ccid_handle_reset(USBDevice *dev)
 {
-    USBCCIDState *s = DO_UPCAST(USBCCIDState, dev, dev);
+    USBCCIDState *s = USB_CCID_DEV(dev);
 
     DPRINTF(s, 1, "Reset\n");
 
@@ -692,7 +692,7 @@ static const char *ccid_control_to_str(USBCCIDState *s, int request)
 static void ccid_handle_control(USBDevice *dev, USBPacket *p, int request,
                                int value, int index, int length, uint8_t *data)
 {
-    USBCCIDState *s = DO_UPCAST(USBCCIDState, dev, dev);
+    USBCCIDState *s = USB_CCID_DEV(dev);
     int ret;
 
     DPRINTF(s, 1, "%s: got control %s (%x), value %x\n", __func__,
@@ -1104,7 +1104,7 @@ static void ccid_bulk_in_copy_to_guest(USBCCIDState *s, USBPacket *p)
 
 static void ccid_handle_data(USBDevice *dev, USBPacket *p)
 {
-    USBCCIDState *s = DO_UPCAST(USBCCIDState, dev, dev);
+    USBCCIDState *s = USB_CCID_DEV(dev);
     uint8_t buf[2];
 
     switch (p->pid) {
@@ -1148,7 +1148,7 @@ static void ccid_handle_data(USBDevice *dev, USBPacket *p)
 
 static void ccid_handle_destroy(USBDevice *dev)
 {
-    USBCCIDState *s = DO_UPCAST(USBCCIDState, dev, dev);
+    USBCCIDState *s = USB_CCID_DEV(dev);
 
     ccid_bulk_in_clear(s);
 }
@@ -1184,8 +1184,9 @@ static const TypeInfo ccid_bus_info = {
 void ccid_card_send_apdu_to_guest(CCIDCardState *card,
                                   uint8_t *apdu, uint32_t len)
 {
-    USBCCIDState *s = DO_UPCAST(USBCCIDState, dev.qdev,
-                                card->qdev.parent_bus->parent);
+    DeviceState *qdev = DEVICE(card);
+    USBDevice *dev = USB_DEVICE(qdev);
+    USBCCIDState *s = USB_CCID_DEV(dev);
     Answer *answer;
 
     if (!ccid_has_pending_answers(s)) {
@@ -1206,8 +1207,9 @@ void ccid_card_send_apdu_to_guest(CCIDCardState *card,
 
 void ccid_card_card_removed(CCIDCardState *card)
 {
-    USBCCIDState *s =
-        DO_UPCAST(USBCCIDState, dev.qdev, card->qdev.parent_bus->parent);
+    DeviceState *qdev = DEVICE(card);
+    USBDevice *dev = USB_DEVICE(qdev);
+    USBCCIDState *s = USB_CCID_DEV(dev);
 
     ccid_on_slot_change(s, false);
     ccid_flush_pending_answers(s);
@@ -1216,8 +1218,9 @@ void ccid_card_card_removed(CCIDCardState *card)
 
 int ccid_card_ccid_attach(CCIDCardState *card)
 {
-    USBCCIDState *s =
-        DO_UPCAST(USBCCIDState, dev.qdev, card->qdev.parent_bus->parent);
+    DeviceState *qdev = DEVICE(card);
+    USBDevice *dev = USB_DEVICE(qdev);
+    USBCCIDState *s = USB_CCID_DEV(dev);
 
     DPRINTF(s, 1, "CCID Attach\n");
     if (s->migration_state == MIGRATION_MIGRATED) {
@@ -1228,8 +1231,9 @@ int ccid_card_ccid_attach(CCIDCardState *card)
 
 void ccid_card_ccid_detach(CCIDCardState *card)
 {
-    USBCCIDState *s =
-        DO_UPCAST(USBCCIDState, dev.qdev, card->qdev.parent_bus->parent);
+    DeviceState *qdev = DEVICE(card);
+    USBDevice *dev = USB_DEVICE(qdev);
+    USBCCIDState *s = USB_CCID_DEV(dev);
 
     DPRINTF(s, 1, "CCID Detach\n");
     if (ccid_card_inserted(s)) {
@@ -1240,8 +1244,9 @@ void ccid_card_ccid_detach(CCIDCardState *card)
 
 void ccid_card_card_error(CCIDCardState *card, uint64_t error)
 {
-    USBCCIDState *s =
-        DO_UPCAST(USBCCIDState, dev.qdev, card->qdev.parent_bus->parent);
+    DeviceState *qdev = DEVICE(card);
+    USBDevice *dev = USB_DEVICE(qdev);
+    USBCCIDState *s = USB_CCID_DEV(dev);
 
     s->bmCommandStatus = COMMAND_STATUS_FAILED;
     s->last_answer_error = error;
@@ -1258,8 +1263,9 @@ void ccid_card_card_error(CCIDCardState *card, uint64_t error)
 
 void ccid_card_card_inserted(CCIDCardState *card)
 {
-    USBCCIDState *s =
-        DO_UPCAST(USBCCIDState, dev.qdev, card->qdev.parent_bus->parent);
+    DeviceState *qdev = DEVICE(card);
+    USBDevice *dev = USB_DEVICE(qdev);
+    USBCCIDState *s = USB_CCID_DEV(dev);
 
     s->bmCommandStatus = COMMAND_STATUS_NO_ERROR;
     ccid_flush_pending_answers(s);
@@ -1270,8 +1276,8 @@ static int ccid_card_exit(DeviceState *qdev)
 {
     int ret = 0;
     CCIDCardState *card = CCID_CARD(qdev);
-    USBCCIDState *s =
-        DO_UPCAST(USBCCIDState, dev.qdev, card->qdev.parent_bus->parent);
+    USBDevice *dev = USB_DEVICE(qdev);
+    USBCCIDState *s = USB_CCID_DEV(dev);
 
     if (ccid_card_inserted(s)) {
         ccid_card_card_removed(card);
@@ -1284,8 +1290,8 @@ static int ccid_card_exit(DeviceState *qdev)
 static int ccid_card_init(DeviceState *qdev)
 {
     CCIDCardState *card = CCID_CARD(qdev);
-    USBCCIDState *s =
-        DO_UPCAST(USBCCIDState, dev.qdev, card->qdev.parent_bus->parent);
+    USBDevice *dev = USB_DEVICE(qdev);
+    USBCCIDState *s = USB_CCID_DEV(dev);
     int ret = 0;
 
     if (card->slot != 0) {
@@ -1306,7 +1312,7 @@ static int ccid_card_init(DeviceState *qdev)
 
 static void ccid_realize(USBDevice *dev, Error **errp)
 {
-    USBCCIDState *s = DO_UPCAST(USBCCIDState, dev, dev);
+    USBCCIDState *s = USB_CCID_DEV(dev);
 
     usb_desc_create_serial(dev);
     usb_desc_init(dev);
diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c
index ae8d40dc77..abe0e1d6a1 100644
--- a/hw/usb/dev-storage.c
+++ b/hw/usb/dev-storage.c
@@ -64,6 +64,9 @@ typedef struct {
     SCSIDevice *scsi_dev;
 } MSDState;
 
+#define TYPE_USB_STORAGE "usb-storage-dev"
+#define USB_STORAGE_DEV(obj) OBJECT_CHECK(MSDState, (obj), TYPE_USB_STORAGE)
+
 struct usb_msd_cbw {
     uint32_t sig;
     uint32_t tag;
@@ -385,7 +388,7 @@ static void usb_msd_handle_control(USBDevice *dev, USBPacket *p,
 
 static void usb_msd_cancel_io(USBDevice *dev, USBPacket *p)
 {
-    MSDState *s = DO_UPCAST(MSDState, dev, dev);
+    MSDState *s = USB_STORAGE_DEV(dev);
 
     assert(s->packet == p);
     s->packet = NULL;
@@ -599,7 +602,7 @@ static const struct SCSIBusInfo usb_msd_scsi_info_bot = {
 
 static void usb_msd_realize_storage(USBDevice *dev, Error **errp)
 {
-    MSDState *s = DO_UPCAST(MSDState, dev, dev);
+    MSDState *s = USB_STORAGE_DEV(dev);
     BlockBackend *blk = s->conf.blk;
     SCSIDevice *scsi_dev;
     Error *err = NULL;
@@ -658,7 +661,7 @@ static void usb_msd_realize_storage(USBDevice *dev, Error **errp)
 
 static void usb_msd_realize_bot(USBDevice *dev, Error **errp)
 {
-    MSDState *s = DO_UPCAST(MSDState, dev, dev);
+    MSDState *s = USB_STORAGE_DEV(dev);
 
     usb_desc_create_serial(dev);
     usb_desc_init(dev);
@@ -748,7 +751,7 @@ static Property msd_properties[] = {
     DEFINE_PROP_END_OF_LIST(),
 };
 
-static void usb_msd_class_initfn_common(ObjectClass *klass)
+static void usb_msd_class_initfn_common(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
     USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
@@ -772,14 +775,13 @@ static void usb_msd_class_initfn_storage(ObjectClass *klass, void *data)
 
     uc->realize = usb_msd_realize_storage;
     dc->props = msd_properties;
-    usb_msd_class_initfn_common(klass);
 }
 
 static void usb_msd_get_bootindex(Object *obj, Visitor *v, void *opaque,
                                   const char *name, Error **errp)
 {
     USBDevice *dev = USB_DEVICE(obj);
-    MSDState *s = DO_UPCAST(MSDState, dev, dev);
+    MSDState *s = USB_STORAGE_DEV(dev);
 
     visit_type_int32(v, &s->conf.bootindex, name, errp);
 }
@@ -788,7 +790,7 @@ static void usb_msd_set_bootindex(Object *obj, Visitor *v, void *opaque,
                                   const char *name, Error **errp)
 {
     USBDevice *dev = USB_DEVICE(obj);
-    MSDState *s = DO_UPCAST(MSDState, dev, dev);
+    MSDState *s = USB_STORAGE_DEV(dev);
     int32_t boot_index;
     Error *local_err = NULL;
 
@@ -815,6 +817,14 @@ out:
     }
 }
 
+static const TypeInfo usb_storage_dev_type_info = {
+    .name = TYPE_USB_STORAGE,
+    .parent = TYPE_USB_DEVICE,
+    .instance_size = sizeof(MSDState),
+    .abstract = true,
+    .class_init = usb_msd_class_initfn_common,
+};
+
 static void usb_msd_instance_init(Object *obj)
 {
     object_property_add(obj, "bootindex", "int32",
@@ -829,27 +839,25 @@ static void usb_msd_class_initfn_bot(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
 
     uc->realize = usb_msd_realize_bot;
-    usb_msd_class_initfn_common(klass);
     dc->hotpluggable = false;
 }
 
 static const TypeInfo msd_info = {
     .name          = "usb-storage",
-    .parent        = TYPE_USB_DEVICE,
-    .instance_size = sizeof(MSDState),
+    .parent        = TYPE_USB_STORAGE,
     .class_init    = usb_msd_class_initfn_storage,
     .instance_init = usb_msd_instance_init,
 };
 
 static const TypeInfo bot_info = {
     .name          = "usb-bot",
-    .parent        = TYPE_USB_DEVICE,
-    .instance_size = sizeof(MSDState),
+    .parent        = TYPE_USB_STORAGE,
     .class_init    = usb_msd_class_initfn_bot,
 };
 
 static void usb_msd_register_types(void)
 {
+    type_register_static(&usb_storage_dev_type_info);
     type_register_static(&msd_info);
     type_register_static(&bot_info);
     usb_legacy_register("usb-storage", "disk", usb_msd_init);
diff --git a/hw/usb/dev-uas.c b/hw/usb/dev-uas.c
index 04fc515dbe..38b26c586d 100644
--- a/hw/usb/dev-uas.c
+++ b/hw/usb/dev-uas.c
@@ -127,6 +127,9 @@ struct UASDevice {
     USBPacket                 *status3[UAS_MAX_STREAMS + 1];
 };
 
+#define TYPE_USB_UAS "usb-uas"
+#define USB_UAS(obj) OBJECT_CHECK(UASDevice, (obj), TYPE_USB_UAS)
+
 struct UASRequest {
     uint16_t     tag;
     uint64_t     lun;
@@ -626,7 +629,7 @@ static const struct SCSIBusInfo usb_uas_scsi_info = {
 
 static void usb_uas_handle_reset(USBDevice *dev)
 {
-    UASDevice *uas = DO_UPCAST(UASDevice, dev, dev);
+    UASDevice *uas = USB_UAS(dev);
     UASRequest *req, *nreq;
     UASStatus *st, *nst;
 
@@ -655,7 +658,7 @@ static void usb_uas_handle_control(USBDevice *dev, USBPacket *p,
 
 static void usb_uas_cancel_io(USBDevice *dev, USBPacket *p)
 {
-    UASDevice *uas = DO_UPCAST(UASDevice, dev, dev);
+    UASDevice *uas = USB_UAS(dev);
     UASRequest *req, *nreq;
     int i;
 
@@ -797,7 +800,7 @@ incorrect_lun:
 
 static void usb_uas_handle_data(USBDevice *dev, USBPacket *p)
 {
-    UASDevice *uas = DO_UPCAST(UASDevice, dev, dev);
+    UASDevice *uas = USB_UAS(dev);
     uas_iu iu;
     UASStatus *st;
     UASRequest *req;
@@ -888,14 +891,14 @@ static void usb_uas_handle_data(USBDevice *dev, USBPacket *p)
 
 static void usb_uas_handle_destroy(USBDevice *dev)
 {
-    UASDevice *uas = DO_UPCAST(UASDevice, dev, dev);
+    UASDevice *uas = USB_UAS(dev);
 
     qemu_bh_delete(uas->status_bh);
 }
 
 static void usb_uas_realize(USBDevice *dev, Error **errp)
 {
-    UASDevice *uas = DO_UPCAST(UASDevice, dev, dev);
+    UASDevice *uas = USB_UAS(dev);
 
     usb_desc_create_serial(dev);
     usb_desc_init(dev);
@@ -943,7 +946,7 @@ static void usb_uas_class_initfn(ObjectClass *klass, void *data)
 }
 
 static const TypeInfo uas_info = {
-    .name          = "usb-uas",
+    .name          = TYPE_USB_UAS,
     .parent        = TYPE_USB_DEVICE,
     .instance_size = sizeof(UASDevice),
     .class_init    = usb_uas_class_initfn,
diff --git a/hw/usb/dev-wacom.c b/hw/usb/dev-wacom.c
index 844eafadf7..c2450e7297 100644
--- a/hw/usb/dev-wacom.c
+++ b/hw/usb/dev-wacom.c
@@ -56,6 +56,9 @@ typedef struct USBWacomState {
     int changed;
 } USBWacomState;
 
+#define TYPE_USB_WACOM "usb-wacom-tablet"
+#define USB_WACOM(obj) OBJECT_CHECK(USBWacomState, (obj), TYPE_USB_WACOM)
+
 enum {
     STR_MANUFACTURER = 1,
     STR_PRODUCT,
@@ -337,7 +340,7 @@ static void usb_wacom_handle_destroy(USBDevice *dev)
 
 static void usb_wacom_realize(USBDevice *dev, Error **errp)
 {
-    USBWacomState *s = DO_UPCAST(USBWacomState, dev, dev);
+    USBWacomState *s = USB_WACOM(dev);
     usb_desc_create_serial(dev);
     usb_desc_init(dev);
     s->intr = usb_ep_get(dev, USB_TOKEN_IN, 1);
@@ -367,7 +370,7 @@ static void usb_wacom_class_init(ObjectClass *klass, void *data)
 }
 
 static const TypeInfo wacom_info = {
-    .name          = "usb-wacom-tablet",
+    .name          = TYPE_USB_WACOM,
     .parent        = TYPE_USB_DEVICE,
     .instance_size = sizeof(USBWacomState),
     .class_init    = usb_wacom_class_init,
@@ -376,7 +379,7 @@ static const TypeInfo wacom_info = {
 static void usb_wacom_register_types(void)
 {
     type_register_static(&wacom_info);
-    usb_legacy_register("usb-wacom-tablet", "wacom-tablet", NULL);
+    usb_legacy_register(TYPE_USB_WACOM, "wacom-tablet", NULL);
 }
 
 type_init(usb_wacom_register_types)
diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c
index 327f26da70..3f0ed62689 100644
--- a/hw/usb/hcd-uhci.c
+++ b/hw/usb/hcd-uhci.c
@@ -154,6 +154,9 @@ static void uhci_async_cancel(UHCIAsync *async);
 static void uhci_queue_fill(UHCIQueue *q, UHCI_TD *td);
 static void uhci_resume(void *opaque);
 
+#define TYPE_UHCI "pci-uhci-usb"
+#define UHCI(obj) OBJECT_CHECK(UHCIState, (obj), TYPE_UHCI)
+
 static inline int32_t uhci_queue_token(UHCI_TD *td)
 {
     if ((td->token & (0xf << 15)) == 0) {
@@ -351,7 +354,7 @@ static void uhci_update_irq(UHCIState *s)
 static void uhci_reset(DeviceState *dev)
 {
     PCIDevice *d = PCI_DEVICE(dev);
-    UHCIState *s = DO_UPCAST(UHCIState, dev, d);
+    UHCIState *s = UHCI(d);
     uint8_t *pci_conf;
     int i;
     UHCIPort *port;
@@ -363,7 +366,7 @@ static void uhci_reset(DeviceState *dev)
     pci_conf[0x6a] = 0x01; /* usb clock */
     pci_conf[0x6b] = 0x00;
     s->cmd = 0;
-    s->status = 0;
+    s->status = UHCI_STS_HCHALTED;
     s->status2 = 0;
     s->intr = 0;
     s->fl_base_addr = 0;
@@ -1196,7 +1199,7 @@ static void usb_uhci_common_realize(PCIDevice *dev, Error **errp)
     Error *err = NULL;
     PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev);
     UHCIPCIDeviceClass *u = container_of(pc, UHCIPCIDeviceClass, parent_class);
-    UHCIState *s = DO_UPCAST(UHCIState, dev, dev);
+    UHCIState *s = UHCI(dev);
     uint8_t *pci_conf = s->dev.config;
     int i;
 
@@ -1241,7 +1244,7 @@ static void usb_uhci_common_realize(PCIDevice *dev, Error **errp)
 
 static void usb_uhci_vt82c686b_realize(PCIDevice *dev, Error **errp)
 {
-    UHCIState *s = DO_UPCAST(UHCIState, dev, dev);
+    UHCIState *s = UHCI(dev);
     uint8_t *pci_conf = s->dev.config;
 
     /* USB misc control 1/2 */
@@ -1256,7 +1259,7 @@ static void usb_uhci_vt82c686b_realize(PCIDevice *dev, Error **errp)
 
 static void usb_uhci_exit(PCIDevice *dev)
 {
-    UHCIState *s = DO_UPCAST(UHCIState, dev, dev);
+    UHCIState *s = UHCI(dev);
 
     trace_usb_uhci_exit();
 
@@ -1294,6 +1297,26 @@ static void uhci_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->class_id  = PCI_CLASS_SERIAL_USB;
+    dc->vmsd = &vmstate_uhci;
+    dc->reset = uhci_reset;
+    set_bit(DEVICE_CATEGORY_USB, dc->categories);
+}
+
+static const TypeInfo uhci_pci_type_info = {
+    .name = TYPE_UHCI,
+    .parent = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(UHCIState),
+    .class_size    = sizeof(UHCIPCIDeviceClass),
+    .abstract = true,
+    .class_init = uhci_class_init,
+};
+
+static void uhci_data_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+    DeviceClass *dc = DEVICE_CLASS(klass);
     UHCIPCIDeviceClass *u = container_of(k, UHCIPCIDeviceClass, parent_class);
     UHCIInfo *info = data;
 
@@ -1302,9 +1325,6 @@ static void uhci_class_init(ObjectClass *klass, void *data)
     k->vendor_id = info->vendor_id;
     k->device_id = info->device_id;
     k->revision  = info->revision;
-    k->class_id  = PCI_CLASS_SERIAL_USB;
-    dc->vmsd = &vmstate_uhci;
-    dc->reset = uhci_reset;
     if (!info->unplug) {
         /* uhci controllers in companion setups can't be hotplugged */
         dc->hotpluggable = false;
@@ -1312,7 +1332,6 @@ static void uhci_class_init(ObjectClass *klass, void *data)
     } else {
         dc->props = uhci_properties_standalone;
     }
-    set_bit(DEVICE_CATEGORY_USB, dc->categories);
     u->info = *info;
 }
 
@@ -1387,13 +1406,13 @@ static UHCIInfo uhci_info[] = {
 static void uhci_register_types(void)
 {
     TypeInfo uhci_type_info = {
-        .parent        = TYPE_PCI_DEVICE,
-        .instance_size = sizeof(UHCIState),
-        .class_size    = sizeof(UHCIPCIDeviceClass),
-        .class_init    = uhci_class_init,
+        .parent        = TYPE_UHCI,
+        .class_init    = uhci_data_class_init,
     };
     int i;
 
+    type_register_static(&uhci_pci_type_info);
+
     for (i = 0; i < ARRAY_SIZE(uhci_info); i++) {
         uhci_type_info.name = uhci_info[i].name;
         uhci_type_info.class_data = uhci_info + i;
diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index 99f11fcbb3..90a5fbff29 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -1767,18 +1767,9 @@ static void xhci_xfer_report(XHCITransfer *xfer)
             break;
         }
 
-        /*
-         * XHCI 1.1, 4.11.3.1 Transfer Event TRB -- "each Transfer TRB
-         * encountered with its IOC flag set to '1' shall generate a Transfer
-         * Event."
-         *
-         * Otherwise, longer transfers can have multiple data TRBs (for scatter
-         * gather). Short transfers and errors should be reported once per
-         * transfer only.
-         */
-        if ((trb->control & TRB_TR_IOC) ||
-            (!reported && ((shortpkt && (trb->control & TRB_TR_ISP)) ||
-                           (xfer->status != CC_SUCCESS && left == 0)))) {
+        if (!reported && ((trb->control & TRB_TR_IOC) ||
+                          (shortpkt && (trb->control & TRB_TR_ISP)) ||
+                          (xfer->status != CC_SUCCESS && left == 0))) {
             event.slotid = xfer->slotid;
             event.epid = xfer->epid;
             event.length = (trb->status & 0x1ffff) - chunk;
@@ -1802,6 +1793,14 @@ static void xhci_xfer_report(XHCITransfer *xfer)
                 return;
             }
         }
+
+        switch (TRB_TYPE(*trb)) {
+        case TR_SETUP:
+            reported = 0;
+            shortpkt = 0;
+            break;
+        }
+
     }
 }
 
@@ -2223,6 +2222,8 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid,
         if (xfer->running_retry) {
             DPRINTF("xhci: xfer nacked, stopping schedule\n");
             epctx->retry = xfer;
+            timer_mod(epctx->kick_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
+                      epctx->interval * 125000);
             break;
         }
     }
diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
index 2416de83e9..242a654583 100644
--- a/hw/usb/redirect.c
+++ b/hw/usb/redirect.c
@@ -130,6 +130,9 @@ struct USBRedirDevice {
     int compatible_speedmask;
 };
 
+#define TYPE_USB_REDIR "usb-redir"
+#define USB_REDIRECT(obj) OBJECT_CHECK(USBRedirDevice, (obj), TYPE_USB_REDIR)
+
 static void usbredir_hello(void *priv, struct usb_redir_hello_header *h);
 static void usbredir_device_connect(void *priv,
     struct usb_redir_device_connect_header *device_connect);
@@ -360,7 +363,7 @@ static void packet_id_queue_empty(struct PacketIdQueue *q)
 
 static void usbredir_cancel_packet(USBDevice *udev, USBPacket *p)
 {
-    USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
+    USBRedirDevice *dev = USB_REDIRECT(udev);
     int i = USBEP2I(p->ep);
 
     if (p->combined) {
@@ -500,7 +503,7 @@ static void usbredir_free_bufpq(USBRedirDevice *dev, uint8_t ep)
 
 static void usbredir_handle_reset(USBDevice *udev)
 {
-    USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
+    USBRedirDevice *dev = USB_REDIRECT(udev);
 
     DPRINTF("reset device\n");
     usbredirparser_send_reset(dev->parser);
@@ -907,7 +910,7 @@ static void usbredir_stop_interrupt_receiving(USBRedirDevice *dev,
 
 static void usbredir_handle_data(USBDevice *udev, USBPacket *p)
 {
-    USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
+    USBRedirDevice *dev = USB_REDIRECT(udev);
     uint8_t ep;
 
     ep = p->ep->nr;
@@ -976,7 +979,7 @@ static void usbredir_stop_ep(USBRedirDevice *dev, int i)
 
 static void usbredir_ep_stopped(USBDevice *udev, USBEndpoint *uep)
 {
-    USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
+    USBRedirDevice *dev = USB_REDIRECT(udev);
 
     usbredir_stop_ep(dev, USBEP2I(uep));
     usbredirparser_do_write(dev->parser);
@@ -1046,7 +1049,7 @@ static void usbredir_get_interface(USBRedirDevice *dev, USBPacket *p,
 static void usbredir_handle_control(USBDevice *udev, USBPacket *p,
         int request, int value, int index, int length, uint8_t *data)
 {
-    USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
+    USBRedirDevice *dev = USB_REDIRECT(udev);
     struct usb_redir_control_packet_header control_packet;
 
     if (usbredir_already_in_flight(dev, p->id)) {
@@ -1101,7 +1104,7 @@ static void usbredir_handle_control(USBDevice *udev, USBPacket *p,
 static int usbredir_alloc_streams(USBDevice *udev, USBEndpoint **eps,
                                   int nr_eps, int streams)
 {
-    USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
+    USBRedirDevice *dev = USB_REDIRECT(udev);
 #if USBREDIR_VERSION >= 0x000700
     struct usb_redir_alloc_bulk_streams_header alloc_streams;
     int i;
@@ -1140,7 +1143,7 @@ static void usbredir_free_streams(USBDevice *udev, USBEndpoint **eps,
                                   int nr_eps)
 {
 #if USBREDIR_VERSION >= 0x000700
-    USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
+    USBRedirDevice *dev = USB_REDIRECT(udev);
     struct usb_redir_free_bulk_streams_header free_streams;
     int i;
 
@@ -1362,7 +1365,7 @@ static void usbredir_init_endpoints(USBRedirDevice *dev)
 
 static void usbredir_realize(USBDevice *udev, Error **errp)
 {
-    USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
+    USBRedirDevice *dev = USB_REDIRECT(udev);
     int i;
 
     if (dev->cs == NULL) {
@@ -1415,7 +1418,7 @@ static void usbredir_cleanup_device_queues(USBRedirDevice *dev)
 
 static void usbredir_handle_destroy(USBDevice *udev)
 {
-    USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
+    USBRedirDevice *dev = USB_REDIRECT(udev);
 
     qemu_chr_delete(dev->cs);
     dev->cs = NULL;
@@ -2496,7 +2499,7 @@ static void usbredir_class_initfn(ObjectClass *klass, void *data)
 static void usbredir_instance_init(Object *obj)
 {
     USBDevice *udev = USB_DEVICE(obj);
-    USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
+    USBRedirDevice *dev = USB_REDIRECT(udev);
 
     device_add_bootindex_property(obj, &dev->bootindex,
                                   "bootindex", NULL,
@@ -2504,7 +2507,7 @@ static void usbredir_instance_init(Object *obj)
 }
 
 static const TypeInfo usbredir_dev_info = {
-    .name          = "usb-redir",
+    .name          = TYPE_USB_REDIR,
     .parent        = TYPE_USB_DEVICE,
     .instance_size = sizeof(USBRedirDevice),
     .class_init    = usbredir_class_initfn,