From 5f9e9836cf2d183a7645ef6d4badc362fef15f56 Mon Sep 17 00:00:00 2001 From: Eric Pouech Date: Sun, 7 May 2006 14:11:05 +0200 Subject: [PATCH] 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 --- dlls/kernel/comm.c | 134 ++++++++------------------------------------ dlls/ntdll/serial.c | 75 +++++++++++++++++++++++++ 2 files changed, 99 insertions(+), 110 deletions(-) diff --git a/dlls/kernel/comm.c b/dlls/kernel/comm.c index 8f5c18d35c..8f5b9fde83 100644 --- a/dlls/kernel/comm.c +++ b/dlls/kernel/comm.c @@ -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; - - 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 + DWORD ioc; - 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); } /******************************************************************** diff --git a/dlls/ntdll/serial.c b/dlls/ntdll/serial.c index 15d1941f9f..64e181acc0 100644 --- a/dlls/ntdll/serial.c +++ b/dlls/ntdll/serial.c @@ -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, -- 2.32.0.93.g670b81a890