xref: /haiku/src/kits/bluetooth/CommandManager.cpp (revision 68ea01249e1e2088933cb12f9c28d4e5c5d1c9ef)
1 /*
2  * Copyright 2008 Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com
3  * Copyright 2008 Mika Lindqvist
4  * All rights reserved. Distributed under the terms of the MIT License.
5  */
6 
7 
8 #include "CommandManager.h"
9 
10 #include <bluetooth/bluetooth_error.h>
11 #include <bluetooth/debug.h>
12 
13 #include "CompanyIdentifiers.h"
14 
15 
16 inline void*
17 buildCommand(uint8 ogf, uint8 ocf, void** param, size_t psize,
18 	size_t* outsize)
19 {
20 	CALLED();
21 	struct hci_command_header* header;
22 
23 	header = (struct hci_command_header*) malloc(psize
24 		+ sizeof(struct hci_command_header));
25 	*outsize = psize + sizeof(struct hci_command_header);
26 
27 	if (header != NULL) {
28 		header->opcode = B_HOST_TO_LENDIAN_INT16(PACK_OPCODE(ogf, ocf));
29 		header->clen = psize;
30 
31 		if (param != NULL && psize != 0) {
32 			*param = ((uint8*)header) + sizeof(struct hci_command_header);
33 		}
34 	}
35 	return header;
36 }
37 
38 
39 // This is for request that only require a Command complete in reply.
40 
41 // Propagate to ReadBufferSize => reply stored in server side
42 // ReadLocalVersion => reply stored in server side
43 // Reset => no reply
44 
45 // Request that do not need any input parameter
46 // Output reply can be fit in 32 bits field without talking status into account
47 status_t
48 NonParameterCommandRequest(uint8 ofg, uint8 ocf, int32* result, hci_id hId,
49 	BMessenger* messenger)
50 {
51 	CALLED();
52 	int8 bt_status = BT_ERROR;
53 
54 	BluetoothCommand<> simpleCommand(ofg, ocf);
55 
56 	BMessage request(BT_MSG_HANDLE_SIMPLE_REQUEST);
57 	BMessage reply;
58 
59 	request.AddInt32("hci_id", hId);
60 	request.AddData("raw command", B_ANY_TYPE,
61 		simpleCommand.Data(), simpleCommand.Size());
62 	request.AddInt16("eventExpected",  HCI_EVENT_CMD_COMPLETE);
63 	request.AddInt16("opcodeExpected", PACK_OPCODE(ofg, ocf));
64 
65 	if (messenger->SendMessage(&request, &reply) == B_OK) {
66 		reply.FindInt8("status", &bt_status);
67 		if (result != NULL)
68 			reply.FindInt32("result", result);
69 	}
70 
71 	return bt_status;
72 }
73 
74 
75 #if 0
76 #pragma mark - CONTROL BASEBAND -
77 #endif
78 
79 
80 void*
81 buildReset(size_t* outsize)
82 {
83 	CALLED();
84 	return buildCommand(OGF_CONTROL_BASEBAND, OCF_RESET,
85 		NULL, 0, outsize);
86 }
87 
88 
89 void*
90 buildReadLocalName(size_t* outsize)
91 {
92 	CALLED();
93 	return buildCommand(OGF_CONTROL_BASEBAND, OCF_READ_LOCAL_NAME,
94 		NULL, 0, outsize);
95 }
96 
97 
98 void*
99 buildReadClassOfDevice(size_t* outsize)
100 {
101 	CALLED();
102 	return buildCommand(OGF_CONTROL_BASEBAND, OCF_READ_CLASS_OF_DEV,
103 	NULL, 0, outsize);
104 }
105 
106 
107 void*
108 buildReadScan(size_t* outsize)
109 {
110 	CALLED();
111 	return buildCommand(OGF_CONTROL_BASEBAND, OCF_READ_SCAN_ENABLE,
112 	NULL, 0, outsize);
113 }
114 
115 
116 void*
117 buildWriteScan(uint8 scanmode, size_t* outsize)
118 {
119 	CALLED();
120 	struct hci_write_scan_enable* param;
121 	void* command = buildCommand(OGF_CONTROL_BASEBAND, OCF_WRITE_SCAN_ENABLE,
122 		(void**) &param, sizeof(struct hci_write_scan_enable), outsize);
123 
124 
125 	if (command != NULL) {
126 		param->scan = scanmode;
127 	}
128 
129 	return command;
130 }
131 
132 
133 #if 0
134 #pragma mark - LINK CONTROL -
135 #endif
136 
137 
138 void*
139 buildRemoteNameRequest(bdaddr_t bdaddr, uint8 pscan_rep_mode,
140 	uint16 clock_offset, size_t* outsize)
141 {
142 	CALLED();
143 	struct hci_remote_name_request* param;
144 	void* command = buildCommand(OGF_LINK_CONTROL, OCF_REMOTE_NAME_REQUEST,
145 		(void**)&param, sizeof(struct hci_remote_name_request), outsize);
146 
147 	if (command != NULL) {
148 		param->bdaddr = bdaddr;
149 		param->pscan_rep_mode = pscan_rep_mode;
150 		param->clock_offset = clock_offset;
151 	}
152 
153 	return command;
154 }
155 
156 
157 void*
158 buildInquiry(uint32 lap, uint8 length, uint8 num_rsp, size_t* outsize)
159 {
160 	CALLED();
161 	struct hci_cp_inquiry* param;
162 	void* command = buildCommand(OGF_LINK_CONTROL, OCF_INQUIRY,
163 		(void**) &param, sizeof(struct hci_cp_inquiry), outsize);
164 
165 	if (command != NULL) {
166 
167 		param->lap[2] = (lap >> 16) & 0xFF;
168 		param->lap[1] = (lap >>  8) & 0xFF;
169 		param->lap[0] = (lap >>  0) & 0xFF;
170 		param->length = length;
171 		param->num_rsp = num_rsp;
172 	}
173 
174 	return command;
175 }
176 
177 
178 void*
179 buildInquiryCancel(size_t* outsize)
180 {
181 	CALLED();
182 	return buildCommand(OGF_LINK_CONTROL, OCF_INQUIRY_CANCEL, NULL, 0, outsize);
183 }
184 
185 
186 void*
187 buildPinCodeRequestReply(bdaddr_t bdaddr, uint8 length, char pincode[16],
188 	size_t* outsize)
189 {
190 	CALLED();
191 	struct hci_cp_pin_code_reply* param;
192 
193 	if (length > HCI_PIN_SIZE)  // PinCode cannot be longer than 16
194 		return NULL;
195 
196 	void* command = buildCommand(OGF_LINK_CONTROL, OCF_PIN_CODE_REPLY,
197 		(void**)&param, sizeof(struct hci_cp_pin_code_reply), outsize);
198 
199 	if (command != NULL) {
200 		param->bdaddr = bdaddr;
201 		param->pin_len = length;
202 		memcpy(&param->pin_code, pincode, length);
203 	}
204 
205 	return command;
206 }
207 
208 
209 void*
210 buildPinCodeRequestNegativeReply(bdaddr_t bdaddr, size_t* outsize)
211 {
212 	CALLED();
213 	struct hci_cp_pin_code_neg_reply* param;
214 
215 	void* command = buildCommand(OGF_LINK_CONTROL, OCF_PIN_CODE_NEG_REPLY,
216 		(void**) &param, sizeof(struct hci_cp_pin_code_neg_reply), outsize);
217 
218 	if (command != NULL) {
219 
220 		param->bdaddr = bdaddr;
221 
222 	}
223 
224 	return command;
225 }
226 
227 
228 void*
229 buildAcceptConnectionRequest(bdaddr_t bdaddr, uint8 role, size_t* outsize)
230 {
231 	CALLED();
232 	struct hci_cp_accept_conn_req* param;
233 
234 	void* command = buildCommand(OGF_LINK_CONTROL, OCF_ACCEPT_CONN_REQ,
235 		(void**) &param, sizeof(struct hci_cp_accept_conn_req), outsize);
236 
237 	if (command != NULL) {
238 		param->bdaddr = bdaddr;
239 		param->role = role;
240 	}
241 
242 	return command;
243 }
244 
245 
246 void*
247 buildRejectConnectionRequest(bdaddr_t bdaddr, size_t* outsize)
248 {
249 	CALLED();
250 	struct hci_cp_reject_conn_req* param;
251 
252 	void* command = buildCommand(OGF_LINK_CONTROL, OCF_REJECT_CONN_REQ,
253 		(void**)&param, sizeof(struct hci_cp_reject_conn_req),
254 		outsize);
255 
256 	if (command != NULL) {
257 		param->bdaddr = bdaddr;
258 	}
259 
260 	return command;
261 }
262 
263 
264 #if 0
265 #pragma mark - INFORMATIONAL_PARAM -
266 #endif
267 
268 
269 void*
270 buildReadLocalVersionInformation(size_t* outsize)
271 {
272 	CALLED();
273 	return buildCommand(OGF_INFORMATIONAL_PARAM, OCF_READ_LOCAL_VERSION,
274 		NULL, 0, outsize);
275 }
276 
277 
278 void*
279 buildReadBufferSize(size_t* outsize)
280 {
281 	CALLED();
282 	return buildCommand(OGF_INFORMATIONAL_PARAM, OCF_READ_BUFFER_SIZE,
283 		NULL, 0, outsize);
284 }
285 
286 
287 void*
288 buildReadBdAddr(size_t* outsize)
289 {
290 	CALLED();
291 	return buildCommand(OGF_INFORMATIONAL_PARAM, OCF_READ_BD_ADDR,
292 		NULL, 0, outsize);
293 }
294 
295 
296 const char* linkControlCommands[] = {
297 	"Inquiry",
298 	"Inquiry Cancel",
299 	"Periodic Inquiry Mode",
300 	"Exit Periodic Inquiry Mode",
301 	"Create Connection",
302 	"Disconnect",
303 	"Add SCO Connection", // not on 2.1
304 	"Cancel Create Connection",
305 	"Accept Connection Request",
306 	"Reject Connection Request",
307 	"Link Key Request Reply",
308 	"Link Key Request Negative Reply",
309 	"PIN Code Request Reply",
310 	"PIN Code Request Negative Reply",
311 	"Change Connection Packet Type",
312 	"Reserved", // not on 2.1",
313 	"Authentication Requested",
314 	"Reserved", // not on 2.1",
315 	"Set Connection Encryption",
316 	"Reserved", // not on 2.1",
317 	"Change Connection Link Key",
318 	"Reserved", // not on 2.1",
319 	"Master Link Key",
320 	"Reserved", // not on 2.1",
321 	"Remote Name Request",
322 	"Cancel Remote Name Request",
323 	"Read Remote Supported Features",
324 	"Read Remote Extended Features",
325 	"Read Remote Version Information",
326 	"Reserved", // not on 2.1",
327 	"Read Clock Offset",
328 	"Read LMP Handle",
329 	"Reserved",
330 	"Reserved",
331 	"Reserved",
332 	"Reserved",
333 	"Reserved",
334 	"Reserved",
335 	"Reserved",
336 	"Setup Synchronous Connection",
337 	"Accept Synchronous Connection",
338 	"Reject Synchronous Connection",
339 	"IO Capability Request Reply",
340 	"User Confirmation Request Reply",
341 	"User Confirmation Request Negative Reply",
342 	"User Passkey Request Reply",
343 	"User Passkey Request Negative Reply",
344 	"Remote OOB Data Request Reply",
345 	"Reserved",
346 	"Reserved",
347 	"Remote OOB Data Request Negative Reply",
348 	"IO Capabilities Response Negative Reply"
349 };
350 
351 
352 const char* linkPolicyCommands[] = {
353 	"Hold Mode",
354 	"Reserved",
355 	"Sniff Mode",
356 	"Exit Sniff Mode",
357 	"Park State",
358 	"Exit Park State",
359 	"QoS Setup",
360 	"Reserved",
361 	"Role Discovery",
362 	"Reserved",
363 	"Switch Role",
364 	"Read Link Policy Settings",
365 	"Write Link Policy Settings",
366 	"Read Default Link Policy Settings",
367 	"Write Default Link Policy Settings",
368 	"Flow Specification",
369 	"Sniff Subrating"
370 };
371 
372 
373 const char* controllerBasebandCommands[] = {
374 	"Set Event Mask",
375 	"Reserved",
376 	"Reset",
377 	"Reserved",
378 	"Set Event Filter",
379 	"Reserved",
380 	"Reserved",
381 	"Flush",
382 	"Read PIN Type",
383 	"Write PIN Type",
384 	"Create New Unit Key",
385 	"Reserved",
386 	"Read Stored Link Key",
387 	"Reserved",
388 	"Reserved",
389 	"Reserved",
390 	"Write Stored Link Key",
391 	"Delete Stored Link Key",
392 	"Write Local Name",
393 	"Read Local Name",
394 	"Read Connection Accept Timeout",
395 	"Write Connection Accept Timeout",
396 	"Read Page Timeout",
397 	"Write Page Timeout",
398 	"Read Scan Enable",
399 	"Write Scan Enable",
400 	"Read Page Scan Activity",
401 	"Write Page Scan Activity",
402 	"Read Inquiry Scan Activity",
403 	"Write Inquiry Scan Activity",
404 	"Read Authentication Enable",
405 	"Write Authentication Enable",
406 	"Read Encryption Mode", // not 2.1
407 	"Write Encryption Mode",// not 2.1
408 	"Read Class Of Device",
409 	"Write Class Of Device",
410 	"Read Voice Setting",
411 	"Write Voice Setting",
412 	"Read Automatic Flush Timeout",
413 	"Write Automatic Flush Timeout",
414 	"Read Num Broadcast Retransmissions",
415 	"Write Num Broadcast Retransmissions",
416 	"Read Hold Mode Activity",
417 	"Write Hold Mode Activity",
418 	"Read Transmit Power Level",
419 	"Read Synchronous Flow Control Enable",
420 	"Write Synchronous Flow Control Enable",
421 	"Reserved",
422 	"Set Host Controller To Host Flow Control",
423 	"Reserved",
424 	"Host Buffer Size",
425 	"Reserved",
426 	"Host Number Of Completed Packets",
427 	"Read Link Supervision Timeout",
428 	"Write Link Supervision Timeout",
429 	"Read Number of Supported IAC",
430 	"Read Current IAC LAP",
431 	"Write Current IAC LAP",
432 	"Read Page Scan Period Mode", // not 2.1
433 	"Write Page Scan Period Mode", // not 2.1
434 	"Read Page Scan Mode",		// not 2.1
435 	"Write Page Scan Mode",		// not 2.1
436 	"Set AFH Channel Classification",
437 	"Reserved",
438 	"Reserved",
439 	"Read Inquiry Scan Type",
440 	"Write Inquiry Scan Type",
441 	"Read Inquiry Mode",
442 	"Write Inquiry Mode",
443 	"Read Page Scan Type",
444 	"Write Page Scan Type",
445 	"Read AFH Channel Assessment Mode",
446 	"Write AFH Channel Assessment Mode",
447 	"Reserved",
448 	"Reserved",
449 	"Reserved",
450 	"Reserved",
451 	"Reserved",
452 	"Reserved",
453 	"Reserved",
454 	"Read Extended Inquiry Response",
455 	"Write Extended Inquiry Response",
456 	"Refresh Encryption Key",
457 	"Reserved",
458 	"Read Simple Pairing Mode",
459 	"Write Simple Pairing Mode",
460 	"Read Local OOB Data",
461 	"Read Inquiry Transmit Power Level",
462 	"Write Inquiry Transmit Power Level",
463 	"Read Default Erroneous Data Reporting",
464 	"Write Default Erroneous Data Reporting",
465 	"Reserved",
466 	"Reserved",
467 	"Reserved",
468 	"Enhanced Flush",
469 	"Send Keypress Notification"
470 };
471 
472 
473 const char* informationalParametersCommands[] = {
474 	"Read Local Version Information",
475 	"Read Local Supported Commands",
476 	"Read Local Supported Features",
477 	"Read Local Extended Features",
478 	"Read Buffer Size",
479 	"Reserved",
480 	"Read Country Code", // not 2.1
481 	"Reserved",
482 	"Read BD ADDR"
483 };
484 
485 
486 const char* statusParametersCommands[] = {
487 	"Read Failed Contact Counter",
488 	"Reset Failed Contact Counter",
489 	"Read Link Quality",
490 	"Reserved",
491 	"Read RSSI",
492 	"Read AFH Channel Map",
493 	"Read Clock",
494 };
495 
496 
497 const char* testingCommands[] = {
498 	"Read Loopback Mode",
499 	"Write Loopback Mode",
500 	"Enable Device Under Test Mode",
501 	"Write Simple Pairing Debug Mode",
502 };
503 
504 
505 const char* bluetoothEvents[] = {
506 	"Inquiry Complete",
507 	"Inquiry Result",
508 	"Conn Complete",
509 	"Conn Request",
510 	"Disconnection Complete",
511 	"Auth Complete",
512 	"Remote Name Request Complete",
513 	"Encrypt Change",
514 	"Change Conn Link Key Complete",
515 	"Master Link Key Compl",
516 	"Rmt Features",
517 	"Rmt Version",
518 	"Qos Setup Complete",
519 	"Command Complete",
520 	"Command Status",
521 	"Hardware Error",
522 	"Flush Occur",
523 	"Role Change",
524 	"Num Comp Pkts",
525 	"Mode Change",
526 	"Return Link Keys",
527 	"Pin Code Req",
528 	"Link Key Req",
529 	"Link Key Notify",
530 	"Loopback Command",
531 	"Data Buffer Overflow",
532 	"Max Slot Change",
533 	"Read Clock Offset Compl",
534 	"Con Pkt Type Changed",
535 	"Qos Violation",
536 	"Reserved",
537 	"Page Scan Rep Mode Change",
538 	"Flow Specification",
539 	"Inquiry Result With Rssi",
540 	"Remote Extended Features",
541 	"Reserved",
542 	"Reserved",
543 	"Reserved",
544 	"Reserved",
545 	"Reserved",
546 	"Reserved",
547 	"Reserved",
548 	"Reserved",
549 	"Synchronous Connection Completed",
550 	"Synchronous Connection Changed",
551 	"Reserved",
552 	"Extended Inquiry Result",
553 	"Encryption Key Refresh Complete",
554 	"Io Capability Request",
555 	"Io Capability Response",
556 	"User Confirmation Request",
557 	"User Passkey Request",
558 	"Oob Data Request",
559 	"Simple Pairing Complete",
560 	"Reserved",
561 	"Link Supervision Timeout Changed",
562 	"Enhanced Flush Complete",
563 	"Reserved",
564 	"Reserved",
565 	"Keypress Notification",
566 	"Remote Host Supported Features Notification"
567 };
568 
569 
570 const char* bluetoothErrors[] = {
571 	"No Error",
572 	"Unknown Command",
573 	"No Connection",
574 	"Hardware Failure",
575 	"Page Timeout",
576 	"Authentication Failure",
577 	"Pin Or Key Missing",
578 	"Memory Full",
579 	"Connection Timeout",
580 	"Max Number Of Connections",
581 	"Max Number Of Sco Connections",
582 	"Acl Connection Exists",
583 	"Command Disallowed",
584 	"Rejected Limited Resources",
585 	"Rejected Security",
586 	"Rejected Personal",
587 	"Host Timeout",
588 	"Unsupported Feature",
589 	"Invalid Parameters",
590 	"Remote User Ended Connection",
591 	"Remote Low Resources",
592 	"Remote Power Off",
593 	"Connection Terminated",
594 	"Repeated Attempts",
595 	"Pairing Not Allowed",
596 	"Unknown Lmp Pdu",
597 	"Unsupported Remote Feature",
598 	"Sco Offset Rejected",
599 	"Sco Interval Rejected",
600 	"Air Mode Rejected",
601 	"Invalid Lmp Parameters",
602 	"Unspecified Error",
603 	"Unsupported Lmp Parameter Value",
604 	"Role Change Not Allowed",
605 	"Lmp Response Timeout",
606 	"Lmp Error Transaction Collision",
607 	"Lmp Pdu Not Allowed",
608 	"Encryption Mode Not Accepted",
609 	"Unit Link Key Used",
610 	"Qos Not Supported",
611 	"Instant Passed",
612 	"Pairing With Unit Key Not Supported",
613 	"Different Transaction Collision",
614 	"Qos Unacceptable Parameter",
615 	"Qos Rejected",
616 	"Classification Not Supported",
617 	"Insufficient Security",
618 	"Parameter Out Of Range",
619 	"Reserved",
620 	"Role Switch Pending",
621 	"Reserved",
622 	"Slot Violation",
623 	"Role Switch Failed",
624 	"Extended Inquiry Response Too Large",
625 	"Simple Pairing Not Supported By Host",
626 	"Host Busy Pairing"
627 };
628 
629 
630 const char* hciVersion[] = { "1.0B" , "1.1 " , "1.2 " , "2.0 " , "2.1 "};
631 const char* lmpVersion[] = { "1.0 " , "1.1 " , "1.2 " , "2.0 " , "2.1 "};
632 
633 
634 #if 0
635 #pragma mark -
636 #endif
637 
638 
639 const char*
640 BluetoothHciVersion(uint16 ver)
641 {
642 	CALLED();
643 	return hciVersion[ver];
644 }
645 
646 
647 const char*
648 BluetoothLmpVersion(uint16 ver)
649 {
650 	CALLED();
651 	return lmpVersion[ver];
652 }
653 
654 
655 const char*
656 BluetoothCommandOpcode(uint16 opcode)
657 {
658 	CALLED();
659 	// NOTE: BT implementations beyond 2.1
660 	// could specify new commands with OCF numbers
661 	// beyond the boundaries of the arrays and crash.
662 	// But only our stack could issue them so its under
663 	// our control.
664 	switch (GET_OPCODE_OGF(opcode)) {
665 		case OGF_LINK_CONTROL:
666 			return linkControlCommands[GET_OPCODE_OCF(opcode) - 1];
667 			break;
668 
669 		case OGF_LINK_POLICY:
670 			return linkPolicyCommands[GET_OPCODE_OCF(opcode) - 1];
671 			break;
672 
673 		case OGF_CONTROL_BASEBAND:
674 			return controllerBasebandCommands[GET_OPCODE_OCF(opcode) - 1];
675 			break;
676 
677 		case OGF_INFORMATIONAL_PARAM:
678 			return informationalParametersCommands[GET_OPCODE_OCF(opcode) - 1];
679 			break;
680 
681 		case OGF_STATUS_PARAM:
682 			return statusParametersCommands[GET_OPCODE_OCF(opcode) - 1];
683 			break;
684 
685 		case OGF_TESTING_CMD:
686 			return testingCommands[GET_OPCODE_OCF(opcode) - 1];
687 			break;
688 		case OGF_VENDOR_CMD:
689 			return "Vendor specific command";
690 			break;
691 		default:
692 			return "Unknown command";
693 			break;
694 	}
695 
696 }
697 
698 
699 const char*
700 BluetoothEvent(uint8 event)
701 {
702 	CALLED();
703 	if (event < sizeof(bluetoothEvents) / sizeof(const char*))
704 		return bluetoothEvents[event - 1];
705 	else
706 		return "Event out of Range!";
707 }
708 
709 
710 const char*
711 BluetoothManufacturer(uint16 manufacturer)
712 {
713 	CALLED();
714 	if (manufacturer < sizeof(bluetoothManufacturers) / sizeof(const char*))
715 		return bluetoothManufacturers[manufacturer];
716 	else if (manufacturer == 0xFFFF)
717 		return "internal use";
718 	else
719 		return "not assigned";
720 }
721 
722 
723 const char*
724 BluetoothError(uint8 error)
725 {
726 	CALLED();
727 	if (error < sizeof(bluetoothErrors) / sizeof(const char*))
728 		return bluetoothErrors[error];
729 	else
730 		return "not specified";
731 }
732