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

rfcommhelper.cpp

Go to the documentation of this file.
00001 #include <unistd.h>
00002 #include <fcntl.h>
00003 #include <errno.h>
00004 #include <signal.h>
00005 
00006 #include <stdio.h>
00007 #include <stdlib.h>
00008 
00009 #include <sys/types.h>
00010 #include <sys/time.h>
00011 #include <sys/wait.h>
00012 
00013 
00014 #include "rfcommhelper.h"
00015 
00016 using namespace OpieTooth;
00017 
00018 bool RfCommHelper::terminate = false;
00019 pid_t RfCommHelper::m_pid;
00020 
00021 RfCommHelper::RfCommHelper()
00022     : m_connected( false )
00023 {
00024     signal( SIGCHLD, signal_handler );
00025 }
00026 RfCommHelper::~RfCommHelper() {
00027     detach();
00028 }
00029 QCString RfCommHelper::attachedDevice() const {
00030     return m_device;
00031 }
00032 void RfCommHelper::detach() {
00033     if (m_connected )
00034         ::kill( m_pid,  9 );
00035     if ( m_in2out[0] )
00036         close(m_in2out[0] );
00037     if ( m_in2out[1] )
00038         close(m_in2out[1] );
00039     if ( m_out2in[0] )
00040         close(m_out2in[0] );
00041     if ( m_out2in[1] )
00042         close(m_out2in[1] );
00043 }
00044 bool RfCommHelper::attach( const QString& bd_addr, int port ) {
00045     int i =0;
00046     bool ok = false;
00047     while (!ok   ) {
00048         if (i == 4) break;
00049         ok = connect( i,  bd_addr,  port );
00050         i++;
00051     }
00052     return ok;
00053 }
00054 /*
00055  * not implemented yet
00056  */
00057 void RfCommHelper::regroup() {
00058 
00059 }
00060 bool RfCommHelper::connect(int devi, const QString& bdaddr, int port) {
00061     m_connected = false;
00062     if ( pipe(m_fd) < 0 )
00063         m_fd[0] = m_fd[1] = 0;
00064     if ( pipe(m_in2out)  < 0 )
00065         m_in2out[0] = m_in2out[1] = 0;
00066     if ( pipe(m_out2in ) < 0 )
00067         m_out2in[0] = m_out2in[1] = 0;
00068 
00069     m_pid = fork();
00070     switch( m_pid ) {
00071     case -1:
00072         return false;
00073         break;
00074     /*
00075      * This is the child code.
00076      * We do some fd work
00077      * and then we'll execlp
00078      * to start it up
00079      */
00080     case 0:{ // child code
00081         setupComChild();
00082         char por[15];
00083         char dev[15];
00084         sprintf( por, "%d", port );
00085         sprintf( dev, "%d", devi );
00086         execlp( "rfcomm", "rfcomm",  dev, bdaddr.latin1(), por, NULL );
00087         char resultByte = 1;
00088         if ( m_fd[1] )
00089             write(m_fd[1], &resultByte, 1 );
00090         _exit( -1 );
00091         break;
00092     }
00093     /*
00094      * The Parent. We'll first wait for fd[0] to fill
00095      * up.
00096      * Then we will wait for out2in[0] to fill up and then
00097      * we will parse it.
00098      * maybe the signal handler gets it's turn in this case we return
00099      * false
00100      * otheriwse we will parse the Output and either return true
00101      * or false
00102      */
00103     default: {
00104         if ( m_fd[1] )
00105             close( m_fd[1] );
00106         if ( m_fd[0] ) for (;;) {
00107             char resultByte;
00108             int len;
00109             len = read(m_fd[0], &resultByte, 1 );
00110             if ( len == 1 ) { // it failed to execute
00111                 return false;
00112             }
00113             if ( len == -1 )
00114                 if ( (errno == ECHILD ) || (errno == EINTR ) )
00115                     continue; // the other process is not yet ready?
00116 
00117             break;
00118         }
00119         if ( m_fd[0] )
00120             close( m_fd[0] );
00121         terminate = false;
00122         fd_set fds;
00123         struct timeval timeout;
00124         int sel;
00125         while (!terminate ) {
00126             FD_ZERO( &fds );
00127             FD_SET( m_in2out[0], &fds );
00128             timeout.tv_sec = 5;
00129             timeout.tv_usec = 0;
00130 
00131             sel = select( m_in2out[0]+1, &fds, NULL, NULL,  &timeout );
00132             if ( sel )
00133                 if (FD_ISSET(m_in2out[0], &fds ) ) {
00134                     char buf[2048];
00135                     int len;
00136                     buf[0]  = 0;
00137                     len = read( m_in2out[0], buf,  sizeof(buf) );
00138                     if ( len > 0 ) {
00139                         QCString string( buf );
00140                         if (string.left(9) == "Connected" ) {
00141                             m_connected = true;
00142                             m_device = m_device.sprintf("/dev/tty%d", devi );
00143                             break; // we got connected
00144                         };
00145                     }
00146                     // now parese it
00147                 }else {// time out
00148                     // 5 seconds without input check terminate?
00149                     //
00150                     ;
00151                 }
00152         }
00153         break;
00154     }
00155     }
00156     return !terminate;
00157 }
00158 
00159 
00160 void RfCommHelper::setupComChild() {
00161     if ( m_fd[0] )
00162         close(m_fd[0]);
00163     if ( m_fd[1] )
00164         fcntl( m_fd[1] ,  F_SETFD,  FD_CLOEXEC);
00165 
00166     /* duplicating pipes and making them STDIN and STDOUT
00167      * of the new process
00168      * [0] is for reading
00169      * [1] is for writing
00170      */
00171     dup2( m_out2in[0], STDIN_FILENO );
00172     dup2( m_in2out[1], STDOUT_FILENO );
00173 
00174 
00175 };
00176 void RfCommHelper::signal_handler(int) {
00177     int status;
00178     terminate = true;
00179     signal( SIGCHLD, signal_handler );
00180     waitpid( m_pid, &status, WNOHANG );
00181 }

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