00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include <opie2/odebug.h>
00012 #include <qtimer.h>
00013
00014 #include <sys/poll.h>
00015 #include <bluezlib.h>
00016 #ifndef GET_LINK_QUALITY_RP_SIZE
00017 #define GET_LINK_QUALITY_RP_SIZE READ_LINK_QUALITY_RP_SIZE
00018 #endif
00019 #include <OTGateway.h>
00020 #include <OTDriver.h>
00021 #include <OTHCISocket.h>
00022
00023 using namespace Opietooth2;
00024
00025 static struct {
00026 const char *str;
00027 unsigned short rev;
00028 } csr_map[] = {
00029 { "HCI 11.2 (bc01b)", 114 },
00030 { "HCI 11.3 (bc01b)", 115 },
00031 { "HCI 12.1 (bc01b)", 119 },
00032 { "HCI 12.3 (bc01b)", 134 },
00033 { "HCI 12.7 (bc01b)", 188 },
00034 { "HCI 12.8 (bc01b)", 218 },
00035 { "HCI 12.9 (bc01b)", 283 },
00036 { "HCI 13.10 (bc01b)", 309 },
00037 { "HCI 13.11 (bc01b)", 351 },
00038 { "HCI 16.4 (bc01b)", 523 },
00039 { "HCI 14.3 (bc02x)", 272 },
00040 { "HCI 14.6 (bc02x)", 336 },
00041 { "HCI 14.7 (bc02x)", 373 },
00042 { "HCI 14.8 (bc02x)", 487 },
00043 { "HCI 15.3 (bc02x)", 443 },
00044 { "HCI 16.4 (bc02x)", 525 },
00045 { NULL, 0}
00046 };
00047
00048 static char *services[] = { "Positioning",
00049 "Networking",
00050 "Rendering",
00051 "Capturing",
00052 "Object Transfer",
00053 "Audio",
00054 "Telephony",
00055 "Information" };
00056
00057 static char *major_devices[] = { "Miscellaneous",
00058 "Computer",
00059 "Phone",
00060 "LAN Access",
00061 "Audio/Video",
00062 "Peripheral",
00063 "Imaging",
00064 "Uncategorized" };
00065
00066
00067 typedef struct {
00068 short Minor;
00069 const char * Description;
00070 } ClassMap_t;
00071
00072 static ClassMap_t MapMiscClass[] = {
00073 { -1, "" }
00074 };
00075
00076 static ClassMap_t MapUnclassifiedClass[] = {
00077 { -1, "" }
00078 };
00079
00080 static ClassMap_t MapComputerClass[] = {
00081 { 0, "Uncategorized" } ,
00082 { 1, "Desktop workstation" } ,
00083 { 2, "Server" } ,
00084 { 3, "Laptop" } ,
00085 { 4, "Handheld" } ,
00086 { 5, "Palm" } ,
00087 { 6, "Wearable" },
00088 { -1, 0 }
00089 };
00090
00091 static ClassMap_t MapPhoneClass[] = {
00092 { 0, "Uncategorized" },
00093 { 1, "Cellular" },
00094 { 2, "Cordless" },
00095 { 3, "Smart phone" },
00096 { 4, "Wired modem or voice gateway" },
00097 { 5, "Common ISDN Access" },
00098 { 6, "Sim Card Reader" },
00099 { -1, 0 }
00100 };
00101
00102 static ClassMap_t MapAVClass[] = {
00103 { 0, "Uncategorized" },
00104 { 1, "Device conforms to the Headset profile" },
00105 { 2, "Hands-free" },
00106 { 3, 0 },
00107 { 4, "Microphone" },
00108 { 5, "Loudspeaker" },
00109 { 6, "Headphones" },
00110 { 7, "Portable Audio" },
00111 { 8, "Car Audio" },
00112 { 9, "Set-top box" },
00113 { 10, "HiFi Audio Device" },
00114 { 11, "VCR" },
00115 { 12, "Video Camera" },
00116 { 13, "Camcorder" },
00117 { 14, "Video Monitor" },
00118 { 15, "Video Display and Loudspeaker" },
00119 { 16, "Video Conferencing" },
00120 { 17, 0 },
00121 { 18, "Gaming/Toy" },
00122 { -1, 0 }
00123 };
00124
00125 static ClassMap_t MapPeripheralClass[] = {
00126 { 16, "Keyboard" },
00127 { 32, "Pointing device" },
00128 { 48, "Combo keyboard/pointing device" },
00129 { -1, 0 }
00130 };
00131
00132 typedef struct {
00133 int Major;
00134 ClassMap_t * Map;
00135 } MainClassMap_t;
00136
00137 static MainClassMap_t MainClasses[] = {
00138 { 0, MapMiscClass },
00139 { 1, MapComputerClass },
00140 { 2, MapPhoneClass },
00141 { 3, 0 },
00142 { 4, MapAVClass },
00143 { 5, MapPeripheralClass },
00144 { 6, 0 },
00145 { 63, MapUnclassifiedClass },
00146 { -1, 0 }
00147 };
00148
00149 OTDriver::OTDriver( OTGateway * _OT, struct hci_dev_info* di) : QObject( _OT ), Address() {
00150 OT = _OT;
00151 IsUp = 0;
00152 Socket = 0;
00153
00154 init(di);
00155 odebug << "Driver " << devname() << oendl;
00156
00157 AutoClose = new QTimer( this );
00158 connect( AutoClose,
00159 SIGNAL( timeout() ),
00160 this,
00161 SLOT( SLOT_CloseFd() )
00162 );
00163 }
00164
00165 OTDriver::~OTDriver() {
00166 closeSocket();
00167 SLOT_CloseFd();
00168 }
00169
00170 void OTDriver::SLOT_CloseFd( void ){
00171 if ( isOpen() ) {
00172 AutoClose->stop();
00173 ::close( fd() );
00174 setfd( -1 );
00175 }
00176 }
00177
00178 void OTDriver::init(struct hci_dev_info* di) {
00179
00180 Dev = di->name;
00181
00182 setDevId(di->dev_id);
00183 setType(di->type);
00184 setFlags(di->flags);
00185 Address.setBDAddr( di->bdaddr );
00186 setFeatures(di->features);
00187 setfd( -1 );
00188
00189 Manufacturer = "";
00190 }
00191
00192
00193 void OTDriver::reinit() {
00194 bool Old;
00195 Old = IsUp;
00196
00197 if( currentState() < 0 )
00198 return;
00199
00200 if( Old != IsUp ) {
00201
00202 emit stateChange( this, IsUp );
00203 }
00204 }
00205
00206
00207 int OTDriver::currentState() {
00208 struct hci_dev_info di;
00209
00210
00211
00212
00213
00214 memset( &di, 0, sizeof( di ) );
00215 di.dev_id = Dev_id;
00216 if( ioctl( OT->getSocket(), HCIGETDEVINFO, (void*)&di) < 0 ) {
00217 SLOT_CloseFd();
00218 return -1;
00219 } else {
00220
00221 init(&di);
00222 }
00223
00224 return IsUp;
00225 }
00226
00227 bool OTDriver::open() {
00228
00229
00230 AutoClose->start( 30000, TRUE );
00231
00232 if( isOpen() )
00233
00234 return 1;
00235
00236 setfd(hci_open_dev(devId()));
00237
00238 if (fd() < 0) {
00239 emit error( tr( "Can't open device %1. %2 : %3" ).
00240 arg( devname() ).
00241 arg( errno ).
00242 arg( strerror(errno) )
00243 );
00244 return 0;
00245 }
00246
00247 return 1;
00248 }
00249
00250 QString OTDriver::name() {
00251 char name[1000];
00252
00253 if( ! open() ) {
00254 return tr("Cannot open");
00255 }
00256
00257 if (hci_read_local_name( fd(), sizeof(name), name, 1000) < 0) {
00258 if (errno != ETIMEDOUT) {
00259 emit error( tr("Can't read local name on %1. %2 : %3. Default to %4" ).
00260 arg( devname() ).
00261 arg( errno ).
00262 arg( strerror(errno) ).
00263 arg( devname() )
00264 );
00265 }
00266 strcpy(name,devname().latin1());
00267 }
00268 return QString(name);
00269 }
00270
00271 void OTDriver::setFlags(unsigned long flags) {
00272
00273
00274 IsUp = BTVALUE(hci_test_bit(HCI_UP, &flags));
00275
00276 if (isUp()) {
00277 setIScan(BTVALUE(hci_test_bit(HCI_ISCAN, &flags)));
00278 setPScan(BTVALUE(hci_test_bit(HCI_PSCAN, &flags)));
00279 setAuthentication(BTVALUE(hci_test_bit(HCI_AUTH, &flags)));
00280 setEncryption(BTVALUE(hci_test_bit(HCI_ENCRYPT, &flags)));
00281 } else {
00282 setIScan(BT_UNKNOWN);
00283 setPScan(BT_UNKNOWN);
00284 setAuthentication(BT_UNKNOWN);
00285 setEncryption(BT_UNKNOWN);
00286 }
00287 }
00288
00289 QString OTDriver::revision() {
00290
00291 struct hci_version ver;
00292
00293 if( ! open() ) {
00294 return tr("Cannot open");
00295 }
00296
00297 if (hci_read_local_version(fd(), &ver, 1000) < 0) {
00298 emit error( tr( "Can't read revision info on %1. %2 : %3" ).
00299 arg( devname() ).
00300 arg( errno ).
00301 arg( strerror(errno) ) );
00302 return QString();
00303 }
00304
00305 setManufacturer(ver.manufacturer);
00306
00307 switch (ver.manufacturer) {
00308 case 0:
00309 return getRevEricsson();
00310 break;
00311 case 10:
00312 return getRevCsr(ver.hci_rev);
00313 break;
00314 default:
00315 return tr( "Unsupported manufacturer" );
00316 break;
00317 }
00318 }
00319
00320 QString OTDriver::getRevEricsson() {
00321
00322 char revision[102];
00323 struct hci_request rq;
00324
00325 if( ! open() ) {
00326 return QString( "Cannot open" );
00327 }
00328
00329 memset(&rq, 0, sizeof(rq));
00330 rq.ogf = 0x3f;
00331 rq.ocf = 0x000f;
00332 rq.cparam = NULL;
00333 rq.clen = 0;
00334 rq.rparam = &revision;
00335 rq.rlen = sizeof(revision);
00336
00337 if (hci_send_req(fd(), &rq, 1000) < 0) {
00338 emit error( tr( "Can't read revision info on %1. %2 : %3" ).
00339 arg( devname() ).
00340 arg( errno ).
00341 arg( strerror(errno) ) );
00342 return QString();
00343 }
00344
00345 return QString( revision+1 );
00346 }
00347
00348 QString OTDriver::getRevCsr( unsigned short rev) {
00349
00350 int i;
00351
00352 for (i = 0; csr_map[i].str; i++)
00353 if (csr_map[i].rev == rev) {
00354 return QString( csr_map[i].str );
00355 }
00356
00357 return tr( "Unknown firmware" );
00358 }
00359
00360 int OTDriver::reset() {
00361
00362 if( ! open() ) {
00363 return 0;
00364 }
00365
00366 if( ioctl(fd(), HCIDEVRESET, devId()) < 0 ) {
00367 if( errno != EALREADY ) {
00368 emit error( tr( "Reset failed for %1. %2 : %3" ).
00369 arg( devname() ).
00370 arg( errno ).
00371 arg( strerror(errno) ) );
00372 if (errno == EACCES) {
00373 return EACCES;
00374 }
00375 }
00376 }
00377 return 0;
00378 }
00379
00380 void OTDriver::setUp( bool M ) {
00381 if( M && ! isUp() ) {
00382 bringUp();
00383 } else if( ! M && isUp() ) {
00384 bringDown();
00385 }
00386 }
00387
00388 void OTDriver::bringUp() {
00389
00390 odebug << "bringUp : " << Dev << oendl;
00391
00392 if( ! open() ) {
00393 return;
00394 }
00395
00396 if (! isUp()) {
00397 if( ioctl(fd(), HCIDEVUP, devId()) < 0 ) {
00398 if( errno != EALREADY ) {
00399 emit error( tr( "Cannot bring interface %1 up. %2 : %3" ).
00400 arg( devname() ).
00401 arg( errno ).
00402 arg( strerror(errno) ) );
00403 }
00404 return;
00405 }
00406
00407 QTimer::singleShot( 3000, this, SLOT( reinit() ) );
00408 }
00409 }
00410
00411 void OTDriver::bringDown() {
00412
00413 odebug << "bringDown : " << Dev << oendl;
00414
00415 if( ! open() ) {
00416 return;
00417 }
00418
00419 if ( isUp() ) {
00420 if( ioctl(fd(), HCIDEVDOWN, devId()) < 0 ) {
00421 if( errno != EALREADY ) {
00422 emit error( tr( "Cannot bring interface %1 down. %2 : %3" ).
00423 arg( devname() ).
00424 arg( errno ).
00425 arg( strerror(errno) ) );
00426 }
00427 return;
00428 }
00429 reinit();
00430 }
00431 }
00432
00433 void OTDriver::setScanMode(bool iscan, bool pscan) {
00434
00435 struct hci_dev_req dr;
00436
00437 if( ! open() ) {
00438 return;
00439 }
00440
00441 dr.dev_id = devId();
00442 dr.dev_opt = SCAN_DISABLED;
00443
00444 if( iscan&&(!pscan) )
00445 dr.dev_opt = SCAN_INQUIRY;
00446 else if( pscan&&(!iscan) )
00447 dr.dev_opt = SCAN_PAGE;
00448 else if( pscan&&iscan )
00449 dr.dev_opt = SCAN_PAGE | SCAN_INQUIRY;
00450
00451 if( ioctl(fd(), HCISETSCAN, (unsigned long)&dr) < 0 ) {
00452 if( errno != EALREADY ) {
00453 emit error( tr( "Can't set scan mode on %1. %2 : %3" ).
00454 arg( devname() ).
00455 arg( errno ).
00456 arg( strerror(errno) ) );
00457 }
00458 return;
00459 }
00460
00461 reinit();
00462 }
00463
00464 void OTDriver::changeDevName(const char* name) {
00465
00466 if( ! open() ) {
00467 return;
00468 }
00469
00470 if (hci_write_local_name(fd(), name, 1000) < 0) {
00471 emit error( tr( "Can't change local name on %1. %2 : %3" ).
00472 arg( devname() ).
00473 arg( errno ).
00474 arg( strerror(errno) ) );
00475 }
00476 }
00477
00478 void OTDriver::changeAuthentication(bool _auth) {
00479 struct hci_dev_req dr;
00480
00481 if( ! open() ) {
00482 return;
00483 }
00484
00485 dr.dev_id = devId();
00486 dr.dev_opt = _auth?AUTH_ENABLED:AUTH_DISABLED;
00487
00488 if (ioctl(fd(),HCISETAUTH,(unsigned long)&dr) < 0) {
00489 if( errno != EALREADY ) {
00490 emit error( tr( "Can't change authentication on %1. %2 : %3" ).
00491 arg( devname() ).
00492 arg( errno ).
00493 arg( strerror(errno) ) );
00494 }
00495 return;
00496 }
00497 reinit();
00498 }
00499
00500 void OTDriver::changeEncryption(bool _encrypt) {
00501 struct hci_dev_req dr;
00502
00503 if( ! open() ) {
00504 return;
00505 }
00506
00507 dr.dev_id = devId();
00508 dr.dev_opt = _encrypt?ENCRYPT_P2P:ENCRYPT_DISABLED;
00509
00510 if (ioctl(fd(),HCISETENCRYPT,(unsigned long)&dr) < 0) {
00511 if( errno != EALREADY ) {
00512 emit error( tr( "Can't change encryption on %1. %2 : %3" ).
00513 arg( devname() ).
00514 arg( errno ).
00515 arg( strerror(errno) ) );
00516 }
00517 return;
00518 }
00519
00520 reinit();
00521 }
00522
00523 void OTDriver::changeClass ( unsigned char service,
00524 unsigned char major,
00525 unsigned char minor ) {
00526 unsigned long cod = 0;
00527 cod = (service << 16) |
00528 (major << 8) |
00529 (minor ) ;
00530
00531 if( ! open() ) {
00532 return;
00533 }
00534
00535 if ( hci_write_class_of_dev(fd(),cod,1000) < 0 ) {
00536 emit error( tr( "Can't change class informations for %1. %2 : %3" ).
00537 arg( devname() ).
00538 arg( errno ).
00539 arg( strerror(errno) ) );
00540 return;
00541 }
00542 }
00543
00544 void OTDriver::getClass( QString & service,
00545 QString & device ) {
00546 unsigned char cls[3];
00547
00548 if( ! open() ) {
00549 return;
00550 }
00551
00552 if ( hci_read_class_of_dev(fd(),cls,1000) < 0 ) {
00553 emit error( tr( "Can't read class information for %1. %2 : %3" ).
00554 arg( devname() ).
00555 arg( errno ).
00556 arg( strerror(errno) ) );
00557 return;
00558 }
00559
00560 if( cls[2] ) {
00561 int first = 1;
00562 for ( unsigned int s = 0; s < sizeof(*services); s++) {
00563 if (cls[2] & (1 << s)) {
00564 if( !first )
00565 service += ", ";
00566 service += services[s];
00567 first = 0;
00568 }
00569 }
00570 } else {
00571 service = "unspecified";
00572 }
00573
00574 MainClassMap_t * MCM = MainClasses;
00575 int major = cls[1] & 0x1f;
00576 int minor = cls[0] >> 2;
00577
00578 if( (unsigned)(cls[1] & 0x1f) > sizeof(*major_devices)) {
00579 device = tr("Invalid Device Class");
00580 return;
00581 }
00582
00583 device = major_devices[cls[1] & 0x1f];
00584
00585 while( MCM->Major != -1 ) {
00586 if( major == MCM->Major ) {
00587
00588 ClassMap_t * CM = MCM->Map;
00589 if( MCM->Map ) {
00590 while( CM->Minor != -1 ) {
00591 if( minor == CM->Minor ) {
00592 break;
00593 }
00594 CM ++;
00595 }
00596 device = CM->Description;
00597 } else {
00598
00599 if( major == 3 ) {
00600
00601 if( minor == 0 ) {
00602 device = "Uncategorized";
00603 } else {
00604 switch( minor / 8 ) {
00605 case 0:
00606 device = "Fully available";
00607 break;
00608 case 1:
00609 device = "1-17% utilized";
00610 break;
00611 case 2:
00612 device = "17-33% utilized";
00613 break;
00614 case 3:
00615 device = "33-50% utilized";
00616 break;
00617 case 4:
00618 device = "50-67% utilized";
00619 break;
00620 case 5:
00621 device = "67-83% utilized";
00622 break;
00623 case 6:
00624 device = "83-99% utilized";
00625 break;
00626 case 7:
00627 device = "No service available";
00628 break;
00629 }
00630 }
00631 } else if( major == 6 ) {
00632 if (minor & 4)
00633 device = "Display";
00634 if (minor & 8)
00635 device = "Camera";
00636 if (minor & 16)
00637 device = "Scanner";
00638 if (minor & 32)
00639 device = "Printer";
00640 }
00641 }
00642 break;
00643 }
00644 MCM ++;
00645 }
00646
00647 if( MCM->Major == -1 ) {
00648 device = "Unknown (reserved) minor device class";
00649 }
00650 }
00651
00652 QString OTDriver::strType() {
00653 return QString( hci_dtypetostr(Type) );
00654 }
00655
00656 void OTDriver::setFeatures( unsigned char * _f) {
00657 Features = lmp_featurestostr(_f, NULL, 255);
00658 }
00659
00660 void OTDriver::setManufacturer(int compid) {
00661 Manufacturer = bt_compidtostr(compid);
00662 }
00663
00664 OTHCISocket * OTDriver::openSocket( void ) {
00665 if( ! Socket ) {
00666 odebug << "Open HCI socket to " << devname() << oendl;
00667 Socket = new OTHCISocket( this );
00668 }
00669 return Socket;
00670 }
00671
00672 void OTDriver::closeSocket( void ) {
00673 if( Socket ) {
00674 odebug << "Close HCI socket to " << devname() << oendl;
00675 delete Socket;
00676 Socket = 0;
00677 }
00678 }
00679
00680 QString OTDriver::getPeerName( const OTDeviceAddress & PAddr ) {
00681 QString S;
00682 char name[100 ];
00683
00684 if( ! open() ) {
00685 return QString("N/A");
00686 }
00687
00688 if( hci_read_remote_name( fd(),
00689 &(PAddr.getBDAddr()),
00690 sizeof(name),
00691 name,
00692 100000 ) < 0 ) {
00693 return QString( "N/A" );
00694 }
00695
00696 return QString( name );
00697 }
00698
00699 long OTDriver::getLinkQuality( const OTDeviceAddress & Addr ) {
00700 struct hci_conn_info_req *cr;
00701 struct hci_request rq;
00702 read_rssi_rp rp;
00703 uint16_t handle;
00704
00705 if( ! open() ) {
00706 return 0;
00707 }
00708
00709 cr = (struct hci_conn_info_req *)malloc(
00710 sizeof(*cr) + sizeof(struct hci_conn_info));
00711 if (!cr)
00712 return 0;
00713
00714 bacpy( &(cr->bdaddr), &(Addr.getBDAddr()) );
00715 cr->type = ACL_LINK;
00716
00717 if (ioctl( fd(), HCIGETCONNINFO, (unsigned long) cr) < 0) {
00718 odebug << "Get NetworkSetup info failed" << oendl;
00719 free(cr);
00720 return 0;
00721 }
00722
00723 handle = htobs(cr->conn_info->handle);
00724
00725 free(cr);
00726
00727 memset(&rq, 0, sizeof(rq));
00728 rq.ogf = OGF_STATUS_PARAM;
00729 rq.ocf = OCF_READ_RSSI;
00730 rq.cparam = &handle;
00731 rq.clen = 2;
00732 rq.rparam = &rp;
00733 rq.rlen = GET_LINK_QUALITY_RP_SIZE;
00734
00735 if (hci_send_req( fd(), &rq, 100) < 0) {
00736 odebug << "Get NetworkSetup info failed" << oendl;
00737 return 0;
00738 }
00739
00740 if( rp.status ) {
00741 odebug << QString().sprintf("HCI get_link_quality cmd failed (0x%2.2X)", rp.status) << oendl;
00742 return 0;
00743 }
00744
00745 return rp.rssi+50;
00746 }