bus.c 14.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

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
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 已提交
77
USBDevice *usb_device_find_device(USBDevice *dev, uint8_t addr)
78 79
{
    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
G
Gerd Hoffmann 已提交
80 81
    if (klass->find_device) {
        return klass->find_device(dev, addr);
82
    }
G
Gerd Hoffmann 已提交
83
    return NULL;
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 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);
    }
}

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

A
Anthony Liguori 已提交
159
static int usb_qdev_init(DeviceState *qdev)
160
{
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
    const char *name;
    const char *usbdevice_name;
206
    USBDevice *(*usbdevice_init)(USBBus *bus, const char *params);
207
} LegacyUSBFactory;
208

209 210
static GSList *legacy_usb_factory;

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

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

    dev = qdev_create(&bus->qbus, name);
229
    return USB_DEVICE(dev);
230
}
231 232 233 234

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

P
Paul Brook 已提交
237
    if (!dev) {
238
        error_report("Failed to create USB device '%s'", name);
239 240 241 242
        return NULL;
    }
    rc = qdev_init(&dev->qdev);
    if (rc < 0) {
243
        error_report("Failed to initialize USB device '%s'", name);
244
        return NULL;
P
Paul Brook 已提交
245
    }
246 247 248
    return dev;
}

249 250
static void usb_fill_port(USBPort *port, void *opaque, int index,
                          USBPortOps *ops, int speedmask)
251
{
252 253 254
    port->opaque = opaque;
    port->index = index;
    port->ops = ops;
G
Gerd Hoffmann 已提交
255
    port->speedmask = speedmask;
256
    usb_port_location(port, NULL, index + 1);
257 258 259 260 261 262
}

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 已提交
263
    QTAILQ_INSERT_TAIL(&bus->free, port, next);
264 265 266
    bus->nfree++;
}

267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297
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);
}

298 299 300 301 302 303 304 305 306 307
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);
    }
}

308 309 310 311 312 313 314 315
void usb_unregister_port(USBBus *bus, USBPort *port)
{
    if (port->dev)
        qdev_free(&port->dev->qdev);
    QTAILQ_REMOVE(&bus->free, port, next);
    bus->nfree--;
}

316
int usb_claim_port(USBDevice *dev)
317 318 319 320
{
    USBBus *bus = usb_bus_from_device(dev);
    USBPort *port;

321 322
    assert(dev->port == NULL);

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

B
Blue Swirl 已提交
348
    QTAILQ_REMOVE(&bus->free, port, next);
349 350
    bus->nfree--;

351 352
    dev->port = port;
    port->dev = dev;
353

B
Blue Swirl 已提交
354
    QTAILQ_INSERT_TAIL(&bus->used, port, next);
355
    bus->nused++;
356
    return 0;
357 358
}

359
void usb_release_port(USBDevice *dev)
360 361
{
    USBBus *bus = usb_bus_from_device(dev);
362
    USBPort *port = dev->port;
363

364 365 366 367 368 369 370 371 372 373 374
    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++;
375 376
}

377
int usb_device_attach(USBDevice *dev)
378 379
{
    USBBus *bus = usb_bus_from_device(dev);
380
    USBPort *port = dev->port;
381

382 383 384 385 386 387
    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 "
388
                     "usb device %s to bus %s",
389
                     dev->product_desc, bus->qbus.name);
390 391 392
        return -1;
    }

393 394
    dev->attached++;
    usb_attach(port);
395

396 397 398 399 400 401 402
    return 0;
}

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

404 405 406
    assert(port != NULL);
    assert(dev->attached);
    trace_usb_port_detach(bus->busnr, port->path);
407

408 409
    usb_detach(port);
    dev->attached--;
410 411 412
    return 0;
}

413 414 415 416 417 418 419 420 421 422
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 已提交
423
    QTAILQ_FOREACH(port, &bus->used, next) {
424 425 426 427 428 429 430
        if (port->dev->addr == addr)
            break;
    }
    if (!port)
        return -1;
    dev = port->dev;

431
    qdev_free(&dev->qdev);
432 433 434 435 436 437 438 439 440
    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",
441
        [ USB_SPEED_SUPER ] = "5000",
442 443 444 445 446 447 448 449
    };
    if (speed >= ARRAY_SIZE(txt))
        return "?";
    return txt[speed];
}

static void usb_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent)
{
450
    USBDevice *dev = USB_DEVICE(qdev);
451 452
    USBBus *bus = usb_bus_from_device(dev);

453
    monitor_printf(mon, "%*saddr %d.%d, port %s, speed %s, name %s%s\n",
454
                   indent, "", bus->busnr, dev->addr,
455
                   dev->port ? dev->port->path : "-",
456
                   usb_speed(dev->speed), dev->product_desc,
457
                   dev->attached ? ", attached" : "");
458 459
}

