Statistics
| Branch: | Revision:

root / hw / usb-msd.c @ ed5a83dd

History | View | Annotate | Download (15.4 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
    int result;
55
    /* For async completion.  */
56
    USBPacket *packet;
57
} MSDState;
58

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

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

    
76
enum {
77
    STR_MANUFACTURER = 1,
78
    STR_PRODUCT,
79
    STR_SERIALNUMBER,
80
};
81

    
82
static const USBDescStrings desc_strings = {
83
    [STR_MANUFACTURER] = "QEMU " QEMU_VERSION,
84
    [STR_PRODUCT]      = "QEMU USB HARDDRIVE",
85
    [STR_SERIALNUMBER] = "1",
86
};
87

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

    
107
static const USBDescDevice desc_device = {
108
    .bcdUSB                        = 0x0100,
109
    .bMaxPacketSize0               = 8,
110
    .bNumConfigurations            = 1,
111
    .confs = (USBDescConfig[]) {
112
        {
113
            .bNumInterfaces        = 1,
114
            .bConfigurationValue   = 1,
115
            .bmAttributes          = 0xc0,
116
            .ifs = &desc_iface0,
117
        },
118
    },
119
};
120

    
121
static const USBDesc desc = {
122
    .id = {
123
        .idVendor          = 0,
124
        .idProduct         = 0,
125
        .bcdDevice         = 0,
126
        .iManufacturer     = STR_MANUFACTURER,
127
        .iProduct          = STR_PRODUCT,
128
        .iSerialNumber     = STR_SERIALNUMBER,
129
    },
130
    .full = &desc_device,
131
    .str  = desc_strings,
132
};
133

    
134
static void usb_msd_copy_data(MSDState *s)
135
{
136
    uint32_t len;
137
    len = s->usb_len;
138
    if (len > s->scsi_len)
139
        len = s->scsi_len;
140
    if (s->mode == USB_MSDM_DATAIN) {
141
        memcpy(s->usb_buf, s->scsi_buf, len);
142
    } else {
143
        memcpy(s->scsi_buf, s->usb_buf, len);
144
    }
145
    s->usb_len -= len;
146
    s->scsi_len -= len;
147
    s->usb_buf += len;
148
    s->scsi_buf += len;
149
    s->data_len -= len;
150
    if (s->scsi_len == 0) {
151
        if (s->mode == USB_MSDM_DATAIN) {
152
            s->scsi_dev->info->read_data(s->scsi_dev, s->tag);
153
        } else if (s->mode == USB_MSDM_DATAOUT) {
154
            s->scsi_dev->info->write_data(s->scsi_dev, s->tag);
155
        }
156
    }
157
}
158

    
159
static void usb_msd_send_status(MSDState *s)
160
{
161
    struct usb_msd_csw csw;
162

    
163
    csw.sig = cpu_to_le32(0x53425355);
164
    csw.tag = cpu_to_le32(s->tag);
165
    csw.residue = s->residue;
166
    csw.status = s->result;
167
    memcpy(s->usb_buf, &csw, 13);
168
}
169

    
170
static void usb_msd_command_complete(SCSIBus *bus, int reason, uint32_t tag,
171
                                     uint32_t arg)
172
{
173
    MSDState *s = DO_UPCAST(MSDState, dev.qdev, bus->qbus.parent);
174
    USBPacket *p = s->packet;
175

    
176
    if (tag != s->tag) {
177
        fprintf(stderr, "usb-msd: Unexpected SCSI Tag 0x%x\n", tag);
178
    }
179
    if (reason == SCSI_REASON_DONE) {
180
        DPRINTF("Command complete %d\n", arg);
181
        s->residue = s->data_len;
182
        s->result = arg != 0;
183
        if (s->packet) {
184
            if (s->data_len == 0 && s->mode == USB_MSDM_DATAOUT) {
185
                /* A deferred packet with no write data remaining must be
186
                   the status read packet.  */
187
                usb_msd_send_status(s);
188
                s->mode = USB_MSDM_CBW;
189
            } else {
190
                if (s->data_len) {
191
                    s->data_len -= s->usb_len;
192
                    if (s->mode == USB_MSDM_DATAIN)
193
                        memset(s->usb_buf, 0, s->usb_len);
194
                    s->usb_len = 0;
195
                }
196
                if (s->data_len == 0)
197
                    s->mode = USB_MSDM_CSW;
198
            }
199
            s->packet = NULL;
200
            usb_packet_complete(p);
201
        } else if (s->data_len == 0) {
202
            s->mode = USB_MSDM_CSW;
203
        }
204
        return;
205
    }
206
    s->scsi_len = arg;
207
    s->scsi_buf = s->scsi_dev->info->get_buf(s->scsi_dev, tag);
208
    if (p) {
209
        usb_msd_copy_data(s);
210
        if (s->usb_len == 0) {
211
            /* Set s->packet to NULL before calling usb_packet_complete
212
               because annother request may be issued before
213
               usb_packet_complete returns.  */
214
            DPRINTF("Packet complete %p\n", p);
215
            s->packet = NULL;
216
            usb_packet_complete(p);
217
        }
218
    }
219
}
220

    
221
static void usb_msd_handle_reset(USBDevice *dev)
222
{
223
    MSDState *s = (MSDState *)dev;
224

    
225
    DPRINTF("Reset\n");
226
    s->mode = USB_MSDM_CBW;
227
}
228

    
229
static int usb_msd_handle_control(USBDevice *dev, int request, int value,
230
                                  int index, int length, uint8_t *data)
231
{
232
    MSDState *s = (MSDState *)dev;
233
    int ret;
234

    
235
    ret = usb_desc_handle_control(dev, request, value, index, length, data);
236
    if (ret >= 0) {
237
        return ret;
238
    }
239

    
240
    ret = 0;
241
    switch (request) {
242
    case DeviceRequest | USB_REQ_GET_INTERFACE:
243
        data[0] = 0;
244
        ret = 1;
245
        break;
246
    case DeviceOutRequest | USB_REQ_SET_INTERFACE:
247
        ret = 0;
248
        break;
249
    case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:
250
        ret = 0;
251
        break;
252
    case InterfaceOutRequest | USB_REQ_SET_INTERFACE:
253
        ret = 0;
254
        break;
255
        /* Class specific requests.  */
256
    case ClassInterfaceOutRequest | MassStorageReset:
257
        /* Reset state ready for the next CBW.  */
258
        s->mode = USB_MSDM_CBW;
259
        ret = 0;
260
        break;
261
    case ClassInterfaceRequest | GetMaxLun:
262
        data[0] = 0;
263
        ret = 1;
264
        break;
265
    default:
266
        ret = USB_RET_STALL;
267
        break;
268
    }
269
    return ret;
270
}
271

    
272
static void usb_msd_cancel_io(USBPacket *p, void *opaque)
273
{
274
    MSDState *s = opaque;
275
    s->scsi_dev->info->cancel_io(s->scsi_dev, s->tag);
276
    s->packet = NULL;
277
    s->scsi_len = 0;
278
}
279

    
280
static int usb_msd_handle_data(USBDevice *dev, USBPacket *p)
281
{
282
    MSDState *s = (MSDState *)dev;
283
    int ret = 0;
284
    struct usb_msd_cbw cbw;
285
    uint8_t devep = p->devep;
286
    uint8_t *data = p->data;
287
    int len = p->len;
288

    
289
    switch (p->pid) {
290
    case USB_TOKEN_OUT:
291
        if (devep != 2)
292
            goto fail;
293

    
294
        switch (s->mode) {
295
        case USB_MSDM_CBW:
296
            if (len != 31) {
297
                fprintf(stderr, "usb-msd: Bad CBW size");
298
                goto fail;
299
            }
300
            memcpy(&cbw, data, 31);
301
            if (le32_to_cpu(cbw.sig) != 0x43425355) {
302
                fprintf(stderr, "usb-msd: Bad signature %08x\n",
303
                        le32_to_cpu(cbw.sig));
304
                goto fail;
305
            }
306
            DPRINTF("Command on LUN %d\n", cbw.lun);
307
            if (cbw.lun != 0) {
308
                fprintf(stderr, "usb-msd: Bad LUN %d\n", cbw.lun);
309
                goto fail;
310
            }
311
            s->tag = le32_to_cpu(cbw.tag);
312
            s->data_len = le32_to_cpu(cbw.data_len);
313
            if (s->data_len == 0) {
314
                s->mode = USB_MSDM_CSW;
315
            } else if (cbw.flags & 0x80) {
316
                s->mode = USB_MSDM_DATAIN;
317
            } else {
318
                s->mode = USB_MSDM_DATAOUT;
319
            }
320
            DPRINTF("Command tag 0x%x flags %08x len %d data %d\n",
321
                    s->tag, cbw.flags, cbw.cmd_len, s->data_len);
322
            s->residue = 0;
323
            s->scsi_dev->info->send_command(s->scsi_dev, s->tag, cbw.cmd, 0);
324
            /* ??? Should check that USB and SCSI data transfer
325
               directions match.  */
326
            if (s->residue == 0) {
327
                if (s->mode == USB_MSDM_DATAIN) {
328
                    s->scsi_dev->info->read_data(s->scsi_dev, s->tag);
329
                } else if (s->mode == USB_MSDM_DATAOUT) {
330
                    s->scsi_dev->info->write_data(s->scsi_dev, s->tag);
331
                }
332
            }
333
            ret = len;
334
            break;
335

    
336
        case USB_MSDM_DATAOUT:
337
            DPRINTF("Data out %d/%d\n", len, s->data_len);
338
            if (len > s->data_len)
339
                goto fail;
340

    
341
            s->usb_buf = data;
342
            s->usb_len = len;
343
            if (s->scsi_len) {
344
                usb_msd_copy_data(s);
345
            }
346
            if (s->residue && s->usb_len) {
347
                s->data_len -= s->usb_len;
348
                if (s->data_len == 0)
349
                    s->mode = USB_MSDM_CSW;
350
                s->usb_len = 0;
351
            }
352
            if (s->usb_len) {
353
                DPRINTF("Deferring packet %p\n", p);
354
                usb_defer_packet(p, usb_msd_cancel_io, s);
355
                s->packet = p;
356
                ret = USB_RET_ASYNC;
357
            } else {
358
                ret = len;
359
            }
360
            break;
361

    
362
        default:
363
            DPRINTF("Unexpected write (len %d)\n", len);
364
            goto fail;
365
        }
366
        break;
367

    
368
    case USB_TOKEN_IN:
369
        if (devep != 1)
370
            goto fail;
371

    
372
        switch (s->mode) {
373
        case USB_MSDM_DATAOUT:
374
            if (s->data_len != 0 || len < 13)
375
                goto fail;
376
            /* Waiting for SCSI write to complete.  */
377
            usb_defer_packet(p, usb_msd_cancel_io, s);
378
            s->packet = p;
379
            ret = USB_RET_ASYNC;
380
            break;
381

    
382
        case USB_MSDM_CSW:
383
            DPRINTF("Command status %d tag 0x%x, len %d\n",
384
                    s->result, s->tag, len);
385
            if (len < 13)
386
                goto fail;
387

    
388
            s->usb_len = len;
389
            s->usb_buf = data;
390
            usb_msd_send_status(s);
391
            s->mode = USB_MSDM_CBW;
392
            ret = 13;
393
            break;
394

    
395
        case USB_MSDM_DATAIN:
396
            DPRINTF("Data in %d/%d\n", len, s->data_len);
397
            if (len > s->data_len)
398
                len = s->data_len;
399
            s->usb_buf = data;
400
            s->usb_len = len;
401
            if (s->scsi_len) {
402
                usb_msd_copy_data(s);
403
            }
404
            if (s->residue && s->usb_len) {
405
                s->data_len -= s->usb_len;
406
                memset(s->usb_buf, 0, s->usb_len);
407
                if (s->data_len == 0)
408
                    s->mode = USB_MSDM_CSW;
409
                s->usb_len = 0;
410
            }
411
            if (s->usb_len) {
412
                DPRINTF("Deferring packet %p\n", p);
413
                usb_defer_packet(p, usb_msd_cancel_io, s);
414
                s->packet = p;
415
                ret = USB_RET_ASYNC;
416
            } else {
417
                ret = len;
418
            }
419
            break;
420

    
421
        default:
422
            DPRINTF("Unexpected read (len %d)\n", len);
423
            goto fail;
424
        }
425
        break;
426

    
427
    default:
428
        DPRINTF("Bad token\n");
429
    fail:
430
        ret = USB_RET_STALL;
431
        break;
432
    }
433

    
434
    return ret;
435
}
436

    
437
static void usb_msd_password_cb(void *opaque, int err)
438
{
439
    MSDState *s = opaque;
440

    
441
    if (!err)
442
        usb_device_attach(&s->dev);
443
    else
444
        qdev_unplug(&s->dev.qdev);
445
}
446

    
447
static int usb_msd_initfn(USBDevice *dev)
448
{
449
    MSDState *s = DO_UPCAST(MSDState, dev, dev);
450
    BlockDriverState *bs = s->conf.bs;
451
    DriveInfo *dinfo;
452

    
453
    if (!bs) {
454
        error_report("usb-msd: drive property not set");
455
        return -1;
456
    }
457

    
458
    /*
459
     * Hack alert: this pretends to be a block device, but it's really
460
     * a SCSI bus that can serve only a single device, which it
461
     * creates automatically.  But first it needs to detach from its
462
     * blockdev, or else scsi_bus_legacy_add_drive() dies when it
463
     * attaches again.
464
     *
465
     * The hack is probably a bad idea.
466
     */
467
    bdrv_detach(bs, &s->dev.qdev);
468
    s->conf.bs = NULL;
469

    
470
    dinfo = drive_get_by_blockdev(bs);
471
    if (dinfo && dinfo->serial) {
472
        usb_desc_set_string(dev, STR_SERIALNUMBER, dinfo->serial);
473
    }
474

    
475
    usb_desc_init(dev);
476
    scsi_bus_new(&s->bus, &s->dev.qdev, 0, 1, usb_msd_command_complete);
477
    s->scsi_dev = scsi_bus_legacy_add_drive(&s->bus, bs, 0);
478
    if (!s->scsi_dev) {
479
        return -1;
480
    }
481
    s->bus.qbus.allow_hotplug = 0;
482
    usb_msd_handle_reset(dev);
483

    
484
    if (bdrv_key_required(bs)) {
485
        if (cur_mon) {
486
            monitor_read_bdrv_key_start(cur_mon, bs, usb_msd_password_cb, s);
487
            s->dev.auto_attach = 0;
488
        } else {
489
            autostart = 0;
490
        }
491
    }
492

    
493
    return 0;
494
}
495

    
496
static USBDevice *usb_msd_init(const char *filename)
497
{
498
    static int nr=0;
499
    char id[8];
500
    QemuOpts *opts;
501
    DriveInfo *dinfo;
502
    USBDevice *dev;
503
    int fatal_error;
504
    const char *p1;
505
    char fmt[32];
506

    
507
    /* parse -usbdevice disk: syntax into drive opts */
508
    snprintf(id, sizeof(id), "usb%d", nr++);
509
    opts = qemu_opts_create(qemu_find_opts("drive"), id, 0);
510

    
511
    p1 = strchr(filename, ':');
512
    if (p1++) {
513
        const char *p2;
514

    
515
        if (strstart(filename, "format=", &p2)) {
516
            int len = MIN(p1 - p2, sizeof(fmt));
517
            pstrcpy(fmt, len, p2);
518
            qemu_opt_set(opts, "format", fmt);
519
        } else if (*filename != ':') {
520
            printf("unrecognized USB mass-storage option %s\n", filename);
521
            return NULL;
522
        }
523
        filename = p1;
524
    }
525
    if (!*filename) {
526
        printf("block device specification needed\n");
527
        return NULL;
528
    }
529
    qemu_opt_set(opts, "file", filename);
530
    qemu_opt_set(opts, "if", "none");
531

    
532
    /* create host drive */
533
    dinfo = drive_init(opts, 0, &fatal_error);
534
    if (!dinfo) {
535
        qemu_opts_del(opts);
536
        return NULL;
537
    }
538

    
539
    /* create guest device */
540
    dev = usb_create(NULL /* FIXME */, "usb-storage");
541
    if (!dev) {
542
        return NULL;
543
    }
544
    if (qdev_prop_set_drive(&dev->qdev, "drive", dinfo->bdrv) < 0) {
545
        qdev_free(&dev->qdev);
546
        return NULL;
547
    }
548
    if (qdev_init(&dev->qdev) < 0)
549
        return NULL;
550

    
551
    return dev;
552
}
553

    
554
static struct USBDeviceInfo msd_info = {
555
    .product_desc   = "QEMU USB MSD",
556
    .qdev.name      = "usb-storage",
557
    .qdev.size      = sizeof(MSDState),
558
    .usb_desc       = &desc,
559
    .init           = usb_msd_initfn,
560
    .handle_packet  = usb_generic_handle_packet,
561
    .handle_reset   = usb_msd_handle_reset,
562
    .handle_control = usb_msd_handle_control,
563
    .handle_data    = usb_msd_handle_data,
564
    .usbdevice_name = "disk",
565
    .usbdevice_init = usb_msd_init,
566
    .qdev.props     = (Property[]) {
567
        DEFINE_BLOCK_PROPERTIES(MSDState, conf),
568
        DEFINE_PROP_END_OF_LIST(),
569
    },
570
};
571

    
572
static void usb_msd_register_devices(void)
573
{
574
    usb_qdev_register(&msd_info);
575
}
576
device_init(usb_msd_register_devices)