示例#1
0
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;
}
示例#2
0
文件: usbdev_core.c 项目: checko/F4OS
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);
    }
}
示例#3
0
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;
}
示例#4
0
文件: usbdev_core.c 项目: checko/F4OS
/* 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;
}