ntdll/kernel32: SetCommState & IOCTL_SET_LINE_CONTROL
- implemented ntdll's serial IOCTL SET_LINE_CONTROL - used this IOCTL in kernel32.SetCommState
This commit is contained in:
parent
631ec30f78
commit
65f137c56c
|
@ -984,11 +984,12 @@ static void dump_dcb(const DCB* lpdcb)
|
||||||
BOOL WINAPI SetCommState( HANDLE handle, LPDCB lpdcb)
|
BOOL WINAPI SetCommState( HANDLE handle, LPDCB lpdcb)
|
||||||
{
|
{
|
||||||
struct termios port;
|
struct termios port;
|
||||||
int fd, bytesize, stopbits;
|
int fd;
|
||||||
BOOL ret;
|
BOOL ret;
|
||||||
|
|
||||||
SERIAL_BAUD_RATE sbr;
|
SERIAL_BAUD_RATE sbr;
|
||||||
|
SERIAL_LINE_CONTROL slc;
|
||||||
|
|
||||||
if (lpdcb == NULL)
|
if (lpdcb == NULL)
|
||||||
{
|
{
|
||||||
SetLastError(ERROR_INVALID_PARAMETER);
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||||||
|
@ -997,9 +998,17 @@ BOOL WINAPI SetCommState( HANDLE handle, LPDCB lpdcb)
|
||||||
dump_dcb(lpdcb);
|
dump_dcb(lpdcb);
|
||||||
|
|
||||||
sbr.BaudRate = lpdcb->BaudRate;
|
sbr.BaudRate = lpdcb->BaudRate;
|
||||||
|
|
||||||
|
slc.StopBits = lpdcb->StopBits;
|
||||||
|
slc.Parity = lpdcb->Parity;
|
||||||
|
slc.WordLength = lpdcb->ByteSize;
|
||||||
|
|
||||||
if (!DeviceIoControl(handle, IOCTL_SERIAL_SET_BAUD_RATE,
|
if (!DeviceIoControl(handle, IOCTL_SERIAL_SET_BAUD_RATE,
|
||||||
&sbr, sizeof(sbr), NULL, 0, NULL, NULL))
|
&sbr, sizeof(sbr), NULL, 0, NULL, NULL))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
if (!DeviceIoControl(handle, IOCTL_SERIAL_SET_LINE_CONTROL,
|
||||||
|
&slc, sizeof(slc), NULL, 0, NULL, NULL))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
fd = get_comm_fd( handle, FILE_READ_DATA );
|
fd = get_comm_fd( handle, FILE_READ_DATA );
|
||||||
if (fd < 0) return FALSE;
|
if (fd < 0) return FALSE;
|
||||||
|
@ -1014,113 +1023,6 @@ BOOL WINAPI SetCommState( HANDLE handle, LPDCB lpdcb)
|
||||||
port.c_cc[VMIN] = 0;
|
port.c_cc[VMIN] = 0;
|
||||||
port.c_cc[VTIME] = 1;
|
port.c_cc[VTIME] = 1;
|
||||||
|
|
||||||
#ifdef IMAXBEL
|
|
||||||
port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|PARMRK|IMAXBEL);
|
|
||||||
#else
|
|
||||||
port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|PARMRK);
|
|
||||||
#endif
|
|
||||||
port.c_iflag |= (IGNBRK);
|
|
||||||
|
|
||||||
port.c_oflag &= ~(OPOST);
|
|
||||||
|
|
||||||
port.c_cflag &= ~(HUPCL);
|
|
||||||
port.c_cflag |= CLOCAL | CREAD;
|
|
||||||
|
|
||||||
port.c_lflag &= ~(ICANON|ECHO|ISIG);
|
|
||||||
port.c_lflag |= NOFLSH;
|
|
||||||
|
|
||||||
bytesize=lpdcb->ByteSize;
|
|
||||||
stopbits=lpdcb->StopBits;
|
|
||||||
|
|
||||||
#ifdef CMSPAR
|
|
||||||
port.c_cflag &= ~(PARENB | PARODD | CMSPAR);
|
|
||||||
#else
|
|
||||||
port.c_cflag &= ~(PARENB | PARODD);
|
|
||||||
#endif
|
|
||||||
if (lpdcb->fParity)
|
|
||||||
port.c_iflag |= INPCK;
|
|
||||||
else
|
|
||||||
port.c_iflag &= ~INPCK;
|
|
||||||
switch (lpdcb->Parity) {
|
|
||||||
case NOPARITY:
|
|
||||||
break;
|
|
||||||
case ODDPARITY:
|
|
||||||
port.c_cflag |= (PARENB | PARODD);
|
|
||||||
break;
|
|
||||||
case EVENPARITY:
|
|
||||||
port.c_cflag |= PARENB;
|
|
||||||
break;
|
|
||||||
#ifdef CMSPAR
|
|
||||||
/* Linux defines mark/space (stick) parity */
|
|
||||||
case MARKPARITY:
|
|
||||||
port.c_cflag |= (PARENB | CMSPAR);
|
|
||||||
break;
|
|
||||||
case SPACEPARITY:
|
|
||||||
port.c_cflag |= (PARENB | PARODD | CMSPAR);
|
|
||||||
break;
|
|
||||||
#else
|
|
||||||
/* try the POSIX way */
|
|
||||||
case MARKPARITY:
|
|
||||||
if( stopbits == ONESTOPBIT) {
|
|
||||||
stopbits = TWOSTOPBITS;
|
|
||||||
port.c_iflag &= ~INPCK;
|
|
||||||
} else {
|
|
||||||
release_comm_fd( handle, fd );
|
|
||||||
ERR("Cannot set MARK Parity\n");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case SPACEPARITY:
|
|
||||||
if( bytesize < 8) {
|
|
||||||
bytesize +=1;
|
|
||||||
port.c_iflag &= ~INPCK;
|
|
||||||
} else {
|
|
||||||
release_comm_fd( handle, fd );
|
|
||||||
ERR("Cannot set SPACE Parity\n");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
default:
|
|
||||||
release_comm_fd( handle, fd );
|
|
||||||
ERR("Parity\n");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
port.c_cflag &= ~CSIZE;
|
|
||||||
switch (bytesize) {
|
|
||||||
case 5:
|
|
||||||
port.c_cflag |= CS5;
|
|
||||||
break;
|
|
||||||
case 6:
|
|
||||||
port.c_cflag |= CS6;
|
|
||||||
break;
|
|
||||||
case 7:
|
|
||||||
port.c_cflag |= CS7;
|
|
||||||
break;
|
|
||||||
case 8:
|
|
||||||
port.c_cflag |= CS8;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
release_comm_fd( handle, fd );
|
|
||||||
ERR("ByteSize\n");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (stopbits) {
|
|
||||||
case ONESTOPBIT:
|
|
||||||
port.c_cflag &= ~CSTOPB;
|
|
||||||
break;
|
|
||||||
case ONE5STOPBITS: /* will be selected if bytesize is 5 */
|
|
||||||
case TWOSTOPBITS:
|
|
||||||
port.c_cflag |= CSTOPB;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
release_comm_fd( handle, fd );
|
|
||||||
ERR("StopBits\n");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
#ifdef CRTSCTS
|
#ifdef CRTSCTS
|
||||||
if ( lpdcb->fOutxCtsFlow ||
|
if ( lpdcb->fOutxCtsFlow ||
|
||||||
lpdcb->fRtsControl == RTS_CONTROL_HANDSHAKE
|
lpdcb->fRtsControl == RTS_CONTROL_HANDSHAKE
|
||||||
|
|
|
@ -360,6 +360,112 @@ static NTSTATUS set_baud_rate(int fd, const SERIAL_BAUD_RATE* sbr)
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static NTSTATUS set_line_control(int fd, const SERIAL_LINE_CONTROL* slc)
|
||||||
|
{
|
||||||
|
struct termios port;
|
||||||
|
unsigned bytesize, stopbits;
|
||||||
|
|
||||||
|
if (tcgetattr(fd, &port) == -1)
|
||||||
|
{
|
||||||
|
ERR("tcgetattr error '%s'\n", strerror(errno));
|
||||||
|
return FILE_GetNtStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef IMAXBEL
|
||||||
|
port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|PARMRK|IMAXBEL);
|
||||||
|
#else
|
||||||
|
port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|PARMRK);
|
||||||
|
#endif
|
||||||
|
port.c_iflag |= IGNBRK | INPCK;
|
||||||
|
|
||||||
|
port.c_oflag &= ~(OPOST);
|
||||||
|
|
||||||
|
port.c_cflag &= ~(HUPCL);
|
||||||
|
port.c_cflag |= CLOCAL | CREAD;
|
||||||
|
|
||||||
|
port.c_lflag &= ~(ICANON|ECHO|ISIG);
|
||||||
|
port.c_lflag |= NOFLSH;
|
||||||
|
|
||||||
|
bytesize = slc->WordLength;
|
||||||
|
stopbits = slc->StopBits;
|
||||||
|
|
||||||
|
#ifdef CMSPAR
|
||||||
|
port.c_cflag &= ~(PARENB | PARODD | CMSPAR);
|
||||||
|
#else
|
||||||
|
port.c_cflag &= ~(PARENB | PARODD);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
switch (slc->Parity)
|
||||||
|
{
|
||||||
|
case NOPARITY: port.c_iflag &= ~INPCK; break;
|
||||||
|
case ODDPARITY: port.c_cflag |= PARENB | PARODD; break;
|
||||||
|
case EVENPARITY: port.c_cflag |= PARENB; break;
|
||||||
|
#ifdef CMSPAR
|
||||||
|
/* Linux defines mark/space (stick) parity */
|
||||||
|
case MARKPARITY: port.c_cflag |= PARENB | CMSPAR; break;
|
||||||
|
case SPACEPARITY: port.c_cflag |= PARENB | PARODD | CMSPAR; break;
|
||||||
|
#else
|
||||||
|
/* try the POSIX way */
|
||||||
|
case MARKPARITY:
|
||||||
|
if (slc->StopBits == ONESTOPBIT)
|
||||||
|
{
|
||||||
|
stopbits = TWOSTOPBITS;
|
||||||
|
port.c_iflag &= ~INPCK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ERR("Cannot set MARK Parity\n");
|
||||||
|
return STATUS_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SPACEPARITY:
|
||||||
|
if (slc->WordLength < 8)
|
||||||
|
{
|
||||||
|
bytesize +=1;
|
||||||
|
port.c_iflag &= ~INPCK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ERR("Cannot set SPACE Parity\n");
|
||||||
|
return STATUS_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
ERR("Parity\n");
|
||||||
|
return STATUS_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
port.c_cflag &= ~CSIZE;
|
||||||
|
switch (bytesize)
|
||||||
|
{
|
||||||
|
case 5: port.c_cflag |= CS5; break;
|
||||||
|
case 6: port.c_cflag |= CS6; break;
|
||||||
|
case 7: port.c_cflag |= CS7; break;
|
||||||
|
case 8: port.c_cflag |= CS8; break;
|
||||||
|
default:
|
||||||
|
ERR("ByteSize\n");
|
||||||
|
return STATUS_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (stopbits)
|
||||||
|
{
|
||||||
|
case ONESTOPBIT: port.c_cflag &= ~CSTOPB; break;
|
||||||
|
case ONE5STOPBITS: /* will be selected if bytesize is 5 */
|
||||||
|
case TWOSTOPBITS: port.c_cflag |= CSTOPB; break;
|
||||||
|
default:
|
||||||
|
ERR("StopBits\n");
|
||||||
|
return STATUS_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
/* otherwise it hangs with pending input*/
|
||||||
|
if (tcsetattr(fd, TCSANOW, &port) == -1)
|
||||||
|
{
|
||||||
|
ERR("tcsetattr error '%s'\n", strerror(errno));
|
||||||
|
return FILE_GetNtStatus();
|
||||||
|
}
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
static NTSTATUS set_wait_mask(HANDLE hDevice, DWORD mask)
|
static NTSTATUS set_wait_mask(HANDLE hDevice, DWORD mask)
|
||||||
{
|
{
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
|
@ -478,6 +584,12 @@ NTSTATUS COMM_DeviceIoControl(HANDLE hDevice,
|
||||||
status = STATUS_NOT_SUPPORTED;
|
status = STATUS_NOT_SUPPORTED;
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
|
case IOCTL_SERIAL_SET_LINE_CONTROL:
|
||||||
|
if (lpInBuffer && nInBufferSize == sizeof(SERIAL_LINE_CONTROL))
|
||||||
|
status = set_line_control(fd, (const SERIAL_LINE_CONTROL*)lpInBuffer);
|
||||||
|
else
|
||||||
|
status = STATUS_INVALID_PARAMETER;
|
||||||
|
break;
|
||||||
case IOCTL_SERIAL_SET_WAIT_MASK:
|
case IOCTL_SERIAL_SET_WAIT_MASK:
|
||||||
if (lpInBuffer && nInBufferSize == sizeof(DWORD))
|
if (lpInBuffer && nInBufferSize == sizeof(DWORD))
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue