There are USB Mass storage devices which have more than one device. Examples are CD Changers, or USB sticks which are partitioned in a CDROM and Harddisk device.
Signed-off-by: Sven Schnelle svens@stackframe.org --- src/usb-msc.c | 100 +++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 72 insertions(+), 28 deletions(-)
diff --git a/src/usb-msc.c b/src/usb-msc.c index c53a1f5..6025a03 100644 --- a/src/usb-msc.c +++ b/src/usb-msc.c @@ -16,6 +16,7 @@ struct usbdrive_s { struct drive_s drive; struct usb_pipe *bulkin, *bulkout; + int lun; };
@@ -78,7 +79,7 @@ usb_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize) cbw.dCBWTag = 999; // XXX cbw.dCBWDataTransferLength = bytes; cbw.bmCBWFlags = cdb_is_read(cdbcmd, blocksize) ? USB_DIR_IN : USB_DIR_OUT; - cbw.bCBWLUN = 0; // XXX + cbw.bCBWLUN = GET_GLOBAL(udrive_g->lun); cbw.bCBWCBLength = USB_CDB_SIZE;
// Transfer cbw to device. @@ -117,6 +118,47 @@ fail: return DISK_RET_EBADTRACK; }
+static int +usb_msc_maxlun(struct usb_pipe *pipe, unsigned char *maxlun) +{ + if (!CONFIG_USB_MSC) + return -1; + + struct usb_ctrlrequest req; + req.bRequestType = USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE; + req.bRequest = 0xfe; + req.wValue = 0; + req.wIndex = 0; + req.wLength = 1; + return send_default_control(pipe, &req, maxlun); +} + +static int usb_msc_init_lun(struct usb_pipe *inpipe, + struct usb_pipe *outpipe, + struct usbdevice_s *usbdev, + int lun) +{ + // Allocate drive structure. + struct usbdrive_s *udrive_g = malloc_fseg(sizeof(*udrive_g)); + if (!udrive_g) { + warn_noalloc(); + return -1; + } + memset(udrive_g, 0, sizeof(*udrive_g)); + udrive_g->drive.type = DTYPE_USB; + udrive_g->lun = lun; + + udrive_g->bulkin = inpipe; + udrive_g->bulkout = outpipe; + + if (scsi_init_drive(&udrive_g->drive, + "USB MSC", bootprio_find_usb(usbdev))) { + dprintf(1, "Unable to configure USB MSC device.\n"); + free(udrive_g); + return -1; + } + return 0; +}
/**************************************************************** * Setup @@ -126,6 +168,11 @@ fail: int usb_msc_init(struct usbdevice_s *usbdev) { + struct usb_pipe *inpipe = NULL, *outpipe = NULL; + struct usb_endpoint_descriptor *indesc, *outdesc; + unsigned char maxlun, lun; + int pipesused = 0; + if (!CONFIG_USB_MSC) return -1;
@@ -140,39 +187,36 @@ usb_msc_init(struct usbdevice_s *usbdev) return -1; }
- // Allocate drive structure. - struct usbdrive_s *udrive_g = malloc_fseg(sizeof(*udrive_g)); - if (!udrive_g) { - warn_noalloc(); - goto fail; - } - memset(udrive_g, 0, sizeof(*udrive_g)); - udrive_g->drive.type = DTYPE_USB; - // Find bulk in and bulk out endpoints. - struct usb_endpoint_descriptor *indesc = findEndPointDesc( - usbdev, USB_ENDPOINT_XFER_BULK, USB_DIR_IN); - struct usb_endpoint_descriptor *outdesc = findEndPointDesc( - usbdev, USB_ENDPOINT_XFER_BULK, USB_DIR_OUT); - if (!indesc || !outdesc) - goto fail; - udrive_g->bulkin = usb_alloc_pipe(usbdev, indesc); - udrive_g->bulkout = usb_alloc_pipe(usbdev, outdesc); - if (!udrive_g->bulkin || !udrive_g->bulkout) + if (!(indesc = findEndPointDesc(usbdev, USB_ENDPOINT_XFER_BULK, + USB_DIR_IN))) goto fail;
- int prio = bootprio_find_usb(usbdev); - int ret = scsi_init_drive(&udrive_g->drive, "USB MSC", prio); - if (ret) + if (!(outdesc = findEndPointDesc(usbdev, USB_ENDPOINT_XFER_BULK, + USB_DIR_OUT))) goto fail;
+ if (!(inpipe = usb_alloc_pipe(usbdev, indesc))) + goto fail; + + + if (!(outpipe = usb_alloc_pipe(usbdev, outdesc))) + goto fail; + + if (usb_msc_maxlun(usbdev->defpipe, &maxlun)) + maxlun = 0; + + for(lun = 0; lun < maxlun + 1; lun++) { + if (!usb_msc_init_lun(inpipe, outpipe, usbdev, lun)) + pipesused = 1; + } + + if (!pipesused) + goto fail; + return 0; fail: - dprintf(1, "Unable to configure USB MSC device.\n"); - if (udrive_g) { - free_pipe(udrive_g->bulkin); - free_pipe(udrive_g->bulkout); - free(udrive_g); - } + free_pipe(inpipe); + free_pipe(outpipe); return -1; }