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

📄 xllp_udc.c

📁 优龙pxa270平台试验程序
💻 C
📖 第 1 页 / 共 5 页
字号:
          
  Return Value: 
    XLLP_STATUS_T - error code if failed, zero if success

*******************************************************************************/
void XllpUdcControlProcessIdle (P_XLLP_UDC_T pUdcHandle,
                                P_XLLP_UINT32_T pControlXferStatus)
{
    XLLP_UDC_USB_SETUP_DATA_T reqData;
    P_XLLP_UINT32_T rxBuffP = (P_XLLP_UINT32_T)&reqData;
    P_XLLP_UINT32_T pTxBuffEp0;
    XLLP_UINT32_T tempDataLen;
    XLLP_UINT32_T tempReqType;
    XLLP_INT32_T packetLength;
    volatile P_XLLP_UDC_REGISTERS_T pRegs = (P_XLLP_UDC_REGISTERS_T)pUdcHandle->pRegsBase;    

    // Determine if UDCCS0.OPC and UDCCS0.SA both are set.
    // It means that OUT packet in the Endpoint 0 buffer identifying SETUP transaction,
    if (pRegs->UDCCSR[ENDPOINT_0] & (XLLP_UDC_UDCCSR0_OPC | XLLP_UDC_UDCCSR0_SA))
    {
        // Read data from Endpoint 0 data buffer
        // The data packet of the setup stage is always 8 bytes 
        XllpUdcReadDwordFifo (&pRegs->UDCDR[ENDPOINT_0], rxBuffP, 8);
        
        // Parse the data that is in the buffer
        // Identify RequestType
        tempReqType = (reqData.bmRequestType & XLLP_UDC_REQ_TYPE_MASK) >> 5;
        if (tempReqType == STANDARD_REQ)
        {        
            // Identify Standard Request type
            switch (reqData.bRequest)
            {
                case GET_DESCRIPTOR:
                    // Get the number of data bytes in the data stage that follows
                    // This is the maximum number, and the device can return this 
                    // number of bytes or fewer.
                    pUdcHandle->controlXfer.dataLengthEp0 = reqData.wLength;

                    // Identify type of descriptor
                    switch (reqData.wValue >> 8)
                    {
                        case DEVICE_DESCRIPTOR:
                            // Read the length of the device descriptor    
                            // and compare with number of bytes in the data stage
                            tempDataLen = UsbDeviceDesc[0];
                            if (pUdcHandle->controlXfer.dataLengthEp0 > tempDataLen)
                              pUdcHandle->controlXfer.dataLengthEp0 = tempDataLen;
                            // Initialize the Tx buffer pointer with the device descriptor's address
                            pUdcHandle->controlXfer.pTxBuffEp0 = (P_XLLP_UINT32_T)UsbDeviceDesc;
                            break;
                        case CONFIG_DESCRIPTOR:
                            // Read the total length of the configuration descriptor    
                            // and compare with number of bytes in the data stage
                            tempDataLen = XLLP_UDC_CONFIG_TOTAL;
                            if (pUdcHandle->controlXfer.dataLengthEp0 > tempDataLen)
                              pUdcHandle->controlXfer.dataLengthEp0 = tempDataLen;
                            // Initialize the Tx buffer pointer with the config. descriptor's address
                            pUdcHandle->controlXfer.pTxBuffEp0 = (P_XLLP_UINT32_T)UsbConfigDesc;
                            break;
                        case STRING_DESCRIPTOR:
                            if ( XllpUdcGetStringDescriptor(reqData.wValue,
                                                            (P_XLLP_UINT8_T*)&pUdcHandle->controlXfer.pTxBuffEp0,
                                                            &tempDataLen))
                            {
                                if (pUdcHandle->controlXfer.dataLengthEp0 > tempDataLen)
                                    pUdcHandle->controlXfer.dataLengthEp0 = tempDataLen;
                            }
                            else 
                            {
                                // error found
                            }
                    }                    
                    // Preload EP0 FIFO to get ready for IN transaction that follows.
                    // Write up to sixteen bytes to the Endpoint 0 data buffer
                    packetLength = pUdcHandle->controlXfer.dataLengthEp0;
                    pTxBuffEp0 = pUdcHandle->controlXfer.pTxBuffEp0;
                    // Write to the Endpoint 0 data buffer
                    if (packetLength >= MPS_CNTRL_16)
                    {
                        XllpUdcWriteDwordFifo (&pRegs->UDCDR[ENDPOINT_0], pTxBuffEp0, MPS_CNTRL_16);
                        pTxBuffEp0 = (P_XLLP_UINT32_T)((XLLP_UINT32_T)pTxBuffEp0 + MPS_CNTRL_16);
                        pUdcHandle->controlXfer.dataLengthEp0 -= MPS_CNTRL_16;
                        // Update pointer to the transmit buffer
                        pUdcHandle->controlXfer.pTxBuffEp0 = pTxBuffEp0;
                    }
                    else 
                    {
                        XllpUdcWriteDwordFifo (&pRegs->UDCDR[ENDPOINT_0], pTxBuffEp0, packetLength);
                        pUdcHandle->controlXfer.dataLengthEp0 -= packetLength;
                    }
                    
                    // Set UDCCSR0.IPR = 1 if the packet smaller than 16 bytes has been loaded
                    // to the Endpoint 0 FIFO
                    if (packetLength < MPS_CNTRL_16)
                    {
                        pRegs->UDCCSR[ENDPOINT_0] = XLLP_UDC_UDCCSR0_IPR;
                        // Set the status of the Endpoint 0 state machine to XFER data
                        pUdcHandle->controlXfer.statusEp0 = EP0_END_XFER_STATE;
                    }
                    else
                    {
                        // Set the status of the Endpoint 0 state machine to IN data
                        pUdcHandle->controlXfer.statusEp0 = EP0_IN_DATA_STATE;
                    }
                    break;
                    
                 case SET_DESCRIPTOR:
                    // Save descriptor index (lower byte of wValue)
                    pUdcHandle->controlXfer.descIndexEp0 = reqData.wValue & 0xff;
                    // Save descriptor type (upper byte of wValue)
                    pUdcHandle->controlXfer.descTypeEp0 = reqData.wValue >> 8;
                    // Get the number of data bytes in the data stage that follows
                    pUdcHandle->controlXfer.dataLengthEp0 = reqData.wLength;
                    // Initialize Rx buffer pointer with address where the descriptor will be stored
                    pUdcHandle->controlXfer.pRxBuffEp0 = pUdcHandle->controlXfer.outDataEp0;
                    // Set UDCCSR0.IPR in case of premature STATUS IN stage
                    pRegs->UDCCSR[ENDPOINT_0] = XLLP_UDC_UDCCSR0_IPR;
                    // Set the status of the Endpoint 0 state machine to OUT data
                    pUdcHandle->controlXfer.statusEp0 = EP0_OUT_DATA_STATE;
            } 
        }
    
        // Process Vendor Request
        else if (tempReqType == VENDOR_REQ)
        {                       
            // Get ready to process the data that would be sent in the data stage
            pUdcHandle->vendorReq.recipient = reqData.bmRequestType & XLLP_USB_REQ_RECIPIENT_MASK;
            pUdcHandle->vendorReq.vendorReqType = reqData.bRequest;
            pUdcHandle->vendorReq.vendorReqEndpointNum = reqData.wValue;
            pUdcHandle->vendorReq.vendorReqComplete = XLLP_TRUE;
            // Get the number of data bytes in the data stage that follows
            pUdcHandle->controlXfer.dataLengthEp0 = reqData.wLength;
            // Set UDCCSR0.IPR in case of premature STATUS IN stage
            pRegs->UDCCSR[ENDPOINT_0] = XLLP_UDC_UDCCSR0_IPR;
            // Set the status of the Endpoint 0 state machine to OUT data
            if ( /* direction */ !(reqData.bmRequestType & 0x80) )
            {
                // 0: Host to device
                pUdcHandle->controlXfer.statusEp0 = EP0_OUT_DATA_STATE;
            }
            else 
            {
                XllpUdcProcessVendorRequest (pUdcHandle);
                pUdcHandle->vendorReq.vendorReqComplete = XLLP_FALSE;
            }
        }
        else if (tempReqType == CLASS_REQ)
        {}  
    }

    // Clear UDCCS0.OPC and UDCCS0.SA
    pRegs->UDCCSR[ENDPOINT_0] = XLLP_UDC_UDCCSR0_OPC | XLLP_UDC_UDCCSR0_SA;
    
    *pControlXferStatus = 0;        
}

/******************************************************************************

  Function Name: 
    XllpUdcControlProcessOutData

  Description:
    This function services the data OUT state of Endpoint 0 state machine.
    
  Global Register Modified: 
    None. 

  Input Arguments:
    P_XLLP_UDC_T pUdcHandle - a pointer to the UDC's handle

  Output Arguments:
    P_XLLP_UINT32_T pControlXferStatus - returns the value that tells the Endpoint 0 
                                         state machine to switch to the Idle state.
          
  Return Value: 
    None.

*******************************************************************************/

void XllpUdcControlProcessOutData (P_XLLP_UDC_T pUdcHandle,
                                   P_XLLP_UINT32_T pControlXferStatus)
{
    volatile P_XLLP_UDC_REGISTERS_T pRegs = (P_XLLP_UDC_REGISTERS_T)pUdcHandle->pRegsBase;    
    XLLP_INT32_T packetLength;

    // Check UDCCS0.OPC and UDCCS0.SA
    if (pRegs->UDCCSR[ENDPOINT_0] & (XLLP_UDC_UDCCSR0_OPC | XLLP_UDC_UDCCSR0_SA) ==
            (XLLP_UDC_UDCCSR0_OPC | XLLP_UDC_UDCCSR0_SA) )
    {    
        // UDCCSR0.OPC and UDCCSR0.SA both are set,
        // there is another SETUP transaction has been sent by the host 
        // Initialize Endpoint 0 state machine to the Idle state
        pUdcHandle->controlXfer.statusEp0 = EP0_IDLE_STATE;
        *pControlXferStatus = EP0_JUMP_TO_IDLE;
    }

    else if ((pRegs->UDCCSR[ENDPOINT_0] &     
             (XLLP_UDC_UDCCSR0_OPC | XLLP_UDC_UDCCSR0_SA)) == 0)
    {
        // UDCCSR0.OPC = 0 and UDCCSR0.SA = 0 this is premature STATUS stage of 
        // the SETUP transaction.
        // Initialize Endpoint 0 state machine to the Idle state
        pUdcHandle->controlXfer.statusEp0 = EP0_IDLE_STATE;
    }

    else if ((pRegs->UDCCSR[ENDPOINT_0] &     
             (XLLP_UDC_UDCCSR0_OPC | XLLP_UDC_UDCCSR0_SA)) == XLLP_UDC_UDCCSR0_OPC)
    {
        // Read data from the Endpoint 0 FIFO
        if (pRegs->UDCCSR[ENDPOINT_0] & XLLP_UDC_UDCCSR0_RNE)
        {
            packetLength = pRegs->UDCBCR[ENDPOINT_0] & XLLP_UDC_UDCBCR_BC_MASK;
            XllpUdcReadDwordFifo (&pRegs->UDCDR[ENDPOINT_0], pUdcHandle->controlXfer.pRxBuffEp0, packetLength);
            pUdcHandle->controlXfer.dataLengthEp0 -= packetLength;
            *pControlXferStatus = 0;        
        }   
        // Clear UDCCS0.OPC
        pRegs->UDCCSR[ENDPOINT_0] = XLLP_UDC_UDCCSR0_OPC;
        // Set UDCCS0.IPR in case of premature STATUS IN stage
        pRegs->UDCCSR[ENDPOINT_0] = XLLP_UDC_UDCCSR0_IPR;
    }
}

/******************************************************************************

  Function Name: 
    XllpUdcControlProcessInData

  Description:
    This function services the data IN state of Endpoint 0 state machine.
    
  Global Register Modified: 
    None. 

  Input Arguments:
    P_XLLP_UDC_T pUdcHandle - a pointer to the UDC's handle

  Output Arguments:
    P_XLLP_UINT32_T pControlXferStatus - returns the value that tells the Endpoint 0 
                                         state machine to switch to the Idle state.
          
  Return Value: 
    None.

*******************************************************************************/

void XllpUdcControlProcessInData (P_XLLP_UDC_T pUdcHandle,
                                  P_XLLP_UINT32_T pControlXferStatus) 
{
    volatile P_XLLP_UDC_REGISTERS_T pRegs = (P_XLLP_UDC_REGISTERS_T)pUdcHandle->pRegsBase;    
    XLLP_INT32_T packetLength;

    // Check UDCCSR0.OPC and UDCCSR0.SA
    if (pRegs->UDCCSR[ENDPOINT_0] & (XLLP_UDC_UDCCSR0_OPC | XLLP_UDC_UDCCSR0_SA) ==
            (XLLP_UDC_UDCCSR0_OPC | XLLP_UDC_UDCCSR0_SA) )
    {    
        // UDCCSR0.OPC and UDCCSR0.SA both are set,
        // there is another SETUP transaction has been sent by the host 
        // Initialize Endpoint 0 state machine to the Idle state
        pUdcHandle->controlXfer.statusEp0 = EP0_IDLE_STATE;
        *pControlXferStatus = EP0_JUMP_TO_IDLE;
    }
 
    else if ((pRegs->UDCCSR[ENDPOINT_0] &
         (XLLP_UDC_UDCCSR0_OPC | XLLP_UDC_UDCCSR0_SA)) == XLLP_UDC_UDCCSR0_OPC)    
    {
        // UDCCSR0.OPC = 1 and UDCCSR0.SA = 0 this is premature STATUS stage of 
        // the SETUP transaction. Clear UDCCSR0.OPC and empty transmit FIFO
        pRegs->UDCCSR[ENDPOINT_0] = XLLP_UDC_UDCCSR0_OPC | XLLP_UDC_UDCCSR0_FTF;
        
        // Reset all state machine variables
        pUdcHandle->controlXfer.dataLengthEp0 = 0;
        pUdcHandle->controlXfer.pTxBuffEp0 = NULL;
        pUdcHandle->controlXfer.pRxBuffEp0 = NULL;
        
        // Initialize Endpoint 0 state machine to the Idle state
        pUdcHandle->controlXfer.statusEp0 = EP0_IDLE_STATE;
    }
 
    else if ((pRegs->UDCCSR[ENDPOINT_0] & (XLLP_UDC_UDCCSR0_OPC | XLLP_UDC_UDCCSR0_SA)) == 0)    
    {
        packetLength = pUdcHandle->controlXfer.dataLengthEp0;
        if ( packetLength > MPS_CNTRL_16 ) {
            packetLength = MPS_CNTRL_16;
        }
        
        XllpUdcWriteDwordFifo (&pRegs->UDCDR[ENDPOINT_0], pUdcHandle->controlXfer.pTxBuffEp0, packetLength);
        
        pUdcHandle->controlXfer.dataLengthEp0 -= packetLength;
        if ( MPS_CNTRL_16 != packetLength )
        {
            // short packet or ZLP
            
            // No more data left, force UDC to send zero lenght packet.
            // Set Endpoint 0 state machine to the End of transfer state            
            pRegs->UDCCSR[ENDPOINT_0] = XLLP_UDC_UDCCSR0_IPR;
            pUdcHandle->controlXfer.statusEp0 = EP0_END_XFER_STATE;
        }
        else 
        {
            pUdcHandle->controlXfer.pTxBuffEp0 += (MPS_CNTRL_16 >> 2);
            // It needs more data to transmit,
            // so on the next interrupt go back to the same state.
        }
        
        *pControlXferStatus = 0;        
    }
}

/******************************************************************************

  Function Name: 
    XllpUdcControlProcessEndXfer

  Description:
    This function services the Status state of Endpoint 0 state machine.
    
  Global Register Modified: 
    None. 

  Input Arguments:
    P_XLLP_UDC_T pUdcHandle - a pointer to the UDC's handle

  Output Arguments:
    P_XLLP_UINT32_T pControlXferStatus - returns the value that tells the Endpoint 0 
                                         state machine to switch to the Idle state.
          
  Return Value: 
    None.

*******************************************************************************/

void XllpUdcControlProcessEndXfer (P_XLLP_UDC_T pUdcHandle, 
                                   P_XLLP_UINT32_T pControlXferStatus)
{
    volatile P_XLLP_UDC_REGISTERS_T pRegs = (P_XLLP_UDC_REGISTERS_T)pUdcHandle->pRegsBase;    

    // Check UDCCSR0.OPC and UDCCSR0.SA
    if (pRegs->UDCCSR[ENDPOINT_0] & (XLLP_UDC_UDCCSR0_OPC | XLLP_UDC_UDCCSR0_SA) ==
            (XLLP_UDC_UDCCSR0_OPC | XLLP_UDC_UDCCSR0_SA) )
    {    
        // UDCCSR0.OPC and UDCCSR0.SA both are set,
        // there is another SETUP transaction has been sent by the host 
        // Initialize Endpoint 0 state machine to the Idle state
        pUdcHandle->controlXfer.statusEp0 = EP0_IDLE_STATE;
        *pControlXferStatus = EP0_JUMP_TO_IDLE;
    }

    else if ((pRegs->UDCCSR[ENDPOINT_0] &
         (XLLP_UDC_UDCCSR0_OPC | XLLP_UDC_UDCCSR0_SA)) == XLLP_UDC_UDCCSR0_OPC)    
    {
        // UDCCSR0.OPC = 1 and UDCCSR0.SA = 0 this is STATUS stage of 

⌨️ 快捷键说明

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