Statistics
| Branch: | Revision:

root / hw / usb-msd.c @ 001faf32

History | View | Annotate | Download (16 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 "usb.h"
12
#include "block.h"
13
#include "scsi-disk.h"
14
#include "console.h"
15

    
16
//#define DEBUG_MSD
17

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

    
25
/* USB requests.  */
26
#define MassStorageReset  0xff
27
#define GetMaxLun         0xfe
28

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

    
36
typedef struct {
37
    USBDevice dev;
38
    enum USBMSDMode mode;
39
    uint32_t scsi_len;
40
    uint8_t *scsi_buf;
41
    uint32_t usb_len;
42
    uint8_t *usb_buf;
43
    uint32_t data_len;
44
    uint32_t residue;
45
    uint32_t tag;
46
    BlockDriverState *bs;
47
    SCSIDevice *scsi_dev;
48
    int result;
49
    /* For async completion.  */
50
    USBPacket *packet;
51
} MSDState;
52

    
53
struct usb_msd_cbw {
54
    uint32_t sig;
55
    uint32_t tag;
56
    uint32_t data_len;
57
    uint8_t flags;
58
    uint8_t lun;
59
    uint8_t cmd_len;
60
    uint8_t cmd[16];
61
};
62

    
63
struct usb_msd_csw {
64
    uint32_t sig;
65
    uint32_t tag;
66
    uint32_t residue;
67
    uint8_t status;
68
};
69

    
70
static const uint8_t qemu_msd_dev_descriptor[] = {
71
        0x12,       /*  u8 bLength; */
72
        0x01,       /*  u8 bDescriptorType; Device */
73
        0x00, 0x01, /*  u16 bcdUSB; v1.0 */
74

    
75
        0x00,            /*  u8  bDeviceClass; */
76
        0x00,            /*  u8  bDeviceSubClass; */
77
        0x00,       /*  u8  bDeviceProtocol; [ low/full speeds only ] */
78
        0x08,       /*  u8  bMaxPacketSize0; 8 Bytes */
79

    
80
        /* Vendor and product id are arbitrary.  */
81
        0x00, 0x00, /*  u16 idVendor; */
82
         0x00, 0x00, /*  u16 idProduct; */
83
        0x00, 0x00, /*  u16 bcdDevice */
84

    
85
        0x01,       /*  u8  iManufacturer; */
86
        0x02,       /*  u8  iProduct; */
87
        0x03,       /*  u8  iSerialNumber; */
88
        0x01        /*  u8  bNumConfigurations; */
89
};
90

    
91
static const uint8_t qemu_msd_config_descriptor[] = {
92

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

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

    
118
        /* Bulk-In endpoint */
119
        0x07,       /*  u8  ep_bLength; */
120
        0x05,       /*  u8  ep_bDescriptorType; Endpoint */
121
        0x81,       /*  u8  ep_bEndpointAddress; IN Endpoint 1 */
122
         0x02,       /*  u8  ep_bmAttributes; Bulk */
123
         0x40, 0x00, /*  u16 ep_wMaxPacketSize; */
124
        0x00,       /*  u8  ep_bInterval; */
125

    
126
        /* Bulk-Out endpoint */
127
        0x07,       /*  u8  ep_bLength; */
128
        0x05,       /*  u8  ep_bDescriptorType; Endpoint */
129
        0x02,       /*  u8  ep_bEndpointAddress; OUT Endpoint 2 */
130
         0x02,       /*  u8  ep_bmAttributes; Bulk */
131
         0x40, 0x00, /*  u16 ep_wMaxPacketSize; */
132
        0x00        /*  u8  ep_bInterval; */
133
};
134

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

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

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

    
171
static void usb_msd_command_complete(void *opaque, int reason, uint32_t tag,
172
                                     uint32_t arg)
173
{
174
    MSDState *s = (MSDState *)opaque;
175
    USBPacket *p = s->packet;
176

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

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

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

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

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

    
343
static void usb_msd_cancel_io(USBPacket *p, void *opaque)
344
{
345
    MSDState *s = opaque;
346
    s->scsi_dev->cancel_io(s->scsi_dev, s->tag);
347
    s->packet = NULL;
348
    s->scsi_len = 0;
349
}
350

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

    
360
    switch (p->pid) {
361
    case USB_TOKEN_OUT:
362
        if (devep != 2)
363
            goto fail;
364

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

    
407
        case USB_MSDM_DATAOUT:
408
            DPRINTF("Data out %d/%d\n", len, s->data_len);
409
            if (len > s->data_len)
410
                goto fail;
411

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

    
433
        default:
434
            DPRINTF("Unexpected write (len %d)\n", len);
435
            goto fail;
436
        }
437
        break;
438

    
439
    case USB_TOKEN_IN:
440
        if (devep != 1)
441
            goto fail;
442

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

    
453
        case USB_MSDM_CSW:
454
            DPRINTF("Command status %d tag 0x%x, len %d\n",
455
                    s->result, s->tag, len);
456
            if (len < 13)
457
                goto fail;
458

    
459
            s->usb_len = len;
460
            s->usb_buf = data;
461
            usb_msd_send_status(s);
462
            s->mode = USB_MSDM_CBW;
463
            ret = 13;
464
            break;
465

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

    
492
        default:
493
            DPRINTF("Unexpected read (len %d)\n", len);
494
            goto fail;
495
        }
496
        break;
497

    
498
    default:
499
        DPRINTF("Bad token\n");
500
    fail:
501
        ret = USB_RET_STALL;
502
        break;
503
    }
