]> sigrok.org Git - libsigrok.git/blob - hardware/common/serial.c
serial.c: Sanitize serial_stream_detect
[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 <glib.h>
36 #include "libsigrok.h"
37 #include "libsigrok-internal.h"
38
39 /* Message logging helpers with driver-specific prefix string. */
40 #define DRIVER_LOG_DOMAIN "serial: "
41 #define sr_log(l, s, args...) sr_log(l, DRIVER_LOG_DOMAIN s, ## args)
42 #define sr_spew(s, args...) sr_spew(DRIVER_LOG_DOMAIN s, ## args)
43 #define sr_dbg(s, args...) sr_dbg(DRIVER_LOG_DOMAIN s, ## args)
44 #define sr_info(s, args...) sr_info(DRIVER_LOG_DOMAIN s, ## args)
45 #define sr_warn(s, args...) sr_warn(DRIVER_LOG_DOMAIN s, ## args)
46 #define sr_err(s, args...) sr_err(DRIVER_LOG_DOMAIN s, ## args)
47
48 // FIXME: Must be moved, or rather passed as function argument.
49 #ifdef _WIN32
50 static HANDLE hdl;
51 #endif
52
53 /**
54  * Open the specified serial port.
55  *
56  * @param serial Previously initialized serial port structure.
57  * @param flags Flags to use when opening the serial port.
58  * TODO: Abstract 'flags', currently they're OS-specific!
59  *
60  * If the serial structure contains a serialcomm string, it will be
61  * passed to serial_set_paramstr() after the port is opened.
62  *
63  * @return SR_OK on success, SR_ERR on failure.
64  */
65 SR_PRIV int serial_open(struct sr_serial_dev_inst *serial, int flags)
66 {
67
68         if (!serial) {
69                 sr_dbg("Invalid serial port.");
70                 return SR_ERR;
71         }
72
73         sr_spew("Opening serial port '%s' (flags %d).", serial->port, flags);
74
75 #ifdef _WIN32
76         hdl = CreateFile(serial->port, GENERIC_READ | GENERIC_WRITE, 0, 0,
77                          OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
78         if (hdl == INVALID_HANDLE_VALUE) {
79                 sr_err("Error opening serial port '%s'.", serial->port);
80                 return SR_ERR;
81         }
82 #else
83         if ((serial->fd = open(serial->port, flags)) < 0) {
84                 sr_err("Error opening serial port '%s': %s.", serial->port,
85                        strerror(errno));
86                 return SR_ERR;
87         } else
88                 sr_spew("Opened serial port '%s' (fd %d).", serial->port, serial->fd);
89 #endif
90
91         if (serial->serialcomm)
92                 return serial_set_paramstr(serial, serial->serialcomm);
93         else
94                 return SR_OK;
95 }
96
97 /**
98  * Close the specified serial port.
99  *
100  * @param serial Previously initialized serial port structure.
101  *
102  * @return SR_OK on success, SR_ERR on failure.
103  */
104 SR_PRIV int serial_close(struct sr_serial_dev_inst *serial)
105 {
106         int ret;
107
108         if (!serial) {
109                 sr_dbg("Invalid serial port.");
110                 return SR_ERR;
111         }
112
113         if (serial->fd == -1) {
114                 sr_dbg("Cannot close unopened serial port %s (fd %d).",
115                                 serial->port, serial->fd);
116                 return SR_ERR;
117         }
118
119         sr_spew("Closing serial port %s (fd %d).", serial->port, serial->fd);
120         ret = SR_OK;
121
122 #ifdef _WIN32
123         /* Returns non-zero upon success, 0 upon failure. */
124         if (CloseHandle(hdl) == 0)
125                 ret = SR_ERR;
126 #else
127         /* Returns 0 upon success, -1 upon failure. */
128         if (close(serial->fd) < 0) {
129                 sr_err("Error closing serial port: %s (fd %d).", strerror(errno),
130                                 serial->fd);
131                 ret = SR_ERR;
132         }
133 #endif
134
135         serial->fd = -1;
136
137         return ret;
138 }
139
140 /**
141  * Flush serial port buffers.
142  *
143  * @param serial Previously initialized serial port structure.
144  *
145  * @return SR_OK on success, SR_ERR on failure.
146  */
147 SR_PRIV int serial_flush(struct sr_serial_dev_inst *serial)
148 {
149         int ret;
150
151         if (!serial) {
152                 sr_dbg("Invalid serial port.");
153                 return SR_ERR;
154         }
155
156         if (serial->fd == -1) {
157                 sr_dbg("Cannot flush unopened serial port %s (fd %d).",
158                                 serial->port, serial->fd);
159                 return SR_ERR;
160         }
161
162         sr_spew("Flushing serial port %s (fd %d).", serial->port, serial->fd);
163         ret = SR_OK;
164
165 #ifdef _WIN32
166         /* Returns non-zero upon success, 0 upon failure. */
167         if (PurgeComm(hdl, PURGE_RXCLEAR | PURGE_TXCLEAR) == 0) {
168                 sr_err("Error flushing serial port: %s.", strerror(errno));
169                 ret = SR_ERR;
170         }
171 #else
172         /* Returns 0 upon success, -1 upon failure. */
173         if (tcflush(serial->fd, TCIOFLUSH) < 0) {
174                 sr_err("Error flushing serial port: %s.", strerror(errno));
175                 ret = SR_ERR;
176         }
177
178         return ret;
179 #endif
180 }
181
182 /**
183  * Write a number of bytes to the specified serial port.
184  *
185  * @param serial Previously initialized serial port structure.
186  * @param buf Buffer containing the bytes to write.
187  * @param count Number of bytes to write.
188  *
189  * @return The number of bytes written, or -1 upon failure.
190  */
191 SR_PRIV int serial_write(struct sr_serial_dev_inst *serial,
192                 const void *buf, size_t count)
193 {
194         ssize_t ret;
195
196         if (!serial) {
197                 sr_dbg("Invalid serial port.");
198                 return -1;
199         }
200
201         if (serial->fd == -1) {
202                 sr_dbg("Cannot use unopened serial port %s (fd %d).",
203                                 serial->port, serial->fd);
204                 return -1;
205         }
206
207 #ifdef _WIN32
208         DWORD tmp = 0;
209
210         /* FIXME */
211         /* Returns non-zero upon success, 0 upon failure. */
212         WriteFile(hdl, buf, count, &tmp, NULL);
213 #else
214         /* Returns the number of bytes written, or -1 upon failure. */
215         ret = write(serial->fd, buf, count);
216         if (ret < 0)
217                 sr_err("Write error: %s.", strerror(errno));
218         else
219                 sr_spew("Wrote %d/%d bytes (fd %d).", ret, count, serial->fd);
220 #endif
221
222         return ret;
223 }
224
225 /**
226  * Read a number of bytes from the specified serial port.
227  *
228  * @param serial Previously initialized serial port structure.
229  * @param buf Buffer where to store the bytes that are read.
230  * @param count The number of bytes to read.
231  *
232  * @return The number of bytes read, or -1 upon failure.
233  */
234 SR_PRIV int serial_read(struct sr_serial_dev_inst *serial, void *buf,
235                 size_t count)
236 {
237         ssize_t ret;
238
239         if (!serial) {
240                 sr_dbg("Invalid serial port.");
241                 return -1;
242         }
243
244         if (serial->fd == -1) {
245                 sr_dbg("Cannot use unopened serial port %s (fd %d).",
246                                 serial->port, serial->fd);
247                 return -1;
248         }
249
250 #ifdef _WIN32
251         DWORD tmp = 0;
252
253         /* FIXME */
254         /* Returns non-zero upon success, 0 upon failure. */
255         return ReadFile(hdl, buf, count, &tmp, NULL);
256 #else
257         /* Returns the number of bytes read, or -1 upon failure. */
258         ret = read(serial->fd, buf, count);
259         if (ret < 0)
260                 /*
261                  * Should be sr_err(), but that would yield lots of
262                  * "Resource temporarily unavailable" messages.
263                  */
264                 sr_spew("Read error: %s (fd %d).", strerror(errno), serial->fd);
265         else
266                 sr_spew("Read %d/%d bytes (fd %d).", ret, count, serial->fd);
267 #endif
268
269         return ret;
270 }
271
272 /**
273  * Set serial parameters for the specified serial port.
274  *
275  * @param serial Previously initialized serial port structure.
276  * @param baudrate The baudrate to set.
277  * @param bits The number of data bits to use.
278  * @param parity The parity setting to use (0 = none, 1 = even, 2 = odd).
279  * @param stopbits The number of stop bits to use (1 or 2).
280  * @param flowcontrol The flow control settings to use (0 = none, 1 = RTS/CTS,
281  *                    2 = XON/XOFF).
282  *
283  * @return SR_OK upon success, SR_ERR upon failure.
284  */
285 SR_PRIV int serial_set_params(struct sr_serial_dev_inst *serial, int baudrate,
286                 int bits, int parity, int stopbits, int flowcontrol)
287 {
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
345         if (tcgetattr(serial->fd, &term) < 0) {
346                 sr_err("tcgetattr() error on port %s (fd %d): %s.",
347                                 serial->port, serial->fd, strerror(errno));
348                 return SR_ERR;
349         }
350
351         switch (baudrate) {
352         case 50:
353                 baud = B50;
354                 break;
355         case 75:
356                 baud = B75;
357                 break;
358         case 110:
359                 baud = B110;
360                 break;
361         case 134:
362                 baud = B134;
363                 break;
364         case 150:
365                 baud = B150;
366                 break;
367         case 200:
368                 baud = B200;
369                 break;
370         case 300:
371                 baud = B300;
372                 break;
373         case 600:
374                 baud = B600;
375                 break;
376         case 1200:
377                 baud = B1200;
378                 break;
379         case 1800:
380                 baud = B1800;
381                 break;
382         case 2400:
383                 baud = B2400;
384                 break;
385         case 4800:
386                 baud = B4800;
387                 break;
388         case 9600:
389                 baud = B9600;
390                 break;
391         case 19200:
392                 baud = B19200;
393                 break;
394         case 38400:
395                 baud = B38400;
396                 break;
397         case 57600:
398                 baud = B57600;
399                 break;
400         case 115200:
401                 baud = B115200;
402                 break;
403         case 230400:
404                 baud = B230400;
405                 break;
406 #ifndef __APPLE__
407         case 460800:
408                 baud = B460800;
409                 break;
410 #endif
411         default:
412                 sr_err("Unsupported baudrate %d.", baudrate);
413                 return SR_ERR;
414         }
415
416         sr_spew("Configuring output baudrate to %d (%d).", baudrate, baud);
417         if (cfsetospeed(&term, baud) < 0) {
418                 sr_err("cfsetospeed() error: %s.", strerror(errno));
419                 return SR_ERR;
420         }
421
422         sr_spew("Configuring input baudrate to %d (%d).", baudrate, baud);
423         if (cfsetispeed(&term, baud) < 0) {
424                 sr_err("cfsetispeed() error: %s.", strerror(errno));
425                 return SR_ERR;
426         }
427
428         sr_spew("Configuring %d data bits.", bits);
429         term.c_cflag &= ~CSIZE;
430         switch (bits) {
431         case 8:
432                 term.c_cflag |= CS8;
433                 break;
434         case 7:
435                 term.c_cflag |= CS7;
436                 break;
437         default:
438                 sr_err("Unsupported data bits number %d.", bits);
439                 return SR_ERR;
440         }
441
442         sr_spew("Configuring %d stop bits.", stopbits);
443         term.c_cflag &= ~CSTOPB;
444         switch (stopbits) {
445         case 1:
446                 term.c_cflag &= ~CSTOPB;
447                 break;
448         case 2:
449                 term.c_cflag |= CSTOPB;
450                 break;
451         default:
452                 sr_err("Unsupported stopbits number %d.", stopbits);
453                 return SR_ERR;
454         }
455
456         term.c_iflag &= ~(IXON | IXOFF);
457         term.c_cflag &= ~CRTSCTS;
458         switch (flowcontrol) {
459         case 0:
460                 /* No flow control. */
461                 sr_spew("Configuring no flow control.");
462                 break;
463         case 1:
464                 sr_spew("Configuring RTS/CTS flow control.");
465                 term.c_cflag |= CRTSCTS;
466                 break;
467         case 2:
468                 sr_spew("Configuring XON/XOFF flow control.");
469                 term.c_iflag |= IXON | IXOFF;
470                 break;
471         default:
472                 sr_err("Unsupported flow control setting %d.", flowcontrol);
473                 return SR_ERR;
474         }
475
476         term.c_iflag &= ~IGNPAR;
477         term.c_cflag &= ~(PARODD | PARENB);
478         switch (parity) {
479         case SERIAL_PARITY_NONE:
480                 sr_spew("Configuring no parity.");
481                 term.c_iflag |= IGNPAR;
482                 break;
483         case SERIAL_PARITY_EVEN:
484                 sr_spew("Configuring even parity.");
485                 term.c_cflag |= PARENB;
486                 break;
487         case SERIAL_PARITY_ODD:
488                 sr_spew("Configuring odd parity.");
489                 term.c_cflag |= PARENB | PARODD;
490                 break;
491         default:
492                 sr_err("Unsupported parity setting %d.", parity);
493                 return SR_ERR;
494         }
495
496         /* Do not translate carriage return to newline on input. */
497         term.c_iflag &= ~(ICRNL);
498
499         /* Disable canonical mode, and don't echo input characters. */
500         term.c_lflag &= ~(ICANON | ECHO);
501
502         /* Write the configured settings. */
503         if (tcsetattr(serial->fd, TCSADRAIN, &term) < 0) {
504                 sr_err("tcsetattr() error: %s.", strerror(errno));
505                 return SR_ERR;
506         }
507 #endif
508
509         return SR_OK;
510 }
511
512 /**
513  * Set serial parameters for the specified serial port.
514  *
515  * @param serial Previously initialized serial port structure.
516  * @param paramstr A serial communication parameters string, in the form
517  * of <speed>/<data bits><parity><stopbits>, for example "9600/8n1" or
518  * "600/7o2".
519  *
520  * @return SR_OK upon success, SR_ERR upon failure.
521  */
522 #define SERIAL_COMM_SPEC "^(\\d+)/([78])([neo])([12])$"
523 SR_PRIV int serial_set_paramstr(struct sr_serial_dev_inst *serial,
524                 const char *paramstr)
525 {
526         GRegex *reg;
527         GMatchInfo *match;
528         int speed, databits, parity, stopbits;
529         char *mstr;
530
531         speed = databits = parity = stopbits = 0;
532         reg = g_regex_new(SERIAL_COMM_SPEC, 0, 0, NULL);
533         if (g_regex_match(reg, paramstr, 0, &match)) {
534                 if ((mstr = g_match_info_fetch(match, 1)))
535                         speed = strtoul(mstr, NULL, 10);
536                 g_free(mstr);
537                 if ((mstr = g_match_info_fetch(match, 2)))
538                         databits = strtoul(mstr, NULL, 10);
539                 g_free(mstr);
540                 if ((mstr = g_match_info_fetch(match, 3))) {
541                         switch (mstr[0]) {
542                         case 'n':
543                                 parity = SERIAL_PARITY_NONE;
544                                 break;
545                         case 'e':
546                                 parity = SERIAL_PARITY_EVEN;
547                                 break;
548                         case 'o':
549                                 parity = SERIAL_PARITY_ODD;
550                                 break;
551                         }
552                 }
553                 g_free(mstr);
554                 if ((mstr = g_match_info_fetch(match, 4)))
555                         stopbits = strtoul(mstr, NULL, 10);
556                 g_free(mstr);
557         }
558         g_match_info_unref(match);
559         g_regex_unref(reg);
560
561         if (speed)
562                 return serial_set_params(serial, speed, databits, parity, stopbits, 0);
563         else
564                 return SR_ERR_ARG;
565 }
566
567 /**
568  * Read a line from the specified serial port.
569  *
570  * @param serial Previously initialized serial port structure.
571  * @param buf Buffer where to store the bytes that are read.
572  * @param buflen Size of the buffer.
573  * @param timeout_ms How long to wait for a line to come in.
574  *
575  * Reading stops when CR of LR is found, which is stripped from the buffer.
576  *
577  * @return SR_OK on success, SR_ERR on failure.
578  */
579 SR_PRIV int serial_readline(struct sr_serial_dev_inst *serial, char **buf,
580                 int *buflen, gint64 timeout_ms)
581 {
582         gint64 start;
583         int maxlen, len;
584
585         if (!serial || serial->fd == -1) {
586                 sr_dbg("Invalid serial port.");
587                 return SR_ERR;
588         }
589
590         if (serial->fd == -1) {
591                 sr_dbg("Cannot use unopened serial port %s (fd %d).",
592                                 serial->port, serial->fd);
593                 return -1;
594         }
595
596         timeout_ms *= 1000;
597         start = g_get_monotonic_time();
598
599         maxlen = *buflen;
600         *buflen = len = 0;
601         while(1) {
602                 len = maxlen - *buflen - 1;
603                 if (len < 1)
604                         break;
605                 len = serial_read(serial, *buf + *buflen, 1);
606                 if (len > 0) {
607                         *buflen += len;
608                         *(*buf + *buflen) = '\0';
609                         if (*buflen > 0 && (*(*buf + *buflen - 1) == '\r'
610                                         || *(*buf + *buflen - 1) == '\n')) {
611                                 /* Strip CR/LF and terminate. */
612                                 *(*buf + --*buflen) = '\0';
613                                 break;
614                         }
615                 }
616                 if (g_get_monotonic_time() - start > timeout_ms)
617                         /* Timeout */
618                         break;
619                 g_usleep(2000);
620         }
621         if (*buflen)
622                 sr_dbg("Received %d: '%s'.", *buflen, *buf);
623
624         return SR_OK;
625 }
626
627 /**
628  * Try to find a valid packet in a serial data stream.
629  *
630  * @param serial Previously initialized serial port structure.
631  * @param buf Buffer containing the bytes to write.
632  * @param count Size of the buffer.
633  * @param packet_size Size, in bytes, of a valid packet.
634  * @param is_valid Callback that assesses whether the packet is valid or not.
635  * @param timeout_ms The timeout after which, if no packet is detected, to
636  *                   abort scanning.
637  * @param baudrate The baudrate of the serial port. This parameter is not
638  *                 critical, but it helps fine tune the serial port polling
639  *                 delay.
640  *
641  * @return SR_OK if a valid packet is found within the given timeout,
642  *         SR_ERR upon failure.
643  */
644 SR_PRIV int serial_stream_detect(struct sr_serial_dev_inst *serial,
645                                  uint8_t *buf, size_t *buflen,
646                                  size_t packet_size, packet_valid_t is_valid,
647                                  uint64_t timeout_ms, int baudrate)
648 {
649         uint64_t start, time, byte_delay_us;
650         size_t ibuf, i, maxlen;
651         int len;
652
653         maxlen = *buflen;
654
655         sr_dbg("Detecting packets on FD %d (timeout = %" PRIu64
656                "ms, baudrate = %d).", serial->fd, timeout_ms, baudrate);
657
658         if (maxlen < (packet_size / 2) ) {
659                 sr_err("Buffer size must be at least twice the packet size.");
660                 return SR_ERR;
661         }
662
663         /* Assume 8n1 transmission. That is 10 bits for every byte. */
664         byte_delay_us = 10 * (1000000 / baudrate);
665         start = g_get_monotonic_time();
666
667         i = ibuf = len = 0;
668         while (ibuf < maxlen) {
669                 len = serial_read(serial, &buf[ibuf], 1);
670                 if (len > 0) {
671                         ibuf += len;
672                 } else if (len == 0) {
673                         sr_spew("Error: Only read 0 bytes.");
674                 } else {
675                         /* Error reading byte, but continuing anyway. */
676                 }
677
678                 time = g_get_monotonic_time() - start;
679                 time /= 1000;
680
681                 if ((ibuf - i) >= packet_size) {
682                         /* We have at least a packet's worth of data. */
683                         if (is_valid(&buf[i])) {
684                                 sr_spew("Found valid %d-byte packet after "
685                                         "%" PRIu64 "ms.", (ibuf - i), time);
686                                 *buflen = ibuf;
687                                 return SR_OK;
688                         } else {
689                                 sr_spew("Got %d bytes, but not a valid "
690                                         "packet.", (ibuf - i));
691                         }
692                         /* Not a valid packet. Continue searching. */
693                         i++;
694                 }
695                 if (time >= timeout_ms) {
696                         /* Timeout */
697                         sr_dbg("Detection timed out after %dms.", time);
698                         break;
699                 }
700                 g_usleep(byte_delay_us);
701         }
702
703         *buflen = ibuf;
704
705         sr_err("Didn't find a valid packet (read %d bytes).", *buflen);
706
707         return SR_ERR;
708 }