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.
10 #include <sys/select.h>
14 #include <Directory.h>
21 #include <TypeConstants.h>
24 #include <bluetoothserver_p.h>
25 #include <bluetooth/HCI/btHCI_command.h>
26 #include <bluetooth/L2CAP/btL2CAP.h>
27 #include <bluetooth/bluetooth.h>
29 #include "BluetoothServer.h"
30 #include "DeskbarReplicant.h"
31 #include "LocalDeviceImpl.h"
36 DispatchEvent(struct hci_event_header
* header
, int32 code
, size_t size
)
38 // we only handle events
39 if (GET_PORTCODE_TYPE(code
)!= BT_EVENT
) {
40 TRACE_BT("BluetoothServer: Wrong type frame code\n");
44 // fetch the LocalDevice who belongs this event
45 LocalDeviceImpl
* lDeviceImplementation
= ((BluetoothServer
*)be_app
)->
46 LocateLocalDeviceImpl(GET_PORTCODE_HID(code
));
48 if (lDeviceImplementation
== NULL
) {
49 TRACE_BT("BluetoothServer: LocalDevice could not be fetched\n");
53 lDeviceImplementation
->HandleEvent(header
);
59 BluetoothServer::BluetoothServer()
61 BApplication(BLUETOOTH_SIGNATURE
),
63 fIsShuttingDown(false)
65 fDeviceManager
= new DeviceManager();
66 fLocalDevicesList
.MakeEmpty();
68 fEventListener2
= new BluetoothPortListener(BT_USERLAND_PORT_NAME
,
69 (BluetoothPortListener::port_listener_func
)&DispatchEvent
);
73 bool BluetoothServer::QuitRequested(void)
75 LocalDeviceImpl
* lDeviceImpl
= NULL
;
76 while ((lDeviceImpl
= (LocalDeviceImpl
*)
77 fLocalDevicesList
.RemoveItemAt(0)) != NULL
)
82 // stop the SDP server thread
83 fIsShuttingDown
= true;
85 status_t threadReturnStatus
;
86 wait_for_thread(fSDPThreadID
, &threadReturnStatus
);
87 TRACE_BT("BluetoothServer server thread exited with: %s\n",
88 strerror(threadReturnStatus
));
90 delete fEventListener2
;
91 TRACE_BT("Shutting down bluetooth_server.\n");
93 return BApplication::QuitRequested();
97 void BluetoothServer::ArgvReceived(int32 argc
, char **argv
)
100 if (strcmp(argv
[1], "--finish") == 0)
101 PostMessage(B_QUIT_REQUESTED
);
106 void BluetoothServer::ReadyToRun(void)
108 fDeviceManager
->StartMonitoringDevice("bluetooth/h2");
109 fDeviceManager
->StartMonitoringDevice("bluetooth/h3");
110 fDeviceManager
->StartMonitoringDevice("bluetooth/h4");
111 fDeviceManager
->StartMonitoringDevice("bluetooth/h5");
113 if (fEventListener2
->Launch() != B_OK
)
114 TRACE_BT("General: Bluetooth event listener failed\n");
116 TRACE_BT("General: Bluetooth event listener Ready\n");
118 _InstallDeskbarIcon();
120 // Spawn the SDP server thread
121 fSDPThreadID
= spawn_thread(SDPServerThread
, "SDP server thread",
122 B_NORMAL_PRIORITY
, this);
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");
133 void BluetoothServer::AppActivated(bool act
)
135 printf("Activated %d\n",act
);
139 void BluetoothServer::MessageReceived(BMessage
* message
)
142 status_t status
= B_WOULD_BLOCK
; // mark somehow to do not reply anything
144 switch (message
->what
)
146 case BT_MSG_ADD_DEVICE
:
149 message
->FindString("name", &str
);
151 TRACE_BT("BluetoothServer: Requested LocalDevice %s\n", str
.String());
153 BPath
path(str
.String());
155 LocalDeviceImpl
* lDeviceImpl
156 = LocalDeviceImpl::CreateTransportAccessor(&path
);
158 if (lDeviceImpl
->GetID() >= 0) {
159 fLocalDevicesList
.AddItem(lDeviceImpl
);
161 TRACE_BT("LocalDevice %s id=%" B_PRId32
" added\n", str
.String(),
162 lDeviceImpl
->GetID());
164 TRACE_BT("BluetoothServer: Adding LocalDevice hci id invalid\n");
167 status
= B_WOULD_BLOCK
;
168 /* TODO: This should be by user request only! */
169 lDeviceImpl
->Launch();
173 case BT_MSG_REMOVE_DEVICE
:
175 LocalDeviceImpl
* lDeviceImpl
= LocateDelegateFromMessage(message
);
176 if (lDeviceImpl
!= NULL
) {
177 fLocalDevicesList
.RemoveItem(lDeviceImpl
);
183 case BT_MSG_COUNT_LOCAL_DEVICES
:
184 status
= HandleLocalDevicesCount(message
, &reply
);
187 case BT_MSG_ACQUIRE_LOCAL_DEVICE
:
188 status
= HandleAcquireLocalDevice(message
, &reply
);
191 case BT_MSG_HANDLE_SIMPLE_REQUEST
:
192 status
= HandleSimpleRequest(message
, &reply
);
195 case BT_MSG_GET_PROPERTY
:
196 status
= HandleGetProperty(message
, &reply
);
199 // Handle if the bluetooth preferences is running?
200 case B_SOME_APP_LAUNCHED
:
202 const char* signature
;
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) {
214 BApplication::MessageReceived(message
);
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();
234 BluetoothServer::LocateDelegateFromMessage(BMessage
* message
)
236 LocalDeviceImpl
* lDeviceImpl
= NULL
;
239 if (message
->FindInt32("hci_id", &hid
) == B_OK
) {
240 // Try to find out when a ID was specified
242 for (index
= 0; index
< fLocalDevicesList
.CountItems(); index
++) {
243 lDeviceImpl
= fLocalDevicesList
.ItemAt(index
);
244 if (lDeviceImpl
->GetID() == hid
)
255 BluetoothServer::LocateLocalDeviceImpl(hci_id hid
)
257 // Try to find out when a ID was specified
260 for (index
= 0; index
< fLocalDevicesList
.CountItems(); index
++) {
261 LocalDeviceImpl
* lDeviceImpl
= fLocalDevicesList
.ItemAt(index
);
262 if (lDeviceImpl
->GetID() == hid
)
271 #pragma - Messages reply
275 BluetoothServer::HandleLocalDevicesCount(BMessage
* message
, BMessage
* reply
)
277 TRACE_BT("BluetoothServer: count requested\n");
279 return reply
->AddInt32("count", fLocalDevicesList
.CountItems());
284 BluetoothServer::HandleAcquireLocalDevice(BMessage
* message
, BMessage
* reply
)
289 LocalDeviceImpl
* lDeviceImpl
= NULL
;
290 static int32 lastIndex
= 0;
292 if (message
->FindInt32("hci_id", &hid
) == B_OK
) {
293 TRACE_BT("BluetoothServer: GetLocalDevice requested with id\n");
294 lDeviceImpl
= LocateDelegateFromMessage(message
);
296 } else if (message
->FindData("bdaddr", B_ANY_TYPE
,
297 (const void**)&bdaddr
, &size
) == B_OK
) {
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();
303 // TODO: Only possible if the property is available
305 // lDeviceImpl = fLocalDevicesList.ItemAt(lastIndex);
306 // if ((lDeviceImpl->GetAddress(&local, message) == B_OK)
307 // && bacmp(&local, &bdaddr)) {
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());
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());
343 if (lastIndex
<= fLocalDevicesList
.CountItems() && lDeviceImpl
!= NULL
344 && lDeviceImpl
->Available()) {
346 hid
= lDeviceImpl
->GetID();
347 lDeviceImpl
->Acquire();
349 TRACE_BT("BluetoothServer: Device acquired %" B_PRId32
"\n", hid
);
350 return reply
->AddInt32("hci_id", hid
);
359 BluetoothServer::HandleSimpleRequest(BMessage
* message
, BMessage
* reply
)
361 LocalDeviceImpl
* lDeviceImpl
= LocateDelegateFromMessage(message
);
362 if (lDeviceImpl
== NULL
) {
366 const char* propertyRequested
;
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
)) {
373 reply
->AddMessage("properties", lDeviceImpl
->GetPropertiesMessage());
378 // we are gonna need issue the command ...
379 if (lDeviceImpl
->ProcessSimpleRequest(DetachCurrentMessage()) == B_OK
)
380 return B_WOULD_BLOCK
;
382 lDeviceImpl
->Unregister();
390 BluetoothServer::HandleGetProperty(BMessage
* message
, BMessage
* reply
)
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
395 LocalDeviceImpl
* lDeviceImpl
= LocateDelegateFromMessage(message
);
396 if (lDeviceImpl
== NULL
) {
400 const char* propertyRequested
;
402 // Find out if there is a property being requested,
403 if (message
->FindString("property", &propertyRequested
) == B_OK
) {
405 TRACE_BT("BluetoothServer: Searching %s property...\n", propertyRequested
);
407 // Check if the property has been already retrieved
408 if (lDeviceImpl
->IsPropertyAvailable(propertyRequested
)) {
411 if (strcmp(propertyRequested
, "hci_version") == 0
412 || strcmp(propertyRequested
, "lmp_version") == 0
413 || strcmp(propertyRequested
, "sco_mtu") == 0) {
415 uint8 result
= lDeviceImpl
->GetPropertiesMessage()->
416 FindInt8(propertyRequested
);
417 reply
->AddInt32("result", result
);
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 ) {
428 uint16 result
= lDeviceImpl
->GetPropertiesMessage()->
429 FindInt16(propertyRequested
);
430 reply
->AddInt32("result", result
);
433 } else if (strcmp(propertyRequested
, "role_switch_capable") == 0
434 || strcmp(propertyRequested
, "encrypt_capable") == 0) {
436 bool result
= lDeviceImpl
->GetPropertiesMessage()->
437 FindBool(propertyRequested
);
439 reply
->AddInt32("result", result
);
444 TRACE_BT("BluetoothServer: Property %s could not be satisfied\n", propertyRequested
);
458 BluetoothServer::SDPServerThread(void* data
)
460 const BluetoothServer
* server
= (BluetoothServer
*)data
;
462 // Set up the SDP socket
463 struct sockaddr_l2cap loc_addr
= { 0 };
467 char buffer
[512] = "";
469 TRACE_BT("SDP: SDP server thread up...\n");
471 socketServer
= socket(PF_BLUETOOTH
, SOCK_STREAM
, BLUETOOTH_PROTO_L2CAP
);
473 if (socketServer
< 0) {
474 TRACE_BT("SDP: Could not create server socket ...\n");
478 // bind socket to port 0x1001 of the first available
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
);
485 status
= bind(socketServer
, (struct sockaddr
*)&loc_addr
,
486 sizeof(struct sockaddr_l2cap
));
489 TRACE_BT("SDP: Could not bind server socket (%s)...\n", strerror(status
));
493 // setsockopt(sock, SOL_L2CAP, SO_L2CAP_OMTU, &omtu, len );
494 // getsockopt(sock, SOL_L2CAP, SO_L2CAP_IMTU, &omtu, &len );
496 // Listen for up to 10 connections
497 status
= listen(socketServer
, 10);
499 if (status
!= B_OK
) {
500 TRACE_BT("SDP: Could not listen server socket (%s)...\n", strerror(status
));
504 while (!server
->fIsShuttingDown
) {
506 TRACE_BT("SDP: Waiting connection for socket (%s)...\n", strerror(status
));
508 uint len
= sizeof(struct sockaddr_l2cap
);
509 client
= accept(socketServer
, (struct sockaddr
*)&loc_addr
, &len
);
511 TRACE_BT("SDP: Incomming connection... %d\n", client
);
513 ssize_t receivedSize
;
516 receivedSize
= recv(client
, buffer
, 29 , 0);
517 if (receivedSize
< 0)
518 TRACE_BT("SDP: Error reading client socket\n");
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
]);
526 } while (receivedSize
>= 0);
529 TRACE_BT("SDP: Waiting for next connection...\n");
540 BluetoothServer::ShowWindow(BWindow
* pWindow
)
543 if (pWindow
->IsHidden())
552 BluetoothServer::_InstallDeskbarIcon()
555 be_app
->GetAppInfo(&appInfo
);
559 if (deskbar
.HasItem(kDeskbarItemName
)) {
560 _RemoveDeskbarIcon();
563 status_t res
= deskbar
.AddItem(&appInfo
.ref
);
565 TRACE_BT("Failed adding deskbar icon: %" B_PRId32
"\n", res
);
570 BluetoothServer::_RemoveDeskbarIcon()
573 status_t res
= deskbar
.RemoveItem(kDeskbarItemName
);
575 TRACE_BT("Failed removing Deskbar icon: %" B_PRId32
": \n", res
);
584 main(int /*argc*/, char** /*argv*/)
586 BluetoothServer
* bluetoothServer
= new BluetoothServer
;
588 bluetoothServer
->Run();
589 delete bluetoothServer
;