-rw-r--r-- | noncore/apps/opie-console/.cvsignore | 3 | ||||
-rw-r--r-- | noncore/apps/opie-console/io_layer.h | 26 | ||||
-rw-r--r-- | noncore/apps/opie-console/io_serial.cpp | 155 | ||||
-rw-r--r-- | noncore/apps/opie-console/io_serial.h | 51 |
4 files changed, 218 insertions, 17 deletions
diff --git a/noncore/apps/opie-console/.cvsignore b/noncore/apps/opie-console/.cvsignore new file mode 100644 index 0000000..acc07da --- a/dev/null +++ b/noncore/apps/opie-console/.cvsignore @@ -0,0 +1,3 @@ +moc*.cpp +Makefile +Makefile.in diff --git a/noncore/apps/opie-console/io_layer.h b/noncore/apps/opie-console/io_layer.h index c8f41d7..537c851 100644 --- a/noncore/apps/opie-console/io_layer.h +++ b/noncore/apps/opie-console/io_layer.h @@ -4,3 +4,3 @@ #include <qobject.h> - +#include <qpe/config.h> @@ -31,3 +31,4 @@ public: * create an IOLayer instance from a config file - * can be used by session managemnt/profiles + * the currently set group stores the profile/session + * information */ @@ -39,2 +40,12 @@ public: virtual ~IOLayer(); + + /** + * a small internal identifier + */ + virtual QString identifier() const = 0; + + /** + * a short name + */ + virtual QString name() const = 0; signals: @@ -72,13 +83,2 @@ public slots: virtual void reload( const Config& ) = 0; - - /** - * a small internal identifier - */ - virtual QString identifier()const = 0; - - /** - * a short name - */ - virtual QString name()const = 0; - }; diff --git a/noncore/apps/opie-console/io_serial.cpp b/noncore/apps/opie-console/io_serial.cpp index 42c86b5..9a81de9 100644 --- a/noncore/apps/opie-console/io_serial.cpp +++ b/noncore/apps/opie-console/io_serial.cpp @@ -1 +1,5 @@ +#include <fcntl.h> +#include <termios.h> +#include <errno.h> +#include <unistd.h> #include "io_serial.h" @@ -3,2 +7,4 @@ IOSerial::IOSerial(const Config &config) : IOLayer(config) { + m_fd = 0; + reload(config); } @@ -6,7 +12,152 @@ IOSerial::IOSerial(const Config &config) : IOLayer(config) { -void IOSerial::error(int number, const QString &error) { +IOSerial::~IOSerial() { + if (m_fd) { + close(); + } +} + +void IOSerial::send(const QByteArray &data) { + if (m_fd) { + write(m_fd, data.data(), data.size()); + } else { + emit error(Refuse, tr("Not connected")); + } +} + +void IOSerial::close() { + if (m_fd) { + delete m_read; + delete m_error; + ::close(m_fd); + m_fd = 0; + } else { + emit error(Refuse, tr("Not connected")); + } } -void IOSerial::received(const QByteArray &array) { +bool IOSerial::open() { + if (!m_fd) { + struct termios tty; + m_fd = ::open(m_device, O_RDWR | O_NOCTTY | O_NONBLOCK); + if (m_fd < 0) { + emit error(CouldNotOpen, strerror(errno)); + return FALSE; } + tcgetattr(m_fd, &tty); + + /* Baud rate */ + int speed = getBaud(m_baud); + if (speed == -1) { + emit error(Refuse, tr("Invalid baud rate")); + } + cfsetospeed(&tty, speed); + cfsetispeed(&tty, speed); + + /* Take care of Space / Mark parity */ + if (m_dbits == 7 && (m_parity == ParitySpace || m_parity == ParityMark)) { + m_dbits = 8; + } + + /* Data bits */ + switch (m_dbits) { + case 5: tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS5; break; + case 6: tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS6; break; + case 7: tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS7; break; + case 8: tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8; break; + } + + /* Raw, no echo mode */ + tty.c_iflag = IGNBRK; + tty.c_lflag = 0; + tty.c_oflag = 0; + tty.c_cflag |= CLOCAL | CREAD; + + /* Stop bits */ + if (m_sbits == 2) { + tty.c_cflag |= CSTOPB; + } else { + tty.c_cflag &= ~CSTOPB; + } + + tty.c_cc[VMIN] = 1; + tty.c_cc[VTIME] = 5; + + /* Flow control */ + if (m_flow & FlowSW) + tty.c_iflag |= IXON | IXOFF; + else + tty.c_iflag &= ~(IXON|IXOFF|IXANY); + + if (m_flow & FlowHW) + tty.c_cflag |= CRTSCTS; + else + tty.c_cflag &= ~CRTSCTS; + /* Parity */ + tty.c_cflag &= ~(PARENB | PARODD); + if (m_parity & ParityEven) + tty.c_cflag |= PARENB; + else if (m_parity & ParityOdd) + tty.c_cflag |= (PARENB | PARODD); + + /* Set the changes */ + tcsetattr(m_fd, TCSANOW, &tty); + + /* Notifications on read & errors */ + m_read = new QSocketNotifier(m_fd, QSocketNotifier::Read, this); + m_error = new QSocketNotifier(m_fd, QSocketNotifier::Exception, this); + connect(m_read, SIGNAL(activated(int)), this, SLOT(dataArrived())); + connect(m_error, SIGNAL(activated(int)), this, SLOT(errorOccured())); + return TRUE; + } else { + emit error(Refuse, tr("Device is already connected")); + return FALSE; + } +} + +void IOSerial::reload(const Config &config) { + m_device = config.readEntry("Device", SERIAL_DEFAULT_DEVICE); + m_baud = config.readNumEntry("Baud", SERIAL_DEFAULT_BAUD); +} + +int IOSerial::getBaud(int baud) const { + switch (baud) { + case 300: return B300; break; + case 600: return B600; break; + case 1200: return B1200; break; + case 2400: return B2400; break; + case 4800: return B4800; break; + case 9600: return B9600; break; + case 19200: return B19200; break; + case 38400: return B38400; break; + case 57600: return B57600; break; + case 115200: return B115200; break; + } + return -1; +} + +void IOSerial::errorOccured() { + emit error(ClosedUnexpected, strerror(errno)); + close(); +} + +void IOSerial::dataArrived() { + QByteArray array; + char buf[4096]; + + int len = read(m_fd, buf, 4096); + if (len == 0) + close(); + if (len < 0) + return; + array.setRawData(buf, len); + emit received(array); +} + +QString IOSerial::identifier() const { + return "serial"; +} + +QString IOSerial::name() const { + return "RS232 Serial IO Layer"; +} diff --git a/noncore/apps/opie-console/io_serial.h b/noncore/apps/opie-console/io_serial.h index c6a2efd..1d34411 100644 --- a/noncore/apps/opie-console/io_serial.h +++ b/noncore/apps/opie-console/io_serial.h @@ -3,4 +3,15 @@ +#include <qsocketnotifier.h> #include "io_layer.h" +/* Default values to be used if the profile information is incomplete */ +#define SERIAL_DEFAULT_DEVICE "/dev/ttyS0" +#define SERIAL_DEFAULT_BAUD 9600 +#define SERIAL_DEFAULT_PARITY 0 +#define SERIAL_DEFAULT_DBITS 8 +#define SERIAL_DEFAULT_SBITS 1 +#define SERIAL_DEFAULT_FLOW 0 + +/* IOSerial implements a RS232 IO Layer */ + class IOSerial : public IOLayer { @@ -8,9 +19,45 @@ class IOSerial : public IOLayer { public: + enum Parity { + ParityNone = 0, + ParityEven, + ParityOdd, + ParitySpace, + ParityMark + }; + + enum Flow { + FlowHW = 0x01, + FlowSW = 0x02 + }; + IOSerial(const Config &); -public slots: + ~IOSerial(); + + QString identifier() const; + QString name() const; +signals: void received(const QByteArray &); void error(int, const QString &); +public slots: + void send(const QByteArray &); + bool open(); + void close(); + void reload(const Config &); +protected: + int getBaud(int baud) const; +protected slots: + void dataArrived(); + void errorOccured(); +protected: + QSocketNotifier *m_read; + QSocketNotifier *m_error; + QString m_device; + int m_baud; + int m_parity; + int m_dbits; + int m_sbits; + int m_flow; + int m_fd; }; - #endif /* OPIE_IO_SERIAL */ |