summaryrefslogtreecommitdiff
path: root/noncore/settings/networksettings2/opietooth2/OTDriver.cpp
Unidiff
Diffstat (limited to 'noncore/settings/networksettings2/opietooth2/OTDriver.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/settings/networksettings2/opietooth2/OTDriver.cpp744
1 files changed, 744 insertions, 0 deletions
diff --git a/noncore/settings/networksettings2/opietooth2/OTDriver.cpp b/noncore/settings/networksettings2/opietooth2/OTDriver.cpp
new file mode 100644
index 0000000..8bd7919
--- a/dev/null
+++ b/noncore/settings/networksettings2/opietooth2/OTDriver.cpp
@@ -0,0 +1,744 @@
1/***************************************************************************
2 * Copyright (C) 2003 by Mattia Merzi *
3 * ottobit@ferrara.linux.it *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 ***************************************************************************/
10
11#include <opie2/odebug.h>
12#include <qtimer.h>
13
14#include <sys/poll.h>
15#include <bluezlib.h>
16
17#include <OTGateway.h>
18#include <OTDriver.h>
19#include <OTHCISocket.h>
20
21using namespace Opietooth2;
22
23static struct {
24 const char *str;
25 unsigned short rev;
26} csr_map[] = {
27 { "HCI 11.2 (bc01b)", 114 },
28 { "HCI 11.3 (bc01b)", 115 },
29 { "HCI 12.1 (bc01b)", 119 },
30 { "HCI 12.3 (bc01b)", 134 },
31 { "HCI 12.7 (bc01b)", 188 },
32 { "HCI 12.8 (bc01b)", 218 },
33 { "HCI 12.9 (bc01b)", 283 },
34 { "HCI 13.10 (bc01b)", 309 },
35 { "HCI 13.11 (bc01b)", 351 },
36 { "HCI 16.4 (bc01b)", 523 },
37 { "HCI 14.3 (bc02x)", 272 },
38 { "HCI 14.6 (bc02x)", 336 },
39 { "HCI 14.7 (bc02x)", 373 },
40 { "HCI 14.8 (bc02x)", 487 },
41 { "HCI 15.3 (bc02x)", 443 },
42 { "HCI 16.4 (bc02x)", 525 },
43 { NULL, 0}
44};
45
46static char *services[] = { "Positioning",
47 "Networking",
48 "Rendering",
49 "Capturing",
50 "Object Transfer",
51 "Audio",
52 "Telephony",
53 "Information" };
54
55static char *major_devices[] = { "Miscellaneous",
56 "Computer",
57 "Phone",
58 "LAN Access",
59 "Audio/Video",
60 "Peripheral",
61 "Imaging",
62 "Uncategorized" };
63
64
65typedef struct {
66 short Minor;
67 const char * Description;
68} ClassMap_t;
69
70static ClassMap_t MapMiscClass[] = {
71 { -1, "" }
72};
73
74static ClassMap_t MapUnclassifiedClass[] = {
75 { -1, "" }
76};
77
78static ClassMap_t MapComputerClass[] = {
79 { 0, "Uncategorized" } ,
80 { 1, "Desktop workstation" } ,
81 { 2, "Server" } ,
82 { 3, "Laptop" } ,
83 { 4, "Handheld" } ,
84 { 5, "Palm" } ,
85 { 6, "Wearable" },
86 { -1, 0 }
87};
88
89static ClassMap_t MapPhoneClass[] = {
90 { 0, "Uncategorized" },
91 { 1, "Cellular" },
92 { 2, "Cordless" },
93 { 3, "Smart phone" },
94 { 4, "Wired modem or voice gateway" },
95 { 5, "Common ISDN Access" },
96 { 6, "Sim Card Reader" },
97 { -1, 0 }
98};
99
100static ClassMap_t MapAVClass[] = {
101 { 0, "Uncategorized" },
102 { 1, "Device conforms to the Headset profile" },
103 { 2, "Hands-free" },
104 { 3, 0 },
105 { 4, "Microphone" },
106 { 5, "Loudspeaker" },
107 { 6, "Headphones" },
108 { 7, "Portable Audio" },
109 { 8, "Car Audio" },
110 { 9, "Set-top box" },
111 { 10, "HiFi Audio Device" },
112 { 11, "VCR" },
113 { 12, "Video Camera" },
114 { 13, "Camcorder" },
115 { 14, "Video Monitor" },
116 { 15, "Video Display and Loudspeaker" },
117 { 16, "Video Conferencing" },
118 { 17, 0 },
119 { 18, "Gaming/Toy" },
120 { -1, 0 }
121};
122
123static ClassMap_t MapPeripheralClass[] = {
124 { 16, "Keyboard" },
125 { 32, "Pointing device" },
126 { 48, "Combo keyboard/pointing device" },
127 { -1, 0 }
128};
129
130typedef struct {
131 int Major;
132 ClassMap_t * Map;
133} MainClassMap_t;
134
135static MainClassMap_t MainClasses[] = {
136 { 0, MapMiscClass },
137 { 1, MapComputerClass },
138 { 2, MapPhoneClass },
139 { 3, 0 }, // special case
140 { 4, MapAVClass },
141 { 5, MapPeripheralClass },
142 { 6, 0 }, // special case
143 { 63, MapUnclassifiedClass },
144 { -1, 0 }
145};
146
147OTDriver::OTDriver( OTGateway * _OT, struct hci_dev_info* di) : QObject( _OT ), Address() {
148 OT = _OT;
149 IsUp = 0;
150 Socket = 0;
151
152 init(di);
153 owarn << "Driver " << devname() << oendl;
154
155 AutoClose = new QTimer( this );
156 connect( AutoClose,
157 SIGNAL( timeout() ),
158 this,
159 SLOT( SLOT_CloseFd() )
160 );
161}
162
163OTDriver::~OTDriver() {
164 closeSocket();
165 SLOT_CloseFd();
166}
167
168void OTDriver::SLOT_CloseFd( void ){
169 if ( isOpen() ) {
170 AutoClose->stop();
171 ::close( fd() );
172 setfd( -1 );
173 }
174}
175
176void OTDriver::init(struct hci_dev_info* di) {
177
178 Dev = di->name;
179
180 setDevId(di->dev_id);
181 setType(di->type);
182 setFlags(di->flags);
183 Address.setBDAddr( di->bdaddr );
184 setFeatures(di->features);
185 setfd( -1 ); // not open
186
187 Manufacturer = "";
188}
189
190// internal reinitialize
191void OTDriver::reinit() {
192 bool Old;
193 Old = IsUp;
194
195 if( currentState() < 0 )
196 return;
197
198 if( Old != IsUp ) {
199 // state changes
200 emit stateChange( this, IsUp );
201 }
202}
203
204// requested by application
205int OTDriver::currentState() {
206 struct hci_dev_info di;
207
208 // uint16_t tmp_dev_id = device_info.dev_id;
209 // bzero(&device_info,sizeof(struct hci_dev_info));
210 // device_info.dev_id = tmp_dev_id;
211
212 memset( &di, 0, sizeof( di ) );
213 di.dev_id = Dev_id;
214 if( ioctl( OT->getSocket(), HCIGETDEVINFO, (void*)&di) < 0 ) {
215 SLOT_CloseFd();
216 return -1;
217 } else {
218 // load new info
219 init(&di);
220 }
221
222 return IsUp;
223}
224
225bool OTDriver::open() {
226
227 // (re)start single shot close
228 AutoClose->start( 30000, TRUE );
229
230 if( isOpen() )
231 // is open
232 return 1;
233
234 setfd(hci_open_dev(devId()));
235
236 if (fd() < 0) {
237 emit error( tr( "Can't open device %1. %2 : %3" ).
238 arg( devname() ).
239 arg( errno ).
240 arg( strerror(errno) )
241 );
242 return 0;
243 }
244
245 return 1;
246}
247
248QString OTDriver::name() {
249 char name[1000];
250
251 if( ! open() ) {
252 return tr("Cannot open");
253 }
254
255 if (hci_read_local_name( fd(), sizeof(name), name, 1000) < 0) {
256 if (errno != ETIMEDOUT) {
257 emit error( tr("Can't read local name on %1. %2 : %3. Default to %4" ).
258 arg( devname() ).
259 arg( errno ).
260 arg( strerror(errno) ).
261 arg( devname() )
262 );
263 } // ETIMEDOUT error is quite normal, device is down ... I think ! :)
264 strcpy(name,devname().latin1());
265 }
266 return QString(name);
267}
268
269void OTDriver::setFlags(unsigned long flags) {
270
271 // kdDebug() << "Setting OTDriver Values ..." << endl;
272 IsUp = BTVALUE(hci_test_bit(HCI_UP, &flags));
273
274 if (isUp()) {
275 setIScan(BTVALUE(hci_test_bit(HCI_ISCAN, &flags)));
276 setPScan(BTVALUE(hci_test_bit(HCI_PSCAN, &flags)));
277 setAuthentication(BTVALUE(hci_test_bit(HCI_AUTH, &flags)));
278 setEncryption(BTVALUE(hci_test_bit(HCI_ENCRYPT, &flags)));
279 } else {
280 setIScan(BT_UNKNOWN);
281 setPScan(BT_UNKNOWN);
282 setAuthentication(BT_UNKNOWN);
283 setEncryption(BT_UNKNOWN);
284 }
285}
286
287QString OTDriver::revision() {
288
289 struct hci_version ver;
290
291 if( ! open() ) {
292 return tr("Cannot open");
293 }
294
295 if (hci_read_local_version(fd(), &ver, 1000) < 0) {
296 emit error( tr( "Can't read revision info on %1. %2 : %3" ).
297 arg( devname() ).
298 arg( errno ).
299 arg( strerror(errno) ) );
300 return QString();
301 }
302
303 setManufacturer(ver.manufacturer);
304
305 switch (ver.manufacturer) {
306 case 0:
307 return getRevEricsson();
308 break;
309 case 10:
310 return getRevCsr(ver.hci_rev);
311 break;
312 default:
313 return tr( "Unsupported manufacturer" );
314 break;
315 }
316}
317
318QString OTDriver::getRevEricsson() {
319
320 char revision[102];
321 struct hci_request rq;
322
323 if( ! open() ) {
324 return QString( "Cannot open" );
325 }
326
327 memset(&rq, 0, sizeof(rq));
328 rq.ogf = 0x3f;
329 rq.ocf = 0x000f;
330 rq.cparam = NULL;
331 rq.clen = 0;
332 rq.rparam = &revision;
333 rq.rlen = sizeof(revision);
334
335 if (hci_send_req(fd(), &rq, 1000) < 0) {
336 emit error( tr( "Can't read revision info on %1. %2 : %3" ).
337 arg( devname() ).
338 arg( errno ).
339 arg( strerror(errno) ) );
340 return QString();
341 }
342
343 return QString( revision+1 );
344}
345
346QString OTDriver::getRevCsr( unsigned short rev) {
347
348 int i;
349
350 for (i = 0; csr_map[i].str; i++)
351 if (csr_map[i].rev == rev) {
352 return QString( csr_map[i].str );
353 }
354
355 return tr( "Unknown firmware" );
356}
357
358int OTDriver::reset() {
359
360 if( ! open() ) {
361 return 0;
362 }
363
364 if( ioctl(fd(), HCIDEVRESET, devId()) < 0 ) {
365 if( errno != EALREADY ) {
366 emit error( tr( "Reset failed for %1. %2 : %3" ).
367 arg( devname() ).
368 arg( errno ).
369 arg( strerror(errno) ) );
370 if (errno == EACCES) {
371 return EACCES;
372 }
373 }
374 }
375 return 0;
376}
377
378void OTDriver::setUp( bool M ) {
379 if( M && ! isUp() ) {
380 bringUp();
381 } else if( ! M && isUp() ) {
382 bringDown();
383 }
384}
385
386void OTDriver::bringUp() {
387
388 owarn << "bringUp : " << Dev << oendl;
389
390 if( ! open() ) {
391 return;
392 }
393
394 if (! isUp()) {
395 if( ioctl(fd(), HCIDEVUP, devId()) < 0 ) {
396 if( errno != EALREADY ) {
397 emit error( tr( "Cannot bring interface %1 up. %2 : %3" ).
398 arg( devname() ).
399 arg( errno ).
400 arg( strerror(errno) ) );
401 }
402 return;
403 }
404 // have to wait a bit for the 'up' to become active
405 QTimer::singleShot( 3000, this, SLOT( reinit() ) );
406 }
407}
408
409void OTDriver::bringDown() {
410
411 owarn << "bringDown : " << Dev << oendl;
412
413 if( ! open() ) {
414 return;
415 }
416
417 if ( isUp() ) {
418 if( ioctl(fd(), HCIDEVDOWN, devId()) < 0 ) {
419 if( errno != EALREADY ) {
420 emit error( tr( "Cannot bring interface %1 down. %2 : %3" ).
421 arg( devname() ).
422 arg( errno ).
423 arg( strerror(errno) ) );
424 }
425 return;
426 }
427 reinit();
428 }
429}
430
431void OTDriver::setScanMode(bool iscan, bool pscan) {
432
433 struct hci_dev_req dr;
434
435 if( ! open() ) {
436 return;
437 }
438
439 dr.dev_id = devId();
440 dr.dev_opt = SCAN_DISABLED;
441
442 if( iscan&&(!pscan) )
443 dr.dev_opt = SCAN_INQUIRY;
444 else if( pscan&&(!iscan) )
445 dr.dev_opt = SCAN_PAGE;
446 else if( pscan&&iscan )
447 dr.dev_opt = SCAN_PAGE | SCAN_INQUIRY;
448
449 if( ioctl(fd(), HCISETSCAN, (unsigned long)&dr) < 0 ) {
450 if( errno != EALREADY ) {
451 emit error( tr( "Can't set scan mode on %1. %2 : %3" ).
452 arg( devname() ).
453 arg( errno ).
454 arg( strerror(errno) ) );
455 }
456 return;
457 }
458
459 reinit();
460}
461
462void OTDriver::changeDevName(const char* name) {
463
464 if( ! open() ) {
465 return;
466 }
467
468 if (hci_write_local_name(fd(), name, 1000) < 0) {
469 emit error( tr( "Can't change local name on %1. %2 : %3" ).
470 arg( devname() ).
471 arg( errno ).
472 arg( strerror(errno) ) );
473 }
474}
475
476void OTDriver::changeAuthentication(bool _auth) {
477 struct hci_dev_req dr;
478
479 if( ! open() ) {
480 return;
481 }
482
483 dr.dev_id = devId();
484 dr.dev_opt = _auth?AUTH_ENABLED:AUTH_DISABLED;
485
486 if (ioctl(fd(),HCISETAUTH,(unsigned long)&dr) < 0) {
487 if( errno != EALREADY ) {
488 emit error( tr( "Can't change authentication on %1. %2 : %3" ).
489 arg( devname() ).
490 arg( errno ).
491 arg( strerror(errno) ) );
492 }
493 return;
494 }
495 reinit();
496}
497
498void OTDriver::changeEncryption(bool _encrypt) {
499 struct hci_dev_req dr;
500
501 if( ! open() ) {
502 return;
503 }
504
505 dr.dev_id = devId();
506 dr.dev_opt = _encrypt?ENCRYPT_P2P:ENCRYPT_DISABLED;
507
508 if (ioctl(fd(),HCISETENCRYPT,(unsigned long)&dr) < 0) {
509 if( errno != EALREADY ) {
510 emit error( tr( "Can't change encryption on %1. %2 : %3" ).
511 arg( devname() ).
512 arg( errno ).
513 arg( strerror(errno) ) );
514 }
515 return;
516 }
517
518 reinit();
519}
520
521void OTDriver::changeClass ( unsigned char service,
522 unsigned char major,
523 unsigned char minor ) {
524 unsigned long cod = 0;
525 cod = (service << 16) |
526 (major << 8) |
527 (minor ) ;
528
529 if( ! open() ) {
530 return;
531 }
532
533 if ( hci_write_class_of_dev(fd(),cod,1000) < 0 ) {
534 emit error( tr( "Can't change class informations for %1. %2 : %3" ).
535 arg( devname() ).
536 arg( errno ).
537 arg( strerror(errno) ) );
538 return;
539 }
540}
541
542void OTDriver::getClass( QString & service,
543 QString & device ) {
544 unsigned char cls[3];
545
546 if( ! open() ) {
547 return;
548 }
549
550 if ( hci_read_class_of_dev(fd(),cls,1000) < 0 ) {
551 emit error( tr( "Can't read class information for %1. %2 : %3" ).
552 arg( devname() ).
553 arg( errno ).
554 arg( strerror(errno) ) );
555 return;
556 }
557
558 if( cls[2] ) {
559 int first = 1;
560 for ( unsigned int s = 0; s < sizeof(*services); s++) {
561 if (cls[2] & (1 << s)) {
562 if( !first )
563 service += ", ";
564 service += services[s];
565 first = 0;
566 }
567 }
568 } else {
569 service = "unspecified";
570 }
571
572 MainClassMap_t * MCM = MainClasses;
573 int major = cls[1] & 0x1f;
574 int minor = cls[0] >> 2;
575
576 if( (unsigned)(cls[1] & 0x1f) > sizeof(*major_devices)) {
577 device = tr("Invalid Device Class");
578 return;
579 }
580
581 device = major_devices[cls[1] & 0x1f];
582
583 while( MCM->Major != -1 ) {
584 if( major == MCM->Major ) {
585 // this class
586 ClassMap_t * CM = MCM->Map;
587 if( MCM->Map ) {
588 while( CM->Minor != -1 ) {
589 if( minor == CM->Minor ) {
590 break;
591 }
592 CM ++;
593 }
594 device = CM->Description;
595 } else {
596 // special case
597 if( major == 3 ) {
598 /* lan access */
599 if( minor == 0 ) {
600 device = "Uncategorized";
601 } else {
602 switch( minor / 8 ) {
603 case 0:
604 device = "Fully available";
605 break;
606 case 1:
607 device = "1-17% utilized";
608 break;
609 case 2:
610 device = "17-33% utilized";
611 break;
612 case 3:
613 device = "33-50% utilized";
614 break;
615 case 4:
616 device = "50-67% utilized";
617 break;
618 case 5:
619 device = "67-83% utilized";
620 break;
621 case 6:
622 device = "83-99% utilized";
623 break;
624 case 7:
625 device = "No service available";
626 break;
627 }
628 }
629 } else if( major == 6 ) { /* imaging */
630 if (minor & 4)
631 device = "Display";
632 if (minor & 8)
633 device = "Camera";
634 if (minor & 16)
635 device = "Scanner";
636 if (minor & 32)
637 device = "Printer";
638 }
639 }
640 break;
641 }
642 MCM ++;
643 }
644
645 if( MCM->Major == -1 ) {
646 device = "Unknown (reserved) minor device class";
647 }
648}
649
650QString OTDriver::strType() {
651 return QString( hci_dtypetostr(Type) );
652}
653
654void OTDriver::setFeatures( unsigned char * _f) {
655 Features = lmp_featurestostr(_f, NULL, 255);
656}
657
658void OTDriver::setManufacturer(int compid) {
659 Manufacturer = bt_compidtostr(compid);
660}
661
662OTHCISocket * OTDriver::openSocket( void ) {
663 if( ! Socket ) {
664 owarn << "Open HCI socket to " << devname() << oendl;
665 Socket = new OTHCISocket( this );
666 }
667 return Socket;
668}
669
670void OTDriver::closeSocket( void ) {
671 if( Socket ) {
672 owarn << "Close HCI socket to " << devname() << oendl;
673 delete Socket;
674 Socket = 0;
675 }
676}
677
678QString OTDriver::getPeerName( const OTDeviceAddress & PAddr ) {
679 QString S;
680 char name[100 ];
681
682 if( ! open() ) {
683 return QString("N/A");
684 }
685
686 if( hci_read_remote_name( fd(),
687 &(PAddr.getBDAddr()),
688 sizeof(name),
689 name,
690 100000 ) < 0 ) {
691 return QString( "N/A" );
692 }
693
694 return QString( name );
695}
696
697long OTDriver::getLinkQuality( const OTDeviceAddress & Addr ) {
698 struct hci_conn_info_req *cr;
699 struct hci_request rq;
700 read_rssi_rp rp;
701 uint16_t handle;
702
703 if( ! open() ) {
704 return 0;
705 }
706
707 cr = (struct hci_conn_info_req *)malloc(
708 sizeof(*cr) + sizeof(struct hci_conn_info));
709 if (!cr)
710 return 0;
711
712 bacpy( &(cr->bdaddr), &(Addr.getBDAddr()) );
713 cr->type = ACL_LINK;
714
715 if (ioctl( fd(), HCIGETCONNINFO, (unsigned long) cr) < 0) {
716 owarn << "Get connection info failed" << oendl;
717 free(cr);
718 return 0;
719 }
720
721 handle = htobs(cr->conn_info->handle);
722
723 free(cr);
724
725 memset(&rq, 0, sizeof(rq));
726 rq.ogf = OGF_STATUS_PARAM;
727 rq.ocf = OCF_READ_RSSI;
728 rq.cparam = &handle;
729 rq.clen = 2;
730 rq.rparam = &rp;
731 rq.rlen = GET_LINK_QUALITY_RP_SIZE;
732
733 if (hci_send_req( fd(), &rq, 100) < 0) {
734 owarn << "Get connection info failed" << oendl;
735 return 0;
736 }
737
738 if( rp.status ) {
739 owarn << QString().sprintf("HCI get_link_quality cmd failed (0x%2.2X)", rp.status) << oendl;
740 return 0;
741 }
742
743 return rp.rssi+50;
744}