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