winpr-comm: completed _purge() supporting SERIAL_PURGE_RXABORT
winpr-comm: CommReadFile, support of FREERDP_PURGE_RXABORT sent by _purge()
This commit is contained in:
parent
cdbba47eee
commit
85343a435a
@ -1124,15 +1124,21 @@ HANDLE CommCreateFileA(LPCSTR lpDeviceName, DWORD dwDesiredAccess, DWORD dwShare
|
||||
goto error_handle;
|
||||
}
|
||||
|
||||
/* TMP: won't be required once fd_read, fd_read_event implemented */
|
||||
/* Restore the blocking mode for upcoming read/write operations */
|
||||
if (fcntl(pComm->fd, F_SETFL, fcntl(pComm->fd, F_GETFL) & ~O_NONBLOCK) < 0)
|
||||
pComm->fd_read = open(devicePath, O_RDONLY | O_NOCTTY | O_NONBLOCK);
|
||||
if (pComm->fd_read < 0)
|
||||
{
|
||||
DEBUG_WARN("failed to open device %s, could not restore the O_NONBLOCK flag", devicePath);
|
||||
DEBUG_WARN("failed to open fd_read, device: %s", devicePath);
|
||||
SetLastError(ERROR_BAD_DEVICE);
|
||||
goto error_handle;
|
||||
}
|
||||
|
||||
pComm->fd_read_event = eventfd(0, EFD_NONBLOCK); /* EFD_NONBLOCK required because a read() is not always expected */
|
||||
if (pComm->fd_read_event < 0)
|
||||
{
|
||||
DEBUG_WARN("failed to open fd_read_event, device: %s", devicePath);
|
||||
SetLastError(ERROR_BAD_DEVICE);
|
||||
goto error_handle;
|
||||
}
|
||||
|
||||
pComm->fd_write = open(devicePath, O_WRONLY | O_NOCTTY | O_NONBLOCK);
|
||||
if (pComm->fd_write < 0)
|
||||
|
@ -47,6 +47,9 @@ struct winpr_comm
|
||||
WINPR_HANDLE_DEF();
|
||||
|
||||
int fd;
|
||||
|
||||
int fd_read;
|
||||
int fd_read_event; /* as of today, only used by _purge() */
|
||||
|
||||
int fd_write;
|
||||
int fd_write_event; /* as of today, only used by _purge() */
|
||||
|
@ -45,7 +45,7 @@ BOOL _comm_set_permissive(HANDLE hDevice, BOOL permissive)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!pComm || pComm->Type != HANDLE_TYPE_COMM || !pComm->fd )
|
||||
if (!pComm || pComm->Type != HANDLE_TYPE_COMM)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_HANDLE);
|
||||
return FALSE;
|
||||
@ -89,6 +89,9 @@ BOOL CommReadFile(HANDLE hDevice, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
|
||||
LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped)
|
||||
{
|
||||
WINPR_COMM* pComm = (WINPR_COMM*) hDevice;
|
||||
int biggestFd = -1;
|
||||
fd_set read_set;
|
||||
int nbFds;
|
||||
ssize_t nbRead = 0;
|
||||
COMMTIMEOUTS *pTimeouts;
|
||||
UCHAR vmin = 0;
|
||||
@ -101,7 +104,7 @@ BOOL CommReadFile(HANDLE hDevice, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!pComm || pComm->Type != HANDLE_TYPE_COMM || !pComm->fd )
|
||||
if (!pComm || pComm->Type != HANDLE_TYPE_COMM)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_HANDLE);
|
||||
return FALSE;
|
||||
@ -143,7 +146,7 @@ BOOL CommReadFile(HANDLE hDevice, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
|
||||
* http://msdn.microsoft.com/en-us/library/windows/hardware/hh439614%28v=vs.85%29.aspx
|
||||
*
|
||||
* ReadIntervalTimeout | ReadTotalTimeoutMultiplier | ReadTotalTimeoutConstant | VMIN | VTIME | TMAX |
|
||||
* 0 | 0 | 0 | N | 0 | 0 | Blocks for N bytes available. FIXME: reduce N to 1?
|
||||
* 0 | 0 | 0 | N | 0 | 0 | Blocks for N bytes available.
|
||||
* 0< Ti <MAXULONG | 0 | 0 | N | Ti | 0 | Block 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 | 0 | Tc | 0 | Blocks on first byte during Tc or returns immediately whith bytes available
|
||||
@ -208,7 +211,7 @@ BOOL CommReadFile(HANDLE hDevice, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
|
||||
currentTermios.c_cc[VTIME] = vtime;
|
||||
|
||||
// TMP:
|
||||
DEBUG_MSG("Applying timeout VMIN=%u, VTIME=%u", vmin, vtime);
|
||||
fprintf(stderr, "Applying timeout VMIN=%u, VTIME=%u", vmin, vtime);
|
||||
|
||||
if (tcsetattr(pComm->fd, TCSANOW, ¤tTermios) < 0)
|
||||
{
|
||||
@ -218,37 +221,116 @@ BOOL CommReadFile(HANDLE hDevice, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
|
||||
}
|
||||
}
|
||||
|
||||
nbRead = read(pComm->fd, lpBuffer, nNumberOfBytesToRead);
|
||||
|
||||
if (nbRead < 0)
|
||||
|
||||
|
||||
|
||||
biggestFd = pComm->fd_read;
|
||||
if (pComm->fd_read_event > biggestFd)
|
||||
biggestFd = pComm->fd_read_event;
|
||||
|
||||
FD_ZERO(&read_set);
|
||||
|
||||
assert(pComm->fd_read_event < FD_SETSIZE);
|
||||
assert(pComm->fd_read < FD_SETSIZE);
|
||||
|
||||
FD_SET(pComm->fd_read_event, &read_set);
|
||||
FD_SET(pComm->fd_read, &read_set);
|
||||
|
||||
nbFds = select(biggestFd+1, &read_set, NULL, NULL, NULL /* TMP: TODO:*/);
|
||||
if (nbFds < 0)
|
||||
{
|
||||
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=%lu, errno=[%d] %s", nNumberOfBytesToRead, errno, strerror(errno));
|
||||
|
||||
switch (errno)
|
||||
{
|
||||
// TMP: TODO:
|
||||
case EAGAIN: /* EWOULDBLOCK */
|
||||
nbRead = 0;
|
||||
break;
|
||||
|
||||
case EBADF:
|
||||
SetLastError(ERROR_BAD_DEVICE); /* STATUS_INVALID_DEVICE_REQUEST */
|
||||
return FALSE;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
DEBUG_WARN("select() failure, errno=[%d] %s\n", errno, strerror(errno));
|
||||
SetLastError(ERROR_IO_DEVICE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (nbFds == 0)
|
||||
{
|
||||
/* timeout */
|
||||
|
||||
SetLastError(ERROR_TIMEOUT);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// TODO:
|
||||
// SetLastError(ERROR_TIMEOUT)
|
||||
|
||||
*lpNumberOfBytesRead = nbRead;
|
||||
return TRUE;
|
||||
/* read_set */
|
||||
|
||||
if (FD_ISSET(pComm->fd_read_event, &read_set))
|
||||
{
|
||||
eventfd_t event = 0;
|
||||
int nbRead;
|
||||
|
||||
nbRead = eventfd_read(pComm->fd_read_event, &event);
|
||||
if (nbRead < 0)
|
||||
{
|
||||
if (errno == EAGAIN)
|
||||
{
|
||||
assert(FALSE); /* not quite sure this should ever happen */
|
||||
/* keep on */
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_WARN("unexpected error on reading fd_write_event, errno=[%d] %s\n", errno, strerror(errno));
|
||||
/* FIXME: return FALSE ? */
|
||||
}
|
||||
|
||||
assert(errno == EAGAIN);
|
||||
}
|
||||
|
||||
assert(nbRead == sizeof(eventfd_t));
|
||||
|
||||
if (event == FREERDP_PURGE_RXABORT)
|
||||
{
|
||||
SetLastError(ERROR_CANCELLED);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
assert(event == FREERDP_PURGE_RXABORT); /* no other expected event so far */
|
||||
}
|
||||
|
||||
if (FD_ISSET(pComm->fd_read, &read_set))
|
||||
{
|
||||
nbRead = read(pComm->fd_read, lpBuffer, nNumberOfBytesToRead);
|
||||
if (nbRead < 0)
|
||||
{
|
||||
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=%lu, errno=[%d] %s", nNumberOfBytesToRead, errno, strerror(errno));
|
||||
|
||||
if (errno == EAGAIN)
|
||||
{
|
||||
/* keep on */
|
||||
return TRUE; /* expect a read-loop to be implemented on the server side */
|
||||
}
|
||||
else if (errno == EBADF)
|
||||
{
|
||||
SetLastError(ERROR_BAD_DEVICE); /* STATUS_INVALID_DEVICE_REQUEST */
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(FALSE);
|
||||
SetLastError(ERROR_IO_DEVICE);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (nbRead == 0)
|
||||
{
|
||||
/* termios timeout */
|
||||
SetLastError(ERROR_TIMEOUT);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*lpNumberOfBytesRead = nbRead;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
assert(FALSE);
|
||||
*lpNumberOfBytesRead = 0;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
@ -271,7 +353,7 @@ BOOL CommWriteFile(HANDLE hDevice, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!pComm || pComm->Type != HANDLE_TYPE_COMM || !pComm->fd )
|
||||
if (!pComm || pComm->Type != HANDLE_TYPE_COMM)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_HANDLE);
|
||||
return FALSE;
|
||||
@ -363,6 +445,7 @@ BOOL CommWriteFile(HANDLE hDevice, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite
|
||||
if (errno == EAGAIN)
|
||||
{
|
||||
assert(FALSE); /* not quite sure this should ever happen */
|
||||
/* keep on */
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -381,7 +464,7 @@ BOOL CommWriteFile(HANDLE hDevice, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
assert(event == FREERDP_PURGE_TXABORT); /* no other event known so far */
|
||||
assert(event == FREERDP_PURGE_TXABORT); /* no other expected event so far */
|
||||
}
|
||||
|
||||
|
||||
@ -409,6 +492,12 @@ BOOL CommWriteFile(HANDLE hDevice, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite
|
||||
SetLastError(ERROR_BAD_DEVICE); /* STATUS_INVALID_DEVICE_REQUEST */
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(FALSE);
|
||||
SetLastError(ERROR_IO_DEVICE);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
*lpNumberOfBytesWritten += nbWritten;
|
||||
@ -425,7 +514,7 @@ BOOL CommWriteFile(HANDLE hDevice, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite
|
||||
* Write operation. The serial port was oppened with:
|
||||
* DesiredAccess=0x0012019F. The printer worked fine with
|
||||
* mstsc. */
|
||||
tcdrain(pComm->fd);
|
||||
tcdrain(pComm->fd_write);
|
||||
|
||||
|
||||
return TRUE;
|
||||
|
@ -1142,19 +1142,19 @@ static BOOL _purge(WINPR_COMM *pComm, const ULONG *pPurgeMask)
|
||||
{
|
||||
/* Purges all read (IRP_MJ_READ) requests. */
|
||||
|
||||
/* int nbWritten; */
|
||||
int nbWritten;
|
||||
|
||||
/* if ((nbWritten = eventfd_write(pComm->fd_read_event, FREERDP_PURGE_RXABORT)) < 0) */
|
||||
/* { */
|
||||
/* if (errno != EAGAIN) */
|
||||
/* { */
|
||||
/* DEBUG_WARN("eventfd_write failed, errno=[%d] %s", errno, strerror(errno)); */
|
||||
/* } */
|
||||
if ((nbWritten = eventfd_write(pComm->fd_read_event, FREERDP_PURGE_RXABORT)) < 0)
|
||||
{
|
||||
if (errno != EAGAIN)
|
||||
{
|
||||
DEBUG_WARN("eventfd_write failed, errno=[%d] %s", errno, strerror(errno));
|
||||
}
|
||||
|
||||
/* assert(errno == EAGAIN); /\* no reader <=> no pending IRP_MJ_READ *\/ */
|
||||
/* } */
|
||||
assert(errno == EAGAIN); /* no reader <=> no pending IRP_MJ_READ */
|
||||
}
|
||||
|
||||
/* assert(nbWritten == 8); */
|
||||
assert(nbWritten == sizeof(eventfd_t));
|
||||
}
|
||||
|
||||
if (*pPurgeMask & SERIAL_PURGE_TXCLEAR)
|
||||
|
@ -222,6 +222,12 @@ BOOL CloseHandle(HANDLE hObject)
|
||||
if (comm->fd_write_event > 0)
|
||||
close(comm->fd_write_event);
|
||||
|
||||
if (comm->fd_read > 0)
|
||||
close(comm->fd_read);
|
||||
|
||||
if (comm->fd_read_event > 0)
|
||||
close(comm->fd_read_event);
|
||||
|
||||
free(comm);
|
||||
|
||||
return TRUE;
|
||||
|
Loading…
x
Reference in New Issue
Block a user