/** * 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); } }
/* 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( "]"); }