xref: /haiku/src/servers/bluetooth/BluetoothServer.cpp (revision a4ef4a49150f118d47324242917a596a3f8f8bd5)
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 
8 #include <stdio.h>
9 #include <fcntl.h>
10 #include <unistd.h>
11 
12 #include <Entry.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 "LocalDeviceImpl.h"
27 #include "BluetoothServer.h"
28 #include "Output.h"
29 
30 
31 BluetoothServer::BluetoothServer() : BApplication(BLUETOOTH_SIGNATURE)
32 {
33 	Output::Instance()->Run();
34 	Output::Instance()->SetTitle("Bluetooth message gathering");
35 
36 	Output::Instance()->AddTab("General", BLACKBOARD_GENERAL);
37 	Output::Instance()->AddTab("Device Manager", BLACKBOARD_DEVICEMANAGER);
38 	Output::Instance()->AddTab("Events", BLACKBOARD_EVENTS);
39 	Output::Instance()->AddTab("Kit", BLACKBOARD_KIT);
40 
41 	ShowWindow(Output::Instance());
42 
43 	fDeviceManager = new DeviceManager();
44 	fLocalDevicesList.MakeEmpty();
45 
46 	// TODO: Some events should be handled faster than in KL...
47 	fEventListener = spawn_thread(notification_Thread, "BT port listener" ,
48 					B_URGENT_DISPLAY_PRIORITY , this);
49 
50 }
51 
52 bool BluetoothServer::QuitRequested(void)
53 {
54 	// Finish quitting
55 	Output::Instance()->Lock();
56 	Output::Instance()->Quit();
57 
58 	LocalDeviceImpl* ldi = NULL;
59 	while ((ldi = (LocalDeviceImpl *)fLocalDevicesList.RemoveItem((int32)0))
60 		!= NULL)
61 		delete ldi;
62 
63 	printf("Accepting quitting of the application\n");
64 	return BApplication::QuitRequested();
65 }
66 
67 
68 void BluetoothServer::ArgvReceived(int32 argc, char **argv)
69 {
70 	if (argc>1) {
71 		if (strcmp(argv[1], "--finish") == 0)
72 			PostMessage(B_QUIT_REQUESTED);
73 	}
74 
75 }
76 
77 
78 void BluetoothServer::ReadyToRun(void)
79 {
80 	fDeviceManager->StartMonitoringDevice("bluetooth/h2generic");
81 	// Launch the notifier thread
82 	if ( resume_thread(fEventListener) != B_OK )
83 	{
84 		Output::Instance()->Post("Bluetooth port listener failed\n", BLACKBOARD_GENERAL);
85 	}
86 
87 	Output::Instance()->Post("Bluetooth server Ready\n", BLACKBOARD_GENERAL);
88 }
89 
90 
91 void BluetoothServer::AppActivated(bool act)
92 {
93 	printf("Activated %d\n",act);
94 }
95 
96 
97 void BluetoothServer::MessageReceived(BMessage *message)
98 {
99 	BMessage reply;
100 	status_t status = B_WOULD_BLOCK;
101 		// mark somehow.. do not reply anything
102 
103 	switch(message->what)
104 	{
105 		case BT_MSG_ADD_DEVICE:
106 		{
107 			BString str;
108 			message->FindString("name", &str);
109 			BPath path(str.String());
110 			Output::Instance()->Postf(BLACKBOARD_GENERAL,
111 							"Requested LocalDevice %s\n", str.String());
112 			LocalDeviceImpl* ldi = LocalDeviceImpl::CreateTransportAccessor(&path);
113 
114 			if (ldi->GetID() >= 0) {
115 				fLocalDevicesList.AddItem(ldi);
116 				Output::Instance()->AddTab("Local Device", BLACKBOARD_LD(ldi->GetID()));
117 				Output::Instance()->Postf(BLACKBOARD_LD(ldi->GetID()),
118 						"LocalDevice %s id=%x added\n",
119 						str.String(), ldi->GetID());
120 			} else {
121 				Output::Instance()->Post("Adding LocalDevice failed\n",
122 								 BLACKBOARD_GENERAL);
123 			}
124 
125 			status = B_WOULD_BLOCK;
126 			/* TODO: This should be by user request only! */
127 			ldi->Launch();
128 		}
129 		break;
130 		case BT_MSG_COUNT_LOCAL_DEVICES:
131 			status = HandleLocalDevicesCount(message, &reply);
132 		break;
133 		case BT_MSG_ACQUIRE_LOCAL_DEVICE:
134 			status = HandleAcquireLocalDevice(message, &reply);
135 		break;
136 
137 		case BT_MSG_HANDLE_SIMPLE_REQUEST:
138 			status = HandleSimpleRequest(message, &reply);
139 		break;
140 		/* Handle if the bluetooth preferences is running?? */
141 		case B_SOME_APP_LAUNCHED:
142    		{
143 			const char *signature;
144 			// TODO: what's this for?
145 			if (message->FindString("be:signature", &signature) == B_OK) {
146 				printf("input_server : %s\n", signature);
147 				if (strcmp(signature, "application/x-vnd.Be-TSKB") == 0) {
148 
149 				}
150 			}
151 			return;
152 		}
153 
154 		default:
155 			BApplication::MessageReceived(message);
156 		break;
157 	}
158 
159 	// Can we reply right now?
160 	// TOD: review this condition
161 	if (status != B_WOULD_BLOCK) {
162 		reply.AddInt32("status", status);
163 		message->SendReply(&reply);
164 		printf("Sending reply message\n");
165 	}
166 }
167 
168 #if 0
169 #pragma mark -
170 #endif
171 
172 LocalDeviceImpl*
173 BluetoothServer::LocateDelegateFromMessage(BMessage* message)
174 {
175 	LocalDeviceImpl* ldi = NULL;
176 	hci_id hid;
177 
178 	if (message->FindInt32("hci_id", &hid) == B_OK) {
179 		/* Try to find out when a ID was specified */
180 		int index;
181 		for (index = 0; index < fLocalDevicesList.CountItems(); index ++) {
182 		    ldi = fLocalDevicesList.ItemAt(index);
183 		    if (ldi->GetID() == hid)
184 		        break;
185 		}
186 	}
187 
188 	return ldi;
189 
190 }
191 
192 LocalDeviceImpl*
193 BluetoothServer::LocateLocalDeviceImpl(hci_id hid)
194 {
195 	/* Try to find out when a ID was specified */
196 	int index;
197 
198 	for (index = 0; index < fLocalDevicesList.CountItems(); index ++) {
199 		LocalDeviceImpl* ldi = fLocalDevicesList.ItemAt(index);
200 		if (ldi->GetID() == hid)
201 			return ldi;
202 	}
203 
204 	return NULL;
205 }
206 
207 
208 #if 0
209 #pragma - Messages reply
210 #endif
211 
212 status_t
213 BluetoothServer::HandleLocalDevicesCount(BMessage* message, BMessage* reply)
214 {
215 	return reply->AddInt32("count", fLocalDevicesList.CountItems());
216 }
217 
218 
219 status_t
220 BluetoothServer::HandleAcquireLocalDevice(BMessage* message, BMessage* reply)
221 {
222 	hci_id hid;
223 	ssize_t size;
224 	bdaddr_t bdaddr;
225 	LocalDeviceImpl* ldi = NULL;
226 	int32 index = 0;
227 
228 	if (message->FindInt32("hci_id", &hid) == B_OK)
229 	{
230 		Output::Instance()->Post("GetLocalDevice requested with id\n",
231 						BLACKBOARD_KIT);
232 		ldi = LocateDelegateFromMessage(message);
233 
234 	} else if (message->FindData("bdaddr", B_ANY_TYPE, (const void**)&bdaddr, &size )
235 			== B_OK) {
236 		/* Try to find out when the user specified the address */
237 		Output::Instance()->Post("GetLocalDevice requested with bdaddr\n",
238 						BLACKBOARD_KIT);
239 		for (index = 0; index < fLocalDevicesList.CountItems(); index ++) {
240 			bdaddr_t local;
241 			ldi = fLocalDevicesList.ItemAt(index);
242 			// TODO: Only if the property is available
243 			//if ((ldi->GetAddress(&local, message) == B_OK)
244 			//	&& bacmp(&local, &bdaddr))  {
245 			//    break;
246 			//}
247 		}
248 
249 		} else	{
250 			/* Careless, any device not performing operations will be fine */
251 			Output::Instance()->Post("GetLocalDevice requested\n", BLACKBOARD_KIT);
252 			for (index = 0; index < fLocalDevicesList.CountItems(); index ++) {
253 				ldi = fLocalDevicesList.ItemAt(index);
254 				printf("Requesting local device %ld\n", ldi->GetID());
255 				if (ldi != NULL && ldi->Available())
256 				{
257 					printf("dev ours %ld\n", ldi->GetID());
258 					break;
259 				}
260 			}
261 		}
262 
263 	if (index <= fLocalDevicesList.CountItems() && ldi != NULL && ldi->Available()) {
264 		Output::Instance()->Post("Device acquired\n", BLACKBOARD_KIT);
265 		ldi->Acquire();
266 		return reply->AddInt32("hci_id", hid);
267 	}
268 
269 	return B_ERROR;
270 
271 }
272 
273 
274 status_t
275 BluetoothServer::HandleSimpleRequest(BMessage* message, BMessage* reply)
276 {
277 	LocalDeviceImpl* ldi = LocateDelegateFromMessage(message);
278 	BString propertyRequested;
279 
280 	// Find out if there is a property being requested,
281 	if (message->FindString("property", &propertyRequested) == B_OK) {
282 		// Check if the property has been already retrieved
283 		if (ldi->IsPropertyAvailable(propertyRequested)) {
284 			// Dump everything
285 			reply->AddMessage("properties",ldi->GetPropertiesMessage());
286 			return B_OK;
287 		}
288 	}
289 
290 	// we are gonna need issue the command ...
291 	if (ldi->ProcessSimpleRequest(DetachCurrentMessage()) == B_OK)
292 		return B_WOULD_BLOCK;
293 	else
294 		return B_ERROR;
295 
296 }
297 
298 
299 #if 0
300 #pragma mark -
301 #endif
302 
303 
304 int32
305 BluetoothServer::notification_Thread(void* data)
306 {
307 	BPortNot notifierd((BluetoothServer*)data, BT_USERLAND_PORT_NAME);
308 
309 	notifierd.loop();
310 	return B_NO_ERROR;
311 }
312 
313 int32
314 BluetoothServer::sdp_server_Thread(void* data)
315 {
316 
317 	return B_NO_ERROR;
318 }
319 
320 
321 void
322 BluetoothServer::ShowWindow(BWindow* pWindow)
323 {
324 	pWindow->Lock();
325 	if (pWindow->IsHidden())
326 		pWindow->Show();
327 	else
328 		pWindow->Activate();
329 	pWindow->Unlock();
330 }
331 
332 
333 #if 0
334 #pragma mark -
335 #endif
336 
337 int
338 main(int /*argc*/, char** /*argv*/)
339 {
340 	setbuf(stdout, NULL);
341 
342 	BluetoothServer* bluetoothServer = new BluetoothServer;
343 
344 	bluetoothServer->Run();
345 	delete bluetoothServer;
346 
347 	return 0;
348 }
349 
350