Diffstat (limited to 'libopie2/opiebluez/obluetooth.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r-- | libopie2/opiebluez/obluetooth.cpp | 137 |
1 files changed, 130 insertions, 7 deletions
diff --git a/libopie2/opiebluez/obluetooth.cpp b/libopie2/opiebluez/obluetooth.cpp index e0ba0ec..80f4bfc 100644 --- a/libopie2/opiebluez/obluetooth.cpp +++ b/libopie2/opiebluez/obluetooth.cpp | |||
@@ -112,140 +112,263 @@ void OBluetooth::synchronize() | |||
112 | return; | 112 | return; |
113 | } | 113 | } |
114 | 114 | ||
115 | for ( int i = 0; i < dl->dev_num; ++i ) | 115 | for ( int i = 0; i < dl->dev_num; ++i ) |
116 | { | 116 | { |
117 | di.dev_id = ( dr + i )->dev_id; | 117 | di.dev_id = ( dr + i )->dev_id; |
118 | if ( ::ioctl( _fd, HCIGETDEVINFO, (void *) &di ) == -1 ) | 118 | if ( ::ioctl( _fd, HCIGETDEVINFO, (void *) &di ) == -1 ) |
119 | { | 119 | { |
120 | owarn << "OBluetooth::synchronize() - can't issue HCIGETDEVINFO on device " << i << " (" << strerror( errno ) << ") - skipping that device. " << oendl; | 120 | owarn << "OBluetooth::synchronize() - can't issue HCIGETDEVINFO on device " << i << " (" << strerror( errno ) << ") - skipping that device. " << oendl; |
121 | continue; | 121 | continue; |
122 | } | 122 | } |
123 | odebug << "OBluetooth::synchronize() - found device #" << di.dev_id << oendl; | 123 | odebug << "OBluetooth::synchronize() - found device #" << di.dev_id << oendl; |
124 | _interfaces.insert( di.name, new OBluetoothInterface( this, di.name, (void*) &di, _fd ) ); | 124 | _interfaces.insert( di.name, new OBluetoothInterface( this, di.name, (void*) &di, _fd ) ); |
125 | } | 125 | } |
126 | } | 126 | } |
127 | 127 | ||
128 | /*====================================================================================== | 128 | /*====================================================================================== |
129 | * OBluetoothInterface | 129 | * OBluetoothInterface |
130 | *======================================================================================*/ | 130 | *======================================================================================*/ |
131 | 131 | ||
132 | class OBluetoothInterface::Private | 132 | class OBluetoothInterface::Private |
133 | { | 133 | { |
134 | public: | 134 | public: |
135 | Private( struct hci_dev_info* di, int fd ) | 135 | Private( struct hci_dev_info* di, int fd ) |
136 | { | 136 | { |
137 | ::memcpy( &devinfo, di, sizeof(struct hci_dev_info) ); | 137 | ::memcpy( &devinfo, di, sizeof(struct hci_dev_info) ); |
138 | ctlfd = fd; | 138 | ctlfd = fd; |
139 | } | 139 | } |
140 | void reloadInfo() | 140 | void reloadInfo() |
141 | { | 141 | { |
142 | int result = ::ioctl( ctlfd, HCIGETDEVINFO, (void *) &devinfo ); | 142 | int result = ::ioctl( ctlfd, HCIGETDEVINFO, (void *) &devinfo ); |
143 | if ( result == -1 ) | 143 | if ( result == -1 ) |
144 | { | 144 | { |
145 | owarn << "OBluetoothInterface::Private - can't reload device info (" << strerror( errno ) << ")" << oendl; | 145 | owarn << "OBluetoothInterface::Private - can't reload device info (" << strerror( errno ) << ")" << oendl; |
146 | } | 146 | } |
147 | } | 147 | } |
148 | struct hci_dev_info devinfo; | 148 | struct hci_dev_info devinfo; |
149 | int ctlfd; | 149 | int ctlfd; |
150 | }; | 150 | }; |
151 | 151 | ||
152 | OBluetoothInterface::OBluetoothInterface( QObject* parent, const char* name, void* devinfo, int ctlfd ) | 152 | OBluetoothInterface::OBluetoothInterface( QObject* parent, const char* name, void* devinfo, int ctlfd ) |
153 | :QObject( parent, name ) | 153 | :QObject( parent, name ) |
154 | { | 154 | { |
155 | d = new OBluetoothInterface::Private( (struct hci_dev_info*) devinfo, ctlfd ); | 155 | d = new OBluetoothInterface::Private( (struct hci_dev_info*) devinfo, ctlfd ); |
156 | } | 156 | } |
157 | 157 | ||
158 | OBluetoothInterface::~OBluetoothInterface() | 158 | OBluetoothInterface::~OBluetoothInterface() |
159 | { | 159 | { |
160 | } | 160 | } |
161 | 161 | ||
162 | QString OBluetoothInterface::macAddress() const | 162 | QString OBluetoothInterface::macAddress() const |
163 | { | 163 | { |
164 | return QString().sprintf( "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X", | 164 | return QString().sprintf( "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X", |
165 | d->devinfo.bdaddr.b[5], | 165 | d->devinfo.bdaddr.b[5], |
166 | d->devinfo.bdaddr.b[4], | 166 | d->devinfo.bdaddr.b[4], |
167 | d->devinfo.bdaddr.b[3], | 167 | d->devinfo.bdaddr.b[3], |
168 | d->devinfo.bdaddr.b[2], | 168 | d->devinfo.bdaddr.b[2], |
169 | d->devinfo.bdaddr.b[1], | 169 | d->devinfo.bdaddr.b[1], |
170 | d->devinfo.bdaddr.b[0] ); | 170 | d->devinfo.bdaddr.b[0] ); |
171 | } | 171 | } |
172 | 172 | ||
173 | bool OBluetoothInterface::setUp( bool b ) | 173 | bool OBluetoothInterface::setUp( bool b ) |
174 | { | 174 | { |
175 | int cmd = b ? HCIDEVUP : HCIDEVDOWN; | 175 | int cmd = b ? HCIDEVUP : HCIDEVDOWN; |
176 | int result = ::ioctl( d->ctlfd, cmd, d->devinfo.dev_id ); | 176 | int result = ::ioctl( d->ctlfd, cmd, d->devinfo.dev_id ); |
177 | if ( result == -1 && errno != EALREADY ) | 177 | if ( result == -1 && errno != EALREADY ) |
178 | { | 178 | { |
179 | owarn << "OBluetoothInterface::setUp( " << b << " ) - couldn't change interface state (" << strerror( errno ) << ")" << oendl; | 179 | owarn << "OBluetoothInterface::setUp( " << b << " ) - couldn't change interface state (" << strerror( errno ) << ")" << oendl; |
180 | return false; | 180 | return false; |
181 | } | 181 | } |
182 | else | 182 | else |
183 | { | 183 | { |
184 | d->reloadInfo(); | 184 | d->reloadInfo(); |
185 | return true; | 185 | return true; |
186 | } | 186 | } |
187 | } | 187 | } |
188 | 188 | ||
189 | bool OBluetoothInterface::isUp() const | 189 | bool OBluetoothInterface::isUp() const |
190 | { | 190 | { |
191 | return hci_test_bit( HCI_UP, &d->devinfo.flags ); | 191 | return hci_test_bit( HCI_UP, &d->devinfo.flags ); |
192 | } | 192 | } |
193 | 193 | ||
194 | OBluetoothInterface::DeviceIterator OBluetoothInterface::neighbourhood() | 194 | OBluetoothInterface::DeviceIterator OBluetoothInterface::neighbourhood() |
195 | { | 195 | { |
196 | _devices.clear(); | 196 | _devices.clear(); |
197 | struct hci_inquiry_req* ir; | 197 | struct hci_inquiry_req* ir; |
198 | int nrsp = 255; | 198 | int nrsp = 255; |
199 | 199 | ||
200 | char* mybuffer = static_cast<char*>( malloc( sizeof( *ir ) + ( sizeof( inquiry_info ) * (nrsp) ) ) ); | 200 | char* mybuffer = static_cast<char*>( malloc( sizeof( *ir ) + ( sizeof( inquiry_info ) * (nrsp) ) ) ); |
201 | assert( mybuffer ); | 201 | assert( mybuffer ); |
202 | 202 | ||
203 | ir = (struct hci_inquiry_req*) mybuffer; | 203 | ir = (struct hci_inquiry_req*) mybuffer; |
204 | memset( ir, 0, sizeof( *ir ) + ( sizeof( inquiry_info ) * (nrsp) ) ); | 204 | memset( ir, 0, sizeof( *ir ) + ( sizeof( inquiry_info ) * (nrsp) ) ); |
205 | 205 | ||
206 | ir->dev_id = d->devinfo.dev_id; | 206 | ir->dev_id = d->devinfo.dev_id; |
207 | ir->num_rsp = nrsp; | 207 | ir->num_rsp = nrsp; |
208 | ir->length = 8; | 208 | ir->length = 8; // 10 seconds |
209 | ir->flags = 0; | 209 | ir->flags = 0; |
210 | ir->lap[0] = 0x33; | 210 | ir->lap[0] = 0x33; // GIAC |
211 | ir->lap[1] = 0x8b; | 211 | ir->lap[1] = 0x8b; |
212 | ir->lap[2] = 0x9e; | 212 | ir->lap[2] = 0x9e; |
213 | 213 | ||
214 | int result = ::ioctl( d->ctlfd, HCIINQUIRY, mybuffer ); | 214 | int result = ::ioctl( d->ctlfd, HCIINQUIRY, mybuffer ); |
215 | if ( result == -1 ) | 215 | if ( result == -1 ) |
216 | { | 216 | { |
217 | owarn << "OBluetoothInterface::neighbourhood() - can't issue HCIINQUIRY (" << strerror( errno ) << ")" << oendl; | 217 | owarn << "OBluetoothInterface::neighbourhood() - can't issue HCIINQUIRY (" << strerror( errno ) << ")" << oendl; |
218 | return DeviceIterator( _devices ); | 218 | return DeviceIterator( _devices ); |
219 | } | 219 | } |
220 | 220 | ||
221 | for( int i = 0; i < ir->num_rsp; ++i ) | 221 | inquiry_info* ii = (inquiry_info*)( ir+1 ); |
222 | |||
223 | for ( int i = 0; i < ir->num_rsp; ++i ) | ||
222 | { | 224 | { |
223 | odebug << "found a device" << oendl; | 225 | OBluetoothDevice* dev = new OBluetoothDevice( this, 0, ii ); |
226 | _devices.insert( dev->macAddress(), dev ); | ||
227 | ++ii; | ||
224 | } | 228 | } |
225 | 229 | ||
226 | return DeviceIterator( _devices ); | 230 | return DeviceIterator( _devices ); |
227 | } | 231 | } |
228 | 232 | ||
229 | |||
230 | /*====================================================================================== | 233 | /*====================================================================================== |
231 | * OBluetoothDevice | 234 | * OBluetoothDevice |
232 | *======================================================================================*/ | 235 | *======================================================================================*/ |
233 | 236 | ||
234 | OBluetoothDevice::OBluetoothDevice( QObject* parent, const char* name ) | 237 | class OBluetoothDevice::Private |
238 | { | ||
239 | public: | ||
240 | Private( inquiry_info* ii ) | ||
241 | { | ||
242 | ::memcpy( &inqinfo, ii, sizeof(inquiry_info) ); | ||
243 | } | ||
244 | inquiry_info inqinfo; | ||
245 | }; | ||
246 | |||
247 | OBluetoothDevice::OBluetoothDevice( QObject* parent, const char* name, void* inqinfo ) | ||
235 | :QObject( parent, name ) | 248 | :QObject( parent, name ) |
236 | { | 249 | { |
237 | odebug << "OBluetoothDevice::OBluetoothDevice() - '" << name << "'" << oendl; | 250 | odebug << "OBluetoothDevice::OBluetoothDevice() - '" << name << "'" << oendl; |
251 | d = new OBluetoothDevice::Private( (inquiry_info*) inqinfo ); | ||
238 | } | 252 | } |
239 | 253 | ||
240 | OBluetoothDevice::~OBluetoothDevice() | 254 | OBluetoothDevice::~OBluetoothDevice() |
241 | { | 255 | { |
242 | odebug << "OBluetoothDevice::~OBluetoothDevice()" << oendl; | 256 | odebug << "OBluetoothDevice::~OBluetoothDevice()" << oendl; |
243 | } | 257 | } |
244 | 258 | ||
245 | QString OBluetoothDevice::macAddress() const | 259 | QString OBluetoothDevice::macAddress() const |
246 | { | 260 | { |
247 | return "N/A"; | 261 | return QString().sprintf( "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X", |
262 | d->inqinfo.bdaddr.b[5], | ||
263 | d->inqinfo.bdaddr.b[4], | ||
264 | d->inqinfo.bdaddr.b[3], | ||
265 | d->inqinfo.bdaddr.b[2], | ||
266 | d->inqinfo.bdaddr.b[1], | ||
267 | d->inqinfo.bdaddr.b[0] ); | ||
268 | } | ||
269 | |||
270 | QString OBluetoothDevice::deviceClass() const | ||
271 | { | ||
272 | int maj = d->inqinfo.dev_class[1] & 0x1f; | ||
273 | int min = d->inqinfo.dev_class[0] >> 2; | ||
274 | |||
275 | QString major = QString( "Unknown(%1)" ).arg( maj ); | ||
276 | QString minor = QString( "Unknown(%1)" ).arg( min ); | ||
277 | |||
278 | switch ( maj ) | ||
279 | { | ||
280 | case 0: major = "Miscellaneous"; | ||
281 | break; | ||
282 | |||
283 | case 1: major = "Computer"; | ||
284 | switch ( min ) | ||
285 | { | ||
286 | case 0: minor = "Uncategorized"; | ||
287 | case 1: minor = "Desktop workstation"; | ||
288 | case 2: minor = "Server"; | ||
289 | case 3: minor = "Laptop"; | ||
290 | case 4: minor = "Handheld"; | ||
291 | case 5: minor = "Palm"; | ||
292 | case 6: minor = "Wearable"; | ||
293 | } | ||
294 | break; | ||
295 | |||
296 | case 2: major = "Phone"; | ||
297 | switch ( min ) | ||
298 | { | ||
299 | case 0: minor = "Uncategorized"; break; | ||
300 | case 1: minor = "Cellular"; break; | ||
301 | case 2: minor = "Cordless"; break; | ||
302 | case 3: minor = "Smart phone"; break; | ||
303 | case 4: minor = "Wired modem or voice gateway"; break; | ||
304 | case 5: minor = "Common ISDN Access"; break; | ||
305 | case 6: minor = "Sim Card Reader"; break; | ||
306 | } | ||
307 | break; | ||
308 | |||
309 | case 3: major = "LAN Access"; | ||
310 | break; | ||
311 | |||
312 | case 4: major = "Audio/Video"; | ||
313 | switch ( min ) | ||
314 | { | ||
315 | case 0: minor = "Uncategorized"; break; | ||
316 | case 1: minor = "Device conforms to the Headset profile"; break; | ||
317 | case 2: minor = "Hands-free"; break; | ||
318 | case 3: minor = "Reserved(3)"; break; | ||
319 | case 4: minor = "Microphone"; break; | ||
320 | case 5: minor = "Loudspeaker"; break; | ||
321 | case 6: minor = "Headphones"; break; | ||
322 | case 7: minor = "Portable Audio"; break; | ||
323 | case 8: minor = "Car Audio"; break; | ||
324 | case 9: minor = "Set-top box"; break; | ||
325 | case 10: minor = "HiFi Audio Device"; break; | ||
326 | case 11: minor = "VCR"; break; | ||
327 | case 12: minor = "Video Camera"; break; | ||
328 | case 13: minor = "Camcorder"; break; | ||
329 | case 14: minor = "Video Monitor"; break; | ||
330 | case 15: minor = "Video Display and Loudspeaker"; break; | ||
331 | case 16: minor = "Video Conferencing"; break; | ||
332 | case 17: minor = "Reserved(17)"; break; | ||
333 | case 18: minor = "Gaming/Toy"; break; | ||
334 | } | ||
335 | break; | ||
336 | |||
337 | case 5: major = "Peripheral"; | ||
338 | switch ( min ) | ||
339 | { | ||
340 | case 16: minor = "Keyboard"; break; | ||
341 | case 32: minor = "Pointing Device"; break; | ||
342 | case 48: minor = "Keyboard and Pointing Device"; break; | ||
343 | } | ||
344 | break; | ||
345 | |||
346 | case 6: major = "Imaging"; | ||
347 | if (min & 4) minor = "Display"; | ||
348 | else if (min & 8) minor = "Camera"; | ||
349 | else if (min & 16) minor = "Scanner"; | ||
350 | else if (min & 32) minor = "Printer"; | ||
351 | break; | ||
352 | |||
353 | case 63: major = "Uncategorized"; | ||
354 | break; | ||
355 | } | ||
356 | |||
357 | return QString( "%1:%2" ).arg( major ).arg( minor ); | ||
248 | } | 358 | } |
249 | 359 | ||
360 | QString OBluetoothDevice::getName() | ||
361 | { | ||
362 | /* FIXME: Uahhh, this gets ugly. | ||
363 | The BlueZ kernel interface seems to be very badly (if at all) documented. | ||
364 | All people are assuming that you use libbluetooth to talk to that stack. | ||
365 | However since libbluetooth is GPL, we can't do that :/ | ||
366 | Guess, we are stuck here until someone finds time and/or motivation to look | ||
367 | into that and create some easy-to-understand examples for how to talk | ||
368 | directly to the BlueZ kernel interface. | ||
369 | */ | ||
370 | }; | ||
371 | |||
372 | |||
250 | } | 373 | } |
251 | } | 374 | } |