From efb3244b0aeec890e16b210b1b25e424777b8147 Mon Sep 17 00:00:00 2001 From: Eric Pouech Date: Sun, 7 May 2006 14:10:49 +0200 Subject: [PATCH] ntdll/kernel32: GetCommState & SERIAL_GET_LINE_CONTROL - implemented SERIAL_GET_LINE_CONTROL ioctl - made use of it in kernel.GetCommState --- dlls/kernel/comm.c | 60 ++++++++------------------------------------- dlls/ntdll/serial.c | 56 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 50 deletions(-) diff --git a/dlls/kernel/comm.c b/dlls/kernel/comm.c index 8fd765b01df..6fa5b89d244 100644 --- a/dlls/kernel/comm.c +++ b/dlls/kernel/comm.c @@ -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; diff --git a/dlls/ntdll/serial.c b/dlls/ntdll/serial.c index c86dc66e511..0a6d8f12db2 100644 --- a/dlls/ntdll/serial.c +++ b/dlls/ntdll/serial.c @@ -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)) {