serprog: allow to omit specifying a baud rate

On USB-based serial connections (VCP) the requested baud rate usually
does not matter (much). Remove the arbitrary restriction and use whatever
default values the OS/hardware provides.

Corresponding to flashrom svn r1907.

Signed-off-by: Stefan Tauner <stefan.tauner@alumni.tuwien.ac.at>
Acked-by: Urja Rannikko <urjaman@gmail.com>
diff --git a/flashrom.8.tmpl b/flashrom.8.tmpl
index 8b5f98c..26ea6e9 100644
--- a/flashrom.8.tmpl
+++ b/flashrom.8.tmpl
@@ -203,10 +203,9 @@
 Olimex ARM-USB-TINY/-H, Olimex ARM-USB-OCD/-H, TIAO/DIYGADGET USB
 Multi-Protocol Adapter (TUMPA), TUMPA Lite, and GOEPEL PicoTAP.
 .sp
-.BR "* serprog" " (for flash ROMs attached to a programmer speaking serprog), \
-including AVR flasher by Urja Rannikko, AVR flasher by eightdot, \
-Arduino Mega flasher by fritz, InSystemFlasher by Juhana Helovuo, and \
-atmegaXXu2-flasher by Stefan Tauner."
+.BR "* serprog" " (for flash ROMs attached to a programmer speaking serprog, \
+including Arduino-based devices as well as various programmers by Urja Rannikko, \
+Juhana Helovuo, Stefan Tauner and others)."
 .sp
 .BR "* buspirate_spi" " (for SPI flash ROMs attached to a Bus Pirate)"
 .sp
@@ -683,19 +682,22 @@
 syntax.
 .SS
 .BR "serprog " programmer
-A mandatory parameter specifies either a serial
-device/baud combination or an IP/port combination for communication with the
-programmer. In the device/baud combination, the device has to start with a
-slash. For serial, you have to use the
+A mandatory parameter specifies either a serial device (and baud rate) or an IP/port combination for
+communicating with the programmer.
+The device/baud combination has to start with
+.B dev=
+and separate the optional baud rate with a colon.
+For example
 .sp
-.B "  flashrom \-p serprog:dev=/dev/device:baud"
+.B "  flashrom \-p serprog:dev=/dev/ttyS0:115200"
 .sp
-syntax and for IP, you have to use
+If no baud rate is given the default values by the operating system/hardware will be used.
+For IP connections you have to use the
 .sp
 .B "  flashrom \-p serprog:ip=ipaddr:port"
 .sp
-instead. In case the device supports it, you can set the SPI clock frequency
-with the optional
+syntax.
+In case the device supports it, you can set the SPI clock frequency with the optional
 .B spispeed
 parameter. The frequency is parsed as hertz, unless an
 .BR M ", or " k
diff --git a/programmer.h b/programmer.h
index 3bf292d..97f0ffa 100644
--- a/programmer.h
+++ b/programmer.h
@@ -719,10 +719,8 @@
 #endif
 
 void sp_flush_incoming(void);
-fdtype sp_openserport(char *dev, unsigned int baud);
-int serialport_config(fdtype fd, unsigned int baud);
+fdtype sp_openserport(char *dev, int baud);
 extern fdtype sp_fd;
-/* expose serialport_shutdown as it's currently used by buspirate */
 int serialport_shutdown(void *data);
 int serialport_write(const unsigned char *buf, unsigned int writecnt);
 int serialport_write_nonblock(const unsigned char *buf, unsigned int writecnt, unsigned int timeout, unsigned int *really_wrote);
diff --git a/serial.c b/serial.c
index d076bc8..75297f7 100644
--- a/serial.c
+++ b/serial.c
@@ -116,7 +116,7 @@
 	{0, 0}			/* Terminator */
 };
 
-const struct baudentry *round_baud(unsigned int baud)
+static 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. */
@@ -125,11 +125,12 @@
 			return &sp_baudtable[i];
 
 		if (sp_baudtable[i].baud < baud) {
-			msg_pinfo("Warning: given baudrate %d rounded down to %d.\n",
+			msg_pwarn("Warning: given baudrate %d rounded down to %d.\n",
 				  baud, sp_baudtable[i].baud);
 			return &sp_baudtable[i];
 		}
 	}
+	msg_pinfo("Using slowest possible baudrate: %d.\n", sp_baudtable[0].baud);
 	return &sp_baudtable[0];
 }
 
@@ -154,7 +155,7 @@
 #endif
 }
 
