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
DispatchEvent(struct hci_event_header * header,int32 code,size_t size)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
BluetoothServer()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
QuitRequested(void)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
ArgvReceived(int32 argc,char ** argv)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
ReadyToRun(void)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
AppActivated(bool act)133 void BluetoothServer::AppActivated(bool act)
134 {
135 printf("Activated %d\n",act);
136 }
137
138
MessageReceived(BMessage * message)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*
LocateDelegateFromMessage(BMessage * message)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*
LocateLocalDeviceImpl(hci_id hid)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
HandleLocalDevicesCount(BMessage * message,BMessage * reply)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
HandleAcquireLocalDevice(BMessage * message,BMessage * reply)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
HandleSimpleRequest(BMessage * message,BMessage * reply)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
HandleGetProperty(BMessage * message,BMessage * reply)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
SDPServerThread(void * data)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
ShowWindow(BWindow * pWindow)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
_InstallDeskbarIcon()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
_RemoveDeskbarIcon()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
main(int,char **)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