serial redirection: implement event char

The signotec signature device requires the eventChar support to work properly in
serial redirection mode. This implementation is basic but does the job for this
device.

Sponsored by: Rangee GmbH (http://www.rangee.de)
This commit is contained in:
David Fort 2017-11-06 22:23:07 +01:00
parent ff8f7e9474
commit de7d7e43c9
4 changed files with 21 additions and 14 deletions

View File

@ -425,10 +425,8 @@ BOOL GetCommState(HANDLE hFile, LPDCB lpDCB)
lpLocalDcb->fDtrControl = DTR_CONTROL_DISABLE;
}
lpLocalDcb->fDsrSensitivity = (handflow.ControlHandShake &
SERIAL_DSR_SENSITIVITY) != 0;
lpLocalDcb->fTXContinueOnXoff = (handflow.FlowReplace & SERIAL_XOFF_CONTINUE) !=
0;
lpLocalDcb->fDsrSensitivity = (handflow.ControlHandShake & SERIAL_DSR_SENSITIVITY) != 0;
lpLocalDcb->fTXContinueOnXoff = (handflow.FlowReplace & SERIAL_XOFF_CONTINUE) != 0;
lpLocalDcb->fOutX = (handflow.FlowReplace & SERIAL_AUTO_TRANSMIT) != 0;
lpLocalDcb->fInX = (handflow.FlowReplace & SERIAL_AUTO_RECEIVE) != 0;
lpLocalDcb->fErrorChar = (handflow.FlowReplace & SERIAL_ERROR_CHAR) != 0;

View File

@ -69,6 +69,7 @@ struct winpr_comm
ULONG WaitEventMask;
ULONG PendingEvents;
char eventChar;
/* NB: CloseHandle() has to free resources */
};

View File

@ -146,7 +146,7 @@ BOOL CommReadFile(HANDLE hDevice, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
*
* ReadIntervalTimeout | ReadTotalTimeoutMultiplier | ReadTotalTimeoutConstant | VMIN | VTIME | TMAX |
* 0 | 0 | 0 | N | 0 | INDEF | Blocks for N bytes available.
* 0< Ti <MAXULONG | 0 | 0 | N | Ti | INDEF | Blocks on first byte, then use Ti between bytes.
* 0< Ti <MAXULONG | 0 | 0 | N | Ti | INDEF | Blocks on first byte, then use Ti between bytes.
* MAXULONG | 0 | 0 | 0 | 0 | 0 | Returns immediately with bytes available (don't block)
* MAXULONG | MAXULONG | 0< Tc <MAXULONG | N | 0 | Tc | Blocks on first byte during Tc or returns immediately whith bytes available
* MAXULONG | m | MAXULONG | | Invalid
@ -349,6 +349,14 @@ BOOL CommReadFile(HANDLE hDevice, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
}
*lpNumberOfBytesRead = nbRead;
EnterCriticalSection(&pComm->EventsLock);
if (pComm->PendingEvents & SERIAL_EV_FREERDP_WAITING)
{
if (pComm->eventChar != '\0' && memchr(lpBuffer, pComm->eventChar, nbRead))
pComm->PendingEvents |= SERIAL_EV_RXCHAR;
}
LeaveCriticalSection(&pComm->EventsLock);
goto return_true;
}
@ -546,13 +554,15 @@ BOOL CommWriteFile(HANDLE hDevice, LPCVOID lpBuffer,
* printer. Its driver was expecting the modem line status
* SERIAL_MSR_DSR true after the sending which was never
* happenning otherwise. A purge was also done before each
* Write operation. The serial port was oppened with:
* Write operation. The serial port was opened with:
* DesiredAccess=0x0012019F. The printer worked fine with
* mstsc. */
tcdrain(pComm->fd_write);
return_true:
LeaveCriticalSection(&pComm->WriteLock);
return TRUE;
return_false:
LeaveCriticalSection(&pComm->WriteLock);
return FALSE;

View File

@ -316,7 +316,7 @@ static BOOL _set_serial_chars(WINPR_COMM *pComm, const SERIAL_CHARS *pSerialChar
if (pSerialChars->XonChar == pSerialChars->XoffChar)
{
/* http://msdn.microsoft.com/en-us/library/windows/hardware/ff546688%28v=vs.85%29.aspx */
/* https://msdn.microsoft.com/en-us/library/windows/hardware/ff546688?v=vs.85.aspx */
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
@ -360,12 +360,9 @@ static BOOL _set_serial_chars(WINPR_COMM *pComm, const SERIAL_CHARS *pSerialChar
result = FALSE; /* but keep on */
}
/* FIXME: could be implemented during read/write I/O. What about ISIG? */
if (pSerialChars->EventChar != '\0')
{
CommLog_Print(WLOG_WARN, "EventChar 0x%02"PRIX8" ('%c') cannot be set\n", pSerialChars->EventChar, (char) pSerialChars->EventChar);
SetLastError(ERROR_NOT_SUPPORTED);
result = FALSE; /* but keep on */
pComm->eventChar = pSerialChars->EventChar;
}
upcomingTermios.c_cc[VSTART] = pSerialChars->XonChar;
@ -1076,7 +1073,8 @@ static BOOL _set_wait_mask(WINPR_COMM *pComm, const ULONG *pWaitMask)
if (possibleMask != *pWaitMask)
{
CommLog_Print(WLOG_WARN, "Not all wait events supported (Serial.sys), requested events= 0x%08"PRIX32", possible events= 0x%08"PRIX32"", *pWaitMask, possibleMask);
CommLog_Print(WLOG_WARN, "Not all wait events supported (Serial.sys), requested events= 0x%08"PRIX32", possible events= 0x%08"PRIX32"",
*pWaitMask, possibleMask);
/* FIXME: shall we really set the possibleMask and return FALSE? */
pComm->WaitEventMask = possibleMask;
@ -1310,7 +1308,7 @@ static BOOL _get_commstatus(WINPR_COMM *pComm, SERIAL_STATUS *pCommstatus)
if (currentCounters.rx != pComm->counters.rx)
{
pComm->PendingEvents |= SERIAL_EV_RXCHAR;
pComm->PendingEvents |= SERIAL_EV_RXFLAG;
}
if ((currentCounters.tx != pComm->counters.tx) && /* at least a transmission occurred AND ...*/
@ -1458,7 +1456,7 @@ static BOOL _wait_on_mask(WINPR_COMM *pComm, ULONG *pOutputMask)
*
* NOTE: previously used a semaphore but used
* sem_timedwait() anyway. Finally preferred a simpler
* solution with Sleep() whithout the burden of the
* solution with Sleep() without the burden of the
* semaphore initialization and destroying.
*/