xref: /haiku/src/servers/bluetooth/LocalDeviceImpl.cpp (revision 220d04022750f40f8bac8f01fa551211e28d04f2)
1 /*
2  * Copyright 2008 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 "BluetoothServer.h"
9 
10 #include "LocalDeviceImpl.h"
11 #include "CommandManager.h"
12 #include "Output.h"
13 
14 #include <bluetooth/bdaddrUtils.h>
15 #include <bluetooth/bluetooth_error.h>
16 #include <bluetooth/LinkKeyUtils.h>
17 #include <bluetooth/RemoteDevice.h>
18 #include <bluetooth/HCI/btHCI_event.h>
19 
20 #include <bluetoothserver_p.h>
21 #include <ConnectionIncoming.h>
22 #include <PincodeWindow.h>
23 
24 #include <stdio.h>
25 #include <new>
26 
27 
28 #if 0
29 #pragma mark - Class methods -
30 #endif
31 
32 
33 // Factory methods
34 LocalDeviceImpl*
35 LocalDeviceImpl::CreateControllerAccessor(BPath* path)
36 {
37 	HCIDelegate* delegate = new(std::nothrow) HCIControllerAccessor(path);
38 	if (delegate == NULL)
39 		return NULL;
40 
41 	LocalDeviceImpl* device = new(std::nothrow) LocalDeviceImpl(delegate);
42 	if (device == NULL) {
43 		delete delegate;
44 		return NULL;
45 	}
46 
47 	return device;
48 }
49 
50 
51 LocalDeviceImpl*
52 LocalDeviceImpl::CreateTransportAccessor(BPath* path)
53 {
54 	HCIDelegate* delegate = new(std::nothrow) HCITransportAccessor(path);
55 	if (delegate == NULL)
56 		return NULL;
57 
58 	LocalDeviceImpl* device = new(std::nothrow) LocalDeviceImpl(delegate);
59 	if (device == NULL) {
60 		delete delegate;
61 		return NULL;
62 	}
63 
64 	return device;
65 }
66 
67 
68 LocalDeviceImpl::LocalDeviceImpl(HCIDelegate* hd) : LocalDeviceHandler(hd)
69 {
70 
71 }
72 
73 
74 LocalDeviceImpl::~LocalDeviceImpl()
75 {
76 
77 }
78 
79 
80 void
81 LocalDeviceImpl::Unregister()
82 {
83 	BMessage* msg =	new	BMessage(BT_MSG_REMOVE_DEVICE);
84 
85 	msg->AddInt32("hci_id", fHCIDelegate->Id());
86 
87 	Output::Instance()->Postf(BLACKBOARD_DEVICEMANAGER, "Unregistering %x\n",
88 		fHCIDelegate->Id());
89 
90 	be_app_messenger.SendMessage(msg);
91 }
92 
93 
94 #if 0
95 #pragma mark - Event handling methods -
96 #endif
97 
98 template<typename T, typename Header>
99 inline T*
100 JumpEventHeader(Header* event)
101 {
102 	return (T*)(event + 1);
103 }
104 
105 
106 void
107 LocalDeviceImpl::HandleUnexpectedEvent(struct hci_event_header* event)
108 {
109 	// Events here might have not been initated by us
110 	// TODO: ML mark as handled pass a reply by parameter and reply in common
111 	switch (event->ecode) {
112 		case HCI_EVENT_HARDWARE_ERROR:
113 			HardwareError(
114 				JumpEventHeader<struct hci_ev_hardware_error>(event));
115 			break;
116 
117 		case HCI_EVENT_CONN_REQUEST:
118 			ConnectionRequest(
119 				JumpEventHeader<struct hci_ev_conn_request>(event), NULL);
120 			break;
121 
122 		case HCI_EVENT_NUM_COMP_PKTS:
123 			NumberOfCompletedPackets(
124 				JumpEventHeader<struct hci_ev_num_comp_pkts>(event));
125 			break;
126 
127 		case HCI_EVENT_DISCONNECTION_COMPLETE:
128 			// should belong to a request?  can be sporadic or initiated by us¿?...
129 			DisconnectionComplete(
130 				JumpEventHeader<struct hci_ev_disconnection_complete_reply>(event),
131 				NULL);
132 			break;
133 		case HCI_EVENT_PIN_CODE_REQ:
134 			PinCodeRequest(
135 				JumpEventHeader<struct hci_ev_pin_code_req>(event), NULL);
136 			break;
137 		default:
138 			// TODO: feedback unexpected not handled
139 			break;
140 	}
141 }
142 
143 
144 void
145 LocalDeviceImpl::HandleExpectedRequest(struct hci_event_header* event,
146 	BMessage* request)
147 {
148 	// we are waiting for a reply
149 	switch (event->ecode) {
150 		case HCI_EVENT_INQUIRY_COMPLETE:
151 			InquiryComplete(JumpEventHeader<uint8>(event), request);
152 			break;
153 
154 		case HCI_EVENT_INQUIRY_RESULT:
155 			InquiryResult(JumpEventHeader<uint8>(event), request);
156 			break;
157 
158 		case HCI_EVENT_CONN_COMPLETE:
159 			ConnectionComplete(
160 				JumpEventHeader<struct hci_ev_conn_complete>(event), request);
161 			break;
162 
163 		case HCI_EVENT_DISCONNECTION_COMPLETE:
164 			// should belong to a request?  can be sporadic or initiated by us¿?...
165 			DisconnectionComplete(
166 				JumpEventHeader<struct hci_ev_disconnection_complete_reply>
167 				(event), request);
168 			break;
169 
170 		case HCI_EVENT_AUTH_COMPLETE:
171 
172 			break;
173 
174 		case HCI_EVENT_REMOTE_NAME_REQUEST_COMPLETE:
175 			RemoteNameRequestComplete(
176 				JumpEventHeader<struct hci_ev_remote_name_request_complete_reply>
177 				(event), request);
178 			break;
179 
180 		case HCI_EVENT_ENCRYPT_CHANGE:
181 			break;
182 
183 		case HCI_EVENT_CHANGE_CONN_LINK_KEY_COMPLETE:
184 			break;
185 
186 		case HCI_EVENT_MASTER_LINK_KEY_COMPL:
187 			break;
188 
189 		case HCI_EVENT_RMT_FEATURES:
190 			break;
191 
192 		case HCI_EVENT_RMT_VERSION:
193 			break;
194 
195 		case HCI_EVENT_QOS_SETUP_COMPLETE:
196 			break;
197 
198 		case HCI_EVENT_FLUSH_OCCUR:
199 			break;
200 
201 		case HCI_EVENT_ROLE_CHANGE:
202 			RoleChange(JumpEventHeader<struct hci_ev_role_change>(event), request);
203 			break;
204 
205 		case HCI_EVENT_MODE_CHANGE:
206 			break;
207 
208 		case HCI_EVENT_RETURN_LINK_KEYS:
209 			ReturnLinkKeys(JumpEventHeader<struct hci_ev_return_link_keys>(event));
210 			break;
211 
212 		case HCI_EVENT_LINK_KEY_REQ:
213 			LinkKeyRequested(
214 				JumpEventHeader<struct hci_ev_link_key_req>(event), request);
215 			break;
216 
217 		case HCI_EVENT_LINK_KEY_NOTIFY:
218 			LinkKeyNotify(JumpEventHeader<struct hci_ev_link_key_notify>
219 				(event), request);
220 			break;
221 
222 		case HCI_EVENT_LOOPBACK_COMMAND:
223 			break;
224 
225 		case HCI_EVENT_DATA_BUFFER_OVERFLOW:
226 			break;
227 
228 		case HCI_EVENT_MAX_SLOT_CHANGE:
229 			MaxSlotChange(JumpEventHeader<struct hci_ev_max_slot_change>(event),
230 			request);
231 			break;
232 
233 		case HCI_EVENT_READ_CLOCK_OFFSET_COMPL:
234 			break;
235 
236 		case HCI_EVENT_CON_PKT_TYPE_CHANGED:
237 			break;
238 
239 		case HCI_EVENT_QOS_VIOLATION:
240 			break;
241 
242 		case HCI_EVENT_PAGE_SCAN_REP_MODE_CHANGE:
243 			PageScanRepetitionModeChange(
244 				JumpEventHeader<struct hci_ev_page_scan_rep_mode_change>(event),
245 				request);
246 			break;
247 
248 		case HCI_EVENT_FLOW_SPECIFICATION:
249 			break;
250 
251 		case HCI_EVENT_INQUIRY_RESULT_WITH_RSSI:
252 			break;
253 
254 		case HCI_EVENT_REMOTE_EXTENDED_FEATURES:
255 			break;
256 
257 		case HCI_EVENT_SYNCHRONOUS_CONNECTION_COMPLETED:
258 			break;
259 
260 		case HCI_EVENT_SYNCHRONOUS_CONNECTION_CHANGED:
261 			break;
262 	}
263 }
264 
265 
266 void
267 LocalDeviceImpl::HandleEvent(struct hci_event_header* event)
268 {
269 /*
270 
271 	printf("### Incoming event: len = %d\n", event->elen);
272 	for (int16 index = 0; index < event->elen + 2; index++) {
273 		printf("%x:", ((uint8*)event)[index]);
274 	}
275 	printf("### \n");
276 */
277 	BMessage* request = NULL;
278 	int32 eventIndexLocation;
279 
280 	// Check if it is a requested one
281 	switch (event->ecode) {
282 		case HCI_EVENT_CMD_COMPLETE:
283 		{
284 			struct hci_ev_cmd_complete* commandComplete
285 				= JumpEventHeader<struct hci_ev_cmd_complete>(event);
286 
287 			Output::Instance()->Postf(BLACKBOARD_LD(GetID()),
288 				"Incomming CommandComplete(%d) for %s\n", commandComplete->ncmd,
289 				BluetoothCommandOpcode(commandComplete->opcode));
290 
291 			request = FindPetition(event->ecode, commandComplete->opcode,
292 				&eventIndexLocation);
293 
294 			if (request != NULL)
295 				CommandComplete(commandComplete, request, eventIndexLocation);
296 
297 			break;
298 		}
299 		case HCI_EVENT_CMD_STATUS:
300 		{
301 			struct hci_ev_cmd_status* commandStatus
302 				= JumpEventHeader<struct hci_ev_cmd_status>(event);
303 
304 			Output::Instance()->Postf(BLACKBOARD_LD(GetID()),
305 				"Incomming CommandStatus(%d)(%s) for %s\n", commandStatus->ncmd,
306 				BluetoothError(commandStatus->status),
307 				BluetoothCommandOpcode(commandStatus->opcode));
308 
309 			request = FindPetition(event->ecode, commandStatus->opcode,
310 				&eventIndexLocation);
311 			if (request != NULL)
312 				CommandStatus(commandStatus, request, eventIndexLocation);
313 
314 			break;
315 		}
316 		default:
317 			Output::Instance()->Postf(BLACKBOARD_LD(GetID()),"Incomming %s event\n",
318 				BluetoothEvent(event->ecode));
319 
320 			request = FindPetition(event->ecode);
321 			if (request != NULL)
322 				HandleExpectedRequest(event, request);
323 
324 			break;
325 	}
326 
327 	if (request == NULL) {
328 		Output::Instance()->Postf(BLACKBOARD_LD(GetID()),
329 			"Event %s could not be understood or delivered\n",
330 			BluetoothEvent(event->ecode));
331 		HandleUnexpectedEvent(event);
332 	}
333 }
334 
335 
336 #if 0
337 #pragma mark -
338 #endif
339 
340 
341 void
342 LocalDeviceImpl::CommandComplete(struct hci_ev_cmd_complete* event,
343 	BMessage* request,
344 	int32 index) {
345 
346 	int16 opcodeExpected;
347 	BMessage reply;
348 	status_t status;
349 
350 	// Handle command complete information
351 	request->FindInt16("opcodeExpected", index, &opcodeExpected);
352 
353 	if (request->IsSourceWaiting() == false)
354 		Output::Instance()->Post("Nobody waiting for the event\n", BLACKBOARD_KIT);
355 
356 	switch ((uint16)opcodeExpected) {
357 
358 		case PACK_OPCODE(OGF_INFORMATIONAL_PARAM, OCF_READ_LOCAL_VERSION):
359 		{
360 			struct hci_rp_read_loc_version* version
361 				= JumpEventHeader<struct hci_rp_read_loc_version,
362 				struct hci_ev_cmd_complete>(event);
363 
364 
365 			if (version->status == BT_OK) {
366 
367 				if (!IsPropertyAvailable("hci_version"))
368 					fProperties->AddInt8("hci_version", version->hci_version);
369 
370 				if (!IsPropertyAvailable("hci_revision"))
371 					fProperties->AddInt16("hci_revision", version->hci_revision);
372 
373 				if (!IsPropertyAvailable("lmp_version"))
374 					fProperties->AddInt8("lmp_version", version->lmp_version);
375 
376 				if (!IsPropertyAvailable("lmp_subversion"))
377 					fProperties->AddInt16("lmp_subversion", version->lmp_subversion);
378 
379 				if (!IsPropertyAvailable("manufacturer"))
380 					fProperties->AddInt16("manufacturer", version->manufacturer);
381 
382 			}
383 
384 			Output::Instance()->Postf(BLACKBOARD_LD(GetID()),
385 				"Reply for Local Version %x\n", version->status);
386 
387 			reply.AddInt8("status", version->status);
388 			status = request->SendReply(&reply);
389 			//printf("Sending reply ... %ld\n", status);
390 			// debug reply.PrintToStream();
391 
392 			// This request is not gonna be used anymore
393 			ClearWantedEvent(request);
394 			break;
395 		}
396 
397 		case  PACK_OPCODE(OGF_CONTROL_BASEBAND, OCF_READ_PG_TIMEOUT):
398 		{
399 			struct hci_rp_read_page_timeout* pageTimeout
400 				= JumpEventHeader<struct hci_rp_read_page_timeout,
401 				struct hci_ev_cmd_complete>(event);
402 
403 			if (pageTimeout->status == BT_OK) {
404 
405 				fProperties->AddInt16("page_timeout", pageTimeout->page_timeout);
406 
407 				Output::Instance()->Postf(BLACKBOARD_LD(GetID()), "Page Timeout=%x\n",
408 					pageTimeout->page_timeout);
409 			}
410 
411 			reply.AddInt8("status", pageTimeout->status);
412 			reply.AddInt32("result", pageTimeout->page_timeout);
413 			status = request->SendReply(&reply);
414 			//printf("Sending reply ... %ld\n", status);
415 			// debug reply.PrintToStream();
416 
417 			// This request is not gonna be used anymore
418 			ClearWantedEvent(request);
419 			break;
420 		}
421 
422 		case PACK_OPCODE(OGF_INFORMATIONAL_PARAM, OCF_READ_LOCAL_FEATURES):
423 		{
424 			struct hci_rp_read_loc_features* features
425 				= JumpEventHeader<struct hci_rp_read_loc_features,
426 				struct hci_ev_cmd_complete>(event);
427 
428 			if (features->status == BT_OK) {
429 
430 				if (!IsPropertyAvailable("features")) {
431 					fProperties->AddData("features", B_ANY_TYPE, &features->features, 8);
432 
433 					uint16 packetType = HCI_DM1 | HCI_DH1 | HCI_HV1;
434 					bool roleSwitch = (features->features[0] & LMP_RSWITCH) != 0;
435 					bool encryptCapable = (features->features[0] & LMP_ENCRYPT) != 0;
436 
437 					if (features->features[0] & LMP_3SLOT)
438 						packetType |= (HCI_DM3 | HCI_DH3);
439 
440 					if (features->features[0] & LMP_5SLOT)
441 						packetType |= (HCI_DM5 | HCI_DH5);
442 
443 					if (features->features[1] & LMP_HV2)
444 						packetType |= (HCI_HV2);
445 
446 					if (features->features[1] & LMP_HV3)
447 						packetType |= (HCI_HV3);
448 
449 					fProperties->AddInt16("packet_type", packetType);
450 					fProperties->AddBool("role_switch_capable", roleSwitch);
451 					fProperties->AddBool("encrypt_capable", encryptCapable);
452 
453 					Output::Instance()->Postf(BLACKBOARD_KIT,
454 						"Packet type %x role switch %d encrypt %d\n",
455 						packetType, roleSwitch, encryptCapable);
456 				}
457 
458 			}
459 
460 			Output::Instance()->Postf(BLACKBOARD_KIT,
461 				"Reply for Local Features %x\n", features->status);
462 
463 			reply.AddInt8("status", features->status);
464 			status = request->SendReply(&reply);
465 			//printf("Sending reply ... %ld\n", status);
466 			// debug reply.PrintToStream();
467 
468 			// This request is not gonna be used anymore
469 			ClearWantedEvent(request);
470 			break;
471 		}
472 
473 		case PACK_OPCODE(OGF_INFORMATIONAL_PARAM, OCF_READ_BUFFER_SIZE):
474 		{
475 			struct hci_rp_read_buffer_size* buffer
476 				= JumpEventHeader<struct hci_rp_read_buffer_size,
477 				struct hci_ev_cmd_complete>(event);
478 
479 			if (buffer->status == BT_OK) {
480 
481 				if (!IsPropertyAvailable("acl_mtu"))
482 					fProperties->AddInt16("acl_mtu", buffer->acl_mtu);
483 
484 				if (!IsPropertyAvailable("sco_mtu"))
485 					fProperties->AddInt8("sco_mtu", buffer->sco_mtu);
486 
487 				if (!IsPropertyAvailable("acl_max_pkt"))
488 					fProperties->AddInt16("acl_max_pkt", buffer->acl_max_pkt);
489 
490 				if (!IsPropertyAvailable("sco_max_pkt"))
491 					fProperties->AddInt16("sco_max_pkt", buffer->sco_max_pkt);
492 
493 			}
494 
495 			Output::Instance()->Postf(BLACKBOARD_KIT,
496 				"Reply for Read Buffer Size %x\n", buffer->status);
497 
498 
499 			reply.AddInt8("status", buffer->status);
500 			status = request->SendReply(&reply);
501 			//printf("Sending reply ... %ld\n", status);
502 			// debug reply.PrintToStream();
503 
504 			// This request is not gonna be used anymore
505 			ClearWantedEvent(request);
506 		}
507 		break;
508 
509 		case PACK_OPCODE(OGF_INFORMATIONAL_PARAM, OCF_READ_BD_ADDR):
510 		{
511 			struct hci_rp_read_bd_addr* readbdaddr
512 				= JumpEventHeader<struct hci_rp_read_bd_addr,
513 				struct hci_ev_cmd_complete>(event);
514 
515 			if (readbdaddr->status == BT_OK) {
516 				reply.AddData("bdaddr", B_ANY_TYPE, &readbdaddr->bdaddr,
517 					sizeof(bdaddr_t));
518 			}
519 
520 			Output::Instance()->Postf(BLACKBOARD_KIT,
521 				"Read bdaddr status = %x\n", readbdaddr->status);
522 
523 			reply.AddInt8("status", readbdaddr->status);
524 			status = request->SendReply(&reply);
525 			//printf("Sending reply ... %ld\n", status);
526 			// debug reply.PrintToStream();
527 
528 			// This request is not gonna be used anymore
529 			ClearWantedEvent(request);
530 		}
531 		break;
532 
533 
534 		case PACK_OPCODE(OGF_CONTROL_BASEBAND, OCF_READ_CLASS_OF_DEV):
535 		{
536 			struct hci_read_dev_class_reply* classDev
537 				= JumpEventHeader<struct hci_read_dev_class_reply,
538 				struct hci_ev_cmd_complete>(event);
539 
540 			if (classDev->status == BT_OK) {
541 				reply.AddData("devclass", B_ANY_TYPE, &classDev->dev_class,
542 					sizeof(classDev->dev_class));
543 			}
544 
545 			Output::Instance()->Postf(BLACKBOARD_KIT,
546 				"Read DeviceClass status = %x DeviceClass = [%x][%x][%x]\n",
547 				classDev->status, classDev->dev_class[0],
548 				classDev->dev_class[1], classDev->dev_class[2]);
549 
550 
551 			reply.AddInt8("status", classDev->status);
552 			status = request->SendReply(&reply);
553 			//printf("Sending reply ... %ld\n", status);
554 			// debug reply.PrintToStream();
555 
556 			// This request is not gonna be used anymore
557 			ClearWantedEvent(request);
558 			break;
559 		}
560 
561 		case PACK_OPCODE(OGF_CONTROL_BASEBAND, OCF_READ_LOCAL_NAME):
562 		{
563 			struct hci_rp_read_local_name* readLocalName
564 				= JumpEventHeader<struct hci_rp_read_local_name,
565 				struct hci_ev_cmd_complete>(event);
566 
567 
568 			if (readLocalName->status == BT_OK) {
569 				reply.AddString("friendlyname", (const char*)readLocalName->local_name);
570 			}
571 
572 			Output::Instance()->Postf(BLACKBOARD_KIT, "Friendly name status %x\n",
573 				readLocalName->status);
574 
575 			reply.AddInt8("status", readLocalName->status);
576 			status = request->SendReply(&reply);
577 			//printf("Sending reply ... %ld\n", status);
578 			// debug reply.PrintToStream();
579 
580 			// This request is not gonna be used anymore
581 			ClearWantedEvent(request);
582 			break;
583 		}
584 
585 		case PACK_OPCODE(OGF_LINK_CONTROL, OCF_PIN_CODE_REPLY):
586 		{
587 			uint8* statusReply = (uint8*)(event + 1);
588 
589 			// TODO: This reply has to match the BDADDR of the outgoing message
590 			Output::Instance()->Postf(BLACKBOARD_KIT, "pincode accept status %x\n",
591 				*statusReply);
592 
593 			reply.AddInt8("status", *statusReply);
594 			status = request->SendReply(&reply);
595 			//printf("Sending reply ... %ld\n", status);
596 			// debug reply.PrintToStream();
597 
598 			// This request is not gonna be used anymore
599 			ClearWantedEvent(request/*, HCI_EVENT_CMD_COMPLETE, opcodeExpected*/);
600 			break;
601 		}
602 
603 		case PACK_OPCODE(OGF_LINK_CONTROL, OCF_PIN_CODE_NEG_REPLY):
604 		{
605 			uint8* statusReply = (uint8*)(event + 1);
606 
607 			// TODO: This reply might to match the BDADDR of the outgoing message
608 			// => FindPetition should be expanded....
609 			Output::Instance()->Postf(BLACKBOARD_KIT, "pincode reject status %x\n",
610 				*statusReply);
611 
612 			reply.AddInt8("status", *statusReply);
613 			status = request->SendReply(&reply);
614 			//printf("Sending reply ... %ld\n", status);
615 			// debug reply.PrintToStream();
616 
617 			// This request is not gonna be used anymore
618 			ClearWantedEvent(request, HCI_EVENT_CMD_COMPLETE, opcodeExpected);
619 			break;
620 		}
621 
622 		case PACK_OPCODE(OGF_CONTROL_BASEBAND, OCF_READ_STORED_LINK_KEY):
623 		{
624 			struct hci_read_stored_link_key_reply* linkKeyRetrieval
625 				= JumpEventHeader<struct hci_read_stored_link_key_reply,
626 				struct hci_ev_cmd_complete>(event);
627 
628 			Output::Instance()->Postf(BLACKBOARD_LD(GetID()),
629 				"Status %s MaxKeys=%d, KeysRead=%d\n",
630 				BluetoothError(linkKeyRetrieval->status),
631 				linkKeyRetrieval->max_num_keys, linkKeyRetrieval->num_keys_read);
632 
633 			reply.AddInt8("status", linkKeyRetrieval->status);
634 			status = request->SendReply(&reply);
635 			//printf("Sending reply ... %ld\n", status);
636 			// debug reply.PrintToStream();
637 
638 			ClearWantedEvent(request);
639 			break;
640 		}
641 
642 		case PACK_OPCODE(OGF_LINK_CONTROL, OCF_LINK_KEY_NEG_REPLY):
643 		case PACK_OPCODE(OGF_LINK_CONTROL, OCF_LINK_KEY_REPLY):
644 		{
645 			struct hci_cp_link_key_reply_reply* linkKeyReply
646 				= JumpEventHeader<struct hci_cp_link_key_reply_reply,
647 				struct hci_ev_cmd_complete>(event);
648 
649 			Output::Instance()->Postf(BLACKBOARD_LD(GetID()),
650 				"Status %s addresss=%s\n", BluetoothError(linkKeyReply->status),
651 				bdaddrUtils::ToString(linkKeyReply->bdaddr));
652 
653 			ClearWantedEvent(request, HCI_EVENT_CMD_COMPLETE, opcodeExpected);
654 			break;
655 		}
656 
657 		case  PACK_OPCODE(OGF_CONTROL_BASEBAND, OCF_READ_SCAN_ENABLE):
658 		{
659 			struct hci_read_scan_enable* scanEnable
660 				= JumpEventHeader<struct hci_read_scan_enable,
661 				struct hci_ev_cmd_complete>(event);
662 
663 			if (scanEnable->status == BT_OK) {
664 				fProperties->AddInt8("scan_enable", scanEnable->enable);
665 
666 				Output::Instance()->Postf(BLACKBOARD_LD(GetID()), "enable = %x\n",
667 					scanEnable->enable);
668 			}
669 
670 			reply.AddInt8("status", scanEnable->status);
671 			reply.AddInt8("scan_enable", scanEnable->enable);
672 			status = request->SendReply(&reply);
673 			printf("Sending reply. scan_enable = %d\n", scanEnable->enable);
674 			// debug reply.PrintToStream();
675 
676 			// This request is not gonna be used anymore
677 			ClearWantedEvent(request);
678 			break;
679 		}
680 
681 		// place here all CC that just replies a uint8 status
682 		case PACK_OPCODE(OGF_CONTROL_BASEBAND, OCF_RESET):
683 		case PACK_OPCODE(OGF_CONTROL_BASEBAND, OCF_WRITE_SCAN_ENABLE):
684 		case PACK_OPCODE(OGF_CONTROL_BASEBAND, OCF_WRITE_CLASS_OF_DEV):
685 		case PACK_OPCODE(OGF_CONTROL_BASEBAND, OCF_WRITE_PG_TIMEOUT):
686 		case PACK_OPCODE(OGF_CONTROL_BASEBAND, OCF_WRITE_CA_TIMEOUT):
687 		case PACK_OPCODE(OGF_CONTROL_BASEBAND, OCF_WRITE_AUTH_ENABLE):
688 		case PACK_OPCODE(OGF_CONTROL_BASEBAND, OCF_WRITE_LOCAL_NAME):
689 		case PACK_OPCODE(OGF_VENDOR_CMD, OCF_WRITE_BCM2035_BDADDR):
690 		{
691 			reply.AddInt8("status", *(uint8*)(event + 1));
692 
693 			Output::Instance()->Postf(BLACKBOARD_LD(GetID()),"%s for %s status %x\n",
694 				__FUNCTION__, BluetoothCommandOpcode(opcodeExpected), *(uint8*)(event + 1));
695 
696 			status = request->SendReply(&reply);
697 			printf("Sending reply write ... %ld\n", status);
698 
699 			ClearWantedEvent(request);
700 			break;
701 		}
702 
703 		default:
704 			Output::Instance()->Post("Command Complete not handled\n", BLACKBOARD_KIT);
705 			break;
706 
707 	}
708 }
709 
710 
711 void
712 LocalDeviceImpl::CommandStatus(struct hci_ev_cmd_status* event,
713 	BMessage* request, int32 index)
714 {
715 
716 	int16 opcodeExpected;
717 	BMessage reply;
718 	status_t status;
719 
720 	// Handle command complete information
721 	request->FindInt16("opcodeExpected", index, &opcodeExpected);
722 
723 	if (request->IsSourceWaiting() == false)
724 		Output::Instance()->Post("Nobody waiting for the event\n", BLACKBOARD_KIT);
725 
726 	switch (opcodeExpected) {
727 
728 		case PACK_OPCODE(OGF_LINK_CONTROL, OCF_INQUIRY):
729 		{
730 			reply.what = BT_MSG_INQUIRY_STARTED;
731 
732 			Output::Instance()->Postf(BLACKBOARD_KIT,
733 				"Inquiry status %x\n", event->status);
734 
735 			reply.AddInt8("status", event->status);
736 			status = request->SendReply(&reply);
737 			//printf("Sending reply ... %ld\n", status);
738 			// debug reply.PrintToStream();
739 
740 			ClearWantedEvent(request, HCI_EVENT_CMD_STATUS,
741 				PACK_OPCODE(OGF_LINK_CONTROL, OCF_INQUIRY));
742 		}
743 		break;
744 
745 		case PACK_OPCODE(OGF_LINK_CONTROL, OCF_REMOTE_NAME_REQUEST):
746 		case PACK_OPCODE(OGF_LINK_CONTROL, OCF_CREATE_CONN):
747 		{
748 			if (event->status == BT_OK) {
749 				ClearWantedEvent(request, HCI_EVENT_CMD_STATUS, opcodeExpected);
750 			} else {
751 				Output::Instance()->Postf(BLACKBOARD_KIT,
752 					"Command Status for remote friendly name %x\n", event->status);
753 
754 				reply.AddInt8("status", event->status);
755 				status = request->SendReply(&reply);
756 				//printf("Sending reply ... %ld\n", status);
757 				// debug reply.PrintToStream();
758 
759 				ClearWantedEvent(request, HCI_EVENT_CMD_STATUS, opcodeExpected);
760 			}
761 		}
762 		break;
763 		/*
764 		case PACK_OPCODE(OGF_LINK_CONTROL, OCF_ACCEPT_CONN_REQ):
765 		{
766 			ClearWantedEvent(request, HCI_EVENT_CMD_STATUS,
767 				PACK_OPCODE(OGF_LINK_CONTROL, OCF_ACCEPT_CONN_REQ));
768 		}
769 		break;
770 
771 		case PACK_OPCODE(OGF_LINK_CONTROL, OCF_REJECT_CONN_REQ):
772 		{
773 			ClearWantedEvent(request, HCI_EVENT_CMD_STATUS,
774 				PACK_OPCODE(OGF_LINK_CONTROL, OCF_REJECT_CONN_REQ));
775 		}
776 		break;*/
777 
778 		default:
779 			Output::Instance()->Post("Command Status not handled\n", BLACKBOARD_KIT);
780 		break;
781 	}
782 
783 }
784 
785 
786 void
787 LocalDeviceImpl::InquiryResult(uint8* numberOfResponses, BMessage* request)
788 {
789 	BMessage reply(BT_MSG_INQUIRY_DEVICE);
790 
791 	uint8 responses = *numberOfResponses;
792 
793 	// skipping here the number of responses
794 	reply.AddData("info", B_ANY_TYPE, numberOfResponses + 1,
795 		(*numberOfResponses) * sizeof(struct inquiry_info) );
796 
797 	reply.AddInt8("count", *numberOfResponses);
798 
799 	Output::Instance()->Postf(BLACKBOARD_LD(GetID()), "%s #responses=%d\n",
800 		__FUNCTION__, *numberOfResponses);
801 
802 	struct inquiry_info* info = JumpEventHeader<struct inquiry_info, uint8>
803 		(numberOfResponses);
804 
805 	while (responses > 0) {
806 		Output::Instance()->Postf(BLACKBOARD_LD(GetID()),
807 		"page_rep=%d scan_period=%d, scan=%d clock=%d\n", info->pscan_rep_mode,
808 		info->pscan_period_mode, info->pscan_mode, info->clock_offset);
809 		responses--;
810 		info++;
811 	}
812 
813 	status_t status = request->SendReply(&reply);
814 	printf("%s: Sending reply ... %ld\n",__FUNCTION__, status);
815 }
816 
817 
818 void
819 LocalDeviceImpl::InquiryComplete(uint8* status, BMessage* request)
820 {
821 	BMessage reply(BT_MSG_INQUIRY_COMPLETED);
822 
823 	reply.AddInt8("status", *status);
824 	status_t stat = request->SendReply(&reply);
825 	printf("%s: Sending reply ... %ld\n",__FUNCTION__, stat);
826 
827 	ClearWantedEvent(request);
828 }
829 
830 
831 void
832 LocalDeviceImpl::RemoteNameRequestComplete(
833 	struct hci_ev_remote_name_request_complete_reply* remotename,
834 	BMessage* request)
835 {
836 	BMessage reply;
837 
838 	if (remotename->status == BT_OK) {
839 		reply.AddString("friendlyname", (const char*)remotename->remote_name );
840 	}
841 
842 	reply.AddInt8("status", remotename->status);
843 
844 	Output::Instance()->Postf(BLACKBOARD_LD(GetID()),
845 		"%s for %s with status %s\n",
846 		BluetoothEvent(HCI_EVENT_REMOTE_NAME_REQUEST_COMPLETE),
847 		bdaddrUtils::ToString(remotename->bdaddr),
848 		BluetoothError(remotename->status));
849 
850 	status_t status = request->SendReply(&reply);
851 	printf("Sending reply ... %ld\n", status);
852 	// debug reply.PrintToStream();
853 
854 	// This request is not gonna be used anymore
855 	ClearWantedEvent(request);
856 }
857 
858 
859 void
860 LocalDeviceImpl::ConnectionRequest(struct hci_ev_conn_request* event,
861 	BMessage* request)
862 {
863 	size_t size;
864 	void* command;
865 
866 	Output::Instance()->Postf(BLACKBOARD_LD(GetID()),
867 		"Connection Incoming type %x from %s...\n",
868 		event->link_type, bdaddrUtils::ToString(event->bdaddr));
869 
870 	// TODO: add a possible request in the queue
871 	if (true) { // Check Preferences if we are to accept this connection
872 
873 		// Keep ourselves as slave
874 		command = buildAcceptConnectionRequest(event->bdaddr, 0x01 , &size);
875 
876 		BMessage* newrequest = new BMessage;
877 		newrequest->AddInt16("eventExpected",  HCI_EVENT_CMD_STATUS);
878 		newrequest->AddInt16("opcodeExpected", PACK_OPCODE(OGF_LINK_CONTROL,
879 			OCF_ACCEPT_CONN_REQ));
880 
881 		newrequest->AddInt16("eventExpected",  HCI_EVENT_CONN_COMPLETE);
882 		newrequest->AddInt16("eventExpected",  HCI_EVENT_PIN_CODE_REQ);
883 		newrequest->AddInt16("eventExpected",  HCI_EVENT_ROLE_CHANGE);
884 		newrequest->AddInt16("eventExpected",  HCI_EVENT_LINK_KEY_NOTIFY);
885 		newrequest->AddInt16("eventExpected",  HCI_EVENT_PAGE_SCAN_REP_MODE_CHANGE);
886 		// newrequest->AddInt16("eventExpected",  HCI_EVENT_MAX_SLOT_CHANGE);
887 		// newrequest->AddInt16("eventExpected",  HCI_EVENT_DISCONNECTION_COMPLETE);
888 
889 		AddWantedEvent(newrequest);
890 
891 		if ((fHCIDelegate)->IssueCommand(command, size) == B_ERROR) {
892 			Output::Instance()->Postf(BLACKBOARD_LD(GetID()),
893 				"Command issued error for Accepting connection\n");
894 				// remove the request?
895 		} else {
896 			Output::Instance()->Postf(BLACKBOARD_LD(GetID()),
897 				"Command issued for Accepting connection\n");
898 		}
899 	}
900 }
901 
902 
903 void
904 LocalDeviceImpl::ConnectionComplete(struct hci_ev_conn_complete* event,
905 	BMessage* request)
906 {
907 
908 	if (event->status == BT_OK) {
909 		uint8 cod[3] = {0, 0, 0};
910 
911 		// TODO: Review, this rDevice is leaked
912 		ConnectionIncoming* iConnection = new ConnectionIncoming(
913 			new RemoteDevice(event->bdaddr, cod));
914 		iConnection->Show();
915 
916 		Output::Instance()->Postf(BLACKBOARD_LD(GetID()),
917 			"%s: Address %s handle=%#x type=%d encrypt=%d\n", __FUNCTION__,
918 				bdaddrUtils::ToString(event->bdaddr), event->handle,
919 				event->link_type, event->encrypt_mode);
920 
921 	} else {
922 		Output::Instance()->Postf(BLACKBOARD_LD(GetID()),
923 			"%s: failed with error %s\n", __FUNCTION__,
924 			BluetoothError(event->status));
925 	}
926 
927 	// it was expected
928 	if (request != NULL) {
929 		BMessage reply;
930 		reply.AddInt8("status", event->status);
931 
932 		if (event->status == BT_OK)
933 			reply.AddInt16("handle", event->handle);
934 
935 		status_t status = request->SendReply(&reply);
936 		printf("%s: Sending reply ... %ld\n",__FUNCTION__, status);
937 		// debug reply.PrintToStream();
938 
939 		// This request is not gonna be used anymore
940 		ClearWantedEvent(request);
941 	}
942 
943 }
944 
945 
946 void
947 LocalDeviceImpl::DisconnectionComplete(
948 	struct hci_ev_disconnection_complete_reply* event, BMessage* request)
949 {
950 	Output::Instance()->Postf(BLACKBOARD_LD(GetID()),
951 		"%s: Handle=%#x, reason=%s status=%x\n", __FUNCTION__, event->handle,
952 		BluetoothError(event->reason), event->status);
953 
954 	if (request != NULL) {
955 		BMessage reply;
956 		reply.AddInt8("status", event->status);
957 
958 		status_t status = request->SendReply(&reply);
959 		printf("%s: Sending reply ... %ld\n",__FUNCTION__, status);
960 		// debug reply.PrintToStream();
961 
962 		ClearWantedEvent(request);
963 	}
964 }
965 
966 
967 void
968 LocalDeviceImpl::PinCodeRequest(struct hci_ev_pin_code_req* event,
969 	BMessage* request)
970 {
971 	PincodeWindow* iPincode = new PincodeWindow(event->bdaddr, GetID());
972 	iPincode->Show();
973 }
974 
975 
976 void
977 LocalDeviceImpl::RoleChange(hci_ev_role_change* event, BMessage* request)
978 {
979 	Output::Instance()->Postf(BLACKBOARD_LD(GetID()),
980 		"%s: Address %s role=%d status=%d\n", __FUNCTION__,
981 		bdaddrUtils::ToString(event->bdaddr), event->role, event->status);
982 }
983 
984 
985 void
986 LocalDeviceImpl::PageScanRepetitionModeChange(
987 	struct hci_ev_page_scan_rep_mode_change* event, BMessage* request)
988 {
989 	Output::Instance()->Postf(BLACKBOARD_LD(GetID()),
990 		"%s: Address %s type=%d\n",	__FUNCTION__,
991 		bdaddrUtils::ToString(event->bdaddr), event->page_scan_rep_mode);
992 }
993 
994 
995 void
996 LocalDeviceImpl::LinkKeyNotify(hci_ev_link_key_notify* event,
997 	BMessage* request)
998 {
999 	Output::Instance()->Postf(BLACKBOARD_LD(GetID()),
1000 		"%s: Address %s, key=%s, type=%d\n", __FUNCTION__,
1001 		bdaddrUtils::ToString(event->bdaddr),
1002 		LinkKeyUtils::ToString(event->link_key), event->key_type);
1003 }
1004 
1005 
1006 void
1007 LocalDeviceImpl::LinkKeyRequested(struct hci_ev_link_key_req* keyRequested,
1008 	BMessage* request)
1009 {
1010 	Output::Instance()->Postf(BLACKBOARD_LD(GetID()),
1011 		"%s: Address %s\n", __FUNCTION__,
1012 		bdaddrUtils::ToString(keyRequested->bdaddr));
1013 
1014 	// TODO:
1015 	// Here we are suposed to check the BDADDR received, look into the server
1016 	// (RemoteDevice Database) if we have any pas link key interchanged with
1017 	// the given address if we have we are to accept it will "Link key Request
1018 	// Reply". As we dont not have such database yet, we will always deny it
1019 	// forcing the remote device to start a pairing.
1020 
1021 	BluetoothCommand<typed_command(hci_cp_link_key_neg_reply)>
1022 		linkKeyNegativeReply(OGF_LINK_CONTROL, OCF_LINK_KEY_NEG_REPLY);
1023 
1024 	bdaddrUtils::Copy(linkKeyNegativeReply->bdaddr, keyRequested->bdaddr);
1025 
1026 	if ((fHCIDelegate)->IssueCommand(linkKeyNegativeReply.Data(),
1027 		linkKeyNegativeReply.Size()) == B_ERROR) {
1028 		Output::Instance()->Postf(BLACKBOARD_LD(GetID()),
1029 			"Command issued error for reply %s\n", __FUNCTION__);
1030 	} else {
1031 		Output::Instance()->Postf(BLACKBOARD_LD(GetID()),
1032 			"Command issued in reply of  %s\n", __FUNCTION__);
1033 	}
1034 
1035 	if (request != NULL)
1036 		ClearWantedEvent(request, HCI_EVENT_LINK_KEY_REQ);
1037 
1038 }
1039 
1040 
1041 void
1042 LocalDeviceImpl::ReturnLinkKeys(struct hci_ev_return_link_keys* returnedKeys)
1043 {
1044 	Output::Instance()->Postf(BLACKBOARD_LD(GetID()), "%s: #keys=%d %s\n",
1045 		__FUNCTION__, returnedKeys->num_keys);
1046 
1047 	uint8 numKeys = returnedKeys->num_keys;
1048 
1049 	struct link_key_info* linkKeys = &returnedKeys->link_keys;
1050 
1051 	while (numKeys > 0) {
1052 
1053 		Output::Instance()->Postf(BLACKBOARD_LD(GetID()), "Address=%s key=%s\n",
1054 			bdaddrUtils::ToString(linkKeys->bdaddr),
1055 			LinkKeyUtils::ToString(linkKeys->link_key));
1056 
1057 		linkKeys++;
1058 	}
1059 }
1060 
1061 
1062 void
1063 LocalDeviceImpl::MaxSlotChange(struct hci_ev_max_slot_change* event,
1064 	BMessage* request)
1065 {
1066 	Output::Instance()->Postf(BLACKBOARD_LD(GetID()),
1067 		"%s: Handle=%#x, max slots=%d\n", __FUNCTION__,
1068 		event->handle, event->lmp_max_slots);
1069 }
1070 
1071 
1072 void
1073 LocalDeviceImpl::HardwareError(struct hci_ev_hardware_error* event)
1074 {
1075 	Output::Instance()->Postf(BLACKBOARD_LD(GetID()),
1076 		"%s: hardware code=%#x\n",	__FUNCTION__, event->hardware_code);
1077 }
1078 
1079 
1080 void
1081 LocalDeviceImpl::NumberOfCompletedPackets(struct hci_ev_num_comp_pkts* event)
1082 {
1083 	Output::Instance()->Postf(BLACKBOARD_LD(GetID()),
1084 		"%s: #Handles=%d\n", __FUNCTION__, event->num_hndl);
1085 
1086 	struct handle_and_number* numberPackets
1087 		= JumpEventHeader<handle_and_number, hci_ev_num_comp_pkts>(event);
1088 
1089 	for (uint8 i = 0; i < event->num_hndl; i++) {
1090 
1091 		Output::Instance()->Postf(BLACKBOARD_LD(GetID()),
1092 			"%s: Handle=%d #packets=%d\n", __FUNCTION__, numberPackets->handle,
1093 			numberPackets->num_completed);
1094 
1095 			numberPackets++;
1096 	}
1097 }
1098 
1099 
1100 #if 0
1101 #pragma mark - Request Methods -
1102 #endif
1103 
1104 status_t
1105 LocalDeviceImpl::ProcessSimpleRequest(BMessage* request)
1106 {
1107 	ssize_t size;
1108 	void* command = NULL;
1109 
1110 	if (request->FindData("raw command", B_ANY_TYPE, 0,
1111 		(const void **)&command, &size) == B_OK) {
1112 
1113 		// Give the chance of just issuing the command
1114 		int16 eventFound;
1115 		if (request->FindInt16("eventExpected", &eventFound) == B_OK)
1116 			AddWantedEvent(request);
1117 		// LEAK: is command buffer freed within the Message?
1118 		if (((HCITransportAccessor*)fHCIDelegate)->IssueCommand(command, size)
1119 			== B_ERROR) {
1120 			// TODO:
1121 			// Reply the request with error!
1122 			// Remove the just added request
1123 			(Output::Instance()->Post("## ERROR Command issue, REMOVING!\n",
1124 				BLACKBOARD_KIT));
1125 			ClearWantedEvent(request);
1126 
1127 		} else {
1128 			return B_OK;
1129 		}
1130 	} else {
1131 		(Output::Instance()->Post("No command specified for simple request\n",
1132 			BLACKBOARD_KIT));
1133 	}
1134 
1135 	return B_ERROR;
1136 }
1137