Termios2 is a modern Linux feature thats allows usage of any custom baudrate instead of hardcoded values from the 1970's. Also, this patch improves compatibility with the win32 api, because windows allow any custom baudrates by design.
Example software for which this patch is needed: http://www.vi-soft.com.ua/index_e.htm
This software for reading/writing/patch fullflash of Siemens mobile phones, where serial speed is important. V-Klay uses 1600000 baudrate and perfectly works on Linux with termios2 and Prolific PL2303.
From: Kirill Zhumarin kirill.zhumarin@gmail.com
--- configure | 6 ++ dlls/ntdll/Makefile.in | 1 + .../ntdll/i386-windows/unix/serial_termios2.o | 0 dlls/ntdll/unix/serial.c | 14 +++ dlls/ntdll/unix/serial_termios2.c | 87 +++++++++++++++++++ dlls/ntdll/unix/unix_private.h | 6 ++ include/config.h.in | 3 + 7 files changed, 117 insertions(+) create mode 100644 dlls/ntdll/i386-windows/unix/serial_termios2.o create mode 100644 dlls/ntdll/unix/serial_termios2.c
diff --git a/configure b/configure index 83a641ff542..bc8141dfe67 100755 --- a/configure +++ b/configure @@ -7989,6 +7989,12 @@ if test "x$ac_cv_header_linux_serial_h" = xyes then : printf "%s\n" "#define HAVE_LINUX_SERIAL_H 1" >>confdefs.h
+fi +ac_fn_c_check_header_compile "$LINENO" "asm/termbits.h" "ac_cv_header_asm_termbits_h" "$ac_includes_default" +if test "x$ac_cv_header_asm_termbits_h" = xyes +then : + printf "%s\n" "#define HAVE_ASM_TERMBITS_H 1" >>confdefs.h + fi ac_fn_c_check_header_compile "$LINENO" "linux/types.h" "ac_cv_header_linux_types_h" "$ac_includes_default" if test "x$ac_cv_header_linux_types_h" = xyes diff --git a/dlls/ntdll/Makefile.in b/dlls/ntdll/Makefile.in index b519bcd655f..d6fa26ea1d3 100644 --- a/dlls/ntdll/Makefile.in +++ b/dlls/ntdll/Makefile.in @@ -55,6 +55,7 @@ SOURCES = \ unix/registry.c \ unix/security.c \ unix/serial.c \ + unix/serial_termios2.c \ unix/server.c \ unix/signal_arm.c \ unix/signal_arm64.c \ diff --git a/dlls/ntdll/i386-windows/unix/serial_termios2.o b/dlls/ntdll/i386-windows/unix/serial_termios2.o new file mode 100644 index 00000000000..e69de29bb2d diff --git a/dlls/ntdll/unix/serial.c b/dlls/ntdll/unix/serial.c index 372103b4df8..b4601bfeb3c 100644 --- a/dlls/ntdll/unix/serial.c +++ b/dlls/ntdll/unix/serial.c @@ -122,6 +122,14 @@ static NTSTATUS get_baud_rate(int fd, SERIAL_BAUD_RATE* sbr) struct termios port; int speed;
+#ifdef HAVE_ASM_TERMBITS_H + /* If termios2 is supported, first try to use it. Otherwise, use termios as a fallback. */ + if (serial_get_baud_rate_termios2(fd, &speed) == STATUS_SUCCESS) { + sbr->BaudRate = speed; + return STATUS_SUCCESS; + } +#endif + if (tcgetattr(fd, &port) == -1) { ERR("tcgetattr error '%s'\n", strerror(errno)); @@ -455,6 +463,12 @@ static NTSTATUS set_baud_rate(int fd, const SERIAL_BAUD_RATE* sbr) { struct termios port;
+#ifdef HAVE_ASM_TERMBITS_H + /* If termios2 is supported, first try to use it. Otherwise, use termios as a fallback. */ + if (serial_set_baud_rate_termios2(fd, sbr->BaudRate) == STATUS_SUCCESS) + return STATUS_SUCCESS; +#endif + if (tcgetattr(fd, &port) == -1) { ERR("tcgetattr error '%s'\n", strerror(errno)); diff --git a/dlls/ntdll/unix/serial_termios2.c b/dlls/ntdll/unix/serial_termios2.c new file mode 100644 index 00000000000..84be6ac6b5f --- /dev/null +++ b/dlls/ntdll/unix/serial_termios2.c @@ -0,0 +1,87 @@ +/* + * Linux termios2 support + * + * Copyright 2024 Kirill Zhumarin + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#if 0 +#pragma makedep unix +#endif + +#include "config.h" + +#include <errno.h> +#include <sys/ioctl.h> +#ifdef HAVE_ASM_TERMBITS_H +#include <asm/termbits.h> +#endif + +#include "ntstatus.h" +#define WIN32_NO_STATUS +#include "windef.h" +#include "winternl.h" +#include "winioctl.h" +#include "ddk/ntddser.h" +#include "wine/server.h" +#include "unix_private.h" +#include "wine/debug.h" +#include "unix_private.h" + +WINE_DEFAULT_DEBUG_CHANNEL(comm); + +#ifdef HAVE_ASM_TERMBITS_H +NTSTATUS serial_set_baud_rate_termios2( int fd, int baudrate ) { + struct termios2 port; + + if (ioctl(fd, TCGETS2, &port) == -1) + { + ERR("ioctl TCGETS2 error '%s'\n", strerror(errno)); + return errno_to_status( errno ); + } + + port.c_cflag &= ~CBAUD; + port.c_cflag |= BOTHER; + port.c_ospeed = baudrate; + + port.c_cflag &= ~(CBAUD << IBSHIFT); + port.c_cflag |= BOTHER << IBSHIFT; + port.c_ispeed = baudrate; + + if (ioctl(fd, TCSETS2, &port) == -1) + { + ERR("ioctl TCSETS2 error '%s'\n", strerror(errno)); + return errno_to_status( errno ); + } + + return STATUS_SUCCESS; +} + +NTSTATUS serial_get_baud_rate_termios2( int fd, int* baudrate ) { + struct termios2 port; + + if (ioctl(fd, TCGETS2, &port) == -1) + { + ERR("ioctl TCGETS2 error '%s'\n", strerror(errno)); + return errno_to_status( errno ); + } + + /* TERMIOS2 supports separate input and output baudrate, but wine supports only the common baudrate. */ + *baudrate = port.c_ispeed; + + return STATUS_SUCCESS; +} +#endif diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h index b249570d421..1fc8a65ef4e 100644 --- a/dlls/ntdll/unix/unix_private.h +++ b/dlls/ntdll/unix/unix_private.h @@ -308,6 +308,12 @@ extern NTSTATUS serial_DeviceIoControl( HANDLE device, HANDLE event, PIO_APC_ROU IO_STATUS_BLOCK *io, UINT code, void *in_buffer, UINT in_size, void *out_buffer, UINT out_size ); extern NTSTATUS serial_FlushBuffersFile( int fd ); + +#ifdef HAVE_ASM_TERMBITS_H +extern NTSTATUS serial_set_baud_rate_termios2( int fd, int baudrate ); +extern NTSTATUS serial_get_baud_rate_termios2( int fd, int *baudrate ); +#endif + extern NTSTATUS sock_ioctl( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc_user, IO_STATUS_BLOCK *io, UINT code, void *in_buffer, UINT in_size, void *out_buffer, UINT out_size ); extern NTSTATUS sock_read( HANDLE handle, int fd, HANDLE event, PIO_APC_ROUTINE apc, void *apc_user, diff --git a/include/config.h.in b/include/config.h.in index a910b2c85f1..68b8c932bf7 100644 --- a/include/config.h.in +++ b/include/config.h.in @@ -183,6 +183,9 @@ /* Define to 1 if you have the <linux/serial.h> header file. */ #undef HAVE_LINUX_SERIAL_H
+/* Define to 1 if you have the <asm/termbits.h> header file. */ +#undef HAVE_ASM_TERMBITS_H + /* Define to 1 if you have the <linux/types.h> header file. */ #undef HAVE_LINUX_TYPES_H
This merge request was closed by Kirill Zhumarin.
Broken MR with .o files :( :( :(