diff options
author | Nico Huber <nico.huber@secunet.com> | 2012-05-21 14:05:41 +0200 |
---|---|---|
committer | Peter Stuge <peter@stuge.se> | 2012-06-20 19:47:07 +0200 |
commit | 43b9f32d20a41d108d936b776ddfec9d47ad364a (patch) | |
tree | 0e7cf8ae198b30e21b3dc98e50845b2610f71e60 /payloads/libpayload/drivers/usb/usbmsc.c | |
parent | 421303a25aef04bb3d5431a4e6f4f6215bc772fe (diff) |
libpayload: Better error detection in USB mass storage
This implements status transport (CSW) more closely to the standard
(usbmassbulk_10).
Change-Id: Ife516316e054d4e87ebe698dc487eeb9ebcfd38d
Signed-off-by: Nico Huber <nico.huber@secunet.com>
Reviewed-on: http://review.coreboot.org/1072
Reviewed-by: Peter Stuge <peter@stuge.se>
Tested-by: build bot (Jenkins)
Diffstat (limited to 'payloads/libpayload/drivers/usb/usbmsc.c')
-rw-r--r-- | payloads/libpayload/drivers/usb/usbmsc.c | 29 |
1 files changed, 21 insertions, 8 deletions
diff --git a/payloads/libpayload/drivers/usb/usbmsc.c b/payloads/libpayload/drivers/usb/usbmsc.c index 8d5773629f..fd6517a5e3 100644 --- a/payloads/libpayload/drivers/usb/usbmsc.c +++ b/payloads/libpayload/drivers/usb/usbmsc.c @@ -151,8 +151,8 @@ get_max_luns (usbdev_t *dev) return luns; } -int tag; -int lun = 0; +unsigned int tag; +unsigned char lun = 0; static void wrap_cbw (cbw_t *cbw, int datalen, cbw_direction dir, const u8 *cmd, @@ -161,7 +161,7 @@ wrap_cbw (cbw_t *cbw, int datalen, cbw_direction dir, const u8 *cmd, memset (cbw, 0, sizeof (cbw_t)); cbw->dCBWSignature = cbw_signature; - cbw->dCBWTag = tag++; + cbw->dCBWTag = ++tag; cbw->bCBWLUN = lun; // static value per device cbw->dCBWDataTransferLength = datalen; @@ -170,11 +170,22 @@ wrap_cbw (cbw_t *cbw, int datalen, cbw_direction dir, const u8 *cmd, cbw->bCBWCBLength = cmdlen; } -static void +static int get_csw (endpoint_t *ep, csw_t *csw) { - if (ep->dev->controller->bulk (ep, sizeof (csw_t), (u8 *) csw, 1)) + if (ep->dev->controller->bulk (ep, sizeof (csw_t), (u8 *) csw, 1)) { clear_stall (ep); + if (ep->dev->controller->bulk + (ep, sizeof (csw_t), (u8 *) csw, 1)) { + reset_transport (ep->dev); + return 1; + } + } + if (csw->dCSWTag != tag) { + reset_transport (ep->dev); + return 1; + } + return 0; } static int @@ -209,7 +220,8 @@ execute_command (usbdev_t *dev, cbw_direction dir, const u8 *cb, int cblen, } } } - get_csw (MSC_INST (dev)->bulk_in, &csw); + if (get_csw (MSC_INST (dev)->bulk_in, &csw)) + return 1; if (always_succeed == 1) { // return success, regardless of message return 0; @@ -223,8 +235,9 @@ execute_command (usbdev_t *dev, cbw_direction dir, const u8 *cb, int cblen, // no error, exit return 0; } - // error "check condition" or reserved error - request_sense (dev); + if (cb[0] != 0x03) /* 0x03 == request sense */ + // error "check condition" or reserved error + request_sense (dev); return 1; } |