460 461
static char *usb_get_dev_path(DeviceState *qdev)
{
462
    USBDevice *dev = USB_DEVICE(qdev);
463
    return g_strdup(dev->port->path);
464 465
}

466 467
static char *usb_get_fw_dev_path(DeviceState *qdev)
{
468
    USBDevice *dev = USB_DEVICE(qdev);
469
    char *fw_path, *in;
B
Blue Swirl 已提交
470
    ssize_t pos = 0, fw_len;
471 472
    long nr;

B
Blue Swirl 已提交
473
    fw_len = 32 + strlen(dev->port->path) * 6;
474
    fw_path = g_malloc(fw_len);
475
    in = dev->port->path;
B
Blue Swirl 已提交
476
    while (fw_len - pos > 0) {
477 478 479
        nr = strtol(in, &in, 10);
        if (in[0] == '.') {
            /* some hub between root port and device */
B
Blue Swirl 已提交
480
            pos += snprintf(fw_path + pos, fw_len - pos, "hub@%ld/", nr);
481 482 483
            in++;
        } else {
            /* the device itself */
B
Blue Swirl 已提交
484 485
            pos += snprintf(fw_path + pos, fw_len - pos, "%s@%ld",
                            qdev_fw_name(qdev), nr);
486 487 488 489 490 491
            break;
        }
    }
    return fw_path;
}

492 493 494 495 496 497
void usb_info(Monitor *mon)
{
    USBBus *bus;
    USBDevice *dev;
    USBPort *port;

B
Blue Swirl 已提交
498
    if (QTAILQ_EMPTY(&busses)) {
499 500 501 502
        monitor_printf(mon, "USB support not enabled\n");
        return;
    }

B
Blue Swirl 已提交
503 504
    QTAILQ_FOREACH(bus, &busses, next) {
        QTAILQ_FOREACH(port, &bus->used, next) {
505 506 507
            dev = port->dev;
            if (!dev)
                continue;
508 509
            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),
510
                           dev->product_desc);
511 512 513 514
        }
    }
}

G
Gerd Hoffmann 已提交
515 516 517 518
/* handle legacy -usbdevice cmd line option */
USBDevice *usbdevice_create(const char *cmdline)
{
    USBBus *bus = usb_bus_find(-1 /* any */);
519 520
    LegacyUSBFactory *f = NULL;
    GSList *i;
521 522
    char driver[32];
    const char *params;
G
Gerd Hoffmann 已提交
523 524 525 526 527 528 529 530 531 532
    int len;

    params = strchr(cmdline,':');
    if (params) {
        params++;
        len = params - cmdline;
        if (len > sizeof(driver))
            len = sizeof(driver);
        pstrcpy(driver, len, cmdline);
    } else {
533
        params = "";
G
Gerd Hoffmann 已提交
534 535 536
        pstrcpy(driver, sizeof(driver), cmdline);
    }

537 538 539 540 541
    for (i = legacy_usb_factory; i; i = i->next) {
        f = i->data;
        if (strcmp(f->usbdevice_name, driver) == 0) {
            break;
        }
G
Gerd Hoffmann 已提交
542
    }
543
    if (i == NULL) {
G
Gerd Hoffmann 已提交
544 545
#if 0
        /* no error because some drivers are not converted (yet) */
546
        error_report("usbdevice %s not found", driver);
G
Gerd Hoffmann 已提交
547 548 549 550
#endif
        return NULL;
    }

551
    if (!f->usbdevice_init) {
T
TeLeMan 已提交
552
        if (*params) {
553
            error_report("usbdevice %s accepts no params", driver);
G
Gerd Hoffmann 已提交
554 555
            return NULL;
        }
556
        return usb_create_simple(bus, f->name);
G
Gerd Hoffmann 已提交
557
    }
558
    return f->usbdevice_init(bus, params);
G
Gerd Hoffmann 已提交
559
}
560

561 562 563 564 565 566 567 568 569
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;
}

570 571 572 573 574 575
static TypeInfo usb_device_type_info = {
    .name = TYPE_USB_DEVICE,
    .parent = TYPE_DEVICE,
    .instance_size = sizeof(USBDevice),
    .abstract = true,
    .class_size = sizeof(USBDeviceClass),
576
    .class_init = usb_device_class_init,
577 578
};

A
Andreas Färber 已提交
579
static void usb_register_types(void)
580 581 582 583
{
    type_register_static(&usb_device_type_info);
}

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