xref: /btstack/chipset/cc256x/ant_cmd.c (revision e501bae08349e058caa4648e0af3dd01cbd89d20)
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  */
ant_cmd_create_from_template(uint8_t * hci_cmd_buffer,const ant_cmd_t * cmd,va_list argptr)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  */
ant_create_cmd(uint8_t * hci_cmd_buffer,const ant_cmd_t * cmd,...)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];
ant_send_cmd(const ant_cmd_t * cmd,...)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