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