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 11 #include <Entry.h> 12 #include <Deskbar.h> 13 #include <Directory.h> 14 #include <Message.h> 15 #include <Path.h> 16 #include <Roster.h> 17 #include <String.h> 18 19 #include <TypeConstants.h> 20 #include <syslog.h> 21 22 #include <bluetoothserver_p.h> 23 #include <bluetooth/HCI/btHCI_command.h> 24 #include <bluetooth/bluetooth_util.h> 25 26 #include "BluetoothServer.h" 27 #include "DeskbarReplicant.h" 28 #include "LocalDeviceImpl.h" 29 #include "Output.h" 30 31 32 status_t 33 DispatchEvent(struct hci_event_header* header, int32 code, size_t size) 34 { 35 // we only handle events 36 if (GET_PORTCODE_TYPE(code)!= BT_EVENT) { 37 Output::Instance()->Post("Wrong type frame code", BLACKBOARD_KIT); 38 return B_OK; 39 } 40 41 // fetch the LocalDevice who belongs this event 42 LocalDeviceImpl* lDeviceImplementation = ((BluetoothServer*)be_app)-> 43 LocateLocalDeviceImpl(GET_PORTCODE_HID(code)); 44 45 if (lDeviceImplementation == NULL) { 46 Output::Instance()->Post("LocalDevice could not be fetched", BLACKBOARD_KIT); 47 return B_OK; 48 } 49 50 lDeviceImplementation->HandleEvent(header); 51 52 return B_OK; 53 } 54 55 56 BluetoothServer::BluetoothServer() : BApplication(BLUETOOTH_SIGNATURE) 57 { 58 Output::Instance()->Run(); 59 Output::Instance()->SetTitle("Bluetooth message gathering"); 60 61 Output::Instance()->AddTab("General", BLACKBOARD_GENERAL); 62 Output::Instance()->AddTab("Device Manager", BLACKBOARD_DEVICEMANAGER); 63 Output::Instance()->AddTab("Kit", BLACKBOARD_KIT); 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 bool BluetoothServer::QuitRequested(void) 73 { 74 // Finish quitting 75 Output::Instance()->Lock(); 76 Output::Instance()->Quit(); 77 78 LocalDeviceImpl* lDeviceImpl = NULL; 79 while ((lDeviceImpl = (LocalDeviceImpl *)fLocalDevicesList.RemoveItem((int32)0)) 80 != NULL) 81 delete lDeviceImpl; 82 83 _RemoveDeskbarIcon(); 84 85 printf("Accepting quitting of the application\n"); 86 return BApplication::QuitRequested(); 87 } 88 89 90 void BluetoothServer::ArgvReceived(int32 argc, char **argv) 91 { 92 if (argc>1) { 93 if (strcmp(argv[1], "--finish") == 0) 94 PostMessage(B_QUIT_REQUESTED); 95 } 96 97 } 98 99 100 void BluetoothServer::ReadyToRun(void) 101 { 102 fDeviceManager->StartMonitoringDevice("bluetooth/h2"); 103 fDeviceManager->StartMonitoringDevice("bluetooth/h3"); 104 fDeviceManager->StartMonitoringDevice("bluetooth/h4"); 105 fDeviceManager->StartMonitoringDevice("bluetooth/h5"); 106 107 if (fEventListener2->Launch() != B_OK) 108 Output::Instance()->Post("Bluetooth port listener failed\n", BLACKBOARD_GENERAL); 109 else 110 Output::Instance()->Post("Bluetooth server Ready\n", BLACKBOARD_GENERAL); 111 112 ShowWindow(Output::Instance()); 113 114 _InstallDeskbarIcon(); 115 } 116 117 118 void BluetoothServer::AppActivated(bool act) 119 { 120 printf("Activated %d\n",act); 121 } 122 123 124 void BluetoothServer::MessageReceived(BMessage *message) 125 { 126 BMessage reply; 127 status_t status = B_WOULD_BLOCK; // mark somehow to do not reply anything 128 129 switch(message->what) 130 { 131 case BT_MSG_ADD_DEVICE: 132 { 133 BString str; 134 message->FindString("name", &str); 135 BPath path(str.String()); 136 Output::Instance()->Postf(BLACKBOARD_GENERAL, 137 "Requested LocalDevice %s\n", str.String()); 138 LocalDeviceImpl* lDeviceImpl = LocalDeviceImpl::CreateTransportAccessor(&path); 139 140 if (lDeviceImpl->GetID() >= 0) { 141 fLocalDevicesList.AddItem(lDeviceImpl); 142 Output::Instance()->AddTab("Local Device", BLACKBOARD_LD(lDeviceImpl->GetID())); 143 Output::Instance()->Postf(BLACKBOARD_LD(lDeviceImpl->GetID()), 144 "LocalDevice %s id=%x added\n", str.String(), lDeviceImpl->GetID()); 145 146 } else { 147 Output::Instance()->Post("Adding LocalDevice failed\n", 148 BLACKBOARD_GENERAL); 149 } 150 151 status = B_WOULD_BLOCK; 152 /* TODO: This should be by user request only! */ 153 lDeviceImpl->Launch(); 154 break; 155 } 156 157 case BT_MSG_REMOVE_DEVICE: 158 { 159 LocalDeviceImpl* lDeviceImpl = LocateDelegateFromMessage(message); 160 if (lDeviceImpl != NULL) { 161 fLocalDevicesList.RemoveItem(lDeviceImpl); 162 delete lDeviceImpl; 163 } 164 break; 165 } 166 167 case BT_MSG_COUNT_LOCAL_DEVICES: 168 status = HandleLocalDevicesCount(message, &reply); 169 break; 170 171 case BT_MSG_ACQUIRE_LOCAL_DEVICE: 172 status = HandleAcquireLocalDevice(message, &reply); 173 break; 174 175 case BT_MSG_HANDLE_SIMPLE_REQUEST: 176 status = HandleSimpleRequest(message, &reply); 177 break; 178 179 case BT_MSG_GET_PROPERTY: 180 status = HandleGetProperty(message, &reply); 181 break; 182 183 /* Handle if the bluetooth preferences is running?? */ 184 case B_SOME_APP_LAUNCHED: 185 { 186 const char *signature; 187 // TODO: what's this for? 188 if (message->FindString("be:signature", &signature) == B_OK) { 189 printf("input_server : %s\n", signature); 190 if (strcmp(signature, "application/x-vnd.Be-TSKB") == 0) { 191 192 } 193 } 194 return; 195 } 196 197 case BT_MSG_SERVER_SHOW_CONSOLE: 198 ShowWindow(Output::Instance()); 199 break; 200 201 default: 202 BApplication::MessageReceived(message); 203 break; 204 } 205 206 // Can we reply right now? 207 // TOD: review this condition 208 if (status != B_WOULD_BLOCK) { 209 reply.AddInt32("status", status); 210 message->SendReply(&reply); 211 printf("Sending reply message for->\n"); 212 message->PrintToStream(); 213 } 214 } 215 216 #if 0 217 #pragma mark - 218 #endif 219 220 221 LocalDeviceImpl* 222 BluetoothServer::LocateDelegateFromMessage(BMessage* message) 223 { 224 LocalDeviceImpl* lDeviceImpl = NULL; 225 hci_id hid; 226 227 if (message->FindInt32("hci_id", &hid) == B_OK) { 228 /* Try to find out when a ID was specified */ 229 int index; 230 for (index = 0; index < fLocalDevicesList.CountItems(); index ++) { 231 lDeviceImpl = fLocalDevicesList.ItemAt(index); 232 if (lDeviceImpl->GetID() == hid) 233 break; 234 } 235 } 236 237 return lDeviceImpl; 238 239 } 240 241 LocalDeviceImpl* 242 BluetoothServer::LocateLocalDeviceImpl(hci_id hid) 243 { 244 /* Try to find out when a ID was specified */ 245 int index; 246 247 for (index = 0; index < fLocalDevicesList.CountItems(); index ++) { 248 LocalDeviceImpl* lDeviceImpl = fLocalDevicesList.ItemAt(index); 249 if (lDeviceImpl->GetID() == hid) 250 return lDeviceImpl; 251 } 252 253 return NULL; 254 } 255 256 257 #if 0 258 #pragma - Messages reply 259 #endif 260 261 status_t 262 BluetoothServer::HandleLocalDevicesCount(BMessage* message, BMessage* reply) 263 { 264 return reply->AddInt32("count", fLocalDevicesList.CountItems()); 265 } 266 267 268 status_t 269 BluetoothServer::HandleAcquireLocalDevice(BMessage* message, BMessage* reply) 270 { 271 hci_id hid; 272 ssize_t size; 273 bdaddr_t bdaddr; 274 LocalDeviceImpl* lDeviceImpl = NULL; 275 static int32 lastIndex = 0; 276 277 if (message->FindInt32("hci_id", &hid) == B_OK) 278 { 279 Output::Instance()->Post("GetLocalDevice requested with id\n", 280 BLACKBOARD_KIT); 281 lDeviceImpl = LocateDelegateFromMessage(message); 282 283 } else if (message->FindData("bdaddr", B_ANY_TYPE, (const void**)&bdaddr, &size ) 284 == B_OK) { 285 /* Try to find out when the user specified the address */ 286 Output::Instance()->Post("GetLocalDevice requested with bdaddr\n", 287 BLACKBOARD_KIT); 288 for (lastIndex = 0; lastIndex < fLocalDevicesList.CountItems(); lastIndex ++) { 289 //TODO: Only possible if the property is available 290 //bdaddr_t local; 291 //lDeviceImpl = fLocalDevicesList.ItemAt(lastIndex); 292 //if ((lDeviceImpl->GetAddress(&local, message) == B_OK) 293 // && bacmp(&local, &bdaddr)) { 294 // break; 295 //} 296 } 297 298 } else { 299 // Careless, any device not performing operations will be fine 300 Output::Instance()->Post("GetLocalDevice plain request\n", BLACKBOARD_KIT); 301 // from last assigned till end 302 for ( int index = lastIndex + 1; index < fLocalDevicesList.CountItems(); index ++) { 303 lDeviceImpl = fLocalDevicesList.ItemAt(index); 304 printf("Requesting local device %ld\n", lDeviceImpl->GetID()); 305 if (lDeviceImpl != NULL && lDeviceImpl->Available()) 306 { 307 Output::Instance()->Postf(BLACKBOARD_KIT, "Device available: %lx\n", lDeviceImpl->GetID()); 308 lastIndex = index; 309 break; 310 } 311 } 312 313 // from starting till last assigned if not yet found 314 if (lDeviceImpl == NULL) { 315 for ( int index = 0; index <= lastIndex ; index ++) { 316 lDeviceImpl = fLocalDevicesList.ItemAt(index); 317 printf("Requesting local device %ld\n", lDeviceImpl->GetID()); 318 if (lDeviceImpl != NULL && lDeviceImpl->Available()) 319 { 320 Output::Instance()->Postf(BLACKBOARD_KIT, "Device available: %lx\n", lDeviceImpl->GetID()); 321 lastIndex = index; 322 break; 323 } 324 } 325 } 326 } 327 328 if (lastIndex <= fLocalDevicesList.CountItems() && lDeviceImpl != NULL && lDeviceImpl->Available()) { 329 hid = lDeviceImpl->GetID(); 330 lDeviceImpl->Acquire(); 331 332 Output::Instance()->Postf(BLACKBOARD_KIT, "Device acquired %lx\n", hid); 333 return reply->AddInt32("hci_id", hid); 334 } 335 336 return B_ERROR; 337 338 } 339 340 341 status_t 342 BluetoothServer::HandleSimpleRequest(BMessage* message, BMessage* reply) 343 { 344 LocalDeviceImpl* lDeviceImpl = LocateDelegateFromMessage(message); 345 if (lDeviceImpl == NULL) { 346 return B_ERROR; 347 } 348 349 const char* propertyRequested; 350 351 // Find out if there is a property being requested, 352 if (message->FindString("property", &propertyRequested) == B_OK) { 353 // Check if the property has been already retrieved 354 if (lDeviceImpl->IsPropertyAvailable(propertyRequested)) { 355 // Dump everything 356 reply->AddMessage("properties", lDeviceImpl->GetPropertiesMessage()); 357 return B_OK; 358 } 359 } 360 361 // we are gonna need issue the command ... 362 if (lDeviceImpl->ProcessSimpleRequest(DetachCurrentMessage()) == B_OK) 363 return B_WOULD_BLOCK; 364 else { 365 lDeviceImpl->Unregister(); 366 return B_ERROR; 367 } 368 369 } 370 371 372 status_t 373 BluetoothServer::HandleGetProperty(BMessage* message, BMessage* reply) 374 { 375 /* User side will look for the reply in a result field 376 * and will not care about status fields, therefore we return OK in all cases 377 */ 378 LocalDeviceImpl* lDeviceImpl = LocateDelegateFromMessage(message); 379 if (lDeviceImpl == NULL) { 380 return B_ERROR; 381 } 382 383 const char* propertyRequested; 384 385 // Find out if there is a property being requested, 386 if (message->FindString("property", &propertyRequested) == B_OK) { 387 388 Output::Instance()->Postf(BLACKBOARD_LD(lDeviceImpl->GetID()), "Searching %s property...\n", 389 propertyRequested); 390 391 // Check if the property has been already retrieved 392 if (lDeviceImpl->IsPropertyAvailable(propertyRequested)) { 393 if (strcmp(propertyRequested, "hci_version") == 0 394 || strcmp(propertyRequested, "lmp_version") == 0 395 || strcmp(propertyRequested, "sco_mtu") == 0) { 396 397 uint8 result = lDeviceImpl->GetPropertiesMessage()->FindInt8(propertyRequested); 398 reply->AddInt32("result", result); 399 400 } else if (strcmp(propertyRequested, "hci_revision") == 0 401 || strcmp(propertyRequested, "lmp_subversion") == 0 402 || strcmp(propertyRequested, "manufacturer") == 0 403 || strcmp(propertyRequested, "acl_mtu") == 0 404 || strcmp(propertyRequested, "acl_max_pkt") == 0 405 || strcmp(propertyRequested, "sco_max_pkt") == 0 ) { 406 407 uint16 result = lDeviceImpl->GetPropertiesMessage()->FindInt16(propertyRequested); 408 reply->AddInt32("result", result); 409 410 } else { 411 Output::Instance()->Postf(BLACKBOARD_LD(lDeviceImpl->GetID()), "Property %s could not be satisfied\n", 412 propertyRequested); 413 } 414 } 415 } 416 417 return B_OK; 418 } 419 420 #if 0 421 #pragma mark - 422 #endif 423 424 int32 425 BluetoothServer::sdp_server_Thread(void* data) 426 { 427 428 return B_NO_ERROR; 429 } 430 431 432 void 433 BluetoothServer::ShowWindow(BWindow* pWindow) 434 { 435 pWindow->Lock(); 436 if (pWindow->IsHidden()) 437 pWindow->Show(); 438 else 439 pWindow->Activate(); 440 pWindow->Unlock(); 441 } 442 443 444 void 445 BluetoothServer::_InstallDeskbarIcon() 446 { 447 app_info appInfo; 448 be_app->GetAppInfo(&appInfo); 449 450 BDeskbar deskbar; 451 452 if (deskbar.HasItem(kDeskbarItemName)) { 453 _RemoveDeskbarIcon(); 454 } 455 456 status_t res = deskbar.AddItem(&appInfo.ref); 457 if (res != B_OK) { 458 printf("Failed adding deskbar icon: %ld\n", res); 459 } 460 } 461 462 463 void 464 BluetoothServer::_RemoveDeskbarIcon() 465 { 466 BDeskbar deskbar; 467 status_t res = deskbar.RemoveItem(kDeskbarItemName); 468 if (res != B_OK) { 469 printf("Failed removing Deskbar icon: %ld: \n", res); 470 } 471 } 472 473 #if 0 474 #pragma mark - 475 #endif 476 477 int 478 main(int /*argc*/, char** /*argv*/) 479 { 480 setbuf(stdout, NULL); 481 482 BluetoothServer* bluetoothServer = new BluetoothServer; 483 484 bluetoothServer->Run(); 485 delete bluetoothServer; 486 487 return 0; 488 } 489 490