504

    
505
    return ret;
506
}
507

    
508
static void usb_msd_handle_destroy(USBDevice *dev)
509
{
510
    MSDState *s = (MSDState *)dev;
511

    
512
    s->scsi_dev->destroy(s->scsi_dev);
513
    bdrv_delete(s->bs);
514
    qemu_free(s);
515
}
516

    
517
USBDevice *usb_msd_init(const char *filename)
518
{
519
    MSDState *s;
520
    BlockDriverState *bdrv;
521
    BlockDriver *drv = NULL;
522
    const char *p1;
523
    char fmt[32];
524

    
525
    p1 = strchr(filename, ':');
526
    if (p1++) {
527
        const char *p2;
528

    
529
        if (strstart(filename, "format=", &p2)) {
530
            int len = MIN(p1 - p2, sizeof(fmt));
531
            pstrcpy(fmt, len, p2);
532

    
533
            drv = bdrv_find_format(fmt);
534
            if (!drv) {
535
                printf("invalid format %s\n", fmt);
536
                return NULL;
537
            }
538
        } else if (*filename != ':') {
539
            printf("unrecognized USB mass-storage option %s\n", filename);
540
            return NULL;
541
        }
542

    
543
        filename = p1;
544
    }
545

    
546
    if (!*filename) {
547
        printf("block device specification needed\n");
548
        return NULL;
549
    }
550

    
551
    s = qemu_mallocz(sizeof(MSDState));
552

    
553
    bdrv = bdrv_new("usb");
554
    if (bdrv_open2(bdrv, filename, 0, drv) < 0)
555
        goto fail;
556
    s->bs = bdrv;
557

    
558
    s->dev.speed = USB_SPEED_FULL;
559
    s->dev.handle_packet = usb_generic_handle_packet;
560

    
561
    s->dev.handle_reset = usb_msd_handle_reset;
562
    s->dev.handle_control = usb_msd_handle_control;
563
    s->dev.handle_data = usb_msd_handle_data;
564
    s->dev.handle_destroy = usb_msd_handle_destroy;
565

    
566
    snprintf(s->dev.devname, sizeof(s->dev.devname), "QEMU USB MSD(%.16s)",
567
             filename);
568

    
569
    s->scsi_dev = scsi_disk_init(bdrv, 0, usb_msd_command_complete, s);
570
    usb_msd_handle_reset((USBDevice *)s);
571
    return (USBDevice *)s;
572
 fail:
573
    qemu_free(s);
574
    return NULL;
575
}
576

    
577
BlockDriverState *usb_msd_get_bdrv(USBDevice *dev)
578
{
579
    MSDState *s = (MSDState *)dev;
580

    
581
    return s->bs;
582
}