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

📄 sc2440_usb_ser.c

📁 wince 下的bsp测试wince_bspSMDK2440_L35T32.rar
💻 C
📖 第 1 页 / 共 3 页
字号:
	@doc OEM
	@func VOID | SerClearRTS | This routine clears RTS.
 
	@rdesc None.
**************************************************************************/
static
VOID SerClearRTS( PVOID   pHead )		// @parm PVOID returned by HWinit.
{
	DEBUGMSG(1, (TEXT("SerClearRTS, 0x%X\r\n"), pHead));

	// We don't support RTS emulation.
}

/*************************************************************************
	@doc OEM
	@func VOID | SerSetRTS | This routine sets RTS.

	@rdesc None.
**************************************************************************/
static
VOID SerSetRTS( PVOID   pHead )			// @parm PVOID returned by HWinit.
{
	DEBUGMSG(1, (TEXT("SerSetRTS, 0x%X\r\n"), pHead));

	// We don't support RTS emulation.
}

/*************************************************************************
	@doc OEM
	@func BOOL | SerEnableIR | This routine enables ir.
			Not exported to users, only to driver.
	
	@rdesc Returns TRUE if successful, FALSEotherwise.
**************************************************************************/
static
BOOL SerEnableIR( PVOID   pHead,		// @parm PVOID returned by Serinit.
				  ULONG   BaudRate )	// @parm PVOID returned by HWinit.
{
	PSER_INFO pHWHead = (PSER_INFO)pHead;

	DEBUGMSG(1, (TEXT("SerEnableIR, 0x%X\r\n"), pHead));

	// We don't support an IR mode, so fail.
	return (FALSE);
}

/*************************************************************************
	@doc OEM
	@func BOOL | SerDisableIR | This routine disable the ir.
			Not exported to users, only to driver.
 
	@rdesc Returns TRUE if successful, FALSEotherwise.
**************************************************************************/
static
BOOL SerDisableIR( PVOID   pHead )	// @parm PVOID returned by Serinit. 
{
	PSER_INFO pHWHead = (PSER_INFO)pHead;

	DEBUGMSG(1, (TEXT("SerDisableIR, 0x%X\r\n"), pHead));

	// We don't support an IR mode.  But don't fail, in case
	// someone calls this redundantly to ensure that we are
	// in wired mode, which is what we support.
	return (TRUE);
}

/*************************************************************************
	@doc OEM
	@func VOID | SerClearBreak | This routine clears break.
 
	@rdesc None.
*************************************************************************/ 
static
VOID SerClearBreak( PVOID   pHead )		// @parm PVOID returned by HWinit.
{
	DEBUGMSG(1, (TEXT("SerClearBreak, 0x%X\r\n"), pHead));

	// We don't have a concept of break over USB serial
}

/*************************************************************************
	@doc OEM
	@func VOID | SerSetBreak | This routine sets break.

	@rdesc None.
*************************************************************************/
static
VOID SerSetBreak( PVOID   pHead )		// @parm PVOID returned by HWinit.
{
	DEBUGMSG(1, (TEXT("SerSetBreak, 0x%X\r\n"), pHead));

	// We don't have a concept of break over USB serial
}

/*************************************************************************
	@doc OEM
	@func	BOOL | SerXmitComChar | Transmit a char immediately
 
	@rdesc	TRUE if succesful
*************************************************************************/
static
BOOL SerXmitComChar( PVOID   pHead,     // @parm PVOID returned by HWInit.
		     UCHAR   ComChar )  // @parm Character to transmit. 
{
	PSER_INFO pHWHead = (PSER_INFO)pHead;
    
	DEBUGMSG(1, (TEXT("+SerXmitComChar 0x%X\r\n"), pHead));

	// Get critical section, then transmit when buffer empties
	DEBUGMSG(1, (TEXT("XmitComChar wait for CritSec %x.\r\n"),
					&(pHWHead->TransmitCritSec)));

	EnterCriticalSection(&(pHWHead->TransmitCritSec));

	DEBUGMSG(1, (TEXT("XmitComChar got CritSec %x.\r\n"),
					&(pHWHead->TransmitCritSec)));
	try
    {

		// TODO - We need to wait for the current transmit to finish and
		// then sneak this data in ahead of whatever else is queued.
#ifdef TODO
		while( TRUE )  // We know THR will eventually empty
		{
			// Write the character if we can
			ReadLSR( pHWHead );
			if( pHWHead->LSR & SERIAL_LSR_THRE ) 
			{
				OUTB(pHWHead, pData, ComChar);
				DEBUGMSG(1, (TEXT("XmitComChar wrote x%X\r\n"), ComChar));
				break;
			}

			// If we couldn't write the data yet, then wait for a
			// TXINTR to come in and try it again.
            
			// Enable xmit intr.
			OUTB(pHWHead, pIER, IER_NORMAL_INTS | SERIAL_IER_THR);
			// Wait until the txintr has signalled.
			DEBUGMSG(1, (TEXT("XmitComChar WaitIntr x%X\r\n"),
							pHWHead->FlushDone));
			WaitForSingleObject(pHWHead->FlushDone, (ULONG)1000);
		}
#else
		DEBUGMSG (0, (TEXT("!!! SerXmitComChar 0x%X not implemented\r\n"),
		 				 pHead));
#endif        
	}
	except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
		EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) 
	{
		// Just exit
	}
    
	LeaveCriticalSection(&(pHWHead->TransmitCritSec));

	DEBUGMSG(1, (TEXT("XmitComChar released CritSec %x.\r\n"),
					&(pHWHead->TransmitCritSec)));
    
	DEBUGMSG(1, (TEXT("-SerXmitComChar 0x%X\r\n"), pHead));
    
	return TRUE;
}
        

/*************************************************************************
	@doc OEM
	@func	ULONG | SerGetStatus | This structure is called by the MDD
				to retrieve the contents of a COMSTAT structure.

	@rdesc	The return is a ULONG, representing success (0) or failure (-1).
*************************************************************************/
static
ULONG SerGetStatus( PVOID		pHead,	// @parm PVOID returned by HWInit.
					LPCOMSTAT	lpStat )// Pointer to LPCOMMSTAT to hold status.
{
	PSER_INFO	pHWHead	 = (PSER_INFO)pHead;
	ULONG		RetVal	 = pHWHead->CommErrors;
    
	DEBUGMSG(1, (TEXT("++SerGetStatus 0x%X\r\n"), pHead));

	pHWHead->CommErrors = 0; // Clear old errors each time

	// We don't emulate any of this, so always return a fixed result.
	if (lpStat) 
	{
		// TODO - Make sure we return reasonable results here.
		pHWHead->Status.fCtsHold = 0;
		pHWHead->Status.fDsrHold = 0;
		pHWHead->Status.cbInQue  = 0;
		pHWHead->Status.cbOutQue = 0;
	}
	else
		RetVal = (ULONG)-1;

	DEBUGMSG(1, (TEXT("--SerGetStatus 0x%X\r\n"), pHead));

	return RetVal;
}

/*************************************************************************
	@doc OEM
	@func ULONG | SerReset | Perform any operations associated
			with a device reset

	@rdesc	None.
*************************************************************************/
static
VOID SerReset( PVOID   pHead )	// @parm PVOID returned by HWInit.
{
	PSER_INFO pHWHead = (PSER_INFO)pHead;

	DEBUGMSG(1, (TEXT("++SerReset 0x%X\r\n"), pHead));

	memset(&pHWHead->Status, 0, sizeof(COMSTAT));

	// TODO - Is there anything special we need to do here.
    
	DEBUGMSG(1, (TEXT("--SerReset 0x%X\r\n"), pHead));
}

/*************************************************************************
	@doc OEM
	@func	VOID | SerGetModemStatus | Retrieves modem status.

	@rdesc	None.
*************************************************************************/
static
VOID SerGetModemStatus( PVOID   pHead,	       // @parm PVOID returned by HWInit.
						PULONG  pModemStatus ) // @parm PULONG passed in by user.
{
	PSER_INFO pHWHead = (PSER_INFO)pHead;
    
	DEBUGMSG(1, (TEXT("++SerGetModemStatus 0x%X\r\n"), pHead));

	*pModemStatus = pHWHead->ModemStatus;

	DEBUGMSG (0, (TEXT("--SerGetModemStatus 0x%X (stat x%X) \r\n"),
						pHead,
						*pModemStatus));
	return;
}

/*************************************************************************
	@doc OEM
	@func	VOID | SerGetCommProperties | Retrieves Comm Properties.
 
	@rdesc	None.
*************************************************************************/
static
VOID SerGetCommProperties( 
			PVOID   pHead,		// @parm PVOID returned by SerInit. 
			LPCOMMPROP  pCommProp )	// @parm Pointer to receive COMMPROP structure. 
{
	PSER_INFO pHWHead = (PSER_INFO)pHead;

	DEBUGMSG(1, (TEXT("SerGetCommProperties 0x%X\r\n"), pHead));

	*pCommProp = pHWHead->CommProp;
	return;
}

/*************************************************************************
	@doc OEM
	@func	VOID | SerPurgeComm | Purge RX and/or TX
 
	@rdesc	None.
*************************************************************************/
static
VOID SerPurgeComm( PVOID   pHead,		 // @parm PVOID returned by HWInit.
				   DWORD   fdwAction )	 // @parm Action to take. 
{
	PSER_INFO pHWHead = (PSER_INFO)pHead;
    
	DEBUGMSG(1, (TEXT("++SerPurgeComm 0x%X\r\n"), pHead));

	EnterCriticalSection(&(pHWHead->HwRegCritSec));

	if ( (fdwAction & PURGE_TXCLEAR) || (fdwAction & PURGE_TXABORT) ) 
	{
		// Abort any pending TX data.  The MDD takes care of aborting
		// data pended in the driver.  All I can do to stop an IN that
		// has already been queued is to Un-Arm this endpoint, causing
		// subsequent INs to get naked.  If the IN transfer has started, 
		// its not clear I can stop it in progress.
		// In addition to NAKing host, clearing ARM tells TxIntr that he
		// can use the buffer for the next write that comes down.

#if TODO
		ucECR = SC2440_USB_Read(pHWHead, EP1AControl);
		ucECR &= 0xFE;   // Clear the ARM bit.

		SC2440_USB_Write(pHWHead, EP1AControl, ucECR );
#endif
	}

	if ( (fdwAction & PURGE_RXCLEAR) || (fdwAction & PURGE_RXABORT) ) {
#if TODO
		// Abort any pending RX data.
		SC2440_USB_Write(pHWHead, IntStatus, 0x04 );   // Clear the EP2 interrupt
		SC2440_USB_Write(pHWHead, EP2AControl, 0x03);  // Reenable the endpoint
#endif
	}
    
	LeaveCriticalSection(&(pHWHead->HwRegCritSec));

	DEBUGMSG(1,
			(TEXT("--SerPurgeComm 0x%X\r\n"), pHead));
	return;
}

/************************************************************************
	@doc OEM
	@func	BOOL | SerSetDCB | Sets new values for DCB.  This
		routine gets a DCB from the MDD.  It must then compare
		this to the current DCB, and if any fields have changed take
		appropriate action.
 
	@rdesc	BOOL
************************************************************************/
static
BOOL SerSetDCB( PVOID   pHead,	    // @parm	PVOID returned by HWInit.
		LPDCB   lpDCB )     // @parm    Pointer to DCB structure
{
	PSER_INFO pHWHead = (PSER_INFO)pHead;
	BOOL bRet;
    
	DEBUGMSG(1, (TEXT("++SerSetDCB 0x%X\r\n"), pHead));

	bRet = TRUE;

	// If the device is open, scan for changes and do whatever
	// is needed for the changed fields.  if the device isn't
	// open yet, just save the DCB for later use by the open.
	if( pHWHead->OpenCount ) 
	{
#ifdef TODO
		// We don't really support any of this.  Ignore for now
		// Note, fparity just says whether we should check
		// receive parity.  And the 16550 won't let us NOT
		// check parity if we generate it.  So this field
		// has no effect on the hardware.
    
		if ( lpDCB->BaudRate != pHWHead->dcb.BaudRate ) 
		{
			bRet = SerSetBaudRate( pHWHead, lpDCB->BaudRate );
		}
    
		if ( bRet && (lpDCB->ByteSize != pHWHead->dcb.ByteSize )) 
		{
			bRet = SerSetByteSize( pHWHead, lpDCB->ByteSize );
		}
    
		if ( bRet && (lpDCB->Parity != pHWHead->dcb.Parity )) 
		{
			bRet = SerSetParity( pHWHead, lpDCB->Parity );
		}
    
		if ( bRet && (lpDCB->StopBits != pHWHead->dcb.StopBits )) 
		{
			bRet = SerSetStopBits( pHWHead, lpDCB->StopBits );
		}

		// Don't worry about fOutxCtsFlow.  It is a flag which
		// will be examined every time we load the TX buffer.
		// No special action required here.
#endif         
	}
    
	if (bRet) 
	{
		// Now that we have done the right thing, store this DCB
		pHWHead->dcb = *lpDCB;
	}

	DEBUGMSG(1, (TEXT("--SerSetDCB 0x%X\r\n"), pHead));

	return bRet;
}

