summaryrefslogtreecommitdiffstats
path: root/serial.c
diff options
context:
space:
mode:
Diffstat (limited to 'serial.c')
-rw-r--r--serial.c142
1 files changed, 142 insertions, 0 deletions
diff --git a/serial.c b/serial.c
new file mode 100644
index 0000000..e22a8fa
--- /dev/null
+++ b/serial.c
@@ -0,0 +1,142 @@
+/*
+ * This file is part of the flashrom project.
+ *
+ * Copyright (C) 2009 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 <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "flash.h"
+#include <string.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <termios.h>
+
+int sp_fd;
+
+void __attribute__((noreturn)) sp_die(char *msg)
+{
+ perror(msg);
+ exit(1);
+}
+
+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 },
+static const struct baudentry sp_baudtable[] = {
+ BAUDENTRY(9600)
+ BAUDENTRY(19200)
+ BAUDENTRY(38400)
+ BAUDENTRY(57600)
+ BAUDENTRY(115200)
+#ifdef B230400
+ BAUDENTRY(230400)
+#endif
+#ifdef B460800
+ BAUDENTRY(460800)
+#endif
+#ifdef B500000
+ BAUDENTRY(500000)
+#endif
+#ifdef B576000
+ BAUDENTRY(576000)
+#endif
+#ifdef B921600
+ BAUDENTRY(921600)
+#endif
+#ifdef B1000000
+ BAUDENTRY(1000000)
+#endif
+#ifdef B1152000
+ BAUDENTRY(1152000)
+#endif
+#ifdef B1500000
+ BAUDENTRY(1500000)
+#endif
+#ifdef B2000000
+ BAUDENTRY(2000000)
+#endif
+#ifdef B2500000
+ BAUDENTRY(2500000)
+#endif
+#ifdef B3000000
+ BAUDENTRY(3000000)
+#endif
+#ifdef B3500000
+ BAUDENTRY(3500000)
+#endif
+#ifdef B4000000
+ BAUDENTRY(4000000)
+#endif
+ {0, 0} /* Terminator */
+};
+
+int sp_openserport(char *dev, unsigned int baud)
+{
+ struct termios options;
+ int fd, i;
+ fd = open(dev, O_RDWR | O_NOCTTY | O_NDELAY);
+ if (fd < 0)
+ sp_die("Error: cannot open serial port");
+ fcntl(fd, F_SETFL, 0);
+ tcgetattr(fd, &options);
+ for (i = 0;; i++) {
+ if (sp_baudtable[i].baud == 0) {
+ close(fd);
+ fprintf(stderr,
+ "Error: cannot configure for baudrate %d\n",
+ baud);
+ exit(1);
+ }
+ if (sp_baudtable[i].baud == baud) {
+ cfsetispeed(&options, sp_baudtable[i].flag);
+ cfsetospeed(&options, sp_baudtable[i].flag);
+ break;
+ }
+ }
+ options.c_cflag &= ~(PARENB | CSTOPB | CSIZE | CRTSCTS);
+ options.c_cflag |= (CS8 | CLOCAL | CREAD);
+ options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
+ options.c_iflag &= ~(IXON | IXOFF | IXANY | ICRNL | IGNCR | INLCR);
+ options.c_oflag &= ~OPOST;
+ tcsetattr(fd, TCSANOW, &options);
+ return fd;
+}
+
+void sp_flush_incoming(void)
+{
+ int i;
+ for (i=0;i<100;i++) { /* In case the device doesnt do EAGAIN, just read 0 */
+ unsigned char flush[16];
+ ssize_t rv;
+ rv = read(sp_fd, flush, sizeof(flush));
+ if ((rv == -1) && (errno == EAGAIN))
+ break;
+ if (rv == -1)
+ sp_die("flush read");
+ }
+ return;
+}
OpenPOWER on IntegriCloud