1 /* 2 * Copyright (C) 2009-2012 by Matthias Ringwald 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of the copyright holders nor the names of 14 * contributors may be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY MATTHIAS RINGWALD AND CONTRIBUTORS 18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 20 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS 21 * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 23 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 24 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 25 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 27 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 * 30 */ 31 32 /* 33 * ant_cmds.c 34 * 35 * See http://www.thisisant.com/ for more info on ANT(tm) 36 * 37 * Created by Matthias Ringwald on 2012-11-06. 38 */ 39 40 41 #include <string.h> 42 43 #include "ant_cmds.h" 44 #include "classic/sdp_util.h" 45 #include "btstack_config.h" 46 #include "hci.h" 47 48 /** 49 * construct ANT HCI Command based on template 50 * 51 * Format: 52 * 0: adds a zero byte 53 * 1,2,3,4: one to four byte value 54 * D: pointer to 8 bytes of ANT data 55 */ 56 static uint16_t ant_cmd_create_from_template(uint8_t *hci_cmd_buffer, const ant_cmd_t *cmd, va_list argptr){ 57 58 hci_cmd_buffer[0] = 0xd1; 59 hci_cmd_buffer[1] = 0xfd; 60 // hci packet lengh 2 61 // ant packet length 3 62 hci_cmd_buffer[4] = 0x00; 63 hci_cmd_buffer[6] = cmd->message_id; 64 int pos = 7; 65 66 const char *format = cmd->format; 67 uint16_t word; 68 uint32_t longword; 69 uint8_t * ptr; 70 while (*format) { 71 switch(*format) { 72 case '0': // dummy 73 hci_cmd_buffer[pos++] = 0; 74 break; 75 case '1': // 8 bit value 76 case '2': // 16 bit value 77 word = va_arg(argptr, int); // minimal va_arg is int: 2 bytes on 8+16 bit CPUs 78 hci_cmd_buffer[pos++] = word & 0xff; 79 if (*format == '2') { 80 hci_cmd_buffer[pos++] = word >> 8; 81 } else if (*format == 'H') { 82 // TODO implement opaque client connection handles 83 // pass module handle for now 84 hci_cmd_buffer[pos++] = word >> 8; 85 } 86 break; 87 case '3': 88 case '4': 89 longword = va_arg(argptr, uint32_t); 90 // longword = va_arg(argptr, int); 91 hci_cmd_buffer[pos++] = longword; 92 hci_cmd_buffer[pos++] = longword >> 8; 93 hci_cmd_buffer[pos++] = longword >> 16; 94 if (*format == '4'){ 95 hci_cmd_buffer[pos++] = longword >> 24; 96 } 97 break; 98 case 'D': // 8 byte data block 99 ptr = va_arg(argptr, uint8_t *); 100 memcpy(&hci_cmd_buffer[pos], ptr, 8); 101 pos += 8; 102 break; 103 104 default: 105 break; 106 } 107 format++; 108 }; 109 110 hci_cmd_buffer[2] = pos - 3; 111 hci_cmd_buffer[3] = pos - 5; 112 hci_cmd_buffer[5] = pos - 7; 113 return pos; 114 } 115 116 /** 117 * construct ANT HCI Command based on template 118 * 119 * mainly calls ant_cmd_create_from_template 120 */ 121 uint16_t ant_create_cmd(uint8_t *hci_cmd_buffer, const ant_cmd_t *cmd, ...){ 122 va_list argptr; 123 va_start(argptr, cmd); 124 uint16_t len = ant_cmd_create_from_template(hci_cmd_buffer, cmd, argptr); 125 va_end(argptr); 126 return len; 127 } 128 129 /** 130 * pre: numcmds >= 0 - it's allowed to send a command to the controller 131 */ 132 uint8_t ant_packet_buffer[30]; 133 int ant_send_cmd(const ant_cmd_t *cmd, ...){ 134 va_list argptr; 135 va_start(argptr, cmd); 136 uint16_t size = ant_cmd_create_from_template(ant_packet_buffer, cmd, argptr); 137 va_end(argptr); 138 return hci_send_cmd_packet(ant_packet_buffer, size); 139 } 140 141 /** 142 * ANT commands as found in http://www.thisisant.com/resources/ant-message-protocol-and-usage/ 143 */ 144 145 const ant_cmd_t ant_reset = { 146 MESG_SYSTEM_RESET_ID, "0" 147 }; 148 149 const ant_cmd_t ant_assign_channel = { 150 MESG_ASSIGN_CHANNEL_ID, "111" 151 // channel number, channel type, network number 152 }; 153 154 const ant_cmd_t ant_un_assign_channel = { 155 MESG_UNASSIGN_CHANNEL_ID, "1" 156 // channel number 157 }; 158 159 const ant_cmd_t ant_search_timeout = { 160 MESG_CHANNEL_SEARCH_TIMEOUT_ID, "11" 161 // channel number, timeout 162 }; 163 164 const ant_cmd_t ant_lp_search_timeout = { 165 MESG_SET_LP_SEARCH_TIMEOUT_ID, "11" 166 // channel number, timeout 167 }; 168 169 const ant_cmd_t ant_network_key = { 170 MESG_NETWORK_KEY_ID, "1D" 171 // network number, pointer to 8 byte network key 172 }; 173 174 const ant_cmd_t ant_channel_id = { 175 MESG_CHANNEL_ID_ID, "1211" 176 // channel number, device number, device type, transmit type 177 }; 178 179 const ant_cmd_t ant_channel_power = { 180 MESG_RADIO_TX_POWER_ID, "11" 181 // channel number, power 182 }; 183 184 const ant_cmd_t ant_channel_period = { 185 MESG_CHANNEL_MESG_PERIOD_ID, "12" 186 // channel number, period 187 }; 188 189 const ant_cmd_t ant_prox_search_config = { 190 MESG_PROX_SEARCH_CONFIG_ID, "11" 191 // channel number, prox level 192 }; 193 194 const ant_cmd_t ant_broadcast = { 195 MESG_BROADCAST_DATA_ID, "1D" 196 // channel number, pointer to 8 byte data 197 }; 198 199 const ant_cmd_t ant_acknowledged = { 200 MESG_ACKNOWLEDGED_DATA_ID, "1D" 201 // channel number, pointer to 8 byte data 202 }; 203 204 const ant_cmd_t ant_burst_packet = { 205 MESG_BURST_DATA_ID, "1D" 206 // channel number, pointer to 8 byte data 207 }; 208 209 const ant_cmd_t ant_open_channel = { 210 MESG_OPEN_CHANNEL_ID, "1" 211 // channel number 212 }; 213 214 const ant_cmd_t ant_close_channel = { 215 MESG_CLOSE_CHANNEL_ID, "1" 216 // channel number 217 }; 218 219 const ant_cmd_t ant_request_message = { 220 MESG_REQUEST_ID, "11" 221 // channel number, requested message 222 }; 223