summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Tauner <stefan.tauner@alumni.tuwien.ac.at>2013-04-01 00:45:32 +0000
committerStefan Tauner <stefan.tauner@alumni.tuwien.ac.at>2013-04-01 00:45:32 +0000
commitda5b17c0a2c648c60272f92c9ecbcd10f4af8348 (patch)
tree242daf2a20a91eb22e1cd776d6b335ced4149bcc
parentbf88be92911a07d14a4c0bb62a017cad0584d62d (diff)
downloadast2050-flashrom-da5b17c0a2c648c60272f92c9ecbcd10f4af8348.zip
ast2050-flashrom-da5b17c0a2c648c60272f92c9ecbcd10f4af8348.tar.gz
serial.c: round baudrates to valid ones
MSDN says: "The baud rate at which the communications device operates. This member can be an actual baud rate value, or one of the following indexes." But it is not specified what happens for different values, so we round down to valid ones (or to the minimum of 9600) by reusing the existing struct baudentry sp_baudtable[] and the new function round_baud(). Do similarly on non-Windows where arbitrary values are not allowed anyway. Corresponding to flashrom svn r1660. Signed-off-by: Stefan Tauner <stefan.tauner@alumni.tuwien.ac.at> Acked-by: Stefan Tauner <stefan.tauner@alumni.tuwien.ac.at>
-rw-r--r--serial.c103
1 files changed, 63 insertions, 40 deletions
diff --git a/serial.c b/serial.c
index 18562be..9a759ae 100644
--- a/serial.c
+++ b/serial.c
@@ -47,62 +47,95 @@ void __attribute__((noreturn)) sp_die(char *msg)
exit(1);
}
-#ifndef _WIN32
+#ifdef _WIN32
+struct baudentry {
+ DWORD flag;
+ unsigned int baud;
+};
+#define BAUDENTRY(baud) { CBR_##baud, baud },
+#else
struct baudentry {
int flag;
unsigned int baud;
};
-
-/* I'd like if the C preprocessor could have directives in macros */
#define BAUDENTRY(baud) { B##baud, baud },
+#endif
+
+/* I'd like if the C preprocessor could have directives in macros.
+ * See TERMIOS(3) and http://msdn.microsoft.com/en-us/library/windows/desktop/aa363214(v=vs.85).aspx and
+ * http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob;f=include/uapi/asm-generic/termbits.h */
static const struct baudentry sp_baudtable[] = {
- BAUDENTRY(9600)
+ BAUDENTRY(9600) /* unconditional default */
+#if defined(B19200) || defined(CBR_19200)
BAUDENTRY(19200)
+#endif
+#if defined(B38400) || defined(CBR_38400)
BAUDENTRY(38400)
+#endif
+#if defined(B57600) || defined(CBR_57600)
BAUDENTRY(57600)
+#endif
+#if defined(B115200) || defined(CBR_115200)
BAUDENTRY(115200)
-#ifdef B230400
+#endif
+#if defined(B230400) || defined(CBR_230400)
BAUDENTRY(230400)
#endif
-#ifdef B460800
+#if defined(B460800) || defined(CBR_460800)
BAUDENTRY(460800)
#endif
-#ifdef B500000
+#if defined(B500000) || defined(CBR_500000)
BAUDENTRY(500000)
#endif
-#ifdef B576000
+#if defined(B576000) || defined(CBR_576000)
BAUDENTRY(576000)
#endif
-#ifdef B921600
+#if defined(B921600) || defined(CBR_921600)
BAUDENTRY(921600)
#endif
-#ifdef B1000000
+#if defined(B1000000) || defined(CBR_1000000)
BAUDENTRY(1000000)
#endif
-#ifdef B1152000
+#if defined(B1152000) || defined(CBR_1152000)
BAUDENTRY(1152000)
#endif
-#ifdef B1500000
+#if defined(B1500000) || defined(CBR_1500000)
BAUDENTRY(1500000)
#endif
-#ifdef B2000000
+#if defined(B2000000) || defined(CBR_2000000)
BAUDENTRY(2000000)
#endif
-#ifdef B2500000
+#if defined(B2500000) || defined(CBR_2500000)
BAUDENTRY(2500000)
#endif
-#ifdef B3000000
+#if defined(B3000000) || defined(CBR_3000000)
BAUDENTRY(3000000)
#endif
-#ifdef B3500000
+#if defined(B3500000) || defined(CBR_3500000)
BAUDENTRY(3500000)
#endif
-#ifdef B4000000
+#if defined(B4000000) || defined(CBR_4000000)
BAUDENTRY(4000000)
#endif
{0, 0} /* Terminator */
};
-#endif
+
+const struct baudentry *round_baud(unsigned int baud)
+{
+ int i;
+ /* Round baud rate to next lower entry in sp_baudtable if it exists, else use the lowest entry. */
+ for (i = ARRAY_SIZE(sp_baudtable) - 2; i >= 0 ; i--) {
+ if (sp_baudtable[i].baud == baud)
+ return &sp_baudtable[i];
+
+ if (sp_baudtable[i].baud < baud) {
+ msg_pinfo("Warning: given baudrate %d rounded down to %d.\n",
+ baud, sp_baudtable[i].baud);
+ return &sp_baudtable[i];
+ }
+ }
+ return &sp_baudtable[0];
+}
/* Uses msg_perr to print the last system error.
* Prints "Error: " followed first by \c msg and then by the description of the last error retrieved via
@@ -155,15 +188,8 @@ fdtype sp_openserport(char *dev, unsigned int baud)
msg_perr_strerror("Could not fetch serial port configuration: ");
return SER_INV_FD;
}
- switch (baud) {
- case 9600: dcb.BaudRate = CBR_9600; break;
- case 19200: dcb.BaudRate = CBR_19200; break;
- case 38400: dcb.BaudRate = CBR_38400; break;
- case 57600: dcb.BaudRate = CBR_57600; break;
- case 115200: dcb.BaudRate = CBR_115200; break;
- default: msg_perr("Error: Could not set baud rate: %s\n", strerror(errno));
- return SER_INV_FD;
- }
+ const struct baudentry *entry = round_baud(baud);
+ dcb.BaudRate = entry->baud;
dcb.ByteSize = 8;
dcb.Parity = NOPARITY;
dcb.StopBits = ONESTOPBIT;
@@ -171,10 +197,15 @@ fdtype sp_openserport(char *dev, unsigned int baud)
msg_perr_strerror("Could not change serial port configuration: ");
return SER_INV_FD;
}
+ if (!GetCommState(fd, &dcb)) {
+ msg_perr_strerror("Could not fetch serial port configuration: ");
+ return SER_INV_FD;
+ }
+ msg_pdbg("Baud rate is %ld.\n", dcb.BaudRate);
return fd;
#else
struct termios options;
- int fd, i;
+ int fd;
fd = open(dev, O_RDWR | O_NOCTTY | O_NDELAY);
if (fd < 0) {
msg_perr_strerror("Cannot open serial port: ");
@@ -182,18 +213,10 @@ fdtype sp_openserport(char *dev, unsigned int baud)
}
fcntl(fd, F_SETFL, 0);
tcgetattr(fd, &options);
- for (i = 0;; i++) {
- if (sp_baudtable[i].baud == 0) {
- close(fd);
- msg_perr("Error: cannot configure for baudrate %d\n", baud);
- return SER_INV_FD;
- }
- if (sp_baudtable[i].baud == baud) {
- cfsetispeed(&options, sp_baudtable[i].flag);
- cfsetospeed(&options, sp_baudtable[i].flag);
- break;
- }
- }
+ const struct baudentry *entry = round_baud(baud);
+ cfsetispeed(&options, entry->flag);
+ cfsetospeed(&options, entry->flag);
+ msg_pdbg("Setting baud rate to %d.\n", entry->baud);
options.c_cflag &= ~(PARENB | CSTOPB | CSIZE | CRTSCTS);
options.c_cflag |= (CS8 | CLOCAL | CREAD);
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
OpenPOWER on IntegriCloud