qemu/hw/usb/dev-mtp.c
<<
>>
Prefs
   1/*
   2 * Media Transfer Protocol implementation, backed by host filesystem.
   3 *
   4 * Copyright Red Hat, Inc 2014
   5 *
   6 * Author:
   7 *   Gerd Hoffmann <kraxel@redhat.com>
   8 *
   9 * This code is licensed under the GPL v2 or later.
  10 */
  11
  12#include <wchar.h>
  13#include <dirent.h>
  14#include <unistd.h>
  15
  16#include <sys/stat.h>
  17#include <sys/statvfs.h>
  18
  19#include "qemu-common.h"
  20#include "qemu/iov.h"
  21#include "trace.h"
  22#include "hw/usb.h"
  23#include "hw/usb/desc.h"
  24
  25/* ----------------------------------------------------------------------- */
  26
  27enum mtp_container_type {
  28    TYPE_COMMAND  = 1,
  29    TYPE_DATA     = 2,
  30    TYPE_RESPONSE = 3,
  31    TYPE_EVENT    = 4,
  32};
  33
  34enum mtp_code {
  35    /* command codes */
  36    CMD_GET_DEVICE_INFO            = 0x1001,
  37    CMD_OPEN_SESSION               = 0x1002,
  38    CMD_CLOSE_SESSION              = 0x1003,
  39    CMD_GET_STORAGE_IDS            = 0x1004,
  40    CMD_GET_STORAGE_INFO           = 0x1005,
  41    CMD_GET_NUM_OBJECTS            = 0x1006,
  42    CMD_GET_OBJECT_HANDLES         = 0x1007,
  43    CMD_GET_OBJECT_INFO            = 0x1008,
  44    CMD_GET_OBJECT                 = 0x1009,
  45    CMD_GET_PARTIAL_OBJECT         = 0x101b,
  46
  47    /* response codes */
  48    RES_OK                         = 0x2001,
  49    RES_GENERAL_ERROR              = 0x2002,
  50    RES_SESSION_NOT_OPEN           = 0x2003,
  51    RES_INVALID_TRANSACTION_ID     = 0x2004,
  52    RES_OPERATION_NOT_SUPPORTED    = 0x2005,
  53    RES_PARAMETER_NOT_SUPPORTED    = 0x2006,
  54    RES_INCOMPLETE_TRANSFER        = 0x2007,
  55    RES_INVALID_STORAGE_ID         = 0x2008,
  56    RES_INVALID_OBJECT_HANDLE      = 0x2009,
  57    RES_SPEC_BY_FORMAT_UNSUPPORTED = 0x2014,
  58    RES_INVALID_PARENT_OBJECT      = 0x201a,
  59    RES_INVALID_PARAMETER          = 0x201d,
  60    RES_SESSION_ALREADY_OPEN       = 0x201e,
  61
  62    /* format codes */
  63    FMT_UNDEFINED_OBJECT           = 0x3000,
  64    FMT_ASSOCIATION                = 0x3001,
  65};
  66
  67typedef struct {
  68    uint32_t length;
  69    uint16_t type;
  70    uint16_t code;
  71    uint32_t trans;
  72} QEMU_PACKED mtp_container;
  73
  74/* ----------------------------------------------------------------------- */
  75
  76typedef struct MTPState MTPState;
  77typedef struct MTPControl MTPControl;
  78typedef struct MTPData MTPData;
  79typedef struct MTPObject MTPObject;
  80
  81enum {
  82    EP_DATA_IN = 1,
  83    EP_DATA_OUT,
  84    EP_EVENT,
  85};
  86
  87struct MTPControl {
  88    uint16_t     code;
  89    uint32_t     trans;
  90    int          argc;
  91    uint32_t     argv[5];
  92};
  93
  94struct MTPData {
  95    uint16_t     code;
  96    uint32_t     trans;
  97    uint32_t     offset;
  98    uint32_t     length;
  99    uint32_t     alloc;
 100    uint8_t      *data;
 101    bool         first;
 102    int          fd;
 103};
 104
 105struct MTPObject {
 106    uint32_t     handle;
 107    uint16_t     format;
 108    char         *name;
 109    char         *path;
 110    struct stat  stat;
 111    MTPObject    *parent;
 112    MTPObject    **children;
 113    uint32_t     nchildren;
 114    bool         have_children;
 115    QTAILQ_ENTRY(MTPObject) next;
 116};
 117
 118struct MTPState {
 119    USBDevice    dev;
 120    char         *root;
 121    char         *desc;
 122    uint32_t     flags;
 123
 124    MTPData      *data_in;
 125    MTPData      *data_out;
 126    MTPControl   *result;
 127    uint32_t     session;
 128    uint32_t     next_handle;
 129
 130    QTAILQ_HEAD(, MTPObject) objects;
 131};
 132
 133#define QEMU_STORAGE_ID 0x00010001
 134
 135#define MTP_FLAG_WRITABLE 0
 136
 137#define FLAG_SET(_mtp, _flag)  ((_mtp)->flags & (1 << (_flag)))
 138
 139/* ----------------------------------------------------------------------- */
 140
 141#define MTP_MANUFACTURER  "QEMU"
 142#define MTP_PRODUCT       "QEMU filesharing"
 143
 144enum {
 145    STR_MANUFACTURER = 1,
 146    STR_PRODUCT,
 147    STR_SERIALNUMBER,
 148    STR_MTP,
 149    STR_CONFIG_FULL,
 150    STR_CONFIG_HIGH,
 151    STR_CONFIG_SUPER,
 152};
 153
 154static const USBDescStrings desc_strings = {
 155    [STR_MANUFACTURER] = MTP_MANUFACTURER,
 156    [STR_PRODUCT]      = MTP_PRODUCT,
 157    [STR_SERIALNUMBER] = "34617",
 158    [STR_MTP]          = "MTP",
 159    [STR_CONFIG_FULL]  = "Full speed config (usb 1.1)",
 160    [STR_CONFIG_HIGH]  = "High speed config (usb 2.0)",
 161    [STR_CONFIG_SUPER] = "Super speed config (usb 3.0)",
 162};
 163
 164static const USBDescIface desc_iface_full = {
 165    .bInterfaceNumber              = 0,
 166    .bNumEndpoints                 = 3,
 167    .bInterfaceClass               = USB_CLASS_STILL_IMAGE,
 168    .bInterfaceSubClass            = 0x01,
 169    .bInterfaceProtocol            = 0x01,
 170    .iInterface                    = STR_MTP,
 171    .eps = (USBDescEndpoint[]) {
 172        {
 173            .bEndpointAddress      = USB_DIR_IN | EP_DATA_IN,
 174            .bmAttributes          = USB_ENDPOINT_XFER_BULK,
 175            .wMaxPacketSize        = 64,
 176        },{
 177            .bEndpointAddress      = USB_DIR_OUT | EP_DATA_OUT,
 178            .bmAttributes          = USB_ENDPOINT_XFER_BULK,
 179            .wMaxPacketSize        = 64,
 180        },{
 181            .bEndpointAddress      = USB_DIR_IN | EP_EVENT,
 182            .bmAttributes          = USB_ENDPOINT_XFER_INT,
 183            .wMaxPacketSize        = 8,
 184            .bInterval             = 0x0a,
 185        },
 186    }
 187};
 188
 189static const USBDescDevice desc_device_full = {
 190    .bcdUSB                        = 0x0200,
 191    .bMaxPacketSize0               = 8,
 192    .bNumConfigurations            = 1,
 193    .confs = (USBDescConfig[]) {
 194        {
 195            .bNumInterfaces        = 1,
 196            .bConfigurationValue   = 1,
 197            .iConfiguration        = STR_CONFIG_FULL,
 198            .bmAttributes          = USB_CFG_ATT_ONE | USB_CFG_ATT_WAKEUP,
 199            .bMaxPower             = 2,
 200            .nif = 1,
 201            .ifs = &desc_iface_full,
 202        },
 203    },
 204};
 205
 206static const USBDescIface desc_iface_high = {
 207    .bInterfaceNumber              = 0,
 208    .bNumEndpoints                 = 3,
 209    .bInterfaceClass               = USB_CLASS_STILL_IMAGE,
 210    .bInterfaceSubClass            = 0x01,
 211    .bInterfaceProtocol            = 0x01,
 212    .iInterface                    = STR_MTP,
 213    .eps = (USBDescEndpoint[]) {
 214        {
 215            .bEndpointAddress      = USB_DIR_IN | EP_DATA_IN,
 216            .bmAttributes          = USB_ENDPOINT_XFER_BULK,
 217            .wMaxPacketSize        = 512,
 218        },{
 219            .bEndpointAddress      = USB_DIR_OUT | EP_DATA_OUT,
 220            .bmAttributes          = USB_ENDPOINT_XFER_BULK,
 221            .wMaxPacketSize        = 512,
 222        },{
 223            .bEndpointAddress      = USB_DIR_IN | EP_EVENT,
 224            .bmAttributes          = USB_ENDPOINT_XFER_INT,
 225            .wMaxPacketSize        = 8,
 226            .bInterval             = 0x0a,
 227        },
 228    }
 229};
 230
 231static const USBDescDevice desc_device_high = {
 232    .bcdUSB                        = 0x0200,
 233    .bMaxPacketSize0               = 64,
 234    .bNumConfigurations            = 1,
 235    .confs = (USBDescConfig[]) {
 236        {
 237            .bNumInterfaces        = 1,
 238            .bConfigurationValue   = 1,
 239            .iConfiguration        = STR_CONFIG_HIGH,
 240            .bmAttributes          = USB_CFG_ATT_ONE | USB_CFG_ATT_WAKEUP,
 241            .bMaxPower             = 2,
 242            .nif = 1,
 243            .ifs = &desc_iface_high,
 244        },
 245    },
 246};
 247
 248static const USBDescMSOS desc_msos = {
 249    .CompatibleID = "MTP",
 250    .SelectiveSuspendEnabled = true,
 251};
 252
 253static const USBDesc desc = {
 254    .id = {
 255        .idVendor          = 0x46f4, /* CRC16() of "QEMU" */
 256        .idProduct         = 0x0004,
 257        .bcdDevice         = 0,
 258        .iManufacturer     = STR_MANUFACTURER,
 259        .iProduct          = STR_PRODUCT,
 260        .iSerialNumber     = STR_SERIALNUMBER,
 261    },
 262    .full  = &desc_device_full,
 263    .high  = &desc_device_high,
 264    .str   = desc_strings,
 265    .msos  = &desc_msos,
 266};
 267
 268/* ----------------------------------------------------------------------- */
 269
 270static MTPObject *usb_mtp_object_alloc(MTPState *s, uint32_t handle,
 271                                       MTPObject *parent, char *name)
 272{
 273    MTPObject *o = g_new0(MTPObject, 1);
 274
 275    if (name[0] == '.') {
 276        goto ignore;
 277    }
 278
 279    o->handle = handle;
 280    o->parent = parent;
 281    o->name = g_strdup(name);
 282    if (parent == NULL) {
 283        o->path = g_strdup(name);
 284    } else {
 285        o->path = g_strdup_printf("%s/%s", parent->path, name);
 286    }
 287
 288    if (lstat(o->path, &o->stat) != 0) {
 289        goto ignore;
 290    }
 291    if (S_ISREG(o->stat.st_mode)) {
 292        o->format = FMT_UNDEFINED_OBJECT;
 293    } else if (S_ISDIR(o->stat.st_mode)) {
 294        o->format = FMT_ASSOCIATION;
 295    } else {
 296        goto ignore;
 297    }
 298
 299    if (access(o->path, R_OK) != 0) {
 300        goto ignore;
 301    }
 302
 303    trace_usb_mtp_object_alloc(s->dev.addr, o->handle, o->path);
 304
 305    QTAILQ_INSERT_TAIL(&s->objects, o, next);
 306    return o;
 307
 308ignore:
 309    g_free(o->name);
 310    g_free(o->path);
 311    g_free(o);
 312    return NULL;
 313}
 314
 315static void usb_mtp_object_free(MTPState *s, MTPObject *o)
 316{
 317    int i;
 318
 319    trace_usb_mtp_object_free(s->dev.addr, o->handle, o->path);
 320
 321    QTAILQ_REMOVE(&s->objects, o, next);
 322    for (i = 0; i < o->nchildren; i++) {
 323        usb_mtp_object_free(s, o->children[i]);
 324    }
 325    g_free(o->children);
 326    g_free(o->name);
 327    g_free(o->path);
 328    g_free(o);
 329}
 330
 331static MTPObject *usb_mtp_object_lookup(MTPState *s, uint32_t handle)
 332{
 333    MTPObject *o;
 334
 335    QTAILQ_FOREACH(o, &s->objects, next) {
 336        if (o->handle == handle) {
 337            return o;
 338        }
 339    }
 340    return NULL;
 341}
 342
 343static void usb_mtp_object_readdir(MTPState *s, MTPObject *o)
 344{
 345    struct dirent *entry;
 346    DIR *dir;
 347
 348    if (o->have_children) {
 349        return;
 350    }
 351    o->have_children = true;
 352
 353    dir = opendir(o->path);
 354    if (!dir) {
 355        return;
 356    }
 357    while ((entry = readdir(dir)) != NULL) {
 358        if ((o->nchildren % 32) == 0) {
 359            o->children = g_realloc(o->children,
 360                                    (o->nchildren + 32) * sizeof(MTPObject *));
 361        }
 362        o->children[o->nchildren] =
 363            usb_mtp_object_alloc(s, s->next_handle++, o, entry->d_name);
 364        if (o->children[o->nchildren] != NULL) {
 365            o->nchildren++;
 366        }
 367    }
 368    closedir(dir);
 369}
 370
 371/* ----------------------------------------------------------------------- */
 372
 373static MTPData *usb_mtp_data_alloc(MTPControl *c)
 374{
 375    MTPData *data = g_new0(MTPData, 1);
 376
 377    data->code  = c->code;
 378    data->trans = c->trans;
 379    data->fd    = -1;
 380    data->first = true;
 381    return data;
 382}
 383
 384static void usb_mtp_data_free(MTPData *data)
 385{
 386    if (data == NULL) {
 387        return;
 388    }
 389    if (data->fd != -1) {
 390        close(data->fd);
 391    }
 392    g_free(data->data);
 393    g_free(data);
 394}
 395
 396static void usb_mtp_realloc(MTPData *data, uint32_t bytes)
 397{
 398    if (data->length + bytes <= data->alloc) {
 399        return;
 400    }
 401    data->alloc = (data->length + bytes + 0xff) & ~0xff;
 402    data->data  = g_realloc(data->data, data->alloc);
 403}
 404
 405static void usb_mtp_add_u8(MTPData *data, uint8_t val)
 406{
 407    usb_mtp_realloc(data, 1);
 408    data->data[data->length++] = val;
 409}
 410
 411static void usb_mtp_add_u16(MTPData *data, uint16_t val)
 412{
 413    usb_mtp_realloc(data, 2);
 414    data->data[data->length++] = (val >> 0) & 0xff;
 415    data->data[data->length++] = (val >> 8) & 0xff;
 416}
 417
 418static void usb_mtp_add_u32(MTPData *data, uint32_t val)
 419{
 420    usb_mtp_realloc(data, 4);
 421    data->data[data->length++] = (val >>  0) & 0xff;
 422    data->data[data->length++] = (val >>  8) & 0xff;
 423    data->data[data->length++] = (val >> 16) & 0xff;
 424    data->data[data->length++] = (val >> 24) & 0xff;
 425}
 426
 427static void usb_mtp_add_u64(MTPData *data, uint64_t val)
 428{
 429    usb_mtp_realloc(data, 8);
 430    data->data[data->length++] = (val >>  0) & 0xff;
 431    data->data[data->length++] = (val >>  8) & 0xff;
 432    data->data[data->length++] = (val >> 16) & 0xff;
 433    data->data[data->length++] = (val >> 24) & 0xff;
 434    data->data[data->length++] = (val >> 32) & 0xff;
 435    data->data[data->length++] = (val >> 40) & 0xff;
 436    data->data[data->length++] = (val >> 48) & 0xff;
 437    data->data[data->length++] = (val >> 56) & 0xff;
 438}
 439
 440static void usb_mtp_add_u16_array(MTPData *data, uint32_t len,
 441                                  const uint16_t *vals)
 442{
 443    int i;
 444
 445    usb_mtp_add_u32(data, len);
 446    for (i = 0; i < len; i++) {
 447        usb_mtp_add_u16(data, vals[i]);
 448    }
 449}
 450
 451static void usb_mtp_add_u32_array(MTPData *data, uint32_t len,
 452                                  const uint32_t *vals)
 453{
 454    int i;
 455
 456    usb_mtp_add_u32(data, len);
 457    for (i = 0; i < len; i++) {
 458        usb_mtp_add_u32(data, vals[i]);
 459    }
 460}
 461
 462static void usb_mtp_add_wstr(MTPData *data, const wchar_t *str)
 463{
 464    uint32_t len = wcslen(str);
 465    int i;
 466
 467    if (len > 0) {
 468        len++; /* include terminating L'\0' */
 469    }
 470
 471    usb_mtp_add_u8(data, len);
 472    for (i = 0; i < len; i++) {
 473        usb_mtp_add_u16(data, str[i]);
 474    }
 475}
 476
 477static void usb_mtp_add_str(MTPData *data, const char *str)
 478{
 479    uint32_t len = strlen(str)+1;
 480    wchar_t wstr[len];
 481    size_t ret;
 482
 483    ret = mbstowcs(wstr, str, len);
 484    if (ret == -1) {
 485        usb_mtp_add_wstr(data, L"Oops");
 486    } else {
 487        usb_mtp_add_wstr(data, wstr);
 488    }
 489}
 490
 491static void usb_mtp_add_time(MTPData *data, time_t time)
 492{
 493    char buf[16];
 494    struct tm tm;
 495
 496    gmtime_r(&time, &tm);
 497    strftime(buf, sizeof(buf), "%Y%m%dT%H%M%S", &tm);
 498    usb_mtp_add_str(data, buf);
 499}
 500
 501/* ----------------------------------------------------------------------- */
 502
 503static void usb_mtp_queue_result(MTPState *s, uint16_t code, uint32_t trans,
 504                                 int argc, uint32_t arg0, uint32_t arg1)
 505{
 506    MTPControl *c = g_new0(MTPControl, 1);
 507
 508    c->code  = code;
 509    c->trans = trans;
 510    c->argc  = argc;
 511    if (argc > 0) {
 512        c->argv[0] = arg0;
 513    }
 514    if (argc > 1) {
 515        c->argv[1] = arg1;
 516    }
 517
 518    assert(s->result == NULL);
 519    s->result = c;
 520}
 521
 522/* ----------------------------------------------------------------------- */
 523
 524static MTPData *usb_mtp_get_device_info(MTPState *s, MTPControl *c)
 525{
 526    static const uint16_t ops[] = {
 527        CMD_GET_DEVICE_INFO,
 528        CMD_OPEN_SESSION,
 529        CMD_CLOSE_SESSION,
 530        CMD_GET_STORAGE_IDS,
 531        CMD_GET_STORAGE_INFO,
 532        CMD_GET_NUM_OBJECTS,
 533        CMD_GET_OBJECT_HANDLES,
 534        CMD_GET_OBJECT_INFO,
 535        CMD_GET_OBJECT,
 536        CMD_GET_PARTIAL_OBJECT,
 537    };
 538    static const uint16_t fmt[] = {
 539        FMT_UNDEFINED_OBJECT,
 540        FMT_ASSOCIATION,
 541    };
 542    MTPData *d = usb_mtp_data_alloc(c);
 543
 544    trace_usb_mtp_op_get_device_info(s->dev.addr);
 545
 546    usb_mtp_add_u16(d, 100);
 547    usb_mtp_add_u32(d, 0xffffffff);
 548    usb_mtp_add_u16(d, 0x0101);
 549    usb_mtp_add_wstr(d, L"");
 550    usb_mtp_add_u16(d, 0x0000);
 551
 552    usb_mtp_add_u16_array(d, ARRAY_SIZE(ops), ops);
 553    usb_mtp_add_u16_array(d, 0, NULL);
 554    usb_mtp_add_u16_array(d, 0, NULL);
 555    usb_mtp_add_u16_array(d, 0, NULL);
 556    usb_mtp_add_u16_array(d, ARRAY_SIZE(fmt), fmt);
 557
 558    usb_mtp_add_wstr(d, L"" MTP_MANUFACTURER);
 559    usb_mtp_add_wstr(d, L"" MTP_PRODUCT);
 560    usb_mtp_add_wstr(d, L"0.1");
 561    usb_mtp_add_wstr(d, L"0123456789abcdef0123456789abcdef");
 562
 563    return d;
 564}
 565
 566static MTPData *usb_mtp_get_storage_ids(MTPState *s, MTPControl *c)
 567{
 568    static const uint32_t ids[] = {
 569        QEMU_STORAGE_ID,
 570    };
 571    MTPData *d = usb_mtp_data_alloc(c);
 572
 573    trace_usb_mtp_op_get_storage_ids(s->dev.addr);
 574
 575    usb_mtp_add_u32_array(d, ARRAY_SIZE(ids), ids);
 576
 577    return d;
 578}
 579
 580static MTPData *usb_mtp_get_storage_info(MTPState *s, MTPControl *c)
 581{
 582    MTPData *d = usb_mtp_data_alloc(c);
 583    struct statvfs buf;
 584    int rc;
 585
 586    trace_usb_mtp_op_get_storage_info(s->dev.addr);
 587
 588    if (FLAG_SET(s, MTP_FLAG_WRITABLE)) {
 589        usb_mtp_add_u16(d, 0x0003);
 590        usb_mtp_add_u16(d, 0x0002);
 591        usb_mtp_add_u16(d, 0x0000);
 592    } else {
 593        usb_mtp_add_u16(d, 0x0001);
 594        usb_mtp_add_u16(d, 0x0002);
 595        usb_mtp_add_u16(d, 0x0001);
 596    }
 597
 598    rc = statvfs(s->root, &buf);
 599    if (rc == 0) {
 600        usb_mtp_add_u64(d, (uint64_t)buf.f_frsize * buf.f_blocks);
 601        usb_mtp_add_u64(d, (uint64_t)buf.f_bavail * buf.f_blocks);
 602        usb_mtp_add_u32(d, buf.f_ffree);
 603    } else {
 604        usb_mtp_add_u64(d, 0xffffffff);
 605        usb_mtp_add_u64(d, 0xffffffff);
 606        usb_mtp_add_u32(d, 0xffffffff);
 607    }
 608
 609    usb_mtp_add_str(d, s->desc);
 610    usb_mtp_add_wstr(d, L"123456789abcdef");
 611    return d;
 612}
 613
 614static MTPData *usb_mtp_get_object_handles(MTPState *s, MTPControl *c,
 615                                           MTPObject *o)
 616{
 617    MTPData *d = usb_mtp_data_alloc(c);
 618    uint32_t i, handles[o->nchildren];
 619
 620    trace_usb_mtp_op_get_object_handles(s->dev.addr, o->handle, o->path);
 621
 622    for (i = 0; i < o->nchildren; i++) {
 623        handles[i] = o->children[i]->handle;
 624    }
 625    usb_mtp_add_u32_array(d, o->nchildren, handles);
 626
 627    return d;
 628}
 629
 630static MTPData *usb_mtp_get_object_info(MTPState *s, MTPControl *c,
 631                                        MTPObject *o)
 632{
 633    MTPData *d = usb_mtp_data_alloc(c);
 634
 635    trace_usb_mtp_op_get_object_info(s->dev.addr, o->handle, o->path);
 636
 637    usb_mtp_add_u32(d, QEMU_STORAGE_ID);
 638    usb_mtp_add_u16(d, o->format);
 639    usb_mtp_add_u16(d, 0);
 640    usb_mtp_add_u32(d, o->stat.st_size);
 641
 642    usb_mtp_add_u16(d, 0);
 643    usb_mtp_add_u32(d, 0);
 644    usb_mtp_add_u32(d, 0);
 645    usb_mtp_add_u32(d, 0);
 646    usb_mtp_add_u32(d, 0);
 647    usb_mtp_add_u32(d, 0);
 648    usb_mtp_add_u32(d, 0);
 649
 650    if (o->parent) {
 651        usb_mtp_add_u32(d, o->parent->handle);
 652    } else {
 653        usb_mtp_add_u32(d, 0);
 654    }
 655    if (o->format == FMT_ASSOCIATION) {
 656        usb_mtp_add_u16(d, 0x0001);
 657        usb_mtp_add_u32(d, 0x00000001);
 658        usb_mtp_add_u32(d, 0);
 659    } else {
 660        usb_mtp_add_u16(d, 0);
 661        usb_mtp_add_u32(d, 0);
 662        usb_mtp_add_u32(d, 0);
 663    }
 664
 665    usb_mtp_add_str(d, o->name);
 666    usb_mtp_add_time(d, o->stat.st_ctime);
 667    usb_mtp_add_time(d, o->stat.st_mtime);
 668    usb_mtp_add_wstr(d, L"");
 669
 670    return d;
 671}
 672
 673static MTPData *usb_mtp_get_object(MTPState *s, MTPControl *c,
 674                                   MTPObject *o)
 675{
 676    MTPData *d = usb_mtp_data_alloc(c);
 677
 678    trace_usb_mtp_op_get_object(s->dev.addr, o->handle, o->path);
 679
 680    d->fd = open(o->path, O_RDONLY);
 681    if (d->fd == -1) {
 682        usb_mtp_data_free(d);
 683        return NULL;
 684    }
 685    d->length = o->stat.st_size;
 686    d->alloc  = 512;
 687    d->data   = g_malloc(d->alloc);
 688    return d;
 689}
 690
 691static MTPData *usb_mtp_get_partial_object(MTPState *s, MTPControl *c,
 692                                           MTPObject *o)
 693{
 694    MTPData *d = usb_mtp_data_alloc(c);
 695    off_t offset;
 696
 697    trace_usb_mtp_op_get_partial_object(s->dev.addr, o->handle, o->path,
 698                                        c->argv[1], c->argv[2]);
 699
 700    d->fd = open(o->path, O_RDONLY);
 701    if (d->fd == -1) {
 702        usb_mtp_data_free(d);
 703        return NULL;
 704    }
 705
 706    offset = c->argv[1];
 707    if (offset > o->stat.st_size) {
 708        offset = o->stat.st_size;
 709    }
 710    if (lseek(d->fd, offset, SEEK_SET) < 0) {
 711        usb_mtp_data_free(d);
 712        return NULL;
 713    }
 714
 715    d->length = c->argv[2];
 716    if (d->length > o->stat.st_size - offset) {
 717        d->length = o->stat.st_size - offset;
 718    }
 719
 720    return d;
 721}
 722
 723static void usb_mtp_command(MTPState *s, MTPControl *c)
 724{
 725    MTPData *data_in = NULL;
 726    MTPObject *o;
 727    uint32_t nres = 0, res0 = 0;
 728
 729    /* sanity checks */
 730    if (c->code >= CMD_CLOSE_SESSION && s->session == 0) {
 731        usb_mtp_queue_result(s, RES_SESSION_NOT_OPEN,
 732                             c->trans, 0, 0, 0);
 733        return;
 734    }
 735
 736    /* process commands */
 737    switch (c->code) {
 738    case CMD_GET_DEVICE_INFO:
 739        data_in = usb_mtp_get_device_info(s, c);
 740        break;
 741    case CMD_OPEN_SESSION:
 742        if (s->session) {
 743            usb_mtp_queue_result(s, RES_SESSION_ALREADY_OPEN,
 744                                 c->trans, 1, s->session, 0);
 745            return;
 746        }
 747        if (c->argv[0] == 0) {
 748            usb_mtp_queue_result(s, RES_INVALID_PARAMETER,
 749                                 c->trans, 0, 0, 0);
 750            return;
 751        }
 752        trace_usb_mtp_op_open_session(s->dev.addr);
 753        s->session = c->argv[0];
 754        usb_mtp_object_alloc(s, s->next_handle++, NULL, s->root);
 755        break;
 756    case CMD_CLOSE_SESSION:
 757        trace_usb_mtp_op_close_session(s->dev.addr);
 758        s->session = 0;
 759        s->next_handle = 0;
 760        usb_mtp_object_free(s, QTAILQ_FIRST(&s->objects));
 761        assert(QTAILQ_EMPTY(&s->objects));
 762        break;
 763    case CMD_GET_STORAGE_IDS:
 764        data_in = usb_mtp_get_storage_ids(s, c);
 765        break;
 766    case CMD_GET_STORAGE_INFO:
 767        if (c->argv[0] != QEMU_STORAGE_ID &&
 768            c->argv[0] != 0xffffffff) {
 769            usb_mtp_queue_result(s, RES_INVALID_STORAGE_ID,
 770                                 c->trans, 0, 0, 0);
 771            return;
 772        }
 773        data_in = usb_mtp_get_storage_info(s, c);
 774        break;
 775    case CMD_GET_NUM_OBJECTS:
 776    case CMD_GET_OBJECT_HANDLES:
 777        if (c->argv[0] != QEMU_STORAGE_ID &&
 778            c->argv[0] != 0xffffffff) {
 779            usb_mtp_queue_result(s, RES_INVALID_STORAGE_ID,
 780                                 c->trans, 0, 0, 0);
 781            return;
 782        }
 783        if (c->argv[1] != 0x00000000) {
 784            usb_mtp_queue_result(s, RES_SPEC_BY_FORMAT_UNSUPPORTED,
 785                                 c->trans, 0, 0, 0);
 786            return;
 787        }
 788        if (c->argv[2] == 0x00000000 ||
 789            c->argv[2] == 0xffffffff) {
 790            o = QTAILQ_FIRST(&s->objects);
 791        } else {
 792            o = usb_mtp_object_lookup(s, c->argv[2]);
 793        }
 794        if (o == NULL) {
 795            usb_mtp_queue_result(s, RES_INVALID_OBJECT_HANDLE,
 796                                 c->trans, 0, 0, 0);
 797            return;
 798        }
 799        if (o->format != FMT_ASSOCIATION) {
 800            usb_mtp_queue_result(s, RES_INVALID_PARENT_OBJECT,
 801                                 c->trans, 0, 0, 0);
 802            return;
 803        }
 804        usb_mtp_object_readdir(s, o);
 805        if (c->code == CMD_GET_NUM_OBJECTS) {
 806            trace_usb_mtp_op_get_num_objects(s->dev.addr, o->handle, o->path);
 807            nres = 1;
 808            res0 = o->nchildren;
 809        } else {
 810            data_in = usb_mtp_get_object_handles(s, c, o);
 811        }
 812        break;
 813    case CMD_GET_OBJECT_INFO:
 814        o = usb_mtp_object_lookup(s, c->argv[0]);
 815        if (o == NULL) {
 816            usb_mtp_queue_result(s, RES_INVALID_OBJECT_HANDLE,
 817                                 c->trans, 0, 0, 0);
 818            return;
 819        }
 820        data_in = usb_mtp_get_object_info(s, c, o);
 821        break;
 822    case CMD_GET_OBJECT:
 823        o = usb_mtp_object_lookup(s, c->argv[0]);
 824        if (o == NULL) {
 825            usb_mtp_queue_result(s, RES_INVALID_OBJECT_HANDLE,
 826                                 c->trans, 0, 0, 0);
 827            return;
 828        }
 829        if (o->format == FMT_ASSOCIATION) {
 830            usb_mtp_queue_result(s, RES_INVALID_OBJECT_HANDLE,
 831                                 c->trans, 0, 0, 0);
 832            return;
 833        }
 834        data_in = usb_mtp_get_object(s, c, o);
 835        if (data_in == NULL) {
 836            usb_mtp_queue_result(s, RES_GENERAL_ERROR,
 837                                 c->trans, 0, 0, 0);
 838            return;
 839        }
 840        break;
 841    case CMD_GET_PARTIAL_OBJECT:
 842        o = usb_mtp_object_lookup(s, c->argv[0]);
 843        if (o == NULL) {
 844            usb_mtp_queue_result(s, RES_INVALID_OBJECT_HANDLE,
 845                                 c->trans, 0, 0, 0);
 846            return;
 847        }
 848        if (o->format == FMT_ASSOCIATION) {
 849            usb_mtp_queue_result(s, RES_INVALID_OBJECT_HANDLE,
 850                                 c->trans, 0, 0, 0);
 851            return;
 852        }
 853        data_in = usb_mtp_get_partial_object(s, c, o);
 854        if (data_in == NULL) {
 855            usb_mtp_queue_result(s, RES_GENERAL_ERROR,
 856                                 c->trans, 0, 0, 0);
 857            return;
 858        }
 859        nres = 1;
 860        res0 = data_in->length;
 861        break;
 862    default:
 863        trace_usb_mtp_op_unknown(s->dev.addr, c->code);
 864        usb_mtp_queue_result(s, RES_OPERATION_NOT_SUPPORTED,
 865                             c->trans, 0, 0, 0);
 866        return;
 867    }
 868
 869    /* return results on success */
 870    if (data_in) {
 871        assert(s->data_in == NULL);
 872        s->data_in = data_in;
 873    }
 874    usb_mtp_queue_result(s, RES_OK, c->trans, nres, res0, 0);
 875}
 876
 877/* ----------------------------------------------------------------------- */
 878
 879static void usb_mtp_handle_reset(USBDevice *dev)
 880{
 881    MTPState *s = DO_UPCAST(MTPState, dev, dev);
 882
 883    trace_usb_mtp_reset(s->dev.addr);
 884
 885    s->session = 0;
 886    usb_mtp_data_free(s->data_in);
 887    s->data_in = NULL;
 888    usb_mtp_data_free(s->data_out);
 889    s->data_out = NULL;
 890    g_free(s->result);
 891    s->result = NULL;
 892}
 893
 894static void usb_mtp_handle_control(USBDevice *dev, USBPacket *p,
 895                                   int request, int value, int index,
 896                                   int length, uint8_t *data)
 897{
 898    int ret;
 899
 900    ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
 901    if (ret >= 0) {
 902        return;
 903    }
 904
 905    trace_usb_mtp_stall(dev->addr, "unknown control request");
 906    p->status = USB_RET_STALL;
 907}
 908
 909static void usb_mtp_cancel_packet(USBDevice *dev, USBPacket *p)
 910{
 911    /* we don't use async packets, so this should never be called */
 912    fprintf(stderr, "%s\n", __func__);
 913}
 914
 915static void usb_mtp_handle_data(USBDevice *dev, USBPacket *p)
 916{
 917    MTPState *s = DO_UPCAST(MTPState, dev, dev);
 918    MTPControl cmd;
 919    mtp_container container;
 920    uint32_t params[5];
 921    int i, rc;
 922
 923    switch (p->ep->nr) {
 924    case EP_DATA_IN:
 925        if (s->data_out != NULL) {
 926            /* guest bug */
 927            trace_usb_mtp_stall(s->dev.addr, "awaiting data-out");
 928            p->status = USB_RET_STALL;
 929            return;
 930        }
 931        if (p->iov.size < sizeof(container)) {
 932            trace_usb_mtp_stall(s->dev.addr, "packet too small");
 933            p->status = USB_RET_STALL;
 934            return;
 935        }
 936        if (s->data_in !=  NULL) {
 937            MTPData *d = s->data_in;
 938            int dlen = d->length - d->offset;
 939            if (d->first) {
 940                trace_usb_mtp_data_in(s->dev.addr, d->trans, d->length);
 941                container.length = cpu_to_le32(d->length + sizeof(container));
 942                container.type   = cpu_to_le16(TYPE_DATA);
 943                container.code   = cpu_to_le16(d->code);
 944                container.trans  = cpu_to_le32(d->trans);
 945                usb_packet_copy(p, &container, sizeof(container));
 946                d->first = false;
 947                if (dlen > p->iov.size - sizeof(container)) {
 948                    dlen = p->iov.size - sizeof(container);
 949                }
 950            } else {
 951                if (dlen > p->iov.size) {
 952                    dlen = p->iov.size;
 953                }
 954            }
 955            if (d->fd == -1) {
 956                usb_packet_copy(p, d->data + d->offset, dlen);
 957            } else {
 958                if (d->alloc < p->iov.size) {
 959                    d->alloc = p->iov.size;
 960                    d->data = g_realloc(d->data, d->alloc);
 961                }
 962                rc = read(d->fd, d->data, dlen);
 963                if (rc != dlen) {
 964                    memset(d->data, 0, dlen);
 965                    s->result->code = RES_INCOMPLETE_TRANSFER;
 966                }
 967                usb_packet_copy(p, d->data, dlen);
 968            }
 969            d->offset += dlen;
 970            if (d->offset == d->length) {
 971                usb_mtp_data_free(s->data_in);
 972                s->data_in = NULL;
 973            }
 974        } else if (s->result != NULL) {
 975            MTPControl *r = s->result;
 976            int length = sizeof(container) + r->argc * sizeof(uint32_t);
 977            if (r->code == RES_OK) {
 978                trace_usb_mtp_success(s->dev.addr, r->trans,
 979                                      (r->argc > 0) ? r->argv[0] : 0,
 980                                      (r->argc > 1) ? r->argv[1] : 0);
 981            } else {
 982                trace_usb_mtp_error(s->dev.addr, r->code, r->trans,
 983                                    (r->argc > 0) ? r->argv[0] : 0,
 984                                    (r->argc > 1) ? r->argv[1] : 0);
 985            }
 986            container.length = cpu_to_le32(length);
 987            container.type   = cpu_to_le16(TYPE_RESPONSE);
 988            container.code   = cpu_to_le16(r->code);
 989            container.trans  = cpu_to_le32(r->trans);
 990            for (i = 0; i < r->argc; i++) {
 991                params[i] = cpu_to_le32(r->argv[i]);
 992            }
 993            usb_packet_copy(p, &container, sizeof(container));
 994            usb_packet_copy(p, &params, length - sizeof(container));
 995            g_free(s->result);
 996            s->result = NULL;
 997        }
 998        break;
 999    case EP_DATA_OUT:
1000        if (p->iov.size < sizeof(container)) {
1001            trace_usb_mtp_stall(s->dev.addr, "packet too small");
1002            p->status = USB_RET_STALL;
1003            return;
1004        }
1005        usb_packet_copy(p, &container, sizeof(container));
1006        switch (le16_to_cpu(container.type)) {
1007        case TYPE_COMMAND:
1008            if (s->data_in || s->data_out || s->result) {
1009                trace_usb_mtp_stall(s->dev.addr, "transaction inflight");
1010                p->status = USB_RET_STALL;
1011                return;
1012            }
1013            cmd.code = le16_to_cpu(container.code);
1014            cmd.argc = (le32_to_cpu(container.length) - sizeof(container))
1015                / sizeof(uint32_t);
1016            cmd.trans = le32_to_cpu(container.trans);
1017            if (cmd.argc > ARRAY_SIZE(cmd.argv)) {
1018                cmd.argc = ARRAY_SIZE(cmd.argv);
1019            }
1020            if (p->iov.size < sizeof(container) + cmd.argc * sizeof(uint32_t)) {
1021                trace_usb_mtp_stall(s->dev.addr, "packet too small");
1022                p->status = USB_RET_STALL;
1023                return;
1024            }
1025            usb_packet_copy(p, &params, cmd.argc * sizeof(uint32_t));
1026            for (i = 0; i < cmd.argc; i++) {
1027                cmd.argv[i] = le32_to_cpu(params[i]);
1028            }
1029            trace_usb_mtp_command(s->dev.addr, cmd.code, cmd.trans,
1030                                  (cmd.argc > 0) ? cmd.argv[0] : 0,
1031                                  (cmd.argc > 1) ? cmd.argv[1] : 0,
1032                                  (cmd.argc > 2) ? cmd.argv[2] : 0,
1033                                  (cmd.argc > 3) ? cmd.argv[3] : 0,
1034                                  (cmd.argc > 4) ? cmd.argv[4] : 0);
1035            usb_mtp_command(s, &cmd);
1036            break;
1037        default:
1038            /* not needed as long as the mtp device is read-only */
1039            p->status = USB_RET_STALL;
1040            return;
1041        }
1042        break;
1043    case EP_EVENT:
1044        p->status = USB_RET_NAK;
1045        return;
1046    default:
1047        trace_usb_mtp_stall(s->dev.addr, "invalid endpoint");
1048        p->status = USB_RET_STALL;
1049        return;
1050    }
1051
1052    if (p->actual_length == 0) {
1053        trace_usb_mtp_nak(s->dev.addr, p->ep->nr);
1054        p->status = USB_RET_NAK;
1055        return;
1056    } else {
1057        trace_usb_mtp_xfer(s->dev.addr, p->ep->nr, p->actual_length,
1058                           p->iov.size);
1059        return;
1060    }
1061}
1062
1063static void usb_mtp_realize(USBDevice *dev, Error **errp)
1064{
1065    MTPState *s = DO_UPCAST(MTPState, dev, dev);
1066
1067    usb_desc_create_serial(dev);
1068    usb_desc_init(dev);
1069    QTAILQ_INIT(&s->objects);
1070    if (s->desc == NULL) {
1071        s->desc = strrchr(s->root, '/');
1072        if (s->desc && s->desc[0]) {
1073            s->desc = g_strdup(s->desc + 1);
1074        } else {
1075            s->desc = g_strdup("none");
1076        }
1077    }
1078}
1079
1080static const VMStateDescription vmstate_usb_mtp = {
1081    .name = "usb-mtp",
1082    .unmigratable = 1,
1083    .version_id = 1,
1084    .minimum_version_id = 1,
1085    .fields = (VMStateField[]) {
1086        VMSTATE_USB_DEVICE(dev, MTPState),
1087        VMSTATE_END_OF_LIST()
1088    }
1089};
1090
1091static Property mtp_properties[] = {
1092    DEFINE_PROP_STRING("x-root", MTPState, root),
1093    DEFINE_PROP_STRING("desc", MTPState, desc),
1094    DEFINE_PROP_END_OF_LIST(),
1095};
1096
1097static void usb_mtp_class_initfn(ObjectClass *klass, void *data)
1098{
1099    DeviceClass *dc = DEVICE_CLASS(klass);
1100    USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
1101
1102    uc->realize        = usb_mtp_realize;
1103    uc->product_desc   = "QEMU USB MTP";
1104    uc->usb_desc       = &desc;
1105    uc->cancel_packet  = usb_mtp_cancel_packet;
1106    uc->handle_attach  = usb_desc_attach;
1107    uc->handle_reset   = usb_mtp_handle_reset;
1108    uc->handle_control = usb_mtp_handle_control;
1109    uc->handle_data    = usb_mtp_handle_data;
1110    dc->fw_name = "mtp";
1111    dc->vmsd = &vmstate_usb_mtp;
1112    dc->props = mtp_properties;
1113}
1114
1115static TypeInfo mtp_info = {
1116    .name          = "usb-mtp",
1117    .parent        = TYPE_USB_DEVICE,
1118    .instance_size = sizeof(MTPState),
1119    .class_init    = usb_mtp_class_initfn,
1120};
1121
1122static void usb_mtp_register_types(void)
1123{
1124    type_register_static(&mtp_info);
1125}
1126
1127type_init(usb_mtp_register_types)
1128