⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 udp.c

📁 This software package contains the USB framework core developped by ATMEL, as well as two HID driv
💻 C
📖 第 1 页 / 共 4 页
字号:
    for (bEndpoint = 0; bEndpoint < pUsb->dNumEndpoints; bEndpoint++) {

        pEndpoint = USB_GetEndpoint(pUsb, bEndpoint);

        // Reset endpoint transfer descriptor
        pEndpoint->pData = 0;
        pEndpoint->dBytesRemaining = 0;
        pEndpoint->dBytesTransferred = 0;
        pEndpoint->dBytesBuffered = 0;
        pEndpoint->fCallback = 0;
        pEndpoint->pArgument = 0;

        // Configure endpoint characteristics
        pEndpoint->dFlag = AT91C_UDP_RX_DATA_BK0;
        pEndpoint->dState = endpointStateDisabled;
    }
}

//------------------------------------------------------------------------------
// \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;
    }
}

//------------------------------------------------------------------------------
// \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);
            }
        }
    }
    // SETUP packet received
    if (ISSET(dStatus, AT91C_UDP_RXSETUP)) {

        TRACE_DEBUG_L("Stp ");

        // If a transfer was pending, complete it
        // Handle 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 ((pEndpoint->dState == endpointStateWrite)
            || (pEndpoint->dState == endpointStateRead)) {

            UDP_EndOfTransfer(pEndpoint, USB_STATUS_SUCCESS);
        }

        // Copy the setup packet in S_usb
        UDP_GetSetup(pUsb);

        // Set the DIR bit before clearing RXSETUP in Control IN sequence
        if (USB_GetSetup(pUsb)->bmRequestType & 0x80) {

            UDP_SETEPFLAGS(pUsb, bEndpoint, AT91C_UDP_DIR);
        }

        UDP_CLEAREPFLAGS(pUsb, bEndpoint, AT91C_UDP_RXSETUP);

        // Forward the request to the upper layer
        USB_NewRequestCallback(pUsb);
    }
    // STALL sent
    if (ISSET(dStatus, AT91C_UDP_STALLSENT)) {

        TRACE_WARNING("Sta ");

        // Acknowledge the stall flag
        UDP_CLEAREPFLAGS(pUsb, bEndpoint, AT91C_UDP_STALLSENT);

        // If the endpoint is not halted, clear the stall condition
        if (pEndpoint->dState != endpointStateHalted) {

            UDP_CLEAREPFLAGS(pUsb, bEndpoint, AT91C_UDP_FORCESTALL);
        }
    }
}

//------------------------------------------------------------------------------
//      Exported functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// \brief  Configure an endpoint with the provided endpoint descriptor
// \param  pUsb    Pointer to a S_usb instance
// \param  pEpDesc Pointer to the endpoint descriptor
// \return true if the endpoint is now configured, false otherwise
// \see    S_usb_endpoint_descriptor
// \see    S_usb
//------------------------------------------------------------------------------
bool UDP_ConfigureEndpoint(const S_usb                     *pUsb,
                           const S_usb_endpoint_descriptor *pEpDesc)
{
    AT91PS_UDP     pInterface = UDP_GetDriverInterface(pUsb);
    S_usb_endpoint *pEndpoint;
    unsigned char  bEndpoint;
    unsigned char  bType;
    bool           isINEndpoint;
    unsigned int   dFlags;

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

        bEndpoint = 0;
        bType = ENDPOINT_TYPE_CONTROL;
        isINEndpoint = false;
    }
    else {

        bEndpoint = (unsigned char) (pEpDesc->bEndpointAddress & 0x7);
        bType = (unsigned char) (pEpDesc->bmAttributes & 0x3);

        if (ISSET(pEpDesc->bEndpointAddress, 1 << 7)) {

            isINEndpoint = true;
        }
        else {

            isINEndpoint = false;
        }
    }

    // Get pointer on endpoint
    pEndpoint = USB_GetEndpoint(pUsb, bEndpoint);
    if (pEndpoint == 0) {

        return false;
    }

    // Configure wMaxPacketSize
    if (pEpDesc != 0) {

        pEndpoint->wMaxPacketSize = pEpDesc->wMaxPacketSize;
    }
    else {

        pEndpoint->wMaxPacketSize = USB_ENDPOINT0_MAXPACKETSIZE;
    }

    // Abort the current transfer is the endpoint was configured and in
    // Write or Read state
    if ((pEndpoint->dState == endpointStateRead)
        || (pEndpoint->dState == endpointStateWrite)) {

        UDP_EndOfTransfer(pEndpoint, USB_STATUS_RESET);
    }

    // Enter IDLE state
    pEndpoint->dState = endpointStateIdle;

    // Reset Endpoint Fifos
    SET(pInterface->UDP_RSTEP, 1 << bEndpoint);
    CLEAR(pInterface->UDP_RSTEP, 1 << bEndpoint);

    // Configure endpoint
    dFlags = AT91C_UDP_EPEDS;
    SET(dFlags, bType << UDP_EPTYPE_INDEX);

    if (isINEndpoint) {

        SET(dFlags, 1 << UDP_EPDIR_INDEX);
    }

    if (bType == ENDPOINT_TYPE_CONTROL) {

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

    TRACE_DEBUG_L("CfgEpt%d ", bEndpoint);

    UDP_SETEPFLAGS(pUsb, bEndpoint, dFlags);

    return true;
}

//------------------------------------------------------------------------------
// \brief  UDP interrupt handler
//
//         Manages device resume, suspend, end of bus reset. Forwards endpoint
//         interrupts to the appropriate handler.
// \param  pUsb Pointer to a S_usb instance
//------------------------------------------------------------------------------
void UDP_Handler(const S_usb *pUsb)
{
    AT91PS_UDP          pInterface = UDP_GetDriverInterface(pUsb);
    unsigned int        dStatus;
    unsigned char       bEndpoint;

    if ( (!ISSET(USB_GetState(pUsb), USB_STATE_SUSPENDED))
       && (ISSET(USB_GetState(pUsb), USB_STATE_POWERED))){

        LED_TOGGLE(LED_USB);
    }

    TRACE_DEBUG_L("Hlr ");

    // Get interrupts status
    dStatus = pInterface->UDP_ISR & pInterface->UDP_IMR & ISR_MASK;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -