Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

io_serial.cpp

Go to the documentation of this file.
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         /* Baud rate */
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         /* Take care of Space / Mark parity */
00066         if (m_dbits == 7 && (m_parity == ParitySpace || m_parity == ParityMark)) {
00067             m_dbits = 8;
00068         }
00069 
00070         /* Data bits */
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         /* Raw, no echo mode */
00080         tty.c_iflag =  IGNBRK;
00081         tty.c_lflag = 0;
00082         tty.c_oflag = 0;
00083         tty.c_cflag |= CLOCAL | CREAD;
00084 
00085         /* Stop bits */
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         /* Flow control */
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         /* Parity */
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         /* Set the changes */
00114         tcsetattr(m_fd, TCSANOW, &tty);
00115 
00116         /* Notifications on read & errors */
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  * this is used to give the
00213  * class below IOSerial
00214  * the possibility of
00215  * exclusive usage
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  * give power back
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 }

Generated on Sat Nov 5 16:16:50 2005 for OPIE by  doxygen 1.4.2