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