1 /* 2 * Copyright 2007-2009 Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com 3 * Copyright 2008 Mika Lindqvist, monni1995_at_gmail.com 4 * All rights reserved. Distributed under the terms of the MIT License. 5 */ 6 7 #include <stdio.h> 8 #include <fcntl.h> 9 #include <unistd.h> 10 #include <sys/select.h> 11 12 #include <Entry.h> 13 #include <Deskbar.h> 14 #include <Directory.h> 15 #include <Message.h> 16 #include <Path.h> 17 #include <Roster.h> 18 #include <String.h> 19 20 #include <TypeConstants.h> 21 #include <syslog.h> 22 23 #include <bluetoothserver_p.h> 24 #include <bluetooth/HCI/btHCI_command.h> 25 #include <bluetooth/L2CAP/btL2CAP.h> 26 #include <bluetooth/bluetooth.h> 27 #include <bluetooth/bluetooth_util.h> 28 29 #include "BluetoothServer.h" 30 #include "DeskbarReplicant.h" 31 #include "LocalDeviceImpl.h" 32 #include "Output.h" 33 34 35 status_t 36 DispatchEvent(struct hci_event_header* header, int32 code, size_t size) 37 { 38 // we only handle events 39 if (GET_PORTCODE_TYPE(code)!= BT_EVENT) { 40 Output::Instance()->Post("Wrong type frame code", BLACKBOARD_KIT); 41 return B_OK; 42 } 43 44 // fetch the LocalDevice who belongs this event 45 LocalDeviceImpl* lDeviceImplementation = ((BluetoothServer*)be_app)-> 46 LocateLocalDeviceImpl(GET_PORTCODE_HID(code)); 47 48 if (lDeviceImplementation == NULL) { 49 Output::Instance()->Post("LocalDevice could not be fetched", BLACKBOARD_KIT); 50 return B_OK; 51 } 52 53 lDeviceImplementation->HandleEvent(header); 54 55 return B_OK; 56 } 57 58 59 BluetoothServer::BluetoothServer() 60 : BApplication(BLUETOOTH_SIGNATURE) 61 , fSDPThreadID(-1) 62 , fIsShuttingDown(false) 63 { 64 Output::Instance()->Run(); 65 Output::Instance()->SetTitle("Bluetooth message gathering"); 66 67 Output::Instance()->AddTab("General", BLACKBOARD_GENERAL); 68 Output::Instance()->AddTab("Device Manager", BLACKBOARD_DEVICEMANAGER); 69 Output::Instance()->AddTab("Kit", BLACKBOARD_KIT); 70 Output::Instance()->AddTab("SDP", BLACKBOARD_SDP); 71 72 fDeviceManager = new DeviceManager(); 73 fLocalDevicesList.MakeEmpty(); 74 75 fEventListener2 = new BluetoothPortListener(BT_USERLAND_PORT_NAME, 76 (BluetoothPortListener::port_listener_func)&DispatchEvent); 77 } 78 79 80 bool BluetoothServer::QuitRequested(void) 81 { 82 LocalDeviceImpl* lDeviceImpl = NULL; 83 while ((lDeviceImpl = (LocalDeviceImpl*) 84 fLocalDevicesList.RemoveItem((int32)0)) != NULL) 85 delete lDeviceImpl; 86 87 _RemoveDeskbarIcon(); 88 89 // stop the SDP server thread 90 fIsShuttingDown = true; 91 92 status_t threadReturnStatus; 93 wait_for_thread(fSDPThreadID, &threadReturnStatus); 94 printf("SDP server thread exited with: %s\n", strerror(threadReturnStatus)); 95 96 // Finish quitting 97 Output::Instance()->Lock(); 98 Output::Instance()->Quit(); 99 100 delete fEventListener2; 101 printf("Shutting down bluetooth_server.\n"); 102 103 return BApplication::QuitRequested(); 104 } 105 106 107 void BluetoothServer::ArgvReceived(int32 argc, char **argv) 108 { 109 if (argc > 1) { 110 if (strcmp(argv[1], "--finish") == 0) 111 PostMessage(B_QUIT_REQUESTED); 112 } 113 114 } 115 116 117 void BluetoothServer::ReadyToRun(void) 118 { 119 ShowWindow(Output::Instance()); 120 121 fDeviceManager->StartMonitoringDevice("bluetooth/h2"); 122 fDeviceManager->StartMonitoringDevice("bluetooth/h3"); 123 fDeviceManager->StartMonitoringDevice("bluetooth/h4"); 124 fDeviceManager->StartMonitoringDevice("bluetooth/h5"); 125 126 if (fEventListener2->Launch() != B_OK) 127 Output::Instance()->Post("Bluetooth event listener failed\n", 128 BLACKBOARD_GENERAL); 129 else 130 Output::Instance()->Post("Bluetooth event listener Ready\n", 131 BLACKBOARD_GENERAL); 132 133 _InstallDeskbarIcon(); 134 135 // Spawn the SDP server thread 136 fSDPThreadID = spawn_thread(SDPServerThread, "SDP server thread", 137 B_NORMAL_PRIORITY, this); 138 139 #define _USE_FAKE_SDP_SERVER 140 #ifdef _USE_FAKE_SDP_SERVER 141 if (fSDPThreadID <= 0 || resume_thread(fSDPThreadID) != B_OK) { 142 Output::Instance()->Postf(BLACKBOARD_SDP, 143 "Failed launching the SDP server thread: %x\n", fSDPThreadID); 144 } 145 #endif 146 } 147 148 149 void BluetoothServer::AppActivated(bool act) 150 { 151 printf("Activated %d\n",act); 152 } 153 154 155 void BluetoothServer::MessageReceived(BMessage* message) 156 { 157 BMessage reply; 158 status_t status = B_WOULD_BLOCK; // mark somehow to do not reply anything 159 160 switch (message->what) 161 { 162 case BT_MSG_ADD_DEVICE: 163 { 164 BString str; 165 BPath path(str.String()); 166 167 message->FindString("name", &str); 168 169 Output::Instance()->Postf(BLACKBOARD_GENERAL, 170 "Requested LocalDevice %s\n", str.String()); 171 172 LocalDeviceImpl* lDeviceImpl = 173 LocalDeviceImpl::CreateTransportAccessor(&path); 174 175 if (lDeviceImpl->GetID() >= 0) { 176 fLocalDevicesList.AddItem(lDeviceImpl); 177 178 Output::Instance()->AddTab("Local Device", 179 BLACKBOARD_LD(lDeviceImpl->GetID())); 180 Output::Instance()->Postf(BLACKBOARD_LD(lDeviceImpl->GetID()), 181 "LocalDevice %s id=%x added\n", str.String(), 182 lDeviceImpl->GetID()); 183 184 } else { 185 Output::Instance()->Post("Adding LocalDevice hci id invalid\n", 186 BLACKBOARD_GENERAL); 187 } 188 189 status = B_WOULD_BLOCK; 190 /* TODO: This should be by user request only! */ 191 lDeviceImpl->Launch(); 192 break; 193 } 194 195 case BT_MSG_REMOVE_DEVICE: 196 { 197 LocalDeviceImpl* lDeviceImpl = LocateDelegateFromMessage(message); 198 if (lDeviceImpl != NULL) { 199 fLocalDevicesList.RemoveItem(lDeviceImpl); 200 delete lDeviceImpl; 201 } 202 break; 203 } 204 205 case BT_MSG_COUNT_LOCAL_DEVICES: 206 status = HandleLocalDevicesCount(message, &reply); 207 break; 208 209 case BT_MSG_ACQUIRE_LOCAL_DEVICE: 210 status = HandleAcquireLocalDevice(message, &reply); 211 break; 212 213 case BT_MSG_HANDLE_SIMPLE_REQUEST: 214 status = HandleSimpleRequest(message, &reply); 215 break; 216 217 case BT_MSG_GET_PROPERTY: 218 status = HandleGetProperty(message, &reply); 219 break; 220 221 // Handle if the bluetooth preferences is running? 222 case B_SOME_APP_LAUNCHED: 223 { 224 const char* signature; 225 226 if (message->FindString("be:signature", &signature) == B_OK) { 227 printf("input_server : %s\n", signature); 228 if (strcmp(signature, "application/x-vnd.Be-TSKB") == 0) { 229 230 } 231 } 232 return; 233 } 234 235 case BT_MSG_SERVER_SHOW_CONSOLE: 236 ShowWindow(Output::Instance()); 237 break; 238 239 default: 240 BApplication::MessageReceived(message); 241 break; 242 } 243 244 // Can we reply right now? 245 // TOD: review this condition 246 if (status != B_WOULD_BLOCK) { 247 reply.AddInt32("status", status); 248 message->SendReply(&reply); 249 printf("Sending reply message for->\n"); 250 message->PrintToStream(); 251 } 252 } 253 254 255 #if 0 256 #pragma mark - 257 #endif 258 259 LocalDeviceImpl* 260 BluetoothServer::LocateDelegateFromMessage(BMessage* message) 261 { 262 LocalDeviceImpl* lDeviceImpl = NULL; 263 hci_id hid; 264 265 if (message->FindInt32("hci_id", &hid) == B_OK) { 266 // Try to find out when a ID was specified 267 int index; 268 for (index = 0; index < fLocalDevicesList.CountItems(); index ++) { 269 lDeviceImpl = fLocalDevicesList.ItemAt(index); 270 if (lDeviceImpl->GetID() == hid) 271 break; 272 } 273 } 274 275 return lDeviceImpl; 276 277 } 278 279 280 LocalDeviceImpl* 281 BluetoothServer::LocateLocalDeviceImpl(hci_id hid) 282 { 283 // Try to find out when a ID was specified 284 int index; 285 286 for (index = 0; index < fLocalDevicesList.CountItems(); index++) { 287 LocalDeviceImpl* lDeviceImpl = fLocalDevicesList.ItemAt(index); 288 if (lDeviceImpl->GetID() == hid) 289 return lDeviceImpl; 290 } 291 292 return NULL; 293 } 294 295 296 #if 0 297 #pragma - Messages reply 298 #endif 299 300 status_t 301 BluetoothServer::HandleLocalDevicesCount(BMessage* message, BMessage* reply) 302 { 303 return reply->AddInt32("count", fLocalDevicesList.CountItems()); 304 } 305 306 307 status_t 308 BluetoothServer::HandleAcquireLocalDevice(BMessage* message, BMessage* reply) 309 { 310 hci_id hid; 311 ssize_t size; 312 bdaddr_t bdaddr; 313 LocalDeviceImpl* lDeviceImpl = NULL; 314 static int32 lastIndex = 0; 315 316 if (message->FindInt32("hci_id", &hid) == B_OK) { 317 Output::Instance()->Post("GetLocalDevice requested with id\n", 318 BLACKBOARD_KIT); 319 lDeviceImpl = LocateDelegateFromMessage(message); 320 321 } else if (message->FindData("bdaddr", B_ANY_TYPE, 322 (const void**)&bdaddr, &size) == B_OK) { 323 324 // Try to find out when the user specified the address 325 Output::Instance()->Post("GetLocalDevice requested with bdaddr\n", 326 BLACKBOARD_KIT); 327 for (lastIndex = 0; lastIndex < fLocalDevicesList.CountItems(); 328 lastIndex ++) { 329 // TODO: Only possible if the property is available 330 // bdaddr_t local; 331 // lDeviceImpl = fLocalDevicesList.ItemAt(lastIndex); 332 // if ((lDeviceImpl->GetAddress(&local, message) == B_OK) 333 // && bacmp(&local, &bdaddr)) { 334 // break; 335 // } 336 } 337 338 } else { 339 // Careless, any device not performing operations will be fine 340 Output::Instance()->Post("GetLocalDevice plain request\n", BLACKBOARD_KIT); 341 // from last assigned till end 342 for (int index = lastIndex + 1; 343 index < fLocalDevicesList.CountItems(); index++) { 344 lDeviceImpl= fLocalDevicesList.ItemAt(index); 345 printf("Requesting local device %ld\n", lDeviceImpl->GetID()); 346 if (lDeviceImpl != NULL && lDeviceImpl->Available()) { 347 Output::Instance()->Postf(BLACKBOARD_KIT, 348 "Device available: %lx\n", lDeviceImpl->GetID()); 349 lastIndex = index; 350 break; 351 } 352 } 353 354 // from starting till last assigned if not yet found 355 if (lDeviceImpl == NULL) { 356 for (int index = 0; index <= lastIndex ; index ++) { 357 lDeviceImpl = fLocalDevicesList.ItemAt(index); 358 printf("Requesting local device %ld\n", lDeviceImpl->GetID()); 359 if (lDeviceImpl != NULL && lDeviceImpl->Available()) { 360 Output::Instance()->Postf(BLACKBOARD_KIT, 361 "Device available: %lx\n", lDeviceImpl->GetID()); 362 lastIndex = index; 363 break; 364 } 365 } 366 } 367 } 368 369 if (lastIndex <= fLocalDevicesList.CountItems() && lDeviceImpl != NULL 370 && lDeviceImpl->Available()) { 371 372 hid = lDeviceImpl->GetID(); 373 lDeviceImpl->Acquire(); 374 375 Output::Instance()->Postf(BLACKBOARD_KIT, "Device acquired %lx\n", hid); 376 return reply->AddInt32("hci_id", hid); 377 } 378 379 return B_ERROR; 380 381 } 382 383 384 status_t 385 BluetoothServer::HandleSimpleRequest(BMessage* message, BMessage* reply) 386 { 387 LocalDeviceImpl* lDeviceImpl = LocateDelegateFromMessage(message); 388 if (lDeviceImpl == NULL) { 389 return B_ERROR; 390 } 391 392 const char* propertyRequested; 393 394 // Find out if there is a property being requested, 395 if (message->FindString("property", &propertyRequested) == B_OK) { 396 // Check if the property has been already retrieved 397 if (lDeviceImpl->IsPropertyAvailable(propertyRequested)) { 398 // Dump everything 399 reply->AddMessage("properties", lDeviceImpl->GetPropertiesMessage()); 400 return B_OK; 401 } 402 } 403 404 // we are gonna need issue the command ... 405 if (lDeviceImpl->ProcessSimpleRequest(DetachCurrentMessage()) == B_OK) 406 return B_WOULD_BLOCK; 407 else { 408 lDeviceImpl->Unregister(); 409 return B_ERROR; 410 } 411 412 } 413 414 415 status_t 416 BluetoothServer::HandleGetProperty(BMessage* message, BMessage* reply) 417 { 418 /* User side will look for the reply in a result field and will 419 * not care about status fields, therefore we return OK in all cases 420 */ 421 LocalDeviceImpl* lDeviceImpl = LocateDelegateFromMessage(message); 422 if (lDeviceImpl == NULL) { 423 return B_ERROR; 424 } 425 426 const char* propertyRequested; 427 428 // Find out if there is a property being requested, 429 if (message->FindString("property", &propertyRequested) == B_OK) { 430 431 Output::Instance()->Postf(BLACKBOARD_LD(lDeviceImpl->GetID()), 432 "Searching %s property...\n", propertyRequested); 433 434 // Check if the property has been already retrieved 435 if (lDeviceImpl->IsPropertyAvailable(propertyRequested)) { 436 if (strcmp(propertyRequested, "hci_version") == 0 437 || strcmp(propertyRequested, "lmp_version") == 0 438 || strcmp(propertyRequested, "sco_mtu") == 0) { 439 440 uint8 result = lDeviceImpl->GetPropertiesMessage()-> 441 FindInt8(propertyRequested); 442 reply->AddInt32("result", result); 443 444 } else if (strcmp(propertyRequested, "hci_revision") == 0 445 || strcmp(propertyRequested, "lmp_subversion") == 0 446 || strcmp(propertyRequested, "manufacturer") == 0 447 || strcmp(propertyRequested, "acl_mtu") == 0 448 || strcmp(propertyRequested, "acl_max_pkt") == 0 449 || strcmp(propertyRequested, "sco_max_pkt") == 0 ) { 450 451 uint16 result = lDeviceImpl->GetPropertiesMessage()-> 452 FindInt16(propertyRequested); 453 reply->AddInt32("result", result); 454 455 } else { 456 Output::Instance()->Postf(BLACKBOARD_LD(lDeviceImpl->GetID()), 457 "Property %s could not be satisfied\n", propertyRequested); 458 } 459 } 460 } 461 462 return B_OK; 463 } 464 465 466 #if 0 467 #pragma mark - 468 #endif 469 470 int32 471 BluetoothServer::SDPServerThread(void* data) 472 { 473 const BluetoothServer* server = (BluetoothServer*)data; 474 475 // Set up the SDP socket 476 struct sockaddr_l2cap loc_addr = { 0 }; 477 int socketServer; 478 int client; 479 status_t status; 480 char buffer[512] = ""; 481 482 Output::Instance()->Postf(BLACKBOARD_SDP, "SDP server thread up...\n"); 483 484 socketServer = socket(PF_BLUETOOTH, SOCK_STREAM, BLUETOOTH_PROTO_L2CAP); 485 486 if (socketServer < 0) { 487 Output::Instance()->Post("Could not create server socket ...\n", 488 BLACKBOARD_SDP); 489 return B_ERROR; 490 } 491 492 // bind socket to port 0x1001 of the first available 493 // bluetooth adapter 494 loc_addr.l2cap_family = AF_BLUETOOTH; 495 loc_addr.l2cap_bdaddr = *BDADDR_ANY; 496 loc_addr.l2cap_psm = B_HOST_TO_LENDIAN_INT16(1); 497 loc_addr.l2cap_len = sizeof(struct sockaddr_l2cap); 498 499 status = bind(socketServer, (struct sockaddr*)&loc_addr, 500 sizeof(struct sockaddr_l2cap)); 501 502 if (status < 0) { 503 Output::Instance()->Postf(BLACKBOARD_SDP, 504 "Could not bind server socket %d ...\n", status); 505 return status; 506 } 507 508 // setsockopt(sock, SOL_L2CAP, SO_L2CAP_OMTU, &omtu, len ); 509 // getsockopt(sock, SOL_L2CAP, SO_L2CAP_IMTU, &omtu, &len ); 510 511 // Listen for up to 10 connections 512 status = listen(socketServer, 10); 513 514 if (status != B_OK) { 515 Output::Instance()->Postf(BLACKBOARD_SDP, 516 "Could not listen server socket %d ...\n", status); 517 return status; 518 } 519 520 while (!server->fIsShuttingDown) { 521 522 Output::Instance()->Postf(BLACKBOARD_SDP, 523 "Waiting connection for socket %d ...\n", socketServer); 524 525 uint len = sizeof(struct sockaddr_l2cap); 526 client = accept(socketServer, (struct sockaddr*)&loc_addr, &len); 527 528 Output::Instance()->Postf(BLACKBOARD_SDP, 529 "Incomming connection... %ld\n", client); 530 531 ssize_t receivedSize; 532 533 do { 534 receivedSize = recv(client, buffer, 29 , 0); 535 if (receivedSize < 0) 536 Output::Instance()->Post("Error reading client socket\n", 537 BLACKBOARD_SDP); 538 else { 539 Output::Instance()->Postf(BLACKBOARD_SDP, 540 "Received from SDP client: %ld:\n", receivedSize); 541 for (int i = 0; i < receivedSize ; i++) 542 Output::Instance()->Postf(BLACKBOARD_SDP, "%x:", buffer[i]); 543 544 Output::Instance()->Post("\n", BLACKBOARD_SDP); 545 } 546 } while (receivedSize >= 0); 547 548 snooze(5000000); 549 Output::Instance()->Post("\nWaiting for next connection...\n", 550 BLACKBOARD_SDP); 551 } 552 553 // Close the socket 554 close(socketServer); 555 556 return B_NO_ERROR; 557 } 558 559 560 void 561 BluetoothServer::ShowWindow(BWindow* pWindow) 562 { 563 pWindow->Lock(); 564 if (pWindow->IsHidden()) 565 pWindow->Show(); 566 else 567 pWindow->Activate(); 568 pWindow->Unlock(); 569 } 570 571 572 void 573 BluetoothServer::_InstallDeskbarIcon() 574 { 575 app_info appInfo; 576 be_app->GetAppInfo(&appInfo); 577 578 BDeskbar deskbar; 579 580 if (deskbar.HasItem(kDeskbarItemName)) { 581 _RemoveDeskbarIcon(); 582 } 583 584 status_t res = deskbar.AddItem(&appInfo.ref); 585 if (res != B_OK) { 586 printf("Failed adding deskbar icon: %ld\n", res); 587 } 588 } 589 590 591 void 592 BluetoothServer::_RemoveDeskbarIcon() 593 { 594 BDeskbar deskbar; 595 status_t res = deskbar.RemoveItem(kDeskbarItemName); 596 if (res != B_OK) { 597 printf("Failed removing Deskbar icon: %ld: \n", res); 598 } 599 } 600 601 602 #if 0 603 #pragma mark - 604 #endif 605 606 int 607 main(int /*argc*/, char** /*argv*/) 608 { 609 setbuf(stdout, NULL); 610 611 BluetoothServer* bluetoothServer = new BluetoothServer; 612 613 bluetoothServer->Run(); 614 delete bluetoothServer; 615 616 return 0; 617 } 618 619