diff options
author | Alan Stern <stern@rowland.harvard.edu> | 2008-08-14 15:48:30 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2008-10-17 17:40:52 -0400 |
commit | 851a526dcf97964265cadcc6664a9f0ff7c143c7 (patch) | |
tree | faf8bdb4322b89db72f8c1c8738733a9b86dba2f /drivers/usb/gadget/dummy_hcd.c | |
parent | a7a19fac8a9fbc0182fb1b464848a31529c39433 (diff) |
USB: gadget: dummy_hcd: implement set_wedge
This patch (as1131) implements the set_wedge() method for dummy_hcd.
This method is necessary for strict USBCV compliance in
g_file_storage.
Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/gadget/dummy_hcd.c')
-rw-r--r-- | drivers/usb/gadget/dummy_hcd.c | 33 |
1 files changed, 27 insertions, 6 deletions
diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index 7600a0c78753..9064696636ac 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c | |||
@@ -82,6 +82,7 @@ struct dummy_ep { | |||
82 | const struct usb_endpoint_descriptor *desc; | 82 | const struct usb_endpoint_descriptor *desc; |
83 | struct usb_ep ep; | 83 | struct usb_ep ep; |
84 | unsigned halted : 1; | 84 | unsigned halted : 1; |
85 | unsigned wedged : 1; | ||
85 | unsigned already_seen : 1; | 86 | unsigned already_seen : 1; |
86 | unsigned setup_stage : 1; | 87 | unsigned setup_stage : 1; |
87 | }; | 88 | }; |
@@ -436,6 +437,7 @@ dummy_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) | |||
436 | /* at this point real hardware should be NAKing transfers | 437 | /* at this point real hardware should be NAKing transfers |
437 | * to that endpoint, until a buffer is queued to it. | 438 | * to that endpoint, until a buffer is queued to it. |
438 | */ | 439 | */ |
440 | ep->halted = ep->wedged = 0; | ||
439 | retval = 0; | 441 | retval = 0; |
440 | done: | 442 | done: |
441 | return retval; | 443 | return retval; |
@@ -597,7 +599,7 @@ static int dummy_dequeue (struct usb_ep *_ep, struct usb_request *_req) | |||
597 | } | 599 | } |
598 | 600 | ||
599 | static int | 601 | static int |
600 | dummy_set_halt (struct usb_ep *_ep, int value) | 602 | dummy_set_halt_and_wedge(struct usb_ep *_ep, int value, int wedged) |
601 | { | 603 | { |
602 | struct dummy_ep *ep; | 604 | struct dummy_ep *ep; |
603 | struct dummy *dum; | 605 | struct dummy *dum; |
@@ -609,16 +611,32 @@ dummy_set_halt (struct usb_ep *_ep, int value) | |||
609 | if (!dum->driver) | 611 | if (!dum->driver) |
610 | return -ESHUTDOWN; | 612 | return -ESHUTDOWN; |
611 | if (!value) | 613 | if (!value) |
612 | ep->halted = 0; | 614 | ep->halted = ep->wedged = 0; |
613 | else if (ep->desc && (ep->desc->bEndpointAddress & USB_DIR_IN) && | 615 | else if (ep->desc && (ep->desc->bEndpointAddress & USB_DIR_IN) && |
614 | !list_empty (&ep->queue)) | 616 | !list_empty (&ep->queue)) |
615 | return -EAGAIN; | 617 | return -EAGAIN; |
616 | else | 618 | else { |
617 | ep->halted = 1; | 619 | ep->halted = 1; |
620 | if (wedged) | ||
621 | ep->wedged = 1; | ||
622 | } | ||
618 | /* FIXME clear emulated data toggle too */ | 623 | /* FIXME clear emulated data toggle too */ |
619 | return 0; | 624 | return 0; |
620 | } | 625 | } |
621 | 626 | ||
627 | static int | ||
628 | dummy_set_halt(struct usb_ep *_ep, int value) | ||
629 | { | ||
630 | return dummy_set_halt_and_wedge(_ep, value, 0); | ||
631 | } | ||
632 | |||
633 | static int dummy_set_wedge(struct usb_ep *_ep) | ||
634 | { | ||
635 | if (!_ep || _ep->name == ep0name) | ||
636 | return -EINVAL; | ||
637 | return dummy_set_halt_and_wedge(_ep, 1, 1); | ||
638 | } | ||
639 | |||
622 | static const struct usb_ep_ops dummy_ep_ops = { | 640 | static const struct usb_ep_ops dummy_ep_ops = { |
623 | .enable = dummy_enable, | 641 | .enable = dummy_enable, |
624 | .disable = dummy_disable, | 642 | .disable = dummy_disable, |
@@ -630,6 +648,7 @@ static const struct usb_ep_ops dummy_ep_ops = { | |||
630 | .dequeue = dummy_dequeue, | 648 | .dequeue = dummy_dequeue, |
631 | 649 | ||
632 | .set_halt = dummy_set_halt, | 650 | .set_halt = dummy_set_halt, |
651 | .set_wedge = dummy_set_wedge, | ||
633 | }; | 652 | }; |
634 | 653 | ||
635 | /*-------------------------------------------------------------------------*/ | 654 | /*-------------------------------------------------------------------------*/ |
@@ -760,7 +779,8 @@ usb_gadget_register_driver (struct usb_gadget_driver *driver) | |||
760 | ep->ep.name = ep_name [i]; | 779 | ep->ep.name = ep_name [i]; |
761 | ep->ep.ops = &dummy_ep_ops; | 780 | ep->ep.ops = &dummy_ep_ops; |
762 | list_add_tail (&ep->ep.ep_list, &dum->gadget.ep_list); | 781 | list_add_tail (&ep->ep.ep_list, &dum->gadget.ep_list); |
763 | ep->halted = ep->already_seen = ep->setup_stage = 0; | 782 | ep->halted = ep->wedged = ep->already_seen = |
783 | ep->setup_stage = 0; | ||
764 | ep->ep.maxpacket = ~0; | 784 | ep->ep.maxpacket = ~0; |
765 | ep->last_io = jiffies; | 785 | ep->last_io = jiffies; |
766 | ep->gadget = &dum->gadget; | 786 | ep->gadget = &dum->gadget; |
@@ -1351,7 +1371,7 @@ restart: | |||
1351 | } else if (setup.bRequestType == Ep_Request) { | 1371 | } else if (setup.bRequestType == Ep_Request) { |
1352 | // endpoint halt | 1372 | // endpoint halt |
1353 | ep2 = find_endpoint (dum, w_index); | 1373 | ep2 = find_endpoint (dum, w_index); |
1354 | if (!ep2) { | 1374 | if (!ep2 || ep2->ep.name == ep0name) { |
1355 | value = -EOPNOTSUPP; | 1375 | value = -EOPNOTSUPP; |
1356 | break; | 1376 | break; |
1357 | } | 1377 | } |
@@ -1380,7 +1400,8 @@ restart: | |||
1380 | value = -EOPNOTSUPP; | 1400 | value = -EOPNOTSUPP; |
1381 | break; | 1401 | break; |
1382 | } | 1402 | } |
1383 | ep2->halted = 0; | 1403 | if (!ep2->wedged) |
1404 | ep2->halted = 0; | ||
1384 | value = 0; | 1405 | value = 0; |
1385 | status = 0; | 1406 | status = 0; |
1386 | } | 1407 | } |