/*************************************************************************
	@doc OEM
	@func	BOOL | SerSetCommTimeouts | Sets new values for the
		CommTimeouts structure. routine gets a DCB from the MDD.  It
		must then compare this to the current DCB, and if any fields
		have changed take appropriate action.

	@rdesc	ULONG
*************************************************************************/
static
ULONG SerSetCommTimeouts( 
	PVOID   pHead,			  // @parm	PVOID returned by HWInit.
	LPCOMMTIMEOUTS   lpCommTimeouts ) // @parm Pointer to CommTimeout structure
{
	PSER_INFO pHWHead = (PSER_INFO)pHead;
	ULONG retval      = 0;
    
	DEBUGMSG(1, (TEXT("++SerSetCommTimeout 0x%X\r\n"), pHead));

	// OK, first check for any changes and act upon them
	if( lpCommTimeouts->WriteTotalTimeoutMultiplier !=
		pHWHead->CommTimeouts.WriteTotalTimeoutMultiplier )
	{

	}
    
	// Now that we have done the right thing, store this DCB
	pHWHead->CommTimeouts = *lpCommTimeouts;

	DEBUGMSG(1, (TEXT("--SerSetCommTimeout 0x%X\r\n"), pHead));

	return retval;
}

/*************************************************************************
    @doc OEM
    @func    BOOL | SerIoctl | Device IO control routine.  
    @parm DWORD | dwOpenData | value returned from COM_Open call
    @parm DWORD | dwCode | io control code to be performed
    @parm PBYTE | pBufIn | input data to the device
    @parm DWORD | dwLenIn | number of bytes being passed in
    @parm PBYTE | pBufOut | output data from the device
    @parm DWORD | dwLenOut |maximum number of bytes to receive from device
    @parm PDWORD | pdwActualOut | actual number of bytes received from device

    @rdesc        Returns TRUE for success, FALSE for failure

    @remark  The MDD will pass any unrecognized IOCTLs through to this function.
*************************************************************************/
static
BOOL SerIoctl(PVOID pHead, DWORD dwCode,PBYTE pBufIn,DWORD dwLenIn,
         PBYTE pBufOut,DWORD dwLenOut,PDWORD pdwActualOut)
{
	PSER_INFO pHWHead = (PSER_INFO)pHead;
 	BOOL RetVal = TRUE;

	DEBUGMSG(1, (TEXT("++SerIoctl 0x%X\r\n"), pHead));

	switch (dwCode) 
	{
		// Currently, no defined IOCTLs
		default:
			RetVal = FALSE;

			DEBUGMSG(1, (TEXT(" Unsupported ioctl 0x%X\r\n"), dwCode));
			break;            
	}

	DEBUGMSG(1, (TEXT("--SerIoctl 0x%X\r\n"), pHead));

	return(RetVal);
}

const
HW_VTBL IoVTbl = {
    SerInit,
    SerPostInit,
    SerDeinit,
    SerOpen,
    SerClose,
    SerGetInterruptType,
    SerRxIntr,
    SerTxIntr,
    SerModemIntr,
    SerLineIntr,
    SerGetRxBufferSize,
    SerPowerOff,
    SerPowerOn,
    SerClearDTR,
    SerSetDTR,
    SerClearRTS,
    SerSetRTS,
    SerEnableIR,
    SerDisableIR,
    SerClearBreak,
    SerSetBreak,
    SerXmitComChar,
    SerGetStatus,
    SerReset,
    SerGetModemStatus,
    SerGetCommProperties,
    SerPurgeComm,
    SerSetDCB,
    SerSetCommTimeouts,
    SerIoctl};

extern const HW_VTBL SerCardIoVTbl;

PHWOBJ
GetSerialObject( DWORD DeviceArrayIndex )
{
	PHWOBJ pSerObj;

	// We do not have a statically allocated array of HWObjs.  Instead, we 
	// allocate a new HWObj for each instance of the driver.  The MDD will 
	// always call GetSerialObj/HWInit/HWDeinit in that order, so we can do 
	// the alloc here and do any subsequent free in HWDeInit.
  
	// Allocate space for the HWOBJ.
	pSerObj = (PHWOBJ)LocalAlloc( LPTR, sizeof(HWOBJ) );
	if ( !pSerObj )
		return (NULL);

	// Fill in the HWObj structure that we just allocated.
	pSerObj->BindFlags = THREAD_IN_PDD;      // We take care of our own IST
	pSerObj->dwIntID = SYSINTR_USBD;   // SysIntr 
	pSerObj->pFuncTbl = (HW_VTBL *) &IoVTbl; // Return pointer to functions

	// Now return this structure to the MDD.
	return (pSerObj);
}

⌨️ 快捷键说明

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