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