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

📄 udp.c

📁 This software package contains the USB framework core developped by ATMEL, as well as two HID driv
💻 C
📖 第 1 页 / 共 4 页
字号:
/* ----------------------------------------------------------------------------
 *         ATMEL Microcontroller Software Support  -  ROUSSET  -
 * ----------------------------------------------------------------------------
 * Copyright (c) 2006, Atmel Corporation

 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * - Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the disclaiimer below.
 *
 * - Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the disclaimer below in the documentation and/or
 * other materials provided with the distribution.
 *
 * Atmel's name may not be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
 * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * ----------------------------------------------------------------------------
 */

/*
$Id: udp.c 196 2006-10-30 09:56:17Z jjoannic $
*/

//------------------------------------------------------------------------------
//      Includes
//------------------------------------------------------------------------------

#include "common.h"
#include "device.h"
#include "board.h"
#include "trace.h"
#include "usb.h"

#ifdef UDP

#define UDP_STATE_SHOULD_RECONNECT      0x10000000
#define UDP_EPTYPE_INDEX                8
#define UDP_EPDIR_INDEX                 10

#define ISR_MASK                      0x00003FFF

//------------------------------------------------------------------------------
//      Structures
//------------------------------------------------------------------------------

// \brief  Endpoint states
typedef enum {

    endpointStateDisabled,
    endpointStateIdle,
    endpointStateWrite,
    endpointStateRead,
    endpointStateHalted

} EndpointState_t;

//------------------------------------------------------------------------------
//      Macros
//------------------------------------------------------------------------------

// \brief  Clear flags in the UDP_CSR register and waits for synchronization
// \param  pUsb      Pointer to a S_usb instance
// \param  bEndpoint Index of endpoint
// \param  dFlags    Flags to clear
#define UDP_CLEAREPFLAGS(pUsb, bEndpoint, dFlags) { \
    while (!ISCLEARED(UDP_GetDriverInterface(pUsb)->UDP_CSR[bEndpoint], dFlags)) \
        CLEAR(UDP_GetDriverInterface(pUsb)->UDP_CSR[bEndpoint], dFlags); \
}

// \brief  Set flags in the UDP_CSR register and waits for synchronization
// \param  pUsb      Pointer to a S_usb instance
// \param  bEndpoint Index of endpoint
// \param  dFlags    Flags to clear
#define UDP_SETEPFLAGS(pUsb, bEndpoint, dFlags) { \
    while (ISCLEARED(UDP_GetDriverInterface(pUsb)->UDP_CSR[bEndpoint], dFlags)) \
        SET(UDP_GetDriverInterface(pUsb)->UDP_CSR[bEndpoint], dFlags); \
}

//------------------------------------------------------------------------------
//      Internal Functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// \brief  Returns a pointer to the UDP controller interface used by an USB
//         driver
//
//         The pointer is cast to the correct type (AT91PS_UDP).
// \param  pUsb Pointer to a S_usb instance
// \return Pointer to the USB controller interface
// \see    S_usb
//------------------------------------------------------------------------------
extern __inline AT91PS_UDP UDP_GetDriverInterface(const S_usb *pUsb)
{
    return (AT91PS_UDP) pUsb->pDriver->pInterface;
}

//------------------------------------------------------------------------------
// \brief  Enables the peripheral clock of the USB controller associated with
//         the specified USB driver
// \param  pUsb Pointer to a S_usb instance
// \see    S_usb
//------------------------------------------------------------------------------
extern __inline void UDP_EnableMCK(const S_usb *pUsb)
{
    AT91C_BASE_PMC->PMC_PCER = 1 << USB_GetDriverID(pUsb);
}

//------------------------------------------------------------------------------
// \brief  Disables the peripheral clock of the USB controller associated with
//         the specified USB driver
// \param  pUsb Pointer to a S_usb instance
// \see    S_usb
//------------------------------------------------------------------------------
extern __inline void UDP_DisableMCK(const S_usb *pUsb)
{
    AT91C_BASE_PMC->PMC_PCDR = 1 << USB_GetDriverID(pUsb);
}

