summaryrefslogtreecommitdiff
Side-by-side diff
Diffstat (more/less context) (show whitespace changes)
-rw-r--r--noncore/net/opietooth/manager/manager.pro4
-rw-r--r--noncore/net/opietooth/manager/rfcommhelper.cpp181
-rw-r--r--noncore/net/opietooth/manager/rfcommhelper.h69
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
@@ -8,6 +8,7 @@ HEADERS = btconnectionitem.h btdeviceitem.h \
hciconfwrapper.h bticonloader.h \
pppdialog.h obexdialog.h \
devicehandler.h rfcpopup.h obexpopup.h \
+ rfcommhelper.h
SOURCES = btconnectionitem.cpp btdeviceitem.cpp \
btserviceitem.cpp stdpopups.cpp \
@@ -16,7 +17,8 @@ SOURCES = btconnectionitem.cpp btdeviceitem.cpp \
btlistitem.cpp hciconfwrapper.cpp \
bticonloader.cpp pppdialog.cpp \
obexdialog.cpp devicehandler.cpp \
- rfcpopup.cpp obexpopup.cpp
+ rfcpopup.cpp obexpopup.cpp \
+ rfcommhelper.cpp
INCLUDEPATH += $(OPIEDIR)/include
INCLUDEPATH += $(OPIEDIR)/noncore/net/opietooth/lib
DEPENDPATH += $(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