+ return SR_OK;
+}
+
+#define SERIAL_COMM_SPEC "^(\\d+)/([78])([neo])([12])$"
+SR_PRIV int serial_set_paramstr(int fd, const char *paramstr)
+{
+ GRegex *reg;
+ GMatchInfo *match;
+ int speed, databits, parity, stopbits;
+ char *mstr;
+
+ speed = databits = parity = stopbits = 0;
+ reg = g_regex_new(SERIAL_COMM_SPEC, 0, 0, NULL);
+ if (g_regex_match(reg, paramstr, 0, &match)) {
+ if ((mstr = g_match_info_fetch(match, 1)))
+ speed = strtoul(mstr, NULL, 10);
+ g_free(mstr);
+ if ((mstr = g_match_info_fetch(match, 2)))
+ databits = strtoul(mstr, NULL, 10);
+ g_free(mstr);
+ if ((mstr = g_match_info_fetch(match, 3))) {
+ switch (mstr[0]) {
+ case 'n':
+ parity = SERIAL_PARITY_NONE;
+ break;
+ case 'e':
+ parity = SERIAL_PARITY_EVEN;
+ break;
+ case 'o':
+ parity = SERIAL_PARITY_ODD;
+ break;
+ }
+ }
+ g_free(mstr);
+ if ((mstr = g_match_info_fetch(match, 4)))
+ stopbits = strtoul(mstr, NULL, 10);
+ g_free(mstr);
+ }
+ g_match_info_unref(match);
+ g_regex_unref(reg);
+
+ if (speed)
+ return serial_set_params(fd, speed, databits, parity, stopbits, 0);
+ else
+ return SR_ERR_ARG;
+}
+
+SR_PRIV int serial_readline(int fd, char **buf, int *buflen,
+ uint64_t timeout_ms)
+{
+ uint64_t start;
+ int maxlen, len;
+
+ timeout_ms *= 1000;
+ start = g_get_monotonic_time();
+
+ maxlen = *buflen;
+ *buflen = len = 0;
+ while(1) {
+ len = maxlen - *buflen - 1;
+ if (len < 1)
+ break;
+ len = serial_read(fd, *buf + *buflen, 1);
+ if (len > 0) {
+ *buflen += len;
+ *(*buf + *buflen) = '\0';
+ if (*buflen > 0 && *(*buf + *buflen - 1) == '\r') {
+ /* Strip LF and terminate. */
+ *(*buf + --*buflen) = '\0';
+ break;
+ }
+ }
+ if (g_get_monotonic_time() - start > timeout_ms)
+ /* Timeout */
+ break;
+ g_usleep(2000);
+ }
+ sr_dbg("Received %d: '%s'.", *buflen, *buf);
+
+ return SR_OK;