static char usbdev_resource_read(void *env, int *error) { if (!usb_ready) { if (error != NULL) { *error = -1; } return 0; } if (error != NULL) { *error = 0; } while (ring_buf_empty(&ep_rx.rx)) { if (task_switching && !IPSR()) { release(&usbdev_semaphore); SVC(SVC_YIELD); acquire(&usbdev_semaphore); } } char c = (char) ep_rx.rx.buf[ep_rx.rx.start]; ep_rx.rx.start = (ep_rx.rx.start + 1) % ep_rx.rx.len; return c; }
void usbdev_data_in(struct endpoint *ep) { if (ep == NULL) { DEBUG_PRINT("Warning: Invalid endpoint in usbdev_data_in. "); return; } if (!ep->tx.buf) { return; } DEBUG_PRINT("Writing FIFO %d: ", ep->num); /* Write until buffer empty */ int written = 0; int space = *USB_FS_DTXFSTS(ep->num); while (written < space && !ring_buf_empty(&ep->tx)) { union uint8_uint32 data; data.uint32 = 0; for (int i = 0; i < 4; i++) { if (!ring_buf_empty(&ep->tx)) { data.uint8[i] = ep->tx.buf[ep->tx.start]; ep->tx.start = (ep->tx.start + 1) % ep->tx.len; } else { data.uint8[i] = 0; } } DEBUG_PRINT("0x%x ", data.uint32); *USB_FS_DFIFO_EP(ep->num) = data.uint32; written++; } /* Only disable interrupt once all data has been written */ if (ring_buf_empty(&ep->tx)) { *USB_FS_DIEPEMPMSK &= ~(1 << ep->num); } }
static char usbdev_resource_read(void *env, int *error) { if (!usb_ready) { if (error != NULL) { *error = -1; } return 0; } if (error != NULL) { *error = 0; } while (ring_buf_empty(&ep_rx.rx)) { yield_if_possible(); } char c = (char) ep_rx.rx.buf[ep_rx.rx.start]; ep_rx.rx.start = (ep_rx.rx.start + 1) % ep_rx.rx.len; return c; }
/* Returns bytes written, negative on error */ int usbdev_write(struct endpoint *ep, uint8_t *packet, int size) { if (ep == NULL) { DEBUG_PRINT("Warning: Invalid endpoint in usbdev_write. "); return -1; } if (ep->num != 0 && !usb_ready) { return -1; } if (ep->tx.buf == NULL) { DEBUG_PRINT("Warning: Endpoint has no tx buffer in usbdev_write. "); return -1; } /* Wait until current buffer is empty */ while (!ring_buf_empty(&ep->tx)) { yield_if_possible(); } int filled_buffer = 0; int written = 0; /* Copy to ring buffer */ while (size > 0 && !ring_buf_full(&ep->tx)) { ep->tx.buf[ep->tx.end] = *packet++; size--; written++; ep->tx.end = (ep->tx.end + 1) % ep->tx.len; } if (ring_buf_full(&ep->tx)) { filled_buffer = 1; } uint8_t packets = written % ep->mpsize ? written/ep->mpsize + 1 : written/ep->mpsize; if (!packets) { packets = 1; } int count = 500; /* Setup endpoint for transmit */ if (ep->num == 0) { /* Wait for ep to disable */ while (*USB_FS_DIEPCTL0 & USB_FS_DIEPCTL0_EPENA && count > 0) { count--; } /* Abort timed out transfer */ if (count <= 0) { ep->request_disable = 1; *USB_FS_DIEPCTL0 |= USB_FS_DIEPCTL0_SNAK; *USB_FS_DIEPMSK |= USB_FS_DIEPMSK_INEPNEM | USB_FS_DIEPMSK_EPDM; /* Wait for endpoint to disable */ while(ep->request_disable); *USB_FS_DIEPMSK &= ~(USB_FS_DIEPMSK_INEPNEM | USB_FS_DIEPMSK_EPDM); } *USB_FS_DIEPTSIZ0 = USB_FS_DIEPTSIZ0_PKTCNT(packets) | USB_FS_DIEPTSIZ0_XFRSIZ(written); *USB_FS_DIEPCTL0 |= USB_FS_DIEPCTL0_CNAK | USB_FS_DIEPCTL0_EPENA; } else { /* Wait for ep to disable */ while (*USB_FS_DIEPCTL(ep->num) & USB_FS_DIEPCTLx_EPENA && count > 0) { count--; } /* Abort timed out transfer */ if (count <= 0) { ep->request_disable = 1; *USB_FS_DIEPCTL(ep->num) |= USB_FS_DIEPCTLx_SNAK; *USB_FS_DIEPMSK |= USB_FS_DIEPMSK_INEPNEM | USB_FS_DIEPMSK_EPDM; /* Wait for endpoint to disable */ while(ep->request_disable); *USB_FS_DIEPMSK &= ~(USB_FS_DIEPMSK_INEPNEM | USB_FS_DIEPMSK_EPDM); } *USB_FS_DIEPTSIZ(ep->num) = USB_FS_DIEPTSIZx_PKTCNT(packets) | USB_FS_DIEPTSIZx_XFRSIZ(written); *USB_FS_DIEPCTL(ep->num) |= USB_FS_DIEPCTLx_CNAK | USB_FS_DIEPCTLx_EPENA; } /* Enable TX FIFO empty interrupt */ *USB_FS_DIEPEMPMSK |= (1 << ep->num); /* Filled buffer, call recursively until packet finishes */ if (filled_buffer && size) { int ret = usbdev_write(ep, packet, size); if (ret >= 0) { written += ret; } else { written = ret; } } return written; }