libpayload: usbmsc: Factor out usb_msc_force_init() function
We're planning to have a use case with a custom USB device that implements the USB mass storage protocol on its bulk endpoints, but does not have the normal MSC class/protocol interface descriptors and does not support class-specific control requests (Get Max LUN and Bulk-Only Reset). We'd like to identify/enumerate the device via usb_generic_create() in our payload but then reuse all the normal MSC driver code. In order to make that possible, this patch factors a new usb_msc_force_init() function out of usb_msc_init() which will initialize an MSC device without checking its descriptors. It also adds some "quirks" flags that allow devices registered this way to customize behavior of the MSC stack. Change-Id: I50392128409cb2a879954f234149a5e3b060a229 Signed-off-by: Julius Werner <jwerner@chromium.org> Reviewed-on: https://review.coreboot.org/c/coreboot/+/34227 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Patrick Georgi <pgeorgi@google.com>
This commit is contained in:
parent
182fea717e
commit
277498c283
|
@ -157,6 +157,9 @@ reset_transport (usbdev_t *dev)
|
||||||
dr.wIndex = 0;
|
dr.wIndex = 0;
|
||||||
dr.wLength = 0;
|
dr.wLength = 0;
|
||||||
|
|
||||||
|
if (MSC_INST (dev)->quirks & USB_MSC_QUIRK_NO_RESET)
|
||||||
|
return MSC_COMMAND_FAIL;
|
||||||
|
|
||||||
/* if any of these fails, detach device, as we are lost */
|
/* if any of these fails, detach device, as we are lost */
|
||||||
if (dev->controller->control (dev, OUT, sizeof (dr), &dr, 0, 0) < 0 ||
|
if (dev->controller->control (dev, OUT, sizeof (dr), &dr, 0, 0) < 0 ||
|
||||||
clear_stall (MSC_INST (dev)->bulk_in) ||
|
clear_stall (MSC_INST (dev)->bulk_in) ||
|
||||||
|
@ -185,7 +188,8 @@ initialize_luns (usbdev_t *dev)
|
||||||
dr.wValue = 0;
|
dr.wValue = 0;
|
||||||
dr.wIndex = 0;
|
dr.wIndex = 0;
|
||||||
dr.wLength = 1;
|
dr.wLength = 1;
|
||||||
if (dev->controller->control (dev, IN, sizeof (dr), &dr,
|
if (MSC_INST (dev)->quirks & USB_MSC_QUIRK_NO_LUNS ||
|
||||||
|
dev->controller->control (dev, IN, sizeof (dr), &dr,
|
||||||
sizeof (msc->num_luns), &msc->num_luns) < 0)
|
sizeof (msc->num_luns), &msc->num_luns) < 0)
|
||||||
msc->num_luns = 0; /* assume only 1 lun if req fails */
|
msc->num_luns = 0; /* assume only 1 lun if req fails */
|
||||||
msc->num_luns++; /* Get Max LUN returns number of last LUN */
|
msc->num_luns++; /* Get Max LUN returns number of last LUN */
|
||||||
|
@ -600,14 +604,6 @@ usb_msc_test_unit_ready (usbdev_t *dev)
|
||||||
void
|
void
|
||||||
usb_msc_init (usbdev_t *dev)
|
usb_msc_init (usbdev_t *dev)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
|
|
||||||
/* init .data before setting .destroy */
|
|
||||||
dev->data = NULL;
|
|
||||||
|
|
||||||
dev->destroy = usb_msc_destroy;
|
|
||||||
dev->poll = usb_msc_poll;
|
|
||||||
|
|
||||||
configuration_descriptor_t *cd =
|
configuration_descriptor_t *cd =
|
||||||
(configuration_descriptor_t *) dev->configuration;
|
(configuration_descriptor_t *) dev->configuration;
|
||||||
interface_descriptor_t *interface =
|
interface_descriptor_t *interface =
|
||||||
|
@ -634,6 +630,19 @@ usb_msc_init (usbdev_t *dev)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
usb_msc_force_init (dev, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void usb_msc_force_init (usbdev_t *dev, u32 quirks)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* init .data before setting .destroy */
|
||||||
|
dev->data = NULL;
|
||||||
|
|
||||||
|
dev->destroy = usb_msc_destroy;
|
||||||
|
dev->poll = usb_msc_poll;
|
||||||
|
|
||||||
dev->data = malloc (sizeof (usbmsc_inst_t));
|
dev->data = malloc (sizeof (usbmsc_inst_t));
|
||||||
if (!dev->data)
|
if (!dev->data)
|
||||||
fatal("Not enough memory for USB MSC device.\n");
|
fatal("Not enough memory for USB MSC device.\n");
|
||||||
|
@ -641,6 +650,7 @@ usb_msc_init (usbdev_t *dev)
|
||||||
MSC_INST (dev)->bulk_in = 0;
|
MSC_INST (dev)->bulk_in = 0;
|
||||||
MSC_INST (dev)->bulk_out = 0;
|
MSC_INST (dev)->bulk_out = 0;
|
||||||
MSC_INST (dev)->usbdisk_created = 0;
|
MSC_INST (dev)->usbdisk_created = 0;
|
||||||
|
MSC_INST (dev)->quirks = quirks;
|
||||||
|
|
||||||
for (i = 1; i <= dev->num_endp; i++) {
|
for (i = 1; i <= dev->num_endp; i++) {
|
||||||
if (dev->endpoints[i].endpoint == 0)
|
if (dev->endpoints[i].endpoint == 0)
|
||||||
|
|
|
@ -34,13 +34,24 @@ typedef struct {
|
||||||
unsigned int numblocks;
|
unsigned int numblocks;
|
||||||
endpoint_t *bulk_in;
|
endpoint_t *bulk_in;
|
||||||
endpoint_t *bulk_out;
|
endpoint_t *bulk_out;
|
||||||
u8 usbdisk_created;
|
u8 quirks : 7;
|
||||||
|
u8 usbdisk_created : 1;
|
||||||
s8 ready;
|
s8 ready;
|
||||||
u8 lun;
|
u8 lun;
|
||||||
u8 num_luns;
|
u8 num_luns;
|
||||||
void *data; /* For use by consumers of libpayload. */
|
void *data; /* For use by consumers of libpayload. */
|
||||||
} usbmsc_inst_t;
|
} usbmsc_inst_t;
|
||||||
|
|
||||||
|
/* Possible values for quirks field. */
|
||||||
|
enum {
|
||||||
|
/* Don't check for LUNs (force assumption that there's only one LUN). */
|
||||||
|
USB_MSC_QUIRK_NO_LUNS = 1 << 0,
|
||||||
|
/* Never do a BULK_ONLY reset, just continue. This means that the device
|
||||||
|
cannot recover from phase errors and won't detach automatically for
|
||||||
|
unrecoverable errors. Do not use unless you have to. */
|
||||||
|
USB_MSC_QUIRK_NO_RESET = 1 << 1,
|
||||||
|
};
|
||||||
|
|
||||||
/* Possible values for ready field. */
|
/* Possible values for ready field. */
|
||||||
enum {
|
enum {
|
||||||
USB_MSC_DETACHED = -1, /* Disk detached or out to lunch. */
|
USB_MSC_DETACHED = -1, /* Disk detached or out to lunch. */
|
||||||
|
@ -56,4 +67,8 @@ typedef enum { cbw_direction_data_in = 0x80, cbw_direction_data_out = 0
|
||||||
int readwrite_blocks_512 (usbdev_t *dev, int start, int n, cbw_direction dir, u8 *buf);
|
int readwrite_blocks_512 (usbdev_t *dev, int start, int n, cbw_direction dir, u8 *buf);
|
||||||
int readwrite_blocks (usbdev_t *dev, int start, int n, cbw_direction dir, u8 *buf);
|
int readwrite_blocks (usbdev_t *dev, int start, int n, cbw_direction dir, u8 *buf);
|
||||||
|
|
||||||
|
/* Force a device to enumerate as MSC, without checking class/protocol types.
|
||||||
|
It must still have a bulk endpoint pair and respond to MSC commands. */
|
||||||
|
void usb_msc_force_init (usbdev_t *dev, u32 quirks);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue