xref: /btstack/chipset/cc256x/ant_cmd.c (revision 7907f06931c075b55e3402fa469abbe35eebee25)
175a994c4SMatthias Ringwald /*
275a994c4SMatthias Ringwald  * Copyright (C) 2009-2012 by Matthias Ringwald
375a994c4SMatthias Ringwald  *
475a994c4SMatthias Ringwald  * Redistribution and use in source and binary forms, with or without
575a994c4SMatthias Ringwald  * modification, are permitted provided that the following conditions
675a994c4SMatthias Ringwald  * are met:
775a994c4SMatthias Ringwald  *
875a994c4SMatthias Ringwald  * 1. Redistributions of source code must retain the above copyright
975a994c4SMatthias Ringwald  *    notice, this list of conditions and the following disclaimer.
1075a994c4SMatthias Ringwald  * 2. Redistributions in binary form must reproduce the above copyright
1175a994c4SMatthias Ringwald  *    notice, this list of conditions and the following disclaimer in the
1275a994c4SMatthias Ringwald  *    documentation and/or other materials provided with the distribution.
1375a994c4SMatthias Ringwald  * 3. Neither the name of the copyright holders nor the names of
1475a994c4SMatthias Ringwald  *    contributors may be used to endorse or promote products derived
1575a994c4SMatthias Ringwald  *    from this software without specific prior written permission.
1675a994c4SMatthias Ringwald  *
1775a994c4SMatthias Ringwald  * THIS SOFTWARE IS PROVIDED BY MATTHIAS RINGWALD AND CONTRIBUTORS
1875a994c4SMatthias Ringwald  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1975a994c4SMatthias Ringwald  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
2075a994c4SMatthias Ringwald  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
2175a994c4SMatthias Ringwald  * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
2275a994c4SMatthias Ringwald  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
2375a994c4SMatthias Ringwald  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
2475a994c4SMatthias Ringwald  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
2575a994c4SMatthias Ringwald  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
2675a994c4SMatthias Ringwald  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
2775a994c4SMatthias Ringwald  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2875a994c4SMatthias Ringwald  * SUCH DAMAGE.
2975a994c4SMatthias Ringwald  *
3075a994c4SMatthias Ringwald  */
3175a994c4SMatthias Ringwald 
3275a994c4SMatthias Ringwald /*
3375a994c4SMatthias Ringwald  *  ant_cmds.c
3475a994c4SMatthias Ringwald  *
3575a994c4SMatthias Ringwald  *  See http://www.thisisant.com/ for more info on ANT(tm)
3675a994c4SMatthias Ringwald  *
3775a994c4SMatthias Ringwald  *  Created by Matthias Ringwald on 2012-11-06.
3875a994c4SMatthias Ringwald  */
3975a994c4SMatthias Ringwald 
4075a994c4SMatthias Ringwald 
4175a994c4SMatthias Ringwald #include <string.h>
4275a994c4SMatthias Ringwald 
4375a994c4SMatthias Ringwald #include "ant_cmds.h"
4475a994c4SMatthias Ringwald #include "classic/sdp_util.h"
45*7907f069SMatthias Ringwald #include "btstack_config.h"
4675a994c4SMatthias Ringwald #include "hci.h"
4775a994c4SMatthias Ringwald 
4875a994c4SMatthias Ringwald /**
4975a994c4SMatthias Ringwald  * construct ANT HCI Command based on template
5075a994c4SMatthias Ringwald  *
5175a994c4SMatthias Ringwald  * Format:
5275a994c4SMatthias Ringwald  *   0: adds a zero byte
5375a994c4SMatthias Ringwald  *   1,2,3,4: one to four byte value
5475a994c4SMatthias Ringwald  *   D: pointer to 8 bytes of ANT data
5575a994c4SMatthias Ringwald  */
5675a994c4SMatthias Ringwald static uint16_t ant_cmd_create_from_template(uint8_t *hci_cmd_buffer, const ant_cmd_t *cmd, va_list argptr){
5775a994c4SMatthias Ringwald 
5875a994c4SMatthias Ringwald     hci_cmd_buffer[0] = 0xd1;
5975a994c4SMatthias Ringwald     hci_cmd_buffer[1] = 0xfd;
6075a994c4SMatthias Ringwald     // hci packet lengh 2
6175a994c4SMatthias Ringwald     // ant packet length 3
6275a994c4SMatthias Ringwald     hci_cmd_buffer[4] = 0x00;
6375a994c4SMatthias Ringwald     hci_cmd_buffer[6] = cmd->message_id;
6475a994c4SMatthias Ringwald     int pos = 7;
6575a994c4SMatthias Ringwald 
6675a994c4SMatthias Ringwald     const char *format = cmd->format;
6775a994c4SMatthias Ringwald     uint16_t word;
6875a994c4SMatthias Ringwald     uint32_t longword;
6975a994c4SMatthias Ringwald     uint8_t * ptr;
7075a994c4SMatthias Ringwald     while (*format) {
7175a994c4SMatthias Ringwald         switch(*format) {
7275a994c4SMatthias Ringwald             case '0': // dummy
7375a994c4SMatthias Ringwald                 hci_cmd_buffer[pos++] = 0;
7475a994c4SMatthias Ringwald                 break;
7575a994c4SMatthias Ringwald             case '1': //  8 bit value
7675a994c4SMatthias Ringwald             case '2': // 16 bit value
7775a994c4SMatthias Ringwald                 word = va_arg(argptr, int);  // minimal va_arg is int: 2 bytes on 8+16 bit CPUs
7875a994c4SMatthias Ringwald                 hci_cmd_buffer[pos++] = word & 0xff;
7975a994c4SMatthias Ringwald                 if (*format == '2') {
8075a994c4SMatthias Ringwald                     hci_cmd_buffer[pos++] = word >> 8;
8175a994c4SMatthias Ringwald                 } else if (*format == 'H') {
8275a994c4SMatthias Ringwald                     // TODO implement opaque client connection handles
8375a994c4SMatthias Ringwald                     //      pass module handle for now
8475a994c4SMatthias Ringwald                     hci_cmd_buffer[pos++] = word >> 8;
8575a994c4SMatthias Ringwald                 }
8675a994c4SMatthias Ringwald                 break;
8775a994c4SMatthias Ringwald             case '3':
8875a994c4SMatthias Ringwald             case '4':
8975a994c4SMatthias Ringwald                 longword = va_arg(argptr, uint32_t);
9075a994c4SMatthias Ringwald                 // longword = va_arg(argptr, int);
9175a994c4SMatthias Ringwald                 hci_cmd_buffer[pos++] = longword;
9275a994c4SMatthias Ringwald                 hci_cmd_buffer[pos++] = longword >> 8;
9375a994c4SMatthias Ringwald                 hci_cmd_buffer[pos++] = longword >> 16;
9475a994c4SMatthias Ringwald                 if (*format == '4'){
9575a994c4SMatthias Ringwald                     hci_cmd_buffer[pos++] = longword >> 24;
9675a994c4SMatthias Ringwald                 }
9775a994c4SMatthias Ringwald                 break;
9875a994c4SMatthias Ringwald             case 'D': // 8 byte data block
9975a994c4SMatthias Ringwald                 ptr = va_arg(argptr, uint8_t *);
10075a994c4SMatthias Ringwald                 memcpy(&hci_cmd_buffer[pos], ptr, 8);
10175a994c4SMatthias Ringwald                 pos += 8;
10275a994c4SMatthias Ringwald                 break;
10375a994c4SMatthias Ringwald 
10475a994c4SMatthias Ringwald             default:
10575a994c4SMatthias Ringwald                 break;
10675a994c4SMatthias Ringwald         }
10775a994c4SMatthias Ringwald         format++;
10875a994c4SMatthias Ringwald     };
10975a994c4SMatthias Ringwald 
11075a994c4SMatthias Ringwald     hci_cmd_buffer[2] = pos - 3;
11175a994c4SMatthias Ringwald     hci_cmd_buffer[3] = pos - 5;
11275a994c4SMatthias Ringwald     hci_cmd_buffer[5] = pos - 7;
11375a994c4SMatthias Ringwald     return pos;
11475a994c4SMatthias Ringwald }
11575a994c4SMatthias Ringwald 
11675a994c4SMatthias Ringwald /**
11775a994c4SMatthias Ringwald  * construct ANT HCI Command based on template
11875a994c4SMatthias Ringwald  *
11975a994c4SMatthias Ringwald  * mainly calls ant_cmd_create_from_template
12075a994c4SMatthias Ringwald  */
12175a994c4SMatthias Ringwald uint16_t ant_create_cmd(uint8_t *hci_cmd_buffer, const ant_cmd_t *cmd, ...){
12275a994c4SMatthias Ringwald     va_list argptr;
12375a994c4SMatthias Ringwald     va_start(argptr, cmd);
12475a994c4SMatthias Ringwald     uint16_t len = ant_cmd_create_from_template(hci_cmd_buffer, cmd, argptr);
12575a994c4SMatthias Ringwald     va_end(argptr);
12675a994c4SMatthias Ringwald     return len;
12775a994c4SMatthias Ringwald }
12875a994c4SMatthias Ringwald 
12975a994c4SMatthias Ringwald /**
13075a994c4SMatthias Ringwald  * pre: numcmds >= 0 - it's allowed to send a command to the controller
13175a994c4SMatthias Ringwald  */
13275a994c4SMatthias Ringwald uint8_t ant_packet_buffer[30];
13375a994c4SMatthias Ringwald int ant_send_cmd(const ant_cmd_t *cmd, ...){
13475a994c4SMatthias Ringwald     va_list argptr;
13575a994c4SMatthias Ringwald     va_start(argptr, cmd);
13675a994c4SMatthias Ringwald     uint16_t size = ant_cmd_create_from_template(ant_packet_buffer, cmd, argptr);
13775a994c4SMatthias Ringwald     va_end(argptr);
13875a994c4SMatthias Ringwald     return hci_send_cmd_packet(ant_packet_buffer, size);
13975a994c4SMatthias Ringwald }
14075a994c4SMatthias Ringwald 
14175a994c4SMatthias Ringwald /**
14275a994c4SMatthias Ringwald  *  ANT commands as found in http://www.thisisant.com/resources/ant-message-protocol-and-usage/
14375a994c4SMatthias Ringwald  */
14475a994c4SMatthias Ringwald 
14575a994c4SMatthias Ringwald const ant_cmd_t ant_reset = {
14675a994c4SMatthias Ringwald MESG_SYSTEM_RESET_ID, "0"
14775a994c4SMatthias Ringwald };
14875a994c4SMatthias Ringwald 
14975a994c4SMatthias Ringwald const ant_cmd_t ant_assign_channel = {
15075a994c4SMatthias Ringwald MESG_ASSIGN_CHANNEL_ID, "111"
15175a994c4SMatthias Ringwald // channel number, channel type, network number
15275a994c4SMatthias Ringwald };
15375a994c4SMatthias Ringwald 
15475a994c4SMatthias Ringwald const ant_cmd_t ant_un_assign_channel = {
15575a994c4SMatthias Ringwald MESG_UNASSIGN_CHANNEL_ID, "1"
15675a994c4SMatthias Ringwald // channel number
15775a994c4SMatthias Ringwald };
15875a994c4SMatthias Ringwald 
15975a994c4SMatthias Ringwald const ant_cmd_t ant_search_timeout = {
16075a994c4SMatthias Ringwald MESG_CHANNEL_SEARCH_TIMEOUT_ID, "11"
16175a994c4SMatthias Ringwald // channel number, timeout
16275a994c4SMatthias Ringwald };
16375a994c4SMatthias Ringwald 
16475a994c4SMatthias Ringwald const ant_cmd_t ant_lp_search_timeout = {
16575a994c4SMatthias Ringwald MESG_SET_LP_SEARCH_TIMEOUT_ID, "11"
16675a994c4SMatthias Ringwald // channel number, timeout
16775a994c4SMatthias Ringwald };
16875a994c4SMatthias Ringwald 
16975a994c4SMatthias Ringwald const ant_cmd_t ant_network_key = {
17075a994c4SMatthias Ringwald MESG_NETWORK_KEY_ID, "1D"
17175a994c4SMatthias Ringwald // network number, pointer to 8 byte network key
17275a994c4SMatthias Ringwald };
17375a994c4SMatthias Ringwald 
17475a994c4SMatthias Ringwald const ant_cmd_t ant_channel_id = {
17575a994c4SMatthias Ringwald MESG_CHANNEL_ID_ID, "1211"
17675a994c4SMatthias Ringwald // channel number, device number, device type, transmit type
17775a994c4SMatthias Ringwald };
17875a994c4SMatthias Ringwald 
17975a994c4SMatthias Ringwald const ant_cmd_t ant_channel_power = {
18075a994c4SMatthias Ringwald MESG_RADIO_TX_POWER_ID, "11"
18175a994c4SMatthias Ringwald // channel number, power
18275a994c4SMatthias Ringwald };
18375a994c4SMatthias Ringwald 
18475a994c4SMatthias Ringwald const ant_cmd_t ant_channel_period = {
18575a994c4SMatthias Ringwald MESG_CHANNEL_MESG_PERIOD_ID, "12"
18675a994c4SMatthias Ringwald // channel number, period
18775a994c4SMatthias Ringwald };
18875a994c4SMatthias Ringwald 
18975a994c4SMatthias Ringwald const ant_cmd_t ant_prox_search_config = {
19075a994c4SMatthias Ringwald MESG_PROX_SEARCH_CONFIG_ID, "11"
19175a994c4SMatthias Ringwald // channel number, prox level
19275a994c4SMatthias Ringwald };
19375a994c4SMatthias Ringwald 
19475a994c4SMatthias Ringwald const ant_cmd_t ant_broadcast = {
19575a994c4SMatthias Ringwald MESG_BROADCAST_DATA_ID, "1D"
19675a994c4SMatthias Ringwald // channel number, pointer to 8 byte data
19775a994c4SMatthias Ringwald };
19875a994c4SMatthias Ringwald 
19975a994c4SMatthias Ringwald const ant_cmd_t ant_acknowledged = {
20075a994c4SMatthias Ringwald MESG_ACKNOWLEDGED_DATA_ID, "1D"
20175a994c4SMatthias Ringwald // channel number, pointer to 8 byte data
20275a994c4SMatthias Ringwald };
20375a994c4SMatthias Ringwald 
20475a994c4SMatthias Ringwald const ant_cmd_t ant_burst_packet = {
20575a994c4SMatthias Ringwald MESG_BURST_DATA_ID, "1D"
20675a994c4SMatthias Ringwald // channel number, pointer to 8 byte data
20775a994c4SMatthias Ringwald };
20875a994c4SMatthias Ringwald 
20975a994c4SMatthias Ringwald const ant_cmd_t ant_open_channel = {
21075a994c4SMatthias Ringwald MESG_OPEN_CHANNEL_ID, "1"
21175a994c4SMatthias Ringwald // channel number
21275a994c4SMatthias Ringwald };
21375a994c4SMatthias Ringwald 
21475a994c4SMatthias Ringwald const ant_cmd_t ant_close_channel = {
21575a994c4SMatthias Ringwald MESG_CLOSE_CHANNEL_ID, "1"
21675a994c4SMatthias Ringwald // channel number
21775a994c4SMatthias Ringwald };
21875a994c4SMatthias Ringwald 
21975a994c4SMatthias Ringwald const ant_cmd_t ant_request_message = {
22075a994c4SMatthias Ringwald MESG_REQUEST_ID, "11"
22175a994c4SMatthias Ringwald // channel number, requested message
22275a994c4SMatthias Ringwald };
223