ntdll/kernel32: GetCommState & SERIAL_GET_LINE_CONTROL

- implemented SERIAL_GET_LINE_CONTROL ioctl
- made use of it in kernel.GetCommState
This commit is contained in:
Eric Pouech 2006-05-07 14:10:49 +02:00 committed by Alexandre Julliard
parent c7016d9325
commit efb3244b0a
2 changed files with 66 additions and 50 deletions

View File

@ -1082,6 +1082,7 @@ BOOL WINAPI GetCommState(HANDLE handle, LPDCB lpdcb)
int stat = DTR_CONTROL_ENABLE | RTS_CONTROL_ENABLE;
SERIAL_BAUD_RATE sbr;
SERIAL_LINE_CONTROL slc;
TRACE("handle %p, ptr %p\n", handle, lpdcb);
@ -1093,13 +1094,21 @@ BOOL WINAPI GetCommState(HANDLE handle, LPDCB lpdcb)
lpdcb->DCBlength = sizeof(*lpdcb);
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,
NULL, 0, &slc, sizeof(slc), NULL, NULL))
return FALSE;
/* yes, they seem no never be (re)set on NT */
lpdcb->fBinary = 1;
lpdcb->fParity = 0;
lpdcb->BaudRate = sbr.BaudRate;
lpdcb->StopBits = slc.StopBits;
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) {
@ -1118,59 +1127,10 @@ BOOL WINAPI GetCommState(HANDLE handle, LPDCB lpdcb)
}
#endif
release_comm_fd( handle, fd );
switch (port.c_cflag & CSIZE) {
case CS5:
lpdcb->ByteSize = 5;
break;
case CS6:
lpdcb->ByteSize = 6;
break;
case CS7:
lpdcb->ByteSize = 7;
break;
case CS8:
lpdcb->ByteSize = 8;
break;
default:
ERR("unknown size %x\n", port.c_cflag & CSIZE);
}
if(port.c_iflag & INPCK)
lpdcb->fParity = TRUE;
else
lpdcb->fParity = FALSE;
#ifdef CMSPAR
switch (port.c_cflag & (PARENB | PARODD | CMSPAR))
#else
switch (port.c_cflag & (PARENB | PARODD))
#endif
{
case 0:
lpdcb->Parity = NOPARITY;
break;
case PARENB:
lpdcb->Parity = EVENPARITY;
break;
case (PARENB | PARODD):
lpdcb->Parity = ODDPARITY;
break;
#ifdef CMSPAR
case (PARENB | CMSPAR):
lpdcb->Parity = MARKPARITY;
break;
case (PARENB | PARODD | CMSPAR):
lpdcb->Parity = SPACEPARITY;
break;
#endif
}
if (port.c_cflag & CSTOPB)
if(lpdcb->ByteSize == 5)
lpdcb->StopBits = ONE5STOPBITS;
else
lpdcb->StopBits = TWOSTOPBITS;
else
lpdcb->StopBits = ONESTOPBIT;
lpdcb->fNull = 0;

View File

@ -185,6 +185,53 @@ static NTSTATUS get_baud_rate(int fd, SERIAL_BAUD_RATE* sbr)
return STATUS_SUCCESS;
}
static NTSTATUS get_line_control(int fd, SERIAL_LINE_CONTROL* slc)
{
struct termios port;
if (tcgetattr(fd, &port) == -1)
{
ERR("tcgetattr error '%s'\n", strerror(errno));
return FILE_GetNtStatus();
}
#ifdef CMSPAR
switch (port.c_cflag & (PARENB | PARODD | CMSPAR))
#else
switch (port.c_cflag & (PARENB | PARODD))
#endif
{
case 0: slc->Parity = NOPARITY; break;
case PARENB: slc->Parity = EVENPARITY; break;
case PARENB|PARODD: slc->Parity = ODDPARITY; break;
#ifdef CMSPAR
case PARENB|CMSPAR: slc->Parity = MARKPARITY; break;
case PARENB|PARODD|CMSPAR: slc->Parity = SPACEPARITY; break;
break;
#endif
}
switch (port.c_cflag & CSIZE)
{
case CS5: slc->WordLength = 5; break;
case CS6: slc->WordLength = 6; break;
case CS7: slc->WordLength = 7; break;
case CS8: slc->WordLength = 8; break;
default: ERR("unknown size %x\n", port.c_cflag & CSIZE);
}
if (port.c_cflag & CSTOPB)
{
if (slc->WordLength == 5)
slc->StopBits = ONE5STOPBITS;
else
slc->StopBits = TWOSTOPBITS;
}
else
slc->StopBits = ONESTOPBIT;
return STATUS_SUCCESS;
}
static NTSTATUS get_modem_status(int fd, DWORD* lpModemStat)
{
NTSTATUS status = STATUS_SUCCESS;
@ -692,6 +739,15 @@ NTSTATUS COMM_DeviceIoControl(HANDLE hDevice,
}
else status = STATUS_INVALID_PARAMETER;
break;
case IOCTL_SERIAL_GET_LINE_CONTROL:
if (lpOutBuffer && nOutBufferSize == sizeof(SERIAL_LINE_CONTROL))
{
if (!(status = get_line_control(fd, (SERIAL_LINE_CONTROL*)lpOutBuffer)))
sz = sizeof(SERIAL_LINE_CONTROL);
}
else
status = STATUS_INVALID_PARAMETER;
break;
case IOCTL_SERIAL_GET_MODEMSTATUS:
if (lpOutBuffer && nOutBufferSize == sizeof(DWORD))
{