xref: /openbmc/qemu/hw/usb/bus.c (revision 59a3a1c0)
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, Error **errp);
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, Error **errp)
134 {
135     USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
136 
137     if (klass->unrealize) {
138         klass->unrealize(dev, errp);
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, NULL);
269             error_propagate(errp, local_err);
270             return;
271         }
272     }
273 }
274 
275 static void usb_qdev_unrealize(DeviceState *qdev, Error **errp)
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, errp);
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)(USBBus *bus, 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)(USBBus *bus,
306                                                       const char *params))
307 {
308     if (usbdevice_name) {
309         LegacyUSBFactory *f = g_malloc0(sizeof(*f));
310         f->name = typename;
311         f->usbdevice_name = usbdevice_name;
312         f->usbdevice_init = usbdevice_init;
313         legacy_usb_factory = g_slist_append(legacy_usb_factory, f);
314     }
315 }
316 
317 USBDevice *usb_create(USBBus *bus, const char *name)
318 {
319     DeviceState *dev;
320 
321     dev = qdev_create(&bus->qbus, name);
322     return USB_DEVICE(dev);
323 }
324 
325 static USBDevice *usb_try_create_simple(USBBus *bus, const char *name,
326                                         Error **errp)
327 {
328     Error *err = NULL;
329     USBDevice *dev;
330 
331     dev = USB_DEVICE(qdev_try_create(&bus->qbus, name));
332     if (!dev) {
333         error_setg(errp, "Failed to create USB device '%s'", name);
334         return NULL;
335     }
336     object_property_set_bool(OBJECT(dev), true, "realized", &err);
337     if (err) {
338         error_propagate_prepend(errp, err,
339                                 "Failed to initialize USB device '%s': ",
340                                 name);
341         return NULL;
342     }
343     return dev;
344 }
345 
346 USBDevice *usb_create_simple(USBBus *bus, const char *name)
347 {
348     return usb_try_create_simple(bus, name, &error_abort);
349 }
350 
351 static void usb_fill_port(USBPort *port, void *opaque, int index,
352                           USBPortOps *ops, int speedmask)
353 {
354     port->opaque = opaque;
355     port->index = index;
356     port->ops = ops;
357     port->speedmask = speedmask;
358     usb_port_location(port, NULL, index + 1);
359 }
360 
361 void usb_register_port(USBBus *bus, USBPort *port, void *opaque, int index,
362                        USBPortOps *ops, int speedmask)
363 {
364     usb_fill_port(port, opaque, index, ops, speedmask);
365     QTAILQ_INSERT_TAIL(&bus->free, port, next);
366     bus->nfree++;
367 }
368 
369 void usb_register_companion(const char *masterbus, USBPort *ports[],
370                             uint32_t portcount, uint32_t firstport,
371                             void *opaque, USBPortOps *ops, int speedmask,
372                             Error **errp)
373 {
374     USBBus *bus;
375     int i;
376 
377     QTAILQ_FOREACH(bus, &busses, next) {
378         if (strcmp(bus->qbus.name, masterbus) == 0) {
379             break;
380         }
381     }
382 
383     if (!bus) {
384         error_setg(errp, "USB bus '%s' not found", masterbus);
385         return;
386     }
387     if (!bus->ops->register_companion) {
388         error_setg(errp, "Can't use USB bus '%s' as masterbus,"
389                    " it doesn't support companion controllers",
390                    masterbus);
391         return;
392     }
393 
394     for (i = 0; i < portcount; i++) {
395         usb_fill_port(ports[i], opaque, i, ops, speedmask);
396     }
397 
398     bus->ops->register_companion(bus, ports, portcount, firstport, errp);
399 }
400 
401 void usb_port_location(USBPort *downstream, USBPort *upstream, int portnr)
402 {
403     if (upstream) {
404         int l = snprintf(downstream->path, sizeof(downstream->path), "%s.%d",
405                          upstream->path, portnr);
406         /* Max string is nn.nn.nn.nn.nn, which fits in 16 bytes */
407         assert(l < sizeof(downstream->path));
408         downstream->hubcount = upstream->hubcount + 1;
409     } else {
410         snprintf(downstream->path, sizeof(downstream->path), "%d", portnr);
411         downstream->hubcount = 0;
412     }
413 }
414 
415 void usb_unregister_port(USBBus *bus, USBPort *port)
416 {
417     if (port->dev) {
418         object_unparent(OBJECT(port->dev));
419     }
420     QTAILQ_REMOVE(&bus->free, port, next);
421     bus->nfree--;
422 }
423 
424 void usb_claim_port(USBDevice *dev, Error **errp)
425 {
426     USBBus *bus = usb_bus_from_device(dev);
427     USBPort *port;
428 
429     assert(dev->port == NULL);
430 
431     if (dev->port_path) {
432         QTAILQ_FOREACH(port, &bus->free, next) {
433             if (strcmp(port->path, dev->port_path) == 0) {
434                 break;
435             }
436         }
437         if (port == NULL) {
438             error_setg(errp, "usb port %s (bus %s) not found (in use?)",
439                        dev->port_path, bus->qbus.name);
440             return;
441         }
442     } else {
443         if (bus->nfree == 1 && strcmp(object_get_typename(OBJECT(dev)), "usb-hub") != 0) {
444             /* Create a new hub and chain it on */
445             usb_try_create_simple(bus, "usb-hub", NULL);
446         }
447         if (bus->nfree == 0) {
448             error_setg(errp, "tried to attach usb device %s to a bus "
449                        "with no free ports", dev->product_desc);
450             return;
451         }
452         port = QTAILQ_FIRST(&bus->free);
453     }
454     trace_usb_port_claim(bus->busnr, port->path);
455 
456     QTAILQ_REMOVE(&bus->free, port, next);
457     bus->nfree--;
458 
459     dev->port = port;
460     port->dev = dev;
461 
462     QTAILQ_INSERT_TAIL(&bus->used, port, next);
463     bus->nused++;
464 }
465 
466 void usb_release_port(USBDevice *dev)
467 {
468     USBBus *bus = usb_bus_from_device(dev);
469     USBPort *port = dev->port;
470 
471     assert(port != NULL);
472     trace_usb_port_release(bus->busnr, port->path);
473 
474     QTAILQ_REMOVE(&bus->used, port, next);
475     bus->nused--;
476 
477     dev->port = NULL;
478     port->dev = NULL;
479 
480     QTAILQ_INSERT_TAIL(&bus->free, port, next);
481     bus->nfree++;
482 }
483 
484 static void usb_mask_to_str(char *dest, size_t size,
485                             unsigned int speedmask)
486 {
487     static const struct {
488         unsigned int mask;
489         const char *name;
490     } speeds[] = {
491         { .mask = USB_SPEED_MASK_FULL,  .name = "full"  },
492         { .mask = USB_SPEED_MASK_HIGH,  .name = "high"  },
493         { .mask = USB_SPEED_MASK_SUPER, .name = "super" },
494     };
495     int i, pos = 0;
496 
497     for (i = 0; i < ARRAY_SIZE(speeds); i++) {
498         if (speeds[i].mask & speedmask) {
499             pos += snprintf(dest + pos, size - pos, "%s%s",
500                             pos ? "+" : "",
501                             speeds[i].name);
502         }
503     }
504 
505     if (pos == 0) {
506         snprintf(dest, size, "unknown");
507     }
508 }
509 
510 void usb_check_attach(USBDevice *dev, Error **errp)
511 {
512     USBBus *bus = usb_bus_from_device(dev);
513     USBPort *port = dev->port;
514     char devspeed[32], portspeed[32];
515 
516     assert(port != NULL);
517     assert(!dev->attached);
518     usb_mask_to_str(devspeed, sizeof(devspeed), dev->speedmask);
519     usb_mask_to_str(portspeed, sizeof(portspeed), port->speedmask);
520     trace_usb_port_attach(bus->busnr, port->path,
521                           devspeed, portspeed);
522 
523     if (!(port->speedmask & dev->speedmask)) {
524         error_setg(errp, "Warning: speed mismatch trying to attach"
525                    " usb device \"%s\" (%s speed)"
526                    " to bus \"%s\", port \"%s\" (%s speed)",
527                    dev->product_desc, devspeed,
528                    bus->qbus.name, port->path, portspeed);
529         return;
530     }
531 }
532 
533 void usb_device_attach(USBDevice *dev, Error **errp)
534 {
535     USBPort *port = dev->port;
536     Error *local_err = NULL;
537 
538     usb_check_attach(dev, &local_err);
539     if (local_err) {
540         error_propagate(errp, local_err);
541         return;
542     }
543 
544     dev->attached = true;
545     usb_attach(port);
546 }
547 
548 int usb_device_detach(USBDevice *dev)
549 {
550     USBBus *bus = usb_bus_from_device(dev);
551     USBPort *port = dev->port;
552 
553     assert(port != NULL);
554     assert(dev->attached);
555     trace_usb_port_detach(bus->busnr, port->path);
556 
557     usb_detach(port);
558     dev->attached = false;
559     return 0;
560 }
561 
562 static const char *usb_speed(unsigned int speed)
563 {
564     static const char *txt[] = {
565         [ USB_SPEED_LOW  ] = "1.5",
566         [ USB_SPEED_FULL ] = "12",
567         [ USB_SPEED_HIGH ] = "480",
568         [ USB_SPEED_SUPER ] = "5000",
569     };
570     if (speed >= ARRAY_SIZE(txt))
571         return "?";
572     return txt[speed];
573 }
574 
575 static void usb_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent)
576 {
577     USBDevice *dev = USB_DEVICE(qdev);
578     USBBus *bus = usb_bus_from_device(dev);
579 
580     monitor_printf(mon, "%*saddr %d.%d, port %s, speed %s, name %s%s\n",
581                    indent, "", bus->busnr, dev->addr,
582                    dev->port ? dev->port->path : "-",
583                    usb_speed(dev->speed), dev->product_desc,
584                    dev->attached ? ", attached" : "");
585 }
586 
587 static char *usb_get_dev_path(DeviceState *qdev)
588 {
589     USBDevice *dev = USB_DEVICE(qdev);
590     DeviceState *hcd = qdev->parent_bus->parent;
591     char *id = NULL;
592 
593     if (dev->flags & (1 << USB_DEV_FLAG_FULL_PATH)) {
594         id = qdev_get_dev_path(hcd);
595     }
596     if (id) {
597         char *ret = g_strdup_printf("%s/%s", id, dev->port->path);
598         g_free(id);
599         return ret;
600     } else {
601         return g_strdup(dev->port->path);
602     }
603 }
604 
605 static char *usb_get_fw_dev_path(DeviceState *qdev)
606 {
607     USBDevice *dev = USB_DEVICE(qdev);
608     char *fw_path, *in;
609     ssize_t pos = 0, fw_len;
610     long nr;
611 
612     fw_len = 32 + strlen(dev->port->path) * 6;
613     fw_path = g_malloc(fw_len);
614     in = dev->port->path;
615     while (fw_len - pos > 0) {
616         nr = strtol(in, &in, 10);
617         if (in[0] == '.') {
618             /* some hub between root port and device */
619             pos += snprintf(fw_path + pos, fw_len - pos, "hub@%lx/", nr);
620             in++;
621         } else {
622             /* the device itself */
623             pos += snprintf(fw_path + pos, fw_len - pos, "%s@%lx",
624                             qdev_fw_name(qdev), nr);
625             break;
626         }
627     }
628     return fw_path;
629 }
630 
631 void hmp_info_usb(Monitor *mon, const QDict *qdict)
632 {
633     USBBus *bus;
634     USBDevice *dev;
635     USBPort *port;
636 
637     if (QTAILQ_EMPTY(&busses)) {
638         monitor_printf(mon, "USB support not enabled\n");
639         return;
640     }
641 
642     QTAILQ_FOREACH(bus, &busses, next) {
643         QTAILQ_FOREACH(port, &bus->used, next) {
644             dev = port->dev;
645             if (!dev)
646                 continue;
647             monitor_printf(mon, "  Device %d.%d, Port %s, Speed %s Mb/s, "
648                            "Product %s%s%s\n",
649                            bus->busnr, dev->addr, port->path,
650                            usb_speed(dev->speed), dev->product_desc,
651                            dev->qdev.id ? ", ID: " : "",
652                            dev->qdev.id ?: "");
653         }
654     }
655 }
656 
657 /* handle legacy -usbdevice cmd line option */
658 USBDevice *usbdevice_create(const char *cmdline)
659 {
660     USBBus *bus = usb_bus_find(-1 /* any */);
661     LegacyUSBFactory *f = NULL;
662     Error *err = NULL;
663     GSList *i;
664     char driver[32];
665     const char *params;
666     int len;
667     USBDevice *dev;
668 
669     params = strchr(cmdline,':');
670     if (params) {
671         params++;
672         len = params - cmdline;
673         if (len > sizeof(driver))
674             len = sizeof(driver);
675         pstrcpy(driver, len, cmdline);
676     } else {
677         params = "";
678         pstrcpy(driver, sizeof(driver), cmdline);
679     }
680 
681     for (i = legacy_usb_factory; i; i = i->next) {
682         f = i->data;
683         if (strcmp(f->usbdevice_name, driver) == 0) {
684             break;
685         }
686     }
687     if (i == NULL) {
688 #if 0
689         /* no error because some drivers are not converted (yet) */
690         error_report("usbdevice %s not found", driver);
691 #endif
692         return NULL;
693     }
694 
695     if (!bus) {
696         error_report("Error: no usb bus to attach usbdevice %s, "
697                      "please try -machine usb=on and check that "
698                      "the machine model supports USB", driver);
699         return NULL;
700     }
701 
702     if (f->usbdevice_init) {
703         dev = f->usbdevice_init(bus, params);
704     } else {
705         if (*params) {
706             error_report("usbdevice %s accepts no params", driver);
707             return NULL;
708         }
709         dev = usb_create(bus, f->name);
710     }
711     if (!dev) {
712         error_report("Failed to create USB device '%s'", f->name);
713         return NULL;
714     }
715     object_property_set_bool(OBJECT(dev), true, "realized", &err);
716     if (err) {
717         error_reportf_err(err, "Failed to initialize USB device '%s': ",
718                           f->name);
719         object_unparent(OBJECT(dev));
720         return NULL;
721     }
722     return dev;
723 }
724 
725 static bool usb_get_attached(Object *obj, Error **errp)
726 {
727     USBDevice *dev = USB_DEVICE(obj);
728 
729     return dev->attached;
730 }
731 
732 static void usb_set_attached(Object *obj, bool value, Error **errp)
733 {
734     USBDevice *dev = USB_DEVICE(obj);
735     Error *err = NULL;
736 
737     if (dev->attached == value) {
738         return;
739     }
740 
741     if (value) {
742         usb_device_attach(dev, &err);
743         error_propagate(errp, err);
744     } else {
745         usb_device_detach(dev);
746     }
747 }
748 
749 static void usb_device_instance_init(Object *obj)
750 {
751     USBDevice *dev = USB_DEVICE(obj);
752     USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
753 
754     if (klass->attached_settable) {
755         object_property_add_bool(obj, "attached",
756                                  usb_get_attached, usb_set_attached,
757                                  NULL);
758     } else {
759         object_property_add_bool(obj, "attached",
760                                  usb_get_attached, NULL,
761                                  NULL);
762     }
763 }
764 
765 static void usb_device_class_init(ObjectClass *klass, void *data)
766 {
767     DeviceClass *k = DEVICE_CLASS(klass);
768     k->bus_type = TYPE_USB_BUS;
769     k->realize  = usb_qdev_realize;
770     k->unrealize = usb_qdev_unrealize;
771     k->props    = usb_props;
772 }
773 
774 static const TypeInfo usb_device_type_info = {
775     .name = TYPE_USB_DEVICE,
776     .parent = TYPE_DEVICE,
777     .instance_size = sizeof(USBDevice),
778     .instance_init = usb_device_instance_init,
779     .abstract = true,
780     .class_size = sizeof(USBDeviceClass),
781     .class_init = usb_device_class_init,
782 };
783 
784 static void usb_register_types(void)
785 {
786     type_register_static(&usb_bus_info);
787     type_register_static(&usb_device_type_info);
788 }
789 
790 type_init(usb_register_types)
791