serial: got rid of most the warning message with MAKE_BUILD_TYPE=Release
winpr-comm: consolidated _set_handflow()/_get_handflow() winpr-comm: introduced a permissive mode winpr-comm: implementation of IOCTL_SERIAL_WAIT_ON_MASK still in progress
This commit is contained in:
parent
8179affea9
commit
baf4896a38
@ -125,12 +125,18 @@ static void serial_process_irp_create(SERIAL_DEVICE* serial, IRP* irp)
|
||||
|
||||
if (!serial->hComm || (serial->hComm == INVALID_HANDLE_VALUE))
|
||||
{
|
||||
DEBUG_WARN("CreateFile failure: %s last-error: Ox%x\n", serial->device.name, GetLastError());
|
||||
DEBUG_WARN("CreateFile failure: %s last-error: Ox%lX\n", serial->device.name, GetLastError());
|
||||
|
||||
irp->IoStatus = STATUS_UNSUCCESSFUL;
|
||||
goto error_handle;
|
||||
}
|
||||
|
||||
/* FIXME: Appeared to be useful to setup some devices. Guess
|
||||
* the device driver asked to setup some unsupported feature
|
||||
* that were not eventually used. TODO: collecting more
|
||||
* details, a command line argument? */
|
||||
/* _comm_set_permissive(serial->hComm, TRUE); */
|
||||
|
||||
/* FIXME: this stinks, see also IOCTL_SERIAL_PURGE */
|
||||
_comm_set_ReadIrpQueue(serial->hComm, serial->ReadIrpQueue);
|
||||
|
||||
@ -208,7 +214,7 @@ static void serial_process_irp_read(SERIAL_DEVICE* serial, IRP* irp)
|
||||
}
|
||||
|
||||
|
||||
/* MSRDPESP 3.2.5.1.4: If the Offset field is not set to 0, the value MUST be ignored
|
||||
/* MS-RDPESP 3.2.5.1.4: If the Offset field is not set to 0, the value MUST be ignored
|
||||
* assert(Offset == 0);
|
||||
*/
|
||||
|
||||
@ -257,6 +263,7 @@ static void serial_process_irp_read(SERIAL_DEVICE* serial, IRP* irp)
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG_SVC("%lu bytes read from %s", nbRead, serial->device.name);
|
||||
|
||||
error_handle:
|
||||
|
||||
@ -284,7 +291,12 @@ static void serial_process_irp_write(SERIAL_DEVICE* serial, IRP* irp)
|
||||
Stream_Read_UINT64(irp->input, Offset); /* Offset (8 bytes) */
|
||||
Stream_Seek(irp->input, 20); /* Padding (20 bytes) */
|
||||
|
||||
assert(Offset == 0); /* not implemented otherwise */
|
||||
/* MS-RDPESP 3.2.5.1.5: The Offset field is ignored
|
||||
* assert(Offset == 0);
|
||||
*
|
||||
* Using a serial printer, noticed though this field could be
|
||||
* set.
|
||||
*/
|
||||
|
||||
DEBUG_SVC("writing %lu bytes to %s", Length, serial->device.name);
|
||||
|
||||
@ -296,7 +308,6 @@ static void serial_process_irp_write(SERIAL_DEVICE* serial, IRP* irp)
|
||||
else
|
||||
{
|
||||
DEBUG_SVC("write failure to %s, nbWritten=%d, last-error: 0x%0.8x", serial->device.name, nbWritten, GetLastError());
|
||||
|
||||
switch(GetLastError())
|
||||
{
|
||||
case ERROR_INVALID_HANDLE:
|
||||
@ -337,6 +348,7 @@ static void serial_process_irp_write(SERIAL_DEVICE* serial, IRP* irp)
|
||||
irp->Complete(irp);
|
||||
}
|
||||
|
||||
|
||||
static void serial_process_irp_device_control(SERIAL_DEVICE* serial, IRP* irp)
|
||||
{
|
||||
UINT32 IoControlCode;
|
||||
@ -367,7 +379,7 @@ static void serial_process_irp_device_control(SERIAL_DEVICE* serial, IRP* irp)
|
||||
|
||||
Stream_Read(irp->input, InputBuffer, InputBufferLength);
|
||||
|
||||
DEBUG_SVC("CommDeviceIoControl: IoControlCode=[0x%x] %s", IoControlCode, _comm_serial_ioctl_name(IoControlCode));
|
||||
DEBUG_SVC("CommDeviceIoControl: CompletionId=%d, IoControlCode=[0x%x] %s", irp->CompletionId, IoControlCode, _comm_serial_ioctl_name(IoControlCode));
|
||||
|
||||
/* FIXME: CommDeviceIoControl to be replaced by DeviceIoControl() */
|
||||
if (CommDeviceIoControl(serial->hComm, IoControlCode, InputBuffer, InputBufferLength, OutputBuffer, OutputBufferLength, &BytesReturned, NULL))
|
||||
@ -424,6 +436,8 @@ static void serial_process_irp_device_control(SERIAL_DEVICE* serial, IRP* irp)
|
||||
|
||||
error_handle:
|
||||
|
||||
assert(OutputBufferLength == BytesReturned);
|
||||
|
||||
Stream_Write_UINT32(irp->output, BytesReturned); /* OutputBufferLength (4 bytes) */
|
||||
|
||||
if (BytesReturned > 0)
|
||||
@ -541,6 +555,7 @@ static void* serial_thread_func(void* arg)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static void serial_irp_request(DEVICE* device, IRP* irp)
|
||||
{
|
||||
SERIAL_DEVICE* serial = (SERIAL_DEVICE*) device;
|
||||
|
@ -524,6 +524,13 @@ static const _SERIAL_IOCTL_NAME _SERIAL_IOCTL_NAMES[] =
|
||||
*/
|
||||
const char* _comm_serial_ioctl_name(ULONG number);
|
||||
|
||||
/**
|
||||
* FIXME: got a proper function name and place
|
||||
*
|
||||
* permissive mode is disabled by default.
|
||||
*/
|
||||
BOOL _comm_set_permissive(HANDLE hDevice, BOOL permissive);
|
||||
|
||||
void _comm_set_ReadIrpQueue(HANDLE hComm, wMessageQueue* ReadIrpQueue);
|
||||
|
||||
|
||||
|
@ -1029,7 +1029,7 @@ HANDLE CommCreateFileA(LPCSTR lpDeviceName, DWORD dwDesiredAccess, DWORD dwShare
|
||||
|
||||
if (dwDesiredAccess != (GENERIC_READ | GENERIC_WRITE))
|
||||
{
|
||||
DEBUG_WARN("unexpected access to the device: 0x%x", dwDesiredAccess);
|
||||
DEBUG_WARN("unexpected access to the device: 0x%lX", dwDesiredAccess);
|
||||
}
|
||||
|
||||
if (dwShareMode != 0)
|
||||
@ -1043,7 +1043,7 @@ HANDLE CommCreateFileA(LPCSTR lpDeviceName, DWORD dwDesiredAccess, DWORD dwShare
|
||||
|
||||
if (lpSecurityAttributes != NULL)
|
||||
{
|
||||
DEBUG_WARN("unexpected security attributes: 0x%x", lpSecurityAttributes);
|
||||
DEBUG_WARN("unexpected security attributes, nLength=%lu", lpSecurityAttributes->nLength);
|
||||
}
|
||||
|
||||
if (dwCreationDisposition != OPEN_EXISTING)
|
||||
@ -1067,14 +1067,14 @@ HANDLE CommCreateFileA(LPCSTR lpDeviceName, DWORD dwDesiredAccess, DWORD dwShare
|
||||
|
||||
if (!S_ISCHR(deviceStat.st_mode))
|
||||
{
|
||||
DEBUG_WARN("bad device %d", devicePath);
|
||||
DEBUG_WARN("bad device %s", devicePath);
|
||||
SetLastError(ERROR_BAD_DEVICE);
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
if (dwFlagsAndAttributes != 0)
|
||||
{
|
||||
DEBUG_WARN("unexpected flags and attributes: 0x%x", dwFlagsAndAttributes);
|
||||
DEBUG_WARN("unexpected flags and attributes: 0x%lX", dwFlagsAndAttributes);
|
||||
}
|
||||
|
||||
if (hTemplateFile != NULL)
|
||||
@ -1146,7 +1146,7 @@ HANDLE CommCreateFileA(LPCSTR lpDeviceName, DWORD dwDesiredAccess, DWORD dwShare
|
||||
/* upcomingTermios.c_cflag &= ~(CSIZE | PARENB); */
|
||||
/* upcomingTermios.c_cflag |= CS8; */
|
||||
|
||||
/* About missing missing flags recommended by termios(3)
|
||||
/* About missing flags recommended by termios(3):
|
||||
*
|
||||
* IGNBRK and IXON, see: IOCTL_SERIAL_SET_HANDFLOW
|
||||
* CSIZE, PARENB and CS8, see: IOCTL_SERIAL_SET_LINE_CONTROL
|
||||
|
@ -46,6 +46,17 @@ struct winpr_comm
|
||||
WINPR_HANDLE_DEF();
|
||||
|
||||
int fd;
|
||||
|
||||
/* permissive mode on errors if TRUE (default is FALSE).
|
||||
*
|
||||
* Since not all features are supported, some devices and applications
|
||||
* can still be functional on such errors.
|
||||
*
|
||||
* TODO: command line switch or getting rid of it.
|
||||
*/
|
||||
BOOL permissive;
|
||||
|
||||
|
||||
REMOTE_SERIAL_DRIVER_ID remoteSerialDriverId;
|
||||
|
||||
wMessageQueue* ReadIrpQueue; /* considered as optional since it is
|
||||
@ -55,7 +66,7 @@ struct winpr_comm
|
||||
COMMTIMEOUTS timeouts;
|
||||
|
||||
struct serial_icounter_struct counters;
|
||||
ULONG waitMask;
|
||||
ULONG waitMask; /* TMP: to be renamed EventMask */
|
||||
ULONG pendingEvents;
|
||||
|
||||
/* NB: CloseHandle() has to free resources */
|
||||
|
@ -34,6 +34,27 @@
|
||||
|
||||
#include "comm.h"
|
||||
|
||||
BOOL _comm_set_permissive(HANDLE hDevice, BOOL permissive)
|
||||
{
|
||||
WINPR_COMM* pComm = (WINPR_COMM*) hDevice;
|
||||
|
||||
if (hDevice == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_HANDLE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!pComm || pComm->Type != HANDLE_TYPE_COMM || !pComm->fd )
|
||||
{
|
||||
SetLastError(ERROR_INVALID_HANDLE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pComm->permissive = permissive;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/* Computes Tmax in deciseconds (m and Tcare in milliseconds) */
|
||||
static UCHAR _tmax(DWORD N, ULONG m, ULONG Tc)
|
||||
{
|
||||
@ -200,10 +221,10 @@ BOOL CommReadFile(HANDLE hDevice, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
|
||||
|
||||
if (nbRead < 0)
|
||||
{
|
||||
DEBUG_WARN("CommReadFile failed, ReadIntervalTimeout=%d, ReadTotalTimeoutMultiplier=%d, ReadTotalTimeoutConstant=%d VMIN=%d, VTIME=%d",
|
||||
DEBUG_WARN("CommReadFile failed, ReadIntervalTimeout=%lu, ReadTotalTimeoutMultiplier=%lu, ReadTotalTimeoutConstant=%lu VMIN=%u, VTIME=%u",
|
||||
pTimeouts->ReadIntervalTimeout, pTimeouts->ReadTotalTimeoutMultiplier, pTimeouts->ReadTotalTimeoutConstant,
|
||||
currentTermios.c_cc[VMIN], currentTermios.c_cc[VTIME]);
|
||||
DEBUG_WARN("CommReadFile failed, nNumberOfBytesToRead=%d, errno=[%d] %s", nNumberOfBytesToRead, errno, strerror(errno));
|
||||
DEBUG_WARN("CommReadFile failed, nNumberOfBytesToRead=%lu, errno=[%d] %s", nNumberOfBytesToRead, errno, strerror(errno));
|
||||
|
||||
switch (errno)
|
||||
{
|
||||
@ -287,7 +308,7 @@ BOOL CommWriteFile(HANDLE hDevice, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite
|
||||
|
||||
if (nbWritten < 0)
|
||||
{
|
||||
DEBUG_WARN("CommWriteFile failed after %d bytes written, errno=[%d] %s\n", *lpNumberOfBytesWritten, errno, strerror(errno));
|
||||
DEBUG_WARN("CommWriteFile failed after %lu bytes written, errno=[%d] %s\n", *lpNumberOfBytesWritten, errno, strerror(errno));
|
||||
|
||||
switch (errno)
|
||||
{
|
||||
|
@ -72,22 +72,9 @@ const char* _comm_serial_ioctl_name(ULONG number)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* FIXME: to be used through winpr-io's DeviceIoControl
|
||||
*
|
||||
* Any previous error as returned by GetLastError is cleared.
|
||||
*
|
||||
* ERRORS:
|
||||
* ERROR_INVALID_HANDLE
|
||||
* ERROR_INVALID_PARAMETER
|
||||
* ERROR_NOT_SUPPORTED lpOverlapped is not supported
|
||||
* ERROR_INSUFFICIENT_BUFFER
|
||||
* ERROR_CALL_NOT_IMPLEMENTED unimplemented ioctl
|
||||
*/
|
||||
BOOL CommDeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize,
|
||||
LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped)
|
||||
static BOOL _CommDeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize,
|
||||
LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped)
|
||||
{
|
||||
|
||||
WINPR_COMM* pComm = (WINPR_COMM*) hDevice;
|
||||
REMOTE_SERIAL_DRIVER* pRemoteSerialDriver = NULL;
|
||||
|
||||
@ -151,6 +138,17 @@ BOOL CommDeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode, LPVOID lpInBuffe
|
||||
|
||||
switch (dwIoControlCode)
|
||||
{
|
||||
case 0x220034:
|
||||
case 0X1B006C:
|
||||
DEBUG_WARN("Undocumented IoControlCode: 0X%X", dwIoControlCode);
|
||||
*lpBytesReturned = nOutBufferSize; /* an empty OutputBuffer will be returned */
|
||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
||||
if (pComm->permissive)
|
||||
return FALSE;
|
||||
else
|
||||
return TRUE;
|
||||
|
||||
break;
|
||||
case IOCTL_SERIAL_SET_BAUD_RATE:
|
||||
{
|
||||
if (pRemoteSerialDriver->set_baud_rate)
|
||||
@ -467,7 +465,10 @@ BOOL CommDeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode, LPVOID lpInBuffe
|
||||
}
|
||||
|
||||
if (!pRemoteSerialDriver->wait_on_mask(pComm, pOutputMask))
|
||||
{
|
||||
*lpBytesReturned = sizeof(ULONG); /* TMP: TODO: all lpBytesReturned values to be reviewed on error */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*lpBytesReturned = sizeof(ULONG);
|
||||
return TRUE;
|
||||
@ -511,7 +512,7 @@ BOOL CommDeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode, LPVOID lpInBuffe
|
||||
|
||||
}
|
||||
|
||||
DEBUG_WARN(_T("unsupported IoControlCode=[Ox%0.8x] %s (remote serial driver: %s)"),
|
||||
DEBUG_WARN(_T("unsupported IoControlCode=[0x%lX] %s (remote serial driver: %s)"),
|
||||
dwIoControlCode, _comm_serial_ioctl_name(dwIoControlCode), pRemoteSerialDriver->name);
|
||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
||||
return FALSE;
|
||||
@ -519,6 +520,53 @@ BOOL CommDeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode, LPVOID lpInBuffe
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* FIXME: to be used through winpr-io's DeviceIoControl
|
||||
*
|
||||
* Any previous error as returned by GetLastError is cleared.
|
||||
*
|
||||
* ERRORS:
|
||||
* ERROR_INVALID_HANDLE
|
||||
* ERROR_INVALID_PARAMETER
|
||||
* ERROR_NOT_SUPPORTED lpOverlapped is not supported
|
||||
* ERROR_INSUFFICIENT_BUFFER
|
||||
* ERROR_CALL_NOT_IMPLEMENTED unimplemented ioctl
|
||||
*/
|
||||
BOOL CommDeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize,
|
||||
LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped)
|
||||
{
|
||||
WINPR_COMM* pComm = (WINPR_COMM*) hDevice;
|
||||
BOOL result;
|
||||
|
||||
if (hDevice == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_HANDLE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!pComm || pComm->Type != HANDLE_TYPE_COMM || !pComm->fd )
|
||||
{
|
||||
SetLastError(ERROR_INVALID_HANDLE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
result = _CommDeviceIoControl(hDevice, dwIoControlCode, lpInBuffer, nInBufferSize,
|
||||
lpOutBuffer, nOutBufferSize, lpBytesReturned, lpOverlapped);
|
||||
|
||||
if (pComm->permissive)
|
||||
{
|
||||
if (!result)
|
||||
{
|
||||
DEBUG_WARN("[permissive]: whereas it failed, made to succeed IoControlCode=[0x%lX] %s, last-error: 0x%lX",
|
||||
dwIoControlCode, _comm_serial_ioctl_name(dwIoControlCode), GetLastError());
|
||||
}
|
||||
|
||||
return TRUE; /* always! */
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int _comm_ioctl_tcsetattr(int fd, int optional_actions, const struct termios *termios_p)
|
||||
{
|
||||
int result;
|
||||
|
@ -81,7 +81,7 @@ static BOOL _set_wait_mask(WINPR_COMM *pComm, const ULONG *pWaitMask)
|
||||
|
||||
if (possibleMask != *pWaitMask)
|
||||
{
|
||||
DEBUG_WARN("Not all wait events supported (SerCx2.sys), requested events= 0X%0.4X, possible events= 0X%0.4X", *pWaitMask, possibleMask);
|
||||
DEBUG_WARN("Not all wait events supported (SerCx2.sys), requested events= 0X%lX, possible events= 0X%lX", *pWaitMask, possibleMask);
|
||||
|
||||
/* FIXME: shall we really set the possibleMask and return FALSE? */
|
||||
pComm->waitMask = possibleMask;
|
||||
|
@ -180,7 +180,7 @@ static BOOL _set_baud_rate(WINPR_COMM *pComm, const SERIAL_BAUD_RATE *pBaudRate)
|
||||
newSpeed = _SERCX_SYS_BAUD_TABLE[i][0];
|
||||
if (cfsetspeed(&futureState, newSpeed) < 0)
|
||||
{
|
||||
DEBUG_WARN("failed to set speed 0x%x (%d)", newSpeed, pBaudRate->BaudRate);
|
||||
DEBUG_WARN("failed to set speed 0x%x (%lu)", newSpeed, pBaudRate->BaudRate);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -188,7 +188,7 @@ static BOOL _set_baud_rate(WINPR_COMM *pComm, const SERIAL_BAUD_RATE *pBaudRate)
|
||||
|
||||
if (_comm_ioctl_tcsetattr(pComm->fd, TCSANOW, &futureState) < 0)
|
||||
{
|
||||
DEBUG_WARN("_comm_ioctl_tcsetattr failure: last-error: 0x%0.8x", GetLastError());
|
||||
DEBUG_WARN("_comm_ioctl_tcsetattr failure: last-error: 0x%lX", GetLastError());
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -196,7 +196,7 @@ static BOOL _set_baud_rate(WINPR_COMM *pComm, const SERIAL_BAUD_RATE *pBaudRate)
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG_WARN("could not find a matching speed for the baud rate %d", pBaudRate->BaudRate);
|
||||
DEBUG_WARN("could not find a matching speed for the baud rate %lu", pBaudRate->BaudRate);
|
||||
SetLastError(ERROR_INVALID_DATA);
|
||||
return FALSE;
|
||||
}
|
||||
@ -231,264 +231,102 @@ static BOOL _get_baud_rate(WINPR_COMM *pComm, SERIAL_BAUD_RATE *pBaudRate)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* hard-coded in N_TTY */
|
||||
#define TTY_THRESHOLD_THROTTLE 128 /* now based on remaining room */
|
||||
#define TTY_THRESHOLD_UNTHROTTLE 128
|
||||
|
||||
/* FIXME: mostly copied/pasted from comm_serial_sys.c, better share this code */
|
||||
static BOOL _set_handflow(WINPR_COMM *pComm, const SERIAL_HANDFLOW *pHandflow)
|
||||
{
|
||||
SERIAL_HANDFLOW SerCxHandflow;
|
||||
BOOL result = TRUE;
|
||||
struct termios upcomingTermios;
|
||||
REMOTE_SERIAL_DRIVER* pSerialSys = SerialSys_s();
|
||||
|
||||
/* logical XOR */
|
||||
if ((!(pHandflow->ControlHandShake & SERIAL_DTR_CONTROL) && (pHandflow->FlowReplace & SERIAL_RTS_CONTROL)) ||
|
||||
((pHandflow->ControlHandShake & SERIAL_DTR_CONTROL) && !(pHandflow->FlowReplace & SERIAL_RTS_CONTROL)))
|
||||
{
|
||||
DEBUG_WARN("SERIAL_DTR_CONTROL cannot be different SERIAL_RTS_CONTROL, HUPCL will be set according SERIAL_RTS_CONTROL.");
|
||||
result = FALSE; /* but keep on */
|
||||
}
|
||||
memcpy(&SerCxHandflow, pHandflow, sizeof(SERIAL_HANDFLOW));
|
||||
|
||||
ZeroMemory(&upcomingTermios, sizeof(struct termios));
|
||||
if (tcgetattr(pComm->fd, &upcomingTermios) < 0)
|
||||
{
|
||||
SetLastError(ERROR_IO_DEVICE);
|
||||
return FALSE;
|
||||
}
|
||||
/* filter out unsupported bits by SerCx.sys
|
||||
*
|
||||
* http://msdn.microsoft.com/en-us/library/windows/hardware/jj680685%28v=vs.85%29.aspx
|
||||
*/
|
||||
|
||||
/* ControlHandShake */
|
||||
SerCxHandflow.ControlHandShake = pHandflow->ControlHandShake & (SERIAL_DTR_CONTROL | SERIAL_DTR_HANDSHAKE | SERIAL_CTS_HANDSHAKE | SERIAL_DSR_HANDSHAKE);
|
||||
SerCxHandflow.FlowReplace = pHandflow->FlowReplace & (SERIAL_RTS_CONTROL | SERIAL_RTS_HANDSHAKE);
|
||||
|
||||
if (pHandflow->ControlHandShake & SERIAL_DTR_CONTROL)
|
||||
if (SerCxHandflow.ControlHandShake != pHandflow->ControlHandShake)
|
||||
{
|
||||
upcomingTermios.c_cflag |= HUPCL;
|
||||
}
|
||||
else
|
||||
{
|
||||
upcomingTermios.c_cflag &= ~HUPCL;
|
||||
if (pHandflow->ControlHandShake & SERIAL_DCD_HANDSHAKE)
|
||||
{
|
||||
DEBUG_WARN("SERIAL_DCD_HANDSHAKE not supposed to be implemented by SerCx.sys");
|
||||
}
|
||||
|
||||
/* FIXME: is the DTR line also needs to be forced to a disable state? */
|
||||
}
|
||||
if (pHandflow->ControlHandShake & SERIAL_DSR_SENSITIVITY)
|
||||
{
|
||||
DEBUG_WARN("SERIAL_DSR_SENSITIVITY not supposed to be implemented by SerCx.sys");
|
||||
}
|
||||
|
||||
if (pHandflow->ControlHandShake & SERIAL_DTR_HANDSHAKE)
|
||||
{
|
||||
/* DTR/DSR flow control not supported on Linux */
|
||||
DEBUG_WARN("Attempt to use the unsupported SERIAL_DTR_HANDSHAKE feature.");
|
||||
SetLastError(ERROR_NOT_SUPPORTED);
|
||||
result = FALSE; /* but keep on */
|
||||
}
|
||||
if (pHandflow->ControlHandShake & SERIAL_ERROR_ABORT)
|
||||
{
|
||||
DEBUG_WARN("SERIAL_ERROR_ABORT not supposed to be implemented by SerCx.sys");
|
||||
}
|
||||
|
||||
if (pHandflow->ControlHandShake & SERIAL_CTS_HANDSHAKE)
|
||||
{
|
||||
upcomingTermios.c_cflag |= CRTSCTS;
|
||||
}
|
||||
else
|
||||
{
|
||||
upcomingTermios.c_cflag &= ~CRTSCTS;
|
||||
}
|
||||
|
||||
if (pHandflow->ControlHandShake & SERIAL_DSR_HANDSHAKE)
|
||||
{
|
||||
/* DTR/DSR flow control not supported on Linux */
|
||||
DEBUG_WARN("Attempt to use the unsupported SERIAL_DSR_HANDSHAKE feature.");
|
||||
SetLastError(ERROR_NOT_SUPPORTED);
|
||||
result = FALSE; /* but keep on */
|
||||
}
|
||||
|
||||
/* SERIAL_DCD_HANDSHAKE unsupported by SerCx */
|
||||
if (pHandflow->ControlHandShake & SERIAL_DCD_HANDSHAKE)
|
||||
{
|
||||
DEBUG_WARN("Attempt to set SERIAL_DCD_HANDSHAKE (not implemented)");
|
||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
||||
result = FALSE; /* but keep on */
|
||||
result = FALSE;
|
||||
}
|
||||
|
||||
/* SERIAL_DSR_SENSITIVITY unsupported by SerCx */
|
||||
if (pHandflow->ControlHandShake & SERIAL_DSR_SENSITIVITY)
|
||||
if (SerCxHandflow.FlowReplace != pHandflow->FlowReplace)
|
||||
{
|
||||
DEBUG_WARN("Attempt to set SERIAL_DSR_SENSITIVITY (not implemented)");
|
||||
if (pHandflow->ControlHandShake & SERIAL_AUTO_TRANSMIT)
|
||||
{
|
||||
DEBUG_WARN("SERIAL_AUTO_TRANSMIT not supposed to be implemented by SerCx.sys");
|
||||
}
|
||||
|
||||
if (pHandflow->ControlHandShake & SERIAL_AUTO_RECEIVE)
|
||||
{
|
||||
DEBUG_WARN("SERIAL_AUTO_RECEIVE not supposed to be implemented by SerCx.sys");
|
||||
}
|
||||
|
||||
if (pHandflow->ControlHandShake & SERIAL_ERROR_CHAR)
|
||||
{
|
||||
DEBUG_WARN("SERIAL_ERROR_CHAR not supposed to be implemented by SerCx.sys");
|
||||
}
|
||||
|
||||
if (pHandflow->ControlHandShake & SERIAL_NULL_STRIPPING)
|
||||
{
|
||||
DEBUG_WARN("SERIAL_NULL_STRIPPING not supposed to be implemented by SerCx.sys");
|
||||
}
|
||||
|
||||
if (pHandflow->ControlHandShake & SERIAL_BREAK_CHAR)
|
||||
{
|
||||
DEBUG_WARN("SERIAL_BREAK_CHAR not supposed to be implemented by SerCx.sys");
|
||||
}
|
||||
|
||||
if (pHandflow->ControlHandShake & SERIAL_XOFF_CONTINUE)
|
||||
{
|
||||
DEBUG_WARN("SERIAL_XOFF_CONTINUE not supposed to be implemented by SerCx.sys");
|
||||
}
|
||||
|
||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
||||
result = FALSE; /* but keep on */
|
||||
}
|
||||
|
||||
/* SERIAL_ERROR_ABORT unsupported by SerCx */
|
||||
if (pHandflow->ControlHandShake & SERIAL_ERROR_ABORT)
|
||||
{
|
||||
DEBUG_WARN("Attempt to set SERIAL_ERROR_ABORT (not implemented)");
|
||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
||||
result = FALSE; /* but keep on */
|
||||
}
|
||||
|
||||
|
||||
/* FlowReplace */
|
||||
|
||||
/* SERIAL_AUTO_TRANSMIT unsupported by SerCx */
|
||||
if (pHandflow->FlowReplace & SERIAL_AUTO_TRANSMIT)
|
||||
{
|
||||
DEBUG_WARN("Attempt to set SERIAL_AUTO_TRANSMIT (not implemented)");
|
||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
||||
result = FALSE; /* but keep on */
|
||||
}
|
||||
|
||||
|
||||
/* SERIAL_AUTO_RECEIVE unsupported by SerCx */
|
||||
if (pHandflow->FlowReplace & SERIAL_AUTO_RECEIVE)
|
||||
{
|
||||
DEBUG_WARN("Attempt to set SERIAL_AUTO_RECEIVE (not implemented)");
|
||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
||||
result = FALSE; /* but keep on */
|
||||
}
|
||||
|
||||
/* SERIAL_ERROR_CHAR unsupported by SerCx */
|
||||
if (pHandflow->FlowReplace & SERIAL_ERROR_CHAR)
|
||||
{
|
||||
DEBUG_WARN("Attempt to set SERIAL_ERROR_CHAR (not implemented)");
|
||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
||||
result = FALSE; /* but keep on */
|
||||
}
|
||||
|
||||
/* SERIAL_NULL_STRIPPING unsupported by SerCx */
|
||||
if (pHandflow->FlowReplace & SERIAL_NULL_STRIPPING)
|
||||
{
|
||||
DEBUG_WARN("Attempt to set SERIAL_NULL_STRIPPING (not implemented)");
|
||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
||||
result = FALSE; /* but keep on */
|
||||
}
|
||||
|
||||
/* SERIAL_BREAK_CHAR unsupported by SerCx */
|
||||
if (pHandflow->FlowReplace & SERIAL_BREAK_CHAR)
|
||||
{
|
||||
DEBUG_WARN("Attempt to set SERIAL_BREAK_CHAR (not implemented)");
|
||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
||||
result = FALSE; /* but keep on */
|
||||
}
|
||||
|
||||
if (pHandflow->FlowReplace & SERIAL_RTS_CONTROL)
|
||||
{
|
||||
upcomingTermios.c_cflag |= HUPCL;
|
||||
}
|
||||
else
|
||||
{
|
||||
upcomingTermios.c_cflag &= ~HUPCL;
|
||||
|
||||
/* FIXME: is the RTS line also needs to be forced to a disable state? */
|
||||
}
|
||||
|
||||
if (pHandflow->FlowReplace & SERIAL_RTS_HANDSHAKE)
|
||||
{
|
||||
upcomingTermios.c_cflag |= CRTSCTS;
|
||||
}
|
||||
else
|
||||
{
|
||||
upcomingTermios.c_cflag &= ~CRTSCTS;
|
||||
}
|
||||
|
||||
/* SERIAL_XOFF_CONTINUE unsupported by SerCx */
|
||||
if (pHandflow->FlowReplace & SERIAL_XOFF_CONTINUE)
|
||||
{
|
||||
DEBUG_WARN("Attempt to set SERIAL_XOFF_CONTINUE (not implemented)");
|
||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
||||
result = FALSE; /* but keep on */
|
||||
}
|
||||
|
||||
|
||||
/* XonLimit */
|
||||
|
||||
// FIXME: could be implemented during read/write I/O
|
||||
if (pHandflow->XonLimit != TTY_THRESHOLD_UNTHROTTLE)
|
||||
{
|
||||
DEBUG_WARN("Attempt to set XonLimit with an unsupported value: %d", pHandflow->XonLimit);
|
||||
SetLastError(ERROR_NOT_SUPPORTED);
|
||||
result = FALSE; /* but keep on */
|
||||
}
|
||||
|
||||
/* XoffChar */
|
||||
|
||||
// FIXME: could be implemented during read/write I/O
|
||||
if (pHandflow->XoffLimit != TTY_THRESHOLD_THROTTLE)
|
||||
{
|
||||
DEBUG_WARN("Attempt to set XoffLimit with an unsupported value: %d", pHandflow->XoffLimit);
|
||||
SetLastError(ERROR_NOT_SUPPORTED);
|
||||
result = FALSE; /* but keep on */
|
||||
result = FALSE;
|
||||
}
|
||||
|
||||
|
||||
if (_comm_ioctl_tcsetattr(pComm->fd, TCSANOW, &upcomingTermios) < 0)
|
||||
{
|
||||
DEBUG_WARN("_comm_ioctl_tcsetattr failure: last-error: 0x0.8x", GetLastError());
|
||||
if (!pSerialSys->set_handflow(pComm, &SerCxHandflow))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/* FIXME: mostly copied/pasted from comm_serial_sys.c, better share this code */
|
||||
static BOOL _get_handflow(WINPR_COMM *pComm, SERIAL_HANDFLOW *pHandflow)
|
||||
{
|
||||
struct termios currentTermios;
|
||||
BOOL result;
|
||||
REMOTE_SERIAL_DRIVER* pSerialSys = SerialSys_s();
|
||||
|
||||
ZeroMemory(¤tTermios, sizeof(struct termios));
|
||||
if (tcgetattr(pComm->fd, ¤tTermios) < 0)
|
||||
{
|
||||
SetLastError(ERROR_IO_DEVICE);
|
||||
return FALSE;
|
||||
}
|
||||
result = pSerialSys->get_handflow(pComm, pHandflow);
|
||||
|
||||
/* filter out unsupported bits by SerCx.sys
|
||||
*
|
||||
* http://msdn.microsoft.com/en-us/library/windows/hardware/jj680685%28v=vs.85%29.aspx
|
||||
*/
|
||||
|
||||
/* ControlHandShake */
|
||||
pHandflow->ControlHandShake = pHandflow->ControlHandShake & (SERIAL_DTR_CONTROL | SERIAL_DTR_HANDSHAKE | SERIAL_CTS_HANDSHAKE | SERIAL_DSR_HANDSHAKE);
|
||||
pHandflow->FlowReplace = pHandflow->FlowReplace & (SERIAL_RTS_CONTROL | SERIAL_RTS_HANDSHAKE);
|
||||
|
||||
pHandflow->ControlHandShake = 0;
|
||||
|
||||
if (currentTermios.c_cflag & HUPCL)
|
||||
pHandflow->ControlHandShake |= SERIAL_DTR_CONTROL;
|
||||
|
||||
/* SERIAL_DTR_HANDSHAKE unsupported */
|
||||
|
||||
if (currentTermios.c_cflag & CRTSCTS)
|
||||
pHandflow->ControlHandShake |= SERIAL_CTS_HANDSHAKE;
|
||||
|
||||
/* SERIAL_DSR_HANDSHAKE unsupported */
|
||||
|
||||
/* SERIAL_DCD_HANDSHAKE unsupported by SerCx */
|
||||
|
||||
/* SERIAL_DSR_SENSITIVITY unsupported by SerCx */
|
||||
|
||||
/* SERIAL_ERROR_ABORT unsupported by SerCx */
|
||||
|
||||
|
||||
/* FlowReplace */
|
||||
|
||||
pHandflow->FlowReplace = 0;
|
||||
|
||||
/* SERIAL_AUTO_TRANSMIT unsupported by SerCx */
|
||||
|
||||
/* SERIAL_AUTO_RECEIVE unsupported by SerCx */
|
||||
|
||||
/* SERIAL_ERROR_CHAR unsupported by SerCx */
|
||||
|
||||
/* SERIAL_NULL_STRIPPING unsupported by SerCx */
|
||||
|
||||
/* SERIAL_BREAK_CHAR unsupported by SerCx */
|
||||
|
||||
if (currentTermios.c_cflag & HUPCL)
|
||||
pHandflow->FlowReplace |= SERIAL_RTS_CONTROL;
|
||||
|
||||
if (currentTermios.c_cflag & CRTSCTS)
|
||||
pHandflow->FlowReplace |= SERIAL_RTS_HANDSHAKE;
|
||||
|
||||
/* SERIAL_XOFF_CONTINUE unsupported by SerCx */
|
||||
|
||||
|
||||
/* XonLimit */
|
||||
|
||||
pHandflow->XonLimit = TTY_THRESHOLD_UNTHROTTLE;
|
||||
|
||||
|
||||
/* XoffLimit */
|
||||
|
||||
pHandflow->XoffLimit = TTY_THRESHOLD_THROTTLE;
|
||||
|
||||
return TRUE;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@ -518,7 +356,7 @@ static BOOL _set_wait_mask(WINPR_COMM *pComm, const ULONG *pWaitMask)
|
||||
|
||||
if (possibleMask != *pWaitMask)
|
||||
{
|
||||
DEBUG_WARN("Not all wait events supported (SerCx.sys), requested events= 0X%0.4X, possible events= 0X%0.4X", *pWaitMask, possibleMask);
|
||||
DEBUG_WARN("Not all wait events supported (SerCx.sys), requested events= 0x%lX, possible events= 0x%lX", *pWaitMask, possibleMask);
|
||||
|
||||
/* FIXME: shall we really set the possibleMask and return FALSE? */
|
||||
pComm->waitMask = possibleMask;
|
||||
|
@ -236,13 +236,13 @@ static BOOL _set_baud_rate(WINPR_COMM *pComm, const SERIAL_BAUD_RATE *pBaudRate)
|
||||
newSpeed = _SERIAL_SYS_BAUD_TABLE[i][0];
|
||||
if (cfsetspeed(&upcomingTermios, newSpeed) < 0)
|
||||
{
|
||||
DEBUG_WARN("failed to set speed %d (%d)", newSpeed, pBaudRate->BaudRate);
|
||||
DEBUG_WARN("failed to set speed %u (%lu)", newSpeed, pBaudRate->BaudRate);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (_comm_ioctl_tcsetattr(pComm->fd, TCSANOW, &upcomingTermios) < 0)
|
||||
{
|
||||
DEBUG_WARN("_comm_ioctl_tcsetattr failure: last-error: 0x0.8x", GetLastError());
|
||||
DEBUG_WARN("_comm_ioctl_tcsetattr failure: last-error: 0x%lX", GetLastError());
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -250,7 +250,7 @@ static BOOL _set_baud_rate(WINPR_COMM *pComm, const SERIAL_BAUD_RATE *pBaudRate)
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG_WARN("could not find a matching speed for the baud rate %d", pBaudRate->BaudRate);
|
||||
DEBUG_WARN("could not find a matching speed for the baud rate %lu", pBaudRate->BaudRate);
|
||||
SetLastError(ERROR_INVALID_DATA);
|
||||
return FALSE;
|
||||
}
|
||||
@ -352,7 +352,7 @@ static BOOL _set_serial_chars(WINPR_COMM *pComm, const SERIAL_CHARS *pSerialChar
|
||||
result = FALSE; /* but keep on */
|
||||
}
|
||||
|
||||
/* TMP: FIXME: Didn't find anything similar yet on Linux */
|
||||
/* TMP: FIXME: Didn't find anything similar yet on Linux. What about ISIG? */
|
||||
if (pSerialChars->EventChar != '\0')
|
||||
{
|
||||
DEBUG_WARN("EventChar='%c' (0x%x) cannot be set\n", pSerialChars->EventChar, pSerialChars->EventChar);
|
||||
@ -367,7 +367,7 @@ static BOOL _set_serial_chars(WINPR_COMM *pComm, const SERIAL_CHARS *pSerialChar
|
||||
|
||||
if (_comm_ioctl_tcsetattr(pComm->fd, TCSANOW, &upcomingTermios) < 0)
|
||||
{
|
||||
DEBUG_WARN("_comm_ioctl_tcsetattr failure: last-error: 0x0.8x", GetLastError());
|
||||
DEBUG_WARN("_comm_ioctl_tcsetattr failure: last-error: 0x%lX", GetLastError());
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -512,7 +512,7 @@ static BOOL _set_line_control(WINPR_COMM *pComm, const SERIAL_LINE_CONTROL *pLin
|
||||
|
||||
if (_comm_ioctl_tcsetattr(pComm->fd, TCSANOW, &upcomingTermios) < 0)
|
||||
{
|
||||
DEBUG_WARN("_comm_ioctl_tcsetattr failure: last-error: 0x0.8x", GetLastError());
|
||||
DEBUG_WARN("_comm_ioctl_tcsetattr failure: last-error: 0x%lX", GetLastError());
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -572,15 +572,6 @@ static BOOL _set_handflow(WINPR_COMM *pComm, const SERIAL_HANDFLOW *pHandflow)
|
||||
BOOL result = TRUE;
|
||||
struct termios upcomingTermios;
|
||||
|
||||
/* logical XOR */
|
||||
if ((!(pHandflow->ControlHandShake & SERIAL_DTR_CONTROL) && (pHandflow->FlowReplace & SERIAL_RTS_CONTROL)) ||
|
||||
((pHandflow->ControlHandShake & SERIAL_DTR_CONTROL) && !(pHandflow->FlowReplace & SERIAL_RTS_CONTROL)))
|
||||
{
|
||||
DEBUG_WARN("SERIAL_DTR_CONTROL cannot be different SERIAL_RTS_CONTROL, HUPCL will be set according SERIAL_RTS_CONTROL.");
|
||||
result = FALSE; /* but keep on */
|
||||
}
|
||||
|
||||
|
||||
ZeroMemory(&upcomingTermios, sizeof(struct termios));
|
||||
if (tcgetattr(pComm->fd, &upcomingTermios) < 0)
|
||||
{
|
||||
@ -588,9 +579,18 @@ static BOOL _set_handflow(WINPR_COMM *pComm, const SERIAL_HANDFLOW *pHandflow)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* ControlHandShake */
|
||||
/* HUPCL */
|
||||
|
||||
if (pHandflow->ControlHandShake & SERIAL_DTR_CONTROL)
|
||||
/* logical XOR */
|
||||
if ((!(pHandflow->ControlHandShake & SERIAL_DTR_CONTROL) && (pHandflow->FlowReplace & SERIAL_RTS_CONTROL)) ||
|
||||
((pHandflow->ControlHandShake & SERIAL_DTR_CONTROL) && !(pHandflow->FlowReplace & SERIAL_RTS_CONTROL)))
|
||||
{
|
||||
DEBUG_WARN("SERIAL_DTR_CONTROL:%s and SERIAL_RTS_CONTROL:%s cannot be different, HUPCL will be set since it is claimed for one of the both lines.",
|
||||
(pHandflow->ControlHandShake & SERIAL_DTR_CONTROL) ? "ON" : "OFF",
|
||||
(pHandflow->FlowReplace & SERIAL_RTS_CONTROL) ? "ON" : "OFF");
|
||||
}
|
||||
|
||||
if ((pHandflow->ControlHandShake & SERIAL_DTR_CONTROL) || (pHandflow->FlowReplace & SERIAL_RTS_CONTROL))
|
||||
{
|
||||
upcomingTermios.c_cflag |= HUPCL;
|
||||
}
|
||||
@ -598,9 +598,34 @@ static BOOL _set_handflow(WINPR_COMM *pComm, const SERIAL_HANDFLOW *pHandflow)
|
||||
{
|
||||
upcomingTermios.c_cflag &= ~HUPCL;
|
||||
|
||||
/* FIXME: is the DTR line also needs to be forced to a disable state? */
|
||||
/* FIXME: is the DTR line also needs to be forced to a disable state according SERIAL_DTR_CONTROL? */
|
||||
/* FIXME: is the RTS line also needs to be forced to a disable state according SERIAL_RTS_CONTROL? */
|
||||
}
|
||||
|
||||
|
||||
/* CRTSCTS */
|
||||
|
||||
/* logical XOR */
|
||||
if ((!(pHandflow->ControlHandShake & SERIAL_CTS_HANDSHAKE) && (pHandflow->FlowReplace & SERIAL_RTS_HANDSHAKE)) ||
|
||||
((pHandflow->ControlHandShake & SERIAL_CTS_HANDSHAKE) && !(pHandflow->FlowReplace & SERIAL_RTS_HANDSHAKE)))
|
||||
{
|
||||
DEBUG_WARN("SERIAL_CTS_HANDSHAKE:%s and SERIAL_RTS_HANDSHAKE:%s cannot be different, CRTSCTS will be set since it is claimed for one of the both lines.",
|
||||
(pHandflow->ControlHandShake & SERIAL_CTS_HANDSHAKE) ? "ON" : "OFF",
|
||||
(pHandflow->FlowReplace & SERIAL_RTS_HANDSHAKE) ? "ON" : "OFF");
|
||||
}
|
||||
|
||||
if ((pHandflow->ControlHandShake & SERIAL_CTS_HANDSHAKE) || (pHandflow->FlowReplace & SERIAL_RTS_HANDSHAKE))
|
||||
{
|
||||
upcomingTermios.c_cflag |= CRTSCTS;
|
||||
}
|
||||
else
|
||||
{
|
||||
upcomingTermios.c_cflag &= ~CRTSCTS;
|
||||
}
|
||||
|
||||
|
||||
/* ControlHandShake */
|
||||
|
||||
if (pHandflow->ControlHandShake & SERIAL_DTR_HANDSHAKE)
|
||||
{
|
||||
/* DTR/DSR flow control not supported on Linux */
|
||||
@ -610,15 +635,6 @@ static BOOL _set_handflow(WINPR_COMM *pComm, const SERIAL_HANDFLOW *pHandflow)
|
||||
}
|
||||
|
||||
|
||||
if (pHandflow->ControlHandShake & SERIAL_CTS_HANDSHAKE)
|
||||
{
|
||||
upcomingTermios.c_cflag |= CRTSCTS;
|
||||
}
|
||||
else
|
||||
{
|
||||
upcomingTermios.c_cflag &= ~CRTSCTS;
|
||||
}
|
||||
|
||||
if (pHandflow->ControlHandShake & SERIAL_DSR_HANDSHAKE)
|
||||
{
|
||||
/* DTR/DSR flow control not supported on Linux */
|
||||
@ -673,12 +689,10 @@ static BOOL _set_handflow(WINPR_COMM *pComm, const SERIAL_HANDFLOW *pHandflow)
|
||||
upcomingTermios.c_iflag &= ~IXOFF;
|
||||
}
|
||||
|
||||
// TMP: FIXME: could be implemented during read/write I/O
|
||||
// TMP: FIXME: could be implemented during read/write I/O, as of today ErrorChar is necessary '\0'
|
||||
if (pHandflow->FlowReplace & SERIAL_ERROR_CHAR)
|
||||
{
|
||||
DEBUG_WARN("Attempt to use the unsupported SERIAL_ERROR_CHAR feature. A character with a parity error or framing error will be read as \0");
|
||||
|
||||
/* errors will be replaced by the character '\0' */
|
||||
/* errors will be replaced by the character '\0'. */
|
||||
upcomingTermios.c_iflag &= ~IGNPAR;
|
||||
}
|
||||
else
|
||||
@ -703,27 +717,6 @@ static BOOL _set_handflow(WINPR_COMM *pComm, const SERIAL_HANDFLOW *pHandflow)
|
||||
result = FALSE; /* but keep on */
|
||||
}
|
||||
|
||||
if (pHandflow->FlowReplace & SERIAL_RTS_CONTROL)
|
||||
{
|
||||
upcomingTermios.c_cflag |= HUPCL;
|
||||
}
|
||||
else
|
||||
{
|
||||
upcomingTermios.c_cflag &= ~HUPCL;
|
||||
|
||||
/* FIXME: is the RTS line also needs to be forced to a disable state? */
|
||||
}
|
||||
|
||||
if (pHandflow->FlowReplace & SERIAL_RTS_HANDSHAKE)
|
||||
{
|
||||
upcomingTermios.c_cflag |= CRTSCTS;
|
||||
}
|
||||
else
|
||||
{
|
||||
upcomingTermios.c_cflag &= ~CRTSCTS;
|
||||
}
|
||||
|
||||
|
||||
// FIXME: could be implemented during read/write I/O
|
||||
if (pHandflow->FlowReplace & SERIAL_XOFF_CONTINUE)
|
||||
{
|
||||
@ -738,7 +731,7 @@ static BOOL _set_handflow(WINPR_COMM *pComm, const SERIAL_HANDFLOW *pHandflow)
|
||||
// FIXME: could be implemented during read/write I/O
|
||||
if (pHandflow->XonLimit != TTY_THRESHOLD_UNTHROTTLE)
|
||||
{
|
||||
DEBUG_WARN("Attempt to set XonLimit with an unsupported value: %d", pHandflow->XonLimit);
|
||||
DEBUG_WARN("Attempt to set XonLimit with an unsupported value: %lu", pHandflow->XonLimit);
|
||||
SetLastError(ERROR_NOT_SUPPORTED);
|
||||
result = FALSE; /* but keep on */
|
||||
}
|
||||
@ -748,7 +741,7 @@ static BOOL _set_handflow(WINPR_COMM *pComm, const SERIAL_HANDFLOW *pHandflow)
|
||||
// FIXME: could be implemented during read/write I/O
|
||||
if (pHandflow->XoffLimit != TTY_THRESHOLD_THROTTLE)
|
||||
{
|
||||
DEBUG_WARN("Attempt to set XoffLimit with an unsupported value: %d", pHandflow->XoffLimit);
|
||||
DEBUG_WARN("Attempt to set XoffLimit with an unsupported value: %lu", pHandflow->XoffLimit);
|
||||
SetLastError(ERROR_NOT_SUPPORTED);
|
||||
result = FALSE; /* but keep on */
|
||||
}
|
||||
@ -756,7 +749,7 @@ static BOOL _set_handflow(WINPR_COMM *pComm, const SERIAL_HANDFLOW *pHandflow)
|
||||
|
||||
if (_comm_ioctl_tcsetattr(pComm->fd, TCSANOW, &upcomingTermios) < 0)
|
||||
{
|
||||
DEBUG_WARN("_comm_ioctl_tcsetattr failure: last-error: 0x0.8x", GetLastError());
|
||||
DEBUG_WARN("_comm_ioctl_tcsetattr failure: last-error: 0x%lX", GetLastError());
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -873,7 +866,7 @@ static BOOL _set_lines(WINPR_COMM *pComm, UINT32 lines)
|
||||
{
|
||||
if (ioctl(pComm->fd, TIOCMBIS, &lines) < 0)
|
||||
{
|
||||
DEBUG_WARN("TIOCMBIS ioctl failed, lines=0x%0.4X, errno=[%d] %s", lines, errno, strerror(errno));
|
||||
DEBUG_WARN("TIOCMBIS ioctl failed, lines=0x%X, errno=[%d] %s", lines, errno, strerror(errno));
|
||||
SetLastError(ERROR_IO_DEVICE);
|
||||
return FALSE;
|
||||
}
|
||||
@ -886,7 +879,7 @@ static BOOL _clear_lines(WINPR_COMM *pComm, UINT32 lines)
|
||||
{
|
||||
if (ioctl(pComm->fd, TIOCMBIC, &lines) < 0)
|
||||
{
|
||||
DEBUG_WARN("TIOCMBIC ioctl failed, lines=0x%0.4X, errno=[%d] %s", lines, errno, strerror(errno));
|
||||
DEBUG_WARN("TIOCMBIC ioctl failed, lines=0x%X, errno=[%d] %s", lines, errno, strerror(errno));
|
||||
SetLastError(ERROR_IO_DEVICE);
|
||||
return FALSE;
|
||||
}
|
||||
@ -933,32 +926,30 @@ static BOOL _clear_dtr(WINPR_COMM *pComm)
|
||||
|
||||
static BOOL _set_rts(WINPR_COMM *pComm)
|
||||
{
|
||||
// TMP: really required?
|
||||
/* SERIAL_HANDFLOW handflow; */
|
||||
/* if (!_get_handflow(pComm, &handflow)) */
|
||||
/* return FALSE; */
|
||||
SERIAL_HANDFLOW handflow;
|
||||
if (!_get_handflow(pComm, &handflow))
|
||||
return FALSE;
|
||||
|
||||
/* if (handflow.FlowReplace & SERIAL_RTS_HANDSHAKE) */
|
||||
/* { */
|
||||
/* SetLastError(ERROR_INVALID_PARAMETER); */
|
||||
/* return FALSE; */
|
||||
/* } */
|
||||
if (handflow.FlowReplace & SERIAL_RTS_HANDSHAKE)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return _set_lines(pComm, TIOCM_RTS);
|
||||
}
|
||||
|
||||
static BOOL _clear_rts(WINPR_COMM *pComm)
|
||||
{
|
||||
// TMP: really required?
|
||||
/* SERIAL_HANDFLOW handflow; */
|
||||
/* if (!_get_handflow(pComm, &handflow)) */
|
||||
/* return FALSE; */
|
||||
SERIAL_HANDFLOW handflow;
|
||||
if (!_get_handflow(pComm, &handflow))
|
||||
return FALSE;
|
||||
|
||||
/* if (handflow.FlowReplace & SERIAL_RTS_HANDSHAKE) */
|
||||
/* { */
|
||||
/* SetLastError(ERROR_INVALID_PARAMETER); */
|
||||
/* return FALSE; */
|
||||
/* } */
|
||||
if (handflow.FlowReplace & SERIAL_RTS_HANDSHAKE)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return _clear_lines(pComm, TIOCM_RTS);
|
||||
}
|
||||
@ -977,8 +968,9 @@ static BOOL _get_modemstatus(WINPR_COMM *pComm, ULONG *pRegister)
|
||||
|
||||
ZeroMemory(pRegister, sizeof(ULONG));
|
||||
|
||||
/* TODO: FIXME: how to get a direct access from the user space
|
||||
* to the MSR register in order to complete the 4 first bits?
|
||||
/* FIXME: Is the last read of the MSR register available or
|
||||
* cached somewhere? Not quite sure we need to return the 4
|
||||
* LSBits anyway.
|
||||
*/
|
||||
|
||||
/* #define SERIAL_MSR_DCTS 0x01 */
|
||||
@ -1038,13 +1030,13 @@ static BOOL _set_wait_mask(WINPR_COMM *pComm, const ULONG *pWaitMask)
|
||||
// TMP: TODO:
|
||||
// pending wait_on_mask must be stopped with STATUS_SUCCESS
|
||||
// http://msdn.microsoft.com/en-us/library/ff546805%28v=vs.85%29.aspx
|
||||
|
||||
// and pOutputMask = 0;
|
||||
|
||||
possibleMask = *pWaitMask & _SERIAL_SYS_SUPPORTED_EV_MASK;
|
||||
|
||||
if (possibleMask != *pWaitMask)
|
||||
{
|
||||
DEBUG_WARN("Not all wait events supported (Serial.sys), requested events= 0X%0.4X, possible events= 0X%0.4X", *pWaitMask, possibleMask);
|
||||
DEBUG_WARN("Not all wait events supported (Serial.sys), requested events= 0X%lX, possible events= 0X%lX", *pWaitMask, possibleMask);
|
||||
|
||||
/* FIXME: shall we really set the possibleMask and return FALSE? */
|
||||
pComm->waitMask = possibleMask;
|
||||
@ -1067,7 +1059,7 @@ static BOOL _wait_on_mask(WINPR_COMM *pComm, ULONG *pOutputMask)
|
||||
{
|
||||
assert(*pOutputMask == 0);
|
||||
|
||||
// TMP: TODO:
|
||||
// TMP: TODO: be sure to get a dedicated thread
|
||||
/* while (TRUE) */
|
||||
{
|
||||
int nbBytesToBeRead = 0;
|
||||
@ -1097,7 +1089,7 @@ static BOOL _wait_on_mask(WINPR_COMM *pComm, ULONG *pOutputMask)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* NB: preferred below "currentCounters.* != pComm->counters.*" over "currentCounters.* > pComm->counters.*" thinking the counters can loop */
|
||||
/* NB: preferred below (currentCounters.* != pComm->counters.*) over (currentCounters.* > pComm->counters.*) thinking the counters can loop */
|
||||
|
||||
|
||||
/* events */
|
||||
@ -1224,8 +1216,9 @@ static BOOL _wait_on_mask(WINPR_COMM *pComm, ULONG *pOutputMask)
|
||||
}
|
||||
|
||||
|
||||
/* FIXME: TIOCMIWAIT could be possible if _wait_on_mask gets its own thread */
|
||||
/* if (*pOutputMask == 0) */
|
||||
// TMP: TIOCMIWAIT could be possible if _wait_on_mask gets its own thread
|
||||
/* if ((*pOutputMask == 0) && /\* don't bother at least one of the events event already occured *\/ */
|
||||
/* ((pComm->waitMask & ~(SERIAL_EV_CTS | SERIAL_EV_DSR | SERIAL_EV_RLSD | SERIAL_EV_RING)) == 0)) /\* only events handled by TIOCMIWAIT, otherwise go through the regular loop *\/ */
|
||||
/* { */
|
||||
/* if (ioctl(pComm->fd, TIOCMIWAIT, &tiocmiwaitMask) < 0) */
|
||||
/* { */
|
||||
@ -1233,7 +1226,9 @@ static BOOL _wait_on_mask(WINPR_COMM *pComm, ULONG *pOutputMask)
|
||||
/* SetLastError(ERROR_IO_DEVICE); */
|
||||
/* return FALSE; */
|
||||
/* } */
|
||||
/* /\* TODO: check counters again after TIOCMIWAIT *\/ */
|
||||
|
||||
/* /\* check counters again after TIOCMIWAIT *\/ */
|
||||
/* continue; */
|
||||
/* } */
|
||||
}
|
||||
|
||||
@ -1243,13 +1238,14 @@ static BOOL _wait_on_mask(WINPR_COMM *pComm, ULONG *pOutputMask)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* // TMP: */
|
||||
/* DEBUG_WARN("waiting on events:0X%0.4X", pComm->waitMask); */
|
||||
/* /\* // TMP: *\/ */
|
||||
/* DEBUG_WARN("waiting on events:0X%lX", pComm->waitMask); */
|
||||
|
||||
/* sleep(1); */
|
||||
|
||||
}
|
||||
|
||||
DEBUG_WARN("_wait_on_mask pending on events:0X%0.4X", pComm->waitMask);
|
||||
DEBUG_WARN("_wait_on_mask pending on events:0X%lX", pComm->waitMask);
|
||||
SetLastError(ERROR_IO_PENDING); /* see: WaitCommEvent's help */
|
||||
return FALSE;
|
||||
}
|
||||
@ -1275,10 +1271,10 @@ static BOOL _set_queue_size(WINPR_COMM *pComm, const SERIAL_QUEUE_SIZE *pQueueSi
|
||||
/* FIXME: could be implemented on top of N_TTY */
|
||||
|
||||
if (pQueueSize->InSize > N_TTY_BUF_SIZE)
|
||||
DEBUG_WARN("Requested an incompatible input buffer size: %d", pQueueSize->InSize);
|
||||
DEBUG_WARN("Requested an incompatible input buffer size: %lu", pQueueSize->InSize);
|
||||
|
||||
if (pQueueSize->OutSize > N_TTY_BUF_SIZE)
|
||||
DEBUG_WARN("Requested an incompatible output buffer size: %d", pQueueSize->OutSize);
|
||||
DEBUG_WARN("Requested an incompatible output buffer size: %lu", pQueueSize->OutSize);
|
||||
|
||||
SetLastError(ERROR_CANCELLED);
|
||||
return FALSE;
|
||||
@ -1289,7 +1285,7 @@ static BOOL _purge(WINPR_COMM *pComm, const ULONG *pPurgeMask)
|
||||
{
|
||||
if ((*pPurgeMask & ~(SERIAL_PURGE_TXABORT | SERIAL_PURGE_RXABORT | SERIAL_PURGE_TXCLEAR | SERIAL_PURGE_RXCLEAR)) > 0)
|
||||
{
|
||||
DEBUG_WARN("Invalid purge mask: 0x%X\n", *pPurgeMask);
|
||||
DEBUG_WARN("Invalid purge mask: 0x%lX\n", *pPurgeMask);
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
@ -1313,9 +1309,10 @@ static BOOL _purge(WINPR_COMM *pComm, const ULONG *pPurgeMask)
|
||||
}
|
||||
|
||||
/* TMP: TODO: double check if this gives well a change to abort a pending CommReadFile */
|
||||
fcntl(pComm->fd, F_SETFL, fcntl(pComm->fd, F_GETFL) | O_NONBLOCK);
|
||||
sleep(1);
|
||||
fcntl(pComm->fd, F_SETFL, fcntl(pComm->fd, F_GETFL) & ~O_NONBLOCK);
|
||||
//assert(0);
|
||||
/* fcntl(pComm->fd, F_SETFL, fcntl(pComm->fd, F_GETFL) | O_NONBLOCK); */
|
||||
/* sleep(1); */
|
||||
/* fcntl(pComm->fd, F_SETFL, fcntl(pComm->fd, F_GETFL) & ~O_NONBLOCK); */
|
||||
|
||||
/* TMP: FIXME: synchronization of the incoming
|
||||
* IRP_MJ_READ-s. Could be possible to make them to
|
||||
|
Loading…
Reference in New Issue
Block a user