📄 mdd.c
字号:
pSerialHead->DCB.fBinary = TRUE;
pSerialHead->DCB.fParity = FALSE;
pSerialHead->DCB.fOutxCtsFlow = FALSE;
pSerialHead->DCB.fOutxDsrFlow = FALSE;
// pSerialHead->DCB.fDtrControl = FALSE; //DTR_CONTROL_ENABLE; -by HMSEO
pSerialHead->DCB.fDtrControl = DTR_CONTROL_ENABLE; //-by HMSEO
pSerialHead->DCB.fDsrSensitivity = FALSE;
pSerialHead->DCB.fTXContinueOnXoff = FALSE;
pSerialHead->DCB.fOutX = FALSE;
pSerialHead->DCB.fInX = FALSE;
pSerialHead->DCB.fErrorChar = FALSE; //NOTE: ignored
pSerialHead->DCB.fNull = FALSE; //NOTE: ignored
//by gerryzhou 2007.4.23
pSerialHead->DCB.fRtsControl = RTS_CONTROL_ENABLE; //RTS_CONTROL_ENABLE; -by HMSEO
pSerialHead->DCB.fAbortOnError = FALSE; //NOTE: ignored
pSerialHead->DCB.XonLim = 512;
pSerialHead->DCB.XoffLim = 128;
pSerialHead->DCB.ByteSize = 8;
pSerialHead->DCB.Parity = NOPARITY;
pSerialHead->DCB.StopBits = ONESTOPBIT;
pSerialHead->DCB.XonChar = X_ON_CHAR;
pSerialHead->DCB.XoffChar = X_OFF_CHAR;
pSerialHead->DCB.ErrorChar = ERROR_CHAR;
pSerialHead->DCB.EofChar = E_OF_CHAR;
pSerialHead->DCB.EvtChar = EVENT_CHAR;
pSerialHead->StopXmit = 0;
pSerialHead->SentXoff = 0;
pSerialHead->DtrFlow = 0;
pSerialHead->RtsFlow = 0;
ApplyDCB (pSerialHead, &(pSerialHead->DCB), FALSE);
pHWObj->pFuncTbl->HWSetCommTimeouts(pSerialHead->pHWHead,
&(pSerialHead->CommTimeouts));
if ( !pHWObj->pFuncTbl->HWOpen(pSerialHead->pHWHead) ) {
RETAILMSG (ZONE_OPEN|ZONE_ERROR, (TEXT("HW Open failed.\r\n")));
goto OpenFail;
}
pHWObj->pFuncTbl->HWPurgeComm(pSerialHead->pHWHead, PURGE_RXCLEAR);
memset(pSerialHead->RxBufferInfo.RxCharBuffer, 0, pSerialHead->RxBufferInfo.Length);
if ( pHWObj->BindFlags & THREAD_IN_MDD ) {
CeSetThreadPriority(pSerialHead->pDispatchThread,
pSerialHead->Priority256);
}
RxResetFifo (pSerialHead);
}
++(pSerialHead->OpenCnt);
// OK, we are finally back in a stable state. Release the CS.
LeaveCriticalSection(&(pSerialHead->OpenCS));
RETAILMSG (ZONE_OPEN|ZONE_FUNCTION, (TEXT("-COM_Open handle x%X, x%X, Ref x%X\r\n"),
pOpenHead, pOpenHead->pSerialHead, pSerialHead->OpenCnt));
return(pOpenHead);
OpenFail :
RETAILMSG (ZONE_OPEN|ZONE_FUNCTION, (TEXT("-COM_Open handle x%X, x%X, Ref x%X\r\n"),
NULL, pOpenHead->pSerialHead, pSerialHead->OpenCnt));
SetLastError(ERROR_OPEN_FAILED);
// If this was the handle with access permission, remove pointer
if ( pOpenHead == pSerialHead->pAccessOwner )
pSerialHead->pAccessOwner = NULL;
// Remove the Open entry from the linked list
RemoveEntryList(&pOpenHead->llist);
// OK, everything is stable so release the critical section
LeaveCriticalSection(&(pSerialHead->OpenCS));
// Free all data allocated in open
if ( pOpenHead->CommEvents.hCommEvent )
CloseHandle(pOpenHead->CommEvents.hCommEvent);
DeleteCriticalSection(&(pOpenHead->CommEvents.EventCS));
LocalFree( pOpenHead );
return(NULL);
}
// ****************************************************************
//
// @doc EXTERNAL
//
// @func BOOL | COM_Close | close the serial device.
//
// @parm DWORD | pHead | Context pointer returned from COM_Open
//
// @rdesc TRUE if success; FALSE if failure
//
// @remark This routine is called by the device manager to close the device.
//
//
//
BOOL
COM_Close(PHW_OPEN_INFO pOpenHead)
{
PHW_INDEP_INFO pSerialHead = pOpenHead->pSerialHead;
PHWOBJ pHWObj;
int i;
BOOL RetCode = TRUE;
RETAILMSG (ZONE_CLOSE|ZONE_FUNCTION, (TEXT("+COM_Close\r\n")));
if ( !pSerialHead ) {
RETAILMSG (ZONE_ERROR, (TEXT("!!COM_Close: pSerialHead == NULL!!\r\n")));
SetLastError(ERROR_INVALID_HANDLE);
return(FALSE);
}
pHWObj = (PHWOBJ)pSerialHead->pHWObj;
// Use the OpenCS to make sure we don't collide with an in-progress open.
EnterCriticalSection(&(pSerialHead->OpenCS));
if ( pSerialHead->OpenCnt ) {
--(pSerialHead->OpenCnt);
RETAILMSG (0,
(TEXT("COM_Close: (%d handles) total RX %d, total TX %d, dropped (mdd, pdd) %d,%d\r\n"),
pSerialHead->OpenCnt, pSerialHead->RxBytes, pSerialHead->TxBytes, pSerialHead->DroppedBytesMDD, pSerialHead->DroppedBytesPDD));
// In multi open case, do we need to restore state later on or something????
if ( pHWObj && (pHWObj->BindFlags & THREAD_IN_MDD) &&
pSerialHead->pDispatchThread ) {
SetThreadPriority(pSerialHead->pDispatchThread,
THREAD_PRIORITY_NORMAL);
}
// Free up any threads which may be blocked waiting for events.
// Monitor users count to make sure no one is still in one of
// the COM_ functions before proceeding (wait up to 2 s).
for ( i=0; i<20 && pOpenHead->StructUsers; i++ ) {
RETAILMSG(ZONE_INIT|ZONE_CLOSE,
(TEXT("COM_Close: %d users in MDD functions\n\r"),pOpenHead->StructUsers));
// For any open handle, we must free pending waitcommevents
EnterCriticalSection(&(pOpenHead->CommEvents.EventCS));
pOpenHead->CommEvents.fEventMask = 0;
pOpenHead->CommEvents.fAbort = 1;
SetEvent(pOpenHead->CommEvents.hCommEvent);
LeaveCriticalSection(&(pOpenHead->CommEvents.EventCS));
// And only for the handle with access permissions do we
// have to worry about read, write, etc being blocked.
if ( pOpenHead->AccessCode & (GENERIC_READ | GENERIC_WRITE) ) {
SetEvent(pSerialHead->hReadEvent);
SetEvent(pSerialHead->hTransmitEvent);
}
/* Sleep, let threads finish */
Sleep(100);
}
if ( i==20 )
RETAILMSG(ZONE_CLOSE|ZONE_INIT|ZONE_ERROR,
(TEXT("COM_Close: Waited 2s for serial users to exit, %d left\n\r"),
pOpenHead->StructUsers));
// If we are closing the last open handle, then close PDD also
if ( !pSerialHead->OpenCnt ) {
RETAILMSG (ZONE_CLOSE, (TEXT("About to call HWClose\r\n")));
if ( pHWObj )
pHWObj->pFuncTbl->HWClose(pSerialHead->pHWHead);
RETAILMSG (ZONE_CLOSE, (TEXT("Returned from HWClose\r\n")));
// And if thread was spun in open, kill it now.
if ( pSerialHead->pHWObj->BindFlags & THREAD_AT_OPEN ) {
RETAILMSG (ZONE_CLOSE, (TEXT("COM_Close : Stopping Dispatch Thread\r\n")));
StopDispatchThread( pSerialHead );
}
}
// If this was the handle with access permission, remove pointer
if ( pOpenHead == pSerialHead->pAccessOwner ) {
RETAILMSG(ZONE_INIT|ZONE_CLOSE,
(TEXT("COM_Close: Closed access owner handle\n\r"),
pOpenHead));
pSerialHead->pAccessOwner = NULL;
}
// Remove the entry from the linked list
RemoveEntryList(&pOpenHead->llist);
// Free all data allocated in open
DeleteCriticalSection(&(pOpenHead->CommEvents.EventCS));
if ( pOpenHead->CommEvents.hCommEvent )
CloseHandle(pOpenHead->CommEvents.hCommEvent);
LocalFree( pOpenHead );
} else {
RETAILMSG (ZONE_ERROR, (TEXT("!!Close of non-open serial port\r\n")));
SetLastError(ERROR_INVALID_HANDLE);
RetCode = FALSE;
}
// OK, other inits/opens can go ahead.
LeaveCriticalSection(&(pSerialHead->OpenCS));
RETAILMSG (ZONE_CLOSE|ZONE_FUNCTION, (TEXT("-COM_Close\r\n")));
return(RetCode);
}
// Routine to handle the PROCESS_EXITING flag. Should let free any threads blocked on pOpenHead,
// so they can be killed and the process closed.
BOOL
ProcessExiting(PHW_OPEN_INFO pOpenHead)
{
PHW_INDEP_INFO pSerialHead = pOpenHead->pSerialHead;
PHWOBJ pHWObj;
int i;
BOOL RetCode = TRUE;
RETAILMSG (ZONE_CLOSE|ZONE_FUNCTION, (TEXT("+ProcessExiting\r\n")));
if ( !pSerialHead ) {
RETAILMSG (ZONE_ERROR, (TEXT("!!ProcessExiting: pSerialHead == NULL!!\r\n")));
SetLastError(ERROR_INVALID_HANDLE);
return(FALSE);
}
pHWObj = (PHWOBJ)pSerialHead->pHWObj;
// Use the OpenCS to make sure we don't collide with an in-progress open.
EnterCriticalSection(&(pSerialHead->OpenCS));
if ( pSerialHead->OpenCnt ) {
// --(pSerialHead->OpenCnt);
RETAILMSG (1,
(TEXT("ProcessClose: (%d handles) total RX %d, total TX %d, dropped (mdd, pdd) %d,%d\r\n"),
pSerialHead->OpenCnt, pSerialHead->RxBytes, pSerialHead->TxBytes, pSerialHead->DroppedBytesMDD, pSerialHead->DroppedBytesPDD));
// In multi open case, do we need to restore state later on or something????
if ( pHWObj && (pHWObj->BindFlags & THREAD_IN_MDD) &&
pSerialHead->pDispatchThread ) {
SetThreadPriority(pSerialHead->pDispatchThread,
THREAD_PRIORITY_NORMAL);
}
// Free up any threads which may be blocked waiting for events.
// Monitor users count to make sure no one is still in one of
// the COM_ functions before proceeding (wait up to 2 s).
for ( i=0; i<20 && pOpenHead->StructUsers; i++ ) {
RETAILMSG(ZONE_INIT|ZONE_CLOSE,
(TEXT("ProcessExiting: %d users in MDD functions\n\r"),pOpenHead->StructUsers));
// For any open handle, we must free pending waitcommevents
EnterCriticalSection(&(pOpenHead->CommEvents.EventCS));
pOpenHead->CommEvents.fEventMask = 0;
pOpenHead->CommEvents.fAbort = 1;
SetEvent(pOpenHead->CommEvents.hCommEvent);
LeaveCriticalSection(&(pOpenHead->CommEvents.EventCS));
// And only for the handle with access permissions do we
// have to worry about read, write, etc being blocked.
if ( pOpenHead->AccessCode & (GENERIC_READ | GENERIC_WRITE) ) {
SetEvent(pSerialHead->hReadEvent);
SetEvent(pSerialHead->hTransmitEvent);
}
/* Sleep, let threads finish */
Sleep(100);
}
if ( i==20 )
RETAILMSG(ZONE_CLOSE|ZONE_INIT|ZONE_ERROR,
(TEXT("ProcessExiting: Waited 2s for serial users to exit, %d left\n\r"),
pOpenHead->StructUsers));
/* Don't really want to close everything. Just want to free threads
// If we are closing the last open handle, then close PDD also
if ( !pSerialHead->OpenCnt ) {
RETAILMSG (ZONE_CLOSE, (TEXT("About to call HWClose\r\n")));
if ( pHWObj )
pHWObj->pFuncTbl->HWClose(pSerialHead->pHWHead);
RETAILMSG (ZONE_CLOSE, (TEXT("Returned from HWClose\r\n")));
// And if thread was spun in open, kill it now.
if ( pSerialHead->pHWObj->BindFlags & THREAD_AT_OPEN ) {
RETAILMSG (ZONE_CLOSE, (TEXT("COM_Close : Stopping Dispatch Thread\r\n")));
StopDispatchThread( pSerialHead );
}
}
// If this was the handle with access permission, remove pointer
if ( pOpenHead == pSerialHead->pAccessOwner ) {
RETAILMSG(ZONE_INIT|ZONE_CLOSE,
(TEXT("COM_Close: Closed access owner handle\n\r"),
pOpenHead));
pSerialHead->pAccessOwner = NULL;
}
// Remove the entry from the linked list
RemoveEntryList(&pOpenHead->llist);
// Free all data allocated in open
if ( pOpenHead->CommEvents.hCommEvent )
CloseHandle(pOpenHead->CommEvents.hCommEvent);
LocalFree( pOpenHead );
*/
} else {
RETAILMSG (ZONE_ERROR, (TEXT("!!Close of non-open serial port\r\n")));
SetLastError(ERROR_INVALID_HANDLE);
RetCode = FALSE;
}
// OK, other inits/opens can go ahead.
LeaveCriticalSection(&(pSerialHead->OpenCS));
RETAILMSG (ZONE_CLOSE|ZONE_FUNCTION, (TEXT("-ProcessExiting\r\n")));
return(RetCode);
}
/*
@doc EXTERNAL
@func BOOL | COM_Deinit | De-initialize serial port.
@parm DWORD | pSerialHead | Context pointer returned from COM_Init
*
@rdesc None.
*/
BOOL
COM_Deinit(PHW_INDEP_INFO pSerialHead)
{
RETAILMSG (ZONE_INIT|ZONE_FUNCTION, (TEXT("+COM_Deinit\r\n")));
if ( !pSerialHead ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -