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