Urja Rannikko has uploaded this change for review. ( https://review.coreboot.org/20224
Change subject: serial: support custom baud rates on linux ......................................................................
serial: support custom baud rates on linux
the function to do this is contained in linux_baud.c because broken include stuff (see the urls in that file).
Change-Id: I2a20f9182cb85e7bce5d6654a2caf20e6202b195 Signed-off-by: Urja Rannikko urjaman@gmail.com --- M Makefile A linux_baud.c A linux_baud.h M serial.c 4 files changed, 79 insertions(+), 3 deletions(-)
git pull ssh://review.coreboot.org:29418/flashrom refs/changes/24/20224/1
diff --git a/Makefile b/Makefile index 65026da..3d07c91 100644 --- a/Makefile +++ b/Makefile @@ -921,7 +921,7 @@ endif
ifneq ($(NEED_SERIAL), ) -LIB_OBJS += serial.o +LIB_OBJS += serial.o linux_baud.o endif
ifneq ($(NEED_POSIX_SOCKETS), ) diff --git a/linux_baud.c b/linux_baud.c new file mode 100644 index 0000000..6214767 --- /dev/null +++ b/linux_baud.c @@ -0,0 +1,50 @@ +/* + * This file is part of the flashrom project. + * + * Copyright (C) 2017 Urja Rannikko urjaman@gmail.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "platform.h" +#if IS_LINUX == 1 + +#include <sys/ioctl.h> +#include <fcntl.h> +#include <asm-generic/termbits.h> +#include <asm-generic/ioctls.h> + +#include "linux_baud.h" + +/* This include hell above is why this is in a separate source file. See eg. + * https://www.downtowndougbrown.com/2013/11/linux-custom-serial-baud-rates/ + * https://stackoverflow.com/questions/12646324/how-to-set-a-custom-baud-rate-o... + * https://github.com/jbkim/Linux-custom-baud-rate + * for more info. */ + +int linux_set_custom_baudrate(int fd, int speed) +{ + struct termios2 tio; + if (ioctl(fd, TCGETS2, &tio)) { + return -1; + } + tio.c_cflag &= ~CBAUD; + tio.c_cflag |= BOTHER; + tio.c_ispeed = speed; + tio.c_ospeed = speed; + return ioctl(fd, TCSETS2, &tio); +} + +#endif diff --git a/linux_baud.h b/linux_baud.h new file mode 100644 index 0000000..bbcd4d4 --- /dev/null +++ b/linux_baud.h @@ -0,0 +1 @@ +int linux_set_custom_baudrate(int fd, int speed); diff --git a/serial.c b/serial.c index a64a51d..08a204b 100644 --- a/serial.c +++ b/serial.c @@ -41,6 +41,10 @@ #include "flash.h" #include "programmer.h"
+#if IS_LINUX +#include "linux_baud.h" +#endif + fdtype sp_fd = SER_INV_FD;
/* There is no way defined by POSIX to use arbitrary baud rates. It only defines some macros that can be used to @@ -49,8 +53,7 @@ * The code below creates a mapping in sp_baudtable between these macros and the numerical baud rates to deal * with numerical user input. * - * On Linux there is a non-standard way to use arbitrary baud rates that flashrom does not support (yet), cf. - * http://www.downtowndougbrown.com/2013/11/linux-custom-serial-baud-rates/ + * On Linux there is a non-standard way to use arbitrary baud rates that we use, see linux_baud.c * * On Windows there exist similar macros (starting with CBR_ instead of B) but they are only defined for * backwards compatibility and the API supports arbitrary baud rates in the same manner as the macros, see @@ -119,6 +122,8 @@ {0, 0} /* Terminator */ };
+/* On linux, we dont return non-exact rates but instead NULL, + * so setting a custom rate can be attempted. */ static const struct baudentry *round_baud(unsigned int baud) { int i; @@ -128,13 +133,21 @@ return &sp_baudtable[i];
if (sp_baudtable[i].baud < baud) { +#if IS_LINUX + return NULL; +#else msg_pwarn("Warning: given baudrate %d rounded down to %d.\n", baud, sp_baudtable[i].baud); return &sp_baudtable[i]; +#endif } } +#if IS_LINUX + return NULL; +#else msg_pinfo("Using slowest possible baudrate: %d.\n", sp_baudtable[0].baud); return &sp_baudtable[0]; +#endif } #endif
@@ -196,6 +209,17 @@ wanted = observed; if (baud >= 0) { const struct baudentry *entry = round_baud(baud); +#if IS_LINUX + if (!entry) { + msg_pdbg("Trying to set custom baud rate.\n"); + if (linux_set_custom_baudrate(fd, baud)) { + msg_perr_strerror("Could not set custom baudrate: "); + } + /* We want whatever the termios looks like now, so the rest of the + * setup doesnt mess up the custom rate, hopefully. */ + tcgetattr(fd, &wanted); + } else +#endif if (cfsetispeed(&wanted, entry->flag) != 0 || cfsetospeed(&wanted, entry->flag) != 0) { msg_perr_strerror("Could not set serial baud rate: "); return 1; @@ -230,6 +254,7 @@ (long)observed.c_oflag, (long)wanted.c_oflag ); } + if (cfgetispeed(&observed) != cfgetispeed(&wanted) || cfgetospeed(&observed) != cfgetospeed(&wanted)) { msg_pwarn("Could not set baud rates exactly.\n");