00001
00002 #include <fcntl.h>
00003 #include <termios.h>
00004 #include <errno.h>
00005 #include <unistd.h>
00006 #include <stdio.h>
00007
00008 #include "io_serial.h"
00009
00010 IOSerial::IOSerial(const Profile &config) : IOLayer(config) {
00011 m_read = 0l;
00012 m_error = 0l;
00013 m_fd = 0;
00014 m_connected = false;
00015 reload(config);
00016 }
00017
00018
00019 IOSerial::~IOSerial() {
00020 if (m_fd) {
00021 close();
00022 }
00023 }
00024
00025 void IOSerial::send(const QByteArray &data) {
00026 if (m_fd) {
00027 write(m_fd, data.data(), data.size());
00028 } else {
00029 emit error(Refuse, tr("Not connected"));
00030 }
00031 }
00032
00033 void IOSerial::close() {
00034 if (m_fd) {
00035 delete m_read;
00036 delete m_error;
00037 ::close(m_fd);
00038 m_fd = 0;
00039 m_connected = false;
00040 } else {
00041 m_connected = false;
00042 emit error(Refuse, tr("Not connected"));
00043 }
00044 }
00045
00046 bool IOSerial::open() {
00047 if (!m_fd) {
00048 struct termios tty;
00049 m_fd = ::open(m_device, O_RDWR | O_NOCTTY | O_NONBLOCK);
00050 if (m_fd < 0) {
00051 emit error(CouldNotOpen, strerror(errno));
00052 m_fd = 0;
00053 return FALSE;
00054 }
00055 tcgetattr(m_fd, &tty);
00056
00057
00058 int speed = baud(m_baud);
00059 if (speed == -1) {
00060 emit error(Refuse, tr("Invalid baud rate"));
00061 }
00062 cfsetospeed(&tty, speed);
00063 cfsetispeed(&tty, speed);
00064
00065
00066 if (m_dbits == 7 && (m_parity == ParitySpace || m_parity == ParityMark)) {
00067 m_dbits = 8;
00068 }
00069
00070
00071 switch (m_dbits) {
00072 case 5: tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS5; break;
00073 case 6: tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS6; break;
00074 case 7: tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS7; break;
00075 case 8: tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8; break;
00076 default: break;
00077 }
00078
00079
00080 tty.c_iflag = IGNBRK;
00081 tty.c_lflag = 0;
00082 tty.c_oflag = 0;
00083 tty.c_cflag |= CLOCAL | CREAD;
00084
00085
00086 if (m_sbits == 2) {
00087 tty.c_cflag |= CSTOPB;
00088 } else {
00089 tty.c_cflag &= ~CSTOPB;
00090 }
00091
00092 tty.c_cc[VMIN] = 1;
00093 tty.c_cc[VTIME] = 5;
00094
00095
00096 if (m_flow & FlowSW)
00097 tty.c_iflag |= IXON | IXOFF;
00098 else
00099 tty.c_iflag &= ~(IXON|IXOFF|IXANY);
00100
00101 if (m_flow & FlowHW)
00102 tty.c_cflag |= CRTSCTS;
00103 else
00104 tty.c_cflag &= ~CRTSCTS;
00105
00106
00107 tty.c_cflag &= ~(PARENB | PARODD);
00108 if (m_parity & ParityEven)
00109 tty.c_cflag |= PARENB;
00110 else if (m_parity & ParityOdd)
00111 tty.c_cflag |= (PARENB | PARODD);
00112
00113
00114 tcsetattr(m_fd, TCSANOW, &tty);
00115
00116
00117 m_read = new QSocketNotifier(m_fd, QSocketNotifier::Read, this);
00118 m_error = new QSocketNotifier(m_fd, QSocketNotifier::Exception, this);
00119 connect(m_read, SIGNAL(activated(int)), this, SLOT(dataArrived()));
00120 connect(m_error, SIGNAL(activated(int)), this, SLOT(errorOccured()));
00121 m_connected = false;
00122 return TRUE;
00123 } else {
00124 emit error(Refuse, tr("Device is already connected"));
00125 m_fd = 0;
00126 return FALSE;
00127 }
00128 }
00129
00130 void IOSerial::reload(const Profile &config) {
00131 m_device = config.readEntry("Device", SERIAL_DEFAULT_DEVICE);
00132 m_baud = config.readNumEntry("Speed", SERIAL_DEFAULT_BAUD);
00133 m_parity = config.readNumEntry("Parity", SERIAL_DEFAULT_PARITY);
00134 m_dbits = config.readNumEntry("DataBits", SERIAL_DEFAULT_DBITS);
00135 m_sbits = config.readNumEntry("StopBits", SERIAL_DEFAULT_SBITS);
00136 m_flow = config.readNumEntry("Flow", SERIAL_DEFAULT_FLOW);
00137
00138 }
00139
00140 int IOSerial::baud(int baud) const {
00141 switch (baud) {
00142 case 300: return B300; break;
00143 case 600: return B600; break;
00144 case 1200: return B1200; break;
00145 case 2400: return B2400; break;
00146 case 4800: return B4800; break;
00147 case 9600: return B9600; break;
00148 case 19200: return B19200; break;
00149 case 38400: return B38400; break;
00150 case 57600: return B57600; break;
00151 case 115200: return B115200; break;
00152 }
00153 return -1;
00154 }
00155
00156 void IOSerial::errorOccured() {
00157 emit error(ClosedUnexpected, strerror(errno));
00158 close();
00159 }
00160
00161 void IOSerial::dataArrived() {
00162 QByteArray array(4097);
00163
00164 int len = read(m_fd, array.data(), 4096);
00165 if (len == 0)
00166 close();
00167 if (len < 0)
00168 return;
00169
00170 array.resize( len );
00171 emit received(array);
00172 }
00173
00174 QString IOSerial::identifier() const {
00175 return "serial";
00176 }
00177
00178 QString IOSerial::name() const {
00179 return "RS232 Serial IO Layer";
00180 }
00181 int IOSerial::rawIO()const {
00182 if (m_read )
00183 disconnect(m_read, SIGNAL(activated(int)), this, SLOT(dataArrived()));
00184 if (m_error )
00185 disconnect(m_error, SIGNAL(activated(int)), this, SLOT(errorOccured()));
00186
00187 int fd = ::open(m_device, O_RDWR );
00188
00189 return fd;
00190 };
00191 void IOSerial::closeRawIO(int fd) {
00192 if (m_read )
00193 connect(m_read, SIGNAL(activated(int)), this, SLOT(dataArrived()));
00194 if (m_error )
00195 connect(m_error, SIGNAL(activated(int)), this, SLOT(errorOccured()));
00196
00197 ::close( fd );
00198 }
00199 QBitArray IOSerial::supports()const {
00200 QBitArray ar(3);
00201 ar[0] = ar[2] = 0;
00202 ar[1] = 1;
00203
00204 return ar;
00205 }
00206
00207 bool IOSerial::isConnected() {
00208 return m_connected;
00209 }
00210
00211
00212
00213
00214
00215
00216
00217 void IOSerial::internDetach() {
00218 if (m_read )
00219 disconnect(m_read, SIGNAL(activated(int)), this, SLOT(dataArrived()));
00220 if (m_error )
00221 disconnect(m_error, SIGNAL(activated(int)), this, SLOT(errorOccured()));
00222 }
00223
00224
00225
00226 void IOSerial::internAttach() {
00227 if (m_read )
00228 connect(m_read, SIGNAL(activated(int)), this, SLOT(dataArrived()));
00229 if (m_error )
00230 connect(m_error, SIGNAL(activated(int)), this, SLOT(errorOccured()));
00231 }