diff options
-rw-r--r-- | hw/usb-audio.c | 38 | ||||
-rw-r--r-- | hw/usb-bt.c | 33 | ||||
-rw-r--r-- | hw/usb-bus.c | 188 | ||||
-rw-r--r-- | hw/usb-ccid.c | 38 | ||||
-rw-r--r-- | hw/usb-desc.c | 22 | ||||
-rw-r--r-- | hw/usb-hid.c | 108 | ||||
-rw-r--r-- | hw/usb-hub.c | 35 | ||||
-rw-r--r-- | hw/usb-msd.c | 41 | ||||
-rw-r--r-- | hw/usb-net.c | 41 | ||||
-rw-r--r-- | hw/usb-serial.c | 74 | ||||
-rw-r--r-- | hw/usb-wacom.c | 36 | ||||
-rw-r--r-- | hw/usb-xhci.c | 4 | ||||
-rw-r--r-- | hw/usb.c | 24 | ||||
-rw-r--r-- | hw/usb.h | 50 | ||||
-rw-r--r-- | usb-bsd.c | 29 | ||||
-rw-r--r-- | usb-linux.c | 37 | ||||
-rw-r--r-- | usb-redir.c | 33 |
17 files changed, 528 insertions, 303 deletions
diff --git a/hw/usb-audio.c b/hw/usb-audio.c index b22d578910..561ae31d25 100644 --- a/hw/usb-audio.c +++ b/hw/usb-audio.c @@ -674,21 +674,27 @@ static const VMStateDescription vmstate_usb_audio = { .unmigratable = 1, }; -static struct USBDeviceInfo usb_audio_info = { - .product_desc = "QEMU USB Audio Interface", - .usbdevice_name = "audio", - .qdev.name = "usb-audio", - .qdev.size = sizeof(USBAudioState), - .qdev.vmsd = &vmstate_usb_audio, - .usb_desc = &desc_audio, - .init = usb_audio_initfn, - .handle_packet = usb_generic_handle_packet, - .handle_reset = usb_audio_handle_reset, - .handle_control = usb_audio_handle_control, - .handle_data = usb_audio_handle_data, - .handle_destroy = usb_audio_handle_destroy, - .set_interface = usb_audio_set_interface, - .qdev.props = (Property[]) { +static void usb_audio_class_init(ObjectClass *klass, void *data) +{ + USBDeviceClass *k = USB_DEVICE_CLASS(klass); + + k->product_desc = "QEMU USB Audio Interface"; + k->usb_desc = &desc_audio; + k->init = usb_audio_initfn; + k->handle_packet = usb_generic_handle_packet; + k->handle_reset = usb_audio_handle_reset; + k->handle_control = usb_audio_handle_control; + k->handle_data = usb_audio_handle_data; + k->handle_destroy = usb_audio_handle_destroy; + k->set_interface = usb_audio_set_interface; +} + +static struct DeviceInfo usb_audio_info = { + .name = "usb-audio", + .size = sizeof(USBAudioState), + .vmsd = &vmstate_usb_audio, + .class_init = usb_audio_class_init, + .props = (Property[]) { DEFINE_PROP_UINT32("debug", USBAudioState, debug, 0), DEFINE_PROP_UINT32("buffer", USBAudioState, buffer, 8 * USBAUDIO_PACKET_SIZE), @@ -698,7 +704,7 @@ static struct USBDeviceInfo usb_audio_info = { static void usb_audio_register_devices(void) { - usb_qdev_register(&usb_audio_info); + usb_qdev_register(&usb_audio_info, "audio", NULL); } device_init(usb_audio_register_devices) diff --git a/hw/usb-bt.c b/hw/usb-bt.c index 0c1270be79..bf8c47076a 100644 --- a/hw/usb-bt.c +++ b/hw/usb-bt.c @@ -527,22 +527,29 @@ static const VMStateDescription vmstate_usb_bt = { .unmigratable = 1, }; -static struct USBDeviceInfo bt_info = { - .product_desc = "QEMU BT dongle", - .qdev.name = "usb-bt-dongle", - .qdev.size = sizeof(struct USBBtState), - .qdev.vmsd = &vmstate_usb_bt, - .usb_desc = &desc_bluetooth, - .init = usb_bt_initfn, - .handle_packet = usb_generic_handle_packet, - .handle_reset = usb_bt_handle_reset, - .handle_control = usb_bt_handle_control, - .handle_data = usb_bt_handle_data, - .handle_destroy = usb_bt_handle_destroy, +static void usb_bt_class_initfn(ObjectClass *klass, void *data) +{ + USBDeviceClass *uc = USB_DEVICE_CLASS(klass); + + uc->init = usb_bt_initfn; + uc->product_desc = "QEMU BT dongle"; + uc->usb_desc = &desc_bluetooth; + uc->handle_packet = usb_generic_handle_packet; + uc->handle_reset = usb_bt_handle_reset; + uc->handle_control = usb_bt_handle_control; + uc->handle_data = usb_bt_handle_data; + uc->handle_destroy = usb_bt_handle_destroy; +} + +static struct DeviceInfo bt_info = { + .name = "usb-bt-dongle", + .size = sizeof(struct USBBtState), + .vmsd = &vmstate_usb_bt, + .class_init= usb_bt_class_initfn, }; static void usb_bt_register_devices(void) { - usb_qdev_register(&bt_info); + usb_qdev_register(&bt_info, NULL, NULL); } device_init(usb_bt_register_devices) diff --git a/hw/usb-bus.c b/hw/usb-bus.c index 9b67f18b15..aeef908fe4 100644 --- a/hw/usb-bus.c +++ b/hw/usb-bus.c @@ -65,14 +65,104 @@ USBBus *usb_bus_find(int busnr) return NULL; } +static int usb_device_init(USBDevice *dev) +{ + USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev); + if (klass->init) { + return klass->init(dev); + } + return 0; +} + +static void usb_device_handle_destroy(USBDevice *dev) +{ + USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev); + if (klass->handle_destroy) { + klass->handle_destroy(dev); + } +} + +int usb_device_handle_packet(USBDevice *dev, USBPacket *p) +{ + USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev); + if (klass->handle_packet) { + return klass->handle_packet(dev, p); + } + return -ENOSYS; +} + +void usb_device_cancel_packet(USBDevice *dev, USBPacket *p) +{ + USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev); + if (klass->cancel_packet) { + klass->cancel_packet(dev, p); + } +} + +void usb_device_handle_attach(USBDevice *dev) +{ + USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev); + if (klass->handle_attach) { + klass->handle_attach(dev); + } +} + +void usb_device_handle_reset(USBDevice *dev) +{ + USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev); + if (klass->handle_reset) { + klass->handle_reset(dev); + } +} + +int usb_device_handle_control(USBDevice *dev, USBPacket *p, int request, + int value, int index, int length, uint8_t *data) +{ + USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev); + if (klass->handle_control) { + return klass->handle_control(dev, p, request, value, index, length, + data); + } + return -ENOSYS; +} + +int usb_device_handle_data(USBDevice *dev, USBPacket *p) +{ + USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev); + if (klass->handle_data) { + return klass->handle_data(dev, p); + } + return -ENOSYS; +} + +const char *usb_device_get_product_desc(USBDevice *dev) +{ + USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev); + return klass->product_desc; +} + +const USBDesc *usb_device_get_usb_desc(USBDevice *dev) +{ + USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev); + return klass->usb_desc; +} + +void usb_device_set_interface(USBDevice *dev, int interface, + int alt_old, int alt_new) +{ + USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev); + if (klass->set_interface) { + klass->set_interface(dev, interface, alt_old, alt_new); + } +} + static int usb_qdev_init(DeviceState *qdev, DeviceInfo *base) { - USBDevice *dev = DO_UPCAST(USBDevice, qdev, qdev); - USBDeviceInfo *info = DO_UPCAST(USBDeviceInfo, qdev, base); + USBDevice *dev = USB_DEVICE(qdev); int rc; - pstrcpy(dev->product_desc, sizeof(dev->product_desc), info->product_desc); - dev->info = info; + 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); @@ -80,7 +170,7 @@ static int usb_qdev_init(DeviceState *qdev, DeviceInfo *base) if (rc != 0) { return rc; } - rc = dev->info->init(dev); + rc = usb_device_init(dev); if (rc != 0) { usb_release_port(dev); return rc; @@ -97,34 +187,43 @@ static int usb_qdev_init(DeviceState *qdev, DeviceInfo *base) static int usb_qdev_exit(DeviceState *qdev) { - USBDevice *dev = DO_UPCAST(USBDevice, qdev, qdev); + USBDevice *dev = USB_DEVICE(qdev); if (dev->attached) { usb_device_detach(dev); } - if (dev->info->handle_destroy) { - dev->info->handle_destroy(dev); - } + usb_device_handle_destroy(dev); if (dev->port) { usb_release_port(dev); } return 0; } -void usb_qdev_register(USBDeviceInfo *info) +typedef struct LegacyUSBFactory { - info->qdev.bus_info = &usb_bus_info; - info->qdev.init = usb_qdev_init; - info->qdev.unplug = qdev_simple_unplug_cb; - info->qdev.exit = usb_qdev_exit; - qdev_register(&info->qdev); -} + const char *name; + const char *usbdevice_name; + USBDevice *(*usbdevice_init)(const char *params); +} LegacyUSBFactory; -void usb_qdev_register_many(USBDeviceInfo *info) +static GSList *legacy_usb_factory; + +void usb_qdev_register(DeviceInfo *info, + const char *usbdevice_name, + USBDevice *(*usbdevice_init)(const char *params)) { - while (info->qdev.name) { - usb_qdev_register(info); - info++; + info->bus_info = &usb_bus_info; + info->init = usb_qdev_init; + info->unplug = qdev_simple_unplug_cb; + info->exit = usb_qdev_exit; + qdev_register_subclass(info, TYPE_USB_DEVICE); + + if (usbdevice_name) { + LegacyUSBFactory *f = g_malloc0(sizeof(*f)); + f->name = info->name; + f->usbdevice_name = usbdevice_name; + f->usbdevice_init = usbdevice_init; + legacy_usb_factory = g_slist_append(legacy_usb_factory, f); } } @@ -144,7 +243,7 @@ USBDevice *usb_create(USBBus *bus, const char *name) #endif dev = qdev_create(&bus->qbus, name); - return DO_UPCAST(USBDevice, qdev, dev); + return USB_DEVICE(dev); } USBDevice *usb_create_simple(USBBus *bus, const char *name) @@ -365,7 +464,7 @@ static const char *usb_speed(unsigned int speed) static void usb_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent) { - USBDevice *dev = DO_UPCAST(USBDevice, qdev, qdev); + USBDevice *dev = USB_DEVICE(qdev); USBBus *bus = usb_bus_from_device(dev); monitor_printf(mon, "%*saddr %d.%d, port %s, speed %s, name %s%s\n", @@ -377,13 +476,13 @@ static void usb_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent) static char *usb_get_dev_path(DeviceState *qdev) { - USBDevice *dev = DO_UPCAST(USBDevice, qdev, qdev); + USBDevice *dev = USB_DEVICE(qdev); return g_strdup(dev->port->path); } static char *usb_get_fw_dev_path(DeviceState *qdev) { - USBDevice *dev = DO_UPCAST(USBDevice, qdev, qdev); + USBDevice *dev = USB_DEVICE(qdev); char *fw_path, *in; ssize_t pos = 0, fw_len; long nr; @@ -434,8 +533,8 @@ void usb_info(Monitor *mon) USBDevice *usbdevice_create(const char *cmdline) { USBBus *bus = usb_bus_find(-1 /* any */); - DeviceInfo *info; - USBDeviceInfo *usb; + LegacyUSBFactory *f = NULL; + GSList *i; char driver[32]; const char *params; int len; @@ -452,17 +551,13 @@ USBDevice *usbdevice_create(const char *cmdline) pstrcpy(driver, sizeof(driver), cmdline); } - for (info = device_info_list; info != NULL; info = info->next) { - if (info->bus_info != &usb_bus_info) - continue; - usb = DO_UPCAST(USBDeviceInfo, qdev, info); - if (usb->usbdevice_name == NULL) - continue; - if (strcmp(usb->usbdevice_name, driver) != 0) - continue; - break; + for (i = legacy_usb_factory; i; i = i->next) { + f = i->data; + if (strcmp(f->usbdevice_name, driver) == 0) { + break; + } } - if (info == NULL) { + if (i == NULL) { #if 0 /* no error because some drivers are not converted (yet) */ error_report("usbdevice %s not found", driver); @@ -470,12 +565,27 @@ USBDevice *usbdevice_create(const char *cmdline) return NULL; } - if (!usb->usbdevice_init) { + if (!f->usbdevice_init) { if (*params) { error_report("usbdevice %s accepts no params", driver); return NULL; } - return usb_create_simple(bus, usb->qdev.name); + return usb_create_simple(bus, f->name); } - return usb->usbdevice_init(params); + return f->usbdevice_init(params); } + +static TypeInfo usb_device_type_info = { + .name = TYPE_USB_DEVICE, + .parent = TYPE_DEVICE, + .instance_size = sizeof(USBDevice), + .abstract = true, + .class_size = sizeof(USBDeviceClass), +}; + +static void usb_register_devices(void) +{ + type_register_static(&usb_device_type_info); +} + +device_init(usb_register_devices); diff --git a/hw/usb-ccid.c b/hw/usb-ccid.c index 3b7f95d28a..eb63dfc6df 100644 --- a/hw/usb-ccid.c +++ b/hw/usb-ccid.c @@ -1286,28 +1286,34 @@ static VMStateDescription ccid_vmstate = { } }; -static struct USBDeviceInfo ccid_info = { - .product_desc = "QEMU USB CCID", - .qdev.name = CCID_DEV_NAME, - .qdev.desc = "CCID Rev 1.1 smartcard reader", - .qdev.size = sizeof(USBCCIDState), - .init = ccid_initfn, - .usb_desc = &desc_ccid, - .handle_packet = usb_generic_handle_packet, - .handle_reset = ccid_handle_reset, - .handle_control = ccid_handle_control, - .handle_data = ccid_handle_data, - .handle_destroy = ccid_handle_destroy, - .usbdevice_name = "ccid", - .qdev.props = (Property[]) { +static void ccid_class_initfn(ObjectClass *klass, void *data) +{ + USBDeviceClass *uc = USB_DEVICE_CLASS(klass); + + uc->init = ccid_initfn; + uc->product_desc = "QEMU USB CCID"; + uc->usb_desc = &desc_ccid; + uc->handle_packet = usb_generic_handle_packet; + uc->handle_reset = ccid_handle_reset; + uc->handle_control = ccid_handle_control; + uc->handle_data = ccid_handle_data; + uc->handle_destroy = ccid_handle_destroy; +} + +static struct DeviceInfo ccid_info = { + .name = CCID_DEV_NAME, + .desc = "CCID Rev 1.1 smartcard reader", + .size = sizeof(USBCCIDState), + .class_init= ccid_class_initfn, + .vmsd = &ccid_vmstate, + .props = (Property[]) { DEFINE_PROP_UINT8("debug", USBCCIDState, debug, 0), DEFINE_PROP_END_OF_LIST(), }, - .qdev.vmsd = &ccid_vmstate, }; static void ccid_register_devices(void) { - usb_qdev_register(&ccid_info); + usb_qdev_register(&ccid_info, "ccid", NULL); } device_init(ccid_register_devices) diff --git a/hw/usb-desc.c b/hw/usb-desc.c index b3eb97bc6b..3c3ed6a802 100644 --- a/hw/usb-desc.c +++ b/hw/usb-desc.c @@ -297,8 +297,8 @@ static int usb_desc_set_interface(USBDevice *dev, int index, int value) dev->ifaces[index] = iface; usb_desc_ep_init(dev); - if (dev->info->set_interface && old != value) { - dev->info->set_interface(dev, index, old, value); + if (old != value) { + usb_device_set_interface(dev, index, old, value); } return 0; } @@ -338,7 +338,7 @@ static int usb_desc_set_config(USBDevice *dev, int value) static void usb_desc_setdefaults(USBDevice *dev) { - const USBDesc *desc = dev->info->usb_desc; + const USBDesc *desc = usb_device_get_usb_desc(dev); assert(desc != NULL); switch (dev->speed) { @@ -355,7 +355,7 @@ static void usb_desc_setdefaults(USBDevice *dev) void usb_desc_init(USBDevice *dev) { - const USBDesc *desc = dev->info->usb_desc; + const USBDesc *desc = usb_device_get_usb_desc(dev); assert(desc != NULL); dev->speed = USB_SPEED_FULL; @@ -371,7 +371,7 @@ void usb_desc_init(USBDevice *dev) void usb_desc_attach(USBDevice *dev) { - const USBDesc *desc = dev->info->usb_desc; + const USBDesc *desc = usb_device_get_usb_desc(dev); assert(desc != NULL); if (desc->high && (dev->port->speedmask & USB_SPEED_MASK_HIGH)) { @@ -380,7 +380,7 @@ void usb_desc_attach(USBDevice *dev) dev->speed = USB_SPEED_FULL; } else { fprintf(stderr, "usb: port/device speed mismatch for \"%s\"\n", - dev->info->product_desc); + usb_device_get_product_desc(dev)); return; } usb_desc_setdefaults(dev); @@ -436,7 +436,7 @@ int usb_desc_string(USBDevice *dev, int index, uint8_t *dest, size_t len) str = usb_desc_get_string(dev, index); if (str == NULL) { - str = dev->info->usb_desc->str[index]; + str = usb_device_get_usb_desc(dev)->str[index]; if (str == NULL) { return 0; } @@ -455,7 +455,7 @@ int usb_desc_string(USBDevice *dev, int index, uint8_t *dest, size_t len) int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len) { - const USBDesc *desc = dev->info->usb_desc; + const USBDesc *desc = usb_device_get_usb_desc(dev); const USBDescDevice *other_dev; uint8_t buf[256]; uint8_t type = value >> 8; @@ -463,9 +463,9 @@ int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len int ret = -1; if (dev->speed == USB_SPEED_HIGH) { - other_dev = dev->info->usb_desc->full; + other_dev = usb_device_get_usb_desc(dev)->full; } else { - other_dev = dev->info->usb_desc->high; + other_dev = usb_device_get_usb_desc(dev)->high; } switch(type) { @@ -520,7 +520,7 @@ int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len int usb_desc_handle_control(USBDevice *dev, USBPacket *p, int request, int value, int index, int length, uint8_t *data) { - const USBDesc *desc = dev->info->usb_desc; + const USBDesc *desc = usb_device_get_usb_desc(dev); int ret = -1; assert(desc != NULL); diff --git a/hw/usb-hid.c b/hw/usb-hid.c index 997f8287d8..88fdd35e36 100644 --- a/hw/usb-hid.c +++ b/hw/usb-hid.c @@ -553,53 +553,73 @@ static const VMStateDescription vmstate_usb_kbd = { } }; -static struct USBDeviceInfo hid_info[] = { - { - .product_desc = "QEMU USB Tablet", - .qdev.name = "usb-tablet", - .usbdevice_name = "tablet", - .qdev.size = sizeof(USBHIDState), - .qdev.vmsd = &vmstate_usb_ptr, - .usb_desc = &desc_tablet, - .init = usb_tablet_initfn, - .handle_packet = usb_generic_handle_packet, - .handle_reset = usb_hid_handle_reset, - .handle_control = usb_hid_handle_control, - .handle_data = usb_hid_handle_data, - .handle_destroy = usb_hid_handle_destroy, - },{ - .product_desc = "QEMU USB Mouse", - .qdev.name = "usb-mouse", - .usbdevice_name = "mouse", - .qdev.size = sizeof(USBHIDState), - .qdev.vmsd = &vmstate_usb_ptr, - .usb_desc = &desc_mouse, - .init = usb_mouse_initfn, - .handle_packet = usb_generic_handle_packet, - .handle_reset = usb_hid_handle_reset, - .handle_control = usb_hid_handle_control, - .handle_data = usb_hid_handle_data, - .handle_destroy = usb_hid_handle_destroy, - },{ - .product_desc = "QEMU USB Keyboard", - .qdev.name = "usb-kbd", - .usbdevice_name = "keyboard", - .qdev.size = sizeof(USBHIDState), - .qdev.vmsd = &vmstate_usb_kbd, - .usb_desc = &desc_keyboard, - .init = usb_keyboard_initfn, - .handle_packet = usb_generic_handle_packet, - .handle_reset = usb_hid_handle_reset, - .handle_control = usb_hid_handle_control, - .handle_data = usb_hid_handle_data, - .handle_destroy = usb_hid_handle_destroy, - },{ - /* end of list */ - } +static void usb_tablet_class_initfn(ObjectClass *klass, void *data) +{ + USBDeviceClass *uc = USB_DEVICE_CLASS(klass); + + uc->init = usb_tablet_initfn; + uc->product_desc = "QEMU USB Tablet"; + uc->usb_desc = &desc_tablet; + uc->handle_packet = usb_generic_handle_packet; + uc->handle_reset = usb_hid_handle_reset; + uc->handle_control = usb_hid_handle_control; + uc->handle_data = usb_hid_handle_data; + uc->handle_destroy = usb_hid_handle_destroy; +} + +static struct DeviceInfo usb_tablet_info = { + .name = "usb-tablet", + .size = sizeof(USBHIDState), + .vmsd = &vmstate_usb_ptr, + .class_init= usb_tablet_class_initfn, +}; + +static void usb_mouse_class_initfn(ObjectClass *klass, void *data) +{ + USBDeviceClass *uc = USB_DEVICE_CLASS(klass); + + uc->init = usb_mouse_initfn; + uc->product_desc = "QEMU USB Mouse"; + uc->usb_desc = &desc_mouse; + uc->handle_packet = usb_generic_handle_packet; + uc->handle_reset = usb_hid_handle_reset; + uc->handle_control = usb_hid_handle_control; + uc->handle_data = usb_hid_handle_data; + uc->handle_destroy = usb_hid_handle_destroy; +} + +static struct DeviceInfo usb_mouse_info = { + .name = "usb-mouse", + .size = sizeof(USBHIDState), + .vmsd = &vmstate_usb_ptr, + .class_init= usb_mouse_class_initfn, +}; + +static void usb_keyboard_class_initfn(ObjectClass *klass, void *data) +{ + USBDeviceClass *uc = USB_DEVICE_CLASS(klass); + + uc->init = usb_keyboard_initfn; + uc->product_desc = "QEMU USB Keyboard"; + uc->usb_desc = &desc_keyboard; + uc->handle_packet = usb_generic_handle_packet; + uc->handle_reset = usb_hid_handle_reset; + uc->handle_control = usb_hid_handle_control; + uc->handle_data = usb_hid_handle_data; + uc->handle_destroy = usb_hid_handle_destroy; +} + +static struct DeviceInfo usb_keyboard_info = { + .name = "usb-kbd", + .size = sizeof(USBHIDState), + .vmsd = &vmstate_usb_kbd, + .class_init= usb_keyboard_class_initfn, }; static void usb_hid_register_devices(void) { - usb_qdev_register_many(hid_info); + usb_qdev_register(&usb_tablet_info, "tablet", NULL); + usb_qdev_register(&usb_mouse_info, "mouse", NULL); + usb_qdev_register(&usb_keyboard_info, "keyboard", NULL); } device_init(usb_hid_register_devices) diff --git a/hw/usb-hub.c b/hw/usb-hub.c index 069611bbfb..ee4e6a6920 100644 --- a/hw/usb-hub.c +++ b/hw/usb-hub.c @@ -533,23 +533,30 @@ static const VMStateDescription vmstate_usb_hub = { } }; -static struct USBDeviceInfo hub_info = { - .product_desc = "QEMU USB Hub", - .qdev.name = "usb-hub", - .qdev.fw_name = "hub", - .qdev.size = sizeof(USBHubState), - .qdev.vmsd = &vmstate_usb_hub, - .usb_desc = &desc_hub, - .init = usb_hub_initfn, - .handle_packet = usb_hub_handle_packet, - .handle_reset = usb_hub_handle_reset, - .handle_control = usb_hub_handle_control, - .handle_data = usb_hub_handle_data, - .handle_destroy = usb_hub_handle_destroy, +static void usb_hub_class_initfn(ObjectClass *klass, void *data) +{ + USBDeviceClass *uc = USB_DEVICE_CLASS(klass); + + uc->init = usb_hub_initfn; + uc->product_desc = "QEMU USB Hub"; + uc->usb_desc = &desc_hub; + uc->handle_packet = usb_hub_handle_packet; + uc->handle_reset = usb_hub_handle_reset; + uc->handle_control = usb_hub_handle_control; + uc->handle_data = usb_hub_handle_data; + uc->handle_destroy = usb_hub_handle_destroy; +} + +static struct DeviceInfo hub_info = { + .name = "usb-hub", + .fw_name = "hub", + .size = sizeof(USBHubState), + .vmsd = &vmstate_usb_hub, + .class_init= usb_hub_class_initfn, }; static void usb_hub_register_devices(void) { - usb_qdev_register(&hub_info); + usb_qdev_register(&hub_info, NULL, NULL); } device_init(usb_hub_register_devices) diff --git a/hw/usb-msd.c b/hw/usb-msd.c index 186831d71b..ceb01e0eef 100644 --- a/hw/usb-msd.c +++ b/hw/usb-msd.c @@ -636,23 +636,28 @@ static const VMStateDescription vmstate_usb_msd = { } }; -static struct USBDeviceInfo msd_info = { - .product_desc = "QEMU USB MSD", - .qdev.name = "usb-storage", - .qdev.fw_name = "storage", - .qdev.size = sizeof(MSDState), - .qdev.vmsd = &vmstate_usb_msd, - .usb_desc = &desc, - .init = usb_msd_initfn, - .handle_packet = usb_generic_handle_packet, - .cancel_packet = usb_msd_cancel_io, - .handle_attach = usb_desc_attach, - .handle_reset = usb_msd_handle_reset, - .handle_control = usb_msd_handle_control, - .handle_data = usb_msd_handle_data, - .usbdevice_name = "disk", - .usbdevice_init = usb_msd_init, - .qdev.props = (Property[]) { +static void usb_msd_class_initfn(ObjectClass *klass, void *data) +{ + USBDeviceClass *uc = USB_DEVICE_CLASS(klass); + + uc->init = usb_msd_initfn; + uc->product_desc = "QEMU USB MSD"; + uc->usb_desc = &desc; + uc->handle_packet = usb_generic_handle_packet; + uc->cancel_packet = usb_msd_cancel_io; + uc->handle_attach = usb_desc_attach; + uc->handle_reset = usb_msd_handle_reset; + uc->handle_control = usb_msd_handle_control; + uc->handle_data = usb_msd_handle_data; +} + +static struct DeviceInfo msd_info = { + .name = "usb-storage", + .fw_name = "storage", + .size = sizeof(MSDState), + .vmsd = &vmstate_usb_msd, + .class_init= usb_msd_class_initfn, + .props = (Property[]) { DEFINE_BLOCK_PROPERTIES(MSDState, conf), DEFINE_PROP_STRING("serial", MSDState, serial), DEFINE_PROP_BIT("removable", MSDState, removable, 0, false), @@ -662,6 +667,6 @@ static struct USBDeviceInfo msd_info = { static void usb_msd_register_devices(void) { - usb_qdev_register(&msd_info); + usb_qdev_register(&msd_info, "disk", usb_msd_init); } device_init(usb_msd_register_devices) diff --git a/hw/usb-net.c b/hw/usb-net.c index fd4106b99b..57b58ac1da 100644 --- a/hw/usb-net.c +++ b/hw/usb-net.c @@ -1385,29 +1385,34 @@ static const VMStateDescription vmstate_usb_net = { .unmigratable = 1, }; -static struct USBDeviceInfo net_info = { - .product_desc = "QEMU USB Network Interface", - .qdev.name = "usb-net", - .qdev.fw_name = "network", - .qdev.size = sizeof(USBNetState), - .qdev.vmsd = &vmstate_usb_net, - .usb_desc = &desc_net, - .init = usb_net_initfn, - .handle_packet = usb_generic_handle_packet, - .handle_reset = usb_net_handle_reset, - .handle_control = usb_net_handle_control, - .handle_data = usb_net_handle_data, - .handle_destroy = usb_net_handle_destroy, - .usbdevice_name = "net", - .usbdevice_init = usb_net_init, - .qdev.props = (Property[]) { +static void usb_net_class_initfn(ObjectClass *klass, void *data) +{ + USBDeviceClass *uc = USB_DEVICE_CLASS(klass); + + uc->init = usb_net_initfn; + uc->product_desc = "QEMU USB Network Interface"; + uc->usb_desc = &desc_net; + uc->handle_packet = usb_generic_handle_packet; + uc->handle_reset = usb_net_handle_reset; + uc->handle_control = usb_net_handle_control; + uc->handle_data = usb_net_handle_data; + uc->handle_destroy = usb_net_handle_destroy; +} + +static struct DeviceInfo net_info = { + .name = "usb-net", + .fw_name = "network", + .size = sizeof(USBNetState), + .vmsd = &vmstate_usb_net, + .class_init= usb_net_class_initfn, + .props = (Property[]) { DEFINE_NIC_PROPERTIES(USBNetState, conf), DEFINE_PROP_END_OF_LIST(), - } + }, }; static void usb_net_register_devices(void) { - usb_qdev_register(&net_info); + usb_qdev_register(&net_info, "net", usb_net_init); } device_init(usb_net_register_devices) diff --git a/hw/usb-serial.c b/hw/usb-serial.c index e3c82388ac..de49607831 100644 --- a/hw/usb-serial.c +++ b/hw/usb-serial.c @@ -570,41 +570,51 @@ static const VMStateDescription vmstate_usb_serial = { .unmigratable = 1, }; -static struct USBDeviceInfo serial_info = { - .product_desc = "QEMU USB Serial", - .qdev.name = "usb-serial", - .qdev.size = sizeof(USBSerialState), - .qdev.vmsd = &vmstate_usb_serial, - .usb_desc = &desc_serial, - .init = usb_serial_initfn, - .handle_packet = usb_generic_handle_packet, - .handle_reset = usb_serial_handle_reset, - .handle_control = usb_serial_handle_control, - .handle_data = usb_serial_handle_data, - .handle_destroy = usb_serial_handle_destroy, - .usbdevice_name = "serial", - .usbdevice_init = usb_serial_init, - .qdev.props = (Property[]) { +static void usb_serial_class_initfn(ObjectClass *klass, void *data) +{ + USBDeviceClass *uc = USB_DEVICE_CLASS(klass); + + uc->init = usb_serial_initfn; + uc->product_desc = "QEMU USB Serial"; + uc->usb_desc = &desc_serial; + uc->handle_packet = usb_generic_handle_packet; + uc->handle_reset = usb_serial_handle_reset; + uc->handle_control = usb_serial_handle_control; + uc->handle_data = usb_serial_handle_data; + uc->handle_destroy = usb_serial_handle_destroy; +} + +static struct DeviceInfo serial_info = { + .name = "usb-serial", + .size = sizeof(USBSerialState), + .vmsd = &vmstate_usb_serial, + .class_init= usb_serial_class_initfn, + .props = (Property[]) { DEFINE_PROP_CHR("chardev", USBSerialState, cs), DEFINE_PROP_END_OF_LIST(), }, }; -static struct USBDeviceInfo braille_info = { - .product_desc = "QEMU USB Braille", - .qdev.name = "usb-braille", - .qdev.size = sizeof(USBSerialState), - .qdev.vmsd = &vmstate_usb_serial, - .usb_desc = &desc_braille, - .init = usb_serial_initfn, - .handle_packet = usb_generic_handle_packet, - .handle_reset = usb_serial_handle_reset, - .handle_control = usb_serial_handle_control, - .handle_data = usb_serial_handle_data, - .handle_destroy = usb_serial_handle_destroy, - .usbdevice_name = "braille", - .usbdevice_init = usb_braille_init, - .qdev.props = (Property[]) { +static void usb_braille_class_initfn(ObjectClass *klass, void *data) +{ + USBDeviceClass *uc = USB_DEVICE_CLASS(klass); + + uc->init = usb_serial_initfn; + uc->product_desc = "QEMU USB Braille"; + uc->usb_desc = &desc_braille; + uc->handle_packet = usb_generic_handle_packet; + uc->handle_reset = usb_serial_handle_reset; + uc->handle_control = usb_serial_handle_control; + uc->handle_data = usb_serial_handle_data; + uc->handle_destroy = usb_serial_handle_destroy; +} + +static struct DeviceInfo braille_info = { + .name = "usb-braille", + .size = sizeof(USBSerialState), + .vmsd = &vmstate_usb_serial, + .class_init= usb_braille_class_initfn, + .props = (Property[]) { DEFINE_PROP_CHR("chardev", USBSerialState, cs), DEFINE_PROP_END_OF_LIST(), }, @@ -612,7 +622,7 @@ static struct USBDeviceInfo braille_info = { static void usb_serial_register_devices(void) { - usb_qdev_register(&serial_info); - usb_qdev_register(&braille_info); + usb_qdev_register(&serial_info, "serial", usb_serial_init); + usb_qdev_register(&braille_info, "braille", usb_braille_init); } device_init(usb_serial_register_devices) diff --git a/hw/usb-wacom.c b/hw/usb-wacom.c index 61d5b184df..9b20a3154c 100644 --- a/hw/usb-wacom.c +++ b/hw/usb-wacom.c @@ -349,24 +349,30 @@ static const VMStateDescription vmstate_usb_wacom = { .unmigratable = 1, }; -static struct USBDeviceInfo wacom_info = { - .product_desc = "QEMU PenPartner Tablet", - .qdev.name = "usb-wacom-tablet", - .qdev.desc = "QEMU PenPartner Tablet", - .usbdevice_name = "wacom-tablet", - .usb_desc = &desc_wacom, - .qdev.size = sizeof(USBWacomState), - .qdev.vmsd = &vmstate_usb_wacom, - .init = usb_wacom_initfn, - .handle_packet = usb_generic_handle_packet, - .handle_reset = usb_wacom_handle_reset, - .handle_control = usb_wacom_handle_control, - .handle_data = usb_wacom_handle_data, - .handle_destroy = usb_wacom_handle_destroy, +static void usb_wacom_class_init(ObjectClass *class, void *data) +{ + USBDeviceClass *uc = USB_DEVICE_CLASS(class); + + uc->product_desc = "QEMU PenPartner Tablet"; + uc->usb_desc = &desc_wacom; + uc->init = usb_wacom_initfn; + uc->handle_packet = usb_generic_handle_packet; + uc->handle_reset = usb_wacom_handle_reset; + uc->handle_control = usb_wacom_handle_control; + uc->handle_data = usb_wacom_handle_data; + uc->handle_destroy = usb_wacom_handle_destroy; +} + +static struct DeviceInfo wacom_info = { + .name = "usb-wacom-tablet", + .desc = "QEMU PenPartner Tablet", + .size = sizeof(USBWacomState), + .vmsd = &vmstate_usb_wacom, + .class_init= usb_wacom_class_init, }; static void usb_wacom_register_devices(void) { - usb_qdev_register(&wacom_info); + usb_qdev_register(&wacom_info, "wacom-tablet", NULL); } device_init(usb_wacom_register_devices) diff --git a/hw/usb-xhci.c b/hw/usb-xhci.c index 28fe9de2a0..95bf010101 100644 --- a/hw/usb-xhci.c +++ b/hw/usb-xhci.c @@ -1458,7 +1458,7 @@ static int xhci_fire_ctl_transfer(XHCIState *xhci, XHCITransfer *xfer) if (!xfer->in_xfer) { xhci_xfer_data(xfer, xfer->data, wLength, 0, 1, 0); } - ret = dev->info->handle_control(dev, &xfer->packet, + ret = usb_device_handle_control(dev, &xfer->packet, (bmRequestType << 8) | bRequest, wValue, wIndex, wLength, xfer->data); @@ -1767,7 +1767,7 @@ static TRBCCode xhci_address_slot(XHCIState *xhci, unsigned int slotid, slot->devaddr = xhci->devaddr++; slot_ctx[3] = (SLOT_ADDRESSED << SLOT_STATE_SHIFT) | slot->devaddr; DPRINTF("xhci: device address is %d\n", slot->devaddr); - dev->info->handle_control(dev, NULL, + usb_device_handle_control(dev, NULL, DeviceOutRequest | USB_REQ_SET_ADDRESS, slot->devaddr, 0, 0, NULL); } @@ -95,8 +95,8 @@ static int do_token_setup(USBDevice *s, USBPacket *p) index = (s->setup_buf[5] << 8) | s->setup_buf[4]; if (s->setup_buf[0] & USB_DIR_IN) { - ret = s->info->handle_control(s, p, request, value, index, - s->setup_len, s->data_buf); + ret = usb_device_handle_control(s, p, request, value, index, + s->setup_len, s->data_buf); if (ret == USB_RET_ASYNC) { s->setup_state = SETUP_STATE_SETUP; return USB_RET_ASYNC; @@ -129,7 +129,7 @@ static int do_token_in(USBDevice *s, USBPacket *p) int ret = 0; if (p->devep != 0) - return s->info->handle_data(s, p); + return usb_device_handle_data(s, p); request = (s->setup_buf[0] << 8) | s->setup_buf[1]; value = (s->setup_buf[3] << 8) | s->setup_buf[2]; @@ -138,8 +138,8 @@ static int do_token_in(USBDevice *s, USBPacket *p) switch(s->setup_state) { case SETUP_STATE_ACK: if (!(s->setup_buf[0] & USB_DIR_IN)) { - ret = s->info->handle_control(s, p, request, value, index, - s->setup_len, s->data_buf); + ret = usb_device_handle_control(s, p, request, value, index, + s->setup_len, s->data_buf); if (ret == USB_RET_ASYNC) { return USB_RET_ASYNC; } @@ -176,7 +176,7 @@ static int do_token_in(USBDevice *s, USBPacket *p) static int do_token_out(USBDevice *s, USBPacket *p) { if (p->devep != 0) - return s->info->handle_data(s, p); + return usb_device_handle_data(s, p); switch(s->setup_state) { case SETUP_STATE_ACK: @@ -220,9 +220,7 @@ int usb_generic_handle_packet(USBDevice *s, USBPacket *p) switch(p->pid) { case USB_MSG_ATTACH: s->state = USB_STATE_ATTACHED; - if (s->info->handle_attach) { - s->info->handle_attach(s); - } + usb_device_handle_attach(s); return 0; case USB_MSG_DETACH: @@ -233,9 +231,7 @@ int usb_generic_handle_packet(USBDevice *s, USBPacket *p) s->remote_wakeup = 0; s->addr = 0; s->state = USB_STATE_DEFAULT; - if (s->info->handle_reset) { - s->info->handle_reset(s); - } + usb_device_handle_reset(s); return 0; } @@ -326,7 +322,7 @@ int usb_handle_packet(USBDevice *dev, USBPacket *p) int ret; assert(p->owner == NULL); - ret = dev->info->handle_packet(dev, p); + ret = usb_device_handle_packet(dev, p); if (ret == USB_RET_ASYNC) { if (p->owner == NULL) { p->owner = usb_ep_get(dev, p->pid, p->devep); @@ -357,7 +353,7 @@ void usb_packet_complete(USBDevice *dev, USBPacket *p) void usb_cancel_packet(USBPacket * p) { assert(p->owner != NULL); - p->owner->dev->info->cancel_packet(p->owner->dev, p); + usb_device_cancel_packet(p->owner->dev, p); p->owner = NULL; } @@ -1,3 +1,6 @@ +#ifndef QEMU_USB_H +#define QEMU_USB_H + /* * QEMU USB API * @@ -150,7 +153,6 @@ typedef struct USBBus USBBus; typedef struct USBBusOps USBBusOps; typedef struct USBPort USBPort; typedef struct USBDevice USBDevice; -typedef struct USBDeviceInfo USBDeviceInfo; typedef struct USBPacket USBPacket; typedef struct USBEndpoint USBEndpoint; @@ -183,7 +185,6 @@ struct USBEndpoint { /* definition of a USB device */ struct USBDevice { DeviceState qdev; - USBDeviceInfo *info; USBPort *port; char *port_path; void *opaque; @@ -219,8 +220,17 @@ struct USBDevice { const USBDescIface *ifaces[USB_MAX_INTERFACES]; }; -struct USBDeviceInfo { - DeviceInfo qdev; +#define TYPE_USB_DEVICE "usb-device" +#define USB_DEVICE(obj) \ + OBJECT_CHECK(USBDevice, (obj), TYPE_USB_DEVICE) +#define USB_DEVICE_CLASS(klass) \ + OBJECT_CLASS_CHECK(USBDeviceClass, (klass), TYPE_USB_DEVICE) +#define USB_DEVICE_GET_CLASS(obj) \ + OBJECT_GET_CLASS(USBDeviceClass, (obj), TYPE_USB_DEVICE) + +typedef struct USBDeviceClass { + DeviceClass parent_class; + int (*init)(USBDevice *dev); /* @@ -274,11 +284,7 @@ struct USBDeviceInfo { const char *product_desc; const USBDesc *usb_desc; - - /* handle legacy -usbdevice command line options */ - const char *usbdevice_name; - USBDevice *(*usbdevice_init)(const char *params); -}; +} USBDeviceClass; typedef struct USBPortOps { void (*attach)(USBPort *port); @@ -412,8 +418,9 @@ struct USBBusOps { void usb_bus_new(USBBus *bus, USBBusOps *ops, DeviceState *host); USBBus *usb_bus_find(int busnr); -void usb_qdev_register(USBDeviceInfo *info); -void usb_qdev_register_many(USBDeviceInfo *info); +void usb_qdev_register(DeviceInfo *info, + const char *usbdevice_name, + USBDevice *(*usbdevice_init)(const char *params)); USBDevice *usb_create(USBBus *bus, const char *name); USBDevice *usb_create_simple(USBBus *bus, const char *name); USBDevice *usbdevice_create(const char *cmdline); @@ -445,4 +452,25 @@ extern const VMStateDescription vmstate_usb_device; .offset = vmstate_offset_value(_state, _field, USBDevice), \ } +int usb_device_handle_packet(USBDevice *dev, USBPacket *p); + +void usb_device_cancel_packet(USBDevice *dev, USBPacket *p); + +void usb_device_handle_attach(USBDevice *dev); + +void usb_device_handle_reset(USBDevice *dev); + +int usb_device_handle_control(USBDevice *dev, USBPacket *p, int request, int value, + int index, int length, uint8_t *data); + +int usb_device_handle_data(USBDevice *dev, USBPacket *p); + +void usb_device_set_interface(USBDevice *dev, int interface, + int alt_old, int alt_new); + +const char *usb_device_get_product_desc(USBDevice *dev); + +const USBDesc *usb_device_get_usb_desc(USBDevice *dev); + +#endif @@ -397,21 +397,28 @@ fail: return ret; } -static struct USBDeviceInfo usb_host_dev_info = { - .product_desc = "USB Host Device", - .qdev.name = "usb-host", - .qdev.size = sizeof(USBHostDevice), - .init = usb_host_initfn, - .handle_packet = usb_generic_handle_packet, - .handle_reset = usb_host_handle_reset, - .handle_control = usb_host_handle_control, - .handle_data = usb_host_handle_data, - .handle_destroy = usb_host_handle_destroy, +static void usb_host_class_initfn(ObjectClass *klass, void *data) +{ + USBDeviceClass *uc = USB_DEVICE_CLASS(klass); + + uc->product_desc = "USB Host Device"; + uc->init = usb_host_initfn; + uc->handle_packet = usb_generic_handle_packet; + uc->handle_reset = usb_host_handle_reset; + uc->handle_control = usb_host_handle_control; + uc->handle_data = usb_host_handle_data; + uc->handle_destroy = usb_host_handle_destroy; +} + +static struct DeviceInfo usb_host_dev_info = { + .name = "usb-host", + .size = sizeof(USBHostDevice), + .class_init= usb_host_initfn, }; static void usb_host_register_devices(void) { - usb_qdev_register(&usb_host_dev_info); + usb_qdev_register(&usb_host_dev_info, NULL, NULL); } device_init(usb_host_register_devices) diff --git a/usb-linux.c b/usb-linux.c index 56898dd4cd..31810f6f40 100644 --- a/usb-linux.c +++ b/usb-linux.c @@ -1402,21 +1402,26 @@ static const VMStateDescription vmstate_usb_host = { .unmigratable = 1, }; -static struct USBDeviceInfo usb_host_dev_info = { - .product_desc = "USB Host Device", - .qdev.name = "usb-host", - .qdev.size = sizeof(USBHostDevice), - .qdev.vmsd = &vmstate_usb_host, - .init = usb_host_initfn, - .handle_packet = usb_generic_handle_packet, - .cancel_packet = usb_host_async_cancel, - .handle_data = usb_host_handle_data, - .handle_control = usb_host_handle_control, - .handle_reset = usb_host_handle_reset, - .handle_destroy = usb_host_handle_destroy, - .usbdevice_name = "host", - .usbdevice_init = usb_host_device_open, - .qdev.props = (Property[]) { +static void usb_host_class_initfn(ObjectClass *klass, void *data) +{ + USBDeviceClass *uc = USB_DEVICE_CLASS(klass); + + uc->init = usb_host_initfn; + uc->product_desc = "USB Host Device"; + uc->handle_packet = usb_generic_handle_packet; + uc->cancel_packet = usb_host_async_cancel; + uc->handle_data = usb_host_handle_data; + uc->handle_control = usb_host_handle_control; + uc->handle_reset = usb_host_handle_reset; + uc->handle_destroy = usb_host_handle_destroy; +} + +static struct DeviceInfo usb_host_dev_info = { + .name = "usb-host", + .size = sizeof(USBHostDevice), + .vmsd = &vmstate_usb_host, + .class_init= usb_host_class_initfn, + .props = (Property[]) { DEFINE_PROP_UINT32("hostbus", USBHostDevice, match.bus_num, 0), DEFINE_PROP_UINT32("hostaddr", USBHostDevice, match.addr, 0), DEFINE_PROP_STRING("hostport", USBHostDevice, match.port), @@ -1429,7 +1434,7 @@ static struct USBDeviceInfo usb_host_dev_info = { static void usb_host_register_devices(void) { - usb_qdev_register(&usb_host_dev_info); + usb_qdev_register(&usb_host_dev_info, "host", usb_host_device_open); } device_init(usb_host_register_devices) diff --git a/usb-redir.c b/usb-redir.c index 79d29ece1b..8f4a29a218 100644 --- a/usb-redir.c +++ b/usb-redir.c @@ -1315,18 +1315,25 @@ static void usbredir_interrupt_packet(void *priv, uint32_t id, } } -static struct USBDeviceInfo usbredir_dev_info = { - .product_desc = "USB Redirection Device", - .qdev.name = "usb-redir", - .qdev.size = sizeof(USBRedirDevice), - .init = usbredir_initfn, - .handle_destroy = usbredir_handle_destroy, - .handle_packet = usb_generic_handle_packet, - .cancel_packet = usbredir_cancel_packet, - .handle_reset = usbredir_handle_reset, - .handle_data = usbredir_handle_data, - .handle_control = usbredir_handle_control, - .qdev.props = (Property[]) { +static void usbredir_class_initfn(ObjectClass *klass, void *data) +{ + USBDeviceClass *uc = USB_DEVICE_CLASS(klass); + + uc->init = usbredir_initfn; + uc->product_desc = "USB Redirection Device"; + uc->handle_destroy = usbredir_handle_destroy; + uc->handle_packet = usb_generic_handle_packet; + uc->cancel_packet = usbredir_cancel_packet; + uc->handle_reset = usbredir_handle_reset; + uc->handle_data = usbredir_handle_data; + uc->handle_control = usbredir_handle_control; +} + +static struct DeviceInfo usbredir_dev_info = { + .name = "usb-redir", + .size = sizeof(USBRedirDevice), + .class_init= usbredir_class_initfn, + .props = (Property[]) { DEFINE_PROP_CHR("chardev", USBRedirDevice, cs), DEFINE_PROP_UINT8("debug", USBRedirDevice, debug, 0), DEFINE_PROP_END_OF_LIST(), @@ -1335,6 +1342,6 @@ static struct USBDeviceInfo usbredir_dev_info = { static void usbredir_register_devices(void) { - usb_qdev_register(&usbredir_dev_info); + usb_qdev_register(&usbredir_dev_info, NULL, NULL); } device_init(usbredir_register_devices); |