]> Git Repo - qemu.git/blob - hw/usb-msd.c
block: Simplify usb_msd_initfn() test for "can read bdrv key"
[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 "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 (cur_mon) {
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     if (!dev) {
596         return NULL;
597     }
598     qdev_prop_set_drive(&dev->qdev, "drive", dinfo);
599     if (qdev_init(&dev->qdev) < 0)
600         return NULL;
601
602     return dev;
603 }
604
605 static struct USBDeviceInfo msd_info = {
606     .product_desc   = "QEMU USB MSD",
607     .qdev.name      = "usb-storage",
608     .qdev.size      = sizeof(MSDState),
609     .init           = usb_msd_initfn,
610     .handle_packet  = usb_generic_handle_packet,
611     .handle_reset   = usb_msd_handle_reset,
612     .handle_control = usb_msd_handle_control,
613     .handle_data    = usb_msd_handle_data,
614     .usbdevice_name = "disk",
615     .usbdevice_init = usb_msd_init,
616     .qdev.props     = (Property[]) {
617         DEFINE_BLOCK_PROPERTIES(MSDState, conf),
618         DEFINE_PROP_END_OF_LIST(),
619     },
620 };
621
622 static void usb_msd_register_devices(void)
623 {
624     usb_qdev_register(&msd_info);
625 }
626 device_init(usb_msd_register_devices)
This page took 0.060343 seconds and 4 git commands to generate.