00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include "obluetooth.h"
00031
00032
00033 #include <opie2/odebug.h>
00034 using namespace Opie::Core;
00035
00036
00037 #include <bluetooth/bluetooth.h>
00038 #include <bluetooth/hci.h>
00039 #include <bluetooth/hci_lib.h>
00040 #include <assert.h>
00041 #include <errno.h>
00042 #include <stdlib.h>
00043 #include <string.h>
00044 #include <unistd.h>
00045 #include <sys/ioctl.h>
00046 #include <sys/types.h>
00047 #include <sys/socket.h>
00048
00049 namespace Opie {
00050 namespace Bluez {
00051
00052
00053
00054
00055
00056 OBluetooth* OBluetooth::_instance = 0;
00057
00058 OBluetooth::OBluetooth()
00059 {
00060 synchronize();
00061 }
00062
00063 OBluetooth* OBluetooth::instance()
00064 {
00065 if ( !_instance ) _instance = new OBluetooth();
00066 return _instance;
00067 }
00068
00069 OBluetooth::InterfaceIterator OBluetooth::iterator() const
00070 {
00071 return OBluetooth::InterfaceIterator( _interfaces );
00072 }
00073
00074 int OBluetooth::count() const
00075 {
00076 return _interfaces.count();
00077 }
00078
00079 OBluetoothInterface* OBluetooth::interface( const QString& iface ) const
00080 {
00081 return _interfaces[iface];
00082 }
00083
00084 void OBluetooth::synchronize()
00085 {
00086 odebug << "OBluetooth::synchronize() - gathering available HCI devices" << oendl;
00087 _interfaces.clear();
00088
00089 _fd = ::socket( AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI );
00090 if ( _fd == -1 )
00091 {
00092 owarn << "OBluetooth::synchronize() - can't open HCI control socket (" << strerror( errno ) << ")" << oendl;
00093 return;
00094 }
00095
00096 struct hci_dev_list_req *dl;
00097 struct hci_dev_req *dr;
00098 struct hci_dev_info di;
00099
00100 if (!(dl = (struct hci_dev_list_req*)malloc(HCI_MAX_DEV * sizeof(struct hci_dev_req) + sizeof(uint16_t))))
00101 {
00102 ofatal << "OBluetooth::synchronize() - can't allocate memory for HCI request" << oendl;
00103 return;
00104 }
00105
00106 dl->dev_num = HCI_MAX_DEV;
00107 dr = dl->dev_req;
00108
00109 if (::ioctl( _fd, HCIGETDEVLIST, (void *) dl) == -1)
00110 {
00111 owarn << "OBluetooth::synchronize() - can't complete HCIGETDEVLIST (" << strerror( errno ) << ")" << oendl;
00112 return;
00113 }
00114
00115 for ( int i = 0; i < dl->dev_num; ++i )
00116 {
00117 di.dev_id = ( dr + i )->dev_id;
00118 if ( ::ioctl( _fd, HCIGETDEVINFO, (void *) &di ) == -1 )
00119 {
00120 owarn << "OBluetooth::synchronize() - can't issue HCIGETDEVINFO on device " << i << " (" << strerror( errno ) << ") - skipping that device. " << oendl;
00121 continue;
00122 }
00123 odebug << "OBluetooth::synchronize() - found device #" << di.dev_id << oendl;
00124 _interfaces.insert( di.name, new OBluetoothInterface( this, di.name, (void*) &di, _fd ) );
00125 }
00126 }
00127
00128
00129
00130
00131
00132 class OBluetoothInterface::Private
00133 {
00134 public:
00135 Private( struct hci_dev_info* di, int fd )
00136 {
00137 ::memcpy( &devinfo, di, sizeof(struct hci_dev_info) );
00138 ctlfd = fd;
00139 }
00140 void reloadInfo()
00141 {
00142 int result = ::ioctl( ctlfd, HCIGETDEVINFO, (void *) &devinfo );
00143 if ( result == -1 )
00144 {
00145 owarn << "OBluetoothInterface::Private - can't reload device info (" << strerror( errno ) << ")" << oendl;
00146 }
00147 }
00148 struct hci_dev_info devinfo;
00149 int ctlfd;
00150 };
00151
00152 OBluetoothInterface::OBluetoothInterface( QObject* parent, const char* name, void* devinfo, int ctlfd )
00153 :QObject( parent, name )
00154 {
00155 d = new OBluetoothInterface::Private( (struct hci_dev_info*) devinfo, ctlfd );
00156 }
00157
00158 OBluetoothInterface::~OBluetoothInterface()
00159 {
00160 }
00161
00162 QString OBluetoothInterface::macAddress() const
00163 {
00164 return QString().sprintf( "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X",
00165 d->devinfo.bdaddr.b[5],
00166 d->devinfo.bdaddr.b[4],
00167 d->devinfo.bdaddr.b[3],
00168 d->devinfo.bdaddr.b[2],
00169 d->devinfo.bdaddr.b[1],
00170 d->devinfo.bdaddr.b[0] );
00171 }
00172
00173 bool OBluetoothInterface::setUp( bool b )
00174 {
00175 int cmd = b ? HCIDEVUP : HCIDEVDOWN;
00176 int result = ::ioctl( d->ctlfd, cmd, d->devinfo.dev_id );
00177 if ( result == -1 && errno != EALREADY )
00178 {
00179 owarn << "OBluetoothInterface::setUp( " << b << " ) - couldn't change interface state (" << strerror( errno ) << ")" << oendl;
00180 return false;
00181 }
00182 else
00183 {
00184 d->reloadInfo();
00185 return true;
00186 }
00187 }
00188
00189 bool OBluetoothInterface::isUp() const
00190 {
00191 return hci_test_bit( HCI_UP, &d->devinfo.flags );
00192 }
00193
00194 OBluetoothInterface::DeviceIterator OBluetoothInterface::neighbourhood()
00195 {
00196 _devices.clear();
00197 struct hci_inquiry_req* ir;
00198 int nrsp = 255;
00199
00200 char* mybuffer = static_cast<char*>( malloc( sizeof( *ir ) + ( sizeof( inquiry_info ) * (nrsp) ) ) );
00201 assert( mybuffer );
00202
00203 ir = (struct hci_inquiry_req*) mybuffer;
00204 memset( ir, 0, sizeof( *ir ) + ( sizeof( inquiry_info ) * (nrsp) ) );
00205
00206 ir->dev_id = d->devinfo.dev_id;
00207 ir->num_rsp = nrsp;
00208 ir->length = 8;
00209 ir->flags = 0;
00210 ir->lap[0] = 0x33;
00211 ir->lap[1] = 0x8b;
00212 ir->lap[2] = 0x9e;
00213
00214 int result = ::ioctl( d->ctlfd, HCIINQUIRY, mybuffer );
00215 if ( result == -1 )
00216 {
00217 owarn << "OBluetoothInterface::neighbourhood() - can't issue HCIINQUIRY (" << strerror( errno ) << ")" << oendl;
00218 return DeviceIterator( _devices );
00219 }
00220
00221 inquiry_info* ii = (inquiry_info*)( ir+1 );
00222
00223 for ( int i = 0; i < ir->num_rsp; ++i )
00224 {
00225 OBluetoothDevice* dev = new OBluetoothDevice( this, 0, ii );
00226 _devices.insert( dev->macAddress(), dev );
00227 ++ii;
00228 }
00229
00230 return DeviceIterator( _devices );
00231 }
00232
00233
00234
00235
00236
00237 class OBluetoothDevice::Private
00238 {
00239 public:
00240 Private( inquiry_info* ii )
00241 {
00242 ::memcpy( &inqinfo, ii, sizeof(inquiry_info) );
00243 }
00244 inquiry_info inqinfo;
00245 };
00246
00247 OBluetoothDevice::OBluetoothDevice( QObject* parent, const char* name, void* inqinfo )
00248 :QObject( parent, name )
00249 {
00250 odebug << "OBluetoothDevice::OBluetoothDevice() - '" << name << "'" << oendl;
00251 d = new OBluetoothDevice::Private( (inquiry_info*) inqinfo );
00252 }
00253
00254 OBluetoothDevice::~OBluetoothDevice()
00255 {
00256 odebug << "OBluetoothDevice::~OBluetoothDevice()" << oendl;
00257 }
00258
00259 QString OBluetoothDevice::macAddress() const
00260 {
00261 return QString().sprintf( "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X",
00262 d->inqinfo.bdaddr.b[5],
00263 d->inqinfo.bdaddr.b[4],
00264 d->inqinfo.bdaddr.b[3],
00265 d->inqinfo.bdaddr.b[2],
00266 d->inqinfo.bdaddr.b[1],
00267 d->inqinfo.bdaddr.b[0] );
00268 }
00269
00270 QString OBluetoothDevice::deviceClass() const
00271 {
00272 int maj = d->inqinfo.dev_class[1] & 0x1f;
00273 int min = d->inqinfo.dev_class[0] >> 2;
00274
00275 QString major = QString( "Unknown(%1)" ).arg( maj );
00276 QString minor = QString( "Unknown(%1)" ).arg( min );
00277
00278 switch ( maj )
00279 {
00280 case 0: major = "Miscellaneous";
00281 break;
00282
00283 case 1: major = "Computer";
00284 switch ( min )
00285 {
00286 case 0: minor = "Uncategorized";
00287 case 1: minor = "Desktop workstation";
00288 case 2: minor = "Server";
00289 case 3: minor = "Laptop";
00290 case 4: minor = "Handheld";
00291 case 5: minor = "Palm";
00292 case 6: minor = "Wearable";
00293 }
00294 break;
00295
00296 case 2: major = "Phone";
00297 switch ( min )
00298 {
00299 case 0: minor = "Uncategorized"; break;
00300 case 1: minor = "Cellular"; break;
00301 case 2: minor = "Cordless"; break;
00302 case 3: minor = "Smart phone"; break;
00303 case 4: minor = "Wired modem or voice gateway"; break;
00304 case 5: minor = "Common ISDN Access"; break;
00305 case 6: minor = "Sim Card Reader"; break;
00306 }
00307 break;
00308
00309 case 3: major = "LAN Access";
00310 break;
00311
00312 case 4: major = "Audio/Video";
00313 switch ( min )
00314 {
00315 case 0: minor = "Uncategorized"; break;
00316 case 1: minor = "Device conforms to the Headset profile"; break;
00317 case 2: minor = "Hands-free"; break;
00318 case 3: minor = "Reserved(3)"; break;
00319 case 4: minor = "Microphone"; break;
00320 case 5: minor = "Loudspeaker"; break;
00321 case 6: minor = "Headphones"; break;
00322 case 7: minor = "Portable Audio"; break;
00323 case 8: minor = "Car Audio"; break;
00324 case 9: minor = "Set-top box"; break;
00325 case 10: minor = "HiFi Audio Device"; break;
00326 case 11: minor = "VCR"; break;
00327 case 12: minor = "Video Camera"; break;
00328 case 13: minor = "Camcorder"; break;
00329 case 14: minor = "Video Monitor"; break;
00330 case 15: minor = "Video Display and Loudspeaker"; break;
00331 case 16: minor = "Video Conferencing"; break;
00332 case 17: minor = "Reserved(17)"; break;
00333 case 18: minor = "Gaming/Toy"; break;
00334 }
00335 break;
00336
00337 case 5: major = "Peripheral";
00338 switch ( min )
00339 {
00340 case 16: minor = "Keyboard"; break;
00341 case 32: minor = "Pointing Device"; break;
00342 case 48: minor = "Keyboard and Pointing Device"; break;
00343 }
00344 break;
00345
00346 case 6: major = "Imaging";
00347 if (min & 4) minor = "Display";
00348 else if (min & 8) minor = "Camera";
00349 else if (min & 16) minor = "Scanner";
00350 else if (min & 32) minor = "Printer";
00351 break;
00352
00353 case 63: major = "Uncategorized";
00354 break;
00355 }
00356
00357 return QString( "%1:%2" ).arg( major ).arg( minor );
00358 }
00359
00360 QString OBluetoothDevice::getName()
00361 {
00362
00363
00364
00365
00366
00367
00368
00369
00370 };
00371
00372
00373 }
00374 }