xref: /openbmc/qemu/hw/usb/bus.c (revision 6cc9d67c6f682cf04eea2d6e64a252b63a7eccdf)
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_STRING("pcap", USBDevice, pcap_filename),
27      DEFINE_PROP_END_OF_LIST()
28  };
29  
30  static void usb_bus_class_init(ObjectClass *klass, void *data)
31  {
32      BusClass *k = BUS_CLASS(klass);
33      HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass);
34  
35      k->print_dev = usb_bus_dev_print;
36      k->get_dev_path = usb_get_dev_path;
37      k->get_fw_dev_path = usb_get_fw_dev_path;
38      hc->unplug = qdev_simple_device_unplug_cb;
39  }
40  
41  static const TypeInfo usb_bus_info = {
42      .name = TYPE_USB_BUS,
43      .parent = TYPE_BUS,
44      .instance_size = sizeof(USBBus),
45      .class_init = usb_bus_class_init,
46      .interfaces = (InterfaceInfo[]) {
47          { TYPE_HOTPLUG_HANDLER },
48          { }
49      }
50  };
51  
52  static int next_usb_bus = 0;
53  static QTAILQ_HEAD(, USBBus) busses = QTAILQ_HEAD_INITIALIZER(busses);
54  
55  static int usb_device_post_load(void *opaque, int version_id)
56  {
57      USBDevice *dev = opaque;
58  
59      if (dev->state == USB_STATE_NOTATTACHED) {
60          dev->attached = false;
61      } else {
62          dev->attached = true;
63      }
64      return 0;
65  }
66  
67  const VMStateDescription vmstate_usb_device = {
68      .name = "USBDevice",
69      .version_id = 1,
70      .minimum_version_id = 1,
71      .post_load = usb_device_post_load,
72      .fields = (VMStateField[]) {
73          VMSTATE_UINT8(addr, USBDevice),
74          VMSTATE_INT32(state, USBDevice),
75          VMSTATE_INT32(remote_wakeup, USBDevice),
76          VMSTATE_INT32(setup_state, USBDevice),
77          VMSTATE_INT32(setup_len, USBDevice),
78          VMSTATE_INT32(setup_index, USBDevice),
79          VMSTATE_UINT8_ARRAY(setup_buf, USBDevice, 8),
80          VMSTATE_END_OF_LIST(),
81      }
82  };
83  
84  void usb_bus_new(USBBus *bus, size_t bus_size,
85                   USBBusOps *ops, DeviceState *host)
86  {
87      qbus_create_inplace(bus, bus_size, TYPE_USB_BUS, host, NULL);
88      qbus_set_bus_hotplug_handler(BUS(bus));
89      bus->ops = ops;
90      bus->busnr = next_usb_bus++;
91      QTAILQ_INIT(&bus->free);
92      QTAILQ_INIT(&bus->used);
93      QTAILQ_INSERT_TAIL(&busses, bus, next);
94  }
95  
96  void usb_bus_release(USBBus *bus)
97  {
98      assert(next_usb_bus > 0);
99  
100      QTAILQ_REMOVE(&busses, bus, next);
101  }
102  
103  USBBus *usb_bus_find(int busnr)
104  {
105      USBBus *bus;
106  
107      if (-1 == busnr)
108          return QTAILQ_FIRST(&busses);
109      QTAILQ_FOREACH(bus, &busses, next) {
110          if (bus->busnr == busnr)
111              return bus;
112      }
113      return NULL;
114  }
115  
116  static void usb_device_realize(USBDevice *dev, Error **errp)
117  {
118      USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
119  
120      if (klass->realize) {
121          klass->realize(dev, errp);
122      }
123  }
124  
125  USBDevice *usb_device_find_device(USBDevice *dev, uint8_t addr)
126  {
127      USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
128      if (klass->find_device) {
129          return klass->find_device(dev, addr);
130      }
131      return NULL;
132  }
133  
134  static void usb_device_unrealize(USBDevice *dev)
135  {
136      USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
137  
138      if (klass->unrealize) {
139          klass->unrealize(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);
270              error_propagate(errp, local_err);
271              return;
272          }
273      }
274  
275      if (dev->pcap_filename) {
276          int fd = qemu_open_old(dev->pcap_filename, O_CREAT | O_WRONLY | O_TRUNC, 0666);
277          if (fd < 0) {
278              error_setg(errp, "open %s failed", dev->pcap_filename);
279              usb_qdev_unrealize(qdev);
280              return;
281          }
282          dev->pcap = fdopen(fd, "w");
283          usb_pcap_init(dev->pcap);
284      }
285  }
286  
287  static void usb_qdev_unrealize(DeviceState *qdev)
288  {
289      USBDevice *dev = USB_DEVICE(qdev);
290      USBDescString *s, *next;
291  
292      QLIST_FOREACH_SAFE(s, &dev->strings, next, next) {
293          QLIST_REMOVE(s, next);
294          g_free(s->str);
295          g_free(s);
296      }
297  
298      if (dev->pcap) {
299          fclose(dev->pcap);
300      }
301  
302      if (dev->attached) {
303          usb_device_detach(dev);
304      }
305      usb_device_unrealize(dev);
306      if (dev->port) {
307          usb_release_port(dev);
308      }
309  }
310  
311  typedef struct LegacyUSBFactory
312  {
313      const char *name;
314      const char *usbdevice_name;
315      USBDevice *(*usbdevice_init)(const char *params);
316  } LegacyUSBFactory;
317  
318  static GSList *legacy_usb_factory;
319  
320  void usb_legacy_register(const char *typename, const char *usbdevice_name,
321                           USBDevice *(*usbdevice_init)(const char *params))
322  {
323      if (usbdevice_name) {
324          LegacyUSBFactory *f = g_malloc0(sizeof(*f));
325          f->name = typename;
326          f->usbdevice_name = usbdevice_name;
327          f->usbdevice_init = usbdevice_init;
328          legacy_usb_factory = g_slist_append(legacy_usb_factory, f);
329      }
330  }
331  
332  USBDevice *usb_new(const char *name)
333  {
334      return USB_DEVICE(qdev_new(name));
335  }
336  
337  static USBDevice *usb_try_new(const char *name)
338  {
339      return USB_DEVICE(qdev_try_new(name));
340  }
341  
342  bool usb_realize_and_unref(USBDevice *dev, USBBus *bus, Error **errp)
343  {
344      return qdev_realize_and_unref(&dev->qdev, &bus->qbus, errp);
345  }
346  
347  USBDevice *usb_create_simple(USBBus *bus, const char *name)
348  {
349      USBDevice *dev = usb_new(name);
350  
351      usb_realize_and_unref(dev, bus, &error_abort);
352      return dev;
353  }
354  
355  static void usb_fill_port(USBPort *port, void *opaque, int index,
356                            USBPortOps *ops, int speedmask)
357  {
358      port->opaque = opaque;
359      port->index = index;
360      port->ops = ops;
361      port->speedmask = speedmask;
362      usb_port_location(port, NULL, index + 1);
363  }
364  
365  void usb_register_port(USBBus *bus, USBPort *port, void *opaque, int index,
366                         USBPortOps *ops, int speedmask)
367  {
368      usb_fill_port(port, opaque, index, ops, speedmask);
369      QTAILQ_INSERT_TAIL(&bus->free, port, next);
370      bus->nfree++;
371  }
372  
373  void usb_register_companion(const char *masterbus, USBPort *ports[],
374                              uint32_t portcount, uint32_t firstport,
375                              void *opaque, USBPortOps *ops, int speedmask,
376                              Error **errp)
377  {
378      USBBus *bus;
379      int i;
380  
381      QTAILQ_FOREACH(bus, &busses, next) {
382          if (strcmp(bus->qbus.name, masterbus) == 0) {
383              break;
384          }
385      }
386  
387      if (!bus) {
388          error_setg(errp, "USB bus '%s' not found", masterbus);
389          return;
390      }
391      if (!bus->ops->register_companion) {
392          error_setg(errp, "Can't use USB bus '%s' as masterbus,"
393                     " it doesn't support companion controllers",
394                     masterbus);
395          return;
396      }
397  
398      for (i = 0; i < portcount; i++) {
399          usb_fill_port(ports[i], opaque, i, ops, speedmask);
400      }
401  
402      bus->ops->register_companion(bus, ports, portcount, firstport, errp);
403  }
404  
405  void usb_port_location(USBPort *downstream, USBPort *upstream, int portnr)
406  {
407      if (upstream) {
408          int l = snprintf(downstream->path, sizeof(downstream->path), "%s.%d",
409                           upstream->path, portnr);
410          /* Max string is nn.nn.nn.nn.nn, which fits in 16 bytes */
411          assert(l < sizeof(downstream->path));
412          downstream->hubcount = upstream->hubcount + 1;
413      } else {
414          snprintf(downstream->path, sizeof(downstream->path), "%d", portnr);
415          downstream->hubcount = 0;
416      }
417  }
418  
419  void usb_unregister_port(USBBus *bus, USBPort *port)
420  {
421      if (port->dev) {
422          object_unparent(OBJECT(port->dev));
423      }
424      QTAILQ_REMOVE(&bus->free, port, next);
425      bus->nfree--;
426  }
427  
428  void usb_claim_port(USBDevice *dev, Error **errp)
429  {
430      USBBus *bus = usb_bus_from_device(dev);
431      USBPort *port;
432      USBDevice *hub;
433  
434      assert(dev->port == NULL);
435  
436      if (dev->port_path) {
437          QTAILQ_FOREACH(port, &bus->free, next) {
438              if (strcmp(port->path, dev->port_path) == 0) {
439                  break;
440              }
441          }
442          if (port == NULL) {
443              error_setg(errp, "usb port %s (bus %s) not found (in use?)",
444                         dev->port_path, bus->qbus.name);
445              return;
446          }
447      } else {
448          if (bus->nfree == 1 && strcmp(object_get_typename(OBJECT(dev)), "usb-hub") != 0) {
449              /* Create a new hub and chain it on */
450              hub = usb_try_new("usb-hub");
451              if (hub) {
452                  usb_realize_and_unref(hub, bus, NULL);
453              }
454          }
455          if (bus->nfree == 0) {
456              error_setg(errp, "tried to attach usb device %s to a bus "
457                         "with no free ports", dev->product_desc);
458              return;
459          }
460          port = QTAILQ_FIRST(&bus->free);
461      }
462      trace_usb_port_claim(bus->busnr, port->path);
463  
464      QTAILQ_REMOVE(&bus->free, port, next);
465      bus->nfree--;
466  
467      dev->port = port;
468      port->dev = dev;
469  
470      QTAILQ_INSERT_TAIL(&bus->used, port, next);
471      bus->nused++;
472  }
473  
474  void usb_release_port(USBDevice *dev)
475  {
476      USBBus *bus = usb_bus_from_device(dev);
477      USBPort *port = dev->port;
478  
479      assert(port != NULL);
480      trace_usb_port_release(bus->busnr, port->path);
481  
482      QTAILQ_REMOVE(&bus->used, port, next);
483      bus->nused--;
484  
485      dev->port = NULL;
486      port->dev = NULL;
487  
488      QTAILQ_INSERT_TAIL(&bus->free, port, next);
489      bus->nfree++;
490  }
491  
492  static void usb_mask_to_str(char *dest, size_t size,
493                              unsigned int speedmask)
494  {
495      static const struct {
496          unsigned int mask;
497          const char *name;
498      } speeds[] = {
499          { .mask = USB_SPEED_MASK_FULL,  .name = "full"  },
500          { .mask = USB_SPEED_MASK_HIGH,  .name = "high"  },
501          { .mask = USB_SPEED_MASK_SUPER, .name = "super" },
502      };
503      int i, pos = 0;
504  
505      for (i = 0; i < ARRAY_SIZE(speeds); i++) {
506          if (speeds[i].mask & speedmask) {
507              pos += snprintf(dest + pos, size - pos, "%s%s",
508                              pos ? "+" : "",
509                              speeds[i].name);
510          }
511      }
512  
513      if (pos == 0) {
514          snprintf(dest, size, "unknown");
515      }
516  }
517  
518  void usb_check_attach(USBDevice *dev, Error **errp)
519  {
520      USBBus *bus = usb_bus_from_device(dev);
521      USBPort *port = dev->port;
522      char devspeed[32], portspeed[32];
523  
524      assert(port != NULL);
525      assert(!dev->attached);
526      usb_mask_to_str(devspeed, sizeof(devspeed), dev->speedmask);
527      usb_mask_to_str(portspeed, sizeof(portspeed), port->speedmask);
528      trace_usb_port_attach(bus->busnr, port->path,
529                            devspeed, portspeed);
530  
531      if (!(port->speedmask & dev->speedmask)) {
532          error_setg(errp, "Warning: speed mismatch trying to attach"
533                     " usb device \"%s\" (%s speed)"
534                     " to bus \"%s\", port \"%s\" (%s speed)",
535                     dev->product_desc, devspeed,
536                     bus->qbus.name, port->path, portspeed);
537          return;
538      }
539  }
540  
541  void usb_device_attach(USBDevice *dev, Error **errp)
542  {
543      USBPort *port = dev->port;
544      Error *local_err = NULL;
545  
546      usb_check_attach(dev, &local_err);
547      if (local_err) {
548          error_propagate(errp, local_err);
549          return;
550      }
551  
552      dev->attached = true;
553      usb_attach(port);
554  }
555  
556  int usb_device_detach(USBDevice *dev)
557  {
558      USBBus *bus = usb_bus_from_device(dev);
559      USBPort *port = dev->port;
560  
561      assert(port != NULL);
562      assert(dev->attached);
563      trace_usb_port_detach(bus->busnr, port->path);
564  
565      usb_detach(port);
566      dev->attached = false;
567      return 0;
568  }
569  
570  static const char *usb_speed(unsigned int speed)
571  {
572      static const char *txt[] = {
573          [ USB_SPEED_LOW  ] = "1.5",
574          [ USB_SPEED_FULL ] = "12",
575          [ USB_SPEED_HIGH ] = "480",
576          [ USB_SPEED_SUPER ] = "5000",
577      };
578      if (speed >= ARRAY_SIZE(txt))
579          return "?";
580      return txt[speed];
581  }
582  
583  static void usb_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent)
584  {
585      USBDevice *dev = USB_DEVICE(qdev);
586      USBBus *bus = usb_bus_from_device(dev);
587  
588      monitor_printf(mon, "%*saddr %d.%d, port %s, speed %s, name %s%s\n",
589                     indent, "", bus->busnr, dev->addr,
590                     dev->port ? dev->port->path : "-",
591                     usb_speed(dev->speed), dev->product_desc,
592                     dev->attached ? ", attached" : "");
593  }
594  
595  static char *usb_get_dev_path(DeviceState *qdev)
596  {
597      USBDevice *dev = USB_DEVICE(qdev);
598      DeviceState *hcd = qdev->parent_bus->parent;
599      char *id = NULL;
600  
601      if (dev->flags & (1 << USB_DEV_FLAG_FULL_PATH)) {
602          id = qdev_get_dev_path(hcd);
603      }
604      if (id) {
605          char *ret = g_strdup_printf("%s/%s", id, dev->port->path);
606          g_free(id);
607          return ret;
608      } else {
609          return g_strdup(dev->port->path);
610      }
611  }
612  
613  static char *usb_get_fw_dev_path(DeviceState *qdev)
614  {
615      USBDevice *dev = USB_DEVICE(qdev);
616      char *fw_path, *in;
617      ssize_t pos = 0, fw_len;
618      long nr;
619  
620      fw_len = 32 + strlen(dev->port->path) * 6;
621      fw_path = g_malloc(fw_len);
622      in = dev->port->path;
623      while (fw_len - pos > 0) {
624          nr = strtol(in, &in, 10);
625          if (in[0] == '.') {
626              /* some hub between root port and device */
627              pos += snprintf(fw_path + pos, fw_len - pos, "hub@%lx/", nr);
628              in++;
629          } else {
630              /* the device itself */
631              snprintf(fw_path + pos, fw_len - pos, "%s@%lx",
632                       qdev_fw_name(qdev), nr);
633              break;
634          }
635      }
636      return fw_path;
637  }
638  
639  void hmp_info_usb(Monitor *mon, const QDict *qdict)
640  {
641      USBBus *bus;
642      USBDevice *dev;
643      USBPort *port;
644  
645      if (QTAILQ_EMPTY(&busses)) {
646          monitor_printf(mon, "USB support not enabled\n");
647          return;
648      }
649  
650      QTAILQ_FOREACH(bus, &busses, next) {
651          QTAILQ_FOREACH(port, &bus->used, next) {
652              dev = port->dev;
653              if (!dev)
654                  continue;
655              monitor_printf(mon, "  Device %d.%d, Port %s, Speed %s Mb/s, "
656                             "Product %s%s%s\n",
657                             bus->busnr, dev->addr, port->path,
658                             usb_speed(dev->speed), dev->product_desc,
659                             dev->qdev.id ? ", ID: " : "",
660                             dev->qdev.id ?: "");
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(params);
712      } else {
713          if (*params) {
714              error_report("usbdevice %s accepts no params", driver);
715              return NULL;
716          }
717          dev = usb_new(f->name);
718      }
719      if (!dev) {
720          error_report("Failed to create USB device '%s'", f->name);
721          return NULL;
722      }
723      if (!usb_realize_and_unref(dev, bus, &err)) {
724          error_reportf_err(err, "Failed to initialize USB device '%s': ",
725                            f->name);
726          object_unparent(OBJECT(dev));
727          return NULL;
728      }
729      return dev;
730  }
731  
732  static bool usb_get_attached(Object *obj, Error **errp)
733  {
734      USBDevice *dev = USB_DEVICE(obj);
735  
736      return dev->attached;
737  }
738  
739  static void usb_set_attached(Object *obj, bool value, Error **errp)
740  {
741      USBDevice *dev = USB_DEVICE(obj);
742  
743      if (dev->attached == value) {
744          return;
745      }
746  
747      if (value) {
748          usb_device_attach(dev, errp);
749      } else {
750          usb_device_detach(dev);
751      }
752  }
753  
754  static void usb_device_instance_init(Object *obj)
755  {
756      USBDevice *dev = USB_DEVICE(obj);
757      USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
758  
759      if (klass->attached_settable) {
760          object_property_add_bool(obj, "attached",
761                                   usb_get_attached, usb_set_attached);
762      } else {
763          object_property_add_bool(obj, "attached",
764                                   usb_get_attached, NULL);
765      }
766  }
767  
768  static void usb_device_class_init(ObjectClass *klass, void *data)
769  {
770      DeviceClass *k = DEVICE_CLASS(klass);
771      k->bus_type = TYPE_USB_BUS;
772      k->realize  = usb_qdev_realize;
773      k->unrealize = usb_qdev_unrealize;
774      device_class_set_props(k, usb_props);
775  }
776  
777  static const TypeInfo usb_device_type_info = {
778      .name = TYPE_USB_DEVICE,
779      .parent = TYPE_DEVICE,
780      .instance_size = sizeof(USBDevice),
781      .instance_init = usb_device_instance_init,
782      .abstract = true,
783      .class_size = sizeof(USBDeviceClass),
784      .class_init = usb_device_class_init,
785  };
786  
787  static void usb_register_types(void)
788  {
789      type_register_static(&usb_bus_info);
790      type_register_static(&usb_device_type_info);
791  }
792  
793  type_init(usb_register_types)
794