ntdll/kernel32: EscapeCommFunction & associated IOCTLs
- implemented ntdll's serial IOCTL: CLR_DTR, CLR_RTS, SET_DTR, SET_RTS, SET_XOFF, SET_XON, RESET_DEVICE - implemented kernel32.EscapeCommFunction on top of them
This commit is contained in:
parent
fcdc293bb0
commit
5f9e9836cf
|
@ -146,19 +146,6 @@ static int COMM_GetEInfo(int fd, serial_irq_info *irq_info)
|
|||
return -1;
|
||||
}
|
||||
|
||||
static int COMM_WhackModem(int fd, unsigned int andy, unsigned int orrie)
|
||||
{
|
||||
#ifdef TIOCMGET
|
||||
unsigned int mstat, okay;
|
||||
okay = ioctl(fd, TIOCMGET, &mstat);
|
||||
if (okay) return okay;
|
||||
if (andy) mstat &= andy;
|
||||
mstat |= orrie;
|
||||
return ioctl(fd, TIOCMSET, &mstat);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* COMM_Parse* (Internal)
|
||||
|
@ -699,111 +686,38 @@ BOOL WINAPI ClearCommBreak(HANDLE handle)
|
|||
*
|
||||
* Directs a communication device to perform an extended function.
|
||||
*
|
||||
* PARAMS
|
||||
*
|
||||
* handle [in] The communication device to perform the extended function
|
||||
* nFunction [in] The extended function to be performed
|
||||
*
|
||||
* RETURNS
|
||||
*
|
||||
* True or requested data on successful completion of the command,
|
||||
* false if the device is not present cannot execute the command
|
||||
* or the command failed.
|
||||
*/
|
||||
BOOL WINAPI EscapeCommFunction(
|
||||
HANDLE handle, /* [in] The communication device to perform the extended function. */
|
||||
UINT nFunction) /* [in] The extended function to be performed. */
|
||||
BOOL WINAPI EscapeCommFunction(HANDLE handle, UINT func)
|
||||
{
|
||||
int fd,direct=FALSE,result=FALSE;
|
||||
struct termios port;
|
||||
DWORD ioc;
|
||||
|
||||
TRACE("handle %p, function=%d\n", handle, nFunction);
|
||||
fd = get_comm_fd( handle, FILE_READ_DATA );
|
||||
if(fd<0) return FALSE;
|
||||
|
||||
if (tcgetattr(fd,&port) == -1) {
|
||||
release_comm_fd( handle, fd );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
switch (nFunction) {
|
||||
case RESETDEV:
|
||||
TRACE("\n");
|
||||
break;
|
||||
|
||||
case CLRDTR:
|
||||
TRACE("CLRDTR\n");
|
||||
#ifdef TIOCM_DTR
|
||||
direct=TRUE;
|
||||
result= COMM_WhackModem(fd, ~TIOCM_DTR, 0);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case CLRRTS:
|
||||
TRACE("CLRRTS\n");
|
||||
#ifdef TIOCM_RTS
|
||||
direct=TRUE;
|
||||
result= COMM_WhackModem(fd, ~TIOCM_RTS, 0);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case SETDTR:
|
||||
TRACE("SETDTR\n");
|
||||
#ifdef TIOCM_DTR
|
||||
direct=TRUE;
|
||||
result= COMM_WhackModem(fd, 0, TIOCM_DTR);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case SETRTS:
|
||||
TRACE("SETRTS\n");
|
||||
#ifdef TIOCM_RTS
|
||||
direct=TRUE;
|
||||
result= COMM_WhackModem(fd, 0, TIOCM_RTS);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case SETXOFF:
|
||||
TRACE("SETXOFF\n");
|
||||
port.c_iflag |= IXOFF;
|
||||
break;
|
||||
|
||||
case SETXON:
|
||||
TRACE("SETXON\n");
|
||||
port.c_iflag |= IXON;
|
||||
break;
|
||||
case SETBREAK:
|
||||
TRACE("setbreak\n");
|
||||
#ifdef TIOCSBRK
|
||||
direct=TRUE;
|
||||
result = ioctl(fd,TIOCSBRK,0);
|
||||
break;
|
||||
#endif
|
||||
case CLRBREAK:
|
||||
TRACE("clrbreak\n");
|
||||
#ifdef TIOCSBRK
|
||||
direct=TRUE;
|
||||
result = ioctl(fd,TIOCCBRK,0);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
WARN("(handle=%p,nFunction=%d): Unknown function\n",
|
||||
handle, nFunction);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!direct)
|
||||
if (tcsetattr(fd, TCSADRAIN, &port) == -1) {
|
||||
release_comm_fd( handle, fd );
|
||||
return FALSE;
|
||||
} else
|
||||
result= TRUE;
|
||||
else
|
||||
{
|
||||
if (result == -1)
|
||||
{
|
||||
result= FALSE;
|
||||
}
|
||||
else
|
||||
result = TRUE;
|
||||
}
|
||||
release_comm_fd( handle, fd );
|
||||
return result;
|
||||
switch (func)
|
||||
{
|
||||
case CLRDTR: ioc = IOCTL_SERIAL_CLR_DTR; break;
|
||||
case CLRRTS: ioc = IOCTL_SERIAL_CLR_RTS; break;
|
||||
case SETDTR: ioc = IOCTL_SERIAL_SET_DTR; break;
|
||||
case SETRTS: ioc = IOCTL_SERIAL_SET_RTS; break;
|
||||
case SETXOFF: ioc = IOCTL_SERIAL_SET_XOFF; break;
|
||||
case SETXON: ioc = IOCTL_SERIAL_SET_XON; break;
|
||||
case SETBREAK: ioc = IOCTL_SERIAL_SET_BREAK_ON; break;
|
||||
case CLRBREAK: ioc = IOCTL_SERIAL_SET_BREAK_OFF; break;
|
||||
case RESETDEV: ioc = IOCTL_SERIAL_RESET_DEVICE; break;
|
||||
default:
|
||||
ERR("Unknown function code (%u)\n", func);
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
return DeviceIoControl(handle, ioc, NULL, 0, NULL, 0, NULL, NULL);
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
|
|
|
@ -823,6 +823,44 @@ static NTSTATUS set_wait_mask(HANDLE hDevice, DWORD mask)
|
|||
return status;
|
||||
}
|
||||
|
||||
static NTSTATUS set_XOff(int fd)
|
||||
{
|
||||
struct termios port;
|
||||
|
||||
if (tcgetattr(fd,&port) == -1)
|
||||
{
|
||||
FIXME("tcgetattr on fd %d failed (%s)!\n", fd, strerror(errno));
|
||||
return FILE_GetNtStatus();
|
||||
|
||||
|
||||
}
|
||||
port.c_iflag |= IXOFF;
|
||||
if (tcsetattr(fd, TCSADRAIN, &port) == -1)
|
||||
{
|
||||
FIXME("tcsetattr on fd %d failed (%s)!\n", fd, strerror(errno));
|
||||
return FILE_GetNtStatus();
|
||||
}
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static NTSTATUS set_XOn(int fd)
|
||||
{
|
||||
struct termios port;
|
||||
|
||||
if (tcgetattr(fd,&port) == -1)
|
||||
{
|
||||
FIXME("tcgetattr on fd %d failed (%s)!\n", fd, strerror(errno));
|
||||
return FILE_GetNtStatus();
|
||||
}
|
||||
port.c_iflag |= IXON;
|
||||
if (tcsetattr(fd, TCSADRAIN, &port) == -1)
|
||||
{
|
||||
FIXME("tcsetattr on fd %d failed (%s)!\n", fd, strerror(errno));
|
||||
return FILE_GetNtStatus();
|
||||
}
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static NTSTATUS xmit_immediate(HANDLE hDevice, int fd, char* ptr)
|
||||
{
|
||||
/* FIXME: not perfect as it should bypass the in-queue */
|
||||
|
@ -861,6 +899,20 @@ NTSTATUS COMM_DeviceIoControl(HANDLE hDevice,
|
|||
|
||||
switch (dwIoControlCode)
|
||||
{
|
||||
case IOCTL_SERIAL_CLR_DTR:
|
||||
#ifdef TIOCM_DTR
|
||||
if (whack_modem(fd, ~TIOCM_DTR, 0) == -1) status = FILE_GetNtStatus();
|
||||
#else
|
||||
status = STATUS_NOT_SUPPORTED;
|
||||
#endif
|
||||
break;
|
||||
case IOCTL_SERIAL_CLR_RTS:
|
||||
#ifdef TIOCM_RTS
|
||||
if (whack_modem(fd, ~TIOCM_RTS, 0) == -1) status = FILE_GetNtStatus();
|
||||
#else
|
||||
status = STATUS_NOT_SUPPORTED;
|
||||
#endif
|
||||
break;
|
||||
case IOCTL_SERIAL_GET_BAUD_RATE:
|
||||
if (lpOutBuffer && nOutBufferSize == sizeof(SERIAL_BAUD_RATE))
|
||||
{
|
||||
|
@ -943,6 +995,9 @@ NTSTATUS COMM_DeviceIoControl(HANDLE hDevice,
|
|||
else
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
break;
|
||||
case IOCTL_SERIAL_RESET_DEVICE:
|
||||
FIXME("Unsupported\n");
|
||||
break;
|
||||
case IOCTL_SERIAL_SET_BAUD_RATE:
|
||||
if (lpInBuffer && nInBufferSize == sizeof(SERIAL_BAUD_RATE))
|
||||
status = set_baud_rate(fd, (const SERIAL_BAUD_RATE*)lpInBuffer);
|
||||
|
@ -979,6 +1034,13 @@ NTSTATUS COMM_DeviceIoControl(HANDLE hDevice,
|
|||
else
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
break;
|
||||
case IOCTL_SERIAL_SET_DTR:
|
||||
#ifdef TIOCM_DTR
|
||||
if (whack_modem(fd, 0, TIOCM_DTR) == -1) status = FILE_GetNtStatus();
|
||||
#else
|
||||
status = STATUS_NOT_SUPPORTED;
|
||||
#endif
|
||||
break;
|
||||
case IOCTL_SERIAL_SET_HANDFLOW:
|
||||
if (lpInBuffer && nInBufferSize == sizeof(SERIAL_HANDFLOW))
|
||||
status = set_handflow(fd, (const SERIAL_HANDFLOW*)lpInBuffer);
|
||||
|
@ -997,6 +1059,13 @@ NTSTATUS COMM_DeviceIoControl(HANDLE hDevice,
|
|||
else
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
break;
|
||||
case IOCTL_SERIAL_SET_RTS:
|
||||
#ifdef TIOCM_RTS
|
||||
if (whack_modem(fd, 0, TIOCM_RTS) == -1) status = FILE_GetNtStatus();
|
||||
#else
|
||||
status = STATUS_NOT_SUPPORTED;
|
||||
#endif
|
||||
break;
|
||||
case IOCTL_SERIAL_SET_TIMEOUTS:
|
||||
if (lpInBuffer && nInBufferSize == sizeof(SERIAL_TIMEOUTS))
|
||||
status = set_timeouts(hDevice, fd, (const SERIAL_TIMEOUTS*)lpInBuffer);
|
||||
|
@ -1010,6 +1079,12 @@ NTSTATUS COMM_DeviceIoControl(HANDLE hDevice,
|
|||
}
|
||||
else status = STATUS_INVALID_PARAMETER;
|
||||
break;
|
||||
case IOCTL_SERIAL_SET_XOFF:
|
||||
status = set_XOff(fd);
|
||||
break;
|
||||
case IOCTL_SERIAL_SET_XON:
|
||||
status = set_XOn(fd);
|
||||
break;
|
||||
default:
|
||||
FIXME("Unsupported IOCTL %lx (type=%lx access=%lx func=%lx meth=%lx)\n",
|
||||
dwIoControlCode, dwIoControlCode >> 16, (dwIoControlCode >> 14) & 3,
|
||||
|
|
Loading…
Reference in New Issue