diff options
author | Alan Stern <stern@rowland.harvard.edu> | 2008-04-14 11:45:29 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2008-04-25 00:16:52 -0400 |
commit | b950bdbc67041412cb042e404938667204c7902c (patch) | |
tree | 6325701be401abd45c60e7f98d253e33ce9b589e /drivers | |
parent | 9aebfd6bda789891e6d296bb49b5fb32d1057f18 (diff) |
USB: g_file_storage: ignore bulk-out data after invalid CBW
This patch (as1061) makes g_file_storage more compliant with the
Bulk-Only Transport specification. After an invalid CBW is received,
the gadget must ignore any further bulk-OUT data until it is reset.
Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/usb/gadget/file_storage.c | 28 |
1 files changed, 15 insertions, 13 deletions
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c index 017a196d041f..0a726e106ccd 100644 --- a/drivers/usb/gadget/file_storage.c +++ b/drivers/usb/gadget/file_storage.c | |||
@@ -644,7 +644,7 @@ struct fsg_dev { | |||
644 | 644 | ||
645 | unsigned long atomic_bitflags; | 645 | unsigned long atomic_bitflags; |
646 | #define REGISTERED 0 | 646 | #define REGISTERED 0 |
647 | #define CLEAR_BULK_HALTS 1 | 647 | #define IGNORE_BULK_OUT 1 |
648 | #define SUSPENDED 2 | 648 | #define SUSPENDED 2 |
649 | 649 | ||
650 | struct usb_ep *bulk_in; | 650 | struct usb_ep *bulk_in; |
@@ -2936,8 +2936,8 @@ static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh) | |||
2936 | struct usb_request *req = bh->outreq; | 2936 | struct usb_request *req = bh->outreq; |
2937 | struct bulk_cb_wrap *cbw = req->buf; | 2937 | struct bulk_cb_wrap *cbw = req->buf; |
2938 | 2938 | ||
2939 | /* Was this a real packet? */ | 2939 | /* Was this a real packet? Should it be ignored? */ |
2940 | if (req->status) | 2940 | if (req->status || test_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags)) |
2941 | return -EINVAL; | 2941 | return -EINVAL; |
2942 | 2942 | ||
2943 | /* Is the CBW valid? */ | 2943 | /* Is the CBW valid? */ |
@@ -2948,13 +2948,17 @@ static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh) | |||
2948 | req->actual, | 2948 | req->actual, |
2949 | le32_to_cpu(cbw->Signature)); | 2949 | le32_to_cpu(cbw->Signature)); |
2950 | 2950 | ||
2951 | /* The Bulk-only spec says we MUST stall the bulk pipes! | 2951 | /* The Bulk-only spec says we MUST stall the IN endpoint |
2952 | * If we want to avoid stalls, set a flag so that we will | 2952 | * (6.6.1), so it's unavoidable. It also says we must |
2953 | * clear the endpoint halts at the next reset. */ | 2953 | * retain this state until the next reset, but there's |
2954 | if (!mod_data.can_stall) | 2954 | * no way to tell the controller driver it should ignore |
2955 | set_bit(CLEAR_BULK_HALTS, &fsg->atomic_bitflags); | 2955 | * Clear-Feature(HALT) requests. |
2956 | fsg_set_halt(fsg, fsg->bulk_out); | 2956 | * |
2957 | * We aren't required to halt the OUT endpoint; instead | ||
2958 | * we can simply accept and discard any data received | ||
2959 | * until the next reset. */ | ||
2957 | halt_bulk_in_endpoint(fsg); | 2960 | halt_bulk_in_endpoint(fsg); |
2961 | set_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags); | ||
2958 | return -EINVAL; | 2962 | return -EINVAL; |
2959 | } | 2963 | } |
2960 | 2964 | ||
@@ -3140,6 +3144,7 @@ reset: | |||
3140 | goto reset; | 3144 | goto reset; |
3141 | fsg->bulk_out_enabled = 1; | 3145 | fsg->bulk_out_enabled = 1; |
3142 | fsg->bulk_out_maxpacket = le16_to_cpu(d->wMaxPacketSize); | 3146 | fsg->bulk_out_maxpacket = le16_to_cpu(d->wMaxPacketSize); |
3147 | clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags); | ||
3143 | 3148 | ||
3144 | if (transport_is_cbi()) { | 3149 | if (transport_is_cbi()) { |
3145 | d = ep_desc(fsg->gadget, &fs_intr_in_desc, &hs_intr_in_desc); | 3150 | d = ep_desc(fsg->gadget, &fs_intr_in_desc, &hs_intr_in_desc); |
@@ -3321,11 +3326,8 @@ static void handle_exception(struct fsg_dev *fsg) | |||
3321 | /* In case we were forced against our will to halt a | 3326 | /* In case we were forced against our will to halt a |
3322 | * bulk endpoint, clear the halt now. (The SuperH UDC | 3327 | * bulk endpoint, clear the halt now. (The SuperH UDC |
3323 | * requires this.) */ | 3328 | * requires this.) */ |
3324 | if (test_and_clear_bit(CLEAR_BULK_HALTS, | 3329 | if (test_and_clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags)) |
3325 | &fsg->atomic_bitflags)) { | ||
3326 | usb_ep_clear_halt(fsg->bulk_in); | 3330 | usb_ep_clear_halt(fsg->bulk_in); |
3327 | usb_ep_clear_halt(fsg->bulk_out); | ||
3328 | } | ||
3329 | 3331 | ||
3330 | if (transport_is_bbb()) { | 3332 | if (transport_is_bbb()) { |
3331 | if (fsg->ep0_req_tag == exception_req_tag) | 3333 | if (fsg->ep0_req_tag == exception_req_tag) |