-int serialport_config(fdtype fd, unsigned int baud)
+int serialport_config(fdtype fd, int baud)
 {
 	if (fd == SER_INV_FD) {
 		msg_perr("%s: File descriptor is invalid.\n", __func__);
@@ -167,8 +168,10 @@
 		msg_perr_strerror("Could not fetch original serial port configuration: ");
 		return 1;
 	}
-	const struct baudentry *entry = round_baud(baud);
-	dcb.BaudRate = entry->flag;
+	if (baud >= 0) {
+		const struct baudentry *entry = round_baud(baud);
+		dcb.BaudRate = entry->flag;
+	}
 	dcb.ByteSize = 8;
 	dcb.Parity = NOPARITY;
 	dcb.StopBits = ONESTOPBIT;
@@ -188,10 +191,12 @@
 		return 1;
 	}
 	wanted = observed;
-	const struct baudentry *entry = round_baud(baud);
-	if (cfsetispeed(&wanted, entry->flag) != 0 || cfsetospeed(&wanted, entry->flag) != 0) {
-		msg_perr_strerror("Could not set serial baud rate: ");
-		return 1;
+	if (baud >= 0) {
+		const struct baudentry *entry = round_baud(baud);
+		if (cfsetispeed(&wanted, entry->flag) != 0 || cfsetospeed(&wanted, entry->flag) != 0) {
+			msg_perr_strerror("Could not set serial baud rate: ");
+			return 1;
+		}
 	}
 	wanted.c_cflag &= ~(PARENB | CSTOPB | CSIZE | CRTSCTS);
 	wanted.c_cflag |= (CS8 | CLOCAL | CREAD);
@@ -232,7 +237,7 @@
 	return 0;
 }
 
-fdtype sp_openserport(char *dev, unsigned int baud)
+fdtype sp_openserport(char *dev, int baud)
 {
 	fdtype fd;
 #if IS_WINDOWS
diff --git a/serprog.c b/serprog.c
index a2a3fe0..917aba5 100644
--- a/serprog.c
+++ b/serprog.c
@@ -342,26 +342,28 @@
 	unsigned char rbuf[3];
 	unsigned char c;
 	char *device;
-	char *baudport;
 	int have_device = 0;
 
-	/* the parameter is either of format "dev=/dev/device:baud" or "ip=ip:port" */
+	/* the parameter is either of format "dev=/dev/device[:baud]" or "ip=ip:port" */
 	device = extract_programmer_param("dev");
 	if (device && strlen(device)) {
-		baudport = strstr(device, ":");
-		if (baudport) {
+		char *baud_str = strstr(device, ":");
+		if (baud_str != NULL) {
 			/* Split device from baudrate. */
-			*baudport = '\0';
-			baudport++;
+			*baud_str = '\0';
+			baud_str++;
 		}
-		if (!baudport || !strlen(baudport)) {
-			msg_perr("Error: No baudrate specified.\n"
-				 "Use flashrom -p serprog:dev=/dev/device:baud\n");
-			free(device);
-			return 1;
-		}
-		if (strlen(device)) {
-			sp_fd = sp_openserport(device, atoi(baudport));
+		int baud;
+		/* Convert baud string to value.
+		 * baud_str is either NULL (if strstr can't find the colon), points to the \0 after the colon
+		 * if no characters where given after the colon, or a string to convert... */
+		if (baud_str == NULL || *baud_str == '\0') {
+			baud = -1;
+			msg_pdbg("No baudrate specified, using the hardware's defaults.\n");
+		} else
+			baud = atoi(baud_str); // FIXME: replace atoi with strtoul
+		if (strlen(device) > 0) {
+			sp_fd = sp_openserport(device, baud);
 			if (sp_fd == SER_INV_FD) {
 				free(device);
 				return 1;
@@ -371,7 +373,7 @@
 	}
 	if (device && !strlen(device)) {
 		msg_perr("Error: No device specified.\n"
-			 "Use flashrom -p serprog:dev=/dev/device:baud\n");
+			 "Use flashrom -p serprog:dev=/dev/device[:baud]\n");
 		free(device);
 		return 1;
 	}
@@ -386,20 +388,20 @@
 		return 1;
 	}
 	if (device && strlen(device)) {
-		baudport = strstr(device, ":");
-		if (baudport) {
+		char *port = strstr(device, ":");
+		if (port != NULL) {
 			/* Split host from port. */
-			*baudport = '\0';
-			baudport++;
+			*port = '\0';
+			port++;
 		}
-		if (!baudport || !strlen(baudport)) {
+		if (!port || !strlen(port)) {
 			msg_perr("Error: No port specified.\n"
 				 "Use flashrom -p serprog:ip=ipaddr:port\n");
 			free(device);
 			return 1;
 		}
 		if (strlen(device)) {
-			sp_fd = sp_opensocket(device, atoi(baudport));
+			sp_fd = sp_opensocket(device, atoi(port)); // FIXME: replace atoi with strtoul
 			if (sp_fd < 0) {
 				free(device);
 				return 1;