]> sigrok.org Git - libsigrok.git/blob - hardware/common/serial.c
serial: allow for extra rts and dtr options in conn string
[libsigrok.git] / hardware / common / serial.c
1 /*
2  * This file is part of the sigrok project.
3  *
4  * Copyright (C) 2010-2012 Bert Vermeulen <bert@biot.com>
5  * Copyright (C) 2010-2012 Uwe Hermann <uwe@hermann-uwe.de>
6  * Copyright (C) 2012 Alexandru Gagniuc <mr.nuke.me@gmail.com>
7  *
8  * This program is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
20  */
21
22 #include <string.h>
23 #include <sys/types.h>
24 #include <sys/stat.h>
25 #include <fcntl.h>
26 #include <unistd.h>
27 #ifdef _WIN32
28 #include <windows.h>
29 #else
30 #include <glob.h>
31 #include <termios.h>
32 #endif
33 #include <stdlib.h>
34 #include <errno.h>
35 #include <sys/ioctl.h>
36 #include <glib.h>
37 #include "libsigrok.h"
38 #include "libsigrok-internal.h"
39
40 /* Message logging helpers with driver-specific prefix string. */
41 #define DRIVER_LOG_DOMAIN "serial: "
42 #define sr_log(l, s, args...) sr_log(l, DRIVER_LOG_DOMAIN s, ## args)
43 #define sr_spew(s, args...) sr_spew(DRIVER_LOG_DOMAIN s, ## args)
44 #define sr_dbg(s, args...) sr_dbg(DRIVER_LOG_DOMAIN s, ## args)
45 #define sr_info(s, args...) sr_info(DRIVER_LOG_DOMAIN s, ## args)
46 #define sr_warn(s, args...) sr_warn(DRIVER_LOG_DOMAIN s, ## args)
47 #define sr_err(s, args...) sr_err(DRIVER_LOG_DOMAIN s, ## args)
48
49 // FIXME: Must be moved, or rather passed as function argument.
50 #ifdef _WIN32
51 static HANDLE hdl;
52 #endif
53
54 /**
55  * Open the specified serial port.
56  *
57  * @param serial Previously initialized serial port structure.
58  * @param flags Flags to use when opening the serial port.
59  * TODO: Abstract 'flags', currently they're OS-specific!
60  *
61  * If the serial structure contains a serialcomm string, it will be
62  * passed to serial_set_paramstr() after the port is opened.
63  *
64  * @return SR_OK on success, SR_ERR on failure.
65  */
66 SR_PRIV int serial_open(struct sr_serial_dev_inst *serial, int flags)
67 {
68
69         if (!serial) {
70                 sr_dbg("Invalid serial port.");
71                 return SR_ERR;
72         }
73
74         sr_spew("Opening serial port '%s' (flags %d).", serial->port, flags);
75
76 #ifdef _WIN32
77         hdl = CreateFile(serial->port, GENERIC_READ | GENERIC_WRITE, 0, 0,
78                          OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
79         if (hdl == INVALID_HANDLE_VALUE) {
80                 sr_err("Error opening serial port '%s'.", serial->port);
81                 return SR_ERR;
82         }
83 #else
84         if ((serial->fd = open(serial->port, flags)) < 0) {
85                 sr_err("Error opening serial port '%s': %s.", serial->port,
86                        strerror(errno));
87                 return SR_ERR;
88         } else
89                 sr_spew("Opened serial port '%s' (fd %d).", serial->port, serial->fd);
90 #endif
91
92         if (serial->serialcomm)
93                 return serial_set_paramstr(serial, serial->serialcomm);
94         else
95                 return SR_OK;
96 }
97
98 /**
99  * Close the specified serial port.
100  *
101  * @param serial Previously initialized serial port structure.
102  *
103  * @return SR_OK on success, SR_ERR on failure.
104  */
105 SR_PRIV int serial_close(struct sr_serial_dev_inst *serial)
106 {
107         int ret;
108
109         if (!serial) {
110                 sr_dbg("Invalid serial port.");
111                 return SR_ERR;
112         }
113
114         if (serial->fd == -1) {
115                 sr_dbg("Cannot close unopened serial port %s (fd %d).",
116                                 serial->port, serial->fd);
117                 return SR_ERR;
118         }
119
120         sr_spew("Closing serial port %s (fd %d).", serial->port, serial->fd);
121         ret = SR_OK;
122
123 #ifdef _WIN32
124         /* Returns non-zero upon success, 0 upon failure. */
125         if (CloseHandle(hdl) == 0)
126                 ret = SR_ERR;
127 #else
128         /* Returns 0 upon success, -1 upon failure. */
129         if (close(serial->fd) < 0) {
130                 sr_err("Error closing serial port: %s (fd %d).", strerror(errno),
131                                 serial->fd);
132                 ret = SR_ERR;
133         }
134 #endif
135
136         serial->fd = -1;
137
138         return ret;
139 }
140
141 /**
142  * Flush serial port buffers.
143  *
144  * @param serial Previously initialized serial port structure.
145  *
146  * @return SR_OK on success, SR_ERR on failure.
147  */
148 SR_PRIV int serial_flush(struct sr_serial_dev_inst *serial)
149 {
150         int ret;
151
152         if (!serial) {
153                 sr_dbg("Invalid serial port.");
154                 return SR_ERR;
155         }
156
157         if (serial->fd == -1) {
158                 sr_dbg("Cannot flush unopened serial port %s (fd %d).",
159                                 serial->port, serial->fd);
160                 return SR_ERR;
161         }
162
163         sr_spew("Flushing serial port %s (fd %d).", serial->port, serial->fd);
164         ret = SR_OK;
165
166 #ifdef _WIN32
167         /* Returns non-zero upon success, 0 upon failure. */
168         if (PurgeComm(hdl, PURGE_RXCLEAR | PURGE_TXCLEAR) == 0) {
169                 sr_err("Error flushing serial port: %s.", strerror(errno));
170                 ret = SR_ERR;
171         }
172 #else
173         /* Returns 0 upon success, -1 upon failure. */
174         if (tcflush(serial->fd, TCIOFLUSH) < 0) {
175                 sr_err("Error flushing serial port: %s.", strerror(errno));
176                 ret = SR_ERR;
177         }
178
179         return ret;
180 #endif
181 }
182
183 /**
184  * Write a number of bytes to the specified serial port.
185  *
186  * @param serial Previously initialized serial port structure.
187  * @param buf Buffer containing the bytes to write.
188  * @param count Number of bytes to write.
189  *
190  * @return The number of bytes written, or -1 upon failure.
191  */
192 SR_PRIV int serial_write(struct sr_serial_dev_inst *serial,
193                 const void *buf, size_t count)
194 {
195         ssize_t ret;
196
197         if (!serial) {
198                 sr_dbg("Invalid serial port.");
199                 return -1;
200         }
201
202         if (serial->fd == -1) {
203                 sr_dbg("Cannot use unopened serial port %s (fd %d).",
204                                 serial->port, serial->fd);
205                 return -1;
206         }
207
208 #ifdef _WIN32
209         DWORD tmp = 0;
210
211         /* FIXME */
212         /* Returns non-zero upon success, 0 upon failure. */
213         WriteFile(hdl, buf, count, &tmp, NULL);
214 #else
215         /* Returns the number of bytes written, or -1 upon failure. */
216         ret = write(serial->fd, buf, count);
217         if (ret < 0)
218                 sr_err("Write error: %s.", strerror(errno));
219         else
220                 sr_spew("Wrote %d/%d bytes (fd %d).", ret, count, serial->fd);
221 #endif
222
223         return ret;
224 }
225
226 /**
227  * Read a number of bytes from the specified serial port.
228  *
229  * @param serial Previously initialized serial port structure.
230  * @param buf Buffer where to store the bytes that are read.
231  * @param count The number of bytes to read.
232  *
233  * @return The number of bytes read, or -1 upon failure.
234  */
235 SR_PRIV int serial_read(struct sr_serial_dev_inst *serial, void *buf,
236                 size_t count)
237 {
238         ssize_t ret;
239
240         if (!serial) {
241                 sr_dbg("Invalid serial port.");
242                 return -1;
243         }
244
245         if (serial->fd == -1) {
246                 sr_dbg("Cannot use unopened serial port %s (fd %d).",
247                                 serial->port, serial->fd);
248                 return -1;
249         }
250
251 #ifdef _WIN32
252         DWORD tmp = 0;
253
254         /* FIXME */
255         /* Returns non-zero upon success, 0 upon failure. */
256         return ReadFile(hdl, buf, count, &tmp, NULL);
257 #else
258         /* Returns the number of bytes read, or -1 upon failure. */
259         ret = read(serial->fd, buf, count);
260         if (ret < 0)
261                 /*
262                  * Should be sr_err(), but that would yield lots of
263                  * "Resource temporarily unavailable" messages.
264                  */
265                 sr_spew("Read error: %s (fd %d).", strerror(errno), serial->fd);
266         else
267                 sr_spew("Read %d/%d bytes (fd %d).", ret, count, serial->fd);
268 #endif
269
270         return ret;
271 }
272
273 /**
274  * Set serial parameters for the specified serial port.
275  *
276  * @param serial Previously initialized serial port structure.
277  * @param baudrate The baudrate to set.
278  * @param bits The number of data bits to use.
279  * @param parity The parity setting to use (0 = none, 1 = even, 2 = odd).
280  * @param stopbits The number of stop bits to use (1 or 2).
281  * @param flowcontrol The flow control settings to use (0 = none, 1 = RTS/CTS,
282  *                    2 = XON/XOFF).
283  *
284  * @return SR_OK upon success, SR_ERR upon failure.
285  */
286 SR_PRIV int serial_set_params(struct sr_serial_dev_inst *serial, int baudrate,
287                 int bits, int parity, int stopbits, int flowcontrol, int rts, int dtr)
288 {
289         if (!serial) {
290                 sr_dbg("Invalid serial port.");
291                 return SR_ERR;
292         }
293
294         if (serial->fd == -1) {
295                 sr_dbg("Cannot configure unopened serial port %s (fd %d).",
296                                 serial->port, serial->fd);
297                 return SR_ERR;
298         }
299
300         sr_spew("Setting serial parameters on port %s (fd %d).", serial->port,
301                         serial->fd);
302
303 #ifdef _WIN32
304         DCB dcb;
305
306         if (!GetCommState(hdl, &dcb))
307                 return SR_ERR;
308
309         switch (baudrate) {
310         case 115200:
311                 dcb.BaudRate = CBR_115200;
312                 break;
313         case 57600:
314                 dcb.BaudRate = CBR_57600;
315                 break;
316         case 38400:
317                 dcb.BaudRate = CBR_38400;
318                 break;
319         case 19200:
320                 dcb.BaudRate = CBR_19200;
321                 break;
322         case 9600:
323                 dcb.BaudRate = CBR_9600;
324                 break;
325         case 4800:
326                 dcb.BaudRate = CBR_4800;
327                 break;
328         case 2400:
329                 dcb.BaudRate = CBR_2400;
330                 break;
331         default:
332                 sr_err("Unsupported baudrate %d.", baudrate);
333                 return SR_ERR;
334         }
335         dcb.ByteSize = bits;
336         dcb.Parity = NOPARITY; /* TODO: Don't hardcode. */
337         dcb.StopBits = ONESTOPBIT; /* TODO: Don't hardcode. */
338
339         if (!SetCommState(hdl, &dcb))
340                 return SR_ERR;
341 #else
342         struct termios term;
343         speed_t baud;
344         int ret, controlbits;
345
346         if (tcgetattr(serial->fd, &term) < 0) {
347                 sr_err("tcgetattr() error on port %s (fd %d): %s.",
348                                 serial->port, serial->fd, strerror(errno));
349                 return SR_ERR;
350         }
351
352         switch (baudrate) {
353         case 50:
354                 baud = B50;
355                 break;
356         case 75:
357                 baud = B75;
358                 break;
359         case 110:
360                 baud = B110;
361                 break;
362         case 134:
363                 baud = B134;
364                 break;
365         case 150:
366                 baud = B150;
367                 break;
368         case 200:
369                 baud = B200;
370                 break;
371         case 300:
372                 baud = B300;
373                 break;
374         case 600:
375                 baud = B600;
376                 break;
377         case 1200:
378                 baud = B1200;
379                 break;
380         case 1800:
381                 baud = B1800;
382                 break;
383         case 2400:
384                 baud = B2400;
385                 break;
386         case 4800:
387                 baud = B4800;
388                 break;
389         case 9600:
390                 baud = B9600;
391                 break;
392         case 19200:
393                 baud = B19200;
394                 break;
395         case 38400:
396                 baud = B38400;
397                 break;
398         case 57600:
399                 baud = B57600;
400                 break;
401         case 115200:
402                 baud = B115200;
403                 break;
404         case 230400:
405                 baud = B230400;
406                 break;
407 #ifndef __APPLE__
408         case 460800:
409                 baud = B460800;
410                 break;
411 #endif
412         default:
413                 sr_err("Unsupported baudrate %d.", baudrate);
414                 return SR_ERR;
415         }
416
417         sr_spew("Configuring output baudrate to %d (%d).", baudrate, baud);
418         if (cfsetospeed(&term, baud) < 0) {
419                 sr_err("cfsetospeed() error: %s.", strerror(errno));
420                 return SR_ERR;
421         }
422
423         sr_spew("Configuring input baudrate to %d (%d).", baudrate, baud);
424         if (cfsetispeed(&term, baud) < 0) {
425                 sr_err("cfsetispeed() error: %s.", strerror(errno));
426                 return SR_ERR;
427         }
428
429         sr_spew("Configuring %d data bits.", bits);
430         term.c_cflag &= ~CSIZE;
431         switch (bits) {
432         case 8:
433                 term.c_cflag |= CS8;
434                 break;
435         case 7:
436                 term.c_cflag |= CS7;
437                 break;
438         default:
439                 sr_err("Unsupported data bits number %d.", bits);
440                 return SR_ERR;
441         }
442
443         sr_spew("Configuring %d stop bits.", stopbits);
444         term.c_cflag &= ~CSTOPB;
445         switch (stopbits) {
446         case 1:
447                 term.c_cflag &= ~CSTOPB;
448                 break;
449         case 2:
450                 term.c_cflag |= CSTOPB;
451                 break;
452         default:
453                 sr_err("Unsupported stopbits number %d.", stopbits);
454                 return SR_ERR;
455         }
456
457         term.c_iflag &= ~(IXON | IXOFF);
458         term.c_cflag &= ~CRTSCTS;
459         switch (flowcontrol) {
460         case 0:
461                 /* No flow control. */
462                 sr_spew("Configuring no flow control.");
463                 break;
464         case 1:
465                 sr_spew("Configuring RTS/CTS flow control.");
466                 term.c_cflag |= CRTSCTS;
467                 break;
468         case 2:
469                 sr_spew("Configuring XON/XOFF flow control.");
470                 term.c_iflag |= IXON | IXOFF;
471                 break;
472         default:
473                 sr_err("Unsupported flow control setting %d.", flowcontrol);
474                 return SR_ERR;
475         }
476
477         term.c_iflag &= ~IGNPAR;
478         term.c_cflag &= ~(PARODD | PARENB);
479         switch (parity) {
480         case SERIAL_PARITY_NONE:
481                 sr_spew("Configuring no parity.");
482                 term.c_iflag |= IGNPAR;
483                 break;
484         case SERIAL_PARITY_EVEN:
485                 sr_spew("Configuring even parity.");
486                 term.c_cflag |= PARENB;
487                 break;
488         case SERIAL_PARITY_ODD:
489                 sr_spew("Configuring odd parity.");
490                 term.c_cflag |= PARENB | PARODD;
491                 break;
492         default:
493                 sr_err("Unsupported parity setting %d.", parity);
494                 return SR_ERR;
495         }
496
497         /* Do not translate carriage return to newline on input. */
498         term.c_iflag &= ~(ICRNL);
499
500         /* Disable canonical mode, and don't echo input characters. */
501         term.c_lflag &= ~(ICANON | ECHO);
502
503         /* Write the configured settings. */
504         if (tcsetattr(serial->fd, TCSADRAIN, &term) < 0) {
505                 sr_err("tcsetattr() error: %s.", strerror(errno));
506                 return SR_ERR;
507         }
508
509         if (rts != -1) {
510                 sr_spew("Setting RTS %s.", rts ? "high" : "low");
511                 controlbits = TIOCM_RTS;
512                 if ((ret = ioctl(serial->fd, rts ? TIOCMBIS : TIOCMBIC,
513                                 &controlbits)) < 0) {
514                         sr_err("Error setting RTS: %s.", strerror(errno));
515                         return SR_ERR;
516                 }
517         }
518
519         if (dtr != -1) {
520                 sr_spew("Setting DTR %s.", dtr ? "high" : "low");
521                 controlbits = TIOCM_DTR;
522                 if ((ret = ioctl(serial->fd, dtr ? TIOCMBIS : TIOCMBIC,
523                                 &controlbits)) < 0) {
524                         sr_err("Error setting DTR: %s.", strerror(errno));
525                         return SR_ERR;
526                 }
527         }
528
529 #endif
530
531         return SR_OK;
532 }
533
534 /**
535  * Set serial parameters for the specified serial port.
536  *
537  * @param serial Previously initialized serial port structure.
538  * @param paramstr A serial communication parameters string, in the form
539  * of <speed>/<data bits><parity><stopbits>, for example "9600/8n1" or
540  * "600/7o2".
541  *
542  * @return SR_OK upon success, SR_ERR upon failure.
543  */
544 #define SERIAL_COMM_SPEC "^(\\d+)/([78])([neo])([12])(.*)$"
545 SR_PRIV int serial_set_paramstr(struct sr_serial_dev_inst *serial,
546                 const char *paramstr)
547 {
548         GRegex *reg;
549         GMatchInfo *match;
550         int speed, databits, parity, stopbits, rts, dtr, i;
551         char *mstr, **opts, **kv;
552
553         speed = databits = parity = stopbits = 0;
554         rts = dtr = -1;
555         reg = g_regex_new(SERIAL_COMM_SPEC, 0, 0, NULL);
556         if (g_regex_match(reg, paramstr, 0, &match)) {
557                 if ((mstr = g_match_info_fetch(match, 1)))
558                         speed = strtoul(mstr, NULL, 10);
559                 g_free(mstr);
560                 if ((mstr = g_match_info_fetch(match, 2)))
561                         databits = strtoul(mstr, NULL, 10);
562                 g_free(mstr);
563                 if ((mstr = g_match_info_fetch(match, 3))) {
564                         switch (mstr[0]) {
565                         case 'n':
566                                 parity = SERIAL_PARITY_NONE;
567                                 break;
568                         case 'e':
569                                 parity = SERIAL_PARITY_EVEN;
570                                 break;
571                         case 'o':
572                                 parity = SERIAL_PARITY_ODD;
573                                 break;
574                         }
575                 }
576                 g_free(mstr);
577                 if ((mstr = g_match_info_fetch(match, 4)))
578                         stopbits = strtoul(mstr, NULL, 10);
579                 g_free(mstr);
580                 if ((mstr = g_match_info_fetch(match, 5)) && mstr[0] != '\0') {
581                         if (mstr[0] != '/') {
582                                 sr_dbg("missing separator before extra options");
583                                 speed = 0;
584                         } else {
585                                 /* A set of "key=value" options separated by / */
586                                 opts = g_strsplit(mstr + 1, "/", 0);
587                                 for (i = 0; opts[i]; i++) {
588                                         kv = g_strsplit(opts[i], "=", 2);
589                                         if (!strncmp(kv[0], "rts", 3)) {
590                                                 if (kv[1][0] == '1')
591                                                         rts = 1;
592                                                 else if (kv[1][0] == '0')
593                                                         rts = 0;
594                                                 else {
595                                                         sr_dbg("invalid value for rts: %c", kv[1][0]);
596                                                         speed = 0;
597                                                 }
598                                         } else if (!strncmp(kv[0], "dtr", 3)) {
599                                                 if (kv[1][0] == '1')
600                                                         dtr = 1;
601                                                 else if (kv[1][0] == '0')
602                                                         dtr = 0;
603                                                 else {
604                                                         sr_dbg("invalid value for dtr: %c", kv[1][0]);
605                                                         speed = 0;
606                                                 }
607                                         }
608                                         g_strfreev(kv);
609                                 }
610                                 g_strfreev(opts);
611                         }
612                 }
613                 g_free(mstr);
614         }
615         g_match_info_unref(match);
616         g_regex_unref(reg);
617
618         if (speed)
619                 return serial_set_params(serial, speed, databits, parity, stopbits,
620                                 0, rts, dtr);
621         else
622                 return SR_ERR_ARG;
623 }
624
625 /**
626  * Read a line from the specified serial port.
627  *
628  * @param serial Previously initialized serial port structure.
629  * @param buf Buffer where to store the bytes that are read.
630  * @param buflen Size of the buffer.
631  * @param timeout_ms How long to wait for a line to come in.
632  *
633  * Reading stops when CR of LR is found, which is stripped from the buffer.
634  *
635  * @return SR_OK on success, SR_ERR on failure.
636  */
637 SR_PRIV int serial_readline(struct sr_serial_dev_inst *serial, char **buf,
638                 int *buflen, gint64 timeout_ms)
639 {
640         gint64 start;
641         int maxlen, len;
642
643         if (!serial || serial->fd == -1) {
644                 sr_dbg("Invalid serial port.");
645                 return SR_ERR;
646         }
647
648         if (serial->fd == -1) {
649                 sr_dbg("Cannot use unopened serial port %s (fd %d).",
650                                 serial->port, serial->fd);
651                 return -1;
652         }
653
654         timeout_ms *= 1000;
655         start = g_get_monotonic_time();
656
657         maxlen = *buflen;
658         *buflen = len = 0;
659         while(1) {
660                 len = maxlen - *buflen - 1;
661                 if (len < 1)
662                         break;
663                 len = serial_read(serial, *buf + *buflen, 1);
664                 if (len > 0) {
665                         *buflen += len;
666                         *(*buf + *buflen) = '\0';
667                         if (*buflen > 0 && (*(*buf + *buflen - 1) == '\r'
668                                         || *(*buf + *buflen - 1) == '\n')) {
669                                 /* Strip CR/LF and terminate. */
670                                 *(*buf + --*buflen) = '\0';
671                                 break;
672                         }
673                 }
674                 if (g_get_monotonic_time() - start > timeout_ms)
675                         /* Timeout */
676                         break;
677                 g_usleep(2000);
678         }
679         if (*buflen)
680                 sr_dbg("Received %d: '%s'.", *buflen, *buf);
681
682         return SR_OK;
683 }
684
685 /**
686  * Try to find a valid packet in a serial data stream.
687  *
688  * @param serial Previously initialized serial port structure.
689  * @param buf Buffer containing the bytes to write.
690  * @param count Size of the buffer.
691  * @param packet_size Size, in bytes, of a valid packet.
692  * @param is_valid Callback that assesses whether the packet is valid or not.
693  * @param timeout_ms The timeout after which, if no packet is detected, to
694  *                   abort scanning.
695  * @param baudrate The baudrate of the serial port. This parameter is not
696  *                 critical, but it helps fine tune the serial port polling
697  *                 delay.
698  *
699  * @return SR_OK if a valid packet is found within the given timeout,
700  *         SR_ERR upon failure.
701  */
702 SR_PRIV int serial_stream_detect(struct sr_serial_dev_inst *serial,
703                                  uint8_t *buf, size_t *buflen,
704                                  size_t packet_size, packet_valid_t is_valid,
705                                  uint64_t timeout_ms, int baudrate)
706 {
707         uint64_t start, time, byte_delay_us;
708         size_t ibuf, i, maxlen;
709         int len;
710
711         maxlen = *buflen;
712
713         sr_dbg("Detecting packets on FD %d (timeout = %" PRIu64
714                "ms, baudrate = %d).", serial->fd, timeout_ms, baudrate);
715
716         if (maxlen < (packet_size / 2) ) {
717                 sr_err("Buffer size must be at least twice the packet size.");
718                 return SR_ERR;
719         }
720
721         /* Assume 8n1 transmission. That is 10 bits for every byte. */
722         byte_delay_us = 10 * (1000000 / baudrate);
723         start = g_get_monotonic_time();
724
725         i = ibuf = len = 0;
726         while (ibuf < maxlen) {
727                 len = serial_read(serial, &buf[ibuf], 1);
728                 if (len > 0) {
729                         ibuf += len;
730                 } else if (len == 0) {
731                         sr_spew("Error: Only read 0 bytes.");
732                 } else {
733                         /* Error reading byte, but continuing anyway. */
734                 }
735
736                 time = g_get_monotonic_time() - start;
737                 time /= 1000;
738
739                 if ((ibuf - i) >= packet_size) {
740                         /* We have at least a packet's worth of data. */
741                         if (is_valid(&buf[i])) {
742                                 sr_spew("Found valid %d-byte packet after "
743                                         "%" PRIu64 "ms.", (ibuf - i), time);
744                                 *buflen = ibuf;
745                                 return SR_OK;
746                         } else {
747                                 sr_spew("Got %d bytes, but not a valid "
748                                         "packet.", (ibuf - i));
749                         }
750                         /* Not a valid packet. Continue searching. */
751                         i++;
752                 }
753                 if (time >= timeout_ms) {
754                         /* Timeout */
755                         sr_dbg("Detection timed out after %dms.", time);
756                         break;
757                 }
758                 g_usleep(byte_delay_us);
759         }
760
761         *buflen = ibuf;
762
763         sr_err("Didn't find a valid packet (read %d bytes).", *buflen);
764
765         return SR_ERR;
766 }