forked from Minki/linux
USB: fsl_usb2_udc: fix bug in processing setup requests
Kim Liu found that in the original code certain class setup requests are wrongly recognized and processed as standard setup requests. For that reason gadget ether can't work in RNDIS mode with Windows host. The patch fixes the setup request processing code, and makes class requests correctly passed to gadget layer. Signed-off-by: Li Yang <leoli@freescale.com> Signed-off-by: Kim Liu <KLiu@vixs.com> Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
parent
d1a94f080f
commit
39d1f8c9fc
@ -1277,31 +1277,32 @@ static void setup_received_irq(struct fsl_udc *udc,
|
||||
|
||||
udc_reset_ep_queue(udc, 0);
|
||||
|
||||
/* We process some stardard setup requests here */
|
||||
switch (setup->bRequest) {
|
||||
/* Request that need Data+Status phase from udc */
|
||||
case USB_REQ_GET_STATUS:
|
||||
if ((setup->bRequestType & (USB_DIR_IN | USB_TYPE_STANDARD))
|
||||
/* Data+Status phase from udc */
|
||||
if ((setup->bRequestType & (USB_DIR_IN | USB_TYPE_MASK))
|
||||
!= (USB_DIR_IN | USB_TYPE_STANDARD))
|
||||
break;
|
||||
ch9getstatus(udc, setup->bRequestType, wValue, wIndex, wLength);
|
||||
break;
|
||||
return;
|
||||
|
||||
/* Requests that need Status phase from udc */
|
||||
case USB_REQ_SET_ADDRESS:
|
||||
/* Status phase from udc */
|
||||
if (setup->bRequestType != (USB_DIR_OUT | USB_TYPE_STANDARD
|
||||
| USB_RECIP_DEVICE))
|
||||
break;
|
||||
ch9setaddress(udc, wValue, wIndex, wLength);
|
||||
break;
|
||||
return;
|
||||
|
||||
/* Handled by udc, no data, status by udc */
|
||||
case USB_REQ_CLEAR_FEATURE:
|
||||
case USB_REQ_SET_FEATURE:
|
||||
{ /* status transaction */
|
||||
/* Status phase from udc */
|
||||
{
|
||||
int rc = -EOPNOTSUPP;
|
||||
|
||||
if ((setup->bRequestType & USB_RECIP_MASK)
|
||||
== USB_RECIP_ENDPOINT) {
|
||||
if ((setup->bRequestType & (USB_RECIP_MASK | USB_TYPE_MASK))
|
||||
== (USB_RECIP_ENDPOINT | USB_TYPE_STANDARD)) {
|
||||
int pipe = get_pipe_by_windex(wIndex);
|
||||
struct fsl_ep *ep;
|
||||
|
||||
@ -1315,8 +1316,9 @@ static void setup_received_irq(struct fsl_udc *udc,
|
||||
? 1 : 0);
|
||||
spin_lock(&udc->lock);
|
||||
|
||||
} else if ((setup->bRequestType & USB_RECIP_MASK)
|
||||
== USB_RECIP_DEVICE) {
|
||||
} else if ((setup->bRequestType & (USB_RECIP_MASK
|
||||
| USB_TYPE_MASK)) == (USB_RECIP_DEVICE
|
||||
| USB_TYPE_STANDARD)) {
|
||||
/* Note: The driver has not include OTG support yet.
|
||||
* This will be set when OTG support is added */
|
||||
if (!udc->gadget.is_otg)
|
||||
@ -1329,38 +1331,41 @@ static void setup_received_irq(struct fsl_udc *udc,
|
||||
USB_DEVICE_A_ALT_HNP_SUPPORT)
|
||||
udc->gadget.a_alt_hnp_support = 1;
|
||||
rc = 0;
|
||||
}
|
||||
} else
|
||||
break;
|
||||
|
||||
if (rc == 0) {
|
||||
if (ep0_prime_status(udc, EP_DIR_IN))
|
||||
ep0stall(udc);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
/* Requests handled by gadget */
|
||||
default:
|
||||
if (wLength) {
|
||||
/* Data phase from gadget, status phase from udc */
|
||||
udc->ep0_dir = (setup->bRequestType & USB_DIR_IN)
|
||||
? USB_DIR_IN : USB_DIR_OUT;
|
||||
spin_unlock(&udc->lock);
|
||||
if (udc->driver->setup(&udc->gadget,
|
||||
&udc->local_setup_buff) < 0)
|
||||
ep0stall(udc);
|
||||
spin_lock(&udc->lock);
|
||||
udc->ep0_state = (setup->bRequestType & USB_DIR_IN)
|
||||
? DATA_STATE_XMIT : DATA_STATE_RECV;
|
||||
|
||||
} else {
|
||||
/* No data phase, IN status from gadget */
|
||||
udc->ep0_dir = USB_DIR_IN;
|
||||
spin_unlock(&udc->lock);
|
||||
if (udc->driver->setup(&udc->gadget,
|
||||
&udc->local_setup_buff) < 0)
|
||||
ep0stall(udc);
|
||||
spin_lock(&udc->lock);
|
||||
udc->ep0_state = WAIT_FOR_OUT_STATUS;
|
||||
}
|
||||
break;
|
||||
/* Requests handled by gadget */
|
||||
if (wLength) {
|
||||
/* Data phase from gadget, status phase from udc */
|
||||
udc->ep0_dir = (setup->bRequestType & USB_DIR_IN)
|
||||
? USB_DIR_IN : USB_DIR_OUT;
|
||||
spin_unlock(&udc->lock);
|
||||
if (udc->driver->setup(&udc->gadget,
|
||||
&udc->local_setup_buff) < 0)
|
||||
ep0stall(udc);
|
||||
spin_lock(&udc->lock);
|
||||
udc->ep0_state = (setup->bRequestType & USB_DIR_IN)
|
||||
? DATA_STATE_XMIT : DATA_STATE_RECV;
|
||||
} else {
|
||||
/* No data phase, IN status from gadget */
|
||||
udc->ep0_dir = USB_DIR_IN;
|
||||
spin_unlock(&udc->lock);
|
||||
if (udc->driver->setup(&udc->gadget,
|
||||
&udc->local_setup_buff) < 0)
|
||||
ep0stall(udc);
|
||||
spin_lock(&udc->lock);
|
||||
udc->ep0_state = WAIT_FOR_OUT_STATUS;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user