xref: /btstack/chipset/cc256x/ant_cmd.c (revision e501bae08349e058caa4648e0af3dd01cbd89d20)
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 
32*e501bae0SMatthias Ringwald #define BTSTACK_FILE__ "ant_cmd.c"
33ab2c6ae4SMatthias Ringwald 
3475a994c4SMatthias Ringwald /*
3575a994c4SMatthias Ringwald  *  ant_cmds.c
3675a994c4SMatthias Ringwald  *
3775a994c4SMatthias Ringwald  *  See http://www.thisisant.com/ for more info on ANT(tm)
3875a994c4SMatthias Ringwald  *
3975a994c4SMatthias Ringwald  *  Created by Matthias Ringwald on 2012-11-06.
4075a994c4SMatthias Ringwald  */
4175a994c4SMatthias Ringwald 
4275a994c4SMatthias Ringwald 
4375a994c4SMatthias Ringwald #include <string.h>
4475a994c4SMatthias Ringwald 
455ca1628eSMatthias Ringwald #include "ant_cmd.h"
4675a994c4SMatthias Ringwald #include "classic/sdp_util.h"
477907f069SMatthias Ringwald #include "btstack_config.h"
4875a994c4SMatthias Ringwald #include "hci.h"
4975a994c4SMatthias Ringwald 
5075a994c4SMatthias Ringwald /**
5175a994c4SMatthias Ringwald  * construct ANT HCI Command based on template
5275a994c4SMatthias Ringwald  *
5375a994c4SMatthias Ringwald  * Format:
5475a994c4SMatthias Ringwald  *   0: adds a zero byte
5575a994c4SMatthias Ringwald  *   1,2,3,4: one to four byte value
5675a994c4SMatthias Ringwald  *   D: pointer to 8 bytes of ANT data
5775a994c4SMatthias Ringwald  */
ant_cmd_create_from_template(uint8_t * hci_cmd_buffer,const ant_cmd_t * cmd,va_list argptr)5875a994c4SMatthias Ringwald static uint16_t ant_cmd_create_from_template(uint8_t *hci_cmd_buffer, const ant_cmd_t *cmd, va_list argptr){
5975a994c4SMatthias Ringwald 
6075a994c4SMatthias Ringwald     hci_cmd_buffer[0] = 0xd1;
6175a994c4SMatthias Ringwald     hci_cmd_buffer[1] = 0xfd;
6275a994c4SMatthias Ringwald     // hci packet lengh 2
6375a994c4SMatthias Ringwald     // ant packet length 3
6475a994c4SMatthias Ringwald     hci_cmd_buffer[4] = 0x00;
6575a994c4SMatthias Ringwald     hci_cmd_buffer[6] = cmd->message_id;
6675a994c4SMatthias Ringwald     int pos = 7;
6775a994c4SMatthias Ringwald 
6875a994c4SMatthias Ringwald     const char *format = cmd->format;
6975a994c4SMatthias Ringwald     uint16_t word;
7075a994c4SMatthias Ringwald     uint32_t longword;
7175a994c4SMatthias Ringwald     uint8_t * ptr;
7275a994c4SMatthias Ringwald     while (*format) {
7375a994c4SMatthias Ringwald         switch(*format) {
7475a994c4SMatthias Ringwald             case '0': // dummy
7575a994c4SMatthias Ringwald                 hci_cmd_buffer[pos++] = 0;
7675a994c4SMatthias Ringwald                 break;
7775a994c4SMatthias Ringwald             case '1': //  8 bit value
7875a994c4SMatthias Ringwald             case '2': // 16 bit value
7975a994c4SMatthias Ringwald                 word = va_arg(argptr, int);  // minimal va_arg is int: 2 bytes on 8+16 bit CPUs
8075a994c4SMatthias Ringwald                 hci_cmd_buffer[pos++] = word & 0xff;
8175a994c4SMatthias Ringwald                 if (*format == '2') {
8275a994c4SMatthias Ringwald                     hci_cmd_buffer[pos++] = word >> 8;
8375a994c4SMatthias Ringwald                 } else if (*format == 'H') {
8475a994c4SMatthias Ringwald                     // TODO implement opaque client connection handles
8575a994c4SMatthias Ringwald                     //      pass module handle for now
8675a994c4SMatthias Ringwald                     hci_cmd_buffer[pos++] = word >> 8;
8775a994c4SMatthias Ringwald                 }
8875a994c4SMatthias Ringwald                 break;
8975a994c4SMatthias Ringwald             case '3':
9075a994c4SMatthias Ringwald             case '4':
9175a994c4SMatthias Ringwald                 longword = va_arg(argptr, uint32_t);
9275a994c4SMatthias Ringwald                 // longword = va_arg(argptr, int);
9375a994c4SMatthias Ringwald                 hci_cmd_buffer[pos++] = longword;
9475a994c4SMatthias Ringwald                 hci_cmd_buffer[pos++] = longword >> 8;
9575a994c4SMatthias Ringwald                 hci_cmd_buffer[pos++] = longword >> 16;
9675a994c4SMatthias Ringwald                 if (*format == '4'){
9775a994c4SMatthias Ringwald                     hci_cmd_buffer[pos++] = longword >> 24;
9875a994c4SMatthias Ringwald                 }
9975a994c4SMatthias Ringwald                 break;
10075a994c4SMatthias Ringwald             case 'D': // 8 byte data block
10175a994c4SMatthias Ringwald                 ptr = va_arg(argptr, uint8_t *);
10275a994c4SMatthias Ringwald                 memcpy(&hci_cmd_buffer[pos], ptr, 8);
10375a994c4SMatthias Ringwald                 pos += 8;
10475a994c4SMatthias Ringwald                 break;
10575a994c4SMatthias Ringwald 
10675a994c4SMatthias Ringwald             default:
10775a994c4SMatthias Ringwald                 break;
10875a994c4SMatthias Ringwald         }
10975a994c4SMatthias Ringwald         format++;
11075a994c4SMatthias Ringwald     };
11175a994c4SMatthias Ringwald 
11275a994c4SMatthias Ringwald     hci_cmd_buffer[2] = pos - 3;
11375a994c4SMatthias Ringwald     hci_cmd_buffer[3] = pos - 5;
11475a994c4SMatthias Ringwald     hci_cmd_buffer[5] = pos - 7;
11575a994c4SMatthias Ringwald     return pos;
11675a994c4SMatthias Ringwald }
11775a994c4SMatthias Ringwald 
11875a994c4SMatthias Ringwald /**
11975a994c4SMatthias Ringwald  * construct ANT HCI Command based on template
12075a994c4SMatthias Ringwald  *
12175a994c4SMatthias Ringwald  * mainly calls ant_cmd_create_from_template
12275a994c4SMatthias Ringwald  */
ant_create_cmd(uint8_t * hci_cmd_buffer,const ant_cmd_t * cmd,...)12375a994c4SMatthias Ringwald uint16_t ant_create_cmd(uint8_t *hci_cmd_buffer, const ant_cmd_t *cmd, ...){
12475a994c4SMatthias Ringwald     va_list argptr;
12575a994c4SMatthias Ringwald     va_start(argptr, cmd);
12675a994c4SMatthias Ringwald     uint16_t len = ant_cmd_create_from_template(hci_cmd_buffer, cmd, argptr);
12775a994c4SMatthias Ringwald     va_end(argptr);
12875a994c4SMatthias Ringwald     return len;
12975a994c4SMatthias Ringwald }
13075a994c4SMatthias Ringwald 
13175a994c4SMatthias Ringwald /**
13275a994c4SMatthias Ringwald  * pre: numcmds >= 0 - it's allowed to send a command to the controller
13375a994c4SMatthias Ringwald  */
13475a994c4SMatthias Ringwald uint8_t ant_packet_buffer[30];
ant_send_cmd(const ant_cmd_t * cmd,...)13575a994c4SMatthias Ringwald int ant_send_cmd(const ant_cmd_t *cmd, ...){
13675a994c4SMatthias Ringwald     va_list argptr;
13775a994c4SMatthias Ringwald     va_start(argptr, cmd);
13875a994c4SMatthias Ringwald     uint16_t size = ant_cmd_create_from_template(ant_packet_buffer, cmd, argptr);
13975a994c4SMatthias Ringwald     va_end(argptr);
14075a994c4SMatthias Ringwald     return hci_send_cmd_packet(ant_packet_buffer, size);
14175a994c4SMatthias Ringwald }
14275a994c4SMatthias Ringwald 
14375a994c4SMatthias Ringwald /**
14475a994c4SMatthias Ringwald  *  ANT commands as found in http://www.thisisant.com/resources/ant-message-protocol-and-usage/
14575a994c4SMatthias Ringwald  */
14675a994c4SMatthias Ringwald 
14775a994c4SMatthias Ringwald const ant_cmd_t ant_reset = {
14875a994c4SMatthias Ringwald MESG_SYSTEM_RESET_ID, "0"
14975a994c4SMatthias Ringwald };
15075a994c4SMatthias Ringwald 
15175a994c4SMatthias Ringwald const ant_cmd_t ant_assign_channel = {
15275a994c4SMatthias Ringwald MESG_ASSIGN_CHANNEL_ID, "111"
15375a994c4SMatthias Ringwald // channel number, channel type, network number
15475a994c4SMatthias Ringwald };
15575a994c4SMatthias Ringwald 
15675a994c4SMatthias Ringwald const ant_cmd_t ant_un_assign_channel = {
15775a994c4SMatthias Ringwald MESG_UNASSIGN_CHANNEL_ID, "1"
15875a994c4SMatthias Ringwald // channel number
15975a994c4SMatthias Ringwald };
16075a994c4SMatthias Ringwald 
16175a994c4SMatthias Ringwald const ant_cmd_t ant_search_timeout = {
16275a994c4SMatthias Ringwald MESG_CHANNEL_SEARCH_TIMEOUT_ID, "11"
16375a994c4SMatthias Ringwald // channel number, timeout
16475a994c4SMatthias Ringwald };
16575a994c4SMatthias Ringwald 
16675a994c4SMatthias Ringwald const ant_cmd_t ant_lp_search_timeout = {
16775a994c4SMatthias Ringwald MESG_SET_LP_SEARCH_TIMEOUT_ID, "11"
16875a994c4SMatthias Ringwald // channel number, timeout
16975a994c4SMatthias Ringwald };
17075a994c4SMatthias Ringwald 
17175a994c4SMatthias Ringwald const ant_cmd_t ant_network_key = {
17275a994c4SMatthias Ringwald MESG_NETWORK_KEY_ID, "1D"
17375a994c4SMatthias Ringwald // network number, pointer to 8 byte network key
17475a994c4SMatthias Ringwald };
17575a994c4SMatthias Ringwald 
17675a994c4SMatthias Ringwald const ant_cmd_t ant_channel_id = {
17775a994c4SMatthias Ringwald MESG_CHANNEL_ID_ID, "1211"
17875a994c4SMatthias Ringwald // channel number, device number, device type, transmit type
17975a994c4SMatthias Ringwald };
18075a994c4SMatthias Ringwald 
18175a994c4SMatthias Ringwald const ant_cmd_t ant_channel_power = {
18275a994c4SMatthias Ringwald MESG_RADIO_TX_POWER_ID, "11"
18375a994c4SMatthias Ringwald // channel number, power
18475a994c4SMatthias Ringwald };
18575a994c4SMatthias Ringwald 
18675a994c4SMatthias Ringwald const ant_cmd_t ant_channel_period = {
18775a994c4SMatthias Ringwald MESG_CHANNEL_MESG_PERIOD_ID, "12"
18875a994c4SMatthias Ringwald // channel number, period
18975a994c4SMatthias Ringwald };
19075a994c4SMatthias Ringwald 
19175a994c4SMatthias Ringwald const ant_cmd_t ant_prox_search_config = {
19275a994c4SMatthias Ringwald MESG_PROX_SEARCH_CONFIG_ID, "11"
19375a994c4SMatthias Ringwald // channel number, prox level
19475a994c4SMatthias Ringwald };
19575a994c4SMatthias Ringwald 
19675a994c4SMatthias Ringwald const ant_cmd_t ant_broadcast = {
19775a994c4SMatthias Ringwald MESG_BROADCAST_DATA_ID, "1D"
19875a994c4SMatthias Ringwald // channel number, pointer to 8 byte data
19975a994c4SMatthias Ringwald };
20075a994c4SMatthias Ringwald 
20175a994c4SMatthias Ringwald const ant_cmd_t ant_acknowledged = {
20275a994c4SMatthias Ringwald MESG_ACKNOWLEDGED_DATA_ID, "1D"
20375a994c4SMatthias Ringwald // channel number, pointer to 8 byte data
20475a994c4SMatthias Ringwald };
20575a994c4SMatthias Ringwald 
20675a994c4SMatthias Ringwald const ant_cmd_t ant_burst_packet = {
20775a994c4SMatthias Ringwald MESG_BURST_DATA_ID, "1D"
20875a994c4SMatthias Ringwald // channel number, pointer to 8 byte data
20975a994c4SMatthias Ringwald };
21075a994c4SMatthias Ringwald 
21175a994c4SMatthias Ringwald const ant_cmd_t ant_open_channel = {
21275a994c4SMatthias Ringwald MESG_OPEN_CHANNEL_ID, "1"
21375a994c4SMatthias Ringwald // channel number
21475a994c4SMatthias Ringwald };
21575a994c4SMatthias Ringwald 
21675a994c4SMatthias Ringwald const ant_cmd_t ant_close_channel = {
21775a994c4SMatthias Ringwald MESG_CLOSE_CHANNEL_ID, "1"
21875a994c4SMatthias Ringwald // channel number
21975a994c4SMatthias Ringwald };
22075a994c4SMatthias Ringwald 
22175a994c4SMatthias Ringwald const ant_cmd_t ant_request_message = {
22275a994c4SMatthias Ringwald MESG_REQUEST_ID, "11"
22375a994c4SMatthias Ringwald // channel number, requested message
22475a994c4SMatthias Ringwald };
225