Index: README
===================================================================
--- README	(.../tags/RELEASE_2_1_5)	(Revision 1759)
+++ README	(.../branches/bw-rs232speed)	(Revision 1877)
@@ -224,7 +224,10 @@ Konfiguration
       Yes/No
 
     improve-nmradcc-timing
-      Yes/No recommended: Yes
+      Yes/No/termios2 recommendation: see "man 5 srcpd.conf"
+      
+    nmradcc_baudrate
+      custom baudrate in case of improve-nmradcc-timing=termios2
 
     nmradcc-translation-routine
       1, 2 or 3 recommended: 3
Index: man/de/srcpd.conf.5
===================================================================
--- man/de/srcpd.conf.5	(.../tags/RELEASE_2_1_5)	(Revision 1759)
+++ man/de/srcpd.conf.5	(.../branches/bw-rs232speed)	(Revision 1877)
@@ -448,16 +448,31 @@ CPU-Last ist das nicht benötigte Protok
 .\"
 .TP
 improve_nmradcc_timing
-Dieser Wert sollte im reinen NMRA-DCC-Betrieb auf
-.IR yes
-gesetzt werden.  In allen anderen Situation - also falls
-.IR enable_marklin
-auf
-.IR yes
-gesetzt ist - muss(!) dieser Wert auf
-.IR no
-gesetzt werden.  Der voreingestellte Wert ist
-.IR no .
+Gültige Werte sind \fByes\fR, \fBno\fR oder \fBtermios2\fR.
+Die voreingestellte Baudrate für DDL (Wert \fBno\fR) ist 19200\ baud, was 
+etwas mehr ist als
+vom NMRA DCC Standard erlaubt. Mit dem UART 16550A kann dieser Wert durch die
+Einstellung \fByes\fR auf
+16457\ baud gesetzt werden, was in der Spezifikation liegt. Dies ist nur bei
+Timing Problemen mit der Voreinstellung nötig.
+
+\fBtermios2\fR ist eine
+alternative Möglichkeit unter Linux, Nicht-Standard Baudraten zu setzen, wenn 
+die Hardware
+das unterstützt. Im Gegensatz zu \fByes\fR unterstützt diese Methode auch neuere
+Linux Kernels.
+Mit dieser Einstellung kann die Baudrate individuell mittels
+des Parameters nmradcc_baudrate gesetzt werden. Auch diese Einstellung sowie
+die sich daraus tatsächlich ergebende Baudrate sind Hardware-abhängig.
+(Auf einem Raspberry Pi mit baud base 3000000 können durch Teilung granularere
+Baudraten erzielt werden als mit der voreingestellten baud base 115200 des
+UART 16550A eines Standard PCs.) 
+.\"
+.TP
+nmradcc_baudrate
+Individuelle Baudrate für NMRA DCC im Falle improve_nmradcc_timing=\fBtermios2\fR. 
+Voreinstellung=17287.
+Bei einer Änderung der Voreinstellung den NMRA-Standard beachten!
 .\"
 .TP
 nmra_ga_offset
Index: man/srcpd.conf.5
===================================================================
--- man/srcpd.conf.5	(.../tags/RELEASE_2_1_5)	(Revision 1759)
+++ man/srcpd.conf.5	(.../branches/bw-rs232speed)	(Revision 1877)
@@ -369,13 +369,28 @@ disabled.
 .\"
 .TP
 improve_nmradcc_timing
-The default baudrate of DDL is 19200\ baud, which is slightly higher
-than allowed by NMRA DCC standard.  With a UART 16550A you can change the
-baudrate to  16457\ baud, which is within the specification.  This is
+Valid input values are \fByes\fR, \fBno\fR or \fBtermios2\fR.
+The default baudrate of DDL (setting \fBno\fR) is 19200\ baud, 
+which is slightly higher
+than allowed by NMRA DCC standard.  With a UART 16550A
+you can change the
+baudrate to  16457\ baud  by setting this parameter to \fByes\fR, so the
+baudrate is within the specification.  This is
 only needed if you have timing problems with the default.
-Valid input values are \fByes\fR or \fBno\fR.  The default value is
-\fBno\fR, which
-corresponds to 19200\ baud.
+
+\fBtermios2\fR is an alternative method in linux to set a non-standard
+baudrate if the hardware supports it. In contrast to \fByes\fR it supports
+newer linux kernels as well.
+With this method, the baudrate can be set by the nmradcc_baudrate parameter.
+This setting is hardware-dependent as well as the resulting real baudrate.
+(On a Raspberry Pi with baud base 3000000 more granular baudrates can be got
+by division than with the preset baud base 115200 of a
+standard PC's UART 16550A.)
+.\"
+.TP
+nmradcc_baudrate
+Custom baudrate for NMRA DCC in case of improve_nmradcc_timing=\fBtermios2\fR. Default=17287.
+Please observe the NMRA standard if you change the default setting!
 .\"
 .TP
 nmra_ga_offset
Index: src/Makefile.am
===================================================================
--- src/Makefile.am	(.../tags/RELEASE_2_1_5)	(Revision 1759)
+++ src/Makefile.am	(.../branches/bw-rs232speed)	(Revision 1877)
@@ -35,7 +35,8 @@ if USE_DDL
 srcpd_SOURCES += \
 	ddl.c ddl.h \
 	ddl_maerklin.c ddl_maerklin.h \
-	ddl_nmra.c ddl_nmra.h
+	ddl_nmra.c ddl_nmra.h \
+	custom_termios2.c custom_termios2.h
 endif
 
 if USE_DDLS88
Index: src/custom_termios2.c
===================================================================
--- src/custom_termios2.c	(.../tags/RELEASE_2_1_5)	(nicht existent)
+++ src/custom_termios2.c	(.../branches/bw-rs232speed)	(Revision 1877)
@@ -0,0 +1,57 @@
+/* from https://github.com/linux4sam/9bit */
+/*
+ * Copyright (C) 2019 Microchip Technology Inc.  All rights reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * SPDX-License-Identifier: MIT
+ */
+#include "custom_termios2.h"
+#include <asm/ioctls.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+
+int tcgetattr2(int fd, struct termios2 *termios)
+{
+	return ioctl(fd, TCGETS2, termios);
+}
+
+int tcsetattr2(int fd, int optional_actions, const struct termios2 *termios)
+{
+	unsigned long int cmd;
+
+	switch (optional_actions)
+	{
+	case TCSANOW:
+		cmd = TCSETS2;
+		break;
+	case TCSADRAIN:
+		cmd = TCSETSW2;
+		break;
+	case TCSAFLUSH:
+		cmd = TCSETSF2;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return ioctl(fd, cmd, termios);
+}
Index: src/custom_termios2.h
===================================================================
--- src/custom_termios2.h	(.../tags/RELEASE_2_1_5)	(nicht existent)
+++ src/custom_termios2.h	(.../branches/bw-rs232speed)	(Revision 1877)
@@ -0,0 +1,79 @@
+/* from https://github.com/linux4sam/9bit */
+/*
+ * Copyright (C) 2019 Microchip Technology Inc.  All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ * 
+ * SPDX-License-Identifier: MIT
+ */
+#ifndef CUSTOM_TERMIOS2_H
+#define CUSTOM_TERMIOS2_H
+
+/*
+ * struct termios2 provides 2 new members that allow us to set any baud rate we
+ * want (as long as the hardware supports it) outside of the predefined ones.
+ *
+ * If you just use struct termios2 to set the baud to something custom, and then
+ * turn around and use the standard struct termios and tcsetattr(), you'll lose
+ * the baud setting.  So, it makes sense to just use struct termios2 everywhere.
+ *
+ * Going straight for <asm/termios.h> causes conflicts with other necessary
+ * headers (like <termios.h>), so we are stuck trying to get to struct termios2
+ * with that header.
+ *
+ * The result is this header provides:
+ *  1. Bring struct termios2 definition here.
+ *  2. Define some helper functions tcgetattr2() and tcsetattr2() which are
+ *     equal to tcgetattr() and tcsetattr(), but for struct termios2.
+ */
+
+#include <termios.h>
+
+/*
+#if !defined(__arm__)
+#warning "Only tested on ARM arch.  This may or may not work."
+#endif
+*/
+/*
+ * Definition from linux/include/uapi/asm-generic/termbits.h
+ */
+
+#define _NCCS 19
+struct termios2 {
+	tcflag_t c_iflag;               /* input mode flags */
+	tcflag_t c_oflag;               /* output mode flags */
+	tcflag_t c_cflag;               /* control mode flags */
+	tcflag_t c_lflag;               /* local mode flags */
+	cc_t c_line;                    /* line discipline */
+	cc_t c_cc[_NCCS];               /* control characters */
+	speed_t c_ispeed;               /* input speed */
+	speed_t c_ospeed;               /* output speed */
+};
+
+#ifndef BOTHER
+#define BOTHER CBAUDEX
+#endif
+
+int tcgetattr2(int fd, struct termios2 *termios);
+
+int tcsetattr2(int fd, int optional_actions, const struct termios2 *termios);
+
+#endif
Index: src/ddl.c
===================================================================
--- src/ddl.c	(.../tags/RELEASE_2_1_5)	(Revision 1759)
+++ src/ddl.c	(.../branches/bw-rs232speed)	(Revision 1877)
@@ -18,6 +18,8 @@
 /* | gpl-license@vogt-it.com so we can mail you a copy immediately.       | */
 /* +----------------------------------------------------------------------+ */
 
+/* 2021 changes by Bernd Wagner to support custom baudrates for NMRA DCC */
+
 /***************************************************************/
 /* erddcd - Electric Railroad Direct Digital Command Daemon    */
 /*    generates without any other hardware digital commands    */
@@ -244,46 +246,78 @@ int setSerialMode(bus_t busnumber, int m
     switch (mode) {
         case SDM_MAERKLIN:
             if (__DDL->SERIAL_DEVICE_MODE != SDM_MAERKLIN) {
-                if (tcsetattr
-                    (buses[busnumber].device.file.fd, TCSANOW,
-                     &__DDL->maerklin_dev_termios) != 0) {
+                if (__DDL->IMPROVE_NMRADCC_TIMING != TERMIOS2_METHOD)
+                { /*IMPROVE_NMRADCC_TIMING in {0,1}*/
+                    if (tcsetattr(buses[busnumber].device.file.fd, TCSANOW,
+                                  &__DDL->maerklin_dev_termios) != 0)
+                    {
                     syslog_bus(busnumber, DBG_ERROR,
                                "Error setting serial device mode to Maerklin!");
                     return -1;
                 }
 #if linux
-                if (__DDL->IMPROVE_NMRADCC_TIMING) {
-                    if (set_customdivisor
-                        (buses[busnumber].device.file.fd,
-                         __DDL->serinfo_marklin) != 0) {
+                    if (__DDL->IMPROVE_NMRADCC_TIMING==DIVISOR_METHOD)
+                    { /*IMPROVE_NMRADCC_TIMING in {1}*/
+                        if (set_customdivisor(buses[busnumber].device.file.fd,
+                                              __DDL->serinfo_marklin) != 0)
+                        {
                         syslog_bus(busnumber, DBG_ERROR,
                                    "Cannot set custom divisor for maerklin of serial device!");
                         return -1;
                     }
+                    } /*IMPROVE_NMRADCC_TIMING in {1}*/
+#endif
+                } /*IMPROVE_NMRADCC_TIMING in {0,1}*/
+#if linux
+                else
+                { /*IMPROVE_NMRADCC_TIMING in {2}*/
+                    if (tcsetattr2(buses[busnumber].device.file.fd, TCSANOW,
+                                   &__DDL->maerklin_dev_termios2) != 0)
+                    {
+                        syslog_bus(busnumber, DBG_ERROR,
+                                   "Error setting serial device mode to Maerklin using termios2!");
+                        return -1;
                 }
+                } /*IMPROVE_NMRADCC_TIMING in {2}*/
 #endif
                 __DDL->SERIAL_DEVICE_MODE = SDM_MAERKLIN;
             }
             break;
         case SDM_NMRA:
             if (__DDL->SERIAL_DEVICE_MODE != SDM_NMRA) {
-                if (tcsetattr
-                    (buses[busnumber].device.file.fd, TCSANOW,
-                     &__DDL->nmra_dev_termios) != 0) {
+                if (__DDL->IMPROVE_NMRADCC_TIMING != TERMIOS2_METHOD)
+                { /*IMPROVE_NMRADCC_TIMING in {0,1}*/
+                    if (tcsetattr(buses[busnumber].device.file.fd, TCSANOW,
+                                  &__DDL->nmra_dev_termios) != 0)
+                    {
                     syslog_bus(busnumber, DBG_ERROR,
                                "Error setting serial device mode to NMRA!");
                     return -1;
                 }
 #if linux
-                if (__DDL->IMPROVE_NMRADCC_TIMING) {
-                    if (set_customdivisor
-                        (buses[busnumber].device.file.fd,
-                         __DDL->serinfo_nmradcc) != 0) {
+                    if (__DDL->IMPROVE_NMRADCC_TIMING==DIVISOR_METHOD)
+                    { /*IMPROVE_NMRADCC_TIMING in {1}*/
+                        if (set_customdivisor(buses[busnumber].device.file.fd,
+                                              __DDL->serinfo_nmradcc) != 0)
+                        {
                         syslog_bus(busnumber, DBG_ERROR,
                                    "Cannot set custom divisor for nmra dcc of serial device!");
                         return -1;
                     }
+                    } /*IMPROVE_NMRADCC_TIMING in {1}*/
+#endif
+                } /*IMPROVE_NMRADCC_TIMING in {0,1}*/  
+#if linux      
+                else
+                { /*IMPROVE_NMRADCC_TIMING in {2}*/
+                    if (tcsetattr2(buses[busnumber].device.file.fd, TCSANOW,
+                                   &__DDL->nmra_dev_termios2) != 0)
+                    {
+                        syslog_bus(busnumber, DBG_ERROR,
+                                   "Error setting serial device mode to NMRA using termios2 method!");
+                        return -1;
                 }
+                } /*IMPROVE_NMRADCC_TIMING in {2}*/
 #endif
                 __DDL->SERIAL_DEVICE_MODE = SDM_NMRA;
             }
@@ -316,7 +350,8 @@ int init_lineDDL(bus_t busnumber)
         exit(EXIT_FAILURE);
     }
 #if linux
-    if ((rc = reset_customdivisor(dev)) != 0) {
+    if ((__DDL->IMPROVE_NMRADCC_TIMING == DIVISOR_METHOD)&&((rc = reset_customdivisor(dev)) != 0)) {
+        /* reset customdivisor only when it was used B.W. */
         syslog_bus(busnumber, DBG_FATAL,
                    "Error initializing device %s (reset custom "
                    "divisor %d). Abort!",
@@ -341,8 +376,11 @@ int init_lineDDL(bus_t busnumber)
         exit(EXIT_FAILURE);
     }
 
+    if (__DDL->IMPROVE_NMRADCC_TIMING != TERMIOS2_METHOD) 
+    { /*IMPROVE_NMRADCC_TIMING in {0,1}*/
     result = tcgetattr(dev, &__DDL->maerklin_dev_termios);
-    if (result == -1) {
+        if (result == -1)
+        {
         syslog_bus(busnumber, DBG_FATAL,
                    "tcgetattr() failed: %s (errno = %d, device = %s).",
                    strerror(result), result,
@@ -351,7 +389,8 @@ int init_lineDDL(bus_t busnumber)
     }
 
     result = tcgetattr(dev, &__DDL->nmra_dev_termios);
-    if (result == -1) {
+        if (result == -1)
+        {
         syslog_bus(busnumber, DBG_FATAL,
                    "tcgetattr() failed: %s (errno = %d, device = %s).",
                    strerror(result), result,
@@ -377,8 +416,9 @@ int init_lineDDL(bus_t busnumber)
         ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
     __DDL->nmra_dev_termios.c_cflag &= ~(CSIZE | PARENB);
     __DDL->nmra_dev_termios.c_cflag |= CS8;     /* 8 data bits      */
-    if (__DDL->IMPROVE_NMRADCC_TIMING) {
-        /* IMPROVE_NMRADCC_TIMING
+        if (__DDL->IMPROVE_NMRADCC_TIMING==DIVISOR_METHOD)
+        {
+            /* IMPROVE_NMRADCC_TIMING == DIVISOR_METHOD
            With 19200 baud we are already outside of the specification of NMRA.
            19200 baud means we have pulses of 52 microseconds - the specification
            for generating DCC signals is in the range between 55 and 61
@@ -401,30 +441,85 @@ int init_lineDDL(bus_t busnumber)
          */
         cfsetospeed(&__DDL->nmra_dev_termios, B38400);  /* baud rate: 38400 */
         cfsetispeed(&__DDL->nmra_dev_termios, B38400);  /* baud rate: 38400 */
-    }
-    else {
+        } /* IMPROVE_NMRADCC_TIMING == DIVISOR_METHOD */
+        else
+        { /* IMPROVE_NMRADCC_TIMING == 0 */
         cfsetospeed(&__DDL->nmra_dev_termios, B19200);  /* baud rate: 19200 */
         cfsetispeed(&__DDL->nmra_dev_termios, B19200);  /* baud rate: 19200 */
-    }
+        } /* IMPROVE_NMRADCC_TIMING == 0 */
 
 #if linux
     /* if IMPROVE_NMRADCC_TIMING is set, we have to initialize some */
     /* structures */
-    if (__DDL->IMPROVE_NMRADCC_TIMING) {
-        if (init_serinfo(dev, 3, &__DDL->serinfo_marklin) != 0) {
+        if (__DDL->IMPROVE_NMRADCC_TIMING == DIVISOR_METHOD)
+        { /* IMPROVE_NMRADCC_TIMING == DIVISOR_METHOD */
+            if (init_serinfo(dev, 3, &__DDL->serinfo_marklin) != 0)
+            {
             syslog_bus(busnumber, DBG_FATAL,
                        "Error initializing device %s (init_serinfo mm). Abort!",
                        buses[busnumber].device.file.path);
             exit(EXIT_FAILURE);
         }
-        if (init_serinfo(dev, 7, &__DDL->serinfo_nmradcc) != 0) {
+            if (init_serinfo(dev, 7, &__DDL->serinfo_nmradcc) != 0)
+            {
             syslog_bus(busnumber, DBG_FATAL,
                        "Error initializing device %s (init_serinfo dcc). Abort!",
                        buses[busnumber].device.file.path);
             exit(EXIT_FAILURE);
         }
+        } /* IMPROVE_NMRADCC_TIMING == DIVISOR_METHOD */
+#endif
+    }  /*IMPROVE_NMRADCC_TIMING in {0,1}*/
+#if linux
+    else 
+    {    /* use termios2 method */
+        result = tcgetattr2(dev, &__DDL->maerklin_dev_termios2);
+        if (result == -1)
+        {
+            syslog_bus(busnumber, DBG_FATAL,
+                       "tcgetattr2() failed for maerklin: %s (errno = %d, device = %s).",
+                       strerror(result), result,
+                       buses[busnumber].device.file.path);
+            exit(EXIT_FAILURE);
+        }
+
+        result = tcgetattr2(dev, &__DDL->nmra_dev_termios2);
+        if (result == -1)
+        {
+            syslog_bus(busnumber, DBG_FATAL,
+                       "tcgetattr2() failed for nmra: %s (errno = %d, device = %s).",
+                       strerror(result), result,
+                       buses[busnumber].device.file.path);
+            exit(EXIT_FAILURE);
     }
+
+        /* init termios2 structure for Maerklin mode */
+        __DDL->maerklin_dev_termios2.c_lflag &=
+            ~(ECHO | ICANON | IEXTEN | ISIG);
+        __DDL->maerklin_dev_termios2.c_oflag &= ~(OPOST);
+        __DDL->maerklin_dev_termios2.c_iflag &=
+            ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
+        __DDL->maerklin_dev_termios2.c_cflag &= ~(CSIZE | PARENB);
+        __DDL->maerklin_dev_termios2.c_cflag |= CS6;        /* 6 data bits      */
+        __DDL->maerklin_dev_termios2.c_cflag &= ~CBAUD;
+        __DDL->maerklin_dev_termios2.c_cflag |= BOTHER;
+        __DDL->maerklin_dev_termios2.c_ospeed = 38400;  /* baud rate: 38400 */
+        __DDL->maerklin_dev_termios2.c_ispeed = 38400;  /* baud rate: 38400 */
+
+        /* init termios2 structure for NMRA mode */
+        __DDL->nmra_dev_termios2.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);
+        __DDL->nmra_dev_termios2.c_oflag &= ~(OPOST);
+        __DDL->nmra_dev_termios2.c_iflag &=
+            ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
+        __DDL->nmra_dev_termios2.c_cflag &= ~(CSIZE | PARENB);
+        __DDL->nmra_dev_termios2.c_cflag |= CS8; /* 8 data bits      */
+        __DDL->nmra_dev_termios2.c_cflag &= ~CBAUD;
+        __DDL->nmra_dev_termios2.c_cflag |= BOTHER;
+        __DDL->nmra_dev_termios2.c_ospeed = __DDL->NMRADCC_BAUDRATE ; /* baud rate */
+        __DDL->nmra_dev_termios2.c_ispeed = __DDL->NMRADCC_BAUDRATE ; /* baud rate */
+    } /* use termios2 method */
 #endif
+
     buses[busnumber].device.file.fd = dev;      /* we need that value at the next step */
     /* setting serial device to default mode */
     if (!setSerialMode(busnumber, SDM_DEFAULT) == 0) {
@@ -433,7 +528,24 @@ int init_lineDDL(bus_t busnumber)
                    buses[busnumber].device.file.path);
         exit(EXIT_FAILURE);
     }
+#if linux
+    switch (__DDL->IMPROVE_NMRADCC_TIMING) {
+        case false:
+        case DIVISOR_METHOD: {
+            struct termios tio;
+            tcgetattr(buses[busnumber].device.file.fd, &tio);
+            syslog_bus(busnumber, DBG_DEBUG, "speed code reported from termios: %u", cfgetospeed(&tio));
+            }
+            break;
 
+        case TERMIOS2_METHOD: {
+            struct termios2 tio;
+            tcgetattr2(buses[busnumber].device.file.fd, &tio);
+            syslog_bus(busnumber, DBG_DEBUG, "baudrate reported by termios2: %u", tio.c_ospeed);
+            }
+            break;
+    }
+#endif
     return dev;
 }
 
@@ -709,8 +821,7 @@ static void waitUARTempty_COMMON_USLEEPP
 
     do {
 #if linux
-        result =
-            ioctl(buses[busnumber].device.file.fd, TIOCSERGETLSR, &value);
+        result = ioctl(buses[busnumber].device.file.fd, TIOCSERGETLSR, &value);
 #else
         result = ioctl(buses[busnumber].device.file.fd, TCSADRAIN, &value);
 #endif
@@ -1523,6 +1634,7 @@ int readconfig_DDL(xmlDocPtr doc, xmlNod
     /*                             translation routine(1, 2 or 3) */
     __DDL->ENABLED_PROTOCOLS = (EP_MAERKLIN | EP_NMRADCC);      /* enabled p's */
     __DDL->IMPROVE_NMRADCC_TIMING = 0;  /* NMRA DCC: improve timing    */
+    __DDL->NMRADCC_BAUDRATE = 17287;  /* NMRA DCC: baudrate when using termios2 */
 
     __DDL->WAITUART_USLEEP_PATCH = true;        /* enable/disable usleep patch */
     __DDL->WAITUART_USLEEP_USEC = 100;  /* usecs for usleep patch      */
@@ -1617,7 +1729,19 @@ int readconfig_DDL(xmlDocPtr doc, xmlNod
             if (txt != NULL) {
                 __DDL->IMPROVE_NMRADCC_TIMING = (xmlStrcmp(txt,
                                                            BAD_CAST "yes")
-                                                 == 0) ? true : false;
+                                                 == 0) ? DIVISOR_METHOD : 
+                        ((xmlStrcmp(txt, BAD_CAST "termios2") == 0) ? 
+                        TERMIOS2_METHOD : false);
+                xmlFree(txt);
+            }
+        }
+
+        else if (xmlStrcmp
+                 (child->name, BAD_CAST "nmradcc_baudrate")
+                 == 0) {
+            txt = xmlNodeListGetString(doc, child->xmlChildrenNode, 1);
+            if (txt != NULL) {
+                __DDL->NMRADCC_BAUDRATE = atoi((char *) txt);
                 xmlFree(txt);
             }
         }
@@ -1695,13 +1819,17 @@ int readconfig_DDL(xmlDocPtr doc, xmlNod
         syslog_bus(busnumber, DBG_ERROR,
                    "Can't create array for locomotives");
     }
-    if (__DDL->IMPROVE_NMRADCC_TIMING && __DDL->oslevel == 1) {
+    if ((__DDL->IMPROVE_NMRADCC_TIMING==DIVISOR_METHOD) && __DDL->oslevel == 1) {
         syslog_bus(busnumber, DBG_NONE,
                    "Improve nmra dcc timing causes changes on serial "
                    "lines custom divisor."
                    "This is deprecated on kernel 2.6 or later. You "
                    "better disable this feature in srcpd.conf");
     }
+    if (__DDL->ENABLED_PROTOCOLS==0){
+        syslog_bus(busnumber, DBG_ERROR, "No protocol enabled - "
+                    "please review .conf file");
+    }
 
     return (1);
 }
@@ -1714,6 +1842,12 @@ int init_bus_DDL(bus_t busnumber)
     static char protocols[3] = { '\0', '\0', '\0' };
     int protocol = 0;
 
+    if (__DDL->ENABLED_PROTOCOLS==0){
+                syslog_bus(busnumber, DBG_ERROR, "No protocol enabled - "
+                    "cannot initialize bus");
+                return 1;
+    }
+
     syslog_bus(busnumber, DBG_INFO, "DDL init with debug level %d",
                buses[busnumber].debuglevel);
 
Index: src/ddl.h
===================================================================
--- src/ddl.h	(.../tags/RELEASE_2_1_5)	(Revision 1759)
+++ src/ddl.h	(.../branches/bw-rs232speed)	(Revision 1877)
@@ -31,12 +31,16 @@
 
 #include "config-srcpd.h"
 #include "netservice.h"
+#include "custom_termios2.h"
 
 #define QSIZE       2000
 /* large packet size reserved for F0-F28 packets */
 #define PKTSIZE     80
 #define MAXDATA     20
 
+#define DIVISOR_METHOD 1  /* custom divisor method for custom baudrate */
+#define TERMIOS2_METHOD 2  /* termios2 method for custom baudrate */
+
 typedef struct _tQData {
     int packet_type;
     int packet_size;
@@ -88,7 +92,8 @@ typedef struct _DDL_DATA {
     int NMRADCC_TR_V;           /* version of the nmra dcc      */
     /*                             translation routine(1,2 or 3) */
     int ENABLED_PROTOCOLS;      /* enabled p's                  */
-    int IMPROVE_NMRADCC_TIMING; /* NMRA DCC: improve timing     */
+    int IMPROVE_NMRADCC_TIMING; /* NMRA DCC: improve timing  0 = no, 1 = custom-divisor method, 2 = termios2 method */
+    int NMRADCC_BAUDRATE;       /* NMRA DCC: baudrate in case of IMPROVE_NMRADCC_TIMING==2 */
 
     bool WAITUART_USLEEP_PATCH;  /* enable/disbable usleep patch */
     int WAITUART_USLEEP_USEC;   /* usecs for usleep patch       */
@@ -99,6 +104,8 @@ typedef struct _DDL_DATA {
     struct termios nmra_dev_termios;
 
 #if linux
+    struct termios2 maerklin_dev_termios2;
+    struct termios2 nmra_dev_termios2;
     struct serial_struct *serinfo_marklin;
     struct serial_struct *serinfo_nmradcc;
 #endif
