xref: /haiku/src/servers/bluetooth/LocalDeviceImpl.cpp (revision b30304acc8c37e678a1bf66976d15bdab103f931)
1 /*
2  * Copyright 2008 Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com
3  *
4  * All rights reserved. Distributed under the terms of the MIT License.
5  *
6  */
7 
8 
9 #include "BluetoothServer.h"
10 
11 #include "LocalDeviceImpl.h"
12 #include "CommandManager.h"
13 #include "Output.h"
14 
15 #include <bluetooth/bluetooth_error.h>
16 #include <bluetooth/HCI/btHCI_event.h>
17 
18 #include <bluetoothserver_p.h>
19 
20 #include <stdio.h>
21 
22 
23 #if 0
24 #pragma mark - Class methods -
25 #endif
26 
27 
28 // Factory methods
29 LocalDeviceImpl*
30 LocalDeviceImpl::CreateControllerAccessor(BPath* path)
31 {
32     HCIDelegate* hd = new HCIControllerAccessor(path);
33 
34     if ( hd != NULL)
35         return new LocalDeviceImpl(hd);
36     else
37         return NULL;
38 }
39 
40 
41 LocalDeviceImpl*
42 LocalDeviceImpl::CreateTransportAccessor(BPath* path)
43 {
44     HCIDelegate* hd = new HCITransportAccessor(path);
45 
46     if ( hd != NULL)
47         return new LocalDeviceImpl(hd);
48     else
49         return NULL;
50 }
51 
52 
53 LocalDeviceImpl::LocalDeviceImpl(HCIDelegate* hd) : LocalDeviceHandler(hd)
54 {
55 
56 }
57 
58 #if 0
59 #pragma mark - Event handling methods -
60 #endif
61 
62 void
63 LocalDeviceImpl::HandleEvent(struct hci_event_header* event)
64 {
65 
66 printf("### Event comming: len = %d\n", event->elen);
67 for (int16 index = 0 ; index < event->elen + 2; index++ ) {
68 	printf("%x:",((uint8*)event)[index]);
69 }
70 printf("### \n");
71 
72 	// Events here might have not been initated by us
73     switch (event->ecode) {
74 	        case HCI_EVENT_HARDWARE_ERROR:
75    				//HardwareError(event);
76    			return;
77 			case HCI_EVENT_CONN_REQUEST:
78 
79 			break;
80 
81    			default:
82    				// lets go on
83    			break;
84 	}
85 
86 
87 
88 	BMessage* request = NULL;
89 
90 	// Check if its a requested one
91 	if ( event->ecode == HCI_EVENT_CMD_COMPLETE ) {
92 
93 		(Output::Instance()->Post("Incoming Command Complete\n", BLACKBOARD_EVENTS));
94 		request = FindPetition(event->ecode, ((struct hci_ev_cmd_complete*)(event+1))->opcode );
95 
96 	} else if ( event->ecode == HCI_EVENT_CMD_STATUS ) {
97 
98 		(Output::Instance()->Post("Incoming Command Status\n", BLACKBOARD_EVENTS));
99 		request = FindPetition(event->ecode, ((struct hci_ev_cmd_status*)(event+1))->opcode );
100 
101 	} else
102 	{
103 		request = FindPetition(event->ecode);
104 	}
105 
106 	if ( request == NULL) {
107 		(Output::Instance()->Post("Event could not be understood or delivered\n", BLACKBOARD_EVENTS));
108 		return;
109 	}
110 
111 	// we are waiting for a reply
112 	switch (event->ecode) {
113 		case HCI_EVENT_INQUIRY_COMPLETE:
114     		InquiryComplete((uint8*)(event+1), request);
115     	break;
116 
117     	case HCI_EVENT_INQUIRY_RESULT:
118     		InquiryResult((uint8*)(event+1), request);
119 		break;
120 
121 		case HCI_EVENT_CONN_COMPLETE:
122 		break;
123 
124 		case HCI_EVENT_DISCONNECTION_COMPLETE:
125 		break;
126 
127 		case HCI_EVENT_AUTH_COMPLETE:
128 		break;
129 
130 		case HCI_EVENT_REMOTE_NAME_REQUEST_COMPLETE:
131 			RemoteNameRequestComplete((struct hci_remote_name_request_complete_reply*)(event+1), request);
132 		break;
133 
134 		case HCI_EVENT_ENCRYPT_CHANGE:
135 		break;
136 
137 		case HCI_EVENT_CHANGE_CONN_LINK_KEY_COMPLETE:
138 		break;
139 
140 		case HCI_EVENT_MASTER_LINK_KEY_COMPL:
141 		break;
142 
143 		case HCI_EVENT_RMT_FEATURES:
144 		break;
145 
146 		case HCI_EVENT_RMT_VERSION:
147 		break;
148 
149 		case HCI_EVENT_QOS_SETUP_COMPLETE:
150 		break;
151 
152 		case HCI_EVENT_CMD_COMPLETE:
153 			CommandComplete((struct hci_ev_cmd_complete*)(event+1), request);
154  		break;
155 
156  		case HCI_EVENT_CMD_STATUS:
157  			CommandStatus((struct hci_ev_cmd_status*)(event+1), request);
158 		break;
159 
160 		case HCI_EVENT_FLUSH_OCCUR:
161 		break;
162 
163 		case HCI_EVENT_ROLE_CHANGE:
164 		break;
165 
166 		case HCI_EVENT_NUM_COMP_PKTS:
167 		break;
168 
169 		case HCI_EVENT_MODE_CHANGE:
170 		break;
171 
172 		case HCI_EVENT_RETURN_LINK_KEYS:
173 		break;
174 
175 		case HCI_EVENT_PIN_CODE_REQ:
176 		break;
177 
178 		case HCI_EVENT_LINK_KEY_REQ:
179 		break;
180 
181 		case HCI_EVENT_LINK_KEY_NOTIFY:
182 		break;
183 
184 		case HCI_EVENT_LOOPBACK_COMMAND:
185 		break;
186 
187 		case HCI_EVENT_DATA_BUFFER_OVERFLOW:
188 		break;
189 
190 		case HCI_EVENT_MAX_SLOT_CHANGE:
191 		break;
192 
193 		case HCI_EVENT_READ_CLOCK_OFFSET_COMPL:
194 		break;
195 
196 		case HCI_EVENT_CON_PKT_TYPE_CHANGED:
197 		break;
198 
199 		case HCI_EVENT_QOS_VIOLATION:
200 		break;
201 
202 		case HCI_EVENT_PAGE_SCAN_REP_MODE_CHANGE:
203 		break;
204 
205 		case HCI_EVENT_FLOW_SPECIFICATION:
206 		break;
207 
208 		case HCI_EVENT_INQUIRY_RESULT_WITH_RSSI:
209 		break;
210 
211 		case HCI_EVENT_REMOTE_EXTENDED_FEATURES:
212 		break;
213 
214 		case HCI_EVENT_SYNCHRONOUS_CONNECTION_COMPLETED:
215 		break;
216 
217 		case HCI_EVENT_SYNCHRONOUS_CONNECTION_CHANGED:
218 
219 		break;
220 	}
221 
222 }
223 
224 
225 void
226 LocalDeviceImpl::CommandComplete(struct hci_ev_cmd_complete* event, BMessage* request) {
227 
228 	int16   opcodeExpected;
229 	BMessage reply;
230 
231     Output::Instance()->Post(__FUNCTION__, BLACKBOARD_LD_OFFSET + GetID());
232     Output::Instance()->Post("\n", BLACKBOARD_LD_OFFSET + GetID());
233 
234 	// Handle command complete information
235 	// FIX ME! the expected code might me in another
236 	// index as is relative to the event not the request
237     request->FindInt16("opcodeExpected", 0 /*REVIEW!*/, &opcodeExpected);
238 
239 
240 	if (request->IsSourceWaiting() == false)
241 		Output::Instance()->Post("Nobody waiting for the event\n", BLACKBOARD_KIT);
242 
243 
244     switch (opcodeExpected) {
245 
246         case PACK_OPCODE(OGF_INFORMATIONAL_PARAM, OCF_READ_BD_ADDR):
247         {
248         	struct hci_rp_read_bd_addr* readbdaddr = (struct hci_rp_read_bd_addr*)(event+1);
249 
250             if (readbdaddr->status == BT_OK) {
251 
252 
253                 reply.AddData("bdaddr", B_ANY_TYPE, &readbdaddr->bdaddr, sizeof(bdaddr_t));
254                 reply.AddInt32("status", readbdaddr->status);
255 
256                 printf("Sending reply ... %ld\n",request->SendReply(&reply));
257                 reply.PrintToStream();
258 
259 
260 			    Output::Instance()->Post("Positive reply for getAdress\n", BLACKBOARD_KIT);
261 
262             } else {
263                 reply.AddInt8("status", readbdaddr->status);
264                 request->SendReply(&reply);
265 			    Output::Instance()->Post("Negative reply for getAdress\n", BLACKBOARD_KIT);
266             }
267 
268  			// This request is not genna be used anymore
269             ClearWantedEvent(request);
270      	}
271         break;
272 
273         case PACK_OPCODE(OGF_CONTROL_BASEBAND, OCF_READ_LOCAL_NAME):
274         {
275         	struct hci_rp_read_local_name* readLocalName = (struct hci_rp_read_local_name*)(event+1);
276 
277         	reply.AddInt8("status", readLocalName->status);
278 
279             if (readLocalName->status == BT_OK) {
280 
281                 reply.AddString("friendlyname", (const char*)readLocalName->local_name );
282 			    Output::Instance()->Post("Positive reply for friendly name\n", BLACKBOARD_KIT);
283 
284             } else {
285 
286 			    Output::Instance()->Post("Negative reply for friendly name\n", BLACKBOARD_KIT);
287 
288             }
289 
290             printf("Sending reply ... %ld\n",request->SendReply(&reply));
291             reply.PrintToStream();
292 
293  			// This request is not genna be used anymore
294             ClearWantedEvent(request);
295      	}
296         break;
297 
298         case PACK_OPCODE(OGF_CONTROL_BASEBAND, OCF_WRITE_SCAN_ENABLE):
299         {
300         	uint8* statusReply = (uint8*)(event+1);
301 
302         	reply.AddInt8("status", *statusReply);
303 
304             if (*statusReply == BT_OK) {
305 
306                 Output::Instance()->Post("Positive reply for scanmode\n", BLACKBOARD_KIT);
307 
308             } else {
309 
310                 Output::Instance()->Post("Negative reply for scanmode\n", BLACKBOARD_KIT);
311 
312             }
313 
314             printf("Sending reply ... %ld\n",request->SendReply(&reply));
315             reply.PrintToStream();
316 
317  			// This request is not genna be used anymore
318             ClearWantedEvent(request);
319      	}
320         break;
321 
322 		default:
323 		    Output::Instance()->Post("Command Complete not handled\n", BLACKBOARD_KIT);
324 		break;
325 
326 
327     }
328 }
329 
330 
331 void
332 LocalDeviceImpl::CommandStatus(struct hci_ev_cmd_status* event, BMessage* request) {
333 
334 	int16   opcodeExpected;
335 	BMessage reply;
336 
337     Output::Instance()->Post(__FUNCTION__, BLACKBOARD_LD_OFFSET + GetID());
338     Output::Instance()->Post("\n", BLACKBOARD_LD_OFFSET + GetID());
339 
340 	// Handle command complete information
341     request->FindInt16("opcodeExpected", 0 /*REVIEW!*/, &opcodeExpected);
342 
343 
344 	if (request->IsSourceWaiting() == false)
345 		Output::Instance()->Post("Nobody waiting for the event\n", BLACKBOARD_KIT);
346 
347 
348     switch (opcodeExpected) {
349 
350         case PACK_OPCODE(OGF_LINK_CONTROL, OCF_INQUIRY):
351         {
352         	reply.what = BT_MSG_INQUIRY_STARTED;
353         	reply.AddInt8("status", event->status);
354 
355             if (event->status == BT_OK) {
356 			    Output::Instance()->Post("Positive reply for inquiry status\n", BLACKBOARD_KIT);
357             } else {
358 			    Output::Instance()->Post("Negative reply for inquiry status\n", BLACKBOARD_KIT);
359             }
360 
361             printf("Sending reply ... %ld\n", request->SendReply(&reply));
362             reply.PrintToStream();
363 
364             ClearWantedEvent(request, HCI_EVENT_CMD_STATUS, PACK_OPCODE(OGF_LINK_CONTROL, OCF_INQUIRY));
365      	}
366         break;
367 
368 		default:
369 		    Output::Instance()->Post("Command Status not handled\n", BLACKBOARD_KIT);
370 		break;
371 	}
372 
373 }
374 
375 
376 void
377 LocalDeviceImpl::InquiryResult(uint8* numberOfResponses, BMessage* request)
378 {
379 
380 	BMessage reply(BT_MSG_INQUIRY_DEVICE);
381 
382 
383     reply.AddData("info", B_ANY_TYPE, numberOfResponses+1 // skiping here the number of responses
384                         , (*numberOfResponses) * sizeof(struct inquiry_info) );
385 
386     printf("%s: Sending reply ... %ld\n",__FUNCTION__, request->SendReply(&reply));
387 
388 }
389 
390 
391 void
392 LocalDeviceImpl::InquiryComplete(uint8* status, BMessage* request)
393 {
394 	BMessage reply(BT_MSG_INQUIRY_COMPLETED);
395 
396 	reply.AddInt8("status", *status);
397 
398 
399     printf("%s: Sending reply ... %ld\n",__FUNCTION__, request->SendReply(&reply));
400 //    (request->ReturnAddress()).SendMessage(&reply);
401 
402     ClearWantedEvent(request);
403 }
404 
405 
406 void
407 LocalDeviceImpl::RemoteNameRequestComplete(struct hci_remote_name_request_complete_reply* remotename, BMessage* request)
408 {
409 	BMessage reply;
410 
411   	reply.AddInt8("status", remotename->status);
412 
413     if (remotename->status == BT_OK) {
414 
415         reply.AddString("friendlyname", (const char*)remotename->remote_name );
416 	    Output::Instance()->Post("Positive reply for remote friendly name\n", BLACKBOARD_KIT);
417 
418     } else {
419 
420 	    Output::Instance()->Post("Negative reply for remote friendly name\n", BLACKBOARD_KIT);
421 
422     }
423 
424     printf("Sending reply ... %ld\n", request->SendReply(&reply));
425     reply.PrintToStream();
426 
427 	// This request is not genna be used anymore
428 	// Although there are many middle events that should be tracked
429     ClearWantedEvent(request);
430 
431 }
432 
433 
434 #if 0
435 #pragma mark - Request Methods -
436 #endif
437 
438 
439 status_t
440 LocalDeviceImpl::GetAddress(bdaddr_t* bdaddr, BMessage* request)
441 {
442 	ssize_t size;
443 
444 	if (fProperties->FindData("bdaddr", B_ANY_TYPE, 0, (const void **)bdaddr, &size) == B_OK) {
445 
446 		(Output::Instance()->Post("BDADDR already present in server\n", BLACKBOARD_EVENTS));
447 	    /* We have this info, returning back */
448 	    return B_OK;
449 
450 	} else {
451 		size_t size;
452 
453 	    void* command = buildReadBdAddr(&size);
454 
455 	    /* Adding a wanted event in the queue */
456 	    request->AddInt16("eventExpected",  HCI_EVENT_CMD_COMPLETE);
457 	    request->AddInt16("opcodeExpected", PACK_OPCODE(OGF_INFORMATIONAL_PARAM, OCF_READ_BD_ADDR));
458 
459 	    printf("Adding request... %p\n", request);
460 	    AddWantedEvent(request);
461 		request->PrintToStream();
462 
463 	    if (((HCITransportAccessor*)fHCIDelegate)->IssueCommand(command, size) == B_ERROR)
464 			(Output::Instance()->Post("Command issue error\n", BLACKBOARD_EVENTS));
465 
466 		(Output::Instance()->Post("Command issued for GetAddress\n", BLACKBOARD_EVENTS));
467 	    return B_WOULD_BLOCK;
468 	}
469 
470 }
471 
472 
473 status_t
474 LocalDeviceImpl::GetFriendlyName(BString str, BMessage* request)
475 {
476 
477 	if (fProperties->FindString("friendlyname", &str) == B_OK) {
478 
479 		(Output::Instance()->Post("Friendly name already present in server\n", BLACKBOARD_EVENTS));
480 	    /* We have this info, returning back */
481 	    return B_OK;
482 
483 	} else {
484 		size_t size;
485 
486 	    void* command = buildReadLocalName(&size);
487 
488 	    /* Adding a wanted event in the queue */
489 	    request->AddInt16("eventExpected",  HCI_EVENT_CMD_COMPLETE);
490 	    request->AddInt16("opcodeExpected", PACK_OPCODE(OGF_CONTROL_BASEBAND, OCF_READ_LOCAL_NAME));
491 
492 	    printf("Adding request... %p\n", request);
493 	    AddWantedEvent(request);
494 		request->PrintToStream();
495 
496 	    if (((HCITransportAccessor*)fHCIDelegate)->IssueCommand(command, size) == B_ERROR)
497 			(Output::Instance()->Post("Command issue error\n", BLACKBOARD_EVENTS));
498 
499 		(Output::Instance()->Post("Command issued for GetFriendlyname\n", BLACKBOARD_EVENTS));
500 
501 	    return B_WOULD_BLOCK;
502 	}
503 
504 }
505 
506 
507 status_t
508 LocalDeviceImpl::ProcessSimpleRequest(BMessage* request)
509 {
510 	ssize_t size;
511 	void* command = NULL;
512 
513 	if (request->FindData("raw command", B_ANY_TYPE, 0, (const void **)&command, &size) == B_OK)
514 	    if (((HCITransportAccessor*)fHCIDelegate)->IssueCommand(command, size) == B_ERROR)
515 			(Output::Instance()->Post("Command issue error\n", BLACKBOARD_EVENTS));
516 		else
517 		{
518 		    AddWantedEvent(request);
519 			return B_OK;
520 		}
521 	else {
522 		(Output::Instance()->Post("No command specified for simple request\n", BLACKBOARD_KIT));
523 	}
524 
525 	return B_ERROR;
526 }
527