usb-bus.c 14.9 KB
Newer Older
1 2 3
#include "hw.h"
#include "usb.h"
#include "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

static struct BusInfo usb_bus_info = {
15 16 17
    .name      = "USB",
    .size      = sizeof(USBBus),
    .print_dev = usb_bus_dev_print,
18
    .get_dev_path = usb_get_dev_path,
19
    .get_fw_dev_path = usb_get_fw_dev_path,
G
Gerd Hoffmann 已提交
20 21 22 23
    .props      = (Property[]) {
        DEFINE_PROP_STRING("port", USBDevice, port_path),
        DEFINE_PROP_END_OF_LIST()
    },
24 25
};
static int next_usb_bus = 0;
B
Blue Swirl 已提交
26
static QTAILQ_HEAD(, USBBus) busses = QTAILQ_HEAD_INITIALIZER(busses);
27

G
Gerd Hoffmann 已提交
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
const VMStateDescription vmstate_usb_device = {
    .name = "USBDevice",
    .version_id = 1,
    .minimum_version_id = 1,
    .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(),
    }
};

44
void usb_bus_new(USBBus *bus, USBBusOps *ops, DeviceState *host)
45
{
46
    qbus_create_inplace(&bus->qbus, &usb_bus_info, host, NULL);
47
    bus->ops = ops;
48
    bus->busnr = next_usb_bus++;
G
Gerd Hoffmann 已提交
49
    bus->qbus.allow_hotplug = 1; /* Yes, we can */
B
Blue Swirl 已提交
50 51 52
    QTAILQ_INIT(&bus->free);
    QTAILQ_INIT(&bus->used);
    QTAILQ_INSERT_TAIL(&busses, bus, next);
53 54 55 56 57 58 59
}

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

    if (-1 == busnr)
B
Blue Swirl 已提交
60 61
        return QTAILQ_FIRST(&busses);
    QTAILQ_FOREACH(bus, &busses, next) {
62 63 64 65 66 67
        if (bus->busnr == busnr)
            return bus;
    }
    return NULL;
}

68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 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 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
static int usb_device_init(USBDevice *dev)
{
    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
    if (klass->init) {
        return klass->init(dev);
    }
    return 0;
}

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

int usb_device_handle_packet(USBDevice *dev, USBPacket *p)
{
    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
    if (klass->handle_packet) {
        return klass->handle_packet(dev, p);
    }
    return -ENOSYS;
}

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

int usb_device_handle_control(USBDevice *dev, USBPacket *p, int request,
                              int value, int index, int length, uint8_t *data)
{
    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
    if (klass->handle_control) {
        return klass->handle_control(dev, p, request, value, index, length,
                                         data);
    }
    return -ENOSYS;
}

int usb_device_handle_data(USBDevice *dev, USBPacket *p)
{
    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
    if (klass->handle_data) {
        return klass->handle_data(dev, p);
    }
    return -ENOSYS;
}

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

159 160
static int usb_qdev_init(DeviceState *qdev, DeviceInfo *base)
{
161
    USBDevice *dev = USB_DEVICE(qdev);
162 163
    int rc;

164 165
    pstrcpy(dev->product_desc, sizeof(dev->product_desc),
            usb_device_get_product_desc(dev));
G
Gerd Hoffmann 已提交
166
    dev->auto_attach = 1;
167
    QLIST_INIT(&dev->strings);
G
Gerd Hoffmann 已提交
168
    usb_ep_init(dev);
169
    rc = usb_claim_port(dev);
170
    if (rc != 0) {
171
        return rc;
172
    }
173
    rc = usb_device_init(dev);
174
    if (rc != 0) {
175 176
        usb_release_port(dev);
        return rc;
177 178
    }
    if (dev->auto_attach) {
179
        rc = usb_device_attach(dev);
180
        if (rc != 0) {
181 182
            usb_qdev_exit(qdev);
            return rc;
183
        }
184
    }
185
    return 0;
186 187
}

188 189
static int usb_qdev_exit(DeviceState *qdev)
{
190
    USBDevice *dev = USB_DEVICE(qdev);
191

192 193 194
    if (dev->attached) {
        usb_device_detach(dev);
    }
195
    usb_device_handle_destroy(dev);
196 197 198
    if (dev->port) {
        usb_release_port(dev);
    }
199 200 201
    return 0;
}

202
typedef struct LegacyUSBFactory
203
{
204 205 206 207
    const char *name;
    const char *usbdevice_name;
    USBDevice *(*usbdevice_init)(const char *params);
} LegacyUSBFactory;
208

209 210
static GSList *legacy_usb_factory;

211 212
void usb_legacy_register(const char *typename, const char *usbdevice_name,
                         USBDevice *(*usbdevice_init)(const char *params))
213
{
214 215
    if (usbdevice_name) {
        LegacyUSBFactory *f = g_malloc0(sizeof(*f));
216
        f->name = typename;
217 218 219
        f->usbdevice_name = usbdevice_name;
        f->usbdevice_init = usbdevice_init;
        legacy_usb_factory = g_slist_append(legacy_usb_factory, f);
220 221 222
    }
}

223
USBDevice *usb_create(USBBus *bus, const char *name)
224 225 226 227 228 229 230 231 232
{
    DeviceState *dev;

#if 1
    /* temporary stopgap until all usb is properly qdev-ified */
    if (!bus) {
        bus = usb_bus_find(-1);
        if (!bus)
            return NULL;
233
        error_report("%s: no bus specified, using \"%s\" for \"%s\"",
234 235 236 237 238
                __FUNCTION__, bus->qbus.name, name);
    }
#endif

    dev = qdev_create(&bus->qbus, name);
239
    return USB_DEVICE(dev);
240
}
241 242 243 244

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

P
Paul Brook 已提交
247
    if (!dev) {
248
        error_report("Failed to create USB device '%s'", name);
249 250 251 252
        return NULL;
    }
    rc = qdev_init(&dev->qdev);
    if (rc < 0) {
253
        error_report("Failed to initialize USB device '%s'", name);
254
        return NULL;
P
Paul Brook 已提交
255
    }
256 257 258
    return dev;
}

259 260
static void usb_fill_port(USBPort *port, void *opaque, int index,
                          USBPortOps *ops, int speedmask)
261
{
262 263 264
    port->opaque = opaque;
    port->index = index;
    port->ops = ops;
G
Gerd Hoffmann 已提交
265
    port->speedmask = speedmask;
266
    usb_port_location(port, NULL, index + 1);
267 268 269 270 271 272
}

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 已提交
273
    QTAILQ_INSERT_TAIL(&bus->free, port, next);
274 275 276
    bus->nfree++;
}

277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307
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);
}

308 309 310 311 312 313 314 315 316 317
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);
    }
}

318 319 320 321 322 323 324 325
void usb_unregister_port(USBBus *bus, USBPort *port)
{
    if (port->dev)
        qdev_free(&port->dev->qdev);
    QTAILQ_REMOVE(&bus->free, port, next);
    bus->nfree--;
}

326
int usb_claim_port(USBDevice *dev)
327 328 329 330
{
    USBBus *bus = usb_bus_from_device(dev);
    USBPort *port;

331 332
    assert(dev->port == NULL);

G
Gerd Hoffmann 已提交
333 334 335 336 337 338 339
    if (dev->port_path) {
        QTAILQ_FOREACH(port, &bus->free, next) {
            if (strcmp(port->path, dev->port_path) == 0) {
                break;
            }
        }
        if (port == NULL) {
340
            error_report("Error: usb port %s (bus %s) not found (in use?)",
341
                         dev->port_path, bus->qbus.name);
342
            return -1;
G
Gerd Hoffmann 已提交
343 344
        }
    } else {
345
        if (bus->nfree == 1 && strcmp(object_get_typename(OBJECT(dev)), "usb-hub") != 0) {
346 347 348 349 350
            /* 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 "
351
                         "with no free ports", dev->product_desc);
352 353
            return -1;
        }
G
Gerd Hoffmann 已提交
354 355
        port = QTAILQ_FIRST(&bus->free);
    }
356
    trace_usb_port_claim(bus->busnr, port->path);
357

B
Blue Swirl 已提交
358
    QTAILQ_REMOVE(&bus->free, port, next);
359 360
    bus->nfree--;

361 362
    dev->port = port;
    port->dev = dev;
363

B
Blue Swirl 已提交
364
    QTAILQ_INSERT_TAIL(&bus->used, port, next);
365
    bus->nused++;
366
    return 0;
367 368
}

369
void usb_release_port(USBDevice *dev)
370 371
{
    USBBus *bus = usb_bus_from_device(dev);
372
    USBPort *port = dev->port;
373

374 375 376 377 378 379 380 381 382 383 384
    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++;
385 386
}

387
int usb_device_attach(USBDevice *dev)
388 389
{
    USBBus *bus = usb_bus_from_device(dev);
390
    USBPort *port = dev->port;
391

392 393 394 395 396 397
    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 "
398
                     "usb device %s to bus %s",
399
                     dev->product_desc, bus->qbus.name);
400 401 402
        return -1;
    }

403 404
    dev->attached++;
    usb_attach(port);
405

406 407 408 409 410 411 412
    return 0;
}

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

414 415 416
    assert(port != NULL);
    assert(dev->attached);
    trace_usb_port_detach(bus->busnr, port->path);
417

418 419
    usb_detach(port);
    dev->attached--;
420 421 422
    return 0;
}

423 424 425 426 427 428 429 430 431 432
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 已提交
433
    QTAILQ_FOREACH(port, &bus->used, next) {
434 435 436 437 438 439 440
        if (port->dev->addr == addr)
            break;
    }
    if (!port)
        return -1;
    dev = port->dev;

441
    qdev_free(&dev->qdev);
442 443 444 445 446 447 448 449 450
    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",
451
        [ USB_SPEED_SUPER ] = "5000",
452 453 454 455 456 457 458 459
    };
    if (speed >= ARRAY_SIZE(txt))
        return "?";
    return txt[speed];
}

static void usb_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent)
{
460
    USBDevice *dev = USB_DEVICE(qdev);
461 462
    USBBus *bus = usb_bus_from_device(dev);

463
    monitor_printf(mon, "%*saddr %d.%d, port %s, speed %s, name %s%s\n",
464
                   indent, "", bus->busnr, dev->addr,
465
                   dev->port ? dev->port->path : "-",
466
                   usb_speed(dev->speed), dev->product_desc,
467
                   dev->attached ? ", attached" : "");
468 469
}

470 471
static char *usb_get_dev_path(DeviceState *qdev)
{
472
    USBDevice *dev = USB_DEVICE(qdev);
473
    return g_strdup(dev->port->path);
474 475
}

476 477
static char *usb_get_fw_dev_path(DeviceState *qdev)
{
478
    USBDevice *dev = USB_DEVICE(qdev);
479
    char *fw_path, *in;
B
Blue Swirl 已提交
480
    ssize_t pos = 0, fw_len;
481 482
    long nr;

B
Blue Swirl 已提交
483
    fw_len = 32 + strlen(dev->port->path) * 6;
484
    fw_path = g_malloc(fw_len);
485
    in = dev->port->path;
B
Blue Swirl 已提交
486
    while (fw_len - pos > 0) {
487 488 489
        nr = strtol(in, &in, 10);
        if (in[0] == '.') {
            /* some hub between root port and device */
B
Blue Swirl 已提交
490
            pos += snprintf(fw_path + pos, fw_len - pos, "hub@%ld/", nr);
491 492 493
            in++;
        } else {
            /* the device itself */
B
Blue Swirl 已提交
494 495
            pos += snprintf(fw_path + pos, fw_len - pos, "%s@%ld",
                            qdev_fw_name(qdev), nr);
496 497 498 499 500 501
            break;
        }
    }
    return fw_path;
}

502 503 504 505 506 507
void usb_info(Monitor *mon)
{
    USBBus *bus;
    USBDevice *dev;
    USBPort *port;

B
Blue Swirl 已提交
508
    if (QTAILQ_EMPTY(&busses)) {
509 510 511 512
        monitor_printf(mon, "USB support not enabled\n");
        return;
    }

B
Blue Swirl 已提交
513 514
    QTAILQ_FOREACH(bus, &busses, next) {
        QTAILQ_FOREACH(port, &bus->used, next) {
515 516 517
            dev = port->dev;
            if (!dev)
                continue;
518 519
            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),
520
                           dev->product_desc);
521 522 523 524
        }
    }
}

G
Gerd Hoffmann 已提交
525 526 527 528
/* handle legacy -usbdevice cmd line option */
USBDevice *usbdevice_create(const char *cmdline)
{
    USBBus *bus = usb_bus_find(-1 /* any */);
529 530
    LegacyUSBFactory *f = NULL;
    GSList *i;
531 532
    char driver[32];
    const char *params;
G
Gerd Hoffmann 已提交
533 534 535 536 537 538 539 540 541 542
    int len;

    params = strchr(cmdline,':');
    if (params) {
        params++;
        len = params - cmdline;
        if (len > sizeof(driver))
            len = sizeof(driver);
        pstrcpy(driver, len, cmdline);
    } else {
543
        params = "";
G
Gerd Hoffmann 已提交
544 545 546
        pstrcpy(driver, sizeof(driver), cmdline);
    }

547 548 549 550 551
    for (i = legacy_usb_factory; i; i = i->next) {
        f = i->data;
        if (strcmp(f->usbdevice_name, driver) == 0) {
            break;
        }
G
Gerd Hoffmann 已提交
552
    }
553
    if (i == NULL) {
G
Gerd Hoffmann 已提交
554 555
#if 0
        /* no error because some drivers are not converted (yet) */
556
        error_report("usbdevice %s not found", driver);
G
Gerd Hoffmann 已提交
557 558 559 560
#endif
        return NULL;
    }

561
    if (!f->usbdevice_init) {
T
TeLeMan 已提交
562
        if (*params) {
563
            error_report("usbdevice %s accepts no params", driver);
G
Gerd Hoffmann 已提交
564 565
            return NULL;
        }
566
        return usb_create_simple(bus, f->name);
G
Gerd Hoffmann 已提交
567
    }
568
    return f->usbdevice_init(params);
G
Gerd Hoffmann 已提交
569
}
570

571 572 573 574 575 576 577 578 579
static void usb_device_class_init(ObjectClass *klass, void *data)
{
    DeviceClass *k = DEVICE_CLASS(klass);
    k->bus_info = &usb_bus_info;
    k->init     = usb_qdev_init;
    k->unplug   = qdev_simple_unplug_cb;
    k->exit     = usb_qdev_exit;
}

580 581 582 583 584 585
static TypeInfo usb_device_type_info = {
    .name = TYPE_USB_DEVICE,
    .parent = TYPE_DEVICE,
    .instance_size = sizeof(USBDevice),
    .abstract = true,
    .class_size = sizeof(USBDeviceClass),
586
    .class_init = usb_device_class_init,
587 588 589 590 591 592 593 594
};

static void usb_register_devices(void)
{
    type_register_static(&usb_device_type_info);
}

device_init(usb_register_devices);