diff options
author | Quinn Jensen <quinn.jensen@freescale.com> | 2007-10-24 21:25:14 -0600 |
---|---|---|
committer | Quinn Jensen <quinn.jensen@freescale.com> | 2007-10-24 21:25:14 -0600 |
commit | 5f4f72844194949c73457d0943ff5d4d1bb1f3ac (patch) | |
tree | 9cfa4335f2ac69759b86622db471a611bf5a2cc2 /drivers/usb/gadget | |
parent | 05e3d1d42ddc0ff46f6d77d71ff8622d33654950 (diff) |
USB: USBCV 1.3 HaltEndpointTest fails.
Bugzilla 783. USBCV 1.3 HaltEndpointTest fails.
Fix this by porting ch9getstatus() from fsl_usb2_udc.c.
Applies to linux 2.6.22 kernel for MX platforms.
http://www.bitshrine.org/gpp/linux-2.6.22-mx-USB-USBCV-1.3-HaltEndpointTest-fails.patch
Diffstat (limited to 'drivers/usb/gadget')
-rw-r--r-- | drivers/usb/gadget/arcotg_udc.c | 79 | ||||
-rw-r--r-- | drivers/usb/gadget/arcotg_udc.h | 3 |
2 files changed, 57 insertions, 25 deletions
diff --git a/drivers/usb/gadget/arcotg_udc.c b/drivers/usb/gadget/arcotg_udc.c index ee91d3f578cf..7c3d19c2ee2f 100644 --- a/drivers/usb/gadget/arcotg_udc.c +++ b/drivers/usb/gadget/arcotg_udc.c @@ -475,11 +475,23 @@ static void dr_ep_change_stall(unsigned char ep_num, unsigned char dir, tmp_epctrl &= ~EPCTRL_RX_EP_STALL; tmp_epctrl |= EPCTRL_RX_DATA_TOGGLE_RST; } - } usb_slave_regs->endptctrl[ep_num] = cpu_to_le32(tmp_epctrl); } +/* Get stall status of a specific ep + Return: 0: not stalled; 1:stalled */ +static int dr_ep_get_stall(unsigned char ep_num, unsigned char dir) +{ + u32 epctrl; + + epctrl = le32_to_cpu(usb_slave_regs->endptctrl[ep_num]); + if (dir) + return (epctrl & EPCTRL_TX_EP_STALL) ? 1 : 0; + else + return (epctrl & EPCTRL_RX_EP_STALL) ? 1 : 0; +} + /******************************************************************** Internal Structure Build up functions ********************************************************************/ @@ -1577,49 +1589,64 @@ static void ch9setaddress(struct arcotg_udc *udc, u16 value, u16 index, ep0stall(udc); } -static void ch9getstatus(struct arcotg_udc *udc, u16 value, u16 index, - u16 length) +static void ch9getstatus(struct arcotg_udc *udc, u8 request_type, u16 value, + u16 index, u16 length) { - u16 usb_status = 0; /* fix me to give correct status */ + u16 tmp = 0; /* Status, cpu endian */ struct arcotg_req *req; struct arcotg_ep *ep; int status = 0; - unsigned long flags; - pr_debug("%s\n", __FUNCTION__); ep = &udc->eps[0]; - req = container_of(arcotg_alloc_request(&ep->ep, GFP_KERNEL), - struct arcotg_req, req); + if ((request_type & USB_RECIP_MASK) == USB_RECIP_DEVICE) { + /* Get device status */ + tmp = 1 << USB_DEVICE_SELF_POWERED; + tmp |= udc->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP; + } else if ((request_type & USB_RECIP_MASK) == USB_RECIP_INTERFACE) { + /* Get interface status */ + /* We don't have interface information in udc driver */ + tmp = 0; + } else if ((request_type & USB_RECIP_MASK) == USB_RECIP_ENDPOINT) { + /* Get endpoint status */ + struct arcotg_ep *target_ep; + + target_ep = get_ep_by_pipe(udc, get_pipe_by_windex(index)); + + /* stall if endpoint doesn't exist */ + if (!target_ep->desc) + goto stall; + tmp = dr_ep_get_stall(ep_index(target_ep), ep_is_in(target_ep)) + << USB_ENDPOINT_HALT; + } + + udc->ep0_dir = USB_DIR_IN; + /* Borrow the per device status_req */ + req = udc->status_req; + /* Fill in the reqest structure */ + *((u16 *) req->req.buf) = cpu_to_le16(tmp); + req->ep = ep; req->req.length = 2; - req->req.buf = &usb_status; req->req.status = -EINPROGRESS; req->req.actual = 0; + req->req.complete = NULL; + req->dtd_count = 0; - spin_lock_irqsave(&udc->lock, flags); - - /* data phase */ + /* prime the data phase */ if ((arcotg_req_to_dtd(req, udc) == 0)) status = arcotg_queue_td(ep, req); else /* no mem */ goto stall; if (status) { - printk(KERN_ERR "Can't respond to getstatus request \n"); - ep0stall(udc); - } else { - udc->ep0_state = DATA_STATE_XMIT; - pr_debug("udc: ep0_state now DATA_STATE_XMIT\n"); + printk(KERN_ERR "Can't respond to getstatus request\n"); + goto stall; } - list_add_tail(&req->queue, &ep->queue); - dump_ep_queue(ep); - - spin_unlock_irqrestore(&udc->lock, flags); + udc->ep0_state = DATA_STATE_XMIT; return; - - stall: +stall: ep0stall(udc); } @@ -1683,8 +1710,8 @@ static void setup_received_irq(struct arcotg_udc *udc, bRequestType & (USB_DIR_IN | USB_TYPE_STANDARD)) != (USB_DIR_IN | USB_TYPE_STANDARD)) break; - ch9getstatus(udc, setup->wValue, setup->wIndex, - setup->wLength); + ch9getstatus(udc, setup->bRequestType, setup->wValue, + setup->wIndex, setup->wLength); break; case USB_REQ_SET_ADDRESS: @@ -2140,6 +2167,7 @@ static void reset_irq(struct arcotg_udc *udc) /* Clear usb state */ udc->usb_state = USB_STATE_DEFAULT; + udc->remote_wakeup = 0; /* default to 0 on reset */ /* Clear all the setup token semaphores */ temp = le32_to_cpu(usb_slave_regs->endptsetupstat); @@ -2759,6 +2787,7 @@ static void *struct_udc_setup(struct platform_device *pdev) udc->resume_state = USB_STATE_NOTATTACHED; udc->usb_state = USB_STATE_POWERED; udc->ep0_dir = 0; + udc->remote_wakeup = 0; /* default to 0 on reset */ /* initliaze the arcotg_udc lock */ spin_lock_init(&udc->lock); diff --git a/drivers/usb/gadget/arcotg_udc.h b/drivers/usb/gadget/arcotg_udc.h index dee374743aaa..46cf84a45ddd 100644 --- a/drivers/usb/gadget/arcotg_udc.h +++ b/drivers/usb/gadget/arcotg_udc.h @@ -517,6 +517,7 @@ struct arcotg_udc { unsigned softconnect:1; unsigned vbus_active:1; unsigned stopped:1; + unsigned remote_wakeup:1; struct ep_queue_head *ep_qh; /* Endpoints Queue-Head */ int ep_qh_size; /* Endpoints Queue-Head */ @@ -591,6 +592,8 @@ static void dump_msg(const char *label, const u8 * buf, unsigned int length) #define get_ep_by_pipe(udc, pipe) ((pipe == 1)? &udc->eps[0]: \ &udc->eps[pipe]) +#define get_pipe_by_windex(windex) ((windex & USB_ENDPOINT_NUMBER_MASK) \ + * 2 + ((windex & USB_DIR_IN) ? 1 : 0)) /* Bulk only class request */ #define USB_BULK_RESET_REQUEST 0xff |