132c01b55SOliver Ruiz Dorantes /* 232c01b55SOliver Ruiz Dorantes * Copyright 2008 Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com 332c01b55SOliver Ruiz Dorantes * 432c01b55SOliver Ruiz Dorantes * All rights reserved. Distributed under the terms of the MIT License. 532c01b55SOliver Ruiz Dorantes * 632c01b55SOliver Ruiz Dorantes */ 732c01b55SOliver Ruiz Dorantes 832c01b55SOliver Ruiz Dorantes 932c01b55SOliver Ruiz Dorantes #include <bluetooth/bluetooth.h> 1032c01b55SOliver Ruiz Dorantes #include <bluetooth/HCI/btHCI_command.h> 1132c01b55SOliver Ruiz Dorantes 1232c01b55SOliver Ruiz Dorantes #include <malloc.h> 1332c01b55SOliver Ruiz Dorantes 1432c01b55SOliver Ruiz Dorantes #include "CommandManager.h" 1532c01b55SOliver Ruiz Dorantes 1632c01b55SOliver Ruiz Dorantes 1732c01b55SOliver Ruiz Dorantes inline void* buildCommand(uint8 ogf, uint8 ocf, void** param, size_t psize, size_t* outsize) 1832c01b55SOliver Ruiz Dorantes { 1932c01b55SOliver Ruiz Dorantes struct hci_command_header* header; 2032c01b55SOliver Ruiz Dorantes 2132c01b55SOliver Ruiz Dorantes #ifdef BT_IOCTLS_PASS_SIZE 2232c01b55SOliver Ruiz Dorantes header = (struct hci_command_header*) malloc(psize + sizeof(struct hci_command_header)); 2332c01b55SOliver Ruiz Dorantes *outsize = psize + sizeof(struct hci_command_header); 2432c01b55SOliver Ruiz Dorantes #else 2532c01b55SOliver Ruiz Dorantes size_t* size = (size_t*)malloc(psize + sizeof(struct hci_command_header) + sizeof(size_t)); 2632c01b55SOliver Ruiz Dorantes *outsize = psize + sizeof(struct hci_command_header) + sizeof(size_t); 2732c01b55SOliver Ruiz Dorantes 2832c01b55SOliver Ruiz Dorantes *size = psize + sizeof(struct hci_command_header); 2932c01b55SOliver Ruiz Dorantes header = (struct hci_command_header*) (((uint8*)size)+4); 3032c01b55SOliver Ruiz Dorantes #endif 3132c01b55SOliver Ruiz Dorantes 3232c01b55SOliver Ruiz Dorantes 3332c01b55SOliver Ruiz Dorantes if (header != NULL) { 3432c01b55SOliver Ruiz Dorantes 3532c01b55SOliver Ruiz Dorantes header->opcode = B_HOST_TO_LENDIAN_INT16(PACK_OPCODE(ogf, ocf)); 3632c01b55SOliver Ruiz Dorantes header->clen = psize; 3732c01b55SOliver Ruiz Dorantes 3832c01b55SOliver Ruiz Dorantes if (param != NULL && psize != 0) { 3932c01b55SOliver Ruiz Dorantes *param = ((uint8*)header) + sizeof(struct hci_command_header); 4032c01b55SOliver Ruiz Dorantes } 4132c01b55SOliver Ruiz Dorantes } 4232c01b55SOliver Ruiz Dorantes #ifdef BT_IOCTLS_PASS_SIZE 4332c01b55SOliver Ruiz Dorantes return header; 4432c01b55SOliver Ruiz Dorantes #else 4532c01b55SOliver Ruiz Dorantes return (void*)size; 4632c01b55SOliver Ruiz Dorantes #endif 4732c01b55SOliver Ruiz Dorantes } 4832c01b55SOliver Ruiz Dorantes 4932c01b55SOliver Ruiz Dorantes 5032c01b55SOliver Ruiz Dorantes #if 0 5132c01b55SOliver Ruiz Dorantes #pragma mark - CONTROL BASEBAND - 5232c01b55SOliver Ruiz Dorantes #endif 5332c01b55SOliver Ruiz Dorantes 5432c01b55SOliver Ruiz Dorantes 5532c01b55SOliver Ruiz Dorantes void* buildReset(size_t* outsize) 5632c01b55SOliver Ruiz Dorantes { 5732c01b55SOliver Ruiz Dorantes return buildCommand(OGF_CONTROL_BASEBAND, OCF_RESET, NULL, 0, outsize); 5832c01b55SOliver Ruiz Dorantes } 5932c01b55SOliver Ruiz Dorantes 6032c01b55SOliver Ruiz Dorantes 6132c01b55SOliver Ruiz Dorantes void* buildReadLocalName(size_t* outsize) 6232c01b55SOliver Ruiz Dorantes { 6332c01b55SOliver Ruiz Dorantes return buildCommand(OGF_CONTROL_BASEBAND, OCF_READ_LOCAL_NAME, NULL, 0, outsize); 6432c01b55SOliver Ruiz Dorantes } 6532c01b55SOliver Ruiz Dorantes 6632c01b55SOliver Ruiz Dorantes 67631aa548SOliver Ruiz Dorantes void* buildWriteScan(uint8 scanmode, size_t* outsize) 68631aa548SOliver Ruiz Dorantes { 69631aa548SOliver Ruiz Dorantes struct hci_write_scan_enable* param; 70631aa548SOliver Ruiz Dorantes void* command = buildCommand(OGF_CONTROL_BASEBAND, OCF_WRITE_SCAN_ENABLE, (void**) ¶m, sizeof(struct hci_write_scan_enable), outsize); 71631aa548SOliver Ruiz Dorantes 72631aa548SOliver Ruiz Dorantes 73631aa548SOliver Ruiz Dorantes if (command != NULL) { 74631aa548SOliver Ruiz Dorantes param->scan = scanmode; 75631aa548SOliver Ruiz Dorantes } 76631aa548SOliver Ruiz Dorantes 77631aa548SOliver Ruiz Dorantes return command; 78631aa548SOliver Ruiz Dorantes 79631aa548SOliver Ruiz Dorantes } 80631aa548SOliver Ruiz Dorantes 81631aa548SOliver Ruiz Dorantes 82631aa548SOliver Ruiz Dorantes void* buildAuthEnable(uint8 auth, size_t* outsize) 83631aa548SOliver Ruiz Dorantes { 84631aa548SOliver Ruiz Dorantes struct hci_write_authentication_enable* param; 85631aa548SOliver Ruiz Dorantes void* command = buildCommand(OGF_CONTROL_BASEBAND, OCF_WRITE_AUTH_ENABLE, (void**) ¶m, sizeof(struct hci_write_authentication_enable), outsize); 86631aa548SOliver Ruiz Dorantes 87631aa548SOliver Ruiz Dorantes 88631aa548SOliver Ruiz Dorantes if (command != NULL) { 89631aa548SOliver Ruiz Dorantes param->authentication = auth; 90631aa548SOliver Ruiz Dorantes } 91631aa548SOliver Ruiz Dorantes 92631aa548SOliver Ruiz Dorantes return command; 93631aa548SOliver Ruiz Dorantes 94631aa548SOliver Ruiz Dorantes } 95631aa548SOliver Ruiz Dorantes 96631aa548SOliver Ruiz Dorantes 9732c01b55SOliver Ruiz Dorantes #if 0 9832c01b55SOliver Ruiz Dorantes #pragma mark - LINK CONTROL - 9932c01b55SOliver Ruiz Dorantes #endif 10032c01b55SOliver Ruiz Dorantes 101631aa548SOliver Ruiz Dorantes void* buildCreateConnection(bdaddr_t bdaddr) 102631aa548SOliver Ruiz Dorantes { 103631aa548SOliver Ruiz Dorantes /* 104631aa548SOliver Ruiz Dorantes cm4.size = sizeof(struct hci_command_header)+sizeof(struct hci_cp_create_conn); 105631aa548SOliver Ruiz Dorantes cm4.header.opcode = B_HOST_TO_LENDIAN_INT16(hci_opcode_pack(OGF_LINK_CONTROL, OCF_CREATE_CONN)); 106631aa548SOliver Ruiz Dorantes cm4.body.bdaddr.b[0] = 0x92; 107631aa548SOliver Ruiz Dorantes cm4.body.bdaddr.b[1] = 0xd3; 108631aa548SOliver Ruiz Dorantes cm4.body.bdaddr.b[2] = 0xaf; 109631aa548SOliver Ruiz Dorantes cm4.body.bdaddr.b[3] = 0xd9; 110631aa548SOliver Ruiz Dorantes cm4.body.bdaddr.b[4] = 0x0a; 111631aa548SOliver Ruiz Dorantes cm4.body.bdaddr.b[5] = 0x00; 112631aa548SOliver Ruiz Dorantes cm4.body.pkt_type = 0xFFFF; 113631aa548SOliver Ruiz Dorantes cm4.body.pscan_rep_mode = 1; 114631aa548SOliver Ruiz Dorantes cm4.body.pscan_mode = 0; 115631aa548SOliver Ruiz Dorantes cm4.body.clock_offset = 0xc7; 116631aa548SOliver Ruiz Dorantes cm4.body.role_switch = 1; 117631aa548SOliver Ruiz Dorantes cm4.header.clen = 13; 118631aa548SOliver Ruiz Dorantes ioctl(fd1, ISSUE_BT_COMMAND, &cm4, sizeof(cm4)); 119631aa548SOliver Ruiz Dorantes */ 120631aa548SOliver Ruiz Dorantes 121631aa548SOliver Ruiz Dorantes return NULL; 122631aa548SOliver Ruiz Dorantes } 123631aa548SOliver Ruiz Dorantes 12432c01b55SOliver Ruiz Dorantes 12532c01b55SOliver Ruiz Dorantes void* buildRemoteNameRequest(bdaddr_t bdaddr,uint8 pscan_rep_mode, uint16 clock_offset, size_t* outsize) 12632c01b55SOliver Ruiz Dorantes { 12732c01b55SOliver Ruiz Dorantes 12832c01b55SOliver Ruiz Dorantes struct hci_remote_name_request* param; 12932c01b55SOliver Ruiz Dorantes void* command = buildCommand(OGF_LINK_CONTROL, OCF_REMOTE_NAME_REQUEST, (void**) ¶m, sizeof(struct hci_remote_name_request), outsize); 13032c01b55SOliver Ruiz Dorantes 13132c01b55SOliver Ruiz Dorantes if (command != NULL) { 13232c01b55SOliver Ruiz Dorantes param->bdaddr = bdaddr; 13332c01b55SOliver Ruiz Dorantes param->pscan_rep_mode = pscan_rep_mode; 13432c01b55SOliver Ruiz Dorantes param->clock_offset = clock_offset; 13532c01b55SOliver Ruiz Dorantes } 13632c01b55SOliver Ruiz Dorantes 13732c01b55SOliver Ruiz Dorantes return command; 13832c01b55SOliver Ruiz Dorantes } 13932c01b55SOliver Ruiz Dorantes 14032c01b55SOliver Ruiz Dorantes 14132c01b55SOliver Ruiz Dorantes void* buildInquiry(uint32 lap, uint8 length, uint8 num_rsp, size_t* outsize) 14232c01b55SOliver Ruiz Dorantes { 14332c01b55SOliver Ruiz Dorantes 14432c01b55SOliver Ruiz Dorantes struct hci_cp_inquiry* param; 14532c01b55SOliver Ruiz Dorantes void* command = buildCommand(OGF_LINK_CONTROL, OCF_INQUIRY, (void**) ¶m, sizeof(struct hci_cp_inquiry), outsize); 14632c01b55SOliver Ruiz Dorantes 14732c01b55SOliver Ruiz Dorantes if (command != NULL) { 14832c01b55SOliver Ruiz Dorantes 14932c01b55SOliver Ruiz Dorantes param->lap[2] = (lap >> 16) & 0xFF; 15032c01b55SOliver Ruiz Dorantes param->lap[1] = (lap >> 8) & 0xFF; 15132c01b55SOliver Ruiz Dorantes param->lap[0] = (lap >> 0) & 0xFF; 15232c01b55SOliver Ruiz Dorantes param->length = length; 15332c01b55SOliver Ruiz Dorantes param->num_rsp = num_rsp; 154*350458a6SOliver Ruiz Dorantes } 155*350458a6SOliver Ruiz Dorantes 156*350458a6SOliver Ruiz Dorantes return command; 157*350458a6SOliver Ruiz Dorantes } 158*350458a6SOliver Ruiz Dorantes 159*350458a6SOliver Ruiz Dorantes void* buildInquiryCancel(size_t* outsize) 160*350458a6SOliver Ruiz Dorantes { 161*350458a6SOliver Ruiz Dorantes 162*350458a6SOliver Ruiz Dorantes return buildCommand(OGF_LINK_CONTROL, OCF_INQUIRY_CANCEL, NULL, 0, outsize); 163*350458a6SOliver Ruiz Dorantes 164*350458a6SOliver Ruiz Dorantes } 165*350458a6SOliver Ruiz Dorantes 166*350458a6SOliver Ruiz Dorantes 167*350458a6SOliver Ruiz Dorantes void* buildPinCodeRequestReply(bdaddr_t bdaddr, uint8 length, char pincode[16], size_t* outsize) 168*350458a6SOliver Ruiz Dorantes { 169*350458a6SOliver Ruiz Dorantes 170*350458a6SOliver Ruiz Dorantes struct hci_cp_pin_code_reply* param; 171*350458a6SOliver Ruiz Dorantes 172*350458a6SOliver Ruiz Dorantes if (length > HCI_PIN_SIZE) // PinCode cannot be longer than 16 173*350458a6SOliver Ruiz Dorantes return NULL; 174*350458a6SOliver Ruiz Dorantes 175*350458a6SOliver Ruiz Dorantes void* command = buildCommand(OGF_LINK_CONTROL, OCF_PIN_CODE_REPLY, (void**) ¶m, sizeof(struct hci_cp_pin_code_reply), outsize); 176*350458a6SOliver Ruiz Dorantes 177*350458a6SOliver Ruiz Dorantes if (command != NULL) { 178*350458a6SOliver Ruiz Dorantes 179*350458a6SOliver Ruiz Dorantes param->bdaddr = bdaddr; 180*350458a6SOliver Ruiz Dorantes param->pin_len = length; 181*350458a6SOliver Ruiz Dorantes memcpy(¶m->pin_code, pincode, length); 182*350458a6SOliver Ruiz Dorantes 183*350458a6SOliver Ruiz Dorantes } 184*350458a6SOliver Ruiz Dorantes 185*350458a6SOliver Ruiz Dorantes return command; 186*350458a6SOliver Ruiz Dorantes } 187*350458a6SOliver Ruiz Dorantes 188*350458a6SOliver Ruiz Dorantes 189*350458a6SOliver Ruiz Dorantes void* buildPinCodeRequestNegativeReply(bdaddr_t bdaddr, uint8 length, char pincode[16], size_t* outsize) 190*350458a6SOliver Ruiz Dorantes { 191*350458a6SOliver Ruiz Dorantes 192*350458a6SOliver Ruiz Dorantes struct hci_cp_pin_code_neg_reply* param; 193*350458a6SOliver Ruiz Dorantes 194*350458a6SOliver Ruiz Dorantes void* command = buildCommand(OGF_LINK_CONTROL, OCF_PIN_CODE_NEG_REPLY, 195*350458a6SOliver Ruiz Dorantes (void**) ¶m, sizeof(struct hci_cp_pin_code_neg_reply), outsize); 196*350458a6SOliver Ruiz Dorantes 197*350458a6SOliver Ruiz Dorantes if (command != NULL) { 198*350458a6SOliver Ruiz Dorantes 199*350458a6SOliver Ruiz Dorantes param->bdaddr = bdaddr; 200*350458a6SOliver Ruiz Dorantes 20132c01b55SOliver Ruiz Dorantes } 20232c01b55SOliver Ruiz Dorantes 20332c01b55SOliver Ruiz Dorantes return command; 20432c01b55SOliver Ruiz Dorantes } 20532c01b55SOliver Ruiz Dorantes 20632c01b55SOliver Ruiz Dorantes 20732c01b55SOliver Ruiz Dorantes #if 0 20832c01b55SOliver Ruiz Dorantes #pragma mark - INFORMATIONAL_PARAM - 20932c01b55SOliver Ruiz Dorantes #endif 21032c01b55SOliver Ruiz Dorantes 21132c01b55SOliver Ruiz Dorantes 21232c01b55SOliver Ruiz Dorantes void* buildReadBufferSize(size_t* outsize) 21332c01b55SOliver Ruiz Dorantes { 21432c01b55SOliver Ruiz Dorantes return buildCommand(OGF_INFORMATIONAL_PARAM, OCF_READ_BUFFER_SIZE, NULL, 0, outsize); 21532c01b55SOliver Ruiz Dorantes } 21632c01b55SOliver Ruiz Dorantes 21732c01b55SOliver Ruiz Dorantes 21832c01b55SOliver Ruiz Dorantes void* buildReadBdAddr(size_t* outsize) 21932c01b55SOliver Ruiz Dorantes { 22032c01b55SOliver Ruiz Dorantes return buildCommand(OGF_INFORMATIONAL_PARAM, OCF_READ_BD_ADDR, NULL, 0, outsize); 22132c01b55SOliver Ruiz Dorantes } 222631aa548SOliver Ruiz Dorantes 223631aa548SOliver Ruiz Dorantes 224631aa548SOliver Ruiz Dorantes 225631aa548SOliver Ruiz Dorantes 226