00001 #include <qmessagebox.h>
00002 #include <qfile.h>
00003 #include <qdir.h>
00004 #include <qtextstream.h>
00005 #include <qpixmap.h>
00006 #include <qvector.h>
00007 #include <qpe/resource.h>
00008
00009 #include <opie2/odebug.h>
00010
00011 #include <bluezlib.h>
00012
00013 #include <OTDevice.h>
00014 #include <OTDriver.h>
00015 #include <OTInquiry.h>
00016 #include <OTDriverList.h>
00017 #include <OTDeviceAddress.h>
00018 #include <OTGateway.h>
00019
00020 using namespace Opietooth2;
00021
00022
00023 OTGateway * OTGateway::SingleGateway = 0;
00024 int OTGateway::UseCount = 0;
00025
00026 OTGateway * OTGateway::getOTGateway( void ) {
00027 if(SingleGateway == 0 ) {
00028 SingleGateway = new OTGateway();
00029 }
00030
00031 UseCount ++;
00032 return SingleGateway;
00033 }
00034
00035 void OTGateway::releaseOTGateway( void ) {
00036 UseCount --;
00037 if( UseCount == 0 ) {
00038 delete SingleGateway;
00039 SingleGateway = 0;
00040 }
00041 }
00042
00043
00044 OTGateway::OTGateway( void ) : QObject( 0, "OTGateway" ),
00045 AllDrivers( this ),
00046 AllPeers() {
00047
00048 ErrorConnectCount = 0;
00049 TheOTDevice = 0;
00050 Scanning = 0;
00051 AllPeersModified = 0;
00052 AllPeers.setAutoDelete( TRUE );
00053
00054 if ( ( HciCtl = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI)) < 0) {
00055 SLOT_ShowError( tr( "error opening hci socket" ) );
00056 return;
00057 }
00058
00059
00060 updateDrivers();
00061
00062
00063 loadKnownPeers();
00064
00065
00066
00067 loadActiveNetworkSetups();
00068
00069
00070 timerEvent(0);
00071 RefreshTimer = -1;
00072 setRefreshTimer( 4000 );
00073
00074
00075 readLinkKeys();
00076 }
00077
00078
00079 OTGateway::~OTGateway( void ) {
00080
00081 if( AllPeersModified ) {
00082 saveKnownPeers();
00083 }
00084
00085 if( Scanning )
00086 delete Scanning;
00087
00088 if( TheOTDevice )
00089 delete TheOTDevice;
00090
00091 if( HciCtl >= 0 ) {
00092 ::close( HciCtl );
00093 }
00094 }
00095
00096 void OTGateway::setRefreshTimer( int T ) {
00097 if( RefreshTimer != -1 ) {
00098 killTimer( RefreshTimer );
00099 }
00100
00101 if( T == 0 )
00102 T = 4000;
00103 RefreshTimer = startTimer( T );
00104 }
00105
00106 OTDevice * OTGateway::getOTDevice( ) {
00107 if( TheOTDevice == 0 ) {
00108
00109 TheOTDevice = new OTDevice( this );
00110 connect( TheOTDevice,
00111 SIGNAL( isEnabled( int, bool ) ),
00112 this,
00113 SLOT( SLOT_Enabled( int, bool ) ) );
00114
00115 connect( TheOTDevice,
00116 SIGNAL( error( const QString & ) ),
00117 this,
00118 SLOT( SLOT_ShowError( const QString & ) ) );
00119 }
00120
00121 return TheOTDevice;
00122 }
00123
00124
00125
00126 void OTGateway::SLOT_SetEnabled( bool Mode ) {
00127 if( Mode ) {
00128 SLOT_Enable();
00129 return;
00130 }
00131 SLOT_Disable();
00132 }
00133
00134 void OTGateway::SLOT_Enable() {
00135 getOTDevice()->attach();
00136 }
00137
00138 void OTGateway::SLOT_Disable() {
00139 getOTDevice()->detach();
00140 }
00141
00142 bool OTGateway::needsEnabling() {
00143 return getOTDevice()->needsAttach();
00144 }
00145
00146 bool OTGateway::isEnabled() {
00147 if( getOTDevice()->deviceNr() >= 0 &&
00148 AllDrivers.count() != 0 &&
00149 driver( getOTDevice()->deviceNr() )->isUp() )
00150 return TRUE;
00151
00152
00153 return getOTDevice()->isAttached();
00154 }
00155
00156 void OTGateway::SLOT_ShowError( const QString & S ) {
00157
00158 odebug << S << oendl;
00159
00160 if( ErrorConnectCount > 0 ) {
00161
00162 emit error( QString( "<p>" ) + S + "</p>" );
00163 return;
00164 }
00165
00166 QMessageBox::warning( 0,
00167 tr("OTGateway error"),
00168 S );
00169 }
00170
00171 void OTGateway::connectNotify( const char * S ) {
00172 if( S && strcmp( S, "error(const QString&)" ) == 0 ) {
00173 ErrorConnectCount ++;
00174 }
00175 }
00176
00177 void OTGateway::disconnectNotify( const char * S ) {
00178 if( S && strcmp( S, "error(const QString&)" ) == 0 ) {
00179 ErrorConnectCount --;
00180 }
00181 }
00182
00183 void OTGateway::timerEvent( QTimerEvent * ) {
00184
00185 OTDriver * D;
00186 unsigned int oldc = AllDrivers.count();
00187 bool old;
00188
00189 AllDrivers.update();
00190
00191 if( oldc != AllDrivers.count() ) {
00192 updateDrivers();
00193 } else {
00194 for( unsigned int i = 0;
00195 i < AllDrivers.count();
00196 i ++ ) {
00197 D = AllDrivers[i];
00198 old = D->isUp();
00199 if( D->currentState() >= 0 ) {
00200 if( old != D->isUp() ) {
00201 emit stateChange( D, D->isUp() );
00202 }
00203 } else {
00204
00205
00206 updateDrivers();
00207 return;
00208 }
00209 }
00210 }
00211 }
00212
00213 void OTGateway::SLOT_Enabled( int id, bool Up ) {
00214 odebug << "device " << id << " state " << Up << oendl;
00215 if( Up ) {
00216
00217 updateDrivers();
00218 if( (unsigned)id >= AllDrivers.count() ) {
00219
00220 AllDrivers[id]->bringUp();
00221 }
00222 }
00223 emit deviceEnabled( Up );
00224 }
00225
00226 void OTGateway::updateDrivers( void ) {
00227 OTDriver * D;
00228
00229 AllDrivers.update();
00230
00231 odebug << "updated drivers. now " << AllDrivers.count() << oendl;
00232
00233
00234 for( unsigned int i = 0;
00235 i < AllDrivers.count();
00236 i ++ ) {
00237 D = AllDrivers[i];
00238
00239 connect( D,
00240 SIGNAL( error( const QString & ) ),
00241 this,
00242 SLOT( SLOT_ShowError( const QString & ) )
00243 );
00244
00245 connect( D,
00246 SIGNAL( stateChange( OTDriver *, bool ) ),
00247 this,
00248 SIGNAL( stateChange( OTDriver *, bool ) )
00249 );
00250
00251 connect( D,
00252 SIGNAL( driverDisappeared( OTDriver * ) ),
00253 this,
00254 SLOT( SLOT_DriverDisappeared( OTDriver * ) )
00255 );
00256 }
00257
00258
00259 if( TheOTDevice )
00260 TheOTDevice->checkAttach();
00261
00262
00263 setScanWith( 0 );
00264
00265 emit driverListChanged();
00266 }
00267
00268 void OTGateway::SLOT_DriverDisappeared( OTDriver * D ) {
00269 odebug << "Driver " << D->devname() << " when offline" << oendl;
00270 updateDrivers();
00271 }
00272
00273 void OTGateway::scanNeighbourhood( OTDriver * D ) {
00274
00275 if( Scanning ) {
00276 stopScanOfNeighbourhood();
00277 }
00278
00279 if( D ) {
00280 setScanWith( D );
00281 }
00282
00283 Scanning = new OTInquiry( scanWith() );
00284
00285 connect( Scanning,
00286 SIGNAL( peerFound( OTPeer *, bool )),
00287 this,
00288 SLOT( SLOT_PeerDetected( OTPeer *, bool ) )
00289 );
00290 connect( Scanning,
00291 SIGNAL( finished()),
00292 this,
00293 SLOT( SLOT_FinishedDetecting() )
00294 );
00295
00296
00297 Scanning->inquire( 30.0 );
00298 }
00299
00300 OTPeer* OTGateway::findPeer( const OTDeviceAddress & Addr ) {
00301 for( unsigned int i = 0 ; i < AllPeers.count(); i ++ ) {
00302 if( AllPeers[i]->address() == Addr ) {
00303 return AllPeers[i];
00304 }
00305 }
00306 return 0;
00307 }
00308
00309 OTDriver* OTGateway::findDriver( const OTDeviceAddress & Addr ) {
00310 for( unsigned int i = 0 ; i < AllDrivers.count(); i ++ ) {
00311 if( AllDrivers[i]->address() == Addr ) {
00312 return AllDrivers[i];
00313 }
00314 }
00315 return 0;
00316 }
00317
00318 void OTGateway::SLOT_PeerDetected( OTPeer * P, bool IsNew ) {
00319
00320 if( IsNew ) {
00321
00322 odebug << "New peer " << P->name() << oendl;
00323 addPeer( P );
00324 }
00325
00326 emit detectedPeer( P, IsNew );
00327 }
00328
00329 void OTGateway::addPeer( OTPeer * P ) {
00330 AllPeers.resize( AllPeers.size()+1);
00331 AllPeers.insert( AllPeers.size()-1, P );
00332 AllPeersModified = 1;
00333 }
00334
00335 void OTGateway::removePeer( OTPeer * P ) {
00336 int i = AllPeers.find( P );
00337 if( i ) {
00338 AllPeers.remove( i );
00339 AllPeersModified = 1;
00340 }
00341 }
00342
00343 void OTGateway::stopScanOfNeighbourhood( void ) {
00344 if( Scanning ) {
00345 delete Scanning;
00346 Scanning = 0;
00347 }
00348 }
00349
00350 void OTGateway::SLOT_FinishedDetecting() {
00351 stopScanOfNeighbourhood();
00352 emit finishedDetecting();
00353 }
00354
00355 const char * OTGateway::deviceTypeToName( int cls ) {
00356 switch ( (cls & 0x001F00) >> 8) {
00357 case 0x00:
00358 return "misc";
00359 case 0x01:
00360 return "computer";
00361 case 0x02:
00362 return "phone";
00363 case 0x03:
00364 return "lan";
00365 case 0x04:
00366 return "av";
00367 case 0x05:
00368 return "peripheral";
00369 case 0x06:
00370 return "imaging";
00371 case 0x07:
00372 default :
00373 break;
00374 }
00375 return "unknown";
00376 }
00377
00378 PANNetworkSetupVector OTGateway::getPANNetworkSetups( void ) {
00379 PANNetworkSetupVector V;
00380
00381 struct bnep_connlist_req req;
00382 struct bnep_conninfo ci[48];
00383
00384 V.setAutoDelete(TRUE);
00385
00386 int ctl = socket(PF_BLUETOOTH, SOCK_RAW, BTPROTO_BNEP);
00387 if (ctl < 0) {
00388 odebug << "Failed to open control socket" << oendl;
00389 return V;
00390 }
00391
00392 req.cnum = 48;
00393 req.ci = ci;
00394 if (ioctl(ctl, BNEPGETCONNLIST, &req)) {
00395 odebug << "Failed to get NetworkSetup list" << oendl;
00396 ::close( ctl );
00397 return V;
00398 }
00399
00400 for ( unsigned i=0; i < req.cnum; i++) {
00401 V.resize( V.size() + 1 );
00402 if( ci[i].role == BNEP_SVC_PANU ) {
00403
00404 V.insert( V.size()-1, new OTPANNetworkSetup(
00405 ci[i].device,
00406 batostr((bdaddr_t *) ci[i].dst)
00407 ) );
00408 }
00409 }
00410
00411 ::close( ctl );
00412 return V;
00413 }
00414
00415 struct link_key {
00416 bdaddr_t sba;
00417 bdaddr_t dba;
00418 uint8_t key[16];
00419 uint8_t type;
00420 time_t time;
00421 };
00422
00423 void OTGateway::readLinkKeys( void ) {
00424
00425 struct link_key k;
00426 int rv;
00427
00428 AllKeys.truncate(0);
00429
00430 QFile F( "/etc/bluetooth/link_key" );
00431
00432 if( ! F.open( IO_ReadOnly ) ) {
00433 emit error( tr("Cannot open link_key file") );
00434 return;
00435 }
00436
00437 while( 1 ) {
00438 rv = F.readBlock( (char *)&k, sizeof( k ) );
00439 if( rv == 0 )
00440
00441 break;
00442
00443 if( rv < 0 ) {
00444 emit error( tr("Read error in link key file") );
00445 }
00446
00447 AllKeys.resize( AllKeys.size()+1 );
00448 AllKeys[ AllKeys.size()-1 ].From.setBDAddr( k.sba );
00449 AllKeys[ AllKeys.size()-1 ].To.setBDAddr( k.dba );
00450 }
00451 }
00452
00453 bool OTGateway::removeLinkKey( unsigned int Index ) {
00454 OTLinkKey & LK = AllKeys[Index];
00455
00456 struct link_key k;
00457 int rv;
00458
00459 QFile F( "/etc/bluetooth/link_key" );
00460 QFile OutF( "/etc/bluetooth/newlink_key" );
00461
00462 if( ! F.open( IO_ReadOnly ) ) {
00463 emit error( tr("Cannot open link_key file") );
00464 return 0;
00465 }
00466
00467 if( ! OutF.open( IO_WriteOnly | IO_Truncate ) ) {
00468 emit error( tr("Cannot open temporary link_key file") );
00469 return 0;
00470 }
00471
00472 while( 1 ) {
00473 rv = F.readBlock( (char *)&k, sizeof( k ) );
00474 if( rv == 0 )
00475
00476 break;
00477
00478 if( rv < 0 ) {
00479 emit error( tr("Read error in link key file") );
00480 return 0;
00481 }
00482
00483 if( LK.from() != OTDeviceAddress( k.sba ) ||
00484 LK.to() != OTDeviceAddress( k.dba ) ) {
00485
00486 OutF.writeBlock( (char *)&k, sizeof( k ) );
00487 }
00488 }
00489
00490
00491 QDir D( "/etc/bluetooth" );
00492
00493 D.remove( "link_key" );
00494 D.rename( "newlink_key", "link_key" );
00495
00496
00497 system( "/etc/init.d/hcid stop" );
00498 system( "/etc/init.d/hcid start" );
00499
00500
00501 if( Index < (AllKeys.size()-1) ) {
00502
00503 AllKeys[Index] = AllKeys[AllKeys.size()-1];
00504 }
00505
00506
00507 AllKeys.resize( AllKeys.size()-1 );
00508
00509 return 1;
00510 }
00511
00512 #define MAXCONNECTIONS 10
00513 void OTGateway::loadActiveNetworkSetups( void ) {
00514
00515 struct hci_conn_list_req *cl;
00516 struct hci_conn_info *ci;
00517 OTDeviceAddress Addr;
00518 OTPeer * P;
00519
00520 if (!(cl = (struct hci_conn_list_req *)malloc(
00521 MAXCONNECTIONS * sizeof(*ci) + sizeof(*cl)))) {
00522 emit error( tr("Can't allocate memory") );
00523 return;
00524 }
00525 memset( cl, 0, MAXCONNECTIONS * sizeof(*ci) + sizeof(*cl) );
00526
00527 for( unsigned int i = 0;
00528 i < AllDrivers.count();
00529 i ++ ) {
00530
00531 if( ! AllDrivers[i]->isUp() ) {
00532 continue;
00533 }
00534
00535
00536 cl->dev_id = AllDrivers[i]->devId();
00537 cl->conn_num = MAXCONNECTIONS;
00538 ci = cl->conn_info;
00539
00540 if (ioctl( getSocket(), HCIGETCONNLIST, (void *) cl)) {
00541 emit error( tr("Can't get NetworkSetup list") );
00542 break;
00543 }
00544
00545 for ( int k = 0; k < cl->conn_num; k++, ci++) {
00546
00547 if( ci->state != BT_CONNECTED ) {
00548
00549 continue;
00550 }
00551
00552 Addr.setBDAddr( ci->bdaddr );
00553 P = findPeer( Addr );
00554 if( ! P ) {
00555
00556 P = new OTPeer( this );
00557 addPeer( P );
00558 P->setAddress( Addr );
00559
00560 P->setName( AllDrivers[i]->getPeerName( Addr ) );
00561 }
00562 P->setState( OTPeer::Peer_Up );
00563 P->setConnectedTo( AllDrivers[i] );
00564 }
00565 }
00566
00567 free( cl );
00568 }
00569
00570 void OTGateway::loadKnownPeers( void ) {
00571 QDir SaveDir = QDir::home();
00572
00573 if( ! SaveDir.exists( "Settings" ) ) {
00574 return;
00575 }
00576 SaveDir.cd( "Settings" );
00577
00578 if( ! SaveDir.exists( "opietooth" ) ) {
00579 return;
00580 }
00581 SaveDir.cd( "opietooth" );
00582
00583 QFile F( SaveDir.path() + "/SeenDevices.conf" );
00584
00585 if( F.open( IO_ReadOnly ) ) {
00586 QTextStream TS(&F);
00587 long count;
00588
00589 count = TS.readLine().toLong();
00590
00591 while( count > 0 ) {
00592 addPeer( new OTPeer( TS, this ) );
00593 count --;
00594 }
00595 }
00596
00597 AllPeersModified = 0;
00598 }
00599
00600 void OTGateway::saveKnownPeers( void ) {
00601 QDir SaveDir = QDir::home();
00602
00603 if( ! SaveDir.exists( "Settings" ) ) {
00604 SaveDir.mkdir( "Settings" );
00605 }
00606 SaveDir.cd( "Settings" );
00607
00608 if( ! SaveDir.exists( "opietooth" ) ) {
00609 SaveDir.mkdir( "opietooth" );
00610 }
00611 SaveDir.cd( "opietooth" );
00612
00613 QFile F( SaveDir.path() + "/SeenDevices.conf" );
00614
00615 if( F.open( IO_WriteOnly | IO_Truncate ) ) {
00616 QTextStream TS(&F);
00617 QString S;
00618
00619 TS << AllPeers.count() << endl;
00620
00621 for( unsigned int i = 0;
00622 i < AllPeers.count();
00623 i ++ ) {
00624 AllPeers[i]->save( TS );
00625 }
00626 AllPeersModified = 0;
00627 }
00628 AllPeersModified = 0;
00629 }
00630
00631 int OTGateway::connectedToRFCommChannel( const OTDeviceAddress & Addr,
00632 int channel ) {
00633
00634 int s;
00635
00636 if( (s = ::socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_RFCOMM)) < 0 ) {
00637 emit error( tr("Can't open RFCOMM control socket") );
00638 return 0;
00639 }
00640
00641
00642 { struct rfcomm_dev_list_req *dl;
00643 struct rfcomm_dev_info *di, *dr;
00644 int i;
00645
00646 dl = (struct rfcomm_dev_list_req *)alloca(
00647 sizeof(*dl) + RFCOMM_MAX_DEV * sizeof(*di));
00648 memset( dl, 0, sizeof(*dl) + RFCOMM_MAX_DEV * sizeof(*di) );
00649 dl->dev_num = RFCOMM_MAX_DEV;
00650 di = dl->dev_info;
00651
00652 if( ::ioctl(s, RFCOMMGETDEVLIST, (void *) dl) < 0) {
00653 emit error( tr("Can't get device list") );
00654 ::close( s );
00655 return 0;
00656 }
00657
00658 dr = di;
00659 for (i = 0; i < dl->dev_num; i++, dr++) {
00660
00661 if( Addr == OTDeviceAddress( dr->dst ) &&
00662 channel == dr->channel &&
00663 ( dr->state != 0 )
00664 ) {
00665
00666 return dr->id;
00667 }
00668 }
00669 }
00670
00671
00672 return -1;
00673 }
00674
00675 static int byID( struct rfcomm_dev_info * d1,
00676 struct rfcomm_dev_info * d2 ) {
00677 return d1->id - d2->id;
00678 }
00679
00680 int OTGateway::getFreeRFCommDevice( void ) {
00681
00682 int s;
00683
00684 if( (s = ::socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_RFCOMM)) < 0 ) {
00685 emit error( tr("Can't open RFCOMM control socket") );
00686 return 0;
00687 }
00688
00689
00690 { struct rfcomm_dev_list_req *dl;
00691 struct rfcomm_dev_info *di, *dr;
00692 int i;
00693
00694 dl = (struct rfcomm_dev_list_req *)alloca(
00695 sizeof(*dl) + RFCOMM_MAX_DEV * sizeof(*di));
00696
00697 dl->dev_num = RFCOMM_MAX_DEV;
00698 di = dl->dev_info;
00699
00700 if( ::ioctl(s, RFCOMMGETDEVLIST, (void *) dl) < 0) {
00701 emit error( tr("Can't get device list") );
00702 ::close( s );
00703 return 0;
00704 }
00705
00706
00707 if( dl->dev_num ) {
00708 qsort( di, sizeof(struct rfcomm_dev_info),
00709 dl->dev_num, (int(*)(const void*,const void*))byID );
00710 int id = 0;
00711
00712 dr = di;
00713
00714 for (i = 0; i < dl->dev_num; i++, dr++) {
00715 if( id != dr->id ) {
00716 return id;
00717 }
00718 id ++;
00719 }
00720 return id;
00721 } else {
00722 return 0;
00723 }
00724 }
00725 }
00726
00727 int OTGateway::releaseRFCommDevice( int devnr ) {
00728
00729 int s;
00730
00731 if( (s = ::socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_RFCOMM)) < 0 ) {
00732 emit error( tr("Can't open RFCOMM control socket") );
00733 return 0;
00734 }
00735
00736
00737 { struct rfcomm_dev_list_req *dl;
00738 struct rfcomm_dev_info *di, *dr;
00739 int i;
00740
00741 dl = (struct rfcomm_dev_list_req *)alloca(
00742 sizeof(*dl) + RFCOMM_MAX_DEV * sizeof(*di));
00743 memset( dl, 0, sizeof(*dl) + RFCOMM_MAX_DEV * sizeof(*di) );
00744 dl->dev_num = RFCOMM_MAX_DEV;
00745 di = dl->dev_info;
00746
00747 if( ::ioctl(s, RFCOMMGETDEVLIST, (void *) dl) < 0) {
00748 emit error( tr("Can't get device list") );
00749 ::close( s );
00750 return 0;
00751 }
00752
00753 dr = di;
00754 for (i = 0; i < dl->dev_num; i++, dr++) {
00755 if( dr->id == devnr ) {
00756
00757 struct rfcomm_dev_req req;
00758 int err;
00759
00760 memset(&req, 0, sizeof(req));
00761 req.dev_id = devnr;
00762
00763 if ((err = ioctl(s, RFCOMMRELEASEDEV, &req)) < 0 ) {
00764 return err;
00765 }
00766 return 0;
00767 }
00768 }
00769 }
00770
00771
00772 return 0;
00773 }
00774