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