libsigrok
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines
serial.c
Go to the documentation of this file.
00001 /*
00002  * This file is part of the sigrok project.
00003  *
00004  * Copyright (C) 2010-2012 Bert Vermeulen <bert@biot.com>
00005  *
00006  * This program is free software: you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation, either version 3 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00018  */
00019 
00020 #include <string.h>
00021 #include <sys/types.h>
00022 #include <sys/stat.h>
00023 #include <fcntl.h>
00024 #include <unistd.h>
00025 #ifdef _WIN32
00026 #include <windows.h>
00027 #else
00028 #include <glob.h>
00029 #include <termios.h>
00030 #endif
00031 #include <stdlib.h>
00032 #include <glib.h>
00033 #include "sigrok.h"
00034 #include "sigrok-internal.h"
00035 
00036 // FIXME: Must be moved, or rather passed as function argument.
00037 #ifdef _WIN32
00038 static HANDLE hdl;
00039 #endif
00040 
00041 static const char *serial_port_glob[] = {
00042         /* Linux */
00043         "/dev/ttyS*",
00044         "/dev/ttyUSB*",
00045         "/dev/ttyACM*",
00046         /* MacOS X */
00047         "/dev/ttys*",
00048         "/dev/tty.USB-*",
00049         "/dev/tty.Modem-*",
00050         NULL,
00051 };
00052 
00053 SR_PRIV GSList *list_serial_ports(void)
00054 {
00055         GSList *ports;
00056 
00057 #ifdef _WIN32
00058         /* TODO */
00059         ports = NULL;
00060         ports = g_slist_append(ports, g_strdup("COM1"));
00061 #else
00062         glob_t g;
00063         unsigned int i, j;
00064 
00065         ports = NULL;
00066         for (i = 0; serial_port_glob[i]; i++) {
00067                 if (glob(serial_port_glob[i], 0, NULL, &g))
00068                         continue;
00069                 for (j = 0; j < g.gl_pathc; j++)
00070                         ports = g_slist_append(ports, g_strdup(g.gl_pathv[j]));
00071                 globfree(&g);
00072         }
00073 #endif
00074 
00075         return ports;
00076 }
00077 
00078 SR_PRIV int serial_open(const char *pathname, int flags)
00079 {
00080 #ifdef _WIN32
00081         /* FIXME: Don't hardcode COM1. */
00082         hdl = CreateFile("COM1", GENERIC_READ | GENERIC_WRITE, 0, 0,
00083                          OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
00084         if (hdl == INVALID_HANDLE_VALUE) {
00085                 /* TODO: Error handling. */
00086         }
00087         return 0;
00088 #else
00089         return open(pathname, flags);
00090 #endif
00091 }
00092 
00093 /*
00094  * Close the serial port.
00095  * Returns 0 upon success, -1 upon failure.
00096  */
00097 SR_PRIV int serial_close(int fd)
00098 {
00099 #ifdef _WIN32
00100         /* Returns non-zero upon success, 0 upon failure. */
00101         return (CloseHandle(hdl) == 0) ? -1 : 0;
00102 #else
00103         /* Returns 0 upon success, -1 upon failure. */
00104         return close(fd);
00105 #endif
00106 }
00107 
00108 /*
00109  * Flush serial port buffers (if any).
00110  * Returns 0 upon success, -1 upon failure.
00111  */
00112 SR_PRIV int serial_flush(int fd)
00113 {
00114 #ifdef _WIN32
00115         /* Returns non-zero upon success, 0 upon failure. */
00116         return (PurgeComm(hdl, PURGE_RXCLEAR | PURGE_TXCLEAR) == 0) ? -1 : 0;
00117 #else
00118         /* Returns 0 upon success, -1 upon failure. */
00119         return tcflush(fd, TCIOFLUSH);
00120 #endif
00121 }
00122 
00123 /*
00124  * Write a number of bytes to the specified serial port.
00125  * Returns the number of bytes written, or -1 upon failure.
00126  */
00127 SR_PRIV int serial_write(int fd, const void *buf, size_t count)
00128 {
00129 #ifdef _WIN32
00130         DWORD tmp = 0;
00131 
00132         /* FIXME */
00133         /* Returns non-zero upon success, 0 upon failure. */
00134         WriteFile(hdl, buf, count, &tmp, NULL);
00135 #else
00136         /* Returns the number of bytes written, or -1 upon failure. */
00137         return write(fd, buf, count);
00138 #endif
00139 }
00140 
00141 /*
00142  * Read a number of bytes from the specified serial port.
00143  * Returns the number of bytes read, or -1 upon failure.
00144  */
00145 SR_PRIV int serial_read(int fd, void *buf, size_t count)
00146 {
00147 #ifdef _WIN32
00148         DWORD tmp = 0;
00149 
00150         /* FIXME */
00151         /* Returns non-zero upon success, 0 upon failure. */
00152         return ReadFile(hdl, buf, count, &tmp, NULL);
00153 #else
00154         /* Returns the number of bytes read, or -1 upon failure. */
00155         return read(fd, buf, count);
00156 #endif
00157 }
00158 
00159 SR_PRIV void *serial_backup_params(int fd)
00160 {
00161 #ifdef _WIN32
00162         /* TODO */
00163 #else
00164         struct termios *term;
00165 
00166         /* TODO: 'term' is never g_free()'d? */
00167         if (!(term = g_try_malloc(sizeof(struct termios)))) {
00168                 sr_err("serial: %s: term malloc failed", __func__);
00169                 return NULL;
00170         }
00171 
00172         tcgetattr(fd, term);
00173 
00174         return term;
00175 #endif
00176 }
00177 
00178 SR_PRIV void serial_restore_params(int fd, void *backup)
00179 {
00180 #ifdef _WIN32
00181         /* TODO */
00182 #else
00183         tcsetattr(fd, TCSADRAIN, (struct termios *)backup);
00184 #endif
00185 }
00186 
00187 /*
00188  * Set serial parameters.
00189  *
00190  * flowcontrol: 1 = rts/cts, 2 = xon/xoff
00191  * parity: 0 = none, 1 = even, 2 = odd
00192  */
00193 SR_PRIV int serial_set_params(int fd, int baudrate, int bits, int parity,
00194                               int stopbits, int flowcontrol)
00195 {
00196 #ifdef _WIN32
00197         DCB dcb;
00198 
00199         if (!GetCommState(hdl, &dcb)) {
00200                 /* TODO: Error handling. */
00201                 return SR_ERR;
00202         }
00203 
00204         switch (baudrate) {
00205         /* TODO: Support for higher baud rates. */
00206         case 115200:
00207                 dcb.BaudRate = CBR_115200;
00208                 break;
00209         case 57600:
00210                 dcb.BaudRate = CBR_57600;
00211                 break;
00212         case 38400:
00213                 dcb.BaudRate = CBR_38400;
00214                 break;
00215         case 19200:
00216                 dcb.BaudRate = CBR_19200;
00217                 break;
00218         case 9600:
00219                 dcb.BaudRate = CBR_9600;
00220                 break;
00221         default:
00222                 /* TODO: Error handling. */
00223                 break;
00224         }
00225         dcb.ByteSize = bits;
00226         dcb.Parity = NOPARITY; /* TODO: Don't hardcode. */
00227         dcb.StopBits = ONESTOPBIT; /* TODO: Don't hardcode. */
00228 
00229         if (!SetCommState(hdl, &dcb)) {
00230                 /* TODO: Error handling. */
00231                 return SR_ERR;
00232         }
00233 #else
00234         struct termios term;
00235         speed_t baud;
00236 
00237         switch (baudrate) {
00238         case 9600:
00239                 baud = B9600;
00240                 break;
00241         case 38400:
00242                 baud = B38400;
00243                 break;
00244         case 57600:
00245                 baud = B57600;
00246                 break;
00247         case 115200:
00248                 baud = B115200;
00249                 break;
00250 #ifndef __APPLE__
00251         case 460800:
00252                 baud = B460800;
00253                 break;
00254 #endif
00255         default:
00256                 return SR_ERR;
00257         }
00258 
00259         if (tcgetattr(fd, &term) < 0)
00260                 return SR_ERR;
00261         if (cfsetispeed(&term, baud) < 0)
00262                 return SR_ERR;
00263 
00264         term.c_cflag &= ~CSIZE;
00265         switch (bits) {
00266         case 8:
00267                 term.c_cflag |= CS8;
00268                 break;
00269         case 7:
00270                 term.c_cflag |= CS7;
00271                 break;
00272         default:
00273                 return SR_ERR;
00274         }
00275 
00276         term.c_cflag &= ~CSTOPB;
00277         switch (stopbits) {
00278         case 1:
00279                 break;
00280         case 2:
00281                 term.c_cflag |= CSTOPB;
00282         default:
00283                 return SR_ERR;
00284         }
00285 
00286         term.c_cflag &= ~(IXON | IXOFF | CRTSCTS);
00287         switch (flowcontrol) {
00288         case 2:
00289                 term.c_cflag |= IXON | IXOFF;
00290                 break;
00291         case 1:
00292                 term.c_cflag |= CRTSCTS;
00293         default:
00294                 return SR_ERR;
00295         }
00296 
00297         term.c_iflag &= ~IGNPAR;
00298         term.c_cflag &= ~(PARODD | PARENB);
00299         switch (parity) {
00300         case 0:
00301                 term.c_iflag |= IGNPAR;
00302                 break;
00303         case 1:
00304                 term.c_cflag |= PARENB;
00305                 break;
00306         case 2:
00307                 term.c_cflag |= PARENB | PARODD;
00308                 break;
00309         default:
00310                 return SR_ERR;
00311         }
00312 
00313         if (tcsetattr(fd, TCSADRAIN, &term) < 0)
00314                 return SR_ERR;
00315 #endif
00316 
00317         return SR_OK;
00318 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines