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**) ¶m, 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**) ¶m, 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**) ¶m, 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**) ¶m, 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**) ¶m, 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(¶m->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**) ¶m, 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**) ¶m, 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**) ¶m, 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