static int udc_read_urb(struct usb_endpoint_instance *endpoint) { struct urb *urb = endpoint->rcv_urb; int ep_num = endpoint->endpoint_address & USB_ENDPOINT_NUMBER_MASK; u32 *data32 = (u32 *) urb->buffer; unsigned int i, n, is_short ; usbdbg("read urb on ep %d", ep_num); #if defined(USBDDBG) && defined(USBDPARANOIA) usbdbg("urb: buf %p, buf_len %d, actual_len %d", urb->buffer, urb->buffer_length, urb->actual_length); usbdbg("endpoint: rcv_packetSize %d", endpoint->rcv_packetSize); #endif if (readl(UDCCSN(ep_num)) & UDCCSR_BNE) n = readl(UDCBCN(ep_num)) & 0x3ff; else /* zlp */ n = 0; is_short = n != endpoint->rcv_packetSize; usbdbg("n %d%s", n, is_short ? "-s" : ""); for (i = 0; i < n; i += 4) data32[urb->actual_length / 4 + i / 4] = readl(UDCDN(ep_num)); udc_dump_buffer("urb read", (u8 *) data32, urb->actual_length + n); usbd_rcv_complete(endpoint, n, 0); return 0; }
static void musb_peri_rx_ep(unsigned int ep) { u16 peri_rxcount = readw(&musbr->ep[ep].epN.rxcount); if (peri_rxcount) { struct usb_endpoint_instance *endpoint; u32 length; u8 *data; endpoint = GET_ENDPOINT(udc_device, ep); if (endpoint && endpoint->rcv_urb) { struct urb *urb = endpoint->rcv_urb; unsigned int remaining_space = urb->buffer_length - urb->actual_length; if (remaining_space) { int urb_bad = 0; /* urb is good */ if (peri_rxcount > remaining_space) length = remaining_space; else length = peri_rxcount; data = (u8 *) urb->buffer_data; data += urb->actual_length; /* The common musb fifo reader */ read_fifo(ep, length, data); musb_peri_rx_ack(ep); /* * urb's actual_length is updated in * usbd_rcv_complete */ usbd_rcv_complete(endpoint, length, urb_bad); } else { if (debug_level > 0) serial_printf("ERROR : %s %d no space " "in rcv buffer\n", __PRETTY_FUNCTION__, ep); } } else { if (debug_level > 0) serial_printf("ERROR : %s %d problem with " "endpoint\n", __PRETTY_FUNCTION__, ep); } } else { if (debug_level > 0) serial_printf("ERROR : %s %d with nothing to do\n", __PRETTY_FUNCTION__, ep); } }
static void mxc_udc_ep_recv(u8 epnum) { mxc_ep_t *ep = mxc_udc.mxc_ep + (epnum * 2 + USB_RECV); struct ep_queue_item *tqi; while (1) { u32 nbytes; tqi = ep->ep_dtd[ep->done]; if (mxc_udc_tqi_empty(tqi)) break; nbytes = _mxc_ep_recv_data(epnum, tqi); usbd_rcv_complete(ep->epi, nbytes, 0); inc_index(ep->done); if (ep->done == ep->index) break; } }
static void S3C24X0_udc_epn(int ep) { struct usb_endpoint_instance *endpoint; struct urb *urb; u32 ep_csr1; if (ep >= S3C24X0_UDC_NUM_ENDPOINTS) return; endpoint = &udc_device->bus->endpoint_array[ep]; S3C24X0_UDC_SETIX(ep); if (endpoint->endpoint_address & USB_DIR_IN) { /* IN transfer (device to host) */ ep_csr1 = inl(S3C24X0_UDC_IN_CSR1_REG); debug("for ep=%u, CSR1=0x%x ", ep, ep_csr1); urb = endpoint->tx_urb; if (ep_csr1 & S3C24X0_UDC_ICSR1_SENTSTL) { /* Stall handshake */ debug("stall\n"); outl(0x00, S3C24X0_UDC_IN_CSR1_REG); return; } if (!(ep_csr1 & S3C24X0_UDC_ICSR1_PKTRDY) && urb && urb->actual_length) { debug("completing previously send data "); usbd_tx_complete(endpoint); /* push pending data into FIFO */ if ((endpoint->last == endpoint->tx_packetSize) && (urb->actual_length - endpoint->sent - endpoint->last == 0)) { endpoint->sent += endpoint->last; /* Write 0 bytes of data (ZLP) */ debug("ZLP "); outl(ep_csr1|S3C24X0_UDC_ICSR1_PKTRDY, S3C24X0_UDC_IN_CSR1_REG); } else { /* write actual data to fifo */ debug_urb_buffer("TX_DATA", endpoint); S3C24X0_write_noniso_tx_fifo(endpoint); outl(ep_csr1|S3C24X0_UDC_ICSR1_PKTRDY, S3C24X0_UDC_IN_CSR1_REG); } } debug("\n"); } else { /* OUT transfer (host to device) */ ep_csr1 = inl(S3C24X0_UDC_OUT_CSR1_REG); debug("for ep=%u, CSR1=0x%x ", ep, ep_csr1); urb = endpoint->rcv_urb; if (ep_csr1 & S3C24X0_UDC_OCSR1_SENTSTL) { /* Stall handshake */ outl(0x00, S3C24X0_UDC_IN_CSR1_REG); return; } if ((ep_csr1 & S3C24X0_UDC_OCSR1_PKTRDY) && urb) { /* Read pending data from fifo */ u32 fifo_count = fifo_count_out(); int is_last = 0; u32 i, urb_avail = urb->buffer_length - urb->actual_length; u8 *cp = urb->buffer + urb->actual_length; if (fifo_count < endpoint->rcv_packetSize) is_last = 1; debug("fifo_count=%u is_last=%, urb_avail=%u)\n", fifo_count, is_last, urb_avail); if (fifo_count < urb_avail) urb_avail = fifo_count; for (i = 0; i < urb_avail; i++) *cp++ = inb(ep_fifo_reg[ep]); if (is_last) outl(ep_csr1 & ~S3C24X0_UDC_OCSR1_PKTRDY, S3C24X0_UDC_OUT_CSR1_REG); usbd_rcv_complete(endpoint, urb_avail, 0); } } urb = endpoint->rcv_urb; }
static void musb_peri_ep0_rx(void) { /* * This is the completion of the data OUT / RX * * Host is sending data to ep0 that is not * part of setup. This comes from the cdc_recv_setup * op that is device specific. * * Pass the data back to driver ep0_recv_setup which * should give the cdc_recv_setup the chance to handle * the rx */ u16 csr0; u16 count0; if (debug_level > 3) { if (0 != ep0_urb->actual_length) { serial_printf("%s finished ? %d of %d\n", __PRETTY_FUNCTION__, ep0_urb->actual_length, ep0_urb->device_request.wLength); } } if (ep0_urb->device_request.wLength == ep0_urb->actual_length) { musb_peri_ep0_last(); SET_EP0_STATE(IDLE); ep0_recv_setup(ep0_urb); return; } csr0 = readw(&musbr->ep[0].ep0.csr0); if (!(MUSB_CSR0_RXPKTRDY & csr0)) return; count0 = readw(&musbr->ep[0].ep0.count0); if (count0) { struct usb_endpoint_instance *endpoint; u32 length; u8 *data; endpoint = ep0_endpoint; if (endpoint && endpoint->rcv_urb) { struct urb *urb = endpoint->rcv_urb; unsigned int remaining_space = urb->buffer_length - urb->actual_length; if (remaining_space) { int urb_bad = 0; /* urb is good */ if (count0 > remaining_space) length = remaining_space; else length = count0; data = (u8 *) urb->buffer_data; data += urb->actual_length; /* The common musb fifo reader */ read_fifo(0, length, data); musb_peri_ep0_ack_req(); /* * urb's actual_length is updated in * usbd_rcv_complete */ usbd_rcv_complete(endpoint, length, urb_bad); } else { if (debug_level > 0) serial_printf("ERROR : %s no space in " "rcv buffer\n", __PRETTY_FUNCTION__); } } else { if (debug_level > 0) serial_printf("ERROR : %s problem with " "endpoint\n", __PRETTY_FUNCTION__); } } else { if (debug_level > 0) serial_printf("ERROR : %s with nothing to do\n", __PRETTY_FUNCTION__); } }
static void s3c2410_udc_epn(int ep) { struct usb_endpoint_instance *endpoint; struct urb *urb; u32 ep_csr1; if (ep >= S3C2410_UDC_NUM_ENDPOINTS) return; endpoint = &udc_device->bus->endpoint_array[ep]; S3C2410_UDC_SETIX(ep); if (endpoint->endpoint_address & USB_DIR_IN) { /* IN transfer (device to host) */ ep_csr1 = inl(S3C2410_UDC_IN_CSR1_REG); debug("for ep=%u, IN_CSR1=0x%x ", ep, ep_csr1); urb = endpoint->tx_urb; if (ep_csr1 & S3C2410_UDC_ICSR1_SENTSTL) { /* Stall handshake */ debug("stall\n"); outl(0x00, S3C2410_UDC_IN_CSR1_REG); return; } if (!(ep_csr1 & S3C2410_UDC_ICSR1_PKTRDY) && urb && urb->actual_length) { debug("completing previously send data "); usbd_tx_complete(endpoint); /* push pending data into FIFO */ if ((endpoint->last == endpoint->tx_packetSize) && (urb->actual_length - endpoint->sent - endpoint->last == 0)) { endpoint->sent += endpoint->last; /* Write 0 bytes of data (ZLP) */ debug("ZLP "); outl(ep_csr1|S3C2410_UDC_ICSR1_PKTRDY, S3C2410_UDC_IN_CSR1_REG); } else { /* write actual data to fifo */ debug_urb_buffer("TX_DATA", endpoint); s3c2410_write_noniso_tx_fifo(endpoint); outl(ep_csr1|S3C2410_UDC_ICSR1_PKTRDY, S3C2410_UDC_IN_CSR1_REG); } } debug("\n"); } else { /* OUT transfer (host to device) */ ep_csr1 = inl(S3C2410_UDC_OUT_CSR1_REG); debug("for ep=%u, OUT_CSR1=0x%x ", ep, ep_csr1); urb = endpoint->rcv_urb; if (ep_csr1 & S3C2410_UDC_OCSR1_SENTSTL) { /* Stall handshake */ debugX("SENT STALL\n"); outl(0x00, S3C2410_UDC_IN_CSR1_REG); return; } if ((ep_csr1 & S3C2410_UDC_OCSR1_PKTRDY) && urb) { /* Read pending data from fifo */ u32 fifo_count = fifo_count_out(); int is_last = 0; u32 i, urb_avail = urb->buffer_length - urb->actual_length; u8 *cp = urb->buffer + urb->actual_length; if (fifo_count < endpoint->rcv_packetSize) is_last = 1; debug("fifo_count=%u is_last=%d, urb_avail=%u\n", fifo_count, is_last, urb_avail); if (fifo_count < urb_avail) urb_avail = fifo_count; for (i = 0; i < urb_avail; i++) *cp++ = inb(ep_fifo_reg[ep]); /* if (is_last) */ /* * Once the MCU reads the packet from FIFO, * this bit should be cleared */ #ifndef AUTO_CLEAR outl(ep_csr1 & ~S3C2410_UDC_OCSR1_PKTRDY, S3C2410_UDC_OUT_CSR1_REG); #endif usbd_rcv_complete(endpoint, urb_avail, 0); /* FIXME is there a better way to notify that, * we have got data */ usbd_device_event_irq(udc_device, DEVICE_FUNCTION_PRIVATE, 0); } } urb = endpoint->rcv_urb; }