From 55a5876eba6a142ca50e1e6b05c25cc7ef5e100a Mon Sep 17 00:00:00 2001 From: Xiaoguang Wu Date: Wed, 17 Jul 2019 11:30:32 +0800 Subject: [PATCH] DM USB: xHCI: workaround for USB SSD which supports UAS protocol The USB mediator doesn't support USB Attached SCSI (UAS) protocol due to no proper implementation for USB Stream. This patch will use USB Bulk transfer to workaround until formal implentation for UAS is ready. Tracked-On: #3486 Signed-off-by: Xiaoguang Wu Acked-by: Yu Wang --- devicemodel/hw/platform/usb_pmapper.c | 42 +++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/devicemodel/hw/platform/usb_pmapper.c b/devicemodel/hw/platform/usb_pmapper.c index df3c577ae..449ddcb30 100644 --- a/devicemodel/hw/platform/usb_pmapper.c +++ b/devicemodel/hw/platform/usb_pmapper.c @@ -902,6 +902,36 @@ done: return xfer->status; } +static void +clear_uas_desc(struct usb_dev *udev, uint8_t *data, uint32_t len) +{ + struct usb_devpath *path; + int32_t i; + + /* only process configuration descriptor */ + if (len < 2 || data[1] != 0x2) + return; + + i = 0; + path = &udev->info.path; + while (i < len) { + /* When UAS protocol is found in interface descriptor, set it + * to invalid value. + * + * According to USB3 spec 9.6.5, Standard Interface Descriptor, + * data[i+0] => bLength + * data[i+1] => bDescriptorType + * data[i+7] => bInterfaceProtocol + */ + if (data[i] == 9 && data[i+1] == 0x4 && data[i+7] == 0x62) { + UPRINTF(LFTL, "%d-%s: clear uas protocol\r\n", + path->bus, usb_dev_path(path)); + data[i+7] = 0; + } + i = i + data[i]; + } +} + int usb_dev_request(void *pdata, struct usb_data_xfer *xfer) { @@ -914,6 +944,7 @@ usb_dev_request(void *pdata, struct usb_data_xfer *xfer) struct usb_data_xfer_block *blk; uint8_t *data; int rc; + bool need_chk_uas = false; udev = pdata; xfer->status = USB_ERR_NORMAL_COMPLETION; @@ -960,6 +991,10 @@ usb_dev_request(void *pdata, struct usb_data_xfer *xfer) UPRINTF(LDBG, "UR_SET_INTERFACE\n"); usb_dev_set_if(udev, index, value, xfer); goto out; + case UREQ(UR_GET_DESCRIPTOR, UT_READ): + if (value == 0x0200) + need_chk_uas = true; + break; case UREQ(UR_CLEAR_FEATURE, UT_WRITE_ENDPOINT): if (value) { /* according to usb spec (ch9), this is impossible */ @@ -985,6 +1020,13 @@ usb_dev_request(void *pdata, struct usb_data_xfer *xfer) rc = libusb_control_transfer(udev->handle, request_type, request, value, index, data, len, 300); + /* TODO: Currently, the USB Attached SCSI (UAS) protocol is not + * supported and the following code is used as a workaround now. + * UAS will be implemented in future. + */ + if (need_chk_uas) + clear_uas_desc(udev, data, rc); + if (rc >= 0 && blk) { blk->blen = len - rc; blk->bdone += rc;