Commit 48646ea8 authored by Eric Pouech's avatar Eric Pouech Committed by Alexandre Julliard

ntdll/kernel32: GetCommState & IOCTL_SERIAL_GET_HANDFLOW

- implemented SERIAL_GET_HANDFLOW ioctl - made use of it in kernel.GetCommState
parent efb3244b
...@@ -1077,12 +1077,9 @@ BOOL WINAPI SetCommState( HANDLE handle, LPDCB lpdcb) ...@@ -1077,12 +1077,9 @@ BOOL WINAPI SetCommState( HANDLE handle, LPDCB lpdcb)
*/ */
BOOL WINAPI GetCommState(HANDLE handle, LPDCB lpdcb) BOOL WINAPI GetCommState(HANDLE handle, LPDCB lpdcb)
{ {
struct termios port;
int fd;
int stat = DTR_CONTROL_ENABLE | RTS_CONTROL_ENABLE;
SERIAL_BAUD_RATE sbr; SERIAL_BAUD_RATE sbr;
SERIAL_LINE_CONTROL slc; SERIAL_LINE_CONTROL slc;
SERIAL_HANDFLOW shf;
TRACE("handle %p, ptr %p\n", handle, lpdcb); TRACE("handle %p, ptr %p\n", handle, lpdcb);
...@@ -1091,14 +1088,18 @@ BOOL WINAPI GetCommState(HANDLE handle, LPDCB lpdcb) ...@@ -1091,14 +1088,18 @@ BOOL WINAPI GetCommState(HANDLE handle, LPDCB lpdcb)
SetLastError(ERROR_INVALID_PARAMETER); SetLastError(ERROR_INVALID_PARAMETER);
return FALSE; return FALSE;
} }
lpdcb->DCBlength = sizeof(*lpdcb);
if (!DeviceIoControl(handle, IOCTL_SERIAL_GET_BAUD_RATE, if (!DeviceIoControl(handle, IOCTL_SERIAL_GET_BAUD_RATE,
NULL, 0, &sbr, sizeof(sbr), NULL, NULL) || NULL, 0, &sbr, sizeof(sbr), NULL, NULL) ||
!DeviceIoControl(handle, IOCTL_SERIAL_GET_LINE_CONTROL, !DeviceIoControl(handle, IOCTL_SERIAL_GET_LINE_CONTROL,
NULL, 0, &slc, sizeof(slc), NULL, NULL)) NULL, 0, &slc, sizeof(slc), NULL, NULL) ||
!DeviceIoControl(handle, IOCTL_SERIAL_GET_HANDFLOW,
NULL, 0, &shf, sizeof(shf), NULL, NULL))
return FALSE; return FALSE;
memset(lpdcb, 0, sizeof(*lpdcb));
lpdcb->DCBlength = sizeof(*lpdcb);
/* yes, they seem no never be (re)set on NT */ /* yes, they seem no never be (re)set on NT */
lpdcb->fBinary = 1; lpdcb->fBinary = 1;
lpdcb->fParity = 0; lpdcb->fParity = 0;
...@@ -1109,69 +1110,37 @@ BOOL WINAPI GetCommState(HANDLE handle, LPDCB lpdcb) ...@@ -1109,69 +1110,37 @@ BOOL WINAPI GetCommState(HANDLE handle, LPDCB lpdcb)
lpdcb->Parity = slc.Parity; lpdcb->Parity = slc.Parity;
lpdcb->ByteSize = slc.WordLength; lpdcb->ByteSize = slc.WordLength;
fd = get_comm_fd( handle, FILE_READ_DATA ); if (shf.ControlHandShake & SERIAL_CTS_HANDSHAKE) lpdcb->fOutxCtsFlow = 1;
if (fd < 0) return FALSE; if (shf.ControlHandShake & SERIAL_DSR_HANDSHAKE) lpdcb->fOutxDsrFlow = 1;
if (tcgetattr(fd, &port) == -1) { switch (shf.ControlHandShake & (SERIAL_DTR_CONTROL | SERIAL_DTR_HANDSHAKE))
int save_error=errno; {
ERR("tcgetattr error '%s'\n", strerror(save_error)); case 0: lpdcb->fDtrControl = DTR_CONTROL_DISABLE; break;
release_comm_fd( handle, fd ); case SERIAL_DTR_CONTROL: lpdcb->fDtrControl = DTR_CONTROL_ENABLE; break;
return FALSE; case SERIAL_DTR_HANDSHAKE: lpdcb->fDtrControl = DTR_CONTROL_HANDSHAKE; break;
} }
switch (shf.FlowReplace & (SERIAL_RTS_CONTROL | SERIAL_RTS_HANDSHAKE))
#ifdef TIOCMGET {
if (ioctl(fd, TIOCMGET, &stat) == -1) case 0: lpdcb->fRtsControl = RTS_CONTROL_DISABLE; break;
{ case SERIAL_RTS_CONTROL: lpdcb->fRtsControl = RTS_CONTROL_ENABLE; break;
int save_error=errno; case SERIAL_RTS_HANDSHAKE: lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE; break;
WARN("ioctl error '%s'\n", strerror(save_error)); case SERIAL_RTS_CONTROL | SERIAL_RTS_HANDSHAKE:
stat = DTR_CONTROL_ENABLE | RTS_CONTROL_ENABLE; lpdcb->fRtsControl = RTS_CONTROL_TOGGLE; break;
} }
#endif if (shf.ControlHandShake & SERIAL_DSR_SENSITIVITY) lpdcb->fDsrSensitivity = 1;
release_comm_fd( handle, fd ); if (shf.ControlHandShake & SERIAL_ERROR_ABORT) lpdcb->fAbortOnError = 1;
if(port.c_iflag & INPCK) if (shf.FlowReplace & SERIAL_ERROR_CHAR) lpdcb->fErrorChar = 1;
lpdcb->fParity = TRUE; if (shf.FlowReplace & SERIAL_NULL_STRIPPING) lpdcb->fNull = 1;
else if (shf.FlowReplace & SERIAL_XOFF_CONTINUE) lpdcb->fTXContinueOnXoff = 1;
lpdcb->fParity = FALSE; lpdcb->XonLim = shf.XonLimit;
lpdcb->XoffLim = shf.XoffLimit;
lpdcb->fNull = 0;
/* termios does not support DTR/DSR flow control */
lpdcb->fOutxDsrFlow = 0;
lpdcb->fDtrControl =
#ifdef TIOCM_DTR
!(stat & TIOCM_DTR) ? DTR_CONTROL_DISABLE:
#endif
DTR_CONTROL_ENABLE ;
#ifdef CRTSCTS if (shf.FlowReplace & SERIAL_AUTO_TRANSMIT) lpdcb->fOutX = 1;
if (shf.FlowReplace & SERIAL_AUTO_RECEIVE) lpdcb->fInX = 1;
if (port.c_cflag & CRTSCTS) {
lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
lpdcb->fOutxCtsFlow = 1;
} else
#endif
{
lpdcb->fRtsControl =
#ifdef TIOCM_RTS
!(stat & TIOCM_RTS) ? RTS_CONTROL_DISABLE :
#endif
RTS_CONTROL_ENABLE ;
lpdcb->fOutxCtsFlow = 0;
}
if (port.c_iflag & IXON)
lpdcb->fInX = 1;
else
lpdcb->fInX = 0;
if (port.c_iflag & IXOFF)
lpdcb->fOutX = 1;
else
lpdcb->fOutX = 0;
/* /*
lpdcb->XonChar = lpdcb->XonChar =
lpdcb->XoffChar = lpdcb->XoffChar =
*/ */
lpdcb->XonLim = 10;
lpdcb->XoffLim = 10;
TRACE("OK\n"); TRACE("OK\n");
dump_dcb(lpdcb); dump_dcb(lpdcb);
......
...@@ -185,6 +185,54 @@ static NTSTATUS get_baud_rate(int fd, SERIAL_BAUD_RATE* sbr) ...@@ -185,6 +185,54 @@ static NTSTATUS get_baud_rate(int fd, SERIAL_BAUD_RATE* sbr)
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
static NTSTATUS get_hand_flow(int fd, SERIAL_HANDFLOW* shf)
{
int stat;
struct termios port;
if (tcgetattr(fd, &port) == -1)
{
ERR("tcgetattr error '%s'\n", strerror(errno));
return FILE_GetNtStatus();
}
#ifdef TIOCMGET
if (ioctl(fd, TIOCMGET, &stat) == -1)
{
WARN("ioctl error '%s'\n", strerror(errno));
stat = DTR_CONTROL_ENABLE | RTS_CONTROL_ENABLE;
}
#endif
/* termios does not support DTR/DSR flow control */
shf->ControlHandShake = 0;
shf->FlowReplace = 0;
#ifdef TIOCM_DTR
if (stat & TIOCM_DTR)
#endif
shf->ControlHandShake |= SERIAL_DTR_CONTROL;
#ifdef CRTSCTS
if (port.c_cflag & CRTSCTS)
{
shf->ControlHandShake |= SERIAL_DTR_CONTROL | SERIAL_DTR_HANDSHAKE;
shf->ControlHandShake |= SERIAL_CTS_HANDSHAKE;
}
else
#endif
{
#ifdef TIOCM_RTS
if (stat & TIOCM_RTS)
#endif
shf->ControlHandShake |= SERIAL_RTS_CONTROL;
}
if (port.c_iflag & IXON)
shf->FlowReplace |= SERIAL_AUTO_RECEIVE;
if (port.c_iflag & IXOFF)
shf->FlowReplace |= SERIAL_AUTO_TRANSMIT;
shf->XonLimit = 10;
shf->XoffLimit = 10;
return STATUS_SUCCESS;
}
static NTSTATUS get_line_control(int fd, SERIAL_LINE_CONTROL* slc) static NTSTATUS get_line_control(int fd, SERIAL_LINE_CONTROL* slc)
{ {
struct termios port; struct termios port;
...@@ -739,6 +787,15 @@ NTSTATUS COMM_DeviceIoControl(HANDLE hDevice, ...@@ -739,6 +787,15 @@ NTSTATUS COMM_DeviceIoControl(HANDLE hDevice,
} }
else status = STATUS_INVALID_PARAMETER; else status = STATUS_INVALID_PARAMETER;
break; break;
case IOCTL_SERIAL_GET_HANDFLOW:
if (lpOutBuffer && nOutBufferSize == sizeof(SERIAL_HANDFLOW))
{
if (!(status = get_hand_flow(fd, (SERIAL_HANDFLOW*)lpOutBuffer)))
sz = sizeof(SERIAL_HANDFLOW);
}
else
status = STATUS_INVALID_PARAMETER;
break;
case IOCTL_SERIAL_GET_LINE_CONTROL: case IOCTL_SERIAL_GET_LINE_CONTROL:
if (lpOutBuffer && nOutBufferSize == sizeof(SERIAL_LINE_CONTROL)) if (lpOutBuffer && nOutBufferSize == sizeof(SERIAL_LINE_CONTROL))
{ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment