-rw-r--r-- | noncore/net/opietooth/manager/manager.pro | 4 | ||||
-rw-r--r-- | noncore/net/opietooth/manager/rfcommhelper.cpp | 181 | ||||
-rw-r--r-- | noncore/net/opietooth/manager/rfcommhelper.h | 69 |
3 files changed, 253 insertions, 1 deletions
diff --git a/noncore/net/opietooth/manager/manager.pro b/noncore/net/opietooth/manager/manager.pro index 4684c67..d3c69e0 100644 --- a/noncore/net/opietooth/manager/manager.pro +++ b/noncore/net/opietooth/manager/manager.pro @@ -10,2 +10,3 @@ HEADERS = btconnectionitem.h btdeviceitem.h \ devicehandler.h rfcpopup.h obexpopup.h \ + rfcommhelper.h @@ -18,3 +19,4 @@ SOURCES = btconnectionitem.cpp btdeviceitem.cpp \ obexdialog.cpp devicehandler.cpp \ - rfcpopup.cpp obexpopup.cpp + rfcpopup.cpp obexpopup.cpp \ + rfcommhelper.cpp INCLUDEPATH += $(OPIEDIR)/include diff --git a/noncore/net/opietooth/manager/rfcommhelper.cpp b/noncore/net/opietooth/manager/rfcommhelper.cpp new file mode 100644 index 0000000..0769da2 --- a/dev/null +++ b/noncore/net/opietooth/manager/rfcommhelper.cpp @@ -0,0 +1,181 @@ +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> +#include <signal.h> + +#include <stdio.h> +#include <stdlib.h> + +#include <sys/types.h> +#include <sys/time.h> +#include <sys/wait.h> + + +#include "rfcommhelper.h" + +using namespace OpieTooth; + +bool RfCommHelper::terminate = false; +pid_t RfCommHelper::m_pid; + +RfCommHelper::RfCommHelper() + : m_connected( false ) +{ + signal( SIGCHLD, signal_handler ); +} +RfCommHelper::~RfCommHelper() { + detach(); +} +QCString RfCommHelper::attachedDevice() const { + return m_device; +} +void RfCommHelper::detach() { + if (m_connected ) + ::kill( m_pid, 9 ); + if ( m_in2out[0] ) + close(m_in2out[0] ); + if ( m_in2out[1] ) + close(m_in2out[1] ); + if ( m_out2in[0] ) + close(m_out2in[0] ); + if ( m_out2in[1] ) + close(m_out2in[1] ); +} +bool RfCommHelper::attach( const QString& bd_addr, int port ) { + int i =0; + bool ok = false; + while (!ok ) { + if (i == 4) break; + ok = connect( i, bd_addr, port ); + i++; + } + return ok; +} +/* + * not implemented yet + */ +void RfCommHelper::regroup() { + +} +bool RfCommHelper::connect(int devi, const QString& bdaddr, int port) { + m_connected = false; + if ( pipe(m_fd) < 0 ) + m_fd[0] = m_fd[1] = 0; + if ( pipe(m_in2out) < 0 ) + m_in2out[0] = m_in2out[1] = 0; + if ( pipe(m_out2in ) < 0 ) + m_out2in[0] = m_out2in[1] = 0; + + m_pid = fork(); + switch( m_pid ) { + case -1: + return false; + break; + /* + * This is the child code. + * We do some fd work + * and then we'll execlp + * to start it up + */ + case 0:{ // child code + setupComChild(); + char por[15]; + char dev[15]; + sprintf( por, "%d", port ); + sprintf( dev, "%d", devi ); + execlp( "rfcomm", "rfcomm", dev, bdaddr.latin1(), por, NULL ); + char resultByte = 1; + if ( m_fd[1] ) + write(m_fd[1], &resultByte, 1 ); + _exit( -1 ); + break; + } + /* + * The Parent. We'll first wait for fd[0] to fill + * up. + * Then we will wait for out2in[0] to fill up and then + * we will parse it. + * maybe the signal handler gets it's turn in this case we return + * false + * otheriwse we will parse the Output and either return true + * or false + */ + default: { + if ( m_fd[1] ) + close( m_fd[1] ); + if ( m_fd[0] ) for (;;) { + char resultByte; + int len; + len = read(m_fd[0], &resultByte, 1 ); + if ( len == 1 ) { // it failed to execute + return false; + } + if ( len == -1 ) + if ( (errno == ECHILD ) || (errno == EINTR ) ) + continue; // the other process is not yet ready? + + break; + } + if ( m_fd[0] ) + close( m_fd[0] ); + terminate = false; + fd_set fds; + struct timeval timeout; + int sel; + while (!terminate ) { + FD_ZERO( &fds ); + FD_SET( m_in2out[0], &fds ); + timeout.tv_sec = 5; + timeout.tv_usec = 0; + + sel = select( m_in2out[0]+1, &fds, NULL, NULL, &timeout ); + if ( sel ) + if (FD_ISSET(m_in2out[0], &fds ) ) { + char buf[2048]; + int len; + buf[0] = 0; + len = read( m_in2out[0], buf, sizeof(buf) ); + if ( len > 0 ) { + QCString string( buf ); + if (string.left(9) == "Connected" ) { + m_connected = true; + m_device = m_device.sprintf("/dev/tty%d", devi ); + break; // we got connected + }; + } + // now parese it + }else {// time out + // 5 seconds without input check terminate? + // + ; + } + } + break; + } + } + return !terminate; +} + + +void RfCommHelper::setupComChild() { + if ( m_fd[0] ) + close(m_fd[0]); + if ( m_fd[1] ) + fcntl( m_fd[1] , F_SETFD, FD_CLOEXEC); + + /* duplicating pipes and making them STDIN and STDOUT + * of the new process + * [0] is for reading + * [1] is for writing + */ + dup2( m_out2in[0], STDIN_FILENO ); + dup2( m_in2out[1], STDOUT_FILENO ); + + +}; +void RfCommHelper::signal_handler(int) { + int status; + terminate = true; + signal( SIGCHLD, signal_handler ); + waitpid( m_pid, &status, WNOHANG ); +} diff --git a/noncore/net/opietooth/manager/rfcommhelper.h b/noncore/net/opietooth/manager/rfcommhelper.h new file mode 100644 index 0000000..545998c --- a/dev/null +++ b/noncore/net/opietooth/manager/rfcommhelper.h @@ -0,0 +1,69 @@ + +#ifndef OPIETOOTH_RFCOMM_HELPER_H +#define OPIETOOTH_RFCOMM_HELPER_H + +#include <sys/types.h> + +#include <qcstring.h> +#include <qstring.h> + +namespace OpieTooth { + /** + * RfCommHelper helps to attach to a remote + * channel of a bt device. + * It uses the commandline tool rfcomm fo the job + * it tries to attach to afree node and either succeeds + * or fails. + * Later RfCommHelper can be used to detach the device + * from the remote device + */ + class RfCommHelper { + public: + /** + * c'tor + */ + RfCommHelper(); + + /** + * d'tor removes the device + */ + ~RfCommHelper(); // kills the process + + /** + * gives the device name of the attached device + */ + QCString attachedDevice() const; + + /** + * detach a device + * kills the rfcomm process + */ + void detach(); + + /** + * tries to connect to a remote device + * @param bd_addr the bluetooth address + * @param port The port of the remote device + */ + bool attach(const QString& bd_addr, int port ); + + /** + * If the original user of the bond exists + * it may regroup the rfcomm process + */ + void regroup(); + private: + bool connect( int dev, const QString& bdaddr, int port ); + static void signal_handler(int); + void setupComChild(); + bool m_connected:1; + static pid_t m_pid; + QCString m_device; + int m_fd[2]; + int m_in2out[2]; + int m_out2in[2]; + static bool terminate ; + }; +}; + +#endif |