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