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
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
00076
00077
00078
00079
00080 case 0:{
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
00095
00096
00097
00098
00099
00100
00101
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 ) {
00111 return false;
00112 }
00113 if ( len == -1 )
00114 if ( (errno == ECHILD ) || (errno == EINTR ) )
00115 continue;
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;
00144 };
00145 }
00146
00147 }else {
00148
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
00167
00168
00169
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 }