xref: /haiku/src/kits/bluetooth/CommandManager.cpp (revision adb0d19d561947362090081e81d90dde59142026)
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 #include "CommandManager.h"
8 
9 inline void* buildCommand(uint8 ogf, uint8 ocf, void** param, size_t psize, size_t* outsize)
10 {
11 	struct hci_command_header* header;
12 
13 #ifdef BT_IOCTLS_PASS_SIZE
14     header = (struct hci_command_header*) malloc(psize + sizeof(struct hci_command_header));
15 	*outsize = psize + sizeof(struct hci_command_header);
16 #else
17 	size_t* size = (size_t*)malloc(psize + sizeof(struct hci_command_header) + sizeof(size_t));
18 	*outsize = psize + sizeof(struct hci_command_header) + sizeof(size_t);
19 
20     *size = psize + sizeof(struct hci_command_header);
21     header = (struct hci_command_header*) (((uint8*)size)+4);
22 #endif
23 
24 
25     if (header != NULL) {
26 
27         header->opcode = B_HOST_TO_LENDIAN_INT16(PACK_OPCODE(ogf, ocf));
28         header->clen = psize;
29 
30         if (param != NULL && psize != 0) {
31             *param = ((uint8*)header) + sizeof(struct hci_command_header);
32         }
33     }
34 #ifdef BT_IOCTLS_PASS_SIZE
35     return header;
36 #else
37     return (void*)size;
38 #endif
39 }
40 
41 
42 #if 0
43 #pragma mark - CONTROL BASEBAND -
44 #endif
45 
46 
47 void* buildReset(size_t* outsize)
48 {
49     return buildCommand(OGF_CONTROL_BASEBAND, OCF_RESET, NULL, 0, outsize);
50 }
51 
52 
53 void* buildReadLocalName(size_t* outsize)
54 {
55     return buildCommand(OGF_CONTROL_BASEBAND, OCF_READ_LOCAL_NAME, NULL, 0, outsize);
56 }
57 
58 
59 void* buildReadClassOfDevice(size_t* outsize)
60 {
61     return buildCommand(OGF_CONTROL_BASEBAND, OCF_READ_CLASS_OF_DEV, NULL, 0, outsize);
62 }
63 
64 
65 void* buildWriteScan(uint8 scanmode, size_t* outsize)
66 {
67     struct hci_write_scan_enable* param;
68 	void* command = buildCommand(OGF_CONTROL_BASEBAND, OCF_WRITE_SCAN_ENABLE, (void**) &param, sizeof(struct hci_write_scan_enable), outsize);
69 
70 
71     if (command != NULL) {
72         param->scan = scanmode;
73     }
74 
75     return command;
76 
77 }
78 
79 
80 void* buildAuthEnable(uint8 auth, size_t* outsize)
81 {
82     struct hci_write_authentication_enable* param;
83 	void* command = buildCommand(OGF_CONTROL_BASEBAND, OCF_WRITE_AUTH_ENABLE, (void**) &param, sizeof(struct hci_write_authentication_enable), outsize);
84 
85 
86     if (command != NULL) {
87         param->authentication = auth;
88     }
89 
90     return command;
91 
92 }
93 
94 
95 #if 0
96 #pragma mark - LINK CONTROL -
97 #endif
98 
99 
100 void* buildCreateConnection(bdaddr_t bdaddr)
101 {
102 	/*
103 	cm4.size = sizeof(struct hci_command_header)+sizeof(struct hci_cp_create_conn);
104 	cm4.header.opcode = B_HOST_TO_LENDIAN_INT16(hci_opcode_pack(OGF_LINK_CONTROL, OCF_CREATE_CONN));
105 	cm4.body.bdaddr.b[0] = 0x92;
106 	cm4.body.bdaddr.b[1] = 0xd3;
107 	cm4.body.bdaddr.b[2] = 0xaf;
108 	cm4.body.bdaddr.b[3] = 0xd9;
109 	cm4.body.bdaddr.b[4] = 0x0a;
110 	cm4.body.bdaddr.b[5] = 0x00;
111 	cm4.body.pkt_type = 0xFFFF;
112 	cm4.body.pscan_rep_mode = 1;
113 	cm4.body.pscan_mode = 0;
114 	cm4.body.clock_offset = 0xc7;
115 	cm4.body.role_switch = 1;
116 	cm4.header.clen = 13;
117 	ioctl(fd1, ISSUE_BT_COMMAND, &cm4, sizeof(cm4));
118 	*/
119 
120 	return NULL;
121 }
122 
123 
124 void* buildRemoteNameRequest(bdaddr_t bdaddr,uint8 pscan_rep_mode, uint16 clock_offset, size_t* outsize)
125 {
126 
127     struct hci_remote_name_request* param;
128     void* command = buildCommand(OGF_LINK_CONTROL, OCF_REMOTE_NAME_REQUEST, (void**) &param, sizeof(struct hci_remote_name_request), outsize);
129 
130     if (command != NULL) {
131         param->bdaddr = bdaddr;
132         param->pscan_rep_mode = pscan_rep_mode;
133         param->clock_offset = clock_offset;
134     }
135 
136     return command;
137 }
138 
139 
140 void* buildInquiry(uint32 lap, uint8 length, uint8 num_rsp, size_t* outsize)
141 {
142 
143     struct hci_cp_inquiry* param;
144     void* command = buildCommand(OGF_LINK_CONTROL, OCF_INQUIRY, (void**) &param, sizeof(struct hci_cp_inquiry), outsize);
145 
146     if (command != NULL) {
147 
148 		param->lap[2] = (lap >> 16) & 0xFF;
149 		param->lap[1] = (lap >>  8) & 0xFF;
150     	param->lap[0] = (lap >>  0) & 0xFF;
151     	param->length = length;
152     	param->num_rsp = num_rsp;
153     }
154 
155     return command;
156 }
157 
158 
159 void* buildInquiryCancel(size_t* outsize)
160 {
161 
162     return buildCommand(OGF_LINK_CONTROL, OCF_INQUIRY_CANCEL, NULL, 0, outsize);
163 
164 }
165 
166 
167 void* buildPinCodeRequestReply(bdaddr_t bdaddr, uint8 length, char pincode[16], size_t* outsize)
168 {
169 
170     struct hci_cp_pin_code_reply* param;
171 
172     if (length > HCI_PIN_SIZE)  // PinCode cannot be longer than 16
173 	return NULL;
174 
175     void* command = buildCommand(OGF_LINK_CONTROL, OCF_PIN_CODE_REPLY, (void**) &param, sizeof(struct hci_cp_pin_code_reply), outsize);
176 
177     if (command != NULL) {
178 
179 	param->bdaddr = bdaddr;
180 	param->pin_len = length;
181     	memcpy(&param->pin_code, pincode, length);
182 
183     }
184 
185     return command;
186 }
187 
188 
189 void* buildPinCodeRequestNegativeReply(bdaddr_t bdaddr, size_t* outsize)
190 {
191 
192     struct hci_cp_pin_code_neg_reply* param;
193 
194     void* command = buildCommand(OGF_LINK_CONTROL, OCF_PIN_CODE_NEG_REPLY,
195                                  (void**) &param, sizeof(struct hci_cp_pin_code_neg_reply), outsize);
196 
197     if (command != NULL) {
198 
199 		param->bdaddr = bdaddr;
200 
201     }
202 
203     return command;
204 }
205 
206 
207 void* buildAcceptConnectionRequest(bdaddr_t bdaddr, uint8 role, size_t* outsize)
208 {
209 	struct hci_cp_accept_conn_req* param;
210 
211 	void* command = buildCommand(OGF_LINK_CONTROL, OCF_ACCEPT_CONN_REQ,
212 					(void**) &param, sizeof(struct hci_cp_accept_conn_req), outsize);
213 
214 	if (command != NULL) {
215 		param->bdaddr = bdaddr;
216 		param->role = role;
217 	}
218 
219 	return command;
220 }
221 
222 
223 void* buildRejectConnectionRequest(bdaddr_t bdaddr, size_t* outsize)
224 {
225 	struct hci_cp_reject_conn_req* param;
226 
227 	void *command = buildCommand(OGF_LINK_CONTROL, OCF_REJECT_CONN_REQ,
228 					(void**) &param, sizeof(struct hci_cp_reject_conn_req), outsize);
229 
230 	if (command != NULL) {
231 		param->bdaddr = bdaddr;
232 	}
233 
234 	return command;
235 }
236 
237 
238 #if 0
239 #pragma mark - INFORMATIONAL_PARAM -
240 #endif
241 
242 void* buildReadLocalVersionInformation(size_t* outsize)
243 {
244     return buildCommand(OGF_INFORMATIONAL_PARAM, OCF_READ_LOCAL_VERSION, NULL, 0, outsize);
245 }
246 
247 
248 void* buildReadBufferSize(size_t* outsize)
249 {
250     return buildCommand(OGF_INFORMATIONAL_PARAM, OCF_READ_BUFFER_SIZE, NULL, 0, outsize);
251 }
252 
253 
254 void* buildReadBdAddr(size_t* outsize)
255 {
256 	return buildCommand(OGF_INFORMATIONAL_PARAM, OCF_READ_BD_ADDR, NULL, 0, outsize);
257 }
258 
259 
260 const char* bluetoothManufacturers[] = {
261 	"Ericsson Technology Licensing",
262 	"Nokia Mobile Phones",
263 	"Intel Corp.",
264 	"IBM Corp.",
265 	"Toshiba Corp.",
266 	"3Com",
267 	"Microsoft",
268 	"Lucent",
269 	"Motorola",
270 	"Infineon Technologies AG",
271 	"Cambridge Silicon Radio",
272 	"Silicon Wave",
273 	"Digianswer A/S",
274 	"Texas Instruments Inc.",
275 	"Parthus Technologies Inc.",
276 	"Broadcom Corporation",
277 	"Mitel Semiconductor",
278 	"Widcomm, Inc.",
279 	"Zeevo, Inc.",
280 	"Atmel Corporation",
281 	"Mitsubishi Electric Corporation",
282 	"RTX Telecom A/S",
283 	"KC Technology Inc.",
284 	"Newlogic",
285 	"Transilica, Inc.",
286 	"Rohde & Schwartz GmbH & Co. KG",
287 	"TTPCom Limited",
288 	"Signia Technologies, Inc.",
289 	"Conexant Systems Inc.",
290 	"Qualcomm",
291 	"Inventel",
292 	"AVM Berlin",
293 	"BandSpeed, Inc.",
294 	"Mansella Ltd",
295 	"NEC Corporation",
296 	"WavePlus Technology Co., Ltd.",
297 	"Alcatel",
298 	"Philips Semiconductors",
299 	"C Technologies",
300 	"Open Interface",
301 	"R F Micro Devices",
302 	"Hitachi Ltd",
303 	"Symbol Technologies, Inc.",
304 	"Tenovis",
305 	"Macronix International Co. Ltd.",
306 	"GCT Semiconductor",
307 	"Norwood Systems",
308 	"MewTel Technology Inc.",
309 	"ST Microelectronics",
310 	"Synopsys",
311 	"Red-M (Communications) Ltd",
312 	"Commil Ltd",
313 	"Computer Access Technology Corporation (CATC)",
314 	"Eclipse (HQ España) S.L.",
315 	"Renesas Technology Corp.",
316 	"Mobilian Corporation",
317 	"Terax",
318 	"Integrated System Solution Corp.",
319 	"Matsushita Electric Industrial Co., Ltd.",
320 	"Gennum Corporation",
321 	"Research In Motion",
322 	"IPextreme, Inc.",
323 	"Systems and Chips, Inc",
324 	"Bluetooth SIG, Inc",
325 	"Seiko Epson Corporation",
326 	"Integrated Silicon Solution Taiwain, Inc.",
327 	"CONWISE Technology Corporation Ltd",
328 	"PARROT SA",
329 	"Socket Communications",
330 	"Atheros Communications, Inc.",
331 	"MediaTek, Inc.",
332 	"Bluegiga",	/* (tentative) */
333 	"Marvell Technology Group Ltd.",
334 	"3DSP Corporation",
335 	"Accel Semiconductor Ltd.",
336 	"Continental Automotive Systems",
337 	"Apple, Inc.",
338 	"Staccato Communications, Inc."
339 };
340 
341 
342 const char* linkControlCommands[] = {
343 	"Inquiry",
344 	"Inquiry Cancel",
345 	"Periodic Inquiry Mode",
346 	"Exit Periodic Inquiry Mode",
347 	"Create Connection",
348 	"Disconnect",
349 	"Add SCO Connection", // not on 2.1
350 	"Cancel Create Connection",
351 	"Accept Connection Request",
352 	"Reject Connection Request",
353 	"Link Key Request Reply",
354 	"Link Key Request Negative Reply",
355 	"PIN Code Request Reply",
356 	"PIN Code Request Negative Reply",
357 	"Change Connection Packet Type",
358 	"Reserved", // not on 2.1",
359 	"Authentication Requested",
360 	"Reserved", // not on 2.1",
361 	"Set Connection Encryption",
362 	"Reserved", // not on 2.1",
363 	"Change Connection Link Key",
364 	"Reserved", // not on 2.1",
365 	"Master Link Key",
366 	"Reserved", // not on 2.1",
367 	"Remote Name Request",
368 	"Cancel Remote Name Request",
369 	"Read Remote Supported Features",
370 	"Read Remote Extended Features",
371 	"Read Remote Version Information",
372 	"Reserved", // not on 2.1",
373 	"Read Clock Offset",
374 	"Read LMP Handle",
375 	"Reserved",
376 	"Reserved",
377 	"Reserved",
378 	"Reserved",
379 	"Reserved",
380 	"Reserved",
381 	"Reserved",
382 	"Setup Synchronous Connection",
383 	"Accept Synchronous Connection",
384 	"Reject Synchronous Connection",
385 	"IO Capability Request Reply",
386 	"User Confirmation Request Reply",
387 	"User Confirmation Request Negative Reply",
388 	"User Passkey Request Reply",
389 	"User Passkey Request Negative Reply",
390 	"Remote OOB Data Request Reply",
391 	"Reserved",
392 	"Reserved",
393 	"Remote OOB Data Request Negative Reply",
394 	"IO Capabilities Response Negative Reply"
395 };
396 
397 
398 const char* linkPolicyCommands[] = {
399 	"Hold Mode",
400 	"Reserved",
401 	"Sniff Mode",
402 	"Exit Sniff Mode",
403 	"Park State",
404 	"Exit Park State",
405 	"QoS Setup",
406 	"Reserved",
407 	"Role Discovery",
408 	"Reserved",
409 	"Switch Role",
410 	"Read Link Policy Settings",
411 	"Write Link Policy Settings",
412 	"Read Default Link Policy Settings",
413 	"Write Default Link Policy Settings",
414 	"Flow Specification",
415 	"Sniff Subrating"
416 };
417 
418 
419 const char* controllerBasebandCommands[] = {
420 	"Set Event Mask",
421 	"Reserved",
422 	"Reset",
423 	"Reserved",
424 	"Set Event Filter",
425 	"Reserved",
426 	"Reserved",
427 	"Flush",
428 	"Read PIN Type",
429 	"Write PIN Type",
430 	"Create New Unit Key",
431 	"Reserved",
432 	"Read Stored Link Key",
433 	"Reserved",
434 	"Reserved",
435 	"Reserved",
436 	"Write Stored Link Key",
437 	"Delete Stored Link Key",
438 	"Write Local Name",
439 	"Read Local Name",
440 	"Read Connection Accept Timeout",
441 	"Write Connection Accept Timeout",
442 	"Read Page Timeout",
443 	"Write Page Timeout",
444 	"Read Scan Enable",
445 	"Write Scan Enable",
446 	"Read Page Scan Activity",
447 	"Write Page Scan Activity",
448 	"Read Inquiry Scan Activity",
449 	"Write Inquiry Scan Activity",
450 	"Read Authentication Enable",
451 	"Write Authentication Enable",
452 	"Read Encryption Mode", // not 2.1
453 	"Write Encryption Mode",// not 2.1
454 	"Read Class Of Device",
455 	"Write Class Of Device",
456 	"Read Voice Setting",
457 	"Write Voice Setting",
458 	"Read Automatic Flush Timeout",
459 	"Write Automatic Flush Timeout",
460 	"Read Num Broadcast Retransmissions",
461 	"Write Num Broadcast Retransmissions",
462 	"Read Hold Mode Activity",
463 	"Write Hold Mode Activity",
464 	"Read Transmit Power Level",
465 	"Read Synchronous Flow Control Enable",
466 	"Write Synchronous Flow Control Enable",
467 	"Reserved",
468 	"Set Host Controller To Host Flow Control",
469 	"Reserved",
470 	"Host Buffer Size",
471 	"Reserved",
472 	"Host Number Of Completed Packets",
473 	"Read Link Supervision Timeout",
474 	"Write Link Supervision Timeout",
475 	"Read Number of Supported IAC",
476 	"Read Current IAC LAP",
477 	"Write Current IAC LAP",
478 	"Read Page Scan Period Mode", // not 2.1
479 	"Write Page Scan Period Mode", // not 2.1
480 	"Read Page Scan Mode",		// not 2.1
481 	"Write Page Scan Mode",		// not 2.1
482 	"Set AFH Channel Classification",
483 	"Reserved",
484 	"Reserved",
485 	"Read Inquiry Scan Type",
486 	"Write Inquiry Scan Type",
487 	"Read Inquiry Mode",
488 	"Write Inquiry Mode",
489 	"Read Page Scan Type",
490 	"Write Page Scan Type",
491 	"Read AFH Channel Assessment Mode",
492 	"Write AFH Channel Assessment Mode",
493 	"Reserved",
494 	"Reserved",
495 	"Reserved",
496 	"Reserved",
497 	"Reserved",
498 	"Reserved",
499 	"Reserved",
500 	"Read Extended Inquiry Response",
501 	"Write Extended Inquiry Response",
502 	"Refresh Encryption Key",
503 	"Reserved",
504 	"Read Simple Pairing Mode",
505 	"Write Simple Pairing Mode",
506 	"Read Local OOB Data",
507 	"Read Inquiry Transmit Power Level",
508 	"Write Inquiry Transmit Power Level",
509 	"Read Default Erroneous Data Reporting",
510 	"Write Default Erroneous Data Reporting",
511 	"Reserved",
512 	"Reserved",
513 	"Reserved",
514 	"Enhanced Flush",
515 	"Send Keypress Notification"
516 };
517 
518 
519 const char* informationalParametersCommands[] = {
520 	"Read Local Version Information",
521 	"Read Local Supported Commands",
522 	"Read Local Supported Features",
523 	"Read Local Extended Features",
524 	"Read Buffer Size",
525 	"Reserved",
526 	"Read Country Code", // not 2.1
527 	"Reserved",
528 	"Read BD ADDR"
529 };
530 
531 
532 const char* statusParametersCommands[] = {
533 	"Read Failed Contact Counter",
534 	"Reset Failed Contact Counter",
535 	"Read Link Quality",
536 	"Reserved",
537 	"Read RSSI",
538 	"Read AFH Channel Map",
539 	"Read Clock",
540 };
541 
542 
543 const char* testingCommands[] = {
544 	"Read Loopback Mode",
545 	"Write Loopback Mode",
546 	"Enable Device Under Test Mode",
547 	"Write Simple Pairing Debug Mode",
548 };
549 
550 
551 const char* bluetoothEvents[] = {
552 "Inquiry Complete",
553 "Inquiry Result",
554 "Conn Complete",
555 "Conn Request",
556 "Disconnection Complete",
557 "Auth Complete",
558 "Remote Name Request Complete",
559 "Encrypt Change",
560 "Change Conn Link Key Complete",
561 "Master Link Key Compl",
562 "Rmt Features",
563 "Rmt Version",
564 "Qos Setup Complete",
565 "Command Complete",
566 "Command Status",
567 "Hardware Error",
568 "Flush Occur",
569 "Role Change",
570 "Num Comp Pkts",
571 "Mode Change",
572 "Return Link Keys",
573 "Pin Code Req",
574 "Link Key Req",
575 "Link Key Notify",
576 "Loopback Command",
577 "Data Buffer Overflow",
578 "Max Slot Change",
579 "Read Clock Offset Compl",
580 "Con Pkt Type Changed",
581 "Qos Violation",
582 "Reserved",
583 "Page Scan Rep Mode Change",
584 "Flow Specification",
585 "Inquiry Result With Rssi",
586 "Remote Extended Features",
587 "Reserved",
588 "Reserved",
589 "Reserved",
590 "Reserved",
591 "Reserved",
592 "Reserved",
593 "Reserved",
594 "Reserved",
595 "Synchronous Connection Completed",
596 "Synchronous Connection Changed",
597 "Reserved",
598 "Extended Inquiry Result",
599 "Encryption Key Refersh Complete",
600 "Io Capability Request",
601 "Io Capability Response",
602 "User Confirmation Request",
603 "User Passkey Request",
604 "Oob Data Request",
605 "Simple Pairing Complete",
606 "Reserved",
607 "Link Supervision Timeout Changed",
608 "Enhanced Flush Complete",
609 "Reserved",
610 "Reserved",
611 "Keypress Notification",
612 "Remote Host Supported Features Notification"
613 };
614 
615 
616 const char* hciVersion[] = { "1.0B" , "1.1 " , "1.2 " , "2.0 " , "2.1 "};
617 const char* lmpVersion[] = { "1.0 " , "1.1 " , "1.2 " , "2.0 " , "2.1 "};
618 
619 
620 const char*
621 GetHciVersion(uint16 ver)
622 {
623 	return hciVersion[ver];
624 }
625 
626 
627 const char*
628 GetLmpVersion(uint16 ver)
629 {
630 	return lmpVersion[ver];
631 }
632 
633 
634 const char*
635 GetCommand(uint16 command)
636 {
637 
638 	// TODO: BT implementations beyond 2.1
639 	// could specify new commands with OCF numbers
640 	// beyond the boundaries of the arrays and crash.
641 	// But only our stack could issue them so its under
642 	// our control.
643 	switch (GET_OPCODE_OGF(command)) {
644 		case OGF_LINK_CONTROL:
645 			return linkControlCommands[GET_OPCODE_OCF(command)-1];
646 			break;
647 
648 		case OGF_LINK_POLICY:
649 			return linkPolicyCommands[GET_OPCODE_OCF(command)-1];
650 			break;
651 
652 		case OGF_CONTROL_BASEBAND:
653 			return controllerBasebandCommands[GET_OPCODE_OCF(command)-1];
654 			break;
655 
656 		case OGF_INFORMATIONAL_PARAM:
657 			return informationalParametersCommands[GET_OPCODE_OCF(command)-1];
658 			break;
659 
660 		case OGF_STATUS_PARAM:
661 			return statusParametersCommands[GET_OPCODE_OCF(command)-1];
662 			break;
663 
664 		case OGF_TESTING_CMD:
665 			return testingCommands[GET_OPCODE_OCF(command)-1];
666 			break;
667 		case OGF_VENDOR_CMD:
668 			return "Vendor specific command";
669 			break;
670 		default:
671 			return "Unknown command";
672 			break;
673 	}
674 
675 }
676 
677 
678 const char*
679 GetEvent(uint8 event) {
680 	if (event < sizeof(bluetoothEvents)/sizeof(const char*)) {
681 		return bluetoothEvents[event-1];
682 	} else {
683 		return "Event out of Range!";
684 	}
685 }
686 
687 
688 const char*
689 GetManufacturer(uint16 manufacturer) {
690 	if (manufacturer < sizeof(bluetoothManufacturers)/sizeof(const char*)) {
691 		return bluetoothManufacturers[manufacturer];
692 	} else if (manufacturer == 0xFFFF) {
693 		return "internal use";
694 	} else {
695 		return "not assigned";
696 	}
697 }
698