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 8 #include <stdio.h> 9 #include <fcntl.h> 10 #include <unistd.h> 11 12 #include <Entry.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 "LocalDeviceImpl.h" 27 #include "BluetoothServer.h" 28 #include "Output.h" 29 30 31 BluetoothServer::BluetoothServer() : BApplication(BLUETOOTH_SIGNATURE) 32 { 33 Output::Instance()->Run(); 34 Output::Instance()->SetTitle("Bluetooth message gathering"); 35 36 Output::Instance()->AddTab("General", BLACKBOARD_GENERAL); 37 Output::Instance()->AddTab("Device Manager", BLACKBOARD_DEVICEMANAGER); 38 Output::Instance()->AddTab("Events", BLACKBOARD_EVENTS); 39 Output::Instance()->AddTab("Kit", BLACKBOARD_KIT); 40 41 ShowWindow(Output::Instance()); 42 43 fDeviceManager = new DeviceManager(); 44 fLocalDevicesList.MakeEmpty(); 45 46 // TODO: Some events should be handled faster than in KL... 47 fEventListener = spawn_thread(notification_Thread, "BT port listener" , 48 B_URGENT_DISPLAY_PRIORITY , this); 49 50 } 51 52 bool BluetoothServer::QuitRequested(void) 53 { 54 // Finish quitting 55 Output::Instance()->Lock(); 56 Output::Instance()->Quit(); 57 58 LocalDeviceImpl* ldi = NULL; 59 while ((ldi = (LocalDeviceImpl *)fLocalDevicesList.RemoveItem((int32)0)) 60 != NULL) 61 delete ldi; 62 63 printf("Accepting quitting of the application\n"); 64 return BApplication::QuitRequested(); 65 } 66 67 68 void BluetoothServer::ArgvReceived(int32 argc, char **argv) 69 { 70 if (argc>1) { 71 if (strcmp(argv[1], "--finish") == 0) 72 PostMessage(B_QUIT_REQUESTED); 73 } 74 75 } 76 77 78 void BluetoothServer::ReadyToRun(void) 79 { 80 fDeviceManager->StartMonitoringDevice("bluetooth/h2generic"); 81 // Launch the notifier thread 82 if ( resume_thread(fEventListener) != B_OK ) 83 { 84 Output::Instance()->Post("Bluetooth port listener failed\n", BLACKBOARD_GENERAL); 85 } 86 87 Output::Instance()->Post("Bluetooth server Ready\n", BLACKBOARD_GENERAL); 88 } 89 90 91 void BluetoothServer::AppActivated(bool act) 92 { 93 printf("Activated %d\n",act); 94 } 95 96 97 void BluetoothServer::MessageReceived(BMessage *message) 98 { 99 BMessage reply; 100 status_t status = B_WOULD_BLOCK; 101 // mark somehow.. do not reply anything 102 103 switch(message->what) 104 { 105 case BT_MSG_ADD_DEVICE: 106 { 107 BString str; 108 message->FindString("name", &str); 109 BPath path(str.String()); 110 Output::Instance()->Postf(BLACKBOARD_GENERAL, 111 "Requested LocalDevice %s\n", str.String()); 112 LocalDeviceImpl* ldi = LocalDeviceImpl::CreateTransportAccessor(&path); 113 114 if (ldi->GetID() >= 0) { 115 fLocalDevicesList.AddItem(ldi); 116 Output::Instance()->AddTab("Local Device", BLACKBOARD_LD(ldi->GetID())); 117 Output::Instance()->Postf(BLACKBOARD_LD(ldi->GetID()), 118 "LocalDevice %s id=%x added\n", 119 str.String(), ldi->GetID()); 120 } else { 121 Output::Instance()->Post("Adding LocalDevice failed\n", 122 BLACKBOARD_GENERAL); 123 } 124 125 status = B_WOULD_BLOCK; 126 /* TODO: This should be by user request only! */ 127 ldi->Launch(); 128 } 129 break; 130 case BT_MSG_COUNT_LOCAL_DEVICES: 131 status = HandleLocalDevicesCount(message, &reply); 132 break; 133 case BT_MSG_ACQUIRE_LOCAL_DEVICE: 134 status = HandleAcquireLocalDevice(message, &reply); 135 break; 136 137 case BT_MSG_HANDLE_SIMPLE_REQUEST: 138 status = HandleSimpleRequest(message, &reply); 139 break; 140 /* Handle if the bluetooth preferences is running?? */ 141 case B_SOME_APP_LAUNCHED: 142 { 143 const char *signature; 144 // TODO: what's this for? 145 if (message->FindString("be:signature", &signature) == B_OK) { 146 printf("input_server : %s\n", signature); 147 if (strcmp(signature, "application/x-vnd.Be-TSKB") == 0) { 148 149 } 150 } 151 return; 152 } 153 154 default: 155 BApplication::MessageReceived(message); 156 break; 157 } 158 159 // Can we reply right now? 160 // TOD: review this condition 161 if (status != B_WOULD_BLOCK) { 162 reply.AddInt32("status", status); 163 message->SendReply(&reply); 164 printf("Sending reply message\n"); 165 } 166 } 167 168 #if 0 169 #pragma mark - 170 #endif 171 172 LocalDeviceImpl* 173 BluetoothServer::LocateDelegateFromMessage(BMessage* message) 174 { 175 LocalDeviceImpl* ldi = NULL; 176 hci_id hid; 177 178 if (message->FindInt32("hci_id", &hid) == B_OK) { 179 /* Try to find out when a ID was specified */ 180 int index; 181 for (index = 0; index < fLocalDevicesList.CountItems(); index ++) { 182 ldi = fLocalDevicesList.ItemAt(index); 183 if (ldi->GetID() == hid) 184 break; 185 } 186 } 187 188 return ldi; 189 190 } 191 192 LocalDeviceImpl* 193 BluetoothServer::LocateLocalDeviceImpl(hci_id hid) 194 { 195 /* Try to find out when a ID was specified */ 196 int index; 197 198 for (index = 0; index < fLocalDevicesList.CountItems(); index ++) { 199 LocalDeviceImpl* ldi = fLocalDevicesList.ItemAt(index); 200 if (ldi->GetID() == hid) 201 return ldi; 202 } 203 204 return NULL; 205 } 206 207 208 #if 0 209 #pragma - Messages reply 210 #endif 211 212 status_t 213 BluetoothServer::HandleLocalDevicesCount(BMessage* message, BMessage* reply) 214 { 215 return reply->AddInt32("count", fLocalDevicesList.CountItems()); 216 } 217 218 219 status_t 220 BluetoothServer::HandleAcquireLocalDevice(BMessage* message, BMessage* reply) 221 { 222 hci_id hid; 223 ssize_t size; 224 bdaddr_t bdaddr; 225 LocalDeviceImpl* ldi = NULL; 226 int32 index = 0; 227 228 if (message->FindInt32("hci_id", &hid) == B_OK) 229 { 230 Output::Instance()->Post("GetLocalDevice requested with id\n", 231 BLACKBOARD_KIT); 232 ldi = LocateDelegateFromMessage(message); 233 234 } else if (message->FindData("bdaddr", B_ANY_TYPE, (const void**)&bdaddr, &size ) 235 == B_OK) { 236 /* Try to find out when the user specified the address */ 237 Output::Instance()->Post("GetLocalDevice requested with bdaddr\n", 238 BLACKBOARD_KIT); 239 for (index = 0; index < fLocalDevicesList.CountItems(); index ++) { 240 bdaddr_t local; 241 ldi = fLocalDevicesList.ItemAt(index); 242 // TODO: Only if the property is available 243 //if ((ldi->GetAddress(&local, message) == B_OK) 244 // && bacmp(&local, &bdaddr)) { 245 // break; 246 //} 247 } 248 249 } else { 250 /* Careless, any device not performing operations will be fine */ 251 Output::Instance()->Post("GetLocalDevice requested\n", BLACKBOARD_KIT); 252 for (index = 0; index < fLocalDevicesList.CountItems(); index ++) { 253 ldi = fLocalDevicesList.ItemAt(index); 254 printf("Requesting local device %ld\n", ldi->GetID()); 255 if (ldi != NULL && ldi->Available()) 256 { 257 printf("dev ours %ld\n", ldi->GetID()); 258 break; 259 } 260 } 261 } 262 263 if (index <= fLocalDevicesList.CountItems() && ldi != NULL && ldi->Available()) { 264 Output::Instance()->Post("Device acquired\n", BLACKBOARD_KIT); 265 ldi->Acquire(); 266 return reply->AddInt32("hci_id", hid); 267 } 268 269 return B_ERROR; 270 271 } 272 273 274 status_t 275 BluetoothServer::HandleSimpleRequest(BMessage* message, BMessage* reply) 276 { 277 LocalDeviceImpl* ldi = LocateDelegateFromMessage(message); 278 BString propertyRequested; 279 280 // Find out if there is a property being requested, 281 if (message->FindString("property", &propertyRequested) == B_OK) { 282 // Check if the property has been already retrieved 283 if (ldi->IsPropertyAvailable(propertyRequested)) { 284 // Dump everything 285 reply->AddMessage("properties",ldi->GetPropertiesMessage()); 286 return B_OK; 287 } 288 } 289 290 // we are gonna need issue the command ... 291 if (ldi->ProcessSimpleRequest(DetachCurrentMessage()) == B_OK) 292 return B_WOULD_BLOCK; 293 else 294 return B_ERROR; 295 296 } 297 298 299 #if 0 300 #pragma mark - 301 #endif 302 303 304 int32 305 BluetoothServer::notification_Thread(void* data) 306 { 307 BPortNot notifierd((BluetoothServer*)data, BT_USERLAND_PORT_NAME); 308 309 notifierd.loop(); 310 return B_NO_ERROR; 311 } 312 313 int32 314 BluetoothServer::sdp_server_Thread(void* data) 315 { 316 317 return B_NO_ERROR; 318 } 319 320 321 void 322 BluetoothServer::ShowWindow(BWindow* pWindow) 323 { 324 pWindow->Lock(); 325 if (pWindow->IsHidden()) 326 pWindow->Show(); 327 else 328 pWindow->Activate(); 329 pWindow->Unlock(); 330 } 331 332 333 #if 0 334 #pragma mark - 335 #endif 336 337 int 338 main(int /*argc*/, char** /*argv*/) 339 { 340 setbuf(stdout, NULL); 341 342 BluetoothServer* bluetoothServer = new BluetoothServer; 343 344 bluetoothServer->Run(); 345 delete bluetoothServer; 346 347 return 0; 348 } 349 350