1/* 2 * Copyright 2007 Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com 3 * Copyright 2008 Mika Lindqvist, monni1995_at_gmail.com 4 * Copyright 2012 Fredrik Mod��en, [firstname]@[lastname] 5 * All rights reserved. Distributed under the terms of the MIT License. 6 */ 7 8 9#include <bluetooth/bluetooth_error.h> 10 11#include <bluetooth/HCI/btHCI_command.h> 12#include <bluetooth/HCI/btHCI_event.h> 13 14#include <bluetooth/DeviceClass.h> 15#include <bluetooth/DiscoveryAgent.h> 16#include <bluetooth/LocalDevice.h> 17#include <bluetooth/RemoteDevice.h> 18 19#include <bluetooth/bdaddrUtils.h> 20#include <bluetoothserver_p.h> 21#include <CommandManager.h> 22 23#include <new> 24 25#include "KitSupport.h" 26 27 28namespace Bluetooth { 29 30 31LocalDevice* 32LocalDevice::RequestLocalDeviceID(BMessage* request) 33{ 34 BMessage reply; 35 hci_id hid; 36 LocalDevice* lDevice = NULL; 37 38 BMessenger* messenger = _RetrieveBluetoothMessenger(); 39 40 if (messenger == NULL) 41 return NULL; 42 43 if (messenger->SendMessage(request, &reply) == B_OK 44 && reply.FindInt32("hci_id", &hid) == B_OK ) { 45 46 if (hid >= 0) 47 lDevice = new (std::nothrow)LocalDevice(hid); 48 } 49 50 delete messenger; 51 return lDevice; 52} 53 54 55#if 0 56#pragma - 57#endif 58 59 60LocalDevice* 61LocalDevice::GetLocalDevice() 62{ 63 BMessage request(BT_MSG_ACQUIRE_LOCAL_DEVICE); 64 65 return RequestLocalDeviceID(&request); 66} 67 68 69LocalDevice* 70LocalDevice::GetLocalDevice(const hci_id hid) 71{ 72 BMessage request(BT_MSG_ACQUIRE_LOCAL_DEVICE); 73 request.AddInt32("hci_id", hid); 74 75 return RequestLocalDeviceID(&request); 76} 77 78 79LocalDevice* 80LocalDevice::GetLocalDevice(const bdaddr_t bdaddr) 81{ 82 BMessage request(BT_MSG_ACQUIRE_LOCAL_DEVICE); 83 request.AddData("bdaddr", B_ANY_TYPE, &bdaddr, sizeof(bdaddr_t)); 84 85 return RequestLocalDeviceID(&request); 86} 87 88 89uint32 90LocalDevice::GetLocalDeviceCount() 91{ 92 BMessenger* messenger = _RetrieveBluetoothMessenger(); 93 uint32 count = 0; 94 95 if (messenger != NULL) { 96 97 BMessage request(BT_MSG_COUNT_LOCAL_DEVICES); 98 BMessage reply; 99 100 if (messenger->SendMessage(&request, &reply) == B_OK) 101 count = reply.FindInt32("count"); 102 103 delete messenger; 104 } 105 106 return count; 107 108} 109 110 111DiscoveryAgent* 112LocalDevice::GetDiscoveryAgent() 113{ 114 // TODO: Study a singleton here 115 return new (std::nothrow)DiscoveryAgent(this); 116} 117 118 119BString 120LocalDevice::GetProperty(const char* property) 121{ 122 return NULL; 123 124} 125 126 127status_t 128LocalDevice::GetProperty(const char* property, uint32* value) 129{ 130 if (fMessenger == NULL) 131 return B_ERROR; 132 133 BMessage request(BT_MSG_GET_PROPERTY); 134 BMessage reply; 135 136 request.AddInt32("hci_id", fHid); 137 request.AddString("property", property); 138 139 if (fMessenger->SendMessage(&request, &reply) == B_OK) { 140 if (reply.FindInt32("result", (int32*)value ) == B_OK ) { 141 return B_OK; 142 143 } 144 } 145 146 return B_ERROR; 147} 148 149 150int 151LocalDevice::GetDiscoverable() 152{ 153 if (fMessenger == NULL) 154 return -1; 155 156 size_t size; 157 void* command = buildReadScan(&size); 158 if (command == NULL) 159 return -1; 160 161 BMessage request(BT_MSG_HANDLE_SIMPLE_REQUEST); 162 request.AddInt32("hci_id", fHid); 163 request.AddData("raw command", B_ANY_TYPE, command, size); 164 request.AddInt16("eventExpected", HCI_EVENT_CMD_COMPLETE); 165 request.AddInt16("opcodeExpected", PACK_OPCODE(OGF_CONTROL_BASEBAND, 166 OCF_READ_SCAN_ENABLE)); 167 168 int8 discoverable; 169 BMessage reply; 170 if (fMessenger->SendMessage(&request, &reply) == B_OK 171 && reply.FindInt8("scan_enable", &discoverable) == B_OK) 172 return discoverable; 173 174 return -1; 175} 176 177 178status_t 179LocalDevice::SetDiscoverable(int mode) 180{ 181 if (fMessenger == NULL) 182 return B_ERROR; 183 184 BMessage request(BT_MSG_HANDLE_SIMPLE_REQUEST); 185 BMessage reply; 186 187 size_t size; 188 int8 bt_status = BT_ERROR; 189 190 request.AddInt32("hci_id", fHid); 191 192 193 void* command = buildWriteScan(mode, &size); 194 195 if (command == NULL) { 196 return B_NO_MEMORY; 197 } 198 199 request.AddData("raw command", B_ANY_TYPE, command, size); 200 request.AddInt16("eventExpected", HCI_EVENT_CMD_COMPLETE); 201 request.AddInt16("opcodeExpected", PACK_OPCODE(OGF_CONTROL_BASEBAND, 202 OCF_WRITE_SCAN_ENABLE)); 203 204 if (fMessenger->SendMessage(&request, &reply) == B_OK) { 205 if (reply.FindInt8("status", &bt_status ) == B_OK ) { 206 return bt_status; 207 208 } 209 } 210 211 return B_ERROR; 212} 213 214 215struct authentication_t { 216 uint8 param; 217}; 218 219 220status_t 221LocalDevice::SetAuthentication(bool authentication) 222{ 223 return SingleParameterCommandRequest<struct authentication_t, uint8> 224 (OGF_CONTROL_BASEBAND, OCF_WRITE_AUTH_ENABLE, authentication, 225 NULL, fHid, fMessenger); 226} 227 228 229bdaddr_t 230LocalDevice::GetBluetoothAddress() 231{ 232 if (fMessenger == NULL) 233 return bdaddrUtils::LocalAddress(); 234 235 size_t size; 236 void* command = buildReadBdAddr(&size); 237 238 if (command == NULL) 239 return bdaddrUtils::LocalAddress(); 240 241 const bdaddr_t* bdaddr; 242 BMessage request(BT_MSG_HANDLE_SIMPLE_REQUEST); 243 BMessage reply; 244 ssize_t ssize; 245 246 request.AddInt32("hci_id", fHid); 247 request.AddData("raw command", B_ANY_TYPE, command, size); 248 request.AddInt16("eventExpected", HCI_EVENT_CMD_COMPLETE); 249 request.AddInt16("opcodeExpected", PACK_OPCODE(OGF_INFORMATIONAL_PARAM, 250 OCF_READ_BD_ADDR)); 251 252 if (fMessenger->SendMessage(&request, &reply) == B_OK 253 && reply.FindData("bdaddr", B_ANY_TYPE, 0, 254 (const void**)&bdaddr, &ssize) == B_OK) 255 return *bdaddr; 256 257 return bdaddrUtils::LocalAddress(); 258} 259 260 261hci_id 262LocalDevice::ID(void) const 263{ 264 return fHid; 265} 266 267 268BString 269LocalDevice::GetFriendlyName() 270{ 271 if (fMessenger == NULL) 272 return BString("Unknown|Messenger"); 273 274 size_t size; 275 void* command = buildReadLocalName(&size); 276 if (command == NULL) 277 return BString("Unknown|NoMemory"); 278 279 BString friendlyname; 280 BMessage request(BT_MSG_HANDLE_SIMPLE_REQUEST); 281 BMessage reply; 282 283 284 request.AddInt32("hci_id", fHid); 285 request.AddData("raw command", B_ANY_TYPE, command, size); 286 request.AddInt16("eventExpected", HCI_EVENT_CMD_COMPLETE); 287 request.AddInt16("opcodeExpected", PACK_OPCODE(OGF_CONTROL_BASEBAND, 288 OCF_READ_LOCAL_NAME)); 289 290 if (fMessenger->SendMessage(&request, &reply) == B_OK 291 && reply.FindString("friendlyname", &friendlyname) == B_OK) 292 return friendlyname; 293 294 return BString("Unknown|ServerFailed"); 295} 296 297 298status_t 299LocalDevice::SetFriendlyName(BString& name) 300{ 301 int8 btStatus = BT_ERROR; 302 303 if (fMessenger == NULL) 304 return btStatus; 305 306 BluetoothCommand<typed_command(hci_write_local_name)> 307 writeName(OGF_CONTROL_BASEBAND, OCF_WRITE_LOCAL_NAME); 308 309 strcpy(writeName->local_name, name.String()); 310 311 BMessage request(BT_MSG_HANDLE_SIMPLE_REQUEST); 312 BMessage reply; 313 314 request.AddInt32("hci_id", fHid); 315 request.AddData("raw command", B_ANY_TYPE, 316 writeName.Data(), writeName.Size()); 317 request.AddInt16("eventExpected", HCI_EVENT_CMD_COMPLETE); 318 request.AddInt16("opcodeExpected", PACK_OPCODE(OGF_CONTROL_BASEBAND, 319 OCF_WRITE_LOCAL_NAME)); 320 321 if (fMessenger->SendMessage(&request, &reply) == B_OK) 322 reply.FindInt8("status", &btStatus); 323 324 return btStatus; 325} 326 327 328DeviceClass 329LocalDevice::GetDeviceClass() 330{ 331 332// if (fDeviceClass.IsUnknownDeviceClass()) { 333 334 if (fMessenger == NULL) 335 return fDeviceClass; 336 337 size_t size; 338 void* command = buildReadClassOfDevice(&size); 339 if (command == NULL) 340 return fDeviceClass; 341 342 BMessage request(BT_MSG_HANDLE_SIMPLE_REQUEST); 343 BMessage reply; 344 const uint8* bufferRecord; 345 ssize_t ssize; 346 347 request.AddInt32("hci_id", fHid); 348 request.AddData("raw command", B_ANY_TYPE, command, size); 349 request.AddInt16("eventExpected", HCI_EVENT_CMD_COMPLETE); 350 request.AddInt16("opcodeExpected", PACK_OPCODE(OGF_CONTROL_BASEBAND, 351 OCF_READ_CLASS_OF_DEV)); 352 353 if (fMessenger->SendMessage(&request, &reply) == B_OK 354 && reply.FindData("devclass", B_ANY_TYPE, 0, (const void**)&bufferRecord, 355 &ssize) == B_OK) { 356 uint8 record[3] = { bufferRecord[0], bufferRecord[1], bufferRecord[2] }; 357 fDeviceClass.SetRecord(record); 358 } 359// } 360 361 return fDeviceClass; 362 363} 364 365 366status_t 367LocalDevice::SetDeviceClass(DeviceClass deviceClass) 368{ 369 int8 bt_status = BT_ERROR; 370 371 if (fMessenger == NULL) 372 return bt_status; 373 374 BluetoothCommand<typed_command(hci_write_dev_class)> 375 setDeviceClass(OGF_CONTROL_BASEBAND, OCF_WRITE_CLASS_OF_DEV); 376 377 setDeviceClass->dev_class[0] = deviceClass.Record() & 0xFF; 378 setDeviceClass->dev_class[1] = (deviceClass.Record() & 0xFF00) >> 8; 379 setDeviceClass->dev_class[2] = (deviceClass.Record() & 0xFF0000) >> 16; 380 381 BMessage request(BT_MSG_HANDLE_SIMPLE_REQUEST); 382 BMessage reply; 383 384 request.AddInt32("hci_id", fHid); 385 request.AddData("raw command", B_ANY_TYPE, 386 setDeviceClass.Data(), setDeviceClass.Size()); 387 request.AddInt16("eventExpected", HCI_EVENT_CMD_COMPLETE); 388 request.AddInt16("opcodeExpected", PACK_OPCODE(OGF_CONTROL_BASEBAND, 389 OCF_WRITE_CLASS_OF_DEV)); 390 391 if (fMessenger->SendMessage(&request, &reply) == B_OK) 392 reply.FindInt8("status", &bt_status); 393 394 return bt_status; 395 396} 397 398 399status_t 400LocalDevice::_ReadLocalVersion() 401{ 402 int8 bt_status = BT_ERROR; 403 404 BluetoothCommand<> localVersion(OGF_INFORMATIONAL_PARAM, 405 OCF_READ_LOCAL_VERSION); 406 407 BMessage request(BT_MSG_HANDLE_SIMPLE_REQUEST); 408 BMessage reply; 409 410 request.AddInt32("hci_id", fHid); 411 request.AddData("raw command", B_ANY_TYPE, 412 localVersion.Data(), localVersion.Size()); 413 request.AddInt16("eventExpected", HCI_EVENT_CMD_COMPLETE); 414 request.AddInt16("opcodeExpected", PACK_OPCODE(OGF_INFORMATIONAL_PARAM, 415 OCF_READ_LOCAL_VERSION)); 416 417 if (fMessenger->SendMessage(&request, &reply) == B_OK) 418 reply.FindInt8("status", &bt_status); 419 420 return bt_status; 421} 422 423 424status_t 425LocalDevice::_ReadBufferSize() 426{ 427 int8 bt_status = BT_ERROR; 428 429 BluetoothCommand<> BufferSize(OGF_INFORMATIONAL_PARAM, 430 OCF_READ_BUFFER_SIZE); 431 432 433 BMessage request(BT_MSG_HANDLE_SIMPLE_REQUEST); 434 BMessage reply; 435 436 request.AddInt32("hci_id", fHid); 437 request.AddData("raw command", B_ANY_TYPE, 438 BufferSize.Data(), BufferSize.Size()); 439 request.AddInt16("eventExpected", HCI_EVENT_CMD_COMPLETE); 440 request.AddInt16("opcodeExpected", PACK_OPCODE(OGF_INFORMATIONAL_PARAM, 441 OCF_READ_BUFFER_SIZE)); 442 443 if (fMessenger->SendMessage(&request, &reply) == B_OK) 444 reply.FindInt8("status", &bt_status); 445 446 return bt_status; 447} 448 449 450status_t 451LocalDevice::_ReadLocalFeatures() 452{ 453 int8 bt_status = BT_ERROR; 454 455 BluetoothCommand<> LocalFeatures(OGF_INFORMATIONAL_PARAM, 456 OCF_READ_LOCAL_FEATURES); 457 458 BMessage request(BT_MSG_HANDLE_SIMPLE_REQUEST); 459 BMessage reply; 460 461 request.AddInt32("hci_id", fHid); 462 request.AddData("raw command", B_ANY_TYPE, 463 LocalFeatures.Data(), LocalFeatures.Size()); 464 request.AddInt16("eventExpected", HCI_EVENT_CMD_COMPLETE); 465 request.AddInt16("opcodeExpected", PACK_OPCODE(OGF_INFORMATIONAL_PARAM, 466 OCF_READ_LOCAL_FEATURES)); 467 468 if (fMessenger->SendMessage(&request, &reply) == B_OK) 469 reply.FindInt8("status", &bt_status); 470 471 return bt_status; 472} 473 474 475status_t 476LocalDevice::_ReadLinkKeys() 477{ 478 int8 bt_status = BT_ERROR; 479 480 BluetoothCommand<> LocalFeatures(OGF_CONTROL_BASEBAND, 481 OCF_READ_STORED_LINK_KEY); 482 483 BMessage request(BT_MSG_HANDLE_SIMPLE_REQUEST); 484 BMessage reply; 485 486 request.AddInt32("hci_id", fHid); 487 request.AddData("raw command", B_ANY_TYPE, 488 LocalFeatures.Data(), LocalFeatures.Size()); 489 request.AddInt16("eventExpected", HCI_EVENT_CMD_COMPLETE); 490 request.AddInt16("opcodeExpected", PACK_OPCODE(OGF_CONTROL_BASEBAND, 491 OCF_READ_STORED_LINK_KEY)); 492 493 request.AddInt16("eventExpected", HCI_EVENT_RETURN_LINK_KEYS); 494 495 496 if (fMessenger->SendMessage(&request, &reply) == B_OK) 497 reply.FindInt8("status", &bt_status); 498 499 return bt_status; 500} 501 502 503struct pageTimeout_t { 504 uint16 param; 505}; 506 507 508status_t 509LocalDevice::_ReadTimeouts() 510{ 511 512 // Read PageTimeout 513 NonParameterCommandRequest(OGF_CONTROL_BASEBAND, 514 OCF_READ_PG_TIMEOUT, NULL, fHid, fMessenger); 515 516 // Write PageTimeout 517 SingleParameterCommandRequest<struct pageTimeout_t, uint16> 518 (OGF_CONTROL_BASEBAND, OCF_WRITE_PG_TIMEOUT, 0x8000, NULL, 519 fHid, fMessenger); 520 521 // Write PageTimeout 522 return SingleParameterCommandRequest<struct pageTimeout_t, uint16> 523 (OGF_CONTROL_BASEBAND, OCF_WRITE_CA_TIMEOUT, 0x7d00, NULL, 524 fHid, fMessenger); 525} 526 527 528status_t 529LocalDevice::Reset() 530{ 531 int8 bt_status = BT_ERROR; 532 533 BluetoothCommand<> Reset(OGF_CONTROL_BASEBAND, OCF_RESET); 534 535 BMessage request(BT_MSG_HANDLE_SIMPLE_REQUEST); 536 BMessage reply; 537 538 request.AddInt32("hci_id", fHid); 539 request.AddData("raw command", B_ANY_TYPE, Reset.Data(), Reset.Size()); 540 request.AddInt16("eventExpected", HCI_EVENT_CMD_COMPLETE); 541 request.AddInt16("opcodeExpected", PACK_OPCODE(OGF_CONTROL_BASEBAND, 542 OCF_RESET)); 543 544 if (fMessenger->SendMessage(&request, &reply) == B_OK) 545 reply.FindInt8("status", &bt_status); 546 547 return bt_status; 548 549} 550 551 552/* 553ServiceRecord 554LocalDevice::getRecord(Connection notifier) { 555 556} 557 558void 559LocalDevice::updateRecord(ServiceRecord srvRecord) { 560 561} 562*/ 563 564 565LocalDevice::LocalDevice(hci_id hid) 566 : 567 BluetoothDevice(), 568 fHid(hid) 569{ 570 fMessenger = _RetrieveBluetoothMessenger(); 571 572 _ReadBufferSize(); 573 _ReadLocalFeatures(); 574 _ReadLocalVersion(); 575 _ReadTimeouts(); 576 _ReadLinkKeys(); 577 578 // Uncomment this if you want your device to have a nicer default name 579 // BString name("HaikuBluetooth"); 580 // SetFriendlyName(name); 581 582 583 uint32 value; 584 585 // HARDCODE -> move this to addons 586 if (GetProperty("manufacturer", &value) == B_OK 587 && value == 15) { 588 589 // Uncomment this out if your Broadcom dongle is not working properly 590 // Reset(); // Perform a reset to Broadcom buggyland 591 592// Uncomment this out if your Broadcom dongle has a null bdaddr 593//#define BT_WRITE_BDADDR_FOR_BCM2035 594#ifdef BT_WRITE_BDADDR_FOR_BCM2035 595#warning Writting broadcom bdaddr @ init. 596 // try write bdaddr to a bcm2035 -> will be moved to an addon 597 int8 bt_status = BT_ERROR; 598 599 BluetoothCommand<typed_command(hci_write_bcm2035_bdaddr)> 600 writeAddress(OGF_VENDOR_CMD, OCF_WRITE_BCM2035_BDADDR); 601 602 BMessage request(BT_MSG_HANDLE_SIMPLE_REQUEST); 603 BMessage reply; 604 writeAddress->bdaddr.b[0] = 0x3C; 605 writeAddress->bdaddr.b[1] = 0x19; 606 writeAddress->bdaddr.b[2] = 0x30; 607 writeAddress->bdaddr.b[3] = 0xC9; 608 writeAddress->bdaddr.b[4] = 0x03; 609 writeAddress->bdaddr.b[5] = 0x00; 610 611 request.AddInt32("hci_id", fHid); 612 request.AddData("raw command", B_ANY_TYPE, 613 writeAddress.Data(), writeAddress.Size()); 614 request.AddInt16("eventExpected", HCI_EVENT_CMD_COMPLETE); 615 request.AddInt16("opcodeExpected", PACK_OPCODE(OGF_VENDOR_CMD, 616 OCF_WRITE_BCM2035_BDADDR)); 617 618 if (fMessenger->SendMessage(&request, &reply) == B_OK) 619 reply.FindInt8("status", &bt_status); 620#endif 621 } 622} 623 624 625LocalDevice::~LocalDevice() 626{ 627 delete fMessenger; 628} 629 630 631} /* end namespace Bluetooth */ 632