+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <linux/termios.h>
+#include <unistd.h>
+
+/*
+ * HACK: declare the ioctl function by hand...
+ *
+ * We cannot include <sys/ioctl.h> as it will eventually include
+ * <termios.h>, which will conflict with <linux/temios.h>. As we
+ * really need the latter one AND the ioctl, just declare it by hand
+ * here so that we get to use it...
+ */
+int ioctl(int d, int request, ...);
+
+/**
+ * Open a serial device and adjust the baud rate to give (arbitrary)
+ * baud rate. The actual baud rate is stored back to the @baud
+ * variable. This might differ from the requested one as the
+ * underlying hardware may not support all possible baud
+ * rates.
+ *
+ * Returns the file descriptor that was opened.
+ */
+int open_at_baud(const char *device, int *baud)
+{
+ struct termios2 tios;
+ int fd;
+
+ fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY);
+
+ if (fd == -1) {
+ fprintf(stderr, "error opening %s: %m", device);
+ return fd;
+ }
+
+ if (ioctl(fd, TCGETS2, &tios)) {
+ perror("TCGETS2");
+ goto err;
+ }
+
+ tios.c_cflag &= ~CBAUD;
+ tios.c_cflag |= BOTHER;
+ tios.c_ispeed = *baud;
+ tios.c_ospeed = *baud;
+
+ if (ioctl(fd, TCSETS2, &tios)) {
+ perror("TCSETS2");
+ goto err;
+ }
+
+ if (ioctl(fd, TCGETS2, &tios)) {
+ perror("TCGETS2");
+ goto err;
+ }
+
+ *baud = tios.c_ospeed;
+
+ return fd;
+err:
+ close(fd);
+
+ return -1;
+}