00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include <assert.h>
00013 #include <sys/poll.h>
00014 #include <string.h>
00015
00016 #include <bluezlib.h>
00017 #include <qarray.h>
00018 #include <qtextstream.h>
00019
00020 #include <opie2/odebug.h>
00021
00022 #include <OTDeviceAddress.h>
00023 #include <OTSDPAttribute.h>
00024 #include <OTSDPService.h>
00025 #include <OTPeer.h>
00026 #include <OTGateway.h>
00027 #include <OTDriver.h>
00028
00029 using namespace Opietooth2;
00030
00031 OTPeer::OTPeer( OTGateway * _OT ) {
00032 OT = _OT;
00033 State = Peer_Unknown;
00034 ConnectedTo = 0;
00035 }
00036
00037 OTPeer::OTPeer( QTextStream & TS, OTGateway * _OT ) {
00038 OT = _OT;
00039 State = Peer_Unknown;
00040 ConnectedTo = 0;
00041
00042 load( TS );
00043 }
00044
00045 OTPeer::~OTPeer( ) {
00046
00047 }
00048
00049 void OTPeer::updateServices( void ) {
00050 sdp_session_t *session;
00051
00052 serviceList.clear();
00053
00054 odebug << "Get services from " << Addr.toString() << oendl;
00055
00056 session = sdp_connect( &(OTDeviceAddress::any.getBDAddr()),
00057 &(Addr.getBDAddr()),
00058 0);
00059
00060 if (!session) {
00061 odebug << "sdp_connect("
00062 << Addr.toString()
00063 << ") failed"
00064 << oendl;
00065 return;
00066 }
00067
00068 uint32_t range = 0x0000ffff;
00069 sdp_list_t* attrId = sdp_list_append(0, &range);
00070
00071
00072 uuid_t grp;
00073 sdp_uuid16_create( &grp, PUBLIC_BROWSE_GROUP );
00074 sdp_list_t * search = sdp_list_append(0, &grp );
00075
00076
00077 sdp_list_t* seq;
00078 if (sdp_service_search_attr_req( session,
00079 search,
00080 SDP_ATTR_REQ_RANGE,
00081 attrId,
00082 &seq ) ) {
00083 odebug << "Service Search failed" << oendl;
00084 sdp_close(session);
00085 return;
00086 }
00087
00088 sdp_list_free(attrId, 0);
00089 sdp_list_free(search, 0);
00090
00091
00092 sdp_list_t* next = NULL;
00093
00094 for (; seq; seq = next) {
00095 sdp_record_t *rec = (sdp_record_t *) seq->data;
00096
00097 sdp_list_t* attrlist = rec->attrlist;
00098 AttributeVector alist;
00099 OTSDPService * service;
00100
00101 service = new OTSDPService();
00102
00103 for (; attrlist; attrlist = attrlist->next) {
00104 int attrID = ((sdp_data_t*)(attrlist->data))->attrId;
00105 service->addAttribute(
00106 attrID,
00107 new OTSDPAttribute( (sdp_data_t*)(attrlist->data) )
00108 );
00109 }
00110
00111 serviceList.resize( serviceList.size() + 1 );
00112 serviceList.insert( serviceList.size() - 1, service );
00113
00114 next = seq->next;
00115 free(seq);
00116 sdp_record_free(rec);
00117 }
00118 sdp_close(session);
00119 }
00120
00121 bool OTPeer::hasServiceClassID( const OTUUID & uuid) {
00122 for( unsigned int i = 0;
00123 i < serviceList.count();
00124 i ++ ) {
00125 if( serviceList[i]->hasClassID(uuid))
00126 return true;
00127 }
00128 return false;
00129 }
00131 QArray<int> OTPeer::rfcommList( const OTUUID & uuid) {
00132
00133 QArray<int> rfcommList;
00134 unsigned int channel;
00135
00136 for( unsigned int i = 0;
00137 i < serviceList.count();
00138 i ++ ) {
00139 if( serviceList[i]->hasClassID(uuid)) {
00140 if( serviceList[i]->rfcommChannel(channel) ) {
00141 rfcommList.resize( rfcommList.size()+1 );
00142 rfcommList[rfcommList.size()-1] = channel;
00143 }
00144 }
00145 }
00146 return rfcommList;
00147 }
00148
00149 void OTPeer::save( QTextStream & TS ) {
00150 TS << "bdaddr " << address().toString() << endl;
00151 TS << "name " << name() << endl;
00152 TS << "class " << deviceClass() << endl;
00153 }
00154
00155 void OTPeer::load( QTextStream & TS ) {
00156 QString S;
00157 S = TS.readLine();
00158 setAddress( OTDeviceAddress( S.mid( 7 ) ) );
00159
00160 S = TS.readLine();
00161 setName( S.mid( 5 ) );
00162
00163 S = TS.readLine();
00164 setDeviceClass( S.mid( 6 ).toLong() );
00165 }
00166
00167 #define MAGICNR -99999
00168 #define POLLDELAY 1000
00169 #define PREMAGICNR (MAGICNR+POLLDELAY)
00170
00171 void OTPeer::findOutState( int timeoutInSec, bool Force ) {
00172 ProbeFD = -1;
00173 if( Force && ConnectedTo == 0 ) {
00174 State = OTPeer::Peer_Unknown;
00175 }
00176
00177 if( State == OTPeer::Peer_Unknown ) {
00178 ProbePhase = 0;
00179 ProbeTimeout = timeoutInSec*1000;
00180 odebug << "Ping " << address().toString() << oendl;
00181 startTimer( POLLDELAY );
00182 } else {
00183 ProbeTimeout = 0;
00184 startTimer( 0 );
00185 }
00186 }
00187
00188 #define PINGSIZE 20
00189 void OTPeer::timerEvent( QTimerEvent * ev ) {
00190
00191 ProbeTimeout -= POLLDELAY;
00192
00193 if( State == OTPeer::Peer_Unknown ) {
00194 switch( ProbePhase ) {
00195 case 0 :
00196 { struct sockaddr_l2 addr;
00197
00198 if (( ProbeFD = ::socket(PF_BLUETOOTH, SOCK_RAW, BTPROTO_L2CAP)) < 0) {
00199 ProbeTimeout = 0;
00200 break;
00201 }
00202
00203 memset(&addr, 0, sizeof(addr));
00204
00205 addr.l2_family = AF_BLUETOOTH;
00206 addr.l2_bdaddr = OTDeviceAddress::any.getBDAddr();
00207
00208 if( ::bind( ProbeFD, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
00209 ProbeTimeout = 0;
00210 break;
00211 }
00212
00213
00214 if( ::fcntl( ProbeFD, F_SETFL, O_NONBLOCK ) < 0 ) {
00215 ProbeTimeout = 0;
00216 break;
00217 }
00218
00219
00220 addr.l2_bdaddr = address().getBDAddr();
00221 if( ::connect( ProbeFD, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
00222 if( errno != EAGAIN && errno != EINPROGRESS ) {
00223 ProbeTimeout = 0;
00224 break;
00225 }
00226 }
00227 }
00228 ProbePhase = 1;
00229 break;
00230 case 1 :
00231 { struct pollfd pf[1];
00232 char buf[L2CAP_CMD_HDR_SIZE + PINGSIZE + 20];
00233 int n;
00234
00235 pf[0].fd = ProbeFD;
00236 pf[0].events = POLLOUT;
00237 if( (n = ::poll(pf, 1, 0)) < 0 ) {
00238 odebug << address().toString()
00239 << " : errno "
00240 << errno
00241 << " "
00242 << strerror(errno)<<oendl;
00243 ProbeTimeout = 0;
00244 break;
00245 }
00246
00247 if( ! n ) {
00248
00249 break;
00250 }
00251
00252
00253 for( unsigned int i = L2CAP_CMD_HDR_SIZE; i < sizeof(buf); i++)
00254 buf[i] = (i % 40) + 'A';
00255
00256 l2cap_cmd_hdr *cmd = (l2cap_cmd_hdr *) buf;
00257
00258
00259 cmd->code = L2CAP_ECHO_REQ;
00260 cmd->ident = *(char *)this;
00261 cmd->len = PINGSIZE;
00262
00263
00264 if( ::send(ProbeFD, buf, PINGSIZE + L2CAP_CMD_HDR_SIZE, 0) <= 0) {
00265 if( errno == EACCES ) {
00266
00267
00268
00269 odebug << address().toString()
00270 << " good send error "
00271 << errno
00272 << " "
00273 << strerror( errno)
00274 << oendl;
00275 State = OTPeer::Peer_Up;
00276 ProbeTimeout = 0;
00277 break;
00278 } else if( errno != EBUSY ) {
00279 odebug << address().toString()
00280 << " : errno "
00281 << errno
00282 << " "
00283 << strerror(errno)
00284 << oendl;
00285 ProbeTimeout = 0;
00286 break;
00287 }
00288 }
00289
00290 ProbePhase = 2;
00291 }
00292 break;
00293 case 2 :
00294 { struct pollfd pf[1];
00295 char buf[L2CAP_CMD_HDR_SIZE + PINGSIZE + 20];
00296 l2cap_cmd_hdr *cmd = (l2cap_cmd_hdr *) buf;
00297 int n;
00298
00299 pf[0].fd = ProbeFD;
00300 pf[0].events = POLLIN;
00301 if( (n = ::poll(pf, 1, 0)) < 0 ) {
00302 odebug << address().toString()
00303 << " : errno "
00304 << errno
00305 << " "
00306 << strerror(errno)
00307 <<oendl;
00308 ProbeTimeout = 0;
00309 break;
00310 }
00311
00312 if( ! n ) {
00313
00314 break;
00315 }
00316
00317 if( (n = ::recv( ProbeFD, buf, sizeof(buf), 0)) < 0) {
00318 odebug << address().toString()
00319 << "errno "
00320 << errno
00321 << " "
00322 << strerror(errno)
00323 << oendl;
00324 ProbeTimeout = 0;
00325 break;
00326 }
00327
00328
00329 if( cmd->ident != *(char *)this )
00330
00331 break;
00332
00333 odebug << "reply from "
00334 << address().toString()
00335 << oendl;
00336
00337 State = OTPeer::Peer_Up;
00338 ProbeTimeout = 0;
00339 }
00340 break;
00341 }
00342
00343 if( State != OTPeer::Peer_Unknown ) {
00344 ProbeTimeout = 0;
00345 }
00346 }
00347
00348 if( ProbeTimeout <= 0 ) {
00349
00350 emit peerStateReport( this );
00351 if( State == Peer_Unknown ) {
00352 State = Peer_Down;
00353 }
00354 if( ProbeFD >= 0 ) {
00355
00356 ::close( ProbeFD );
00357 }
00358
00359 killTimer( ev->timerId() );
00360 }
00361 }
00362
00363 void OTPeer::stopFindingOutState( void ) {
00364 ProbeTimeout = PREMAGICNR;
00365 }
00366