mirror of
https://github.com/morgan9e/FreeRDP
synced 2026-04-15 00:44:19 +09:00
[winpr,comm] fix serial port redirection
* Unify ioctl logging * Fix device reset calls * Unify TIOCGICOUNT calls, only use them if they are supported * Fix XOn/XOff support * Fix modem status flags
This commit is contained in:
@@ -193,6 +193,12 @@ static UINT serial_process_irp_create(SERIAL_DEVICE* serial, IRP* irp)
|
||||
irp->IoStatus = STATUS_SUCCESS;
|
||||
WLog_Print(serial->log, WLOG_DEBUG, "%s (DeviceId: %" PRIu32 ", FileId: %" PRIu32 ") created.",
|
||||
serial->device.name, irp->device->id, irp->FileId);
|
||||
|
||||
DWORD BytesReturned = 0;
|
||||
if (!CommDeviceIoControl(serial->hComm, IOCTL_SERIAL_RESET_DEVICE, NULL, 0, NULL, 0,
|
||||
&BytesReturned, NULL))
|
||||
goto error_handle;
|
||||
|
||||
error_handle:
|
||||
Stream_Write_UINT32(irp->output, irp->FileId); /* FileId (4 bytes) */
|
||||
Stream_Write_UINT8(irp->output, 0); /* Information (1 byte) */
|
||||
@@ -530,6 +536,9 @@ error_out:
|
||||
if (error && data->serial->rdpcontext)
|
||||
setChannelError(data->serial->rdpcontext, error, "irp_thread_func reported an error");
|
||||
|
||||
if (error)
|
||||
data->irp->Discard(data->irp);
|
||||
|
||||
/* NB: At this point, the server might already being reusing
|
||||
* the CompletionId whereas the thread is not yet
|
||||
* terminated */
|
||||
|
||||
@@ -20,7 +20,7 @@ set(MODULE_PREFIX "WINPR_COMM")
|
||||
|
||||
if(NOT WIN32)
|
||||
set(${MODULE_PREFIX}_SRCS comm.c comm.h)
|
||||
if(NOT EMSCRIPTEN)
|
||||
if(NOT EMSCRIPTEN AND NOT APPLE)
|
||||
winpr_definition_add(WINPR_HAVE_SERIAL_SUPPORT)
|
||||
list(
|
||||
APPEND
|
||||
|
||||
@@ -728,7 +728,7 @@ BOOL SetCommState(HANDLE hFile, LPDCB lpDCB)
|
||||
|
||||
if (lpDCB->fBinary)
|
||||
{
|
||||
upcomingTermios.c_lflag &= WINPR_ASSERTING_INT_CAST(tcflag_t, ~ICANON);
|
||||
upcomingTermios.c_lflag &= (tcflag_t)~ICANON;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -742,7 +742,7 @@ BOOL SetCommState(HANDLE hFile, LPDCB lpDCB)
|
||||
}
|
||||
else
|
||||
{
|
||||
upcomingTermios.c_iflag &= WINPR_ASSERTING_INT_CAST(tcflag_t, ~INPCK);
|
||||
upcomingTermios.c_iflag &= (tcflag_t)~INPCK;
|
||||
}
|
||||
|
||||
/* http://msdn.microsoft.com/en-us/library/windows/desktop/aa363423%28v=vs.85%29.aspx
|
||||
@@ -756,7 +756,7 @@ BOOL SetCommState(HANDLE hFile, LPDCB lpDCB)
|
||||
* TCSANOW matches the best this definition
|
||||
*/
|
||||
|
||||
if (_comm_ioctl_tcsetattr(pComm->fd, TCSANOW, &upcomingTermios) < 0)
|
||||
if (comm_ioctl_tcsetattr(pComm->fd, TCSANOW, &upcomingTermios) < 0)
|
||||
{
|
||||
SetLastError(ERROR_IO_DEVICE);
|
||||
return FALSE;
|
||||
@@ -1384,22 +1384,7 @@ HANDLE CommCreateFileA(LPCSTR lpDeviceName, DWORD dwDesiredAccess, DWORD dwShare
|
||||
pComm->serverSerialDriverId = SerialDriverUnknown;
|
||||
InitializeCriticalSection(&pComm->EventsLock);
|
||||
|
||||
#if defined(WINPR_HAVE_COMM_COUNTERS)
|
||||
if (ioctl(pComm->fd, TIOCGICOUNT, &(pComm->counters)) < 0)
|
||||
{
|
||||
char ebuffer[256] = { 0 };
|
||||
CommLog_Print(WLOG_WARN, "TIOCGICOUNT ioctl failed, errno=[%d] %s.", errno,
|
||||
winpr_strerror(errno, ebuffer, sizeof(ebuffer)));
|
||||
CommLog_Print(WLOG_WARN, "could not read counters.");
|
||||
/* could not initialize counters but keep on.
|
||||
*
|
||||
* Not all drivers, especially for USB to serial
|
||||
* adapters (e.g. those based on pl2303), does support
|
||||
* this call.
|
||||
*/
|
||||
ZeroMemory(&(pComm->counters), sizeof(struct serial_icounter_struct));
|
||||
}
|
||||
#endif
|
||||
(void)CommUpdateIOCount(pComm, TRUE);
|
||||
|
||||
/* The binary/raw mode is required for the redirection but
|
||||
* only flags that are not handle somewhere-else, except
|
||||
@@ -1412,8 +1397,8 @@ HANDLE CommCreateFileA(LPCSTR lpDeviceName, DWORD dwDesiredAccess, DWORD dwShare
|
||||
goto error_handle;
|
||||
}
|
||||
|
||||
upcomingTermios.c_iflag &= WINPR_ASSERTING_INT_CAST(
|
||||
tcflag_t, ~(/*IGNBRK |*/ BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL /*| IXON*/));
|
||||
upcomingTermios.c_iflag &=
|
||||
(tcflag_t) ~(/*IGNBRK |*/ BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL /*| IXON*/);
|
||||
upcomingTermios.c_oflag = 0; /* <=> &= ~OPOST */
|
||||
upcomingTermios.c_lflag = 0; /* <=> &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); */
|
||||
/* upcomingTermios.c_cflag &= ~(CSIZE | PARENB); */
|
||||
@@ -1426,7 +1411,7 @@ HANDLE CommCreateFileA(LPCSTR lpDeviceName, DWORD dwDesiredAccess, DWORD dwShare
|
||||
/* a few more settings required for the redirection */
|
||||
upcomingTermios.c_cflag |= CLOCAL | CREAD;
|
||||
|
||||
if (_comm_ioctl_tcsetattr(pComm->fd, TCSANOW, &upcomingTermios) < 0)
|
||||
if (comm_ioctl_tcsetattr(pComm->fd, TCSANOW, &upcomingTermios) < 0)
|
||||
{
|
||||
SetLastError(ERROR_IO_DEVICE);
|
||||
goto error_handle;
|
||||
@@ -1504,3 +1489,216 @@ int eventfd_write(int fd, eventfd_t value)
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static const char* CommIoCtlToStr(unsigned long int io)
|
||||
{
|
||||
switch (io)
|
||||
{
|
||||
#if defined(WINPR_HAVE_SERIAL_SUPPORT)
|
||||
case TCGETS:
|
||||
return "TCGETS";
|
||||
case TCSETS:
|
||||
return "TCSETS";
|
||||
case TCSETSW:
|
||||
return "TCSETSW";
|
||||
case TCSETSF:
|
||||
return "TCSETSF";
|
||||
case TCGETA:
|
||||
return "TCGETA";
|
||||
case TCSETA:
|
||||
return "TCSETA";
|
||||
case TCSETAW:
|
||||
return "TCSETAW";
|
||||
case TCSETAF:
|
||||
return "TCSETAF";
|
||||
case TCSBRK:
|
||||
return "TCSBRK";
|
||||
case TCXONC:
|
||||
return "TCXONC";
|
||||
case TCFLSH:
|
||||
return "TCFLSH";
|
||||
case TIOCEXCL:
|
||||
return "TIOCEXCL";
|
||||
case TIOCNXCL:
|
||||
return "TIOCNXCL";
|
||||
case TIOCSCTTY:
|
||||
return "TIOCSCTTY";
|
||||
case TIOCGPGRP:
|
||||
return "TIOCGPGRP";
|
||||
case TIOCSPGRP:
|
||||
return "TIOCSPGRP";
|
||||
case TIOCOUTQ:
|
||||
return "TIOCOUTQ";
|
||||
case TIOCSTI:
|
||||
return "TIOCSTI";
|
||||
case TIOCGWINSZ:
|
||||
return "TIOCGWINSZ";
|
||||
case TIOCSWINSZ:
|
||||
return "TIOCSWINSZ";
|
||||
case TIOCMGET:
|
||||
return "TIOCMGET";
|
||||
case TIOCMBIS:
|
||||
return "TIOCMBIS";
|
||||
case TIOCMBIC:
|
||||
return "TIOCMBIC";
|
||||
case TIOCMSET:
|
||||
return "TIOCMSET";
|
||||
case TIOCGSOFTCAR:
|
||||
return "TIOCGSOFTCAR";
|
||||
case TIOCSSOFTCAR:
|
||||
return "TIOCSSOFTCAR";
|
||||
case FIONREAD:
|
||||
return "FIONREAD/TIOCINQ";
|
||||
case TIOCLINUX:
|
||||
return "TIOCLINUX";
|
||||
case TIOCCONS:
|
||||
return "TIOCCONS";
|
||||
case TIOCGSERIAL:
|
||||
return "TIOCGSERIAL";
|
||||
case TIOCSSERIAL:
|
||||
return "TIOCSSERIAL";
|
||||
case TIOCPKT:
|
||||
return "TIOCPKT";
|
||||
case FIONBIO:
|
||||
return "FIONBIO";
|
||||
case TIOCNOTTY:
|
||||
return "TIOCNOTTY";
|
||||
case TIOCSETD:
|
||||
return "TIOCSETD";
|
||||
case TIOCGETD:
|
||||
return "TIOCGETD";
|
||||
case TCSBRKP:
|
||||
return "TCSBRKP";
|
||||
case TIOCSBRK:
|
||||
return "TIOCSBRK";
|
||||
case TIOCCBRK:
|
||||
return "TIOCCBRK";
|
||||
case TIOCGSID:
|
||||
return "TIOCGSID";
|
||||
case TIOCGRS485:
|
||||
return "TIOCGRS485";
|
||||
case TIOCSRS485:
|
||||
return "TIOCSRS485";
|
||||
case TIOCSPTLCK:
|
||||
return "TIOCSPTLCK";
|
||||
case TCGETX:
|
||||
return "TCGETX";
|
||||
case TCSETX:
|
||||
return "TCSETX";
|
||||
case TCSETXF:
|
||||
return "TCSETXF";
|
||||
case TCSETXW:
|
||||
return "TCSETXW";
|
||||
case TIOCSIG:
|
||||
return "TIOCSIG";
|
||||
case TIOCVHANGUP:
|
||||
return "TIOCVHANGUP";
|
||||
case TIOCGPTPEER:
|
||||
return "TIOCGPTPEER";
|
||||
case FIONCLEX:
|
||||
return "FIONCLEX";
|
||||
case FIOCLEX:
|
||||
return "FIOCLEX";
|
||||
case FIOASYNC:
|
||||
return "FIOASYNC";
|
||||
case TIOCSERCONFIG:
|
||||
return "TIOCSERCONFIG";
|
||||
case TIOCSERGWILD:
|
||||
return "TIOCSERGWILD";
|
||||
case TIOCSERSWILD:
|
||||
return "TIOCSERSWILD";
|
||||
case TIOCGLCKTRMIOS:
|
||||
return "TIOCGLCKTRMIOS";
|
||||
case TIOCSLCKTRMIOS:
|
||||
return "TIOCSLCKTRMIOS";
|
||||
case TIOCSERGSTRUCT:
|
||||
return "TIOCSERGSTRUCT";
|
||||
case TIOCSERGETLSR:
|
||||
return "TIOCSERGETLSR";
|
||||
case TIOCSERGETMULTI:
|
||||
return "TIOCSERGETMULTI";
|
||||
case TIOCSERSETMULTI:
|
||||
return "TIOCSERSETMULTI";
|
||||
case TIOCMIWAIT:
|
||||
return "TIOCMIWAIT";
|
||||
case TIOCGICOUNT:
|
||||
return "TIOCGICOUNT";
|
||||
case FIOQSIZE:
|
||||
return "FIOQSIZE";
|
||||
case TIOCPKT_DATA:
|
||||
return "TIOCPKT_DATA";
|
||||
case TIOCPKT_FLUSHWRITE:
|
||||
return "TIOCPKT_FLUSHWRITE";
|
||||
case TIOCPKT_STOP:
|
||||
return "TIOCPKT_STOP";
|
||||
case TIOCPKT_START:
|
||||
return "TIOCPKT_START";
|
||||
case TIOCPKT_NOSTOP:
|
||||
return "TIOCPKT_NOSTOP";
|
||||
case TIOCPKT_DOSTOP:
|
||||
return "TIOCPKT_DOSTOP";
|
||||
case TIOCPKT_IOCTL:
|
||||
return "TIOCPKT_IOCTL";
|
||||
#endif
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL CommStatusErrorEx(WINPR_COMM* pComm, unsigned long int ctl, const char* file,
|
||||
const char* fkt, size_t line)
|
||||
{
|
||||
WINPR_ASSERT(pComm);
|
||||
BOOL rc = pComm->permissive ? TRUE : FALSE;
|
||||
const DWORD level = rc ? WLOG_DEBUG : WLOG_WARN;
|
||||
char ebuffer[256] = { 0 };
|
||||
const char* str = CommIoCtlToStr(ctl);
|
||||
|
||||
if (CommInitialized())
|
||||
{
|
||||
if (WLog_IsLevelActive(sLog, level))
|
||||
{
|
||||
WLog_PrintMessage(sLog, WLOG_MESSAGE_TEXT, level, line, file, fkt,
|
||||
"%s [0x%08" PRIx32 "] ioctl failed, errno=[%d] %s.", str, ctl, errno,
|
||||
winpr_strerror(errno, ebuffer, sizeof(ebuffer)));
|
||||
}
|
||||
}
|
||||
|
||||
if (!rc)
|
||||
SetLastError(ERROR_IO_DEVICE);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
BOOL CommIoCtl_int(WINPR_COMM* pComm, unsigned long int ctl, void* data, const char* file,
|
||||
const char* fkt, size_t line)
|
||||
{
|
||||
if (ioctl(pComm->fd, ctl, data) < 0)
|
||||
{
|
||||
if (!CommStatusErrorEx(pComm, ctl, file, fkt, line))
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL CommUpdateIOCount(WINPR_ATTR_UNUSED HANDLE handle, WINPR_ATTR_UNUSED BOOL checkSupportStatus)
|
||||
{
|
||||
WINPR_COMM* pComm = (WINPR_COMM*)handle;
|
||||
WINPR_ASSERT(pComm);
|
||||
|
||||
#if defined(WINPR_HAVE_COMM_COUNTERS)
|
||||
ZeroMemory(&(pComm->counters), sizeof(struct serial_icounter_struct));
|
||||
if (pComm->TIOCGICOUNTSupported || checkSupportStatus)
|
||||
{
|
||||
const int rc = ioctl(pComm->fd, TIOCGICOUNT, &(pComm->counters));
|
||||
if (checkSupportStatus)
|
||||
pComm->TIOCGICOUNTSupported = rc >= 0;
|
||||
else if (rc < 0)
|
||||
{
|
||||
if (!CommStatusErrorEx(pComm, TIOCGICOUNT, __FILE__, __func__, __LINE__))
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -77,6 +77,12 @@ struct winpr_comm
|
||||
|
||||
BYTE eventChar;
|
||||
/* NB: CloseHandle() has to free resources */
|
||||
ULONG XOnLimit;
|
||||
ULONG XOffLimit;
|
||||
|
||||
#if defined(WINPR_HAVE_COMM_COUNTERS)
|
||||
BOOL TIOCGICOUNTSupported;
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef struct winpr_comm WINPR_COMM;
|
||||
@@ -107,6 +113,12 @@ BOOL CommIsHandleValid(HANDLE handle);
|
||||
BOOL CommCloseHandle(HANDLE handle);
|
||||
const HANDLE_CREATOR* GetCommHandleCreator(void);
|
||||
|
||||
#define CommIoCtl(pComm, ctl, data) \
|
||||
CommIoCtl_int((pComm), (ctl), (data), __FILE__, __func__, __LINE__)
|
||||
BOOL CommIoCtl_int(WINPR_COMM* pComm, unsigned long int ctl, void* data, const char* file,
|
||||
const char* fkt, size_t line);
|
||||
BOOL CommUpdateIOCount(HANDLE handle, BOOL checkSupportStatus);
|
||||
|
||||
#if defined(WINPR_HAVE_SYS_EVENTFD_H)
|
||||
#ifndef WITH_EVENTFD_READ_WRITE
|
||||
int eventfd_read(int fd, eventfd_t* value);
|
||||
|
||||
@@ -507,7 +507,8 @@ BOOL CommWriteFile(HANDLE hDevice, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite
|
||||
if (FD_ISSET(pComm->fd_write, &write_set))
|
||||
{
|
||||
ssize_t nbWritten = 0;
|
||||
nbWritten = write(pComm->fd_write, ((const BYTE*)lpBuffer) + (*lpNumberOfBytesWritten),
|
||||
const BYTE* ptr = lpBuffer;
|
||||
nbWritten = write(pComm->fd_write, &ptr[*lpNumberOfBytesWritten],
|
||||
nNumberOfBytesToWrite - (*lpNumberOfBytesWritten));
|
||||
|
||||
if (nbWritten < 0)
|
||||
|
||||
@@ -75,7 +75,8 @@ static BOOL s_CommDeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode, LPVOID
|
||||
|
||||
*lpBytesReturned = 0; /* will be adjusted if required ... */
|
||||
|
||||
CommLog_Print(WLOG_DEBUG, "CommDeviceIoControl: IoControlCode: 0x%0.8x", dwIoControlCode);
|
||||
CommLog_Print(WLOG_DEBUG, "CommDeviceIoControl: IoControlCode: %s [0x%08" PRIx32 "]",
|
||||
_comm_serial_ioctl_name(dwIoControlCode), dwIoControlCode);
|
||||
|
||||
/* remoteSerialDriver to be use ...
|
||||
*
|
||||
@@ -374,6 +375,7 @@ static BOOL s_CommDeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode, LPVOID
|
||||
if (!pServerSerialDriver->get_modemstatus(pComm, pRegister))
|
||||
return FALSE;
|
||||
|
||||
CommLog_Print(WLOG_DEBUG, "modem status 0x%08" PRIx32, *pRegister);
|
||||
*lpBytesReturned = sizeof(ULONG);
|
||||
return TRUE;
|
||||
}
|
||||
@@ -392,7 +394,9 @@ static BOOL s_CommDeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode, LPVOID
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return pServerSerialDriver->set_wait_mask(pComm, pWaitMask);
|
||||
const BOOL rc = pServerSerialDriver->set_wait_mask(pComm, pWaitMask);
|
||||
CommLog_Print(WLOG_DEBUG, "set_wait_mask 0x%08" PRIx32 " -> %d", *pWaitMask, rc);
|
||||
return rc;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -412,6 +416,7 @@ static BOOL s_CommDeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode, LPVOID
|
||||
if (!pServerSerialDriver->get_wait_mask(pComm, pWaitMask))
|
||||
return FALSE;
|
||||
|
||||
CommLog_Print(WLOG_DEBUG, "get_wait_mask 0x%08" PRIx32, *pWaitMask);
|
||||
*lpBytesReturned = sizeof(ULONG);
|
||||
return TRUE;
|
||||
}
|
||||
@@ -430,14 +435,11 @@ static BOOL s_CommDeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode, LPVOID
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!pServerSerialDriver->wait_on_mask(pComm, pOutputMask))
|
||||
{
|
||||
*lpBytesReturned = sizeof(ULONG);
|
||||
return FALSE;
|
||||
}
|
||||
const BOOL rc = pServerSerialDriver->wait_on_mask(pComm, pOutputMask);
|
||||
|
||||
*lpBytesReturned = sizeof(ULONG);
|
||||
return TRUE;
|
||||
CommLog_Print(WLOG_DEBUG, "wait_on_mask 0x%08" PRIx32 " -> %d", *pOutputMask, rc);
|
||||
return rc;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -647,19 +649,19 @@ BOOL CommDeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode, LPVOID lpInBuffe
|
||||
{
|
||||
/* This might be a hint for a bug, especially when result==TRUE */
|
||||
CommLog_Print(WLOG_WARN,
|
||||
"lpBytesReturned=%" PRIu32 " and nOutBufferSize=%" PRIu32 " are different!",
|
||||
*lpBytesReturned, nOutBufferSize);
|
||||
"IoControlCode=[0x%08" PRIX32 "] %s: lpBytesReturned=%" PRIu32
|
||||
" and nOutBufferSize=%" PRIu32 " are different!",
|
||||
dwIoControlCode, _comm_serial_ioctl_name(dwIoControlCode), *lpBytesReturned,
|
||||
nOutBufferSize);
|
||||
}
|
||||
|
||||
if (pComm->permissive)
|
||||
{
|
||||
if (!result)
|
||||
{
|
||||
CommLog_Print(
|
||||
WLOG_WARN,
|
||||
"[permissive]: whereas it failed, made to succeed IoControlCode=[0x%08" PRIX32
|
||||
"] %s, last-error: 0x%08" PRIX32 "",
|
||||
dwIoControlCode, _comm_serial_ioctl_name(dwIoControlCode), GetLastError());
|
||||
CommLog_Print(WLOG_WARN,
|
||||
"[permissive]: IoControlCode=[0x%08" PRIX32 "] %s failed, ignoring",
|
||||
dwIoControlCode, _comm_serial_ioctl_name(dwIoControlCode));
|
||||
}
|
||||
|
||||
return TRUE; /* always! */
|
||||
@@ -668,50 +670,32 @@ BOOL CommDeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode, LPVOID lpInBuffe
|
||||
return result;
|
||||
}
|
||||
|
||||
int _comm_ioctl_tcsetattr(int fd, int optional_actions, const struct termios* termios_p)
|
||||
int comm_ioctl_tcsetattr(int fd, int optional_actions, const struct termios* termios_p)
|
||||
{
|
||||
int result = 0;
|
||||
struct termios currentState = { 0 };
|
||||
|
||||
if ((result = tcsetattr(fd, optional_actions, termios_p)) < 0)
|
||||
size_t count = 0;
|
||||
do
|
||||
{
|
||||
CommLog_Print(WLOG_WARN, "tcsetattr failure, errno: %d", errno);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* NB: tcsetattr() can succeed even if not all changes have been applied. */
|
||||
if ((result = tcgetattr(fd, ¤tState)) < 0)
|
||||
{
|
||||
CommLog_Print(WLOG_WARN, "tcgetattr failure, errno: %d", errno);
|
||||
return result;
|
||||
}
|
||||
|
||||
// NOLINTNEXTLINE(bugprone-suspicious-memory-comparison,cert-exp42-c,cert-flp37-c)
|
||||
if (memcmp(¤tState, termios_p, sizeof(struct termios)) != 0)
|
||||
{
|
||||
CommLog_Print(WLOG_DEBUG,
|
||||
"all termios parameters are not set yet, doing a second attempt...");
|
||||
if ((result = tcsetattr(fd, optional_actions, termios_p)) < 0)
|
||||
const int src = tcsetattr(fd, optional_actions, termios_p);
|
||||
if (src < 0)
|
||||
{
|
||||
CommLog_Print(WLOG_WARN, "2nd tcsetattr failure, errno: %d", errno);
|
||||
return result;
|
||||
char buffer[64] = { 0 };
|
||||
CommLog_Print(WLOG_WARN, "[%" PRIuz "] tcsetattr failure, errno: %s [%d]", count,
|
||||
winpr_strerror(errno, buffer, sizeof(buffer)), errno);
|
||||
return src;
|
||||
}
|
||||
|
||||
ZeroMemory(¤tState, sizeof(struct termios));
|
||||
if ((result = tcgetattr(fd, ¤tState)) < 0)
|
||||
/* NB: tcsetattr() can succeed even if not all changes have been applied. */
|
||||
const int rrc = tcgetattr(fd, ¤tState);
|
||||
if (rrc < 0)
|
||||
{
|
||||
CommLog_Print(WLOG_WARN, "tcgetattr failure, errno: %d", errno);
|
||||
return result;
|
||||
char buffer[64] = { 0 };
|
||||
CommLog_Print(WLOG_WARN, "[%" PRIuz "] tcgetattr failure, errno: %s [%d]", count,
|
||||
winpr_strerror(errno, buffer, sizeof(buffer)), errno);
|
||||
return rrc;
|
||||
}
|
||||
|
||||
// NOLINTNEXTLINE(bugprone-suspicious-memory-comparison,cert-exp42-c,cert-flp37-c)
|
||||
if (memcmp(¤tState, termios_p, sizeof(struct termios)) != 0)
|
||||
{
|
||||
CommLog_Print(WLOG_WARN,
|
||||
"Failure: all termios parameters are still not set on a second attempt");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
// NOLINTNEXTLINE(bugprone-suspicious-memory-comparison)
|
||||
} while ((memcmp(¤tState, termios_p, sizeof(struct termios)) != 0) && (count++ < 2));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -79,8 +79,8 @@ extern "C"
|
||||
{
|
||||
ULONG ControlHandShake;
|
||||
ULONG FlowReplace;
|
||||
WORD XonLimit;
|
||||
WORD XoffLimit;
|
||||
ULONG XonLimit;
|
||||
ULONG XoffLimit;
|
||||
} SERIAL_HANDFLOW, *PSERIAL_HANDFLOW;
|
||||
|
||||
#define SERIAL_DTR_MASK ((ULONG)0x03)
|
||||
@@ -223,7 +223,7 @@ extern "C"
|
||||
|
||||
} SERIAL_DRIVER;
|
||||
|
||||
int _comm_ioctl_tcsetattr(int fd, int optional_actions, const struct termios* termios_p);
|
||||
int comm_ioctl_tcsetattr(int fd, int optional_actions, const struct termios* termios_p);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ BOOL CommDeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode, LPVOID lpInBuffe
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int _comm_ioctl_tcsetattr(int fd, int optional_actions, const struct termios* termios_p)
|
||||
int comm_ioctl_tcsetattr(int fd, int optional_actions, const struct termios* termios_p)
|
||||
{
|
||||
WINPR_UNUSED(fd);
|
||||
WINPR_UNUSED(optional_actions);
|
||||
|
||||
@@ -152,7 +152,53 @@ static const speed_t BAUD_TABLE[][3] = {
|
||||
{ BAUD_TABLE_END, 0, 0 }
|
||||
};
|
||||
|
||||
static BOOL commstatus_error(WINPR_COMM* pComm, const char* ctrl);
|
||||
static const char* get_modem_flag_str(ULONG flag)
|
||||
{
|
||||
if (flag & TIOCM_DTR)
|
||||
return "DTR (data terminal ready)";
|
||||
if (flag & TIOCM_RTS)
|
||||
return "RTS (request to send)";
|
||||
if (flag & TIOCM_ST)
|
||||
return "Secondary TXD (transmit)";
|
||||
if (flag & TIOCM_SR)
|
||||
return "Secondary RXD (receive)";
|
||||
if (flag & TIOCM_CTS)
|
||||
return "CTS (clear to send)";
|
||||
if (flag & TIOCM_CAR)
|
||||
return "DCD (data carrier detect)";
|
||||
if (flag & TIOCM_CD)
|
||||
return "CD (carrier detect)";
|
||||
if (flag & TIOCM_RNG)
|
||||
return "RNG (ring)";
|
||||
if (flag & TIOCM_RI)
|
||||
return "RI (ring)";
|
||||
if (flag & TIOCM_DSR)
|
||||
return "DSR";
|
||||
return "UNKNOWN";
|
||||
}
|
||||
|
||||
static const char* get_modem_status_str(ULONG status, char* buffer, size_t size)
|
||||
{
|
||||
const ULONG flags[] = { TIOCM_DTR, TIOCM_RTS, TIOCM_ST, TIOCM_SR, TIOCM_CTS,
|
||||
TIOCM_CAR, TIOCM_CD, TIOCM_RNG, TIOCM_RI, TIOCM_DSR };
|
||||
winpr_str_append("{", buffer, size, "");
|
||||
|
||||
const char* sep = "";
|
||||
for (size_t x = 0; x < ARRAYSIZE(flags); x++)
|
||||
{
|
||||
const ULONG flag = flags[x];
|
||||
if (status & flag)
|
||||
{
|
||||
winpr_str_append(get_modem_flag_str(flag), buffer, size, sep);
|
||||
sep = "|";
|
||||
}
|
||||
}
|
||||
|
||||
char number[32] = { 0 };
|
||||
_snprintf(number, sizeof(number), "}[0x%08" PRIx32 "]", status);
|
||||
winpr_str_append(number, buffer, size, "");
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static BOOL get_properties(WINPR_ATTR_UNUSED WINPR_COMM* pComm, COMMPROP* pProperties)
|
||||
{
|
||||
@@ -248,9 +294,9 @@ static BOOL set_baud_rate(WINPR_COMM* pComm, const SERIAL_BAUD_RATE* pBaudRate)
|
||||
|
||||
WINPR_ASSERT(cfgetispeed(&futureState) == newSpeed);
|
||||
|
||||
if (_comm_ioctl_tcsetattr(pComm->fd, TCSANOW, &futureState) < 0)
|
||||
if (comm_ioctl_tcsetattr(pComm->fd, TCSANOW, &futureState) < 0)
|
||||
{
|
||||
CommLog_Print(WLOG_WARN, "_comm_ioctl_tcsetattr failure: last-error: 0x%" PRIX32 "",
|
||||
CommLog_Print(WLOG_WARN, "comm_ioctl_tcsetattr failure: last-error: 0x%" PRIX32 "",
|
||||
GetLastError());
|
||||
return FALSE;
|
||||
}
|
||||
@@ -369,9 +415,9 @@ static BOOL set_serial_chars(WINPR_COMM* pComm, const SERIAL_CHARS* pSerialChars
|
||||
|
||||
upcomingTermios.c_cc[VSTOP] = pSerialChars->XoffChar;
|
||||
|
||||
if (_comm_ioctl_tcsetattr(pComm->fd, TCSANOW, &upcomingTermios) < 0)
|
||||
if (comm_ioctl_tcsetattr(pComm->fd, TCSANOW, &upcomingTermios) < 0)
|
||||
{
|
||||
CommLog_Print(WLOG_WARN, "_comm_ioctl_tcsetattr failure: last-error: 0x%08" PRIX32 "",
|
||||
CommLog_Print(WLOG_WARN, "comm_ioctl_tcsetattr failure: last-error: 0x%08" PRIX32 "",
|
||||
GetLastError());
|
||||
return FALSE;
|
||||
}
|
||||
@@ -517,9 +563,9 @@ static BOOL set_line_control(WINPR_COMM* pComm, const SERIAL_LINE_CONTROL* pLine
|
||||
break;
|
||||
}
|
||||
|
||||
if (_comm_ioctl_tcsetattr(pComm->fd, TCSANOW, &upcomingTermios) < 0)
|
||||
if (comm_ioctl_tcsetattr(pComm->fd, TCSANOW, &upcomingTermios) < 0)
|
||||
{
|
||||
CommLog_Print(WLOG_WARN, "_comm_ioctl_tcsetattr failure: last-error: 0x%08" PRIX32 "",
|
||||
CommLog_Print(WLOG_WARN, "comm_ioctl_tcsetattr failure: last-error: 0x%08" PRIX32 "",
|
||||
GetLastError());
|
||||
return FALSE;
|
||||
}
|
||||
@@ -747,29 +793,12 @@ static BOOL set_handflow(WINPR_COMM* pComm, const SERIAL_HANDFLOW* pHandflow)
|
||||
|
||||
/* XonLimit */
|
||||
|
||||
// FIXME: could be implemented during read/write I/O
|
||||
if (pHandflow->XonLimit != TTY_THRESHOLD_UNTHROTTLE)
|
||||
{
|
||||
CommLog_Print(WLOG_WARN, "Attempt to set XonLimit with an unsupported value: %" PRId32 "",
|
||||
pHandflow->XonLimit);
|
||||
SetLastError(ERROR_NOT_SUPPORTED);
|
||||
result = FALSE; /* but keep on */
|
||||
}
|
||||
pComm->XOffLimit = pHandflow->XoffLimit;
|
||||
pComm->XOnLimit = pHandflow->XonLimit;
|
||||
|
||||
/* XoffChar */
|
||||
|
||||
// FIXME: could be implemented during read/write I/O
|
||||
if (pHandflow->XoffLimit != TTY_THRESHOLD_THROTTLE)
|
||||
if (comm_ioctl_tcsetattr(pComm->fd, TCSANOW, &upcomingTermios) < 0)
|
||||
{
|
||||
CommLog_Print(WLOG_WARN, "Attempt to set XoffLimit with an unsupported value: %" PRId32 "",
|
||||
pHandflow->XoffLimit);
|
||||
SetLastError(ERROR_NOT_SUPPORTED);
|
||||
result = FALSE; /* but keep on */
|
||||
}
|
||||
|
||||
if (_comm_ioctl_tcsetattr(pComm->fd, TCSANOW, &upcomingTermios) < 0)
|
||||
{
|
||||
CommLog_Print(WLOG_WARN, "_comm_ioctl_tcsetattr failure: last-error: 0x%" PRIX32 "",
|
||||
CommLog_Print(WLOG_WARN, "comm_ioctl_tcsetattr failure: last-error: 0x%" PRIX32 "",
|
||||
GetLastError());
|
||||
return FALSE;
|
||||
}
|
||||
@@ -836,13 +865,8 @@ static BOOL get_handflow(WINPR_COMM* pComm, SERIAL_HANDFLOW* pHandflow)
|
||||
|
||||
/* SERIAL_XOFF_CONTINUE unsupported */
|
||||
|
||||
/* XonLimit */
|
||||
|
||||
pHandflow->XonLimit = TTY_THRESHOLD_UNTHROTTLE;
|
||||
|
||||
/* XoffLimit */
|
||||
|
||||
pHandflow->XoffLimit = TTY_THRESHOLD_THROTTLE;
|
||||
pHandflow->XonLimit = pComm->XOnLimit;
|
||||
pHandflow->XoffLimit = pComm->XOffLimit;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -903,32 +927,14 @@ static BOOL set_lines(WINPR_COMM* pComm, UINT32 lines)
|
||||
{
|
||||
WINPR_ASSERT(pComm);
|
||||
|
||||
if (ioctl(pComm->fd, TIOCMBIS, &lines) < 0)
|
||||
{
|
||||
char ebuffer[256] = { 0 };
|
||||
CommLog_Print(WLOG_WARN, "TIOCMBIS ioctl failed, lines=0x%" PRIX32 ", errno=[%d] %s", lines,
|
||||
errno, winpr_strerror(errno, ebuffer, sizeof(ebuffer)));
|
||||
SetLastError(ERROR_IO_DEVICE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
return CommIoCtl(pComm, TIOCMBIS, &lines);
|
||||
}
|
||||
|
||||
static BOOL clear_lines(WINPR_COMM* pComm, UINT32 lines)
|
||||
{
|
||||
WINPR_ASSERT(pComm);
|
||||
|
||||
if (ioctl(pComm->fd, TIOCMBIC, &lines) < 0)
|
||||
{
|
||||
char ebuffer[256] = { 0 };
|
||||
CommLog_Print(WLOG_WARN, "TIOCMBIC ioctl failed, lines=0x%" PRIX32 ", errno=[%d] %s", lines,
|
||||
errno, winpr_strerror(errno, ebuffer, sizeof(ebuffer)));
|
||||
SetLastError(ERROR_IO_DEVICE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
return CommIoCtl(pComm, TIOCMBIC, &lines);
|
||||
}
|
||||
|
||||
static BOOL set_dtr(WINPR_COMM* pComm)
|
||||
@@ -1004,28 +1010,30 @@ static BOOL clear_rts(WINPR_COMM* pComm)
|
||||
return clear_lines(pComm, TIOCM_RTS);
|
||||
}
|
||||
|
||||
static BOOL get_modemstatus(WINPR_COMM* pComm, ULONG* pRegister)
|
||||
static BOOL get_raw_modemstatus(WINPR_COMM* pComm, int* pRegister)
|
||||
{
|
||||
UINT32 lines = 0;
|
||||
|
||||
WINPR_ASSERT(pComm);
|
||||
WINPR_ASSERT(pRegister);
|
||||
|
||||
*pRegister = 0;
|
||||
if (ioctl(pComm->fd, TIOCMGET, &lines) < 0)
|
||||
{
|
||||
if (!commstatus_error(pComm, "TIOCMGET"))
|
||||
return FALSE;
|
||||
}
|
||||
return CommIoCtl(pComm, TIOCMGET, pRegister);
|
||||
}
|
||||
|
||||
static BOOL get_modemstatus(WINPR_COMM* pComm, ULONG* pRegister)
|
||||
{
|
||||
int lines = 0;
|
||||
|
||||
if (!get_raw_modemstatus(pComm, &lines))
|
||||
return FALSE;
|
||||
|
||||
*pRegister = 0;
|
||||
if (lines & TIOCM_CTS)
|
||||
*pRegister |= SERIAL_MSR_CTS;
|
||||
*pRegister |= SERIAL_MSR_CTS | SERIAL_MSR_DCTS;
|
||||
if (lines & TIOCM_DSR)
|
||||
*pRegister |= SERIAL_MSR_DSR;
|
||||
*pRegister |= SERIAL_MSR_DSR | SERIAL_MSR_DDSR;
|
||||
if (lines & TIOCM_RI)
|
||||
*pRegister |= SERIAL_MSR_RI;
|
||||
*pRegister |= SERIAL_MSR_RI | SERIAL_MSR_TERI;
|
||||
if (lines & TIOCM_CD)
|
||||
*pRegister |= SERIAL_MSR_DCD;
|
||||
*pRegister |= SERIAL_MSR_DCD | SERIAL_MSR_DDCD;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -1083,17 +1091,12 @@ static BOOL set_wait_mask(WINPR_COMM* pComm, const ULONG* pWaitMask)
|
||||
if (*pWaitMask == 0)
|
||||
{
|
||||
/* clearing pending events */
|
||||
#if defined(WINPR_HAVE_COMM_COUNTERS)
|
||||
if (ioctl(pComm->fd, TIOCGICOUNT, &(pComm->counters)) < 0)
|
||||
if (!CommUpdateIOCount(pComm, FALSE))
|
||||
{
|
||||
if (!commstatus_error(pComm, "TIOCGICOUNT"))
|
||||
{
|
||||
LeaveCriticalSection(&pComm->EventsLock);
|
||||
return FALSE;
|
||||
}
|
||||
ZeroMemory(&(pComm->counters), sizeof(struct serial_icounter_struct));
|
||||
LeaveCriticalSection(&pComm->EventsLock);
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
pComm->PendingEvents = 0;
|
||||
}
|
||||
|
||||
@@ -1239,20 +1242,6 @@ static BOOL purge(WINPR_COMM* pComm, const ULONG* pPurgeMask)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL commstatus_error(WINPR_COMM* pComm, const char* ctrl)
|
||||
{
|
||||
char ebuffer[256] = { 0 };
|
||||
CommLog_Print(WLOG_WARN, "%s ioctl failed, errno=[%d] %s.", ctrl, errno,
|
||||
winpr_strerror(errno, ebuffer, sizeof(ebuffer)));
|
||||
|
||||
if (!pComm->permissive)
|
||||
{
|
||||
SetLastError(ERROR_IO_DEVICE);
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* NB: get_commstatus also produces most of the events consumed by wait_on_mask(). Exceptions:
|
||||
* - SERIAL_EV_RXFLAG: FIXME: once EventChar supported
|
||||
*
|
||||
@@ -1272,25 +1261,14 @@ static BOOL get_commstatus(WINPR_COMM* pComm, SERIAL_STATUS* pCommstatus)
|
||||
|
||||
ZeroMemory(pCommstatus, sizeof(SERIAL_STATUS));
|
||||
|
||||
ULONG status = 0;
|
||||
if (!get_modemstatus(pComm, &status))
|
||||
{
|
||||
if (!commstatus_error(pComm, "TIOCGICOUNT"))
|
||||
goto fail;
|
||||
/* Errors and events based on counters could not be
|
||||
* detected but keep on.
|
||||
*/
|
||||
SetLastError(0);
|
||||
status = 0;
|
||||
}
|
||||
int status = 0;
|
||||
if (!get_raw_modemstatus(pComm, &status))
|
||||
goto fail;
|
||||
|
||||
#if defined(WINPR_HAVE_COMM_COUNTERS)
|
||||
if (ioctl(pComm->fd, TIOCGICOUNT, ¤tCounters) < 0)
|
||||
{
|
||||
if (!commstatus_error(pComm, "TIOCGICOUNT"))
|
||||
goto fail;
|
||||
ZeroMemory(¤tCounters, sizeof(struct serial_icounter_struct));
|
||||
}
|
||||
if (!CommUpdateIOCount(pComm, FALSE))
|
||||
goto fail;
|
||||
currentCounters = pComm->counters;
|
||||
|
||||
/* NB: preferred below (currentCounters.* != pComm->counters.*) over (currentCounters.* >
|
||||
* pComm->counters.*) thinking the counters can loop */
|
||||
@@ -1329,11 +1307,8 @@ static BOOL get_commstatus(WINPR_COMM* pComm, SERIAL_STATUS* pCommstatus)
|
||||
|
||||
/* HoldReasons */
|
||||
|
||||
/* TODO: SERIAL_TX_WAITING_FOR_CTS */
|
||||
|
||||
/* TODO: SERIAL_TX_WAITING_FOR_DSR */
|
||||
|
||||
/* TODO: SERIAL_TX_WAITING_FOR_DCD */
|
||||
if (status & TIOCM_CTS)
|
||||
pComm->PendingEvents |= SERIAL_EV_CTS;
|
||||
|
||||
/* TODO: SERIAL_TX_WAITING_FOR_XON */
|
||||
|
||||
@@ -1341,37 +1316,34 @@ static BOOL get_commstatus(WINPR_COMM* pComm, SERIAL_STATUS* pCommstatus)
|
||||
|
||||
/* TODO: SERIAL_TX_WAITING_XOFF_SENT */
|
||||
|
||||
if (status & TIOCM_SR)
|
||||
pComm->PendingEvents |= SERIAL_EV_RXFLAG | SERIAL_EV_RXCHAR;
|
||||
|
||||
/* AmountInInQueue */
|
||||
int available = 0;
|
||||
if (!CommIoCtl(pComm, FIONREAD, &available))
|
||||
goto fail;
|
||||
|
||||
#if defined(__linux__)
|
||||
if (ioctl(pComm->fd, TIOCINQ, &(pCommstatus->AmountInInQueue)) < 0)
|
||||
{
|
||||
if (!commstatus_error(pComm, "TIOCINQ"))
|
||||
goto fail;
|
||||
}
|
||||
if (!CommIoCtl(pComm, TIOCINQ, &pCommstatus->AmountInInQueue))
|
||||
goto fail;
|
||||
#endif
|
||||
|
||||
/* AmountInOutQueue */
|
||||
|
||||
if (ioctl(pComm->fd, TIOCOUTQ, &(pCommstatus->AmountInOutQueue)) < 0)
|
||||
{
|
||||
if (!commstatus_error(pComm, "TIOCOUTQ"))
|
||||
goto fail;
|
||||
}
|
||||
if (!CommIoCtl(pComm, TIOCOUTQ, &pCommstatus->AmountInOutQueue))
|
||||
goto fail;
|
||||
|
||||
/* BOOLEAN EofReceived; FIXME: once EofChar supported */
|
||||
|
||||
/* BOOLEAN WaitForImmediate; TODO: once IOCTL_SERIAL_IMMEDIATE_CHAR fully supported */
|
||||
|
||||
/* other events based on counters */
|
||||
#if defined(WINPR_HAVE_COMM_COUNTERS)
|
||||
if (currentCounters.rx != pComm->counters.rx)
|
||||
{
|
||||
pComm->PendingEvents |= SERIAL_EV_RXFLAG | SERIAL_EV_RXCHAR;
|
||||
}
|
||||
|
||||
if ((currentCounters.tx != pComm->counters.tx) && /* at least a transmission occurred AND ...*/
|
||||
(pCommstatus->AmountInOutQueue == 0)) /* output buffer is now empty */
|
||||
if (available > 0)
|
||||
pComm->PendingEvents |= SERIAL_EV_RXFLAG | SERIAL_EV_RXCHAR;
|
||||
|
||||
if (pCommstatus->AmountInOutQueue == 0) /* output buffer is now empty */
|
||||
{
|
||||
pComm->PendingEvents |= SERIAL_EV_TXEMPTY;
|
||||
}
|
||||
@@ -1382,6 +1354,21 @@ static BOOL get_commstatus(WINPR_COMM* pComm, SERIAL_STATUS* pCommstatus)
|
||||
pComm->PendingEvents &= (uint32_t)~SERIAL_EV_TXEMPTY;
|
||||
}
|
||||
|
||||
#if defined(WINPR_HAVE_COMM_COUNTERS)
|
||||
if (currentCounters.tx != pComm->counters.tx)
|
||||
{
|
||||
pComm->PendingEvents |= SERIAL_EV_TXEMPTY;
|
||||
}
|
||||
else
|
||||
{
|
||||
pComm->PendingEvents |= SERIAL_EV_TXEMPTY;
|
||||
}
|
||||
|
||||
if (currentCounters.rx != pComm->counters.rx)
|
||||
{
|
||||
pComm->PendingEvents |= SERIAL_EV_RXFLAG | SERIAL_EV_RXCHAR;
|
||||
}
|
||||
|
||||
if (currentCounters.cts != pComm->counters.cts)
|
||||
{
|
||||
pComm->PendingEvents |= SERIAL_EV_CTS;
|
||||
@@ -1401,7 +1388,6 @@ static BOOL get_commstatus(WINPR_COMM* pComm, SERIAL_STATUS* pCommstatus)
|
||||
{
|
||||
pComm->PendingEvents |= SERIAL_EV_RING;
|
||||
}
|
||||
|
||||
pComm->counters = currentCounters;
|
||||
#endif
|
||||
|
||||
@@ -1494,7 +1480,6 @@ static BOOL wait_on_mask(WINPR_COMM* pComm, ULONG* pOutputMask)
|
||||
consume_event(pComm, pOutputMask, SERIAL_EV_RXCHAR);
|
||||
consume_event(pComm, pOutputMask, SERIAL_EV_RXFLAG);
|
||||
consume_event(pComm, pOutputMask, SERIAL_EV_TXEMPTY);
|
||||
consume_event(pComm, pOutputMask, SERIAL_EV_CTS);
|
||||
consume_event(pComm, pOutputMask, SERIAL_EV_DSR);
|
||||
consume_event(pComm, pOutputMask, SERIAL_EV_RLSD);
|
||||
consume_event(pComm, pOutputMask, SERIAL_EV_BREAK);
|
||||
@@ -1527,31 +1512,14 @@ static BOOL wait_on_mask(WINPR_COMM* pComm, ULONG* pOutputMask)
|
||||
static BOOL set_break_on(WINPR_COMM* pComm)
|
||||
{
|
||||
WINPR_ASSERT(pComm);
|
||||
if (ioctl(pComm->fd, TIOCSBRK, NULL) < 0)
|
||||
{
|
||||
char ebuffer[256] = { 0 };
|
||||
CommLog_Print(WLOG_WARN, "TIOCSBRK ioctl failed, errno=[%d] %s", errno,
|
||||
winpr_strerror(errno, ebuffer, sizeof(ebuffer)));
|
||||
SetLastError(ERROR_IO_DEVICE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
return CommIoCtl(pComm, TIOCSBRK, NULL);
|
||||
}
|
||||
|
||||
static BOOL set_break_off(WINPR_COMM* pComm)
|
||||
{
|
||||
WINPR_ASSERT(pComm);
|
||||
if (ioctl(pComm->fd, TIOCCBRK, NULL) < 0)
|
||||
{
|
||||
char ebuffer[256] = { 0 };
|
||||
CommLog_Print(WLOG_WARN, "TIOCSBRK ioctl failed, errno=[%d] %s", errno,
|
||||
winpr_strerror(errno, ebuffer, sizeof(ebuffer)));
|
||||
SetLastError(ERROR_IO_DEVICE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
return CommIoCtl(pComm, TIOCCBRK, NULL);
|
||||
}
|
||||
|
||||
static BOOL set_xoff(WINPR_COMM* pComm)
|
||||
@@ -1588,12 +1556,12 @@ static BOOL set_xon(WINPR_COMM* pComm)
|
||||
|
||||
static BOOL get_dtrrts(WINPR_COMM* pComm, ULONG* pMask)
|
||||
{
|
||||
UINT32 lines = 0;
|
||||
int lines = 0;
|
||||
|
||||
WINPR_ASSERT(pComm);
|
||||
WINPR_ASSERT(pMask);
|
||||
|
||||
if (!get_modemstatus(pComm, &lines))
|
||||
if (!get_raw_modemstatus(pComm, &lines))
|
||||
return FALSE;
|
||||
|
||||
*pMask = 0;
|
||||
@@ -1643,7 +1611,14 @@ static BOOL immediate_char(WINPR_COMM* pComm, const UCHAR* pChar)
|
||||
static BOOL reset_device(WINPR_ATTR_UNUSED WINPR_COMM* pComm)
|
||||
{
|
||||
/* http://msdn.microsoft.com/en-us/library/dn265347%28v=vs.85%29.aspx */
|
||||
return TRUE;
|
||||
WINPR_ASSERT(pComm);
|
||||
|
||||
pComm->XOnLimit = TTY_THRESHOLD_UNTHROTTLE;
|
||||
pComm->XOffLimit = TTY_THRESHOLD_THROTTLE;
|
||||
|
||||
(void)CommUpdateIOCount(pComm, TRUE);
|
||||
|
||||
return CommIoCtl(pComm, TIOCMSET, 0);
|
||||
}
|
||||
|
||||
static const SERIAL_DRIVER SerialSys = {
|
||||
|
||||
Reference in New Issue
Block a user