bus.c 15.2 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
    .props      = (Property[]) {
        DEFINE_PROP_STRING("port", USBDevice, port_path),
G
Gerd Hoffmann 已提交
22 23
        DEFINE_PROP_BIT("full-path", USBDevice, flags,
                        USB_DEV_FLAG_FULL_PATH, true),
G
Gerd Hoffmann 已提交
24 25
        DEFINE_PROP_END_OF_LIST()
    },
26 27
};
static int next_usb_bus = 0;
B
Blue Swirl 已提交
28
static QTAILQ_HEAD(, USBBus) busses = QTAILQ_HEAD_INITIALIZER(busses);
29

G
Gerd Hoffmann 已提交
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
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(),
    }
};

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

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

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

70 71 72 73 74 75 76 77 78
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 已提交
79
USBDevice *usb_device_find_device(USBDevice *dev, uint8_t addr)
80 81
{
    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
G
Gerd Hoffmann 已提交
82 83
    if (klass->find_device) {
        return klass->find_device(dev, addr);
84
    }
G
Gerd Hoffmann 已提交
85
    return NULL;
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 159 160
}

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 已提交
161
static int usb_qdev_init(DeviceState *qdev)
162
{
163
    USBDevice *dev = USB_DEVICE(qdev);
164 165
    int rc;

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

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

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

204
typedef struct LegacyUSBFactory
205
{
206 207
    const char *name;
    const char *usbdevice_name;
208
    USBDevice *(*usbdevice_init)(USBBus *bus, const char *params);
209
} LegacyUSBFactory;
210

211 212
static GSList *legacy_usb_factory;

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

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

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

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

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

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

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

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

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

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

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

323 324
    assert(dev->port == NULL);

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

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

353 354
    dev->port = port;
    port->dev = dev;
355

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

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

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

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

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

395 396
    dev->attached++;
    usb_attach(port);
397

398 399 400 401 402 403 404
    return 0;
}

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

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

410 411
    usb_detach(port);
    dev->attached--;
412 413 414
    return 0;
}

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

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

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

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

462 463
static char *usb_get_dev_path(DeviceState *qdev)
{
464
    USBDevice *dev = USB_DEVICE(qdev);
G
Gerd Hoffmann 已提交
465 466 467 468 469 470 471 472 473 474 475 476 477 478
    DeviceState *hcd = qdev->parent_bus->parent;
    char *id = NULL;

    if ((dev->flags & (1 << USB_DEV_FLAG_FULL_PATH)) &&
        hcd && hcd->parent_bus && hcd->parent_bus->info->get_dev_path) {
        id = hcd->parent_bus->info->get_dev_path(hcd);
    }
    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);
    }
479 480
}

481 482
static char *usb_get_fw_dev_path(DeviceState *qdev)
{
483
    USBDevice *dev = USB_DEVICE(qdev);
484
    char *fw_path, *in;
B
Blue Swirl 已提交
485
    ssize_t pos = 0, fw_len;
486 487
    long nr;

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

507 508 509 510 511 512
void usb_info(Monitor *mon)
{
    USBBus *bus;
    USBDevice *dev;
    USBPort *port;

B
Blue Swirl 已提交
513
    if (QTAILQ_EMPTY(&busses)) {
514 515 516 517
        monitor_printf(mon, "USB support not enabled\n");
        return;
    }

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

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

    params = strchr(cmdline,':');
    if (params) {
        params++;
        len = params - cmdline;
        if (len > sizeof(driver))
            len = sizeof(driver);
        pstrcpy(driver, len, cmdline);
    } else {
548
        params = "";
G
Gerd Hoffmann 已提交
549 550 551
        pstrcpy(driver, sizeof(driver), cmdline);
    }

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

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

576 577 578 579 580 581 582 583 584
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;
}

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

A
Andreas Färber 已提交
594
static void usb_register_types(void)
595 596 597 598
{
    type_register_static(&usb_device_type_info);
}

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