Statistics
| Branch: | Revision:

root / hw / usb-msd.c @ 15d7dc4f

History | View | Annotate | Download (17 kB)

1
/*
2
 * USB Mass Storage Device emulation
3
 *
4
 * Copyright (c) 2006 CodeSourcery.
5
 * Written by Paul Brook
6
 *
7
 * This code is licenced under the LGPL.
8
 */
9

    
10
#include "qemu-common.h"
11
#include "qemu-option.h"
12
#include "qemu-config.h"
13
#include "usb.h"
14
#include "usb-desc.h"
15
#include "scsi.h"
16
#include "console.h"
17
#include "monitor.h"
18
#include "sysemu.h"
19
#include "blockdev.h"
20

    
21
//#define DEBUG_MSD
22

    
23
#ifdef DEBUG_MSD
24
#define DPRINTF(fmt, ...) \
25
do { printf("usb-msd: " fmt , ## __VA_ARGS__); } while (0)
26
#else
27
#define DPRINTF(fmt, ...) do {} while(0)
28
#endif
29

    
30
/* USB requests.  */
31
#define MassStorageReset  0xff
32
#define GetMaxLun         0xfe
33

    
34
enum USBMSDMode {
35
    USB_MSDM_CBW, /* Command Block.  */
36
    USB_MSDM_DATAOUT, /* Tranfer data to device.  */
37
    USB_MSDM_DATAIN, /* Transfer data from device.  */
38
    USB_MSDM_CSW /* Command Status.  */
39
};
40

    
41
typedef struct {
42
    USBDevice dev;
43
    enum USBMSDMode mode;
44
    uint32_t scsi_len;
45
    uint8_t *scsi_buf;
46
    uint32_t usb_len;
47
    uint8_t *usb_buf;
48
    uint32_t data_len;
49
    uint32_t residue;
50
    uint32_t tag;
51
    SCSIBus bus;
52
    BlockConf conf;
53
    SCSIDevice *scsi_dev;
54
    uint32_t removable;
55
    int result;
56
    /* For async completion.  */
57
    USBPacket *packet;
58
} MSDState;
59

    
60
struct usb_msd_cbw {
61
    uint32_t sig;
62
    uint32_t tag;
63
    uint32_t data_len;
64
    uint8_t flags;
65
    uint8_t lun;
66
    uint8_t cmd_len;
67
    uint8_t cmd[16];
68
};
69

    
70
struct usb_msd_csw {
71
    uint32_t sig;
72
    uint32_t tag;
73
    uint32_t residue;
74
    uint8_t status;
75
};
76

    
77
enum {
78
    STR_MANUFACTURER = 1,
79
    STR_PRODUCT,
80
    STR_SERIALNUMBER,
81
    STR_CONFIG_FULL,
82
    STR_CONFIG_HIGH,
83
};
84

    
85
static const USBDescStrings desc_strings = {
86
    [STR_MANUFACTURER] = "QEMU " QEMU_VERSION,
87
    [STR_PRODUCT]      = "QEMU USB HARDDRIVE",
88
    [STR_SERIALNUMBER] = "1",
89
    [STR_CONFIG_FULL]  = "Full speed config (usb 1.1)",
90
    [STR_CONFIG_HIGH]  = "High speed config (usb 2.0)",
91
};
92

    
93
static const USBDescIface desc_iface_full = {
94
    .bInterfaceNumber              = 0,
95
    .bNumEndpoints                 = 2,
96
    .bInterfaceClass               = USB_CLASS_MASS_STORAGE,
97
    .bInterfaceSubClass            = 0x06, /* SCSI */
98
    .bInterfaceProtocol            = 0x50, /* Bulk */
99
    .eps = (USBDescEndpoint[]) {
100
        {
101
            .bEndpointAddress      = USB_DIR_IN | 0x01,
102
            .bmAttributes          = USB_ENDPOINT_XFER_BULK,
103
            .wMaxPacketSize        = 64,
104
        },{
105
            .bEndpointAddress      = USB_DIR_OUT | 0x02,
106
            .bmAttributes          = USB_ENDPOINT_XFER_BULK,
107
            .wMaxPacketSize        = 64,
108
        },
109
    }
110
};
111

    
112
static const USBDescDevice desc_device_full = {
113
    .bcdUSB                        = 0x0200,
114
    .bMaxPacketSize0               = 8,
115
    .bNumConfigurations            = 1,
116
    .confs = (USBDescConfig[]) {
117
        {
118
            .bNumInterfaces        = 1,
119
            .bConfigurationValue   = 1,
120
            .iConfiguration        = STR_CONFIG_FULL,
121
            .bmAttributes          = 0xc0,
122
            .ifs = &desc_iface_full,
123
        },
124
    },
125
};
126

    
127
static const USBDescIface desc_iface_high = {
128
    .bInterfaceNumber              = 0,
129
    .bNumEndpoints                 = 2,
130
    .bInterfaceClass               = USB_CLASS_MASS_STORAGE,
131
    .bInterfaceSubClass            = 0x06, /* SCSI */
132
    .bInterfaceProtocol            = 0x50, /* Bulk */
133
    .eps = (USBDescEndpoint[]) {
134
        {
135
            .bEndpointAddress      = USB_DIR_IN | 0x01,
136
            .bmAttributes          = USB_ENDPOINT_XFER_BULK,
137
            .wMaxPacketSize        = 512,
138
        },{
139
            .bEndpointAddress      = USB_DIR_OUT | 0x02,
140
            .bmAttributes          = USB_ENDPOINT_XFER_BULK,
141
            .wMaxPacketSize        = 512,
142
        },
143
    }
144
};
145

    
146
static const USBDescDevice desc_device_high = {
147
    .bcdUSB                        = 0x0200,
148
    .bMaxPacketSize0               = 64,
149
    .bNumConfigurations            = 1,
150
    .confs = (USBDescConfig[]) {
151
        {
152
            .bNumInterfaces        = 1,
153
            .bConfigurationValue   = 1,
154
            .iConfiguration        = STR_CONFIG_HIGH,
155
            .bmAttributes          = 0xc0,
156
            .ifs = &desc_iface_high,
157
        },
158
    },
159
};
160

    
161
static const USBDesc desc = {
162
    .id = {
163
        .idVendor          = 0,
164
        .idProduct         = 0,
165
        .bcdDevice         = 0,
166
        .iManufacturer     = STR_MANUFACTURER,
167
        .iProduct          = STR_PRODUCT,
168
        .iSerialNumber     = STR_SERIALNUMBER,
169
    },
170
    .full = &desc_device_full,
171
    .high = &desc_device_high,
172
    .str  = desc_strings,
173
};
174

    
175
static void usb_msd_copy_data(MSDState *s)
176
{
177
    uint32_t len;
178
    len = s->usb_len;
179
    if (len > s->scsi_len)
180
        len = s->scsi_len;
181
    if (s->mode == USB_MSDM_DATAIN) {
182
        memcpy(s->usb_buf, s->scsi_buf, len);
183
    } else {
184
        memcpy(s->scsi_buf, s->usb_buf, len);
185
    }
186
    s->usb_len -= len;
187
    s->scsi_len -= len;
188
    s->usb_buf += len;
189
    s->scsi_buf += len;
190
    s->data_len -= len;
191
    if (s->scsi_len == 0 || s->data_len == 0) {
192
        if (s->mode == USB_MSDM_DATAIN) {
193
            s->scsi_dev->info->read_data(s->scsi_dev, s->tag);
194
        } else if (s->mode == USB_MSDM_DATAOUT) {
195
            s->scsi_dev->info->write_data(s->scsi_dev, s->tag);
196
        }
197
    }
198
}
199

    
200
static void usb_msd_send_status(MSDState *s, USBPacket *p)
201
{
202
    struct usb_msd_csw csw;
203
    int len;
204

    
205
    csw.sig = cpu_to_le32(0x53425355);
206
    csw.tag = cpu_to_le32(s->tag);
207
    csw.residue = s->residue;
208
    csw.status = s->result;
209

    
210
    len = MIN(sizeof(csw), p->len);
211
    memcpy(p->data, &csw, len);
212
}
213

    
214
static void usb_msd_command_complete(SCSIBus *bus, int reason, uint32_t tag,
215
                                     uint32_t arg)
216
{
217
    MSDState *s = DO_UPCAST(MSDState, dev.qdev, bus->qbus.parent);
218
    USBPacket *p = s->packet;
219

    
220
    if (tag != s->tag) {
221
        fprintf(stderr, "usb-msd: Unexpected SCSI Tag 0x%x\n", tag);
222
    }
223
    if (reason == SCSI_REASON_DONE) {
224
        DPRINTF("Command complete %d\n", arg);
225
        s->residue = s->data_len;
226
        s->result = arg != 0;
227
        if (s->packet) {
228
            if (s->data_len == 0 && s->mode == USB_MSDM_DATAOUT) {
229
                /* A deferred packet with no write data remaining must be
230
                   the status read packet.  */
231
                usb_msd_send_status(s, p);
232
                s->mode = USB_MSDM_CBW;
233
            } else {
234
                if (s->data_len) {
235
                    s->data_len -= s->usb_len;
236
                    if (s->mode == USB_MSDM_DATAIN)
237
                        memset(s->usb_buf, 0, s->usb_len);
238
                    s->usb_len = 0;
239
                }
240
                if (s->data_len == 0)
241
                    s->mode = USB_MSDM_CSW;
242
            }
243
            s->packet = NULL;
244
            usb_packet_complete(p);
245
        } else if (s->data_len == 0) {
246
            s->mode = USB_MSDM_CSW;
247
        }
248
        return;
249
    }
250
    s->scsi_len = arg;
251
    s->scsi_buf = s->scsi_dev->info->get_buf(s->scsi_dev, tag);
252
    if (p) {
253
        usb_msd_copy_data(s);
254
        if (s->usb_len == 0) {
255
            /* Set s->packet to NULL before calling usb_packet_complete
256
               because annother request may be issued before
257
               usb_packet_complete returns.  */
258
            DPRINTF("Packet complete %p\n", p);
259
            s->packet = NULL;
260
            usb_packet_complete(p);
261
        }
262
    }
263
}
264

    
265
static void usb_msd_handle_reset(USBDevice *dev)
266
{
267
    MSDState *s = (MSDState *)dev;
268

    
269
    DPRINTF("Reset\n");
270
    s->mode = USB_MSDM_CBW;
271
}
272

    
273
static int usb_msd_handle_control(USBDevice *dev, int request, int value,
274
                                  int index, int length, uint8_t *data)
275
{
276
    MSDState *s = (MSDState *)dev;
277
    int ret;
278

    
279
    ret = usb_desc_handle_control(dev, request, value, index, length, data);
280
    if (ret >= 0) {
281
        return ret;
282
    }
283

    
284
    ret = 0;
285
    switch (request) {
286
    case DeviceRequest | USB_REQ_GET_INTERFACE:
287
        data[0] = 0;
288
        ret = 1;
289
        break;
290
    case DeviceOutRequest | USB_REQ_SET_INTERFACE:
291
        ret = 0;
292
        break;
293
    case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:
294
        ret = 0;
295
        break;
296
    case InterfaceOutRequest | USB_REQ_SET_INTERFACE:
297
        ret = 0;
298
        break;
299
        /* Class specific requests.  */
300
    case ClassInterfaceOutRequest | MassStorageReset:
301
        /* Reset state ready for the next CBW.  */
302
        s->mode = USB_MSDM_CBW;
303
        ret = 0;
304
        break;
305
    case ClassInterfaceRequest | GetMaxLun:
306
        data[0] = 0;
307
        ret = 1;
308
        break;
309
    default:
310
        ret = USB_RET_STALL;
311
        break;
312
    }
313
    return ret;
314
}
315

    
316
static void usb_msd_cancel_io(USBPacket *p, void *opaque)
317
{
318
    MSDState *s = opaque;
319
    s->scsi_dev->info->cancel_io(s->scsi_dev, s->tag);
320
    s->packet = NULL;
321
    s->scsi_len = 0;
322
}
323

    
324
static int usb_msd_handle_data(USBDevice *dev, USBPacket *p)
325
{
326
    MSDState *s = (MSDState *)dev;
327
    int ret = 0;
328
    struct usb_msd_cbw cbw;
329
    uint8_t devep = p->devep;
330
    uint8_t *data = p->data;
331
    int len = p->len;
332

    
333
    switch (p->pid) {
334
    case USB_TOKEN_OUT:
335
        if (devep != 2)
336
            goto fail;
337

    
338
        switch (s->mode) {
339
        case USB_MSDM_CBW:
340
            if (len != 31) {
341
                fprintf(stderr, "usb-msd: Bad CBW size");
342
                goto fail;
343
            }
344
            memcpy(&cbw, data, 31);
345
            if (le32_to_cpu(cbw.sig) != 0x43425355) {
346
                fprintf(stderr, "usb-msd: Bad signature %08x\n",
347
                        le32_to_cpu(cbw.sig));
348
                goto fail;
349
            }
350
            DPRINTF("Command on LUN %d\n", cbw.lun);
351
            if (cbw.lun != 0) {
352
                fprintf(stderr, "usb-msd: Bad LUN %d\n", cbw.lun);
353
                goto fail;
354
            }
355
            s->tag = le32_to_cpu(cbw.tag);
356
            s->data_len = le32_to_cpu(cbw.data_len);
357
            if (s->data_len == 0) {
358
                s->mode = USB_MSDM_CSW;
359
            } else if (cbw.flags & 0x80) {
360
                s->mode = USB_MSDM_DATAIN;
361
            } else {
362
                s->mode = USB_MSDM_DATAOUT;
363
            }
364
            DPRINTF("Command tag 0x%x flags %08x len %d data %d\n",
365
                    s->tag, cbw.flags, cbw.cmd_len, s->data_len);
366
            s->residue = 0;
367
            s->scsi_dev->info->send_command(s->scsi_dev, s->tag, cbw.cmd, 0);
368
            /* ??? Should check that USB and SCSI data transfer
369
               directions match.  */
370
            if (s->residue == 0) {
371
                if (s->mode == USB_MSDM_DATAIN) {
372
                    s->scsi_dev->info->read_data(s->scsi_dev, s->tag);
373
                } else if (s->mode == USB_MSDM_DATAOUT) {
374
                    s->scsi_dev->info->write_data(s->scsi_dev, s->tag);
375
                }
376
            }
377
            ret = len;
378
            break;
379

    
380
        case USB_MSDM_DATAOUT:
381
            DPRINTF("Data out %d/%d\n", len, s->data_len);
382
            if (len > s->data_len)
383
                goto fail;
384

    
385
            s->usb_buf = data;
386
            s->usb_len = len;
387
            if (s->scsi_len) {
388
                usb_msd_copy_data(s);
389
            }
390
            if (s->residue && s->usb_len) {
391
                s->data_len -= s->usb_len;
392
                if (s->data_len == 0)
393
                    s->mode = USB_MSDM_CSW;
394
                s->usb_len = 0;
395
            }
396
            if (s->usb_len) {
397
                DPRINTF("Deferring packet %p\n", p);
398
                usb_defer_packet(p, usb_msd_cancel_io, s);
399
                s->packet = p;
400
                ret = USB_RET_ASYNC;
401
            } else {
402
                ret = len;
403
            }
404
            break;
405

    
406
        default:
407
            DPRINTF("Unexpected write (len %d)\n", len);
408
            goto fail;
409
        }
410
        break;
411

    
412
    case USB_TOKEN_IN:
413
        if (devep != 1)
414
            goto fail;
415

    
416
        switch (s->mode) {
417
        case USB_MSDM_DATAOUT:
418
            if (s->data_len != 0 || len < 13)
419
                goto fail;
420
            /* Waiting for SCSI write to complete.  */
421
            usb_defer_packet(p, usb_msd_cancel_io, s);
422
            s->packet = p;
423
            ret = USB_RET_ASYNC;
424
            break;
425

    
426
        case USB_MSDM_CSW:
427
            DPRINTF("Command status %d tag 0x%x, len %d\n",
428
                    s->result, s->tag, len);
429
            if (len < 13)
430
                goto fail;
431

    
432
            usb_msd_send_status(s, p);
433
            s->mode = USB_MSDM_CBW;
434
            ret = 13;
435
            break;
436

    
437
        case USB_MSDM_DATAIN:
438
            DPRINTF("Data in %d/%d, scsi_len %d\n", len, s->data_len, s->scsi_len);
439
            if (len > s->data_len)
440
                len = s->data_len;
441
            s->usb_buf = data;
442
            s->usb_len = len;
443
            if (s->scsi_len) {
444
                usb_msd_copy_data(s);
445
            }
446
            if (s->residue && s->usb_len) {
447
                s->data_len -= s->usb_len;
448
                memset(s->usb_buf, 0, s->usb_len);
449
                if (s->data_len == 0)
450
                    s->mode = USB_MSDM_CSW;
451
                s->usb_len = 0;
452
            }
453
            if (s->usb_len) {
454
                DPRINTF("Deferring packet %p\n", p);
455
                usb_defer_packet(p, usb_msd_cancel_io, s);
456
                s->packet = p;
457
                ret = USB_RET_ASYNC;
458
            } else {
459
                ret = len;
460
            }
461
            break;
462

    
463
        default:
464
            DPRINTF("Unexpected read (len %d)\n", len);
465
            goto fail;
466
        }
467
        break;
468

    
469
    default:
470
        DPRINTF("Bad token\n");
471
    fail:
472
        ret = USB_RET_STALL;
473
        break;
474
    }
475

    
476
    return ret;
477
}
478

    
479
static void usb_msd_password_cb(void *opaque, int err)
480
{
481
    MSDState *s = opaque;
482

    
483
    if (!err)
484
        usb_device_attach(&s->dev);
485
    else
486
        qdev_unplug(&s->dev.qdev);
487
}
488

    
489
static int usb_msd_initfn(USBDevice *dev)
490
{
491
    MSDState *s = DO_UPCAST(MSDState, dev, dev);
492
    BlockDriverState *bs = s->conf.bs;
493
    DriveInfo *dinfo;
494

    
495
    if (!bs) {
496
        error_report("usb-msd: drive property not set");
497
        return -1;
498
    }
499

    
500
    /*
501
     * Hack alert: this pretends to be a block device, but it's really
502
     * a SCSI bus that can serve only a single device, which it
503
     * creates automatically.  But first it needs to detach from its
504
     * blockdev, or else scsi_bus_legacy_add_drive() dies when it
505
     * attaches again.
506
     *
507
     * The hack is probably a bad idea.
508
     */
509
    bdrv_detach(bs, &s->dev.qdev);
510
    s->conf.bs = NULL;
511

    
512
    dinfo = drive_get_by_blockdev(bs);
513
    if (dinfo && dinfo->serial) {
514
        usb_desc_set_string(dev, STR_SERIALNUMBER, dinfo->serial);
515
    }
516

    
517
    usb_desc_init(dev);
518
    scsi_bus_new(&s->bus, &s->dev.qdev, 0, 1, usb_msd_command_complete);
519
    s->scsi_dev = scsi_bus_legacy_add_drive(&s->bus, bs, 0, !!s->removable);
520
    if (!s->scsi_dev) {
521
        return -1;
522
    }
523
    s->bus.qbus.allow_hotplug = 0;
524
    usb_msd_handle_reset(dev);
525

    
526
    if (bdrv_key_required(bs)) {
527
        if (cur_mon) {
528
            monitor_read_bdrv_key_start(cur_mon, bs, usb_msd_password_cb, s);
529
            s->dev.auto_attach = 0;
530
        } else {
531
            autostart = 0;
532
        }
533
    }
534

    
535
    add_boot_device_path(s->conf.bootindex, &dev->qdev, "/disk@0,0");
536
    return 0;
537
}
538

    
539
static USBDevice *usb_msd_init(const char *filename)
540
{
541
    static int nr=0;
542
    char id[8];
543
    QemuOpts *opts;
544
    DriveInfo *dinfo;
545
    USBDevice *dev;
546
    const char *p1;
547
    char fmt[32];
548

    
549
    /* parse -usbdevice disk: syntax into drive opts */
550
    snprintf(id, sizeof(id), "usb%d", nr++);
551
    opts = qemu_opts_create(qemu_find_opts("drive"), id, 0);
552

    
553
    p1 = strchr(filename, ':');
554
    if (p1++) {
555
        const char *p2;
556

    
557
        if (strstart(filename, "format=", &p2)) {
558
            int len = MIN(p1 - p2, sizeof(fmt));
559
            pstrcpy(fmt, len, p2);
560
            qemu_opt_set(opts, "format", fmt);
561
        } else if (*filename != ':') {
562
            printf("unrecognized USB mass-storage option %s\n", filename);
563
            return NULL;
564
        }
565
        filename = p1;
566
    }
567
    if (!*filename) {
568
        printf("block device specification needed\n");
569
        return NULL;
570
    }
571
    qemu_opt_set(opts, "file", filename);
572
    qemu_opt_set(opts, "if", "none");
573

    
574
    /* create host drive */
575
    dinfo = drive_init(opts, 0);
576
    if (!dinfo) {
577
        qemu_opts_del(opts);
578
        return NULL;
579
    }
580

    
581
    /* create guest device */
582
    dev = usb_create(NULL /* FIXME */, "usb-storage");
583
    if (!dev) {
584
        return NULL;
585
    }
586
    if (qdev_prop_set_drive(&dev->qdev, "drive", dinfo->bdrv) < 0) {
587
        qdev_free(&dev->qdev);
588
        return NULL;
589
    }
590
    if (qdev_init(&dev->qdev) < 0)
591
        return NULL;
592

    
593
    return dev;
594
}
595

    
596
static struct USBDeviceInfo msd_info = {
597
    .product_desc   = "QEMU USB MSD",
598
    .qdev.name      = "usb-storage",
599
    .qdev.fw_name      = "storage",
600
    .qdev.size      = sizeof(MSDState),
601
    .usb_desc       = &desc,
602
    .init           = usb_msd_initfn,
603
    .handle_packet  = usb_generic_handle_packet,
604
    .handle_attach  = usb_desc_attach,
605
    .handle_reset   = usb_msd_handle_reset,
606
    .handle_control = usb_msd_handle_control,
607
    .handle_data    = usb_msd_handle_data,
608
    .usbdevice_name = "disk",
609
    .usbdevice_init = usb_msd_init,
610
    .qdev.props     = (Property[]) {
611
        DEFINE_BLOCK_PROPERTIES(MSDState, conf),
612
        DEFINE_PROP_BIT("removable", MSDState, removable, 0, false),
613
        DEFINE_PROP_END_OF_LIST(),
614
    },
615
};
616

    
617
static void usb_msd_register_devices(void)
618
{
619
    usb_qdev_register(&msd_info);
620
}
621
device_init(usb_msd_register_devices)