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