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> 13*4079af86SRene Gollent #include <string.h> 1432c01b55SOliver Ruiz Dorantes 1532c01b55SOliver Ruiz Dorantes #include "CommandManager.h" 1632c01b55SOliver Ruiz Dorantes 1732c01b55SOliver Ruiz Dorantes 1832c01b55SOliver Ruiz Dorantes inline void* buildCommand(uint8 ogf, uint8 ocf, void** param, size_t psize, size_t* outsize) 1932c01b55SOliver Ruiz Dorantes { 2032c01b55SOliver Ruiz Dorantes struct hci_command_header* header; 2132c01b55SOliver Ruiz Dorantes 2232c01b55SOliver Ruiz Dorantes #ifdef BT_IOCTLS_PASS_SIZE 2332c01b55SOliver Ruiz Dorantes header = (struct hci_command_header*) malloc(psize + sizeof(struct hci_command_header)); 2432c01b55SOliver Ruiz Dorantes *outsize = psize + sizeof(struct hci_command_header); 2532c01b55SOliver Ruiz Dorantes #else 2632c01b55SOliver Ruiz Dorantes size_t* size = (size_t*)malloc(psize + sizeof(struct hci_command_header) + sizeof(size_t)); 2732c01b55SOliver Ruiz Dorantes *outsize = psize + sizeof(struct hci_command_header) + sizeof(size_t); 2832c01b55SOliver Ruiz Dorantes 2932c01b55SOliver Ruiz Dorantes *size = psize + sizeof(struct hci_command_header); 3032c01b55SOliver Ruiz Dorantes header = (struct hci_command_header*) (((uint8*)size)+4); 3132c01b55SOliver Ruiz Dorantes #endif 3232c01b55SOliver Ruiz Dorantes 3332c01b55SOliver Ruiz Dorantes 3432c01b55SOliver Ruiz Dorantes if (header != NULL) { 3532c01b55SOliver Ruiz Dorantes 3632c01b55SOliver Ruiz Dorantes header->opcode = B_HOST_TO_LENDIAN_INT16(PACK_OPCODE(ogf, ocf)); 3732c01b55SOliver Ruiz Dorantes header->clen = psize; 3832c01b55SOliver Ruiz Dorantes 3932c01b55SOliver Ruiz Dorantes if (param != NULL && psize != 0) { 4032c01b55SOliver Ruiz Dorantes *param = ((uint8*)header) + sizeof(struct hci_command_header); 4132c01b55SOliver Ruiz Dorantes } 4232c01b55SOliver Ruiz Dorantes } 4332c01b55SOliver Ruiz Dorantes #ifdef BT_IOCTLS_PASS_SIZE 4432c01b55SOliver Ruiz Dorantes return header; 4532c01b55SOliver Ruiz Dorantes #else 4632c01b55SOliver Ruiz Dorantes return (void*)size; 4732c01b55SOliver Ruiz Dorantes #endif 4832c01b55SOliver Ruiz Dorantes } 4932c01b55SOliver Ruiz Dorantes 5032c01b55SOliver Ruiz Dorantes 5132c01b55SOliver Ruiz Dorantes #if 0 5232c01b55SOliver Ruiz Dorantes #pragma mark - CONTROL BASEBAND - 5332c01b55SOliver Ruiz Dorantes #endif 5432c01b55SOliver Ruiz Dorantes 5532c01b55SOliver Ruiz Dorantes 5632c01b55SOliver Ruiz Dorantes void* buildReset(size_t* outsize) 5732c01b55SOliver Ruiz Dorantes { 5832c01b55SOliver Ruiz Dorantes return buildCommand(OGF_CONTROL_BASEBAND, OCF_RESET, NULL, 0, outsize); 5932c01b55SOliver Ruiz Dorantes } 6032c01b55SOliver Ruiz Dorantes 6132c01b55SOliver Ruiz Dorantes 6232c01b55SOliver Ruiz Dorantes void* buildReadLocalName(size_t* outsize) 6332c01b55SOliver Ruiz Dorantes { 6432c01b55SOliver Ruiz Dorantes return buildCommand(OGF_CONTROL_BASEBAND, OCF_READ_LOCAL_NAME, NULL, 0, outsize); 6532c01b55SOliver Ruiz Dorantes } 6632c01b55SOliver Ruiz Dorantes 6732c01b55SOliver Ruiz Dorantes 68631aa548SOliver Ruiz Dorantes void* buildWriteScan(uint8 scanmode, size_t* outsize) 69631aa548SOliver Ruiz Dorantes { 70631aa548SOliver Ruiz Dorantes struct hci_write_scan_enable* param; 71631aa548SOliver Ruiz Dorantes void* command = buildCommand(OGF_CONTROL_BASEBAND, OCF_WRITE_SCAN_ENABLE, (void**) ¶m, sizeof(struct hci_write_scan_enable), outsize); 72631aa548SOliver Ruiz Dorantes 73631aa548SOliver Ruiz Dorantes 74631aa548SOliver Ruiz Dorantes if (command != NULL) { 75631aa548SOliver Ruiz Dorantes param->scan = scanmode; 76631aa548SOliver Ruiz Dorantes } 77631aa548SOliver Ruiz Dorantes 78631aa548SOliver Ruiz Dorantes return command; 79631aa548SOliver Ruiz Dorantes 80631aa548SOliver Ruiz Dorantes } 81631aa548SOliver Ruiz Dorantes 82631aa548SOliver Ruiz Dorantes 83631aa548SOliver Ruiz Dorantes void* buildAuthEnable(uint8 auth, size_t* outsize) 84631aa548SOliver Ruiz Dorantes { 85631aa548SOliver Ruiz Dorantes struct hci_write_authentication_enable* param; 86631aa548SOliver Ruiz Dorantes void* command = buildCommand(OGF_CONTROL_BASEBAND, OCF_WRITE_AUTH_ENABLE, (void**) ¶m, sizeof(struct hci_write_authentication_enable), outsize); 87631aa548SOliver Ruiz Dorantes 88631aa548SOliver Ruiz Dorantes 89631aa548SOliver Ruiz Dorantes if (command != NULL) { 90631aa548SOliver Ruiz Dorantes param->authentication = auth; 91631aa548SOliver Ruiz Dorantes } 92631aa548SOliver Ruiz Dorantes 93631aa548SOliver Ruiz Dorantes return command; 94631aa548SOliver Ruiz Dorantes 95631aa548SOliver Ruiz Dorantes } 96631aa548SOliver Ruiz Dorantes 97631aa548SOliver Ruiz Dorantes 9832c01b55SOliver Ruiz Dorantes #if 0 9932c01b55SOliver Ruiz Dorantes #pragma mark - LINK CONTROL - 10032c01b55SOliver Ruiz Dorantes #endif 10132c01b55SOliver Ruiz Dorantes 102631aa548SOliver Ruiz Dorantes void* buildCreateConnection(bdaddr_t bdaddr) 103631aa548SOliver Ruiz Dorantes { 104631aa548SOliver Ruiz Dorantes /* 105631aa548SOliver Ruiz Dorantes cm4.size = sizeof(struct hci_command_header)+sizeof(struct hci_cp_create_conn); 106631aa548SOliver Ruiz Dorantes cm4.header.opcode = B_HOST_TO_LENDIAN_INT16(hci_opcode_pack(OGF_LINK_CONTROL, OCF_CREATE_CONN)); 107631aa548SOliver Ruiz Dorantes cm4.body.bdaddr.b[0] = 0x92; 108631aa548SOliver Ruiz Dorantes cm4.body.bdaddr.b[1] = 0xd3; 109631aa548SOliver Ruiz Dorantes cm4.body.bdaddr.b[2] = 0xaf; 110631aa548SOliver Ruiz Dorantes cm4.body.bdaddr.b[3] = 0xd9; 111631aa548SOliver Ruiz Dorantes cm4.body.bdaddr.b[4] = 0x0a; 112631aa548SOliver Ruiz Dorantes cm4.body.bdaddr.b[5] = 0x00; 113631aa548SOliver Ruiz Dorantes cm4.body.pkt_type = 0xFFFF; 114631aa548SOliver Ruiz Dorantes cm4.body.pscan_rep_mode = 1; 115631aa548SOliver Ruiz Dorantes cm4.body.pscan_mode = 0; 116631aa548SOliver Ruiz Dorantes cm4.body.clock_offset = 0xc7; 117631aa548SOliver Ruiz Dorantes cm4.body.role_switch = 1; 118631aa548SOliver Ruiz Dorantes cm4.header.clen = 13; 119631aa548SOliver Ruiz Dorantes ioctl(fd1, ISSUE_BT_COMMAND, &cm4, sizeof(cm4)); 120631aa548SOliver Ruiz Dorantes */ 121631aa548SOliver Ruiz Dorantes 122631aa548SOliver Ruiz Dorantes return NULL; 123631aa548SOliver Ruiz Dorantes } 124631aa548SOliver Ruiz Dorantes 12532c01b55SOliver Ruiz Dorantes 12632c01b55SOliver Ruiz Dorantes void* buildRemoteNameRequest(bdaddr_t bdaddr,uint8 pscan_rep_mode, uint16 clock_offset, size_t* outsize) 12732c01b55SOliver Ruiz Dorantes { 12832c01b55SOliver Ruiz Dorantes 12932c01b55SOliver Ruiz Dorantes struct hci_remote_name_request* param; 13032c01b55SOliver Ruiz Dorantes void* command = buildCommand(OGF_LINK_CONTROL, OCF_REMOTE_NAME_REQUEST, (void**) ¶m, sizeof(struct hci_remote_name_request), outsize); 13132c01b55SOliver Ruiz Dorantes 13232c01b55SOliver Ruiz Dorantes if (command != NULL) { 13332c01b55SOliver Ruiz Dorantes param->bdaddr = bdaddr; 13432c01b55SOliver Ruiz Dorantes param->pscan_rep_mode = pscan_rep_mode; 13532c01b55SOliver Ruiz Dorantes param->clock_offset = clock_offset; 13632c01b55SOliver Ruiz Dorantes } 13732c01b55SOliver Ruiz Dorantes 13832c01b55SOliver Ruiz Dorantes return command; 13932c01b55SOliver Ruiz Dorantes } 14032c01b55SOliver Ruiz Dorantes 14132c01b55SOliver Ruiz Dorantes 14232c01b55SOliver Ruiz Dorantes void* buildInquiry(uint32 lap, uint8 length, uint8 num_rsp, size_t* outsize) 14332c01b55SOliver Ruiz Dorantes { 14432c01b55SOliver Ruiz Dorantes 14532c01b55SOliver Ruiz Dorantes struct hci_cp_inquiry* param; 14632c01b55SOliver Ruiz Dorantes void* command = buildCommand(OGF_LINK_CONTROL, OCF_INQUIRY, (void**) ¶m, sizeof(struct hci_cp_inquiry), outsize); 14732c01b55SOliver Ruiz Dorantes 14832c01b55SOliver Ruiz Dorantes if (command != NULL) { 14932c01b55SOliver Ruiz Dorantes 15032c01b55SOliver Ruiz Dorantes param->lap[2] = (lap >> 16) & 0xFF; 15132c01b55SOliver Ruiz Dorantes param->lap[1] = (lap >> 8) & 0xFF; 15232c01b55SOliver Ruiz Dorantes param->lap[0] = (lap >> 0) & 0xFF; 15332c01b55SOliver Ruiz Dorantes param->length = length; 15432c01b55SOliver Ruiz Dorantes param->num_rsp = num_rsp; 155350458a6SOliver Ruiz Dorantes } 156350458a6SOliver Ruiz Dorantes 157350458a6SOliver Ruiz Dorantes return command; 158350458a6SOliver Ruiz Dorantes } 159350458a6SOliver Ruiz Dorantes 160350458a6SOliver Ruiz Dorantes void* buildInquiryCancel(size_t* outsize) 161350458a6SOliver Ruiz Dorantes { 162350458a6SOliver Ruiz Dorantes 163350458a6SOliver Ruiz Dorantes return buildCommand(OGF_LINK_CONTROL, OCF_INQUIRY_CANCEL, NULL, 0, outsize); 164350458a6SOliver Ruiz Dorantes 165350458a6SOliver Ruiz Dorantes } 166350458a6SOliver Ruiz Dorantes 167350458a6SOliver Ruiz Dorantes 168350458a6SOliver Ruiz Dorantes void* buildPinCodeRequestReply(bdaddr_t bdaddr, uint8 length, char pincode[16], size_t* outsize) 169350458a6SOliver Ruiz Dorantes { 170350458a6SOliver Ruiz Dorantes 171350458a6SOliver Ruiz Dorantes struct hci_cp_pin_code_reply* param; 172350458a6SOliver Ruiz Dorantes 173350458a6SOliver Ruiz Dorantes if (length > HCI_PIN_SIZE) // PinCode cannot be longer than 16 174350458a6SOliver Ruiz Dorantes return NULL; 175350458a6SOliver Ruiz Dorantes 176350458a6SOliver Ruiz Dorantes void* command = buildCommand(OGF_LINK_CONTROL, OCF_PIN_CODE_REPLY, (void**) ¶m, sizeof(struct hci_cp_pin_code_reply), outsize); 177350458a6SOliver Ruiz Dorantes 178350458a6SOliver Ruiz Dorantes if (command != NULL) { 179350458a6SOliver Ruiz Dorantes 180350458a6SOliver Ruiz Dorantes param->bdaddr = bdaddr; 181350458a6SOliver Ruiz Dorantes param->pin_len = length; 182350458a6SOliver Ruiz Dorantes memcpy(¶m->pin_code, pincode, length); 183350458a6SOliver Ruiz Dorantes 184350458a6SOliver Ruiz Dorantes } 185350458a6SOliver Ruiz Dorantes 186350458a6SOliver Ruiz Dorantes return command; 187350458a6SOliver Ruiz Dorantes } 188350458a6SOliver Ruiz Dorantes 189350458a6SOliver Ruiz Dorantes 1900df89492SOliver Ruiz Dorantes void* buildPinCodeRequestNegativeReply(bdaddr_t bdaddr, size_t* outsize) 191350458a6SOliver Ruiz Dorantes { 192350458a6SOliver Ruiz Dorantes 193350458a6SOliver Ruiz Dorantes struct hci_cp_pin_code_neg_reply* param; 194350458a6SOliver Ruiz Dorantes 195350458a6SOliver Ruiz Dorantes void* command = buildCommand(OGF_LINK_CONTROL, OCF_PIN_CODE_NEG_REPLY, 196350458a6SOliver Ruiz Dorantes (void**) ¶m, sizeof(struct hci_cp_pin_code_neg_reply), outsize); 197350458a6SOliver Ruiz Dorantes 198350458a6SOliver Ruiz Dorantes if (command != NULL) { 199350458a6SOliver Ruiz Dorantes 200350458a6SOliver Ruiz Dorantes param->bdaddr = bdaddr; 201350458a6SOliver Ruiz Dorantes 20232c01b55SOliver Ruiz Dorantes } 20332c01b55SOliver Ruiz Dorantes 20432c01b55SOliver Ruiz Dorantes return command; 20532c01b55SOliver Ruiz Dorantes } 20632c01b55SOliver Ruiz Dorantes 20732c01b55SOliver Ruiz Dorantes 20832c01b55SOliver Ruiz Dorantes #if 0 20932c01b55SOliver Ruiz Dorantes #pragma mark - INFORMATIONAL_PARAM - 21032c01b55SOliver Ruiz Dorantes #endif 21132c01b55SOliver Ruiz Dorantes 21232c01b55SOliver Ruiz Dorantes 21332c01b55SOliver Ruiz Dorantes void* buildReadBufferSize(size_t* outsize) 21432c01b55SOliver Ruiz Dorantes { 21532c01b55SOliver Ruiz Dorantes return buildCommand(OGF_INFORMATIONAL_PARAM, OCF_READ_BUFFER_SIZE, NULL, 0, outsize); 21632c01b55SOliver Ruiz Dorantes } 21732c01b55SOliver Ruiz Dorantes 21832c01b55SOliver Ruiz Dorantes 21932c01b55SOliver Ruiz Dorantes void* buildReadBdAddr(size_t* outsize) 22032c01b55SOliver Ruiz Dorantes { 22132c01b55SOliver Ruiz Dorantes return buildCommand(OGF_INFORMATIONAL_PARAM, OCF_READ_BD_ADDR, NULL, 0, outsize); 22232c01b55SOliver Ruiz Dorantes } 223631aa548SOliver Ruiz Dorantes 224631aa548SOliver Ruiz Dorantes 225631aa548SOliver Ruiz Dorantes 226631aa548SOliver Ruiz Dorantes 227