//------------------------------------------------------------------------------
// \brief  Enables the 48MHz clock of the USB controller associated with
//         the specified USB driver
// \param  pUsb Pointer to a S_usb instance
// \see    S_usb
//------------------------------------------------------------------------------
extern __inline void UDP_EnableUDPCK(const S_usb *pUsb)
{
    SET(AT91C_BASE_PMC->PMC_SCER, USB_GetDriverPMC(pUsb));
}

//------------------------------------------------------------------------------
// \brief  Disables the 48MHz clock of the USB controller associated with
//         the specified USB driver
// \param  pUsb Pointer to a S_usb instance
// \see    S_usb
//------------------------------------------------------------------------------
extern __inline void UDP_DisableUDPCK(const S_usb *pUsb)
{
    SET(AT91C_BASE_PMC->PMC_SCDR, USB_GetDriverPMC(pUsb));
}

//------------------------------------------------------------------------------
// \brief  Enables the transceiver of the USB controller associated with
//         the specified USB driver
// \param  pUsb Pointer to a S_usb instance
// \see    S_usb
//------------------------------------------------------------------------------
extern __inline void UDP_EnableTransceiver(const S_usb *pUsb)
{
    CLEAR(UDP_GetDriverInterface(pUsb)->UDP_TXVC, AT91C_UDP_TXVDIS);
}

//------------------------------------------------------------------------------
// \brief  Disables the transceiver of the USB controller associated with
//         the specified USB driver
// \param  pUsb Pointer to a S_usb instance
// \see    S_usb
//------------------------------------------------------------------------------
extern __inline void UDP_DisableTransceiver(const S_usb *pUsb)
{
    SET(UDP_GetDriverInterface(pUsb)->UDP_TXVC, AT91C_UDP_TXVDIS);
}

//------------------------------------------------------------------------------
// \brief  Invokes the callback associated with a finished transfer on an
//         endpoint
// \param  pEndpoint Pointer to a S_usb_endpoint instance
// \param  bStatus   Status code returned by the transfer operation
// \see    Status codes
// \see    S_usb_endpoint
//------------------------------------------------------------------------------
extern __inline void UDP_EndOfTransfer(S_usb_endpoint *pEndpoint,
                                       char bStatus)
{
    if ((pEndpoint->dState == endpointStateWrite)
        || (pEndpoint->dState == endpointStateRead)) {

        TRACE_DEBUG_L("EoT ");

        // Endpoint returns in Idle state
        pEndpoint->dState = endpointStateIdle;

        // Invoke callback is present
        if (pEndpoint->fCallback != 0) {

            pEndpoint->fCallback((unsigned int) pEndpoint->pArgument,
                                 (unsigned int) bStatus,
                                 pEndpoint->dBytesTransferred,
                                 pEndpoint->dBytesRemaining
                                 + pEndpoint->dBytesBuffered);
        }
    }
}

//------------------------------------------------------------------------------
// \brief  Clears the correct RX flag in an endpoint status register
// \param  pUsb      Pointer to a S_usb instance
// \param  bEndpoint Index of endpoint
// \see    S_usb_endpoint
// \see    S_usb
//------------------------------------------------------------------------------
static void UDP_ClearRXFlag(const S_usb * pUsb,
                            unsigned char bEndpoint)
{
    S_usb_endpoint *pEndpoint = USB_GetEndpoint(pUsb, bEndpoint);

    // Clear flag
    UDP_CLEAREPFLAGS(pUsb, bEndpoint, pEndpoint->dFlag);

    // Swap banks
    if (pEndpoint->dFlag == AT91C_UDP_RX_DATA_BK0) {

        if (pEndpoint->dNumFIFO > 1) {

            // Swap bank if in dual-fifo mode
            pEndpoint->dFlag = AT91C_UDP_RX_DATA_BK1;
        }
    }
    else {

        pEndpoint->dFlag = AT91C_UDP_RX_DATA_BK0;
    }
}

