xref: /haiku/src/kits/bluetooth/CommandManager.cpp (revision a2f8edf78799e60a6ea75974cbd28a9771f05c28)
132c01b55SOliver Ruiz Dorantes /*
232c01b55SOliver Ruiz Dorantes  * Copyright 2008 Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com
36e82afccSOliver Ruiz Dorantes  * Copyright 2008 Mika Lindqvist
432c01b55SOliver Ruiz Dorantes  *
532c01b55SOliver Ruiz Dorantes  * All rights reserved. Distributed under the terms of the MIT License.
632c01b55SOliver Ruiz Dorantes  *
732c01b55SOliver Ruiz Dorantes  */
832c01b55SOliver Ruiz Dorantes 
932c01b55SOliver Ruiz Dorantes 
1032c01b55SOliver Ruiz Dorantes #include <bluetooth/bluetooth.h>
1132c01b55SOliver Ruiz Dorantes #include <bluetooth/HCI/btHCI_command.h>
1232c01b55SOliver Ruiz Dorantes 
1332c01b55SOliver Ruiz Dorantes #include <malloc.h>
144079af86SRene Gollent #include <string.h>
1532c01b55SOliver Ruiz Dorantes 
1632c01b55SOliver Ruiz Dorantes #include "CommandManager.h"
1732c01b55SOliver Ruiz Dorantes 
1832c01b55SOliver Ruiz Dorantes 
1932c01b55SOliver Ruiz Dorantes inline void* buildCommand(uint8 ogf, uint8 ocf, void** param, size_t psize, size_t* outsize)
2032c01b55SOliver Ruiz Dorantes {
2132c01b55SOliver Ruiz Dorantes 	struct hci_command_header* header;
2232c01b55SOliver Ruiz Dorantes 
2332c01b55SOliver Ruiz Dorantes #ifdef BT_IOCTLS_PASS_SIZE
2432c01b55SOliver Ruiz Dorantes     header = (struct hci_command_header*) malloc(psize + sizeof(struct hci_command_header));
2532c01b55SOliver Ruiz Dorantes 	*outsize = psize + sizeof(struct hci_command_header);
2632c01b55SOliver Ruiz Dorantes #else
2732c01b55SOliver Ruiz Dorantes 	size_t* size = (size_t*)malloc(psize + sizeof(struct hci_command_header) + sizeof(size_t));
2832c01b55SOliver Ruiz Dorantes 	*outsize = psize + sizeof(struct hci_command_header) + sizeof(size_t);
2932c01b55SOliver Ruiz Dorantes 
3032c01b55SOliver Ruiz Dorantes     *size = psize + sizeof(struct hci_command_header);
3132c01b55SOliver Ruiz Dorantes     header = (struct hci_command_header*) (((uint8*)size)+4);
3232c01b55SOliver Ruiz Dorantes #endif
3332c01b55SOliver Ruiz Dorantes 
3432c01b55SOliver Ruiz Dorantes 
3532c01b55SOliver Ruiz Dorantes     if (header != NULL) {
3632c01b55SOliver Ruiz Dorantes 
3732c01b55SOliver Ruiz Dorantes         header->opcode = B_HOST_TO_LENDIAN_INT16(PACK_OPCODE(ogf, ocf));
3832c01b55SOliver Ruiz Dorantes         header->clen = psize;
3932c01b55SOliver Ruiz Dorantes 
4032c01b55SOliver Ruiz Dorantes         if (param != NULL && psize != 0) {
4132c01b55SOliver Ruiz Dorantes             *param = ((uint8*)header) + sizeof(struct hci_command_header);
4232c01b55SOliver Ruiz Dorantes         }
4332c01b55SOliver Ruiz Dorantes     }
4432c01b55SOliver Ruiz Dorantes #ifdef BT_IOCTLS_PASS_SIZE
4532c01b55SOliver Ruiz Dorantes     return header;
4632c01b55SOliver Ruiz Dorantes #else
4732c01b55SOliver Ruiz Dorantes     return (void*)size;
4832c01b55SOliver Ruiz Dorantes #endif
4932c01b55SOliver Ruiz Dorantes }
5032c01b55SOliver Ruiz Dorantes 
5132c01b55SOliver Ruiz Dorantes 
5232c01b55SOliver Ruiz Dorantes #if 0
5332c01b55SOliver Ruiz Dorantes #pragma mark - CONTROL BASEBAND -
5432c01b55SOliver Ruiz Dorantes #endif
5532c01b55SOliver Ruiz Dorantes 
5632c01b55SOliver Ruiz Dorantes 
5732c01b55SOliver Ruiz Dorantes void* buildReset(size_t* outsize)
5832c01b55SOliver Ruiz Dorantes {
5932c01b55SOliver Ruiz Dorantes     return buildCommand(OGF_CONTROL_BASEBAND, OCF_RESET, NULL, 0, outsize);
6032c01b55SOliver Ruiz Dorantes }
6132c01b55SOliver Ruiz Dorantes 
6232c01b55SOliver Ruiz Dorantes 
6332c01b55SOliver Ruiz Dorantes void* buildReadLocalName(size_t* outsize)
6432c01b55SOliver Ruiz Dorantes {
6532c01b55SOliver Ruiz Dorantes     return buildCommand(OGF_CONTROL_BASEBAND, OCF_READ_LOCAL_NAME, NULL, 0, outsize);
6632c01b55SOliver Ruiz Dorantes }
6732c01b55SOliver Ruiz Dorantes 
6832c01b55SOliver Ruiz Dorantes 
69*a2f8edf7SOliver Ruiz Dorantes void* buildReadClassOfDevice(size_t* outsize)
70*a2f8edf7SOliver Ruiz Dorantes {
71*a2f8edf7SOliver Ruiz Dorantes     return buildCommand(OGF_CONTROL_BASEBAND, OCF_READ_CLASS_OF_DEV, NULL, 0, outsize);
72*a2f8edf7SOliver Ruiz Dorantes }
73*a2f8edf7SOliver Ruiz Dorantes 
74*a2f8edf7SOliver Ruiz Dorantes 
75631aa548SOliver Ruiz Dorantes void* buildWriteScan(uint8 scanmode, size_t* outsize)
76631aa548SOliver Ruiz Dorantes {
77631aa548SOliver Ruiz Dorantes     struct hci_write_scan_enable* param;
78631aa548SOliver Ruiz Dorantes 	void* command = buildCommand(OGF_CONTROL_BASEBAND, OCF_WRITE_SCAN_ENABLE, (void**) &param, sizeof(struct hci_write_scan_enable), outsize);
79631aa548SOliver Ruiz Dorantes 
80631aa548SOliver Ruiz Dorantes 
81631aa548SOliver Ruiz Dorantes     if (command != NULL) {
82631aa548SOliver Ruiz Dorantes         param->scan = scanmode;
83631aa548SOliver Ruiz Dorantes     }
84631aa548SOliver Ruiz Dorantes 
85631aa548SOliver Ruiz Dorantes     return command;
86631aa548SOliver Ruiz Dorantes 
87631aa548SOliver Ruiz Dorantes }
88631aa548SOliver Ruiz Dorantes 
89631aa548SOliver Ruiz Dorantes 
90631aa548SOliver Ruiz Dorantes void* buildAuthEnable(uint8 auth, size_t* outsize)
91631aa548SOliver Ruiz Dorantes {
92631aa548SOliver Ruiz Dorantes     struct hci_write_authentication_enable* param;
93631aa548SOliver Ruiz Dorantes 	void* command = buildCommand(OGF_CONTROL_BASEBAND, OCF_WRITE_AUTH_ENABLE, (void**) &param, sizeof(struct hci_write_authentication_enable), outsize);
94631aa548SOliver Ruiz Dorantes 
95631aa548SOliver Ruiz Dorantes 
96631aa548SOliver Ruiz Dorantes     if (command != NULL) {
97631aa548SOliver Ruiz Dorantes         param->authentication = auth;
98631aa548SOliver Ruiz Dorantes     }
99631aa548SOliver Ruiz Dorantes 
100631aa548SOliver Ruiz Dorantes     return command;
101631aa548SOliver Ruiz Dorantes 
102631aa548SOliver Ruiz Dorantes }
103631aa548SOliver Ruiz Dorantes 
104631aa548SOliver Ruiz Dorantes 
10532c01b55SOliver Ruiz Dorantes #if 0
10632c01b55SOliver Ruiz Dorantes #pragma mark - LINK CONTROL -
10732c01b55SOliver Ruiz Dorantes #endif
10832c01b55SOliver Ruiz Dorantes 
1097434b760SOliver Ruiz Dorantes 
110631aa548SOliver Ruiz Dorantes void* buildCreateConnection(bdaddr_t bdaddr)
111631aa548SOliver Ruiz Dorantes {
112631aa548SOliver Ruiz Dorantes 	/*
113631aa548SOliver Ruiz Dorantes 	cm4.size = sizeof(struct hci_command_header)+sizeof(struct hci_cp_create_conn);
114631aa548SOliver Ruiz Dorantes 	cm4.header.opcode = B_HOST_TO_LENDIAN_INT16(hci_opcode_pack(OGF_LINK_CONTROL, OCF_CREATE_CONN));
115631aa548SOliver Ruiz Dorantes 	cm4.body.bdaddr.b[0] = 0x92;
116631aa548SOliver Ruiz Dorantes 	cm4.body.bdaddr.b[1] = 0xd3;
117631aa548SOliver Ruiz Dorantes 	cm4.body.bdaddr.b[2] = 0xaf;
118631aa548SOliver Ruiz Dorantes 	cm4.body.bdaddr.b[3] = 0xd9;
119631aa548SOliver Ruiz Dorantes 	cm4.body.bdaddr.b[4] = 0x0a;
120631aa548SOliver Ruiz Dorantes 	cm4.body.bdaddr.b[5] = 0x00;
121631aa548SOliver Ruiz Dorantes 	cm4.body.pkt_type = 0xFFFF;
122631aa548SOliver Ruiz Dorantes 	cm4.body.pscan_rep_mode = 1;
123631aa548SOliver Ruiz Dorantes 	cm4.body.pscan_mode = 0;
124631aa548SOliver Ruiz Dorantes 	cm4.body.clock_offset = 0xc7;
125631aa548SOliver Ruiz Dorantes 	cm4.body.role_switch = 1;
126631aa548SOliver Ruiz Dorantes 	cm4.header.clen = 13;
127631aa548SOliver Ruiz Dorantes 	ioctl(fd1, ISSUE_BT_COMMAND, &cm4, sizeof(cm4));
128631aa548SOliver Ruiz Dorantes 	*/
129631aa548SOliver Ruiz Dorantes 
130631aa548SOliver Ruiz Dorantes 	return NULL;
131631aa548SOliver Ruiz Dorantes }
132631aa548SOliver Ruiz Dorantes 
13332c01b55SOliver Ruiz Dorantes 
13432c01b55SOliver Ruiz Dorantes void* buildRemoteNameRequest(bdaddr_t bdaddr,uint8 pscan_rep_mode, uint16 clock_offset, size_t* outsize)
13532c01b55SOliver Ruiz Dorantes {
13632c01b55SOliver Ruiz Dorantes 
13732c01b55SOliver Ruiz Dorantes     struct hci_remote_name_request* param;
13832c01b55SOliver Ruiz Dorantes     void* command = buildCommand(OGF_LINK_CONTROL, OCF_REMOTE_NAME_REQUEST, (void**) &param, sizeof(struct hci_remote_name_request), outsize);
13932c01b55SOliver Ruiz Dorantes 
14032c01b55SOliver Ruiz Dorantes     if (command != NULL) {
14132c01b55SOliver Ruiz Dorantes         param->bdaddr = bdaddr;
14232c01b55SOliver Ruiz Dorantes         param->pscan_rep_mode = pscan_rep_mode;
14332c01b55SOliver Ruiz Dorantes         param->clock_offset = clock_offset;
14432c01b55SOliver Ruiz Dorantes     }
14532c01b55SOliver Ruiz Dorantes 
14632c01b55SOliver Ruiz Dorantes     return command;
14732c01b55SOliver Ruiz Dorantes }
14832c01b55SOliver Ruiz Dorantes 
14932c01b55SOliver Ruiz Dorantes 
15032c01b55SOliver Ruiz Dorantes void* buildInquiry(uint32 lap, uint8 length, uint8 num_rsp, size_t* outsize)
15132c01b55SOliver Ruiz Dorantes {
15232c01b55SOliver Ruiz Dorantes 
15332c01b55SOliver Ruiz Dorantes     struct hci_cp_inquiry* param;
15432c01b55SOliver Ruiz Dorantes     void* command = buildCommand(OGF_LINK_CONTROL, OCF_INQUIRY, (void**) &param, sizeof(struct hci_cp_inquiry), outsize);
15532c01b55SOliver Ruiz Dorantes 
15632c01b55SOliver Ruiz Dorantes     if (command != NULL) {
15732c01b55SOliver Ruiz Dorantes 
15832c01b55SOliver Ruiz Dorantes 		param->lap[2] = (lap >> 16) & 0xFF;
15932c01b55SOliver Ruiz Dorantes 		param->lap[1] = (lap >>  8) & 0xFF;
16032c01b55SOliver Ruiz Dorantes     	param->lap[0] = (lap >>  0) & 0xFF;
16132c01b55SOliver Ruiz Dorantes     	param->length = length;
16232c01b55SOliver Ruiz Dorantes     	param->num_rsp = num_rsp;
163350458a6SOliver Ruiz Dorantes     }
164350458a6SOliver Ruiz Dorantes 
165350458a6SOliver Ruiz Dorantes     return command;
166350458a6SOliver Ruiz Dorantes }
167350458a6SOliver Ruiz Dorantes 
1687434b760SOliver Ruiz Dorantes 
169350458a6SOliver Ruiz Dorantes void* buildInquiryCancel(size_t* outsize)
170350458a6SOliver Ruiz Dorantes {
171350458a6SOliver Ruiz Dorantes 
172350458a6SOliver Ruiz Dorantes     return buildCommand(OGF_LINK_CONTROL, OCF_INQUIRY_CANCEL, NULL, 0, outsize);
173350458a6SOliver Ruiz Dorantes 
174350458a6SOliver Ruiz Dorantes }
175350458a6SOliver Ruiz Dorantes 
176350458a6SOliver Ruiz Dorantes 
177350458a6SOliver Ruiz Dorantes void* buildPinCodeRequestReply(bdaddr_t bdaddr, uint8 length, char pincode[16], size_t* outsize)
178350458a6SOliver Ruiz Dorantes {
179350458a6SOliver Ruiz Dorantes 
180350458a6SOliver Ruiz Dorantes     struct hci_cp_pin_code_reply* param;
181350458a6SOliver Ruiz Dorantes 
182350458a6SOliver Ruiz Dorantes     if (length > HCI_PIN_SIZE)  // PinCode cannot be longer than 16
183350458a6SOliver Ruiz Dorantes 	return NULL;
184350458a6SOliver Ruiz Dorantes 
185350458a6SOliver Ruiz Dorantes     void* command = buildCommand(OGF_LINK_CONTROL, OCF_PIN_CODE_REPLY, (void**) &param, sizeof(struct hci_cp_pin_code_reply), outsize);
186350458a6SOliver Ruiz Dorantes 
187350458a6SOliver Ruiz Dorantes     if (command != NULL) {
188350458a6SOliver Ruiz Dorantes 
189350458a6SOliver Ruiz Dorantes 	param->bdaddr = bdaddr;
190350458a6SOliver Ruiz Dorantes 	param->pin_len = length;
191350458a6SOliver Ruiz Dorantes     	memcpy(&param->pin_code, pincode, length);
192350458a6SOliver Ruiz Dorantes 
193350458a6SOliver Ruiz Dorantes     }
194350458a6SOliver Ruiz Dorantes 
195350458a6SOliver Ruiz Dorantes     return command;
196350458a6SOliver Ruiz Dorantes }
197350458a6SOliver Ruiz Dorantes 
198350458a6SOliver Ruiz Dorantes 
1990df89492SOliver Ruiz Dorantes void* buildPinCodeRequestNegativeReply(bdaddr_t bdaddr, size_t* outsize)
200350458a6SOliver Ruiz Dorantes {
201350458a6SOliver Ruiz Dorantes 
202350458a6SOliver Ruiz Dorantes     struct hci_cp_pin_code_neg_reply* param;
203350458a6SOliver Ruiz Dorantes 
204350458a6SOliver Ruiz Dorantes     void* command = buildCommand(OGF_LINK_CONTROL, OCF_PIN_CODE_NEG_REPLY,
205350458a6SOliver Ruiz Dorantes                                  (void**) &param, sizeof(struct hci_cp_pin_code_neg_reply), outsize);
206350458a6SOliver Ruiz Dorantes 
207350458a6SOliver Ruiz Dorantes     if (command != NULL) {
208350458a6SOliver Ruiz Dorantes 
209350458a6SOliver Ruiz Dorantes 		param->bdaddr = bdaddr;
210350458a6SOliver Ruiz Dorantes 
21132c01b55SOliver Ruiz Dorantes     }
21232c01b55SOliver Ruiz Dorantes 
21332c01b55SOliver Ruiz Dorantes     return command;
21432c01b55SOliver Ruiz Dorantes }
21532c01b55SOliver Ruiz Dorantes 
21632c01b55SOliver Ruiz Dorantes 
2177434b760SOliver Ruiz Dorantes void* buildAcceptConnectionRequest(bdaddr_t bdaddr, uint8 role, size_t* outsize)
2187434b760SOliver Ruiz Dorantes {
2197434b760SOliver Ruiz Dorantes 	struct hci_cp_accept_conn_req* param;
2207434b760SOliver Ruiz Dorantes 
2217434b760SOliver Ruiz Dorantes 	void* command = buildCommand(OGF_LINK_CONTROL, OCF_ACCEPT_CONN_REQ,
2227434b760SOliver Ruiz Dorantes 					(void**) &param, sizeof(struct hci_cp_accept_conn_req), outsize);
2237434b760SOliver Ruiz Dorantes 
2247434b760SOliver Ruiz Dorantes 	if (command != NULL) {
2257434b760SOliver Ruiz Dorantes 		param->bdaddr = bdaddr;
2267434b760SOliver Ruiz Dorantes 		param->role = role;
2277434b760SOliver Ruiz Dorantes 	}
2287434b760SOliver Ruiz Dorantes 
2297434b760SOliver Ruiz Dorantes 	return command;
2307434b760SOliver Ruiz Dorantes }
2317434b760SOliver Ruiz Dorantes 
2327434b760SOliver Ruiz Dorantes 
2337434b760SOliver Ruiz Dorantes void* buildRejectConnectionRequest(bdaddr_t bdaddr, size_t* outsize)
2347434b760SOliver Ruiz Dorantes {
2357434b760SOliver Ruiz Dorantes 	struct hci_cp_reject_conn_req* param;
2367434b760SOliver Ruiz Dorantes 
2377434b760SOliver Ruiz Dorantes 	void *command = buildCommand(OGF_LINK_CONTROL, OCF_REJECT_CONN_REQ,
2387434b760SOliver Ruiz Dorantes 					(void**) &param, sizeof(struct hci_cp_reject_conn_req), outsize);
2397434b760SOliver Ruiz Dorantes 
2407434b760SOliver Ruiz Dorantes 	if (command != NULL) {
2417434b760SOliver Ruiz Dorantes 		param->bdaddr = bdaddr;
2427434b760SOliver Ruiz Dorantes 	}
2437434b760SOliver Ruiz Dorantes 
2447434b760SOliver Ruiz Dorantes 	return command;
2457434b760SOliver Ruiz Dorantes }
2467434b760SOliver Ruiz Dorantes 
2477434b760SOliver Ruiz Dorantes 
24832c01b55SOliver Ruiz Dorantes #if 0
24932c01b55SOliver Ruiz Dorantes #pragma mark - INFORMATIONAL_PARAM -
25032c01b55SOliver Ruiz Dorantes #endif
25132c01b55SOliver Ruiz Dorantes 
25232c01b55SOliver Ruiz Dorantes 
25332c01b55SOliver Ruiz Dorantes void* buildReadBufferSize(size_t* outsize)
25432c01b55SOliver Ruiz Dorantes {
25532c01b55SOliver Ruiz Dorantes     return buildCommand(OGF_INFORMATIONAL_PARAM, OCF_READ_BUFFER_SIZE, NULL, 0, outsize);
25632c01b55SOliver Ruiz Dorantes }
25732c01b55SOliver Ruiz Dorantes 
25832c01b55SOliver Ruiz Dorantes 
25932c01b55SOliver Ruiz Dorantes void* buildReadBdAddr(size_t* outsize)
26032c01b55SOliver Ruiz Dorantes {
26132c01b55SOliver Ruiz Dorantes 	return buildCommand(OGF_INFORMATIONAL_PARAM, OCF_READ_BD_ADDR, NULL, 0, outsize);
26232c01b55SOliver Ruiz Dorantes }
263631aa548SOliver Ruiz Dorantes 
264631aa548SOliver Ruiz Dorantes 
265631aa548SOliver Ruiz Dorantes 
266631aa548SOliver Ruiz Dorantes 
267