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