1 #include "qemu/osdep.h" 2 #include "hw/qdev-properties.h" 3 #include "hw/usb.h" 4 #include "qapi/error.h" 5 #include "qemu/error-report.h" 6 #include "qemu/module.h" 7 #include "sysemu/sysemu.h" 8 #include "migration/vmstate.h" 9 #include "monitor/monitor.h" 10 #include "trace.h" 11 #include "qemu/cutils.h" 12 13 static void usb_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent); 14 15 static char *usb_get_dev_path(DeviceState *dev); 16 static char *usb_get_fw_dev_path(DeviceState *qdev); 17 static void usb_qdev_unrealize(DeviceState *qdev); 18 19 static Property usb_props[] = { 20 DEFINE_PROP_STRING("port", USBDevice, port_path), 21 DEFINE_PROP_STRING("serial", USBDevice, serial), 22 DEFINE_PROP_BIT("full-path", USBDevice, flags, 23 USB_DEV_FLAG_FULL_PATH, true), 24 DEFINE_PROP_BIT("msos-desc", USBDevice, flags, 25 USB_DEV_FLAG_MSOS_DESC_ENABLE, true), 26 DEFINE_PROP_END_OF_LIST() 27 }; 28 29 static void usb_bus_class_init(ObjectClass *klass, void *data) 30 { 31 BusClass *k = BUS_CLASS(klass); 32 HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass); 33 34 k->print_dev = usb_bus_dev_print; 35 k->get_dev_path = usb_get_dev_path; 36 k->get_fw_dev_path = usb_get_fw_dev_path; 37 hc->unplug = qdev_simple_device_unplug_cb; 38 } 39 40 static const TypeInfo usb_bus_info = { 41 .name = TYPE_USB_BUS, 42 .parent = TYPE_BUS, 43 .instance_size = sizeof(USBBus), 44 .class_init = usb_bus_class_init, 45 .interfaces = (InterfaceInfo[]) { 46 { TYPE_HOTPLUG_HANDLER }, 47 { } 48 } 49 }; 50 51 static int next_usb_bus = 0; 52 static QTAILQ_HEAD(, USBBus) busses = QTAILQ_HEAD_INITIALIZER(busses); 53 54 static int usb_device_post_load(void *opaque, int version_id) 55 { 56 USBDevice *dev = opaque; 57 58 if (dev->state == USB_STATE_NOTATTACHED) { 59 dev->attached = false; 60 } else { 61 dev->attached = true; 62 } 63 return 0; 64 } 65 66 const VMStateDescription vmstate_usb_device = { 67 .name = "USBDevice", 68 .version_id = 1, 69 .minimum_version_id = 1, 70 .post_load = usb_device_post_load, 71 .fields = (VMStateField[]) { 72 VMSTATE_UINT8(addr, USBDevice), 73 VMSTATE_INT32(state, USBDevice), 74 VMSTATE_INT32(remote_wakeup, USBDevice), 75 VMSTATE_INT32(setup_state, USBDevice), 76 VMSTATE_INT32(setup_len, USBDevice), 77 VMSTATE_INT32(setup_index, USBDevice), 78 VMSTATE_UINT8_ARRAY(setup_buf, USBDevice, 8), 79 VMSTATE_END_OF_LIST(), 80 } 81 }; 82 83 void usb_bus_new(USBBus *bus, size_t bus_size, 84 USBBusOps *ops, DeviceState *host) 85 { 86 qbus_create_inplace(bus, bus_size, TYPE_USB_BUS, host, NULL); 87 qbus_set_bus_hotplug_handler(BUS(bus), &error_abort); 88 bus->ops = ops; 89 bus->busnr = next_usb_bus++; 90 QTAILQ_INIT(&bus->free); 91 QTAILQ_INIT(&bus->used); 92 QTAILQ_INSERT_TAIL(&busses, bus, next); 93 } 94 95 void usb_bus_release(USBBus *bus) 96 { 97 assert(next_usb_bus > 0); 98 99 QTAILQ_REMOVE(&busses, bus, next); 100 } 101 102 USBBus *usb_bus_find(int busnr) 103 { 104 USBBus *bus; 105 106 if (-1 == busnr) 107 return QTAILQ_FIRST(&busses); 108 QTAILQ_FOREACH(bus, &busses, next) { 109 if (bus->busnr == busnr) 110 return bus; 111 } 112 return NULL; 113 } 114 115 static void usb_device_realize(USBDevice *dev, Error **errp) 116 { 117 USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev); 118 119 if (klass->realize) { 120 klass->realize(dev, errp); 121 } 122 } 123 124 USBDevice *usb_device_find_device(USBDevice *dev, uint8_t addr) 125 { 126 USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev); 127 if (klass->find_device) { 128 return klass->find_device(dev, addr); 129 } 130 return NULL; 131 } 132 133 static void usb_device_unrealize(USBDevice *dev) 134 { 135 USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev); 136 137 if (klass->unrealize) { 138 klass->unrealize(dev); 139 } 140 } 141 142 void usb_device_cancel_packet(USBDevice *dev, USBPacket *p) 143 { 144 USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev); 145 if (klass->cancel_packet) { 146 klass->cancel_packet(dev, p); 147 } 148 } 149 150 void usb_device_handle_attach(USBDevice *dev) 151 { 152 USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev); 153 if (klass->handle_attach) { 154 klass->handle_attach(dev); 155 } 156 } 157 158 void usb_device_handle_reset(USBDevice *dev) 159 { 160 USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev); 161 if (klass->handle_reset) { 162 klass->handle_reset(dev); 163 } 164 } 165 166 void usb_device_handle_control(USBDevice *dev, USBPacket *p, int request, 167 int value, int index, int length, uint8_t *data) 168 { 169 USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev); 170 if (klass->handle_control) { 171 klass->handle_control(dev, p, request, value, index, length, data); 172 } 173 } 174 175 void usb_device_handle_data(USBDevice *dev, USBPacket *p) 176 { 177 USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev); 178 if (klass->handle_data) { 179 klass->handle_data(dev, p); 180 } 181 } 182 183 const char *usb_device_get_product_desc(USBDevice *dev) 184 { 185 USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev); 186 return klass->product_desc; 187 } 188 189 const USBDesc *usb_device_get_usb_desc(USBDevice *dev) 190 { 191 USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev); 192 if (dev->usb_desc) { 193 return dev->usb_desc; 194 } 195 return klass->usb_desc; 196 } 197 198 void usb_device_set_interface(USBDevice *dev, int interface, 199 int alt_old, int alt_new) 200 { 201 USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev); 202 if (klass->set_interface) { 203 klass->set_interface(dev, interface, alt_old, alt_new); 204 } 205 } 206 207 void usb_device_flush_ep_queue(USBDevice *dev, USBEndpoint *ep) 208 { 209 USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev); 210 if (klass->flush_ep_queue) { 211 klass->flush_ep_queue(dev, ep); 212 } 213 } 214 215 void usb_device_ep_stopped(USBDevice *dev, USBEndpoint *ep) 216 { 217 USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev); 218 if (klass->ep_stopped) { 219 klass->ep_stopped(dev, ep); 220 } 221 } 222 223 int usb_device_alloc_streams(USBDevice *dev, USBEndpoint **eps, int nr_eps, 224 int streams) 225 { 226 USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev); 227 if (klass->alloc_streams) { 228 return klass->alloc_streams(dev, eps, nr_eps, streams); 229 } 230 return 0; 231 } 232 233 void usb_device_free_streams(USBDevice *dev, USBEndpoint **eps, int nr_eps) 234 { 235 USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev); 236 if (klass->free_streams) { 237 klass->free_streams(dev, eps, nr_eps); 238 } 239 } 240 241 static void usb_qdev_realize(DeviceState *qdev, Error **errp) 242 { 243 USBDevice *dev = USB_DEVICE(qdev); 244 Error *local_err = NULL; 245 246 pstrcpy(dev->product_desc, sizeof(dev->product_desc), 247 usb_device_get_product_desc(dev)); 248 dev->auto_attach = 1; 249 QLIST_INIT(&dev->strings); 250 usb_ep_init(dev); 251 252 usb_claim_port(dev, &local_err); 253 if (local_err) { 254 error_propagate(errp, local_err); 255 return; 256 } 257 258 usb_device_realize(dev, &local_err); 259 if (local_err) { 260 usb_release_port(dev); 261 error_propagate(errp, local_err); 262 return; 263 } 264 265 if (dev->auto_attach) { 266 usb_device_attach(dev, &local_err); 267 if (local_err) { 268 usb_qdev_unrealize(qdev); 269 error_propagate(errp, local_err); 270 return; 271 } 272 } 273 } 274 275 static void usb_qdev_unrealize(DeviceState *qdev) 276 { 277 USBDevice *dev = USB_DEVICE(qdev); 278 USBDescString *s, *next; 279 280 QLIST_FOREACH_SAFE(s, &dev->strings, next, next) { 281 QLIST_REMOVE(s, next); 282 g_free(s->str); 283 g_free(s); 284 } 285 286 if (dev->attached) { 287 usb_device_detach(dev); 288 } 289 usb_device_unrealize(dev); 290 if (dev->port) { 291 usb_release_port(dev); 292 } 293 } 294 295 typedef struct LegacyUSBFactory 296 { 297 const char *name; 298 const char *usbdevice_name; 299 USBDevice *(*usbdevice_init)(const char *params); 300 } LegacyUSBFactory; 301 302 static GSList *legacy_usb_factory; 303 304 void usb_legacy_register(const char *typename, const char *usbdevice_name, 305 USBDevice *(*usbdevice_init)(const char *params)) 306 { 307 if (usbdevice_name) { 308 LegacyUSBFactory *f = g_malloc0(sizeof(*f)); 309 f->name = typename; 310 f->usbdevice_name = usbdevice_name; 311 f->usbdevice_init = usbdevice_init; 312 legacy_usb_factory = g_slist_append(legacy_usb_factory, f); 313 } 314 } 315 316 USBDevice *usb_new(const char *name) 317 { 318 return USB_DEVICE(qdev_new(name)); 319 } 320 321 static USBDevice *usb_try_new(const char *name) 322 { 323 return USB_DEVICE(qdev_try_new(name)); 324 } 325 326 bool usb_realize_and_unref(USBDevice *dev, USBBus *bus, Error **errp) 327 { 328 return qdev_realize_and_unref(&dev->qdev, &bus->qbus, errp); 329 } 330 331 USBDevice *usb_create_simple(USBBus *bus, const char *name) 332 { 333 USBDevice *dev = usb_new(name); 334 335 usb_realize_and_unref(dev, bus, &error_abort); 336 return dev; 337 } 338 339 static void usb_fill_port(USBPort *port, void *opaque, int index, 340 USBPortOps *ops, int speedmask) 341 { 342 port->opaque = opaque; 343 port->index = index; 344 port->ops = ops; 345 port->speedmask = speedmask; 346 usb_port_location(port, NULL, index + 1); 347 } 348 349 void usb_register_port(USBBus *bus, USBPort *port, void *opaque, int index, 350 USBPortOps *ops, int speedmask) 351 { 352 usb_fill_port(port, opaque, index, ops, speedmask); 353 QTAILQ_INSERT_TAIL(&bus->free, port, next); 354 bus->nfree++; 355 } 356 357 void usb_register_companion(const char *masterbus, USBPort *ports[], 358 uint32_t portcount, uint32_t firstport, 359 void *opaque, USBPortOps *ops, int speedmask, 360 Error **errp) 361 { 362 USBBus *bus; 363 int i; 364 365 QTAILQ_FOREACH(bus, &busses, next) { 366 if (strcmp(bus->qbus.name, masterbus) == 0) { 367 break; 368 } 369 } 370 371 if (!bus) { 372 error_setg(errp, "USB bus '%s' not found", masterbus); 373 return; 374 } 375 if (!bus->ops->register_companion) { 376 error_setg(errp, "Can't use USB bus '%s' as masterbus," 377 " it doesn't support companion controllers", 378 masterbus); 379 return; 380 } 381 382 for (i = 0; i < portcount; i++) { 383 usb_fill_port(ports[i], opaque, i, ops, speedmask); 384 } 385 386 bus->ops->register_companion(bus, ports, portcount, firstport, errp); 387 } 388 389 void usb_port_location(USBPort *downstream, USBPort *upstream, int portnr) 390 { 391 if (upstream) { 392 int l = snprintf(downstream->path, sizeof(downstream->path), "%s.%d", 393 upstream->path, portnr); 394 /* Max string is nn.nn.nn.nn.nn, which fits in 16 bytes */ 395 assert(l < sizeof(downstream->path)); 396 downstream->hubcount = upstream->hubcount + 1; 397 } else { 398 snprintf(downstream->path, sizeof(downstream->path), "%d", portnr); 399 downstream->hubcount = 0; 400 } 401 } 402 403 void usb_unregister_port(USBBus *bus, USBPort *port) 404 { 405 if (port->dev) { 406 object_unparent(OBJECT(port->dev)); 407 } 408 QTAILQ_REMOVE(&bus->free, port, next); 409 bus->nfree--; 410 } 411 412 void usb_claim_port(USBDevice *dev, Error **errp) 413 { 414 USBBus *bus = usb_bus_from_device(dev); 415 USBPort *port; 416 USBDevice *hub; 417 418 assert(dev->port == NULL); 419 420 if (dev->port_path) { 421 QTAILQ_FOREACH(port, &bus->free, next) { 422 if (strcmp(port->path, dev->port_path) == 0) { 423 break; 424 } 425 } 426 if (port == NULL) { 427 error_setg(errp, "usb port %s (bus %s) not found (in use?)", 428 dev->port_path, bus->qbus.name); 429 return; 430 } 431 } else { 432 if (bus->nfree == 1 && strcmp(object_get_typename(OBJECT(dev)), "usb-hub") != 0) { 433 /* Create a new hub and chain it on */ 434 hub = usb_try_new("usb-hub"); 435 if (hub) { 436 usb_realize_and_unref(hub, bus, NULL); 437 } 438 } 439 if (bus->nfree == 0) { 440 error_setg(errp, "tried to attach usb device %s to a bus " 441 "with no free ports", dev->product_desc); 442 return; 443 } 444 port = QTAILQ_FIRST(&bus->free); 445 } 446 trace_usb_port_claim(bus->busnr, port->path); 447 448 QTAILQ_REMOVE(&bus->free, port, next); 449 bus->nfree--; 450 451 dev->port = port; 452 port->dev = dev; 453 454 QTAILQ_INSERT_TAIL(&bus->used, port, next); 455 bus->nused++; 456 } 457 458 void usb_release_port(USBDevice *dev) 459 { 460 USBBus *bus = usb_bus_from_device(dev); 461 USBPort *port = dev->port; 462 463 assert(port != NULL); 464 trace_usb_port_release(bus->busnr, port->path); 465 466 QTAILQ_REMOVE(&bus->used, port, next); 467 bus->nused--; 468 469 dev->port = NULL; 470 port->dev = NULL; 471 472 QTAILQ_INSERT_TAIL(&bus->free, port, next); 473 bus->nfree++; 474 } 475 476 static void usb_mask_to_str(char *dest, size_t size, 477 unsigned int speedmask) 478 { 479 static const struct { 480 unsigned int mask; 481 const char *name; 482 } speeds[] = { 483 { .mask = USB_SPEED_MASK_FULL, .name = "full" }, 484 { .mask = USB_SPEED_MASK_HIGH, .name = "high" }, 485 { .mask = USB_SPEED_MASK_SUPER, .name = "super" }, 486 }; 487 int i, pos = 0; 488 489 for (i = 0; i < ARRAY_SIZE(speeds); i++) { 490 if (speeds[i].mask & speedmask) { 491 pos += snprintf(dest + pos, size - pos, "%s%s", 492 pos ? "+" : "", 493 speeds[i].name); 494 } 495 } 496 497 if (pos == 0) { 498 snprintf(dest, size, "unknown"); 499 } 500 } 501 502 void usb_check_attach(USBDevice *dev, Error **errp) 503 { 504 USBBus *bus = usb_bus_from_device(dev); 505 USBPort *port = dev->port; 506 char devspeed[32], portspeed[32]; 507 508 assert(port != NULL); 509 assert(!dev->attached); 510 usb_mask_to_str(devspeed, sizeof(devspeed), dev->speedmask); 511 usb_mask_to_str(portspeed, sizeof(portspeed), port->speedmask); 512 trace_usb_port_attach(bus->busnr, port->path, 513 devspeed, portspeed); 514 515 if (!(port->speedmask & dev->speedmask)) { 516 error_setg(errp, "Warning: speed mismatch trying to attach" 517 " usb device \"%s\" (%s speed)" 518 " to bus \"%s\", port \"%s\" (%s speed)", 519 dev->product_desc, devspeed, 520 bus->qbus.name, port->path, portspeed); 521 return; 522 } 523 } 524 525 void usb_device_attach(USBDevice *dev, Error **errp) 526 { 527 USBPort *port = dev->port; 528 Error *local_err = NULL; 529 530 usb_check_attach(dev, &local_err); 531 if (local_err) { 532 error_propagate(errp, local_err); 533 return; 534 } 535 536 dev->attached = true; 537 usb_attach(port); 538 } 539 540 int usb_device_detach(USBDevice *dev) 541 { 542 USBBus *bus = usb_bus_from_device(dev); 543 USBPort *port = dev->port; 544 545 assert(port != NULL); 546 assert(dev->attached); 547 trace_usb_port_detach(bus->busnr, port->path); 548 549 usb_detach(port); 550 dev->attached = false; 551 return 0; 552 } 553 554 static const char *usb_speed(unsigned int speed) 555 { 556 static const char *txt[] = { 557 [ USB_SPEED_LOW ] = "1.5", 558 [ USB_SPEED_FULL ] = "12", 559 [ USB_SPEED_HIGH ] = "480", 560 [ USB_SPEED_SUPER ] = "5000", 561 }; 562 if (speed >= ARRAY_SIZE(txt)) 563 return "?"; 564 return txt[speed]; 565 } 566 567 static void usb_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent) 568 { 569 USBDevice *dev = USB_DEVICE(qdev); 570 USBBus *bus = usb_bus_from_device(dev); 571 572 monitor_printf(mon, "%*saddr %d.%d, port %s, speed %s, name %s%s\n", 573 indent, "", bus->busnr, dev->addr, 574 dev->port ? dev->port->path : "-", 575 usb_speed(dev->speed), dev->product_desc, 576 dev->attached ? ", attached" : ""); 577 } 578 579 static char *usb_get_dev_path(DeviceState *qdev) 580 { 581 USBDevice *dev = USB_DEVICE(qdev); 582 DeviceState *hcd = qdev->parent_bus->parent; 583 char *id = NULL; 584 585 if (dev->flags & (1 << USB_DEV_FLAG_FULL_PATH)) { 586 id = qdev_get_dev_path(hcd); 587 } 588 if (id) { 589 char *ret = g_strdup_printf("%s/%s", id, dev->port->path); 590 g_free(id); 591 return ret; 592 } else { 593 return g_strdup(dev->port->path); 594 } 595 } 596 597 static char *usb_get_fw_dev_path(DeviceState *qdev) 598 { 599 USBDevice *dev = USB_DEVICE(qdev); 600 char *fw_path, *in; 601 ssize_t pos = 0, fw_len; 602 long nr; 603 604 fw_len = 32 + strlen(dev->port->path) * 6; 605 fw_path = g_malloc(fw_len); 606 in = dev->port->path; 607 while (fw_len - pos > 0) { 608 nr = strtol(in, &in, 10); 609 if (in[0] == '.') { 610 /* some hub between root port and device */ 611 pos += snprintf(fw_path + pos, fw_len - pos, "hub@%lx/", nr); 612 in++; 613 } else { 614 /* the device itself */ 615 pos += snprintf(fw_path + pos, fw_len - pos, "%s@%lx", 616 qdev_fw_name(qdev), nr); 617 break; 618 } 619 } 620 return fw_path; 621 } 622 623 void hmp_info_usb(Monitor *mon, const QDict *qdict) 624 { 625 USBBus *bus; 626 USBDevice *dev; 627 USBPort *port; 628 629 if (QTAILQ_EMPTY(&busses)) { 630 monitor_printf(mon, "USB support not enabled\n"); 631 return; 632 } 633 634 QTAILQ_FOREACH(bus, &busses, next) { 635 QTAILQ_FOREACH(port, &bus->used, next) { 636 dev = port->dev; 637 if (!dev) 638 continue; 639 monitor_printf(mon, " Device %d.%d, Port %s, Speed %s Mb/s, " 640 "Product %s%s%s\n", 641 bus->busnr, dev->addr, port->path, 642 usb_speed(dev->speed), dev->product_desc, 643 dev->qdev.id ? ", ID: " : "", 644 dev->qdev.id ?: ""); 645 } 646 } 647 } 648 649 /* handle legacy -usbdevice cmd line option */ 650 USBDevice *usbdevice_create(const char *cmdline) 651 { 652 USBBus *bus = usb_bus_find(-1 /* any */); 653 LegacyUSBFactory *f = NULL; 654 Error *err = NULL; 655 GSList *i; 656 char driver[32]; 657 const char *params; 658 int len; 659 USBDevice *dev; 660 661 params = strchr(cmdline,':'); 662 if (params) { 663 params++; 664 len = params - cmdline; 665 if (len > sizeof(driver)) 666 len = sizeof(driver); 667 pstrcpy(driver, len, cmdline); 668 } else { 669 params = ""; 670 pstrcpy(driver, sizeof(driver), cmdline); 671 } 672 673 for (i = legacy_usb_factory; i; i = i->next) { 674 f = i->data; 675 if (strcmp(f->usbdevice_name, driver) == 0) { 676 break; 677 } 678 } 679 if (i == NULL) { 680 #if 0 681 /* no error because some drivers are not converted (yet) */ 682 error_report("usbdevice %s not found", driver); 683 #endif 684 return NULL; 685 } 686 687 if (!bus) { 688 error_report("Error: no usb bus to attach usbdevice %s, " 689 "please try -machine usb=on and check that " 690 "the machine model supports USB", driver); 691 return NULL; 692 } 693 694 if (f->usbdevice_init) { 695 dev = f->usbdevice_init(params); 696 } else { 697 if (*params) { 698 error_report("usbdevice %s accepts no params", driver); 699 return NULL; 700 } 701 dev = usb_new(f->name); 702 } 703 if (!dev) { 704 error_report("Failed to create USB device '%s'", f->name); 705 return NULL; 706 } 707 usb_realize_and_unref(dev, bus, &err); 708 if (err) { 709 error_reportf_err(err, "Failed to initialize USB device '%s': ", 710 f->name); 711 object_unparent(OBJECT(dev)); 712 return NULL; 713 } 714 return dev; 715 } 716 717 static bool usb_get_attached(Object *obj, Error **errp) 718 { 719 USBDevice *dev = USB_DEVICE(obj); 720 721 return dev->attached; 722 } 723 724 static void usb_set_attached(Object *obj, bool value, Error **errp) 725 { 726 USBDevice *dev = USB_DEVICE(obj); 727 Error *err = NULL; 728 729 if (dev->attached == value) { 730 return; 731 } 732 733 if (value) { 734 usb_device_attach(dev, &err); 735 error_propagate(errp, err); 736 } else { 737 usb_device_detach(dev); 738 } 739 } 740 741 static void usb_device_instance_init(Object *obj) 742 { 743 USBDevice *dev = USB_DEVICE(obj); 744 USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev); 745 746 if (klass->attached_settable) { 747 object_property_add_bool(obj, "attached", 748 usb_get_attached, usb_set_attached); 749 } else { 750 object_property_add_bool(obj, "attached", 751 usb_get_attached, NULL); 752 } 753 } 754 755 static void usb_device_class_init(ObjectClass *klass, void *data) 756 { 757 DeviceClass *k = DEVICE_CLASS(klass); 758 k->bus_type = TYPE_USB_BUS; 759 k->realize = usb_qdev_realize; 760 k->unrealize = usb_qdev_unrealize; 761 device_class_set_props(k, usb_props); 762 } 763 764 static const TypeInfo usb_device_type_info = { 765 .name = TYPE_USB_DEVICE, 766 .parent = TYPE_DEVICE, 767 .instance_size = sizeof(USBDevice), 768 .instance_init = usb_device_instance_init, 769 .abstract = true, 770 .class_size = sizeof(USBDeviceClass), 771 .class_init = usb_device_class_init, 772 }; 773 774 static void usb_register_types(void) 775 { 776 type_register_static(&usb_bus_info); 777 type_register_static(&usb_device_type_info); 778 } 779 780 type_init(usb_register_types) 781