ntdll/kernel32: GetCommState & IOCTL_SERIAL_GET_HANDFLOW
- implemented SERIAL_GET_HANDFLOW ioctl - made use of it in kernel.GetCommState
This commit is contained in:
parent
efb3244b0a
commit
48646ea82b
|
@ -1077,12 +1077,9 @@ BOOL WINAPI SetCommState( 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_LINE_CONTROL slc;
|
||||
SERIAL_HANDFLOW shf;
|
||||
|
||||
TRACE("handle %p, ptr %p\n", handle, lpdcb);
|
||||
|
||||
|
@ -1091,14 +1088,18 @@ BOOL WINAPI GetCommState(HANDLE handle, LPDCB lpdcb)
|
|||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
lpdcb->DCBlength = sizeof(*lpdcb);
|
||||
|
||||
if (!DeviceIoControl(handle, IOCTL_SERIAL_GET_BAUD_RATE,
|
||||
NULL, 0, &sbr, sizeof(sbr), NULL, NULL) ||
|
||||
!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;
|
||||
|
||||
memset(lpdcb, 0, sizeof(*lpdcb));
|
||||
lpdcb->DCBlength = sizeof(*lpdcb);
|
||||
|
||||
/* yes, they seem no never be (re)set on NT */
|
||||
lpdcb->fBinary = 1;
|
||||
lpdcb->fParity = 0;
|
||||
|
@ -1109,69 +1110,37 @@ BOOL WINAPI GetCommState(HANDLE handle, LPDCB lpdcb)
|
|||
lpdcb->Parity = slc.Parity;
|
||||
lpdcb->ByteSize = slc.WordLength;
|
||||
|
||||
fd = get_comm_fd( handle, FILE_READ_DATA );
|
||||
if (fd < 0) return FALSE;
|
||||
if (tcgetattr(fd, &port) == -1) {
|
||||
int save_error=errno;
|
||||
ERR("tcgetattr error '%s'\n", strerror(save_error));
|
||||
release_comm_fd( handle, fd );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#ifdef TIOCMGET
|
||||
if (ioctl(fd, TIOCMGET, &stat) == -1)
|
||||
{
|
||||
int save_error=errno;
|
||||
WARN("ioctl error '%s'\n", strerror(save_error));
|
||||
stat = DTR_CONTROL_ENABLE | RTS_CONTROL_ENABLE;
|
||||
}
|
||||
#endif
|
||||
release_comm_fd( handle, fd );
|
||||
if(port.c_iflag & INPCK)
|
||||
lpdcb->fParity = TRUE;
|
||||
else
|
||||
lpdcb->fParity = FALSE;
|
||||
if (shf.ControlHandShake & SERIAL_CTS_HANDSHAKE) lpdcb->fOutxCtsFlow = 1;
|
||||
if (shf.ControlHandShake & SERIAL_DSR_HANDSHAKE) lpdcb->fOutxDsrFlow = 1;
|
||||
switch (shf.ControlHandShake & (SERIAL_DTR_CONTROL | SERIAL_DTR_HANDSHAKE))
|
||||
{
|
||||
case 0: lpdcb->fDtrControl = DTR_CONTROL_DISABLE; break;
|
||||
case SERIAL_DTR_CONTROL: lpdcb->fDtrControl = DTR_CONTROL_ENABLE; break;
|
||||
case SERIAL_DTR_HANDSHAKE: lpdcb->fDtrControl = DTR_CONTROL_HANDSHAKE; break;
|
||||
}
|
||||
switch (shf.FlowReplace & (SERIAL_RTS_CONTROL | SERIAL_RTS_HANDSHAKE))
|
||||
{
|
||||
case 0: lpdcb->fRtsControl = RTS_CONTROL_DISABLE; break;
|
||||
case SERIAL_RTS_CONTROL: lpdcb->fRtsControl = RTS_CONTROL_ENABLE; break;
|
||||
case SERIAL_RTS_HANDSHAKE: lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE; break;
|
||||
case SERIAL_RTS_CONTROL | SERIAL_RTS_HANDSHAKE:
|
||||
lpdcb->fRtsControl = RTS_CONTROL_TOGGLE; break;
|
||||
}
|
||||
if (shf.ControlHandShake & SERIAL_DSR_SENSITIVITY) lpdcb->fDsrSensitivity = 1;
|
||||
if (shf.ControlHandShake & SERIAL_ERROR_ABORT) lpdcb->fAbortOnError = 1;
|
||||
if (shf.FlowReplace & SERIAL_ERROR_CHAR) lpdcb->fErrorChar = 1;
|
||||
if (shf.FlowReplace & SERIAL_NULL_STRIPPING) lpdcb->fNull = 1;
|
||||
if (shf.FlowReplace & SERIAL_XOFF_CONTINUE) lpdcb->fTXContinueOnXoff = 1;
|
||||
lpdcb->XonLim = shf.XonLimit;
|
||||
lpdcb->XoffLim = shf.XoffLimit;
|
||||
|
||||
lpdcb->fNull = 0;
|
||||
if (shf.FlowReplace & SERIAL_AUTO_TRANSMIT) lpdcb->fOutX = 1;
|
||||
if (shf.FlowReplace & SERIAL_AUTO_RECEIVE) lpdcb->fInX = 1;
|
||||
|
||||
/* 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 (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->XoffChar =
|
||||
*/
|
||||
lpdcb->XonLim = 10;
|
||||
lpdcb->XoffLim = 10;
|
||||
|
||||
TRACE("OK\n");
|
||||
dump_dcb(lpdcb);
|
||||
|
|
|
@ -185,6 +185,54 @@ static NTSTATUS get_baud_rate(int fd, SERIAL_BAUD_RATE* sbr)
|
|||
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)
|
||||
{
|
||||
struct termios port;
|
||||
|
@ -739,6 +787,15 @@ NTSTATUS COMM_DeviceIoControl(HANDLE hDevice,
|
|||
}
|
||||
else status = STATUS_INVALID_PARAMETER;
|
||||
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:
|
||||
if (lpOutBuffer && nOutBufferSize == sizeof(SERIAL_LINE_CONTROL))
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue