xref: /btstack/chipset/cc256x/ant_cmd.c (revision df25739fc3ea5a0a90f0f5925e6461d653697d2e)
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