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 #define __BTSTACK_FILE__ "ant_cmd.c" 33 34 /* 35 * ant_cmds.c 36 * 37 * See http://www.thisisant.com/ for more info on ANT(tm) 38 * 39 * Created by Matthias Ringwald on 2012-11-06. 40 */ 41 42 43 #include <string.h> 44 45 #include "ant_cmd.h" 46 #include "classic/sdp_util.h" 47 #include "btstack_config.h" 48 #include "hci.h" 49 50 /** 51 * construct ANT HCI Command based on template 52 * 53 * Format: 54 * 0: adds a zero byte 55 * 1,2,3,4: one to four byte value 56 * D: pointer to 8 bytes of ANT data 57 */ 58 static uint16_t ant_cmd_create_from_template(uint8_t *hci_cmd_buffer, const ant_cmd_t *cmd, va_list argptr){ 59 60 hci_cmd_buffer[0] = 0xd1; 61 hci_cmd_buffer[1] = 0xfd; 62 // hci packet lengh 2 63 // ant packet length 3 64 hci_cmd_buffer[4] = 0x00; 65 hci_cmd_buffer[6] = cmd->message_id; 66 int pos = 7; 67 68 const char *format = cmd->format; 69 uint16_t word; 70 uint32_t longword; 71 uint8_t * ptr; 72 while (*format) { 73 switch(*format) { 74 case '0': // dummy 75 hci_cmd_buffer[pos++] = 0; 76 break; 77 case '1': // 8 bit value 78 case '2': // 16 bit value 79 word = va_arg(argptr, int); // minimal va_arg is int: 2 bytes on 8+16 bit CPUs 80 hci_cmd_buffer[pos++] = word & 0xff; 81 if (*format == '2') { 82 hci_cmd_buffer[pos++] = word >> 8; 83 } else if (*format == 'H') { 84 // TODO implement opaque client connection handles 85 // pass module handle for now 86 hci_cmd_buffer[pos++] = word >> 8; 87 } 88 break; 89 case '3': 90 case '4': 91 longword = va_arg(argptr, uint32_t); 92 // longword = va_arg(argptr, int); 93 hci_cmd_buffer[pos++] = longword; 94 hci_cmd_buffer[pos++] = longword >> 8; 95 hci_cmd_buffer[pos++] = longword >> 16; 96 if (*format == '4'){ 97 hci_cmd_buffer[pos++] = longword >> 24; 98 } 99 break; 100 case 'D': // 8 byte data block 101 ptr = va_arg(argptr, uint8_t *); 102 memcpy(&hci_cmd_buffer[pos], ptr, 8); 103 pos += 8; 104 break; 105 106 default: 107 break; 108 } 109 format++; 110 }; 111 112 hci_cmd_buffer[2] = pos - 3; 113 hci_cmd_buffer[3] = pos - 5; 114 hci_cmd_buffer[5] = pos - 7; 115 return pos; 116 } 117 118 /** 119 * construct ANT HCI Command based on template 120 * 121 * mainly calls ant_cmd_create_from_template 122 */ 123 uint16_t ant_create_cmd(uint8_t *hci_cmd_buffer, const ant_cmd_t *cmd, ...){ 124 va_list argptr; 125 va_start(argptr, cmd); 126 uint16_t len = ant_cmd_create_from_template(hci_cmd_buffer, cmd, argptr); 127 va_end(argptr); 128 return len; 129 } 130 131 /** 132 * pre: numcmds >= 0 - it's allowed to send a command to the controller 133 */ 134 uint8_t ant_packet_buffer[30]; 135 int ant_send_cmd(const ant_cmd_t *cmd, ...){ 136 va_list argptr; 137 va_start(argptr, cmd); 138 uint16_t size = ant_cmd_create_from_template(ant_packet_buffer, cmd, argptr); 139 va_end(argptr); 140 return hci_send_cmd_packet(ant_packet_buffer, size); 141 } 142 143 /** 144 * ANT commands as found in http://www.thisisant.com/resources/ant-message-protocol-and-usage/ 145 */ 146 147 const ant_cmd_t ant_reset = { 148 MESG_SYSTEM_RESET_ID, "0" 149 }; 150 151 const ant_cmd_t ant_assign_channel = { 152 MESG_ASSIGN_CHANNEL_ID, "111" 153 // channel number, channel type, network number 154 }; 155 156 const ant_cmd_t ant_un_assign_channel = { 157 MESG_UNASSIGN_CHANNEL_ID, "1" 158 // channel number 159 }; 160 161 const ant_cmd_t ant_search_timeout = { 162 MESG_CHANNEL_SEARCH_TIMEOUT_ID, "11" 163 // channel number, timeout 164 }; 165 166 const ant_cmd_t ant_lp_search_timeout = { 167 MESG_SET_LP_SEARCH_TIMEOUT_ID, "11" 168 // channel number, timeout 169 }; 170 171 const ant_cmd_t ant_network_key = { 172 MESG_NETWORK_KEY_ID, "1D" 173 // network number, pointer to 8 byte network key 174 }; 175 176 const ant_cmd_t ant_channel_id = { 177 MESG_CHANNEL_ID_ID, "1211" 178 // channel number, device number, device type, transmit type 179 }; 180 181 const ant_cmd_t ant_channel_power = { 182 MESG_RADIO_TX_POWER_ID, "11" 183 // channel number, power 184 }; 185 186 const ant_cmd_t ant_channel_period = { 187 MESG_CHANNEL_MESG_PERIOD_ID, "12" 188 // channel number, period 189 }; 190 191 const ant_cmd_t ant_prox_search_config = { 192 MESG_PROX_SEARCH_CONFIG_ID, "11" 193 // channel number, prox level 194 }; 195 196 const ant_cmd_t ant_broadcast = { 197 MESG_BROADCAST_DATA_ID, "1D" 198 // channel number, pointer to 8 byte data 199 }; 200 201 const ant_cmd_t ant_acknowledged = { 202 MESG_ACKNOWLEDGED_DATA_ID, "1D" 203 // channel number, pointer to 8 byte data 204 }; 205 206 const ant_cmd_t ant_burst_packet = { 207 MESG_BURST_DATA_ID, "1D" 208 // channel number, pointer to 8 byte data 209 }; 210 211 const ant_cmd_t ant_open_channel = { 212 MESG_OPEN_CHANNEL_ID, "1" 213 // channel number 214 }; 215 216 const ant_cmd_t ant_close_channel = { 217 MESG_CLOSE_CHANNEL_ID, "1" 218 // channel number 219 }; 220 221 const ant_cmd_t ant_request_message = { 222 MESG_REQUEST_ID, "11" 223 // channel number, requested message 224 }; 225