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
16inline void*
17buildCommand(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
47status_t
48NonParameterCommandRequest(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
80void*
81buildReset(size_t* outsize)
82{
83	CALLED();
84	return buildCommand(OGF_CONTROL_BASEBAND, OCF_RESET,
85		NULL, 0, outsize);
86}
87
88
89void*
90buildReadLocalName(size_t* outsize)
91{
92	CALLED();
93	return buildCommand(OGF_CONTROL_BASEBAND, OCF_READ_LOCAL_NAME,
94		NULL, 0, outsize);
95}
96
97
98void*
99buildReadClassOfDevice(size_t* outsize)
100{
101	CALLED();
102	return buildCommand(OGF_CONTROL_BASEBAND, OCF_READ_CLASS_OF_DEV,
103	NULL, 0, outsize);
104}
105
106
107void*
108buildReadScan(size_t* outsize)
109{
110	CALLED();
111	return buildCommand(OGF_CONTROL_BASEBAND, OCF_READ_SCAN_ENABLE,
112	NULL, 0, outsize);
113}
114
115
116void*
117buildWriteScan(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
138void*
139buildRemoteNameRequest(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
157void*
158buildInquiry(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
178void*
179buildInquiryCancel(size_t* outsize)
180{
181	CALLED();
182	return buildCommand(OGF_LINK_CONTROL, OCF_INQUIRY_CANCEL, NULL, 0, outsize);
183}
184
185
186void*
187buildPinCodeRequestReply(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
209void*
210buildPinCodeRequestNegativeReply(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
228void*
229buildAcceptConnectionRequest(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
246void*
247buildRejectConnectionRequest(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
269void*
270buildReadLocalVersionInformation(size_t* outsize)
271{
272	CALLED();
273	return buildCommand(OGF_INFORMATIONAL_PARAM, OCF_READ_LOCAL_VERSION,
274		NULL, 0, outsize);
275}
276
277
278void*
279buildReadBufferSize(size_t* outsize)
280{
281	CALLED();
282	return buildCommand(OGF_INFORMATIONAL_PARAM, OCF_READ_BUFFER_SIZE,
283		NULL, 0, outsize);
284}
285
286
287void*
288buildReadBdAddr(size_t* outsize)
289{
290	CALLED();
291	return buildCommand(OGF_INFORMATIONAL_PARAM, OCF_READ_BD_ADDR,
292		NULL, 0, outsize);
293}
294
295
296const 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
352const 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
373const 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
473const 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
486const 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
497const 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
505const 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
570const 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
630const char* hciVersion[] = { "1.0B" , "1.1" , "1.2" , "2.0" , "2.1",
631	"3.0", "4.0", "4.1", "4.2", "5.0", "5.1", "5.2"};
632const char* lmpVersion[] = { "1.0" , "1.1" , "1.2" , "2.0" , "2.1",
633	"3.0", "4.0", "4.1", "4.2", "5.0", "5.1", "5.2"};
634
635#if 0
636#pragma mark -
637#endif
638
639
640const char*
641BluetoothHciVersion(uint16 ver)
642{
643	CALLED();
644	return hciVersion[ver];
645}
646
647
648const char*
649BluetoothLmpVersion(uint16 ver)
650{
651	CALLED();
652	return lmpVersion[ver];
653}
654
655
656const char*
657BluetoothCommandOpcode(uint16 opcode)
658{
659	CALLED();
660	// NOTE: BT implementations beyond 2.1
661	// could specify new commands with OCF numbers
662	// beyond the boundaries of the arrays and crash.
663	// But only our stack could issue them so its under
664	// our control.
665	switch (GET_OPCODE_OGF(opcode)) {
666		case OGF_LINK_CONTROL:
667			return linkControlCommands[GET_OPCODE_OCF(opcode) - 1];
668			break;
669
670		case OGF_LINK_POLICY:
671			return linkPolicyCommands[GET_OPCODE_OCF(opcode) - 1];
672			break;
673
674		case OGF_CONTROL_BASEBAND:
675			return controllerBasebandCommands[GET_OPCODE_OCF(opcode) - 1];
676			break;
677
678		case OGF_INFORMATIONAL_PARAM:
679			return informationalParametersCommands[GET_OPCODE_OCF(opcode) - 1];
680			break;
681
682		case OGF_STATUS_PARAM:
683			return statusParametersCommands[GET_OPCODE_OCF(opcode) - 1];
684			break;
685
686		case OGF_TESTING_CMD:
687			return testingCommands[GET_OPCODE_OCF(opcode) - 1];
688			break;
689		case OGF_VENDOR_CMD:
690			return "Vendor specific command";
691			break;
692		default:
693			return "Unknown command";
694			break;
695	}
696
697}
698
699
700const char*
701BluetoothEvent(uint8 event)
702{
703	CALLED();
704	if (event < sizeof(bluetoothEvents) / sizeof(const char*))
705		return bluetoothEvents[event - 1];
706	else
707		return "Event out of Range!";
708}
709
710
711const char*
712BluetoothManufacturer(uint16 manufacturer)
713{
714	CALLED();
715	if (manufacturer < sizeof(bluetoothManufacturers) / sizeof(const char*))
716		return bluetoothManufacturers[manufacturer];
717	else if (manufacturer == 0xFFFF)
718		return "internal use";
719	else
720		return "not assigned";
721}
722
723
724const char*
725BluetoothError(uint8 error)
726{
727	CALLED();
728	if (error < sizeof(bluetoothErrors) / sizeof(const char*))
729		return bluetoothErrors[error];
730	else
731		return "not specified";
732}
733