aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2008-04-14 11:45:29 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2008-04-25 00:16:52 -0400
commitb950bdbc67041412cb042e404938667204c7902c (patch)
tree6325701be401abd45c60e7f98d253e33ce9b589e
parent9aebfd6bda789891e6d296bb49b5fb32d1057f18 (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>
-rw-r--r--drivers/usb/gadget/file_storage.c28
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)