Statistics
| Branch: | Revision:

root / hw / usb-msd.c @ 428c149b

History | View | Annotate | Download (17.3 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 "block.h"
15
#include "scsi.h"
16
#include "console.h"
17
#include "monitor.h"
18

    
19
//#define DEBUG_MSD
20

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

    
28
/* USB requests.  */
29
#define MassStorageReset  0xff
30
#define GetMaxLun         0xfe
31

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

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

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

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

    
74
static const uint8_t qemu_msd_dev_descriptor[] = {
75
        0x12,       /*  u8 bLength; */
76
        0x01,       /*  u8 bDescriptorType; Device */
77
        0x00, 0x01, /*  u16 bcdUSB; v1.0 */
78

    
79
        0x00,            /*  u8  bDeviceClass; */
80
        0x00,            /*  u8  bDeviceSubClass; */
81
        0x00,       /*  u8  bDeviceProtocol; [ low/full speeds only ] */
82
        0x08,       /*  u8  bMaxPacketSize0; 8 Bytes */
83

    
84
        /* Vendor and product id are arbitrary.  */
85
        0x00, 0x00, /*  u16 idVendor; */
86
         0x00, 0x00, /*  u16 idProduct; */
87
        0x00, 0x00, /*  u16 bcdDevice */
88

    
89
        0x01,       /*  u8  iManufacturer; */
90
        0x02,       /*  u8  iProduct; */
91
        0x03,       /*  u8  iSerialNumber; */
92
        0x01        /*  u8  bNumConfigurations; */
93
};
94

    
95
static const uint8_t qemu_msd_config_descriptor[] = {
96

    
97
        /* one configuration */
98
        0x09,       /*  u8  bLength; */
99
        0x02,       /*  u8  bDescriptorType; Configuration */
100
        0x20, 0x00, /*  u16 wTotalLength; */
101
        0x01,       /*  u8  bNumInterfaces; (1) */
102
        0x01,       /*  u8  bConfigurationValue; */
103
        0x00,       /*  u8  iConfiguration; */
104
        0xc0,       /*  u8  bmAttributes;
105
                                 Bit 7: must be set,
106
                                     6: Self-powered,
107
                                     5: Remote wakeup,
108
                                     4..0: resvd */
109
        0x00,       /*  u8  MaxPower; */
110

    
111
        /* one interface */
112
        0x09,       /*  u8  if_bLength; */
113
        0x04,       /*  u8  if_bDescriptorType; Interface */
114
        0x00,       /*  u8  if_bInterfaceNumber; */
115
        0x00,       /*  u8  if_bAlternateSetting; */
116
        0x02,       /*  u8  if_bNumEndpoints; */
117
        0x08,       /*  u8  if_bInterfaceClass; MASS STORAGE */
118
        0x06,       /*  u8  if_bInterfaceSubClass; SCSI */
119
        0x50,       /*  u8  if_bInterfaceProtocol; Bulk Only */
120
        0x00,       /*  u8  if_iInterface; */
121

    
122
        /* Bulk-In endpoint */
123
        0x07,       /*  u8  ep_bLength; */
124
        0x05,       /*  u8  ep_bDescriptorType; Endpoint */
125
        0x81,       /*  u8  ep_bEndpointAddress; IN Endpoint 1 */
126
         0x02,       /*  u8  ep_bmAttributes; Bulk */
127
         0x40, 0x00, /*  u16 ep_wMaxPacketSize; */
128
        0x00,       /*  u8  ep_bInterval; */
129

    
130
        /* Bulk-Out endpoint */
131
        0x07,       /*  u8  ep_bLength; */
132
        0x05,       /*  u8  ep_bDescriptorType; Endpoint */
133
        0x02,       /*  u8  ep_bEndpointAddress; OUT Endpoint 2 */
134
         0x02,       /*  u8  ep_bmAttributes; Bulk */
135
         0x40, 0x00, /*  u16 ep_wMaxPacketSize; */
136
        0x00        /*  u8  ep_bInterval; */
137
};
138

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

    
164
static void usb_msd_send_status(MSDState *s)
165
{
166
    struct usb_msd_csw csw;
167

    
168
    csw.sig = cpu_to_le32(0x53425355);
169
    csw.tag = cpu_to_le32(s->tag);
170
    csw.residue = s->residue;
171
    csw.status = s->result;
172
    memcpy(s->usb_buf, &csw, 13);
173
}
174

    
175
static void usb_msd_command_complete(SCSIBus *bus, int reason, uint32_t tag,
176
                                     uint32_t arg)
177
{
178
    MSDState *s = DO_UPCAST(MSDState, dev.qdev, bus->qbus.parent);
179
    USBPacket *p = s->packet;
180

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

    
226
static void usb_msd_handle_reset(USBDevice *dev)
227
{
228
    MSDState *s = (MSDState *)dev;
229

    
230
    DPRINTF("Reset\n");
231
    s->mode = USB_MSDM_CBW;
232
}
233

    
234
static int usb_msd_handle_control(USBDevice *dev, int request, int value,
235
                                  int index, int length, uint8_t *data)
236
{
237
    MSDState *s = (MSDState *)dev;
238
    int ret = 0;
239

    
240
    switch (request) {
241
    case DeviceRequest | USB_REQ_GET_STATUS:
242
        data[0] = (1 << USB_DEVICE_SELF_POWERED) |
243
            (dev->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP);
244
        data[1] = 0x00;
245
        ret = 2;
246
        break;
247
    case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
248
        if (value == USB_DEVICE_REMOTE_WAKEUP) {
249
            dev->remote_wakeup = 0;
250
        } else {
251
            goto fail;
252
        }
253
        ret = 0;
254
        break;
255
    case DeviceOutRequest | USB_REQ_SET_FEATURE:
256
        if (value == USB_DEVICE_REMOTE_WAKEUP) {
257
            dev->remote_wakeup = 1;
258
        } else {
259
            goto fail;
260
        }
261
        ret = 0;
262
        break;
263
    case DeviceOutRequest | USB_REQ_SET_ADDRESS:
264
        dev->addr = value;
265
        ret = 0;
266
        break;
267
    case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
268
        switch(value >> 8) {
269
        case USB_DT_DEVICE:
270
            memcpy(data, qemu_msd_dev_descriptor,
271
                   sizeof(qemu_msd_dev_descriptor));
272
            ret = sizeof(qemu_msd_dev_descriptor);
273
            break;
274
        case USB_DT_CONFIG:
275
            memcpy(data, qemu_msd_config_descriptor,
276
                   sizeof(qemu_msd_config_descriptor));
277
            ret = sizeof(qemu_msd_config_descriptor);
278
            break;
279
        case USB_DT_STRING:
280
            switch(value & 0xff) {
281
            case 0:
282
                /* language ids */
283
                data[0] = 4;
284
                data[1] = 3;
285
                data[2] = 0x09;
286
                data[3] = 0x04;
287
                ret = 4;
288
                break;
289
            case 1:
290
                /* vendor description */
291
                ret = set_usb_string(data, "QEMU " QEMU_VERSION);
292
                break;
293
            case 2:
294
                /* product description */
295
                ret = set_usb_string(data, "QEMU USB HARDDRIVE");
296
                break;
297
            case 3:
298
                /* serial number */
299
                ret = set_usb_string(data, "1");
300
                break;
301
            default:
302
                goto fail;
303
            }
304
            break;
305
        default:
306
            goto fail;
307
        }
308
        break;
309
    case DeviceRequest | USB_REQ_GET_CONFIGURATION:
310
        data[0] = 1;
311
        ret = 1;
312
        break;
313
    case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
314
        ret = 0;
315
        break;
316
    case DeviceRequest | USB_REQ_GET_INTERFACE:
317
        data[0] = 0;
318
        ret = 1;
319
        break;
320
    case DeviceOutRequest | USB_REQ_SET_INTERFACE:
321
        ret = 0;
322
        break;
323
    case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:
324
        if (value == 0 && index != 0x81) { /* clear ep halt */
325
            goto fail;
326
        }
327
        ret = 0;
328
        break;
329
        /* Class specific requests.  */
330
    case MassStorageReset:
331
        /* Reset state ready for the next CBW.  */
332
        s->mode = USB_MSDM_CBW;
333
        ret = 0;
334
        break;
335
    case GetMaxLun:
336
        data[0] = 0;
337
        ret = 1;
338
        break;
339
    default:
340
    fail:
341
        ret = USB_RET_STALL;
342
        break;
343
    }
344
    return ret;
345
}
346

    
347
static void usb_msd_cancel_io(USBPacket *p, void *opaque)
348
{
349
    MSDState *s = opaque;
350
    s->scsi_dev->info->cancel_io(s->scsi_dev, s->tag);
351
    s->packet = NULL;
352
    s->scsi_len = 0;
353
}
354

    
355
static int usb_msd_handle_data(USBDevice *dev, USBPacket *p)
356
{
357
    MSDState *s = (MSDState *)dev;
358
    int ret = 0;
359
    struct usb_msd_cbw cbw;
360
    uint8_t devep = p->devep;
361
    uint8_t *data = p->data;
362
    int len = p->len;
363

    
364
    switch (p->pid) {
365
    case USB_TOKEN_OUT:
366
        if (devep != 2)
367
            goto fail;
368

    
369
        switch (s->mode) {
370
        case USB_MSDM_CBW:
371
            if (len != 31) {
372
                fprintf(stderr, "usb-msd: Bad CBW size");
373
                goto fail;
374
            }
375
            memcpy(&cbw, data, 31);
376
            if (le32_to_cpu(cbw.sig) != 0x43425355) {
377
                fprintf(stderr, "usb-msd: Bad signature %08x\n",
378
                        le32_to_cpu(cbw.sig));
379
                goto fail;
380
            }
381
            DPRINTF("Command on LUN %d\n", cbw.lun);
382
            if (cbw.lun != 0) {
383
                fprintf(stderr, "usb-msd: Bad LUN %d\n", cbw.lun);
384
                goto fail;
385
            }
386
            s->tag = le32_to_cpu(cbw.tag);
387
            s->data_len = le32_to_cpu(cbw.data_len);
388
            if (s->data_len == 0) {
389
                s->mode = USB_MSDM_CSW;
390
            } else if (cbw.flags & 0x80) {
391
                s->mode = USB_MSDM_DATAIN;
392
            } else {
393
                s->mode = USB_MSDM_DATAOUT;
394
            }
395
            DPRINTF("Command tag 0x%x flags %08x len %d data %d\n",
396
                    s->tag, cbw.flags, cbw.cmd_len, s->data_len);
397
            s->residue = 0;
398
            s->scsi_dev->info->send_command(s->scsi_dev, s->tag, cbw.cmd, 0);
399
            /* ??? Should check that USB and SCSI data transfer
400
               directions match.  */
401
            if (s->residue == 0) {
402
                if (s->mode == USB_MSDM_DATAIN) {
403
                    s->scsi_dev->info->read_data(s->scsi_dev, s->tag);
404
                } else if (s->mode == USB_MSDM_DATAOUT) {
405
                    s->scsi_dev->info->write_data(s->scsi_dev, s->tag);
406
                }
407
            }
408
            ret = len;
409
            break;
410

    
411
        case USB_MSDM_DATAOUT:
412
            DPRINTF("Data out %d/%d\n", len, s->data_len);
413
            if (len > s->data_len)
414
                goto fail;
415

    
416
            s->usb_buf = data;
417
            s->usb_len = len;
418
            if (s->scsi_len) {
419
                usb_msd_copy_data(s);
420
            }
421
            if (s->residue && s->usb_len) {
422
                s->data_len -= s->usb_len;
423
                if (s->data_len == 0)
424
                    s->mode = USB_MSDM_CSW;
425
                s->usb_len = 0;
426
            }
427
            if (s->usb_len) {
428
                DPRINTF("Deferring packet %p\n", p);
429
                usb_defer_packet(p, usb_msd_cancel_io, s);
430
                s->packet = p;
431
                ret = USB_RET_ASYNC;
432
            } else {
433
                ret = len;
434
            }
435
            break;
436

    
437
        default:
438
            DPRINTF("Unexpected write (len %d)\n", len);
439
            goto fail;
440
        }
441
        break;
442

    
443
    case USB_TOKEN_IN:
444
        if (devep != 1)
445
            goto fail;
446

    
447
        switch (s->mode) {
448
        case USB_MSDM_DATAOUT:
449
            if (s->data_len != 0 || len < 13)
450
                goto fail;
451
            /* Waiting for SCSI write to complete.  */
452
            usb_defer_packet(p, usb_msd_cancel_io, s);
453
            s->packet = p;
454
            ret = USB_RET_ASYNC;
455
            break;
456

    
457
        case USB_MSDM_CSW:
458
            DPRINTF("Command status %d tag 0x%x, len %d\n",
459
                    s->result, s->tag, len);
460
            if (len < 13)
461
                goto fail;
462

    
463
            s->usb_len = len;
464
            s->usb_buf = data;
465
            usb_msd_send_status(s);
466
            s->mode = USB_MSDM_CBW;
467
            ret = 13;
468
            break;
469

    
470
        case USB_MSDM_DATAIN:
471
            DPRINTF("Data in %d/%d\n", len, s->data_len);
472
            if (len > s->data_len)
473
                len = s->data_len;
474
            s->usb_buf = data;
475
            s->usb_len = len;
476
            if (s->scsi_len) {
477
                usb_msd_copy_data(s);
478
            }
479
            if (s->residue && s->usb_len) {
480
                s->data_len -= s->usb_len;
481
                memset(s->usb_buf, 0, s->usb_len);
482
                if (s->data_len == 0)
483
                    s->mode = USB_MSDM_CSW;
484
                s->usb_len = 0;
485
            }
486
            if (s->usb_len) {
487
                DPRINTF("Deferring packet %p\n", p);
488
                usb_defer_packet(p, usb_msd_cancel_io, s);
489
                s->packet = p;
490
                ret = USB_RET_ASYNC;
491
            } else {
492
                ret = len;
493
            }
494
            break;
495

    
496
        default:
497
            DPRINTF("Unexpected read (len %d)\n", len);
498
            goto fail;
499
        }
500
        break;
501

    
502
    default:
503
        DPRINTF("Bad token\n");
504
    fail:
505
        ret = USB_RET_STALL;
506
        break;
507
    }
508

    
509
    return ret;
510
}
511

    
512
static void usb_msd_password_cb(void *opaque, int err)
513
{
514
    MSDState *s = opaque;
515

    
516
    if (!err)
517
        usb_device_attach(&s->dev);
518
    else
519
        qdev_unplug(&s->dev.qdev);
520
}
521

    
522
static int usb_msd_initfn(USBDevice *dev)
523
{
524
    MSDState *s = DO_UPCAST(MSDState, dev, dev);
525

    
526
    if (!s->conf.dinfo || !s->conf.dinfo->bdrv) {
527
        qemu_error("usb-msd: drive property not set\n");
528
        return -1;
529
    }
530

    
531
    s->dev.speed = USB_SPEED_FULL;
532
    scsi_bus_new(&s->bus, &s->dev.qdev, 0, 1, usb_msd_command_complete);
533
    s->scsi_dev = scsi_bus_legacy_add_drive(&s->bus, s->conf.dinfo, 0);
534
    s->bus.qbus.allow_hotplug = 0;
535
    usb_msd_handle_reset(dev);
536

    
537
    if (bdrv_key_required(s->conf.dinfo->bdrv)) {
538
        if (s->dev.qdev.hotplugged) {
539
            monitor_read_bdrv_key_start(cur_mon, s->conf.dinfo->bdrv,
540
                                        usb_msd_password_cb, s);
541
            s->dev.auto_attach = 0;
542
        } else {
543
            autostart = 0;
544
        }
545
    }
546

    
547
    return 0;
548
}
549

    
550
static USBDevice *usb_msd_init(const char *filename)
551
{
552
    static int nr=0;
553
    char id[8];
554
    QemuOpts *opts;
555
    DriveInfo *dinfo;
556
    USBDevice *dev;
557
    int fatal_error;
558
    const char *p1;
559
    char fmt[32];
560

    
561
    /* parse -usbdevice disk: syntax into drive opts */
562
    snprintf(id, sizeof(id), "usb%d", nr++);
563
    opts = qemu_opts_create(&qemu_drive_opts, id, 0);
564

    
565
    p1 = strchr(filename, ':');
566
    if (p1++) {
567
        const char *p2;
568

    
569
        if (strstart(filename, "format=", &p2)) {
570
            int len = MIN(p1 - p2, sizeof(fmt));
571
            pstrcpy(fmt, len, p2);
572
            qemu_opt_set(opts, "format", fmt);
573
        } else if (*filename != ':') {
574
            printf("unrecognized USB mass-storage option %s\n", filename);
575
            return NULL;
576
        }
577
        filename = p1;
578
    }
579
    if (!*filename) {
580
        printf("block device specification needed\n");
581
        return NULL;
582
    }
583
    qemu_opt_set(opts, "file", filename);
584
    qemu_opt_set(opts, "if", "none");
585

    
586
    /* create host drive */
587
    dinfo = drive_init(opts, NULL, &fatal_error);
588
    if (!dinfo) {
589
        qemu_opts_del(opts);
590
        return NULL;
591
    }
592

    
593
    /* create guest device */
594
    dev = usb_create(NULL /* FIXME */, "usb-storage");
595
    qdev_prop_set_drive(&dev->qdev, "drive", dinfo);
596
    if (qdev_init(&dev->qdev) < 0)
597
        return NULL;
598

    
599
    return dev;
600
}
601

    
602
static struct USBDeviceInfo msd_info = {
603
    .product_desc   = "QEMU USB MSD",
604
    .qdev.name      = "usb-storage",
605
    .qdev.size      = sizeof(MSDState),
606
    .init           = usb_msd_initfn,
607
    .handle_packet  = usb_generic_handle_packet,
608
    .handle_reset   = usb_msd_handle_reset,
609
    .handle_control = usb_msd_handle_control,
610
    .handle_data    = usb_msd_handle_data,
611
    .usbdevice_name = "disk",
612
    .usbdevice_init = usb_msd_init,
613
    .qdev.props     = (Property[]) {
614
        DEFINE_BLOCK_PROPERTIES(MSDState, conf),
615
        DEFINE_PROP_END_OF_LIST(),
616
    },
617
};
618

    
619
static void usb_msd_register_devices(void)
620
{
621
    usb_qdev_register(&msd_info);
622
}
623
device_init(usb_msd_register_devices)