xref: /haiku/src/servers/bluetooth/BluetoothServer.cpp (revision b87aa6b6121c91d4a932a0b3f877415f468808fe)
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