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