//------------------------------------------------------------------------------
// \brief  Transfers a data payload from the current tranfer buffer to the
//         endpoint FIFO.
// \param  pUsb      Pointer to a S_usb instance
// \param  bEndpoint Index of endpoint
// \return Number of bytes transferred
// \see    S_usb
//------------------------------------------------------------------------------
static unsigned int UDP_WritePayload(const S_usb * pUsb,
                                     unsigned char bEndpoint)
{
    AT91PS_UDP     pInterface = UDP_GetDriverInterface(pUsb);
    S_usb_endpoint *pEndpoint = USB_GetEndpoint(pUsb, bEndpoint);
    unsigned int   dBytes;
    unsigned int   dCtr;

    // Get the number of bytes to send
    dBytes = min(pEndpoint->wMaxPacketSize, pEndpoint->dBytesRemaining);

    // Transfer one packet in the FIFO buffer
    for (dCtr = 0; dCtr < dBytes; dCtr++) {

        pInterface->UDP_FDR[bEndpoint] = *(pEndpoint->pData);
        pEndpoint->pData++;
    }

    pEndpoint->dBytesBuffered += dBytes;
    pEndpoint->dBytesRemaining -= dBytes;

    return dBytes;
}

//------------------------------------------------------------------------------
// \brief  Transfers a data payload from an endpoint FIFO to the current
//         transfer buffer.
// \param  pUsb        Pointer to a S_usb instance
// \param  bEndpoint   Index of endpoint
// \param  wPacketSize Size of received data packet
// \return Number of bytes transferred
// \see    S_usb
//------------------------------------------------------------------------------
static unsigned int UDP_GetPayload(const S_usb * pUsb,
                                   unsigned char bEndpoint,
                                   unsigned short wPacketSize)
{
    AT91PS_UDP     pInterface = UDP_GetDriverInterface(pUsb);
    S_usb_endpoint *pEndpoint = USB_GetEndpoint(pUsb, bEndpoint);
    unsigned int   dBytes;
    unsigned int   dCtr;

    // Get number of bytes to retrieve
    dBytes = min(pEndpoint->dBytesRemaining, wPacketSize);

    // Retrieve packet
    for (dCtr = 0; dCtr < dBytes; dCtr++) {

        *pEndpoint->pData = (char) pInterface->UDP_FDR[bEndpoint];
        pEndpoint->pData++;
    }

    pEndpoint->dBytesRemaining -= dBytes;
    pEndpoint->dBytesTransferred += dBytes;
    pEndpoint->dBytesBuffered += wPacketSize - dBytes;

    return dBytes;
}

//------------------------------------------------------------------------------
// \brief  Transfers a received SETUP packet from endpoint 0 FIFO to the
//         S_usb_request structure of an USB driver
// \param  pUsb Pointer to a S_usb instance
// \see    S_usb
//------------------------------------------------------------------------------
static void UDP_GetSetup(S_usb const *pUsb)
{
    char *pData = (char *) USB_GetSetup(pUsb);
    AT91PS_UDP pInterface = UDP_GetDriverInterface(pUsb);
    unsigned int dCtr;

    // Copy packet
    for (dCtr = 0; dCtr < 8; dCtr++) {

        *pData = (char) pInterface->UDP_FDR[0];
        pData++;
    }
}

//------------------------------------------------------------------------------
// \brief  This function reset all endpoint transfer descriptors
// \param  pUsb Pointer to a S_usb instance
// \see    S_usb
//------------------------------------------------------------------------------
static void UDP_ResetEndpoints(const S_usb *pUsb)
{
    S_usb_endpoint *pEndpoint;
    unsigned char bEndpoint;

    // Reset the transfer descriptor of every endpoint

⌨️ 快捷键说明

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