Beispiel #1
0
/*
    Function: UDP_DisableEndpoints
        Disables all endpoints of the UDP peripheral except Control endpoint 0.
*/
static void UDP_DisableEndpoints()
{
    unsigned char eptnum;

    // Disable each endpoint, terminating any pending transfer
    for (eptnum = 1; eptnum < BOARD_USB_NUMENDPOINTS; eptnum++) {

        UDP_EndOfTransfer(eptnum, USBD_STATUS_ABORTED);
        endpoints[eptnum].state = UDP_ENDPOINT_DISABLED;
    }
}
Beispiel #2
0
//------------------------------------------------------------------------------
// \brief  Disable all endpoints (except control endpoint 0), aborting current
//         transfers if necessary.
// \param  pUsb Pointer to a S_usb instance
//------------------------------------------------------------------------------
static void UDP_DisableEndpoints(const S_usb *pUsb)
{
    S_usb_endpoint *pEndpoint;
    unsigned char bEndpoint;

    // For each endpoint, if it is enabled, disable it and invoke the callback
    // Control endpoint 0 is not disabled
    for (bEndpoint = 1; bEndpoint < pUsb->dNumEndpoints; bEndpoint++) {

        pEndpoint = USB_GetEndpoint(pUsb, bEndpoint);
        UDP_EndOfTransfer(pEndpoint, USB_STATUS_RESET);
        pEndpoint->dState = endpointStateDisabled;
    }
}
Beispiel #3
0
/*
    Function: USBD_ConfigureEndpoint
        Configures an endpoint according to its Endpoint Descriptor.

    Parameters:
        descriptor - Pointer to an Endpoint descriptor.
*/
void USBD_ConfigureEndpoint(const USBEndpointDescriptor *descriptor)
{
    Endpoint *endpoint;
    unsigned char eptnum;
    unsigned char type;
    unsigned char direction;

    // NULL descriptor -> Control endpoint 0
    if (descriptor == 0) {

        eptnum = 0;
        endpoint = &(endpoints[eptnum]);
        type = USBEndpointDescriptor_CONTROL;
        direction = 0;
        endpoint->size = BOARD_USB_ENDPOINTS_MAXPACKETSIZE(0);
    }
    else {

        eptnum = USBEndpointDescriptor_GetNumber(descriptor);
        endpoint = &(endpoints[eptnum]);
        type = USBEndpointDescriptor_GetType(descriptor);
        direction = USBEndpointDescriptor_GetDirection(descriptor);
        endpoint->size = USBEndpointDescriptor_GetMaxPacketSize(descriptor);
    }

    // Abort the current transfer is the endpoint was configured and in
    // Write or Read state
    if ((endpoint->state == UDP_ENDPOINT_RECEIVING)
        || (endpoint->state == UDP_ENDPOINT_SENDING)) {

        UDP_EndOfTransfer(eptnum, USBD_STATUS_RESET);
    }
    endpoint->state = UDP_ENDPOINT_IDLE;

    // Reset Endpoint Fifos
    AT91C_BASE_UDP->UDP_RSTEP |= (1 << eptnum);
    AT91C_BASE_UDP->UDP_RSTEP &= ~(1 << eptnum);

    // Configure endpoint
    SET_CSR(eptnum, AT91C_UDP_EPEDS | (type << 8) | (direction << 10));
    if (type == USBEndpointDescriptor_CONTROL) {

        AT91C_BASE_UDP->UDP_IER = (1 << eptnum);
    }

    TRACE_INFO( "\r\n# CfgEpt%d ", eptnum);
}
Beispiel #4
0
/*
    Function: USBD_Halt
        Sets the HALT feature on the given endpoint (if not already in this
        state).

    Parameters:
        eptnum - Endpoint number.
*/
void USBD_Halt(unsigned char eptnum)
{
    Endpoint *endpoint = &(endpoints[eptnum]);
    
    // Check that endpoint is enabled and not already in Halt state
    if ((endpoint->state != UDP_ENDPOINT_DISABLED)
        && (endpoint->state != UDP_ENDPOINT_HALTED)) {

        TRACE_INFO( "Halt%d ", eptnum);

        // Abort the current transfer if necessary
        UDP_EndOfTransfer(eptnum, USBD_STATUS_ABORTED);

        // Put endpoint into Halt state
        SET_CSR(eptnum, AT91C_UDP_FORCESTALL);
        endpoint->state = UDP_ENDPOINT_HALTED;

        // Enable the endpoint interrupt
        AT91C_BASE_UDP->UDP_IER = 1 << eptnum;
    }
}
Beispiel #5
0
/*
    Function: UDP_EndpointHandler
        Endpoint interrupt handler. Manages IN, OUT & SETUP transaction, as well
        as the STALL condition.

    Parameters:
        eptnum - Number of the endpoint to handle interrupt for.
*/
static void UDP_EndpointHandler(unsigned char eptnum)
{
    Endpoint *endpoint = &(endpoints[eptnum]);
    Transfer *transfer = &(endpoint->transfer);
    unsigned int status = AT91C_BASE_UDP->UDP_CSR[eptnum];

    //TRACE_INFO( "Ept%d ", eptnum);
    //TRACE_INFO( "[");
    // Handle interrupts
    
    // IN packet sent
    if ((status & AT91C_UDP_TXCOMP) != 0) {

        //TRACE_INFO( "Wr ");

        // Check that endpoint was in Sending state
        if (endpoint->state == UDP_ENDPOINT_SENDING) {

            // End of transfer ?
            if (UDP_IsTransferFinished(eptnum)) {

               // TRACE_INFO( "%d ", transfer->buffered);

                transfer->transferred += transfer->buffered;
                transfer->buffered = 0;

                // Disable interrupt if this is not a control endpoint
                if ((status & AT91C_UDP_EPTYPE) != AT91C_UDP_EPTYPE_CTRL) {

                    AT91C_BASE_UDP->UDP_IDR = 1 << eptnum;
                }

                UDP_EndOfTransfer(eptnum, USBD_STATUS_SUCCESS);
                CLEAR_CSR(eptnum, AT91C_UDP_TXCOMP);
            }
            else {

                // Transfer remaining data
              //TRACE_INFO( "PQ:%d ", endpoint->size);

                transfer->transferred += endpoint->size;
                transfer->buffered -= endpoint->size;

                // Send next packet
                if (BOARD_USB_ENDPOINTS_BANKS(eptnum) == 1) {

                    // No double buffering
                    UDP_WritePayload(eptnum);
                    SET_CSR(eptnum, AT91C_UDP_TXPKTRDY);
                    CLEAR_CSR(eptnum, AT91C_UDP_TXCOMP);
                }
                else {
                    // Double buffering
                    SET_CSR(eptnum, AT91C_UDP_TXPKTRDY);
                    CLEAR_CSR(eptnum, AT91C_UDP_TXCOMP);
                    UDP_WritePayload(eptnum);
                }
            }
        }
        else {
            // Acknowledge interrupt
            CLEAR_CSR(eptnum, AT91C_UDP_TXCOMP);
        }
    }

    // OUT packet received
    if ((status & UDP_RXDATA) != 0) {

        //TRACE_INFO( "Rd ");

        // Check that the endpoint is in Receiving state
        if (endpoint->state != UDP_ENDPOINT_RECEIVING) {

            // Check if an ACK has been received on a Control endpoint
            if (((status & AT91C_UDP_EPTYPE) == AT91C_UDP_EPTYPE_CTRL)
                && ((status & AT91C_UDP_RXBYTECNT) == 0)) {

                // Acknowledge the data and finish the current transfer
                ///TRACE_INFO( "[%d]Ack ",eptnum);
                UDP_ClearRxFlag(eptnum);
                UDP_EndOfTransfer(eptnum, USBD_STATUS_SUCCESS);
            }
            // Check if the data has been STALLed
            else if ((status & AT91C_UDP_FORCESTALL) != 0) {

                // Discard STALLed data
                TRACE_INFO( "[%d]Disc ",eptnum);
                UDP_ClearRxFlag(eptnum);
            }
            // NAK the data
            else {

                TRACE_INFO( "[%d]Nak ",eptnum);
                AT91C_BASE_UDP->UDP_IDR = 1 << eptnum;
            }
        }
        // Endpoint is in Read state
        else {

            // Retrieve data and store it into the current transfer buffer
            unsigned short size = (unsigned short) (status >> 16);
            //TRACE_INFO( "-[%d]-", size);
            //TRACE_INFO( "Rec ");
            UDP_ReadPayload(eptnum, size);
            UDP_ClearRxFlag(eptnum);

            // Check if the transfer is finished
            if ((transfer->remaining == 0) || (size < endpoint->size)) {

                // Disable interrupt if this is not a control endpoint
                if ((status & AT91C_UDP_EPTYPE) != AT91C_UDP_EPTYPE_CTRL) {

                    AT91C_BASE_UDP->UDP_IDR = 1 << eptnum;
                }

                UDP_EndOfTransfer(eptnum, USBD_STATUS_SUCCESS);
            }
        }
    }

    // SETUP packet received
    if ((status & AT91C_UDP_RXSETUP) != 0) {

        //TRACE_INFO( "Stp ");

        // If a transfer was pending, complete it
        // Handles the case where during the status phase of a control write
        // transfer, the host receives the device ZLP and ack it, but the ack
        // is not received by the device
        if ((endpoint->state == UDP_ENDPOINT_RECEIVING)
            || (endpoint->state == UDP_ENDPOINT_SENDING)) {

            UDP_EndOfTransfer(eptnum, USBD_STATUS_SUCCESS);
        }
        USBGenericRequest request;
        UDP_ReadRequest(&request);

        // Set the DIR bit before clearing RXSETUP in Control IN sequence
        if (USBGenericRequest_GetDirection(&request) == USBGenericRequest_IN) {

            SET_CSR(eptnum, AT91C_UDP_DIR);
        }
        CLEAR_CSR(eptnum, AT91C_UDP_RXSETUP);

        // Forward the request to the upper layer
        USBDCallbacks_RequestReceived(&request);//------------------------------------
    }

    // STALL sent
    if ((status & AT91C_UDP_STALLSENT) != 0) {

        TRACE_INFO( "STA ");

        // If the endpoint is not halted, clear the STALL condition
        CLEAR_CSR(eptnum, AT91C_UDP_STALLSENT);
        if (endpoint->state != UDP_ENDPOINT_HALTED) {

            CLEAR_CSR(eptnum, AT91C_UDP_FORCESTALL);
        }
        
    }
    //TRACE_INFO( "]");
}
Beispiel #6
0
//------------------------------------------------------------------------------
// \brief  Endpoint interrupt handler.
//
//         Handle IN/OUT transfers, received SETUP packets and STALLing
// \param  pUsb      Pointer to a S_usb instance
// \param  bEndpoint Index of endpoint
// \see    S_usb
//------------------------------------------------------------------------------
static void UDP_EndpointHandler(const S_usb *pUsb, unsigned char bEndpoint)
{
    S_usb_endpoint *pEndpoint = USB_GetEndpoint(pUsb, bEndpoint);
    AT91PS_UDP pInterface = UDP_GetDriverInterface(pUsb);
    unsigned int dStatus = pInterface->UDP_CSR[bEndpoint];

    TRACE_DEBUG_L("Ept%d ", bEndpoint);

    // Handle interrupts
    // IN packet sent
    if (ISSET(dStatus, AT91C_UDP_TXCOMP)) {

        TRACE_DEBUG_L("Wr ");

        // Check that endpoint was in Write state
        if (pEndpoint->dState == endpointStateWrite) {

            // End of transfer ?
            if ((pEndpoint->dBytesBuffered < pEndpoint->wMaxPacketSize)
                ||
                (!ISCLEARED(dStatus, AT91C_UDP_EPTYPE)
                 && (pEndpoint->dBytesRemaining == 0)
                 && (pEndpoint->dBytesBuffered == pEndpoint->wMaxPacketSize))) {

                TRACE_DEBUG_L("%d ", pEndpoint->dBytesBuffered);

                pEndpoint->dBytesTransferred += pEndpoint->dBytesBuffered;
                pEndpoint->dBytesBuffered = 0;

                // Disable interrupt if this is not a control endpoint
                if (!ISCLEARED(dStatus, AT91C_UDP_EPTYPE)) {

                    SET(pInterface->UDP_IDR, 1 << bEndpoint);
                }

                UDP_EndOfTransfer(pEndpoint, USB_STATUS_SUCCESS);
            }
            else {

                // Transfer remaining data
                TRACE_DEBUG_L("%d ", pEndpoint->wMaxPacketSize);

                pEndpoint->dBytesTransferred += pEndpoint->wMaxPacketSize;
                pEndpoint->dBytesBuffered -= pEndpoint->wMaxPacketSize;

                // Send next packet
                if (pEndpoint->dNumFIFO == 1) {

                    // No double buffering
                    UDP_WritePayload(pUsb, bEndpoint);
                    UDP_SETEPFLAGS(pUsb, bEndpoint, AT91C_UDP_TXPKTRDY);
                }
                else {

                    // Double buffering
                    UDP_SETEPFLAGS(pUsb, bEndpoint, AT91C_UDP_TXPKTRDY);
                    UDP_WritePayload(pUsb, bEndpoint);
                }
            }
        }

        // Acknowledge interrupt
        UDP_CLEAREPFLAGS(pUsb, bEndpoint, AT91C_UDP_TXCOMP);
    }
    // OUT packet received
    if (ISSET(dStatus, AT91C_UDP_RX_DATA_BK0)
        || ISSET(dStatus, AT91C_UDP_RX_DATA_BK1)) {

        TRACE_DEBUG_L("Rd ");

        // Check that the endpoint is in Read state
        if (pEndpoint->dState != endpointStateRead) {

            // Endpoint is NOT in Read state
            if (ISCLEARED(dStatus, AT91C_UDP_EPTYPE)
                && ISCLEARED(dStatus, 0xFFFF0000)) {

                // Control endpoint, 0 bytes received
                // Acknowledge the data and finish the current transfer
                TRACE_DEBUG_L("Ack ");
                UDP_ClearRXFlag(pUsb, bEndpoint);

                UDP_EndOfTransfer(pEndpoint, USB_STATUS_SUCCESS);
            }
            else if (ISSET(dStatus, AT91C_UDP_FORCESTALL)) {

                // Non-control endpoint
                // Discard stalled data
                TRACE_DEBUG_L("Disc ");
                UDP_ClearRXFlag(pUsb, bEndpoint);
            }
            else {

                // Non-control endpoint
                // Nak data
                TRACE_DEBUG_L("Nak ");
                SET(pInterface->UDP_IDR, 1 << bEndpoint);
            }
        }
        else {

            // Endpoint is in Read state
            // Retrieve data and store it into the current transfer buffer
            unsigned short wPacketSize = (unsigned short) (dStatus >> 16);

            TRACE_DEBUG_L("%d ", wPacketSize);

            UDP_GetPayload(pUsb, bEndpoint, wPacketSize);
            UDP_ClearRXFlag(pUsb, bEndpoint);

            if ((pEndpoint->dBytesRemaining == 0)
                || (wPacketSize < pEndpoint->wMaxPacketSize)) {

                // Disable interrupt if this is not a control endpoint
                if (!ISCLEARED(dStatus, AT91C_UDP_EPTYPE)) {

                    SET(pInterface->UDP_IDR, 1 << bEndpoint);
                }

                UDP_EndOfTransfer(pEndpoint, USB_STATUS_SUCCESS);
            }
        }
    }