]> Git Repo - qemu.git/blob - hw/usb-msd.c
Merge remote 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, /* 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     return 0;
536 }
537
538 static USBDevice *usb_msd_init(const char *filename)
539 {
540     static int nr=0;
541     char id[8];
542     QemuOpts *opts;
543     DriveInfo *dinfo;
544     USBDevice *dev;
545     const char *p1;
546     char fmt[32];
547
548     /* parse -usbdevice disk: syntax into drive opts */
549     snprintf(id, sizeof(id), "usb%d", nr++);
550     opts = qemu_opts_create(qemu_find_opts("drive"), id, 0);
551
552     p1 = strchr(filename, ':');
553     if (p1++) {
554         const char *p2;
555
556         if (strstart(filename, "format=", &p2)) {
557             int len = MIN(p1 - p2, sizeof(fmt));
558             pstrcpy(fmt, len, p2);
559             qemu_opt_set(opts, "format", fmt);
560         } else if (*filename != ':') {
561             printf("unrecognized USB mass-storage option %s\n", filename);
562             return NULL;
563         }
564         filename = p1;
565     }
566     if (!*filename) {
567         printf("block device specification needed\n");
568         return NULL;
569     }
570     qemu_opt_set(opts, "file", filename);
571     qemu_opt_set(opts, "if", "none");
572
573     /* create host drive */
574     dinfo = drive_init(opts, 0);
575     if (!dinfo) {
576         qemu_opts_del(opts);
577         return NULL;
578     }
579
580     /* create guest device */
581     dev = usb_create(NULL /* FIXME */, "usb-storage");
582     if (!dev) {
583         return NULL;
584     }
585     if (qdev_prop_set_drive(&dev->qdev, "drive", dinfo->bdrv) < 0) {
586         qdev_free(&dev->qdev);
587         return NULL;
588     }
589     if (qdev_init(&dev->qdev) < 0)
590         return NULL;
591
592     return dev;
593 }
594
595 static struct USBDeviceInfo msd_info = {
596     .product_desc   = "QEMU USB MSD",
597     .qdev.name      = "usb-storage",
598     .qdev.size      = sizeof(MSDState),
599     .usb_desc       = &desc,
600     .init           = usb_msd_initfn,
601     .handle_packet  = usb_generic_handle_packet,
602     .handle_attach  = usb_desc_attach,
603     .handle_reset   = usb_msd_handle_reset,
604     .handle_control = usb_msd_handle_control,
605     .handle_data    = usb_msd_handle_data,
606     .usbdevice_name = "disk",
607     .usbdevice_init = usb_msd_init,
608     .qdev.props     = (Property[]) {
609         DEFINE_BLOCK_PROPERTIES(MSDState, conf),
610         DEFINE_PROP_BIT("removable", MSDState, removable, 0, false),
611         DEFINE_PROP_END_OF_LIST(),
612     },
613 };
614
615 static void usb_msd_register_devices(void)
616 {
617     usb_qdev_register(&msd_info);
618 }
619 device_init(usb_msd_register_devices)
This page took 0.063112 seconds and 4 git commands to generate.