-rw-r--r-- | noncore/apps/opie-console/filetransfer.cpp | 142 | ||||
-rw-r--r-- | noncore/apps/opie-console/filetransfer.h | 38 | ||||
-rw-r--r-- | noncore/apps/opie-console/io_layer.cpp | 3 | ||||
-rw-r--r-- | noncore/apps/opie-console/io_layer.h | 7 | ||||
-rw-r--r-- | noncore/apps/opie-console/io_serial.cpp | 7 | ||||
-rw-r--r-- | noncore/apps/opie-console/io_serial.h | 1 | ||||
-rw-r--r-- | noncore/apps/opie-console/sz_transfer.cpp | 121 |
7 files changed, 212 insertions, 107 deletions
diff --git a/noncore/apps/opie-console/filetransfer.cpp b/noncore/apps/opie-console/filetransfer.cpp new file mode 100644 index 0000000..78982bd --- a/dev/null +++ b/noncore/apps/opie-console/filetransfer.cpp @@ -0,0 +1,142 @@ +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <fcntl.h> +#include <unistd.h> + +#include <qcstring.h> +#include <qsocketnotifier.h> + +#include <opie/oprocess.h> + +#include "filetransfer.h" + +bool FileTransfer::terminate = false; +pid_t FileTransfer::m_pid; + +FileTransfer::FileTransfer( Type t, IOLayer* lay ) + : FileTransferLayer( lay ), m_type( t ) { + signal( SIGCHLD, signal_handler ); +} +FileTransfer::~FileTransfer() { +} + +/** + * now we will send the file. + * + * we request an fd. The IOLayer should be closed + * then we will setup a pipe for progress communication + * then we will dup2 the m_fd in the forked process + * to do direct IO from and to the fd + */ +void FileTransfer::sendFile( const QString& file ) { + m_fd = layer()->rawIO(); +// +// m_fd = ::open("/dev/ttyS0", O_RDWR); + + + if ( pipe( m_comm ) < 0 ) + m_comm[0] = m_comm[1] = 0; + if ( pipe( m_info ) < 0 ) + m_info[0] = m_info[1] = 0; + + qWarning("output:"+file ); + m_pid = fork(); + switch( m_pid ) { + case 0:{ + setupChild(); + /* exec */ + char* verbose = "-vv"; + char* binray = "-b"; + + + /* we should never return from here */ + execlp("sz", "sz", verbose, binray, file.latin1(), NULL ); + + /* communication for error!*/ + char resultByte =1; + if (m_info[1] ) + write(m_info[1], &resultByte, 1 ); + _exit( -1 ); + break; + } + default:{ + if ( m_info[1] ) + close( m_info[1] ); + if ( m_info[0] ) for (;;) { + char resultByte; int len; + len = read(m_info[0], &resultByte, 1 ); + /* len == 1 start up failed */ + if ( len == 1 ) + return; + if ( len == -1 ) + if ( (errno == ECHILD ) || (errno == EINTR ) ) + continue; + + // len == 0 or something like this + break; + } + if ( m_info[0] ) + close( m_info[0] ); + + terminate = false; + fd_set fds; + struct timeval timeout; + int sel; + + /* replace by QSocketNotifier!!! */ + while (!terminate) { + FD_ZERO( &fds ); + FD_SET( m_comm[0], &fds ); + sel = select( m_comm[0]+1, &fds, NULL, NULL, &timeout ); + if (sel ) { + if ( FD_ISSET(m_comm[0], &fds ) ) { + printf("out:"); + QByteArray ar(4096); + int len = read(m_comm[0], ar.data(), 4096 ); + for (int i = 0; i < len; i++ ) { + // printf("%c", ar[i] ); + } + printf("\n"); + } + } + } + break; + } + } +} +void FileTransfer::sendFile( const QFile& file ) { + sendFile( file.name() ); +} +void FileTransfer::signal_handler(int ) { + int status; + signal( SIGCHLD, signal_handler ); + waitpid( m_pid, &status, WNOHANG ); + terminate = true; +} +void FileTransfer::setupChild() { + /* + * we do not want to read from our + * information channel + */ + if (m_info[0] ) + close(m_info[0] ); + /* + * FD_CLOEXEC will close the + * fd on successfull exec + */ + if (m_info[1] ) + fcntl(m_info[1], F_SETFD, FD_CLOEXEC ); + + if (m_comm[0] ) + close( m_comm[0] ); + /* + * now set the communication + * m_fd STDIN_FILENO + * STDOUT_FILENO + * STDERR_FILENO + */ + dup2( m_fd, STDIN_FILENO ); + dup2( m_fd, STDOUT_FILENO ); + dup2( m_comm[1], STDERR_FILENO ); +} diff --git a/noncore/apps/opie-console/filetransfer.h b/noncore/apps/opie-console/filetransfer.h new file mode 100644 index 0000000..06c6d12 --- a/dev/null +++ b/noncore/apps/opie-console/filetransfer.h @@ -0,0 +1,38 @@ +#ifndef OPIE_FILE_TRANSFER_H +#define OPIE_FILE_TRANSFER_H + +#include <sys/types.h> + +#include <qfile.h> + +#include "file_layer.h" + +class QSocketNotifier; +class OProcess; +class FileTransfer : public FileTransferLayer{ + Q_OBJECT +public: + enum Type { + SZ = 0, + SX, + SY + }; + FileTransfer( Type t, IOLayer* ); + ~FileTransfer(); + + void sendFile( const QString& file ); + void sendFile( const QFile& ); + +private slots: + void setupChild(); +private: + static pid_t m_pid; + int m_fd; + int m_info[2]; + int m_comm[2]; + Type m_type; + static void signal_handler(int); + static bool terminate; +}; + +#endif diff --git a/noncore/apps/opie-console/io_layer.cpp b/noncore/apps/opie-console/io_layer.cpp index 563a252..79d47f5 100644 --- a/noncore/apps/opie-console/io_layer.cpp +++ b/noncore/apps/opie-console/io_layer.cpp @@ -1,14 +1,17 @@ #include "io_layer.h" IOLayer::IOLayer() : QObject() { } IOLayer::IOLayer(const Profile &) : QObject() { } IOLayer::~IOLayer() { } +int IOLayer::rawIO()const{ + return -1; +} diff --git a/noncore/apps/opie-console/io_layer.h b/noncore/apps/opie-console/io_layer.h index b891b2b..7745021 100644 --- a/noncore/apps/opie-console/io_layer.h +++ b/noncore/apps/opie-console/io_layer.h @@ -1,87 +1,94 @@ #ifndef OPIE_IO_LAYER_H #define OPIE_IO_LAYER_H #include <qobject.h> #include <qpe/config.h> #include "profile.h" /** * This is the base class for IO Layers * It will used to sent and recv data( QByteArray ) * it */ class IOLayer : public QObject { Q_OBJECT public: enum Error { NoError = -1, Refuse = 0, CouldNotOpen =1, ClosedUnexpected =2, ClosedError =3, Terminate = 4 /* add more errors here */ }; /** * a small c'tor */ IOLayer(); /** * create an IOLayer instance from a config file * the currently set group stores the profile/session * information */ IOLayer( const Profile& ); /** * destructor */ virtual ~IOLayer(); /** * a small internal identifier */ virtual QString identifier() const = 0; /** * a short name */ virtual QString name() const = 0; + + /** + * a file descriptor which opens + * the device for io but does not + * do any ioctling on it... + */ + virtual int rawIO()const; signals: /** * received input as QCString */ virtual void received( const QByteArray& ) = 0; /** * an error occured * int for the error number * and QString for a text */ virtual void error( int, const QString& ) = 0; public slots: /** * send a QCString to the device */ virtual void send( const QByteArray& ) = 0; /** * bool open */ virtual bool open() = 0; /** * close the io */ virtual void close() = 0; /** * closes and reloads the settings */ virtual void reload( const Profile& ) = 0; }; #endif diff --git a/noncore/apps/opie-console/io_serial.cpp b/noncore/apps/opie-console/io_serial.cpp index 929aeff..845f4be 100644 --- a/noncore/apps/opie-console/io_serial.cpp +++ b/noncore/apps/opie-console/io_serial.cpp @@ -1,177 +1,182 @@ #include <fcntl.h> #include <termios.h> #include <errno.h> #include <unistd.h> #include "io_serial.h" IOSerial::IOSerial(const Profile &config) : IOLayer(config) { m_read = 0l; m_error = 0l; m_fd = 0; reload(config); } 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")); } } bool IOSerial::open() { qWarning("open"); if (!m_fd) { qWarning("going to open %s", m_device.latin1()); struct termios tty; m_fd = ::open(m_device, O_RDWR | O_NOCTTY | O_NONBLOCK); if (m_fd < 0) { qWarning(" fd < 0 "); emit error(CouldNotOpen, strerror(errno)); return FALSE; } tcgetattr(m_fd, &tty); /* Baud rate */ int speed = baud(m_baud); if (speed == -1) { qWarning("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; default: 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 { qWarning("opened"); emit error(Refuse, tr("Device is already connected")); m_fd = 0; return FALSE; } } void IOSerial::reload(const Profile &config) { m_device = config.readEntry("Device", SERIAL_DEFAULT_DEVICE); qWarning( "Dev" +m_device ); qWarning( "Conf:" +config.readEntry("Device") ); m_baud = config.readNumEntry("Baud", SERIAL_DEFAULT_BAUD); m_parity = config.readNumEntry("Parity", SERIAL_DEFAULT_PARITY); m_dbits = config.readNumEntry("DataBits", SERIAL_DEFAULT_DBITS); m_sbits = config.readNumEntry("StopBits", SERIAL_DEFAULT_SBITS); m_flow = config.readNumEntry("Flow", SERIAL_DEFAULT_FLOW); } int IOSerial::baud(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(4096); + QByteArray array(4097); int len = read(m_fd, array.data(), 4096); if (len == 0) close(); if (len < 0) return; array.resize( len ); emit received(array); } QString IOSerial::identifier() const { return "serial"; } QString IOSerial::name() const { return "RS232 Serial IO Layer"; } +int IOSerial::rawIO()const { + int fd = ::open(m_device, O_RDWR ); + + return fd; +}; diff --git a/noncore/apps/opie-console/io_serial.h b/noncore/apps/opie-console/io_serial.h index 521dac6..00a6d2c 100644 --- a/noncore/apps/opie-console/io_serial.h +++ b/noncore/apps/opie-console/io_serial.h @@ -1,63 +1,64 @@ #ifndef OPIE_IO_SERIAL #define OPIE_IO_SERIAL #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 { Q_OBJECT public: enum Parity { ParityNone = 0, ParityEven, ParityOdd, ParitySpace, ParityMark }; enum Flow { FlowHW = 0x01, FlowSW = 0x02 }; IOSerial(const Profile &); ~IOSerial(); QString identifier() const; QString name() const; + int rawIO()const; signals: void received(const QByteArray &); void error(int, const QString &); public slots: void send(const QByteArray &); bool open(); void close(); void reload(const Profile &); protected: int baud(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 */ diff --git a/noncore/apps/opie-console/sz_transfer.cpp b/noncore/apps/opie-console/sz_transfer.cpp index 41917c0..0a315cf 100644 --- a/noncore/apps/opie-console/sz_transfer.cpp +++ b/noncore/apps/opie-console/sz_transfer.cpp @@ -1,176 +1,85 @@ #include "sz_transfer.h" #include <qfile.h> #include <opie/oprocess.h> #include <stdio.h> #include <sys/termios.h> -/* following function ripped out of minicom's sysdep2.c */ - - -/* - * Set cbreak mode. - * Mode 0 = normal. - * Mode 1 = cbreak, no echo - * Mode 2 = raw, no echo. - * Mode 3 = only return erasechar (for wkeys.c) - * - * Returns: the current erase character. - */ - -static struct termios savetty; -int setcbreak(int mode) -{ -#if 1 - struct termios tty; - static int init = 0; - static int erasechar; - - - if (init == 0) { - tcgetattr(0, &savetty); - erasechar = savetty.c_cc[VERASE]; - init++; - } - - if (mode == 3) return(erasechar); - - - - /* Always return to default settings first */ - tcsetattr(0, TCSADRAIN, &savetty); - - if (mode == 0) { - return(erasechar); - } - - tcgetattr(0, &tty); - if (mode == 1) { - tty.c_oflag &= ~OPOST; - tty.c_lflag &= ~(XCASE|ECHONL|NOFLSH); - tty.c_lflag &= ~(ICANON | ISIG | ECHO); - tty.c_iflag &= ~(ICRNL|INLCR); - tty.c_cflag |= CREAD; - tty.c_cc[VTIME] = 5; - tty.c_cc[VMIN] = 1; - } - if (mode == 2) { /* raw */ - tty.c_iflag &= ~(IGNBRK | IGNCR | INLCR | ICRNL | IUCLC | - IXANY | IXON | IXOFF | INPCK | ISTRIP); - tty.c_iflag |= (BRKINT | IGNPAR); - tty.c_oflag &= ~OPOST; - tty.c_lflag &= ~(XCASE|ECHONL|NOFLSH); - tty.c_lflag &= ~(ICANON | ISIG | ECHO); - tty.c_cflag |= CREAD; - tty.c_cc[VTIME] = 5; - tty.c_cc[VMIN] = 1; - } - tcsetattr(0, TCSADRAIN, &tty); - return(erasechar); -#else - struct sgttyb args; - static int init = 0; - static int erasechar; - - if (init == 0) { - (void) ioctl(0, TIOCGETP, &savetty); - (void) ioctl(0, TIOCGETC, &savetty2); - erasechar = savetty.sg_erase; - init++; - } - - if (mode == 3) return(erasechar); - - if (mode == 0) { - (void) ioctl(0, TIOCSETP, &savetty); - (void) ioctl(0, TIOCSETC, &savetty2); - return(erasechar); - } - - (void) ioctl(0, TIOCGETP, &args); - if (mode == 1) { - args.sg_flags |= CBREAK; - args.sg_flags &= ~(ECHO|RAW); - } - if (mode == 2) { - args.sg_flags |= RAW; - args.sg_flags &= ~(ECHO|CBREAK); - } - (void) ioctl(0, TIOCSETP, &args); - return(erasechar); -#endif - -} SzTransfer::SzTransfer(Type t, IOLayer *layer) : FileTransferLayer(layer), m_t(t) { } SzTransfer::~SzTransfer() { } void SzTransfer::sendFile(const QFile& file) { sendFile(file.name()); } void SzTransfer::sendFile(const QString& file) { //setcbreak(2); /* raw no echo */ proc = new OProcess; *proc << "sz"; - *proc << "-v" << "-v" << "-v" << "-b" << file; - connect(proc, SIGNAL(processExited(OProcess *)), + *proc << "-v" << "-v" << "-b" << file; + connect(proc, SIGNAL(processExited(OProcess *)), this, SLOT(sent())); - connect(proc, SIGNAL(receivedStdout(OProcess *, char *, int)), + connect(proc, SIGNAL(receivedStdout(OProcess *, char *, int)), this, SLOT(SzReceivedStdout(OProcess *, char *, int))); connect(proc, SIGNAL(receivedStderr(OProcess *, char *, int)), this, SLOT(SzReceivedStderr(OProcess *, char *, int))); connect(layer(), SIGNAL(received(const QByteArray &)), this, SLOT(receivedStdin(const QByteArray &))); proc->start(OProcess::NotifyOnExit, OProcess::All); } void SzTransfer::SzReceivedStdout(OProcess *, char *buffer, int buflen) { - //qWarning("recieved from sz %d bytes", buflen); + qWarning("recieved from sz on stdout %d bytes", buflen); QByteArray data(buflen); data.fill(*buffer, buflen); + for (uint i = 0; i < data.count(); i++ ) { + printf("%c", buffer[i] ); + } + printf("\n"); // send out through the io layer - (layer())->send(data); + layer()->send(data); } void SzTransfer::SzReceivedStderr(OProcess *, char *buffer, int length) { // parse and show data in a progress dialog/widget - printf("\n"); - for (int i = 0; i < length; i++) - printf("%c", buffer[i]); + printf("stderr:\n"); + //for (int i = 0; i < length; i++) + // printf("%c", buffer[i]); + //printf("\n"); } void SzTransfer::receivedStdin(const QByteArray &data) { - //qWarning("recieved from io_serial %d bytes", data.size()); - + qWarning("recieved from io_serial %d bytes", data.size()); + // recieved data from the io layer goes to sz proc->writeStdin(data.data(), data.size()); } void SzTransfer::sent() { qWarning("sent file"); //setcbreak(0); /* default */ delete proc; disconnect(layer(), SIGNAL(received(const QByteArray &)), this, SLOT(receivedStdin(const QByteArray &))); } |