예제 #1
0
/*
    Function: USBD_Unhalt
        Clears the Halt feature on the given endpoint.

    Parameters:
        eptnum - Endpoint number.
*/
void USBD_Unhalt(unsigned char eptnum)
{
    Endpoint *endpoint = &(endpoints[eptnum]);

    // Check if the endpoint is enabled
    if (endpoint->state != UDP_ENDPOINT_DISABLED) {

        TRACE_INFO( "Unhalt%d ", eptnum);

        // Return endpoint to Idle state
        endpoint->state = UDP_ENDPOINT_IDLE;

        // Clear FORCESTALL flag
        CLEAR_CSR(eptnum, AT91C_UDP_FORCESTALL);

        // Reset Endpoint Fifos, beware this is a 2 steps operation
        AT91C_BASE_UDP->UDP_RSTEP |= 1 << eptnum;
        AT91C_BASE_UDP->UDP_RSTEP &= ~(1 << eptnum);
    }
}
예제 #2
0
파일: usb_svc.cpp 프로젝트: bratkov/tmos
//-----------------------------------------------------------------------------
void usb_svc_unhalt_hook(USB_DRV_INFO drv_info, HANDLE hnd)
{
	USB_DRIVER_DATA* drv_data = drv_info->drv_data;
	Udp* pUDP = drv_info->hw_base;
	unsigned char eptnum = hnd->src.as_int;
    Endpoint *endpoint = &drv_data->endpoints[eptnum];

	TRACE_USB(" Unhalt(%d)", eptnum);

    if (endpoint->state == ENDPOINT_STATE_HALTED)
    {
        // Return endpoint to Idle state
        endpoint->state = ENDPOINT_STATE_IDLE;

        // Clear FORCESTALL flag
        CLEAR_CSR(&pUDP->UDP_CSR[eptnum], UDP_CSR_FORCESTALL);

        // Reset Endpoint Fifos, beware this is a 2 steps operation
        pUDP->UDP_RST_EP |= 1 << eptnum;
        pUDP->UDP_RST_EP &= ~(1 << eptnum);
    }
}
예제 #3
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( "]");
}