llserial.cpp
1 /* 2 EIBD eib bus access and management daemon 3 Copyright (C) 2005-2011 Martin Koegler <mkoegler@auto.tuwien.ac.at> 4 5 This program is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation; either version 2 of the License, or 8 (at your option) any later version. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program; if not, write to the Free Software 17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 18 */ 19 20 #include "llserial.h" 21 #include "config.h" 22 23 #include <cerrno> 24 #include <fcntl.h> 25 #include <sys/ioctl.h> 26 #include <termios.h> 27 #include <unistd.h> 28 #ifdef HAVE_LINUX_LOWLATENCY 29 #include <cstring> // memcpy 30 #include <sys/ioctl.h> 31 #endif 32 33 34 static speed_t getbaud(int baud) 35 { 36 switch(baud) 37 { 38 case 9600: 39 return B9600; 40 case 19200: 41 return B19200; 42 case 38400: 43 return B38400; 44 case 115200: 45 return B115200; 46 default: 47 return 0; 48 } 49 } 50 51 bool 52 LLserial::setup() 53 { 54 if(!FDdriver::setup()) 55 return false; 56 57 dev = cfg->value("device",""); 58 if(dev.size() == 0) 59 { 60 ERRORPRINTF (t, E_ERROR | 22, "Missing device= config"); 61 return false; 62 } 63 baudrate = cfg->value("baudrate", (int)default_baudrate()); 64 if (getbaud(baudrate) == 0) 65 { 66 ERRORPRINTF (t, E_ERROR | 66, "Wrong baudrate= config"); 67 return false; 68 } 69 low_latency = cfg->value("low-latency",false); 70 71 return true; 72 } 73 74 void 75 LLserial::start() 76 { 77 struct termios t1; 78 int term_baudrate; 79 80 fd = open (dev.c_str(), O_RDWR | O_NOCTTY | O_NDELAY | O_SYNC); 81 if (fd == -1) 82 { 83 ERRORPRINTF (t, E_ERROR | 67, "Opening %s failed: %s", dev, strerror(errno)); 84 goto ex1; 85 } 86 87 if (!set_low_latency (fd, &sold, low_latency)) 88 { 89 ERRORPRINTF (t, E_ERROR | 68, "low_latency %s failed: %s", dev, strerror(errno)); 90 goto ex2; 91 } 92 93 close (fd); 94 95 fd = open (dev.c_str(), O_RDWR | O_NOCTTY | O_SYNC); 96 if (fd == -1) 97 { 98 ERRORPRINTF (t, E_ERROR | 69, "Opening %s failed: %s", dev, strerror(errno)); 99 goto ex1; 100 } 101 102 if (tcgetattr (fd, &old)) 103 { 104 ERRORPRINTF (t, E_ERROR | 24, "tcgetattr %s failed: %s", dev, strerror(errno)); 105 goto ex3; 106 } 107 108 if (tcgetattr (fd, &t1)) 109 { 110 ERRORPRINTF (t, E_ERROR | 70, "tcgetattr %s failed: %s", dev, strerror(errno)); 111 goto ex3; 112 } 113 114 termios_settings(t1); 115 term_baudrate = getbaud(baudrate); 116 if (term_baudrate == -1) 117 { 118 ERRORPRINTF (t, E_ERROR | 71, "baudrate %d not recognized", baudrate); 119 goto ex3; 120 } 121 TRACEPRINTF(t, 0, "Opened %s with baud %d", dev, baudrate); 122 cfsetospeed (&t1, term_baudrate); 123 cfsetispeed (&t1, 0); 124 125 if (tcsetattr (fd, TCSAFLUSH, &t1)) 126 { 127 ERRORPRINTF (t, E_ERROR | 26, "tcsetattr %s failed: %s", dev, strerror(errno)); 128 goto ex3; 129 } 130 131 TRACEPRINTF (t, 2, "Opened"); 132 FDdriver::start(); 133 return; 134 135 ex3: 136 restore_low_latency (fd, &sold, low_latency); 137 ex2: 138 close (fd); 139 fd = -1; 140 ex1: 141 stopped(true); 142 } 143 144 void 145 LLserial::stop(bool err) 146 { 147 if (fd >= 0) 148 restore_low_latency (fd, &sold, low_latency); 149 FDdriver::stop(err); 150 } 151 152 int 153 LLserial::enable_input_parity_check() 154 { 155 struct termios t1; 156 157 TRACEPRINTF (t, 8, "Enabling input parity check on fd %d\n", fd); 158 159 if (tcgetattr (fd, &t1)) 160 { 161 ERRORPRINTF (t, E_ERROR | 70, "tcgetattr failed: %s", strerror(errno)); 162 return -1; 163 } 164 165 t1.c_iflag = t1.c_iflag | INPCK; 166 167 if (tcsetattr (fd, TCSANOW, &t1)) 168 { 169 ERRORPRINTF (t, E_ERROR | 70, "tcsetattr failed: %s", strerror(errno)); 170 return -2; 171 } 172 173 return 0; 174 }