bus.c 16.0 KB
Newer Older
G
Gerd Hoffmann 已提交
1 2 3
#include "hw/hw.h"
#include "hw/usb.h"
#include "hw/qdev.h"
4
#include "sysemu/sysemu.h"
5
#include "monitor/monitor.h"
6
#include "trace.h"
7 8

static void usb_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent);
9 10

static char *usb_get_dev_path(DeviceState *dev);
11
static char *usb_get_fw_dev_path(DeviceState *qdev);
12
static int usb_qdev_exit(DeviceState *qdev);
13

14 15 16 17 18 19 20
static Property usb_props[] = {
    DEFINE_PROP_STRING("port", USBDevice, port_path),
    DEFINE_PROP_BIT("full-path", USBDevice, flags,
                    USB_DEV_FLAG_FULL_PATH, true),
    DEFINE_PROP_END_OF_LIST()
};

21 22 23 24 25 26 27 28 29 30 31 32 33 34
static void usb_bus_class_init(ObjectClass *klass, void *data)
{
    BusClass *k = BUS_CLASS(klass);

    k->print_dev = usb_bus_dev_print;
    k->get_dev_path = usb_get_dev_path;
    k->get_fw_dev_path = usb_get_fw_dev_path;
}

static const TypeInfo usb_bus_info = {
    .name = TYPE_USB_BUS,
    .parent = TYPE_BUS,
    .instance_size = sizeof(USBBus),
    .class_init = usb_bus_class_init,
35
};
36

37
static int next_usb_bus = 0;
B
Blue Swirl 已提交
38
static QTAILQ_HEAD(, USBBus) busses = QTAILQ_HEAD_INITIALIZER(busses);
39

40 41 42 43 44 45 46 47 48 49 50 51
static int usb_device_post_load(void *opaque, int version_id)
{
    USBDevice *dev = opaque;

    if (dev->state == USB_STATE_NOTATTACHED) {
        dev->attached = 0;
    } else {
        dev->attached = 1;
    }
    return 0;
}

G
Gerd Hoffmann 已提交
52 53 54 55
const VMStateDescription vmstate_usb_device = {
    .name = "USBDevice",
    .version_id = 1,
    .minimum_version_id = 1,
56
    .post_load = usb_device_post_load,
G
Gerd Hoffmann 已提交
57 58 59 60 61 62 63 64 65 66 67 68
    .fields = (VMStateField []) {
        VMSTATE_UINT8(addr, USBDevice),
        VMSTATE_INT32(state, USBDevice),
        VMSTATE_INT32(remote_wakeup, USBDevice),
        VMSTATE_INT32(setup_state, USBDevice),
        VMSTATE_INT32(setup_len, USBDevice),
        VMSTATE_INT32(setup_index, USBDevice),
        VMSTATE_UINT8_ARRAY(setup_buf, USBDevice, 8),
        VMSTATE_END_OF_LIST(),
    }
};

69
void 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++;
G
Gerd Hoffmann 已提交
74
    bus->qbus.allow_hotplug = 1; /* Yes, we can */
B
Blue Swirl 已提交
75 76 77
    QTAILQ_INIT(&bus->free);
    QTAILQ_INIT(&bus->used);
    QTAILQ_INSERT_TAIL(&busses, bus, next);
78 79 80 81 82 83 84
}

USBBus *usb_bus_find(int busnr)
{
    USBBus *bus;

    if (-1 == busnr)
B
Blue Swirl 已提交
85 86
        return QTAILQ_FIRST(&busses);
    QTAILQ_FOREACH(bus, &busses, next) {
87 88 89 90 91 92
        if (bus->busnr == busnr)
            return bus;
    }
    return NULL;
}

93 94 95 96 97 98 99 100 101
static int usb_device_init(USBDevice *dev)
{
    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
    if (klass->init) {
        return klass->init(dev);
    }
    return 0;
}

G
Gerd Hoffmann 已提交
102
USBDevice *usb_device_find_device(USBDevice *dev, uint8_t addr)
103 104
{
    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
G
Gerd Hoffmann 已提交
105 106
    if (klass->find_device) {
        return klass->find_device(dev, addr);
107
    }
G
Gerd Hoffmann 已提交
108
    return NULL;
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
}

static void usb_device_handle_destroy(USBDevice *dev)
{
    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
    if (klass->handle_destroy) {
        klass->handle_destroy(dev);
    }
}

void usb_device_cancel_packet(USBDevice *dev, USBPacket *p)
{
    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
    if (klass->cancel_packet) {
        klass->cancel_packet(dev, p);
    }
}

void usb_device_handle_attach(USBDevice *dev)
{
    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
    if (klass->handle_attach) {
        klass->handle_attach(dev);
    }
}

void usb_device_handle_reset(USBDevice *dev)
{
    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
    if (klass->handle_reset) {
        klass->handle_reset(dev);
    }
}

143 144
void usb_device_handle_control(USBDevice *dev, USBPacket *p, int request,
                               int value, int index, int length, uint8_t *data)
145 146 147
{
    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
    if (klass->handle_control) {
148
        klass->handle_control(dev, p, request, value, index, length, data);
149 150 151
    }
}

152
void usb_device_handle_data(USBDevice *dev, USBPacket *p)
153 154 155
{
    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
    if (klass->handle_data) {
156
        klass->handle_data(dev, p);
157 158 159 160 161 162 163 164 165 166 167 168
    }
}

const char *usb_device_get_product_desc(USBDevice *dev)
{
    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
    return klass->product_desc;
}

const USBDesc *usb_device_get_usb_desc(USBDevice *dev)
{
    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
169 170 171
    if (dev->usb_desc) {
        return dev->usb_desc;
    }
172 173 174 175 176 177 178 179 180 181 182 183
    return klass->usb_desc;
}

void usb_device_set_interface(USBDevice *dev, int interface,
                              int alt_old, int alt_new)
{
    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
    if (klass->set_interface) {
        klass->set_interface(dev, interface, alt_old, alt_new);
    }
}

184 185 186 187 188 189 190 191
void usb_device_flush_ep_queue(USBDevice *dev, USBEndpoint *ep)
{
    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
    if (klass->flush_ep_queue) {
        klass->flush_ep_queue(dev, ep);
    }
}

A
Anthony Liguori 已提交
192
static int usb_qdev_init(DeviceState *qdev)
193
{
194
    USBDevice *dev = USB_DEVICE(qdev);
195 196
    int rc;

197 198
    pstrcpy(dev->product_desc, sizeof(dev->product_desc),
            usb_device_get_product_desc(dev));
G
Gerd Hoffmann 已提交
199
    dev->auto_attach = 1;
200
    QLIST_INIT(&dev->strings);
G
Gerd Hoffmann 已提交
201
    usb_ep_init(dev);
202
    rc = usb_claim_port(dev);
203
    if (rc != 0) {
204
        return rc;
205
    }
206
    rc = usb_device_init(dev);
207
    if (rc != 0) {
208 209
        usb_release_port(dev);
        return rc;
210 211
    }
    if (dev->auto_attach) {
212
        rc = usb_device_attach(dev);
213
        if (rc != 0) {
214 215
            usb_qdev_exit(qdev);
            return rc;
216
        }
217
    }
218
    return 0;
219 220
}

221 222
static int usb_qdev_exit(DeviceState *qdev)
{
223
    USBDevice *dev = USB_DEVICE(qdev);
224

225 226 227
    if (dev->attached) {
        usb_device_detach(dev);
    }
228
    usb_device_handle_destroy(dev);
229 230 231
    if (dev->port) {
        usb_release_port(dev);
    }
232 233 234
    return 0;
}

235
typedef struct LegacyUSBFactory
236
{
237 238
    const char *name;
    const char *usbdevice_name;
239
    USBDevice *(*usbdevice_init)(USBBus *bus, const char *params);
240
} LegacyUSBFactory;
241

242 243
static GSList *legacy_usb_factory;

244
void usb_legacy_register(const char *typename, const char *usbdevice_name,
245 246
                         USBDevice *(*usbdevice_init)(USBBus *bus,
                                                      const char *params))
247
{
248 249
    if (usbdevice_name) {
        LegacyUSBFactory *f = g_malloc0(sizeof(*f));
250
        f->name = typename;
251 252 253
        f->usbdevice_name = usbdevice_name;
        f->usbdevice_init = usbdevice_init;
        legacy_usb_factory = g_slist_append(legacy_usb_factory, f);
254 255 256
    }
}

257
USBDevice *usb_create(USBBus *bus, const char *name)
258 259 260 261
{
    DeviceState *dev;

    dev = qdev_create(&bus->qbus, name);
262
    return USB_DEVICE(dev);
263
}
264 265 266 267

USBDevice *usb_create_simple(USBBus *bus, const char *name)
{
    USBDevice *dev = usb_create(bus, name);
268 269
    int rc;

P
Paul Brook 已提交
270
    if (!dev) {
271
        error_report("Failed to create USB device '%s'", name);
272 273 274 275
        return NULL;
    }
    rc = qdev_init(&dev->qdev);
    if (rc < 0) {
276
        error_report("Failed to initialize USB device '%s'", name);
277
        return NULL;
P
Paul Brook 已提交
278
    }
279 280 281
    return dev;
}

282 283
static void usb_fill_port(USBPort *port, void *opaque, int index,
                          USBPortOps *ops, int speedmask)
284
{
285 286 287
    port->opaque = opaque;
    port->index = index;
    port->ops = ops;
G
Gerd Hoffmann 已提交
288
    port->speedmask = speedmask;
289
    usb_port_location(port, NULL, index + 1);
290 291 292 293 294 295
}

void usb_register_port(USBBus *bus, USBPort *port, void *opaque, int index,
                       USBPortOps *ops, int speedmask)
{
    usb_fill_port(port, opaque, index, ops, speedmask);
B
Blue Swirl 已提交
296
    QTAILQ_INSERT_TAIL(&bus->free, port, next);
297 298 299
    bus->nfree++;
}

300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330
int usb_register_companion(const char *masterbus, USBPort *ports[],
                           uint32_t portcount, uint32_t firstport,
                           void *opaque, USBPortOps *ops, int speedmask)
{
    USBBus *bus;
    int i;

    QTAILQ_FOREACH(bus, &busses, next) {
        if (strcmp(bus->qbus.name, masterbus) == 0) {
            break;
        }
    }

    if (!bus || !bus->ops->register_companion) {
        qerror_report(QERR_INVALID_PARAMETER_VALUE, "masterbus",
                      "an USB masterbus");
        if (bus) {
            error_printf_unless_qmp(
                "USB bus '%s' does not allow companion controllers\n",
                masterbus);
        }
        return -1;
    }

    for (i = 0; i < portcount; i++) {
        usb_fill_port(ports[i], opaque, i, ops, speedmask);
    }

    return bus->ops->register_companion(bus, ports, portcount, firstport);
}

331 332 333 334 335 336 337 338 339 340
void usb_port_location(USBPort *downstream, USBPort *upstream, int portnr)
{
    if (upstream) {
        snprintf(downstream->path, sizeof(downstream->path), "%s.%d",
                 upstream->path, portnr);
    } else {
        snprintf(downstream->path, sizeof(downstream->path), "%d", portnr);
    }
}

341 342 343 344 345 346 347 348
void usb_unregister_port(USBBus *bus, USBPort *port)
{
    if (port->dev)
        qdev_free(&port->dev->qdev);
    QTAILQ_REMOVE(&bus->free, port, next);
    bus->nfree--;
}

349
int usb_claim_port(USBDevice *dev)
350 351 352 353
{
    USBBus *bus = usb_bus_from_device(dev);
    USBPort *port;

354 355
    assert(dev->port == NULL);

G
Gerd Hoffmann 已提交
356 357 358 359 360 361 362
    if (dev->port_path) {
        QTAILQ_FOREACH(port, &bus->free, next) {
            if (strcmp(port->path, dev->port_path) == 0) {
                break;
            }
        }
        if (port == NULL) {
363
            error_report("Error: usb port %s (bus %s) not found (in use?)",
364
                         dev->port_path, bus->qbus.name);
365
            return -1;
G
Gerd Hoffmann 已提交
366 367
        }
    } else {
368
        if (bus->nfree == 1 && strcmp(object_get_typename(OBJECT(dev)), "usb-hub") != 0) {
369 370 371 372 373
            /* Create a new hub and chain it on */
            usb_create_simple(bus, "usb-hub");
        }
        if (bus->nfree == 0) {
            error_report("Error: tried to attach usb device %s to a bus "
374
                         "with no free ports", dev->product_desc);
375 376
            return -1;
        }
G
Gerd Hoffmann 已提交
377 378
        port = QTAILQ_FIRST(&bus->free);
    }
379
    trace_usb_port_claim(bus->busnr, port->path);
380

B
Blue Swirl 已提交
381
    QTAILQ_REMOVE(&bus->free, port, next);
382 383
    bus->nfree--;

384 385
    dev->port = port;
    port->dev = dev;
386

B
Blue Swirl 已提交
387
    QTAILQ_INSERT_TAIL(&bus->used, port, next);
388
    bus->nused++;
389
    return 0;
390 391
}

392
void usb_release_port(USBDevice *dev)
393 394
{
    USBBus *bus = usb_bus_from_device(dev);
395
    USBPort *port = dev->port;
396

397 398 399 400 401 402 403 404 405 406 407
    assert(port != NULL);
    trace_usb_port_release(bus->busnr, port->path);

    QTAILQ_REMOVE(&bus->used, port, next);
    bus->nused--;

    dev->port = NULL;
    port->dev = NULL;

    QTAILQ_INSERT_TAIL(&bus->free, port, next);
    bus->nfree++;
408 409
}

410
int usb_device_attach(USBDevice *dev)
411 412
{
    USBBus *bus = usb_bus_from_device(dev);
413
    USBPort *port = dev->port;
414

415 416 417 418 419 420
    assert(port != NULL);
    assert(!dev->attached);
    trace_usb_port_attach(bus->busnr, port->path);

    if (!(port->speedmask & dev->speedmask)) {
        error_report("Warning: speed mismatch trying to attach "
421
                     "usb device %s to bus %s",
422
                     dev->product_desc, bus->qbus.name);
423 424 425
        return -1;
    }

426 427
    dev->attached++;
    usb_attach(port);
428

429 430 431 432 433 434 435
    return 0;
}

int usb_device_detach(USBDevice *dev)
{
    USBBus *bus = usb_bus_from_device(dev);
    USBPort *port = dev->port;
436

437 438 439
    assert(port != NULL);
    assert(dev->attached);
    trace_usb_port_detach(bus->busnr, port->path);
440

441 442
    usb_detach(port);
    dev->attached--;
443 444 445
    return 0;
}

446 447 448 449 450 451 452 453 454 455
int usb_device_delete_addr(int busnr, int addr)
{
    USBBus *bus;
    USBPort *port;
    USBDevice *dev;

    bus = usb_bus_find(busnr);
    if (!bus)
        return -1;

B
Blue Swirl 已提交
456
    QTAILQ_FOREACH(port, &bus->used, next) {
457 458 459 460 461 462 463
        if (port->dev->addr == addr)
            break;
    }
    if (!port)
        return -1;
    dev = port->dev;

464
    qdev_free(&dev->qdev);
465 466 467 468 469 470 471 472 473
    return 0;
}

static const char *usb_speed(unsigned int speed)
{
    static const char *txt[] = {
        [ USB_SPEED_LOW  ] = "1.5",
        [ USB_SPEED_FULL ] = "12",
        [ USB_SPEED_HIGH ] = "480",
474
        [ USB_SPEED_SUPER ] = "5000",
475 476 477 478 479 480 481 482
    };
    if (speed >= ARRAY_SIZE(txt))
        return "?";
    return txt[speed];
}

static void usb_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent)
{
483
    USBDevice *dev = USB_DEVICE(qdev);
484 485
    USBBus *bus = usb_bus_from_device(dev);

486
    monitor_printf(mon, "%*saddr %d.%d, port %s, speed %s, name %s%s\n",
487
                   indent, "", bus->busnr, dev->addr,
488
                   dev->port ? dev->port->path : "-",
489
                   usb_speed(dev->speed), dev->product_desc,
490
                   dev->attached ? ", attached" : "");
491 492
}

493 494
static char *usb_get_dev_path(DeviceState *qdev)
{
495
    USBDevice *dev = USB_DEVICE(qdev);
G
Gerd Hoffmann 已提交
496 497 498
    DeviceState *hcd = qdev->parent_bus->parent;
    char *id = NULL;

499 500
    if (dev->flags & (1 << USB_DEV_FLAG_FULL_PATH)) {
        id = qdev_get_dev_path(hcd);
G
Gerd Hoffmann 已提交
501 502 503 504 505 506 507 508
    }
    if (id) {
        char *ret = g_strdup_printf("%s/%s", id, dev->port->path);
        g_free(id);
        return ret;
    } else {
        return g_strdup(dev->port->path);
    }
509 510
}

511 512
static char *usb_get_fw_dev_path(DeviceState *qdev)
{
513
    USBDevice *dev = USB_DEVICE(qdev);
514
    char *fw_path, *in;
B
Blue Swirl 已提交
515
    ssize_t pos = 0, fw_len;
516 517
    long nr;

B
Blue Swirl 已提交
518
    fw_len = 32 + strlen(dev->port->path) * 6;
519
    fw_path = g_malloc(fw_len);
520
    in = dev->port->path;
B
Blue Swirl 已提交
521
    while (fw_len - pos > 0) {
522 523 524
        nr = strtol(in, &in, 10);
        if (in[0] == '.') {
            /* some hub between root port and device */
B
Blue Swirl 已提交
525
            pos += snprintf(fw_path + pos, fw_len - pos, "hub@%ld/", nr);
526 527 528
            in++;
        } else {
            /* the device itself */
B
Blue Swirl 已提交
529 530
            pos += snprintf(fw_path + pos, fw_len - pos, "%s@%ld",
                            qdev_fw_name(qdev), nr);
531 532 533 534 535 536
            break;
        }
    }
    return fw_path;
}

537 538 539 540 541 542
void usb_info(Monitor *mon)
{
    USBBus *bus;
    USBDevice *dev;
    USBPort *port;

B
Blue Swirl 已提交
543
    if (QTAILQ_EMPTY(&busses)) {
544 545 546 547
        monitor_printf(mon, "USB support not enabled\n");
        return;
    }

B
Blue Swirl 已提交
548 549
    QTAILQ_FOREACH(bus, &busses, next) {
        QTAILQ_FOREACH(port, &bus->used, next) {
550 551 552
            dev = port->dev;
            if (!dev)
                continue;
553 554
            monitor_printf(mon, "  Device %d.%d, Port %s, Speed %s Mb/s, Product %s\n",
                           bus->busnr, dev->addr, port->path, usb_speed(dev->speed),
555
                           dev->product_desc);
556 557 558 559
        }
    }
}

G
Gerd Hoffmann 已提交
560 561 562 563
/* handle legacy -usbdevice cmd line option */
USBDevice *usbdevice_create(const char *cmdline)
{
    USBBus *bus = usb_bus_find(-1 /* any */);
564 565
    LegacyUSBFactory *f = NULL;
    GSList *i;
566 567
    char driver[32];
    const char *params;
G
Gerd Hoffmann 已提交
568 569 570 571 572 573 574 575 576 577
    int len;

    params = strchr(cmdline,':');
    if (params) {
        params++;
        len = params - cmdline;
        if (len > sizeof(driver))
            len = sizeof(driver);
        pstrcpy(driver, len, cmdline);
    } else {
578
        params = "";
G
Gerd Hoffmann 已提交
579 580 581
        pstrcpy(driver, sizeof(driver), cmdline);
    }

582 583 584 585 586
    for (i = legacy_usb_factory; i; i = i->next) {
        f = i->data;
        if (strcmp(f->usbdevice_name, driver) == 0) {
            break;
        }
G
Gerd Hoffmann 已提交
587
    }
588
    if (i == NULL) {
G
Gerd Hoffmann 已提交
589 590
#if 0
        /* no error because some drivers are not converted (yet) */
591
        error_report("usbdevice %s not found", driver);
G
Gerd Hoffmann 已提交
592 593 594 595
#endif
        return NULL;
    }

596 597 598 599 600 601 602
    if (!bus) {
        error_report("Error: no usb bus to attach usbdevice %s, "
                     "please try -machine usb=on and check that "
                     "the machine model supports USB", driver);
        return NULL;
    }

603
    if (!f->usbdevice_init) {
T
TeLeMan 已提交
604
        if (*params) {
605
            error_report("usbdevice %s accepts no params", driver);
G
Gerd Hoffmann 已提交
606 607
            return NULL;
        }
608
        return usb_create_simple(bus, f->name);
G
Gerd Hoffmann 已提交
609
    }
610
    return f->usbdevice_init(bus, params);
G
Gerd Hoffmann 已提交
611
}
612

613 614 615
static void usb_device_class_init(ObjectClass *klass, void *data)
{
    DeviceClass *k = DEVICE_CLASS(klass);
616
    k->bus_type = TYPE_USB_BUS;
617 618 619
    k->init     = usb_qdev_init;
    k->unplug   = qdev_simple_unplug_cb;
    k->exit     = usb_qdev_exit;
620
    k->props    = usb_props;
621 622
}

623 624 625 626 627 628
static TypeInfo usb_device_type_info = {
    .name = TYPE_USB_DEVICE,
    .parent = TYPE_DEVICE,
    .instance_size = sizeof(USBDevice),
    .abstract = true,
    .class_size = sizeof(USBDeviceClass),
629
    .class_init = usb_device_class_init,
630 631
};

A
Andreas Färber 已提交
632
static void usb_register_types(void)
633
{
634
    type_register_static(&usb_bus_info);
635 636 637
    type_register_static(&usb_device_type_info);
}

A
Andreas Färber 已提交
638
type_init(usb_register_types)