Merge remote-tracking branch 'mst/for_anthony' into staging
[qemu.git] / hw / usb-msd.c
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, /* Transfer 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(&s->dev, 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 another 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(&s->dev, 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_len = 0;
368             s->scsi_dev->info->send_command(s->scsi_dev, s->tag, cbw.cmd, 0);
369             /* ??? Should check that USB and SCSI data transfer
370                directions match.  */
371             if (s->residue == 0) {
372                 if (s->mode == USB_MSDM_DATAIN) {
373                     s->scsi_dev->info->read_data(s->scsi_dev, s->tag);
374                 } else if (s->mode == USB_MSDM_DATAOUT) {
375                     s->scsi_dev->info->write_data(s->scsi_dev, s->tag);
376                 }
377             }
378             ret = len;
379             break;
380
381         case USB_MSDM_DATAOUT:
382             DPRINTF("Data out %d/%d\n", len, s->data_len);
383             if (len > s->data_len)
384                 goto fail;
385
386             s->usb_buf = data;
387             s->usb_len = len;
388             if (s->scsi_len) {
389                 usb_msd_copy_data(s);
390             }
391             if (s->residue && s->usb_len) {
392                 s->data_len -= s->usb_len;
393                 if (s->data_len == 0)
394                     s->mode = USB_MSDM_CSW;
395                 s->usb_len = 0;
396             }
397             if (s->usb_len) {
398                 DPRINTF("Deferring packet %p\n", p);
399                 usb_defer_packet(p, usb_msd_cancel_io, s);
400                 s->packet = p;
401                 ret = USB_RET_ASYNC;
402             } else {
403                 ret = len;
404             }
405             break;
406
407         default:
408             DPRINTF("Unexpected write (len %d)\n", len);
409             goto fail;
410         }
411         break;
412
413     case USB_TOKEN_IN:
414         if (devep != 1)
415             goto fail;
416
417         switch (s->mode) {
418         case USB_MSDM_DATAOUT:
419             if (s->data_len != 0 || len < 13)
420                 goto fail;
421             /* Waiting for SCSI write to complete.  */
422             usb_defer_packet(p, usb_msd_cancel_io, s);
423             s->packet = p;
424             ret = USB_RET_ASYNC;
425             break;
426
427         case USB_MSDM_CSW:
428             DPRINTF("Command status %d tag 0x%x, len %d\n",
429                     s->result, s->tag, len);
430             if (len < 13)
431                 goto fail;
432
433             usb_msd_send_status(s, p);
434             s->mode = USB_MSDM_CBW;
435             ret = 13;
436             break;
437
438         case USB_MSDM_DATAIN:
439             DPRINTF("Data in %d/%d, scsi_len %d\n", len, s->data_len, s->scsi_len);
440             if (len > s->data_len)
441                 len = s->data_len;
442             s->usb_buf = data;
443             s->usb_len = len;
444             if (s->scsi_len) {
445                 usb_msd_copy_data(s);
446             }
447             if (s->residue && s->usb_len) {
448                 s->data_len -= s->usb_len;
449                 memset(s->usb_buf, 0, s->usb_len);
450                 if (s->data_len == 0)
451                     s->mode = USB_MSDM_CSW;
452                 s->usb_len = 0;
453             }
454             if (s->usb_len) {
455                 DPRINTF("Deferring packet %p\n", p);
456                 usb_defer_packet(p, usb_msd_cancel_io, s);
457                 s->packet = p;
458                 ret = USB_RET_ASYNC;
459             } else {
460                 ret = len;
461             }
462             break;
463
464         default:
465             DPRINTF("Unexpected read (len %d)\n", len);
466             goto fail;
467         }
468         break;
469
470     default:
471         DPRINTF("Bad token\n");
472     fail:
473         ret = USB_RET_STALL;
474         break;
475     }
476
477     return ret;
478 }
479
480 static void usb_msd_password_cb(void *opaque, int err)
481 {
482     MSDState *s = opaque;
483
484     if (!err)
485         usb_device_attach(&s->dev);
486     else
487         qdev_unplug(&s->dev.qdev);
488 }
489
490 static int usb_msd_initfn(USBDevice *dev)
491 {
492     MSDState *s = DO_UPCAST(MSDState, dev, dev);
493     BlockDriverState *bs = s->conf.bs;
494     DriveInfo *dinfo;
495
496     if (!bs) {
497         error_report("usb-msd: drive property not set");
498         return -1;
499     }
500
501     /*
502      * Hack alert: this pretends to be a block device, but it's really
503      * a SCSI bus that can serve only a single device, which it
504      * creates automatically.  But first it needs to detach from its
505      * blockdev, or else scsi_bus_legacy_add_drive() dies when it
506      * attaches again.
507      *
508      * The hack is probably a bad idea.
509      */
510     bdrv_detach(bs, &s->dev.qdev);
511     s->conf.bs = NULL;
512
513     dinfo = drive_get_by_blockdev(bs);
514     if (dinfo && dinfo->serial) {
515         usb_desc_set_string(dev, STR_SERIALNUMBER, dinfo->serial);
516     }
517
518     usb_desc_init(dev);
519     scsi_bus_new(&s->bus, &s->dev.qdev, 0, 1, usb_msd_command_complete);
520     s->scsi_dev = scsi_bus_legacy_add_drive(&s->bus, bs, 0, !!s->removable);
521     if (!s->scsi_dev) {
522         return -1;
523     }
524     s->bus.qbus.allow_hotplug = 0;
525     usb_msd_handle_reset(dev);
526
527     if (bdrv_key_required(bs)) {
528         if (cur_mon) {
529             monitor_read_bdrv_key_start(cur_mon, bs, usb_msd_password_cb, s);
530             s->dev.auto_attach = 0;
531         } else {
532             autostart = 0;
533         }
534     }
535
536     add_boot_device_path(s->conf.bootindex, &dev->qdev, "/disk@0,0");
537     return 0;
538 }
539
540 static USBDevice *usb_msd_init(const char *filename)
541 {
542     static int nr=0;
543     char id[8];
544     QemuOpts *opts;
545     DriveInfo *dinfo;
546     USBDevice *dev;
547     const char *p1;
548     char fmt[32];
549
550     /* parse -usbdevice disk: syntax into drive opts */
551     snprintf(id, sizeof(id), "usb%d", nr++);
552     opts = qemu_opts_create(qemu_find_opts("drive"), id, 0);
553
554     p1 = strchr(filename, ':');
555     if (p1++) {
556         const char *p2;
557
558         if (strstart(filename, "format=", &p2)) {
559             int len = MIN(p1 - p2, sizeof(fmt));
560             pstrcpy(fmt, len, p2);
561             qemu_opt_set(opts, "format", fmt);
562         } else if (*filename != ':') {
563             printf("unrecognized USB mass-storage option %s\n", filename);
564             return NULL;
565         }
566         filename = p1;
567     }
568     if (!*filename) {
569         printf("block device specification needed\n");
570         return NULL;
571     }
572     qemu_opt_set(opts, "file", filename);
573     qemu_opt_set(opts, "if", "none");
574
575     /* create host drive */
576     dinfo = drive_init(opts, 0);
577     if (!dinfo) {
578         qemu_opts_del(opts);
579         return NULL;
580     }
581
582     /* create guest device */
583     dev = usb_create(NULL /* FIXME */, "usb-storage");
584     if (!dev) {
585         return NULL;
586     }
587     if (qdev_prop_set_drive(&dev->qdev, "drive", dinfo->bdrv) < 0) {
588         qdev_free(&dev->qdev);
589         return NULL;
590     }
591     if (qdev_init(&dev->qdev) < 0)
592         return NULL;
593
594     return dev;
595 }
596
597 static struct USBDeviceInfo msd_info = {
598     .product_desc   = "QEMU USB MSD",
599     .qdev.name      = "usb-storage",
600     .qdev.fw_name      = "storage",
601     .qdev.size      = sizeof(MSDState),
602     .usb_desc       = &desc,
603     .init           = usb_msd_initfn,
604     .handle_packet  = usb_generic_handle_packet,
605     .handle_attach  = usb_desc_attach,
606     .handle_reset   = usb_msd_handle_reset,
607     .handle_control = usb_msd_handle_control,
608     .handle_data    = usb_msd_handle_data,
609     .usbdevice_name = "disk",
610     .usbdevice_init = usb_msd_init,
611     .qdev.props     = (Property[]) {
612         DEFINE_BLOCK_PROPERTIES(MSDState, conf),
613         DEFINE_PROP_BIT("removable", MSDState, removable, 0, false),
614         DEFINE_PROP_END_OF_LIST(),
615     },
616 };
617
618 static void usb_msd_register_devices(void)
619 {
620     usb_qdev_register(&msd_info);
621 }
622 device_init(usb_msd_register_devices)
This page took 0.058445 seconds and 4 git commands to generate.