Beispiel #1
0
/**
 *  Handle the USB setup package received, should be invoked
 *  when an endpoint got a setup package as request.
 *  \param bEndpoint Endpoint number.
 *  \param pRequest  Pointer to content of request.
 */
void USBD_RequestHandler(uint8_t bEndpoint,
                         const USBGenericRequest* pRequest)
{
    if (bEndpoint != 0) {
        TRACE_WARNING("EP%d request not supported, default EP only",
                      bEndpoint);
    } else {
    	USBDCallbacks_RequestReceived(pRequest);
    }
}
Beispiel #2
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( "]");
}