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

📄 bvd_udc_hw.c

📁 自制PDA系列之usb驱动(处理器PXA270)
💻 C
📖 第 1 页 / 共 5 页
字号:
		UDCTrace( pHWHead, 0xbcc5, UDC_CSR0(pHWHead) );
		UDCTrace( pHWHead, 0xbcc5, UDC_ISR0(pHWHead) );
		UDCTrace( pHWHead, 0xbcc5, UDC_ISR1(pHWHead) );
		UDC_STATE( pHWHead ) = WAIT_FOR_OUT_STATUS;
	}
	else
	if( !nXferCount )
	{
		UDCTrace( pHWHead, 0xbcc6, UDC_CSR0(pHWHead) );
		UDCTrace( pHWHead, 0xbcc6, UDC_ISR0(pHWHead) );
		UDCTrace( pHWHead, 0xbcc6, UDC_ISR1(pHWHead) );
		UDC_STATE( pHWHead ) = WAIT_FOR_OUT_STATUS;
	}


}
/*----------------------------------------------------------------------------
 *	ParseSetup
 *
 *	Parse through the setup command and perform actions based upon the
 *	requests.  The caller has already read the data from the FIFO and placed
 *	into the serial info structure.
 *----------------------------------------------------------------------------*/
BOOL ParseSetup( PSER_INFO pHWHead, PDWORD pModemStatus )
{
	BOOL bErr = FALSE;
	PUCHAR p;
	WORD wLen, wTotLen = 0;
	static int count = 0;
    //DWORD udc_cr, udc_csrA, udc_csrB;

    DEBUGMSG( ZONE_USB,
		(TEXT("bmRequest: %02x bRequest: %02x wValue: %04x wIndex: %04x wLength: %04x\n"), 
		pHWHead->dReq.bmRequest,
		pHWHead->dReq.bRequest,
		pHWHead->dReq.wValue,
		pHWHead->dReq.wIndex,
		pHWHead->dReq.wLength));
	

	UDCTrace( pHWHead, UDCT_PARSE_SETUP, (pHWHead->dReq.bmRequest |((DWORD) pHWHead->dReq.bRequest) << 8 | ((DWORD) pHWHead->dReq.wValue) << 16 ));

	/*
	 * Decode and execute the command. We support two sets of commands, vendor
	 * specific (modem control) and chapter 9 standard commands.
	 */
	if (pHWHead->dReq.bmRequest & 0x60) 
    { 
        // vendor or class command
        DEBUGMSG( ZONE_USB, (TEXT("Vendor/Class Command !!\n")));
		
        if ( SET_CONTROL_LINE_STATE == pHWHead->dReq.bRequest ) 
        {
	   /* 
		* Modem Control command
		* 
		* Host is notifying us of control line state.
		* wValue contains bitmask
		* 0 - DTR
		* 1 - RTS
		*/
            DEBUGMSG( ZONE_USB, (TEXT("SET_CONTROL_LINE_STATE %4.4X\r\n"),
				pHWHead->dReq.wValue));
			
            if (pHWHead->dReq.wValue & 0x01)
				*pModemStatus |= (MS_DSR_ON|MS_RLSD_ON);  // DTR active, set DSR/RLSD
            else
				*pModemStatus &= ~(MS_DSR_ON|MS_RLSD_ON); // DTR clear, clr DSR/RLSD
			
            if (pHWHead->dReq.wValue & 0x02) 
				*pModemStatus |= MS_CTS_ON;   // RTS active, set CTS
            else
				*pModemStatus &= ~MS_CTS_ON;  // RTS clear, clear CTS

			UDCTrace( pHWHead, UDCT_VENDOR_MODEM_CMD, pHWHead->dReq.bRequest);

			// Set IPR bit for a EP0 No Data Vendor command.
			// This tells UDC to send ZLP on IN Status.
			// Software does not see the IN Status.

			UDC_CSR0_MWRITE( UDC_CSR0(pHWHead), XLLP_UDC_UDCCSR0_IPR );
			UDC_STATE( pHWHead ) = WAIT_FOR_IN_STATUS;
        }
        else 
        {
		    /*
		     * Unknown vendor/class request
			 */
            DEBUGMSG( ZONE_ERROR|ZONE_USB,
				(TEXT("Unknown vendor/class request %2.2X\r\n"),
				pHWHead->dReq.bRequest));
        }
		
		/* 
		 * Vendor or Class command is complete
		 */
		return FALSE;
    }
	
    /* 
	 * Standard chapter 9 commands
	 */
    switch (pHWHead->dReq.bRequest) {
		
	case GET_DESCRIPTOR:
		
		switch ((BYTE)(pHWHead->dReq.wValue>>8)) 
		{
		case DEVICE:
			DEBUGMSG( ZONE_INIT|ZONE_USB,
				(TEXT("GET_DESCRIPTOR:DEVICE 0x%X, 0x%X\r\n"),
				uStd[0],
				pHWHead->dReq.wLength));
			
			p = (PUCHAR)uStd;
			wLen = (BYTE)min(uStd[0],pHWHead->dReq.wLength);
			wTotLen = uStd[0];
			break;
			
		case CONFIGURATION:
			DEBUGMSG( ZONE_INIT|ZONE_USB,
				(TEXT("GET_DESCRIPTOR:CONFIGURATION\r\n")));

			p = (PUCHAR)&uStd[iCONF];
			wLen = (BYTE)min(CFGLEN,pHWHead->dReq.wLength);
			wTotLen = CFGLEN;
			break;
			
		case STRING:
			DEBUGMSG( ZONE_INIT|ZONE_USB,
				(TEXT("GET_DESCRIPTOR:STRING\r\n")));
			
			UsbRequestGetStringDescriptor((XLLP_UINT16_T)pHWHead->dReq.wValue,
										  (P_XLLP_UINT8_T*)&p, 
										  (P_XLLP_UINT8_T) &wTotLen);

			wLen = (BYTE)min(wTotLen,pHWHead->dReq.wLength);
			break;
			
		default:
			DEBUGMSG( ZONE_INIT|ZONE_USB|ZONE_ERROR,
				(TEXT("GET_DESCRIPTOR:Unknown %d\r\n"),
				(pHWHead->dReq.wValue>>8) ));
			
			p = NULL;
			wLen = 0;
			wTotLen = 0;
			break;		
			
		}

		// Is there data to send?
		if( wLen ) 
		{
			// Setup the pointers in the HW structure and then
			// call to have the data transfer initiated.
			pHWHead->pXmitData = p;
			pHWHead->nXmitIndex = 0;
			pHWHead->nXmitLength = (int) wLen;
			pHWHead->nXmitReq = (int) pHWHead->dReq.wLength;

			count = (int) pHWHead->dReq.wLength;

            // Send IN Data
		    XmitEP0Data( pHWHead );

		}
		break;
		
	case SET_CONFIG:

		DEBUGMSG( ZONE_INIT | ZONE_USB,
					(TEXT("Set Configuration: Configuration = %d\r\n"), pHWHead->dReq.wValue ));
		// Save the configuration index into our state structure.
		pHWHead->dConfIdx = (BYTE)pHWHead->dReq.wValue;
		
		UDC_STATE( pHWHead ) = WAIT_FOR_IN_STATUS;

		//Set SMAC
	    UDCCR_SMAC_SET( UDC_CR(pHWHead) ); 

		break;

	case SET_ADDRESS:
        //Not passed to software
		DEBUGMSG( ZONE_INIT | ZONE_USB,
					(TEXT("Set Address:  Address = %d\r\n"), pHWHead->dReq.wValue ));
		//RETAILMSG( 1,
		//			(TEXT("Set Address:  Address = %d\r\n"), pHWHead->dReq.wValue ));
		pHWHead->dAddress = (BYTE) pHWHead->dReq.wValue;
		break;

	case GET_STATUS:
		//Not passed to software
        DEBUGMSG( ZONE_INIT|ZONE_USB, (TEXT("GET_STATUS\r\n")));
		//NKDbgPrintfW(TEXT("GET_STATUS\r\n"));
        break;

	case SET_DESCRIPTOR:
        DEBUGMSG( ZONE_ERROR|ZONE_USB, (TEXT("SET_DESCRIPTOR\r\n")));
		//NKDbgPrintfW(TEXT("SET_DESCRIPTOR\r\n"));
        break;
	
	case GET_INTERFACE:
		//Not passed to software
        DEBUGMSG( ZONE_ERROR|ZONE_USB, (TEXT("GET_INTERFACE\r\n")));
		//NKDbgPrintfW(TEXT("GET_INTERFACE\r\n"));
        break;
	
	case GET_CONFIG:
		//Not passed to software
        DEBUGMSG( ZONE_ERROR|ZONE_USB, (TEXT("GET_CONFIGURATION\r\n")));
		//NKDbgPrintfW(TEXT("GET_CONFIGURATION\r\n"));
        break;

    case SET_INTERFACE:
        DEBUGMSG( ZONE_INIT|ZONE_USB, (TEXT("SET_INTERFACE : %d,%d\r\n"),
                                       pHWHead->dReq.wIndex, pHWHead->dReq.wValue));
		//NKDbgPrintfW(TEXT("SET_INTERFACE : %d,%d\r\n"),
        //                               pHWHead->dReq.wIndex, pHWHead->dReq.wValue);
        
		//Cotulla UDC stalls on a non-zero alternate setting!
        
		pHWHead->dInterface = (BYTE) pHWHead->dReq.wIndex;
        pHWHead->dSetting = (BYTE) pHWHead->dReq.wValue;
		UDC_STATE( pHWHead ) = WAIT_FOR_IN_STATUS;
        break;

    case CLEAR_FEATURE:
      //Not passed to software
      DEBUGMSG( ZONE_INIT|ZONE_USB, (TEXT("CLEAR_FEATURE\r\n")));
	  //NKDbgPrintfW(TEXT("CLEAR_FEATURE\r\n"));

    /*
     * Request to the endpoint (Clear Halt)
     */
     if (pHWHead->dReq.bmRequest == 0x02)          
      { 
        /*
         * Switch on endpoint number (wIndex)
         */
        switch (pHWHead->dReq.wIndex & 0xF) 
        {
        case 0:

           /*
            * Control endpoint. Not suggested.
            */
            break;

        case 1:
            /*
             * IN endpoint. Clear SST and FST to reset DATA0/DATA1.
             */
            //UDCCS1_FST_CLR (pHWHead->pUDCRegs->udccs1);
            //UDCCS1_MWRITE (pHWHead->pUDCRegs->udccs1, USB_UDCCS1_SST);

            break;

        case 2:
            /*
             * OUT endpoint. Clear SST and FST to reset DATA0/DATA1.
             */
            //UDCCS2_FST_CLR (pHWHead->pUDCRegs->udccs2);
            //UDCCS2_MWRITE (pHWHead->pUDCRegs->udccs2, USB_UDCCS2_SST);

            break;
        }
      }

      break;

    case SET_FEATURE:
      //Not passed to software
	  //NKDbgPrintfW(TEXT("SET_FEATURE\r\n"));
      DEBUGMSG( ZONE_INIT|ZONE_USB,
		(TEXT("SET_FEATURE %d\r\n"),
		 pHWHead->dReq.bmRequest));

      if (pHWHead->dReq.bmRequest == 0x02)
      {
	    switch (pHWHead->dReq.wIndex & 15) 
        {
	        case 0:
            /* 
             * Control endpoint. Not suggested.
             */
            break;

	        case 1:
                /* 
                 * IN endpoint. Set FST to force stall condition
                 */
                //UDCCS1_MWRITE(pHWHead->pUDCRegs->udccs1, USB_UDCCS1_FST);
	            break;

            case 2:
                /*
                 * OUT endpoint. Set FST to force stall condition
                 */
                //UDCCS2_MWRITE(pHWHead->pUDCRegs->udccs2, USB_UDCCS2_FST);
	            break;
	    }
      }

      break;

	default:
		DEBUGMSG( ZONE_ERROR|ZONE_USB,
			(TEXT("Unhandled Command : %d\r\n"),
			pHWHead->dReq.bRequest));

		//NKDbgPrintfW(TEXT("Unhandled Command : %d\r\n"), pHWHead->dReq.bRequest);

		// Unknown command received.
		bErr = TRUE;
		break;

	}

	return bErr;
}

/*----------------------------------------------------------------------------
 *	ProcessEP0Setup
 *
 *	Process a setup packet for Endpoint 0.  
 *----------------------------------------------------------------------------*/
void ProcessEP0Setup( PSER_INFO pHWHead, PDWORD pdwModemStatus )
{
	// Make sure that everything is correct to read the setup packet from
	// the FIFO's
	DEBUGMSG( ZONE_USB,(TEXT("ProcessEP0Setup: UDCCS0=%X\r\n"), UDC_CSR0( pHWHead )));


     if((UDC_CSR0( pHWHead ) & (XLLP_UDC_UDCCSR0_SA | XLLP_UDC_UDCCSR0_OPR | XLLP_UDC_UDCCSR0_RNE)) ==
		(XLLP_UDC_UDCCSR0_SA | XLLP_UDC_UDCCSR0_OPR | XLLP_UDC_UDCCSR0_RNE)) {

		UDCTrace( pHWHead, UDCT_SETUP, UDC_CSR0( pHWHead ));

		// Setup packet is available.  Read it from the FIFO's
		if (getCommand(pHWHead, (void*)&pHWHead->dReq) != 0) {
			// Failed to properly get the data from the FIFO's.
			// Force a STALL condition.
            UDC_CSR0_MWRITE( UDC_CSR0(pHWHead), XLLP_UDC_UDCCSR0_FST );

//	        UDC_CSR0_FST_SET (pHWHead->pUDCRegs->UDC_CSR0);
			ASSERT(0);
		}
	 }
	 //Workaround for 0x81 condition 
	 else if ((UDC_CSR0( pHWHead ) & (XLLP_UDC_UDCCSR0_SA | XLLP_UDC_UDCCSR0_OPR | XLLP_UDC_UDCCSR0_RNE)) ==
		(XLLP_UDC_UDCCSR0_SA | XLLP_UDC_UDCCSR0_OPR)) {

		UDCTrace( pHWHead, UDCT_SETUP, UDC_CSR0( pHWHead ));

		//NKDbgPrintfW(TEXT("!!! STATUS = 81 handled\r\n"));
		// Setup packet is available.  Read it from the FIFO.

		if (getCommandEightBytes(pHWHead, (void*)&pHWHead->dReq) != 0) 
		{
			// Failed to properly get the data from the FIFO's.
			// Force a STALL condition.
            UDC_CSR0_MWRITE( UDC_CSR0(pHWHead), XLLP_UDC_UDCCSR0_FST );
			ASSERT(0);
		}
	 }
	  
     //Log clearing the OPR and SA bits.
	 UDCTrace( pHWHead, UDCT_UDCCS0, (XLLP_UDC_UDCCSR0_OPR | XLLP_UDC_UDCCSR0_SA));

	 // The next two steps should be done atomically to guarantee 
	 // that IR0 bit reflects correct status of another OUT/IN pkt!
     // Clear the OPR and SA bits.
	 UDC_CSR0_MWRITE( UDC_CSR0(pHWHead), (XLLP_UDC_UDCCSR0_OPR | XLLP_UDC_UDCCSR0_SA));
	 // This clears the IR0_0 interrupt due to OPR.
// bpc stuff: this was already done at entry to ServiceEP0:     UDC_ISR0_CLEAR_ENDPOINT_INTR( UDC_ISR0(pHWHead), XLLP_UDC_UDCISR0_IR0_0);
//     UDC_ISR0_CLEAR_ENDPOINT_INTR( UDC_ISR0(pHWHead), XLLP_UDC_UDCISR0_IR0_0);

	 // Process the setup command.  This routine will parse
	 // the setup command and possibly call the xmit EP0 routine
	 // to start the transfer of the descriptor back to the host.
	 // The state will be updated by the routine.

	 if( ParseSetup( pHWHead, pdwModemStatus )) {
			// Parsing of the setup failed.  Force a STALL and
			// then go back to IDLE state.
            UDC_CSR0_MWRITE( UDC_CSR0(pHWHead), XLLP_UDC_UDCCSR0_FST );
			ASSERT(0);
	 }
}	

/*----------------------------------------------------------------------------
 *	ProcessEP0OutStatus
 *
 *	Called to handle the condition where the state machine was waiting for 
 *	a OUT status.
 *----------------------------------------------------------------------------*/
void ProcessEP0OutStatus( PSER_INFO pHWHead )
{
	// Make sure the OPR bit is set and SA and RNE are not set.
	if((UDC_CSR0( pHWHead ) & (XLLP_UDC_UDCCSR0_OPR | XLLP_UDC_UDCCSR0_SA)) == XLLP_UDC_UDCCSR0_OPR ) {
		// Out status was received.  Turn off OPR and move to wait for setup
		UDCTrace( pHWHead, UDCT_STATUS_OUT, UDC_CSR0( pHWHead ));

		// The next two steps should be done atomically to guarantee 
		// that IR0 bit reflects correct status of another OUT/IN pkt!
		// Clear the OPR bit.
		UDC_CSR0_MWRITE( UDC_CSR0(pHWHead), XLLP_UDC_UDCCSR0_OPR );
		// Clear the IR0_0 interrupt due to OPR.
     	UDC_ISR0_CLEAR_ENDPOINT_INTR( UDC_ISR0(pHWHead), XLLP_UDC_UDCISR0_IR0_0);

		UDC_STATE( pHWHead ) = WAIT_FOR_SETUP;
	} 
	else if (0 == UDC_CSR0( pHWHead ))
	{
		// IN Data has been sent out. 
		// STATUS Stage has not been received yet.
		   UDCTrace( pHWHead, UDCT_STATUS_OUT_MISSED, UDC_CSR0( pHWHead ));
		// NKDbgPrintfW(TEXT("IN Data sent out : %X\r\n"), UDC_CSR0( pHWHead ));
	}
	else
	{
	   //RETAILMSG( 1, (TEXT("????EP0 Out Status:  UDC_CSR0= %x\r\n"), UDC_CSR0( pHWHead ) ));
	   //We should not be here.
	   //ASSERT(0);
		UDC_STATE( pHWHead ) = WAIT_FOR_SETUP;
	}
}

/*----------------------------------------------------------------------------
 *	ProcessEP0InStatus
 *
 *	Called to handle condition where the state machine is waiting for an
 *	in status.
 *----------------------------------------------------------------------------*/
void ProcessEP0InStatus( PSER_INFO pHWHead )
{
	//ASSERT( 0 );
	//For Standard Chapter 9 EP0 No data commands,
	//we should not be here as UDC handles them automatically.
	UDC_CSR0_MWRITE( UDC_CSR0(pHWHead), XLLP_UDC_UDCCSR0_IPR );
	UDC_STATE( pHWHead ) = WAIT_FOR_SETUP;
	UDCTrace( pHWHead, UDCT_UDCCS0, XLLP_UDC_UDCCSR0_IPR );
}
/*----------------------------------------------------------------------------

⌨️ 快捷键说明

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