Commit 851a526d authored by Alan Stern's avatar Alan Stern Committed by Greg Kroah-Hartman

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: default avatarAlan Stern <stern@rowland.harvard.edu>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent a7a19fac
...@@ -82,6 +82,7 @@ struct dummy_ep { ...@@ -82,6 +82,7 @@ struct dummy_ep {
const struct usb_endpoint_descriptor *desc; const struct usb_endpoint_descriptor *desc;
struct usb_ep ep; struct usb_ep ep;
unsigned halted : 1; unsigned halted : 1;
unsigned wedged : 1;
unsigned already_seen : 1; unsigned already_seen : 1;
unsigned setup_stage : 1; unsigned setup_stage : 1;
}; };
...@@ -436,6 +437,7 @@ dummy_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) ...@@ -436,6 +437,7 @@ dummy_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
/* at this point real hardware should be NAKing transfers /* at this point real hardware should be NAKing transfers
* to that endpoint, until a buffer is queued to it. * to that endpoint, until a buffer is queued to it.
*/ */
ep->halted = ep->wedged = 0;
retval = 0; retval = 0;
done: done:
return retval; return retval;
...@@ -597,7 +599,7 @@ static int dummy_dequeue (struct usb_ep *_ep, struct usb_request *_req) ...@@ -597,7 +599,7 @@ static int dummy_dequeue (struct usb_ep *_ep, struct usb_request *_req)
} }
static int static int
dummy_set_halt (struct usb_ep *_ep, int value) dummy_set_halt_and_wedge(struct usb_ep *_ep, int value, int wedged)
{ {
struct dummy_ep *ep; struct dummy_ep *ep;
struct dummy *dum; struct dummy *dum;
...@@ -609,16 +611,32 @@ dummy_set_halt (struct usb_ep *_ep, int value) ...@@ -609,16 +611,32 @@ dummy_set_halt (struct usb_ep *_ep, int value)
if (!dum->driver) if (!dum->driver)
return -ESHUTDOWN; return -ESHUTDOWN;
if (!value) if (!value)
ep->halted = 0; ep->halted = ep->wedged = 0;
else if (ep->desc && (ep->desc->bEndpointAddress & USB_DIR_IN) && else if (ep->desc && (ep->desc->bEndpointAddress & USB_DIR_IN) &&
!list_empty (&ep->queue)) !list_empty (&ep->queue))
return -EAGAIN; return -EAGAIN;
else else {
ep->halted = 1; ep->halted = 1;
if (wedged)
ep->wedged = 1;
}
/* FIXME clear emulated data toggle too */ /* FIXME clear emulated data toggle too */
return 0; return 0;
} }
static int
dummy_set_halt(struct usb_ep *_ep, int value)
{
return dummy_set_halt_and_wedge(_ep, value, 0);
}
static int dummy_set_wedge(struct usb_ep *_ep)
{
if (!_ep || _ep->name == ep0name)
return -EINVAL;
return dummy_set_halt_and_wedge(_ep, 1, 1);
}
static const struct usb_ep_ops dummy_ep_ops = { static const struct usb_ep_ops dummy_ep_ops = {
.enable = dummy_enable, .enable = dummy_enable,
.disable = dummy_disable, .disable = dummy_disable,
...@@ -630,6 +648,7 @@ static const struct usb_ep_ops dummy_ep_ops = { ...@@ -630,6 +648,7 @@ static const struct usb_ep_ops dummy_ep_ops = {
.dequeue = dummy_dequeue, .dequeue = dummy_dequeue,
.set_halt = dummy_set_halt, .set_halt = dummy_set_halt,
.set_wedge = dummy_set_wedge,
}; };
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
...@@ -760,7 +779,8 @@ usb_gadget_register_driver (struct usb_gadget_driver *driver) ...@@ -760,7 +779,8 @@ usb_gadget_register_driver (struct usb_gadget_driver *driver)
ep->ep.name = ep_name [i]; ep->ep.name = ep_name [i];
ep->ep.ops = &dummy_ep_ops; ep->ep.ops = &dummy_ep_ops;
list_add_tail (&ep->ep.ep_list, &dum->gadget.ep_list); list_add_tail (&ep->ep.ep_list, &dum->gadget.ep_list);
ep->halted = ep->already_seen = ep->setup_stage = 0; ep->halted = ep->wedged = ep->already_seen =
ep->setup_stage = 0;
ep->ep.maxpacket = ~0; ep->ep.maxpacket = ~0;
ep->last_io = jiffies; ep->last_io = jiffies;
ep->gadget = &dum->gadget; ep->gadget = &dum->gadget;
...@@ -1351,7 +1371,7 @@ static void dummy_timer (unsigned long _dum) ...@@ -1351,7 +1371,7 @@ static void dummy_timer (unsigned long _dum)
} else if (setup.bRequestType == Ep_Request) { } else if (setup.bRequestType == Ep_Request) {
// endpoint halt // endpoint halt
ep2 = find_endpoint (dum, w_index); ep2 = find_endpoint (dum, w_index);
if (!ep2) { if (!ep2 || ep2->ep.name == ep0name) {
value = -EOPNOTSUPP; value = -EOPNOTSUPP;
break; break;
} }
...@@ -1380,7 +1400,8 @@ static void dummy_timer (unsigned long _dum) ...@@ -1380,7 +1400,8 @@ static void dummy_timer (unsigned long _dum)
value = -EOPNOTSUPP; value = -EOPNOTSUPP;
break; break;
} }
ep2->halted = 0; if (!ep2->wedged)
ep2->halted = 0;
value = 0; value = 0;
status = 0; status = 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment