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:
Eric Pouech 2006-05-07 14:11:05 +02:00 committed by Alexandre Julliard
parent fcdc293bb0
commit 5f9e9836cf
2 changed files with 99 additions and 110 deletions

View File

@ -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);
}
/********************************************************************

View File

@ -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,