bus.c 15.7 KB
Newer Older
G
Gerd Hoffmann 已提交
1 2 3
#include "hw/hw.h"
#include "hw/usb.h"
#include "hw/qdev.h"
4 5
#include "sysemu.h"
#include "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 169 170 171 172 173 174 175 176 177 178 179 180
    }
}

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);
    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);
    }
}

181 182 183 184 185 186 187 188
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 已提交
189
static int usb_qdev_init(DeviceState *qdev)
190
{
191
    USBDevice *dev = USB_DEVICE(qdev);
192 193
    int rc;

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

218 219
static int usb_qdev_exit(DeviceState *qdev)
{
220
    USBDevice *dev = USB_DEVICE(qdev);
221

222 223 224
    if (dev->attached) {
        usb_device_detach(dev);
    }
225
    usb_device_handle_destroy(dev);
226 227 228
    if (dev->port) {
        usb_release_port(dev);
    }
229 230 231
    return 0;
}

232
typedef struct LegacyUSBFactory
233
{
234 235
    const char *name;
    const char *usbdevice_name;
236
    USBDevice *(*usbdevice_init)(USBBus *bus, const char *params);
237
} LegacyUSBFactory;
238

239 240
static GSList *legacy_usb_factory;

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

254
USBDevice *usb_create(USBBus *bus, const char *name)
255 256 257 258
{
    DeviceState *dev;

    dev = qdev_create(&bus->qbus, name);
259
    return USB_DEVICE(dev);
260
}
261 262 263 264

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

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

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

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 已提交
293
    QTAILQ_INSERT_TAIL(&bus->free, port, next);
294 295 296
    bus->nfree++;
}

297 298 299 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
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);
}

328 329 330 331 332 333 334 335 336 337
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);
    }
}

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

346
int usb_claim_port(USBDevice *dev)
347 348 349 350
{
    USBBus *bus = usb_bus_from_device(dev);
    USBPort *port;

351 352
    assert(dev->port == NULL);

G
Gerd Hoffmann 已提交
353 354 355 356 357 358 359
    if (dev->port_path) {
        QTAILQ_FOREACH(port, &bus->free, next) {
            if (strcmp(port->path, dev->port_path) == 0) {
                break;
            }
        }
        if (port == NULL) {
360
            error_report("Error: usb port %s (bus %s) not found (in use?)",
361
                         dev->port_path, bus->qbus.name);
362
            return -1;
G
Gerd Hoffmann 已提交
363 364
        }
    } else {
365
        if (bus->nfree == 1 && strcmp(object_get_typename(OBJECT(dev)), "usb-hub") != 0) {
366 367 368 369 370
            /* 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 "
371
                         "with no free ports", dev->product_desc);
372 373
            return -1;
        }
G
Gerd Hoffmann 已提交
374 375
        port = QTAILQ_FIRST(&bus->free);
    }
376
    trace_usb_port_claim(bus->busnr, port->path);
377

B
Blue Swirl 已提交
378
    QTAILQ_REMOVE(&bus->free, port, next);
379 380
    bus->nfree--;

381 382
    dev->port = port;
    port->dev = dev;
383

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

389
void usb_release_port(USBDevice *dev)
390 391
{
    USBBus *bus = usb_bus_from_device(dev);
392
    USBPort *port = dev->port;
393

394 395 396 397 398 399 400 401 402 403 404
    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++;
405 406
}

407
int usb_device_attach(USBDevice *dev)
408 409
{
    USBBus *bus = usb_bus_from_device(dev);
410
    USBPort *port = dev->port;
411

412 413 414 415 416 417
    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 "
418
                     "usb device %s to bus %s",
419
                     dev->product_desc, bus->qbus.name);
420 421 422
        return -1;
    }

423 424
    dev->attached++;
    usb_attach(port);
425

426 427 428 429 430 431 432
    return 0;
}

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

434 435 436
    assert(port != NULL);
    assert(dev->attached);
    trace_usb_port_detach(bus->busnr, port->path);
437

438 439
    usb_detach(port);
    dev->attached--;
440 441 442
    return 0;
}

443 444 445 446 447 448 449 450 451 452
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 已提交
453
    QTAILQ_FOREACH(port, &bus->used, next) {
454 455 456 457 458 459 460
        if (port->dev->addr == addr)
            break;
    }
    if (!port)
        return -1;
    dev = port->dev;

461
    qdev_free(&dev->qdev);
462 463 464 465 466 467 468 469 470
    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",
471
        [ USB_SPEED_SUPER ] = "5000",
472 473 474 475 476 477 478 479
    };
    if (speed >= ARRAY_SIZE(txt))
        return "?";
    return txt[speed];
}

static void usb_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent)
{
480
    USBDevice *dev = USB_DEVICE(qdev);
481 482
    USBBus *bus = usb_bus_from_device(dev);

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

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

496 497
    if (dev->flags & (1 << USB_DEV_FLAG_FULL_PATH)) {
        id = qdev_get_dev_path(hcd);
G
Gerd Hoffmann 已提交
498 499 500 501 502 503 504 505
    }
    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);
    }
506 507
}

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

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

534 535 536 537 538 539
void usb_info(Monitor *mon)
{
    USBBus *bus;
    USBDevice *dev;
    USBPort *port;

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

B
Blue Swirl 已提交
545 546
    QTAILQ_FOREACH(bus, &busses, next) {
        QTAILQ_FOREACH(port, &bus->used, next) {
547 548 549
            dev = port->dev;
            if (!dev)
                continue;
550 551
            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),
552
                           dev->product_desc);
553 554 555 556
        }
    }
}

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

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

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

593
    if (!f->usbdevice_init) {
T
TeLeMan 已提交
594
        if (*params) {
595
            error_report("usbdevice %s accepts no params", driver);
G
Gerd Hoffmann 已提交
596 597
            return NULL;
        }
598
        return usb_create_simple(bus, f->name);
G
Gerd Hoffmann 已提交
599
    }
600
    return f->usbdevice_init(bus, params);
G
Gerd Hoffmann 已提交
601
}
602

603 604 605
static void usb_device_class_init(ObjectClass *klass, void *data)
{
    DeviceClass *k = DEVICE_CLASS(klass);
606
    k->bus_type = TYPE_USB_BUS;
607 608 609
    k->init     = usb_qdev_init;
    k->unplug   = qdev_simple_unplug_cb;
    k->exit     = usb_qdev_exit;
610
    k->props    = usb_props;
611 612
}

613 614 615 616 617 618
static TypeInfo usb_device_type_info = {
    .name = TYPE_USB_DEVICE,
    .parent = TYPE_DEVICE,
    .instance_size = sizeof(USBDevice),
    .abstract = true,
    .class_size = sizeof(USBDeviceClass),
619
    .class_init = usb_device_class_init,
620 621
};

A
Andreas Färber 已提交
622
static void usb_register_types(void)
623
{
624
    type_register_static(&usb_bus_info);
625 626 627
    type_register_static(&usb_device_type_info);
}

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