1*95c72533SMatthias Ringwald /* 2*95c72533SMatthias Ringwald * Copyright (C) 2014 BlueKitchen GmbH 3*95c72533SMatthias Ringwald * 4*95c72533SMatthias Ringwald * Redistribution and use in source and binary forms, with or without 5*95c72533SMatthias Ringwald * modification, are permitted provided that the following conditions 6*95c72533SMatthias Ringwald * are met: 7*95c72533SMatthias Ringwald * 8*95c72533SMatthias Ringwald * 1. Redistributions of source code must retain the above copyright 9*95c72533SMatthias Ringwald * notice, this list of conditions and the following disclaimer. 10*95c72533SMatthias Ringwald * 2. Redistributions in binary form must reproduce the above copyright 11*95c72533SMatthias Ringwald * notice, this list of conditions and the following disclaimer in the 12*95c72533SMatthias Ringwald * documentation and/or other materials provided with the distribution. 13*95c72533SMatthias Ringwald * 3. Neither the name of the copyright holders nor the names of 14*95c72533SMatthias Ringwald * contributors may be used to endorse or promote products derived 15*95c72533SMatthias Ringwald * from this software without specific prior written permission. 16*95c72533SMatthias Ringwald * 4. Any redistribution, use, or modification is done solely for 17*95c72533SMatthias Ringwald * personal benefit and not for any commercial purpose or for 18*95c72533SMatthias Ringwald * monetary gain. 19*95c72533SMatthias Ringwald * 20*95c72533SMatthias Ringwald * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS 21*95c72533SMatthias Ringwald * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22*95c72533SMatthias Ringwald * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23*95c72533SMatthias Ringwald * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS 24*95c72533SMatthias Ringwald * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25*95c72533SMatthias Ringwald * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 26*95c72533SMatthias Ringwald * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 27*95c72533SMatthias Ringwald * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 28*95c72533SMatthias Ringwald * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29*95c72533SMatthias Ringwald * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 30*95c72533SMatthias Ringwald * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31*95c72533SMatthias Ringwald * SUCH DAMAGE. 32*95c72533SMatthias Ringwald * 33*95c72533SMatthias Ringwald * Please inquire about commercial licensing options at 34*95c72533SMatthias Ringwald * [email protected] 35*95c72533SMatthias Ringwald * 36*95c72533SMatthias Ringwald */ 37*95c72533SMatthias Ringwald 38*95c72533SMatthias Ringwald // ***************************************************************************** 39*95c72533SMatthias Ringwald // ANT + SPP Counter demo for TI CC2567 40*95c72533SMatthias Ringwald // - it provides a SPP port and and sends a counter every second 41*95c72533SMatthias Ringwald // - it also listens on ANT channel 33,1,1 42*95c72533SMatthias Ringwald // ***************************************************************************** 43*95c72533SMatthias Ringwald 44*95c72533SMatthias Ringwald #include <stdio.h> 45*95c72533SMatthias Ringwald 46*95c72533SMatthias Ringwald #include "btstack_chipset_cc256x.h" 47*95c72533SMatthias Ringwald 48*95c72533SMatthias Ringwald #include "btstack.h" 49*95c72533SMatthias Ringwald #include "ant_cmd.h" 50*95c72533SMatthias Ringwald 51*95c72533SMatthias Ringwald #define RFCOMM_SERVER_CHANNEL 1 52*95c72533SMatthias Ringwald #define HEARTBEAT_PERIOD_MS 1000 53*95c72533SMatthias Ringwald 54*95c72533SMatthias Ringwald static uint8_t rfcomm_channel_nr = 1; 55*95c72533SMatthias Ringwald static uint16_t rfcomm_channel_id = 0; 56*95c72533SMatthias Ringwald static uint8_t spp_service_buffer[100]; 57*95c72533SMatthias Ringwald static btstack_timer_source_t heartbeat; 58*95c72533SMatthias Ringwald 59*95c72533SMatthias Ringwald static btstack_packet_callback_registration_t hci_event_callback_registration; 60*95c72533SMatthias Ringwald 61*95c72533SMatthias Ringwald // ant logic 62*95c72533SMatthias Ringwald static enum { 63*95c72533SMatthias Ringwald ANT_IDLE, 64*95c72533SMatthias Ringwald ANT_SEND_RESET, 65*95c72533SMatthias Ringwald ANT_W4_RESET_COMPLETE, 66*95c72533SMatthias Ringwald ANT_SEND_ASSIGN_CHANNEL, 67*95c72533SMatthias Ringwald ANT_W4_ASSIGN_CHANNEL_COMPLETE, 68*95c72533SMatthias Ringwald ANT_SEND_SET_CHANNEL_ID, 69*95c72533SMatthias Ringwald ANT_W4_SET_CHANNEL_ID_COMPLETE, 70*95c72533SMatthias Ringwald ANT_SEND_CHANNEL_OPEN, 71*95c72533SMatthias Ringwald ANT_W4_CHANNEL_OPEN_COMPLETE, 72*95c72533SMatthias Ringwald ANT_ACTIVE 73*95c72533SMatthias Ringwald } ant_state = ANT_IDLE; 74*95c72533SMatthias Ringwald 75*95c72533SMatthias Ringwald static void ant_run(void){ 76*95c72533SMatthias Ringwald // check if ANT/HCI command can be sent 77*95c72533SMatthias Ringwald if (!hci_can_send_command_packet_now()) return; 78*95c72533SMatthias Ringwald 79*95c72533SMatthias Ringwald // send next command 80*95c72533SMatthias Ringwald switch(ant_state){ 81*95c72533SMatthias Ringwald case ANT_SEND_RESET: 82*95c72533SMatthias Ringwald ant_state = ANT_W4_RESET_COMPLETE; 83*95c72533SMatthias Ringwald // 1. reset 84*95c72533SMatthias Ringwald printf("Send ANT Reset\n"); 85*95c72533SMatthias Ringwald ant_send_cmd(&ant_reset); 86*95c72533SMatthias Ringwald break; 87*95c72533SMatthias Ringwald case ANT_SEND_ASSIGN_CHANNEL: 88*95c72533SMatthias Ringwald ant_state = ANT_W4_ASSIGN_CHANNEL_COMPLETE; 89*95c72533SMatthias Ringwald // 2. assign channel 90*95c72533SMatthias Ringwald printf("Send Assign Channel\n"); 91*95c72533SMatthias Ringwald ant_send_cmd(&ant_assign_channel, 0, 0x00, 0); 92*95c72533SMatthias Ringwald break; 93*95c72533SMatthias Ringwald case ANT_SEND_SET_CHANNEL_ID: 94*95c72533SMatthias Ringwald ant_state = ANT_W4_SET_CHANNEL_ID_COMPLETE; 95*95c72533SMatthias Ringwald // 3. set channel ID 96*95c72533SMatthias Ringwald printf("Send Set Channel ID\n"); 97*95c72533SMatthias Ringwald ant_send_cmd(&ant_channel_id, 0, 33, 1, 1); 98*95c72533SMatthias Ringwald break; 99*95c72533SMatthias Ringwald case ANT_SEND_CHANNEL_OPEN: 100*95c72533SMatthias Ringwald ant_state = ANT_W4_CHANNEL_OPEN_COMPLETE; 101*95c72533SMatthias Ringwald // 4. open channel 102*95c72533SMatthias Ringwald printf("Send Channel Open\n"); 103*95c72533SMatthias Ringwald ant_send_cmd(&ant_open_channel, 0); 104*95c72533SMatthias Ringwald break; 105*95c72533SMatthias Ringwald default: 106*95c72533SMatthias Ringwald break; 107*95c72533SMatthias Ringwald } 108*95c72533SMatthias Ringwald } 109*95c72533SMatthias Ringwald 110*95c72533SMatthias Ringwald // Bluetooth logic 111*95c72533SMatthias Ringwald static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 112*95c72533SMatthias Ringwald bd_addr_t event_addr; 113*95c72533SMatthias Ringwald uint8_t rfcomm_channel_nr; 114*95c72533SMatthias Ringwald uint16_t mtu; 115*95c72533SMatthias Ringwald 116*95c72533SMatthias Ringwald uint8_t event_code; 117*95c72533SMatthias Ringwald // uint8_t channel; 118*95c72533SMatthias Ringwald uint8_t message_id; 119*95c72533SMatthias Ringwald 120*95c72533SMatthias Ringwald switch (packet_type) { 121*95c72533SMatthias Ringwald case HCI_EVENT_PACKET: 122*95c72533SMatthias Ringwald switch (hci_event_packet_get_type(packet)) { 123*95c72533SMatthias Ringwald 124*95c72533SMatthias Ringwald case BTSTACK_EVENT_STATE: 125*95c72533SMatthias Ringwald if (btstack_event_state_get_state(packet) == HCI_STATE_WORKING){ 126*95c72533SMatthias Ringwald printf("BTstack is up and running\n"); 127*95c72533SMatthias Ringwald // start ANT init 128*95c72533SMatthias Ringwald ant_state = ANT_SEND_RESET; 129*95c72533SMatthias Ringwald } 130*95c72533SMatthias Ringwald break; 131*95c72533SMatthias Ringwald 132*95c72533SMatthias Ringwald case HCI_EVENT_PIN_CODE_REQUEST: 133*95c72533SMatthias Ringwald // inform about pin code request 134*95c72533SMatthias Ringwald printf("Pin code request - using '0000'\n\r"); 135*95c72533SMatthias Ringwald reverse_bd_addr(&packet[2], event_addr); 136*95c72533SMatthias Ringwald hci_send_cmd(&hci_pin_code_request_reply, &event_addr, 4, "0000"); 137*95c72533SMatthias Ringwald break; 138*95c72533SMatthias Ringwald 139*95c72533SMatthias Ringwald case RFCOMM_EVENT_INCOMING_CONNECTION: 140*95c72533SMatthias Ringwald // data: event (8), len(8), address(48), channel (8), rfcomm_cid (16) 141*95c72533SMatthias Ringwald rfcomm_event_incoming_connection_get_bd_addr(packet, event_addr); 142*95c72533SMatthias Ringwald rfcomm_channel_nr = rfcomm_event_incoming_connection_get_server_channel(packet); 143*95c72533SMatthias Ringwald rfcomm_channel_id = rfcomm_event_incoming_connection_get_rfcomm_cid(packet); 144*95c72533SMatthias Ringwald printf("RFCOMM channel %u requested for %s\n", rfcomm_channel_nr, bd_addr_to_str(event_addr)); 145*95c72533SMatthias Ringwald rfcomm_accept_connection(rfcomm_channel_id); 146*95c72533SMatthias Ringwald break; 147*95c72533SMatthias Ringwald 148*95c72533SMatthias Ringwald case RFCOMM_EVENT_CHANNEL_OPENED: 149*95c72533SMatthias Ringwald // data: event(8), len(8), status (8), address (48), server channel(8), rfcomm_cid(16), max frame size(16) 150*95c72533SMatthias Ringwald if (rfcomm_event_channel_opened_get_status(packet)) { 151*95c72533SMatthias Ringwald printf("RFCOMM channel open failed, status %u\n", rfcomm_event_channel_opened_get_status(packet)); 152*95c72533SMatthias Ringwald } else { 153*95c72533SMatthias Ringwald rfcomm_channel_id = rfcomm_event_channel_opened_get_rfcomm_cid(packet); 154*95c72533SMatthias Ringwald mtu = rfcomm_event_channel_opened_get_max_frame_size(packet); 155*95c72533SMatthias Ringwald printf("RFCOMM channel open succeeded. New RFCOMM Channel ID %u, max frame size %u\n", rfcomm_channel_id, mtu); 156*95c72533SMatthias Ringwald } 157*95c72533SMatthias Ringwald break; 158*95c72533SMatthias Ringwald 159*95c72533SMatthias Ringwald case RFCOMM_EVENT_CHANNEL_CLOSED: 160*95c72533SMatthias Ringwald rfcomm_channel_id = 0; 161*95c72533SMatthias Ringwald break; 162*95c72533SMatthias Ringwald 163*95c72533SMatthias Ringwald 164*95c72533SMatthias Ringwald case 0xff: // vendor specific -> ANT 165*95c72533SMatthias Ringwald 166*95c72533SMatthias Ringwald // vendor specific ant message 167*95c72533SMatthias Ringwald if (packet[2] != 0x00) break; 168*95c72533SMatthias Ringwald if (packet[3] != 0x05) break; 169*95c72533SMatthias Ringwald 170*95c72533SMatthias Ringwald event_code = packet[7]; 171*95c72533SMatthias Ringwald 172*95c72533SMatthias Ringwald printf("ANT Event: "); 173*95c72533SMatthias Ringwald printf_hexdump(packet, size); 174*95c72533SMatthias Ringwald 175*95c72533SMatthias Ringwald switch(event_code){ 176*95c72533SMatthias Ringwald 177*95c72533SMatthias Ringwald case MESG_STARTUP_MESG_ID: 178*95c72533SMatthias Ringwald ant_state = ANT_SEND_ASSIGN_CHANNEL; 179*95c72533SMatthias Ringwald break; 180*95c72533SMatthias Ringwald 181*95c72533SMatthias Ringwald case MESG_RESPONSE_EVENT_ID: 182*95c72533SMatthias Ringwald // channel = packet[8]; 183*95c72533SMatthias Ringwald message_id = packet[9]; 184*95c72533SMatthias Ringwald switch (message_id){ 185*95c72533SMatthias Ringwald case MESG_ASSIGN_CHANNEL_ID: 186*95c72533SMatthias Ringwald ant_state = ANT_SEND_SET_CHANNEL_ID; 187*95c72533SMatthias Ringwald break; 188*95c72533SMatthias Ringwald case MESG_CHANNEL_ID_ID: 189*95c72533SMatthias Ringwald ant_state = ANT_SEND_CHANNEL_OPEN; 190*95c72533SMatthias Ringwald break; 191*95c72533SMatthias Ringwald default: 192*95c72533SMatthias Ringwald break; 193*95c72533SMatthias Ringwald } 194*95c72533SMatthias Ringwald break; 195*95c72533SMatthias Ringwald default: 196*95c72533SMatthias Ringwald break; 197*95c72533SMatthias Ringwald } 198*95c72533SMatthias Ringwald break; 199*95c72533SMatthias Ringwald 200*95c72533SMatthias Ringwald default: 201*95c72533SMatthias Ringwald break; 202*95c72533SMatthias Ringwald } 203*95c72533SMatthias Ringwald break; 204*95c72533SMatthias Ringwald 205*95c72533SMatthias Ringwald default: 206*95c72533SMatthias Ringwald break; 207*95c72533SMatthias Ringwald } 208*95c72533SMatthias Ringwald 209*95c72533SMatthias Ringwald ant_run(); 210*95c72533SMatthias Ringwald } 211*95c72533SMatthias Ringwald 212*95c72533SMatthias Ringwald static void heartbeat_handler(struct btstack_timer_source *ts){ 213*95c72533SMatthias Ringwald 214*95c72533SMatthias Ringwald if (rfcomm_channel_id){ 215*95c72533SMatthias Ringwald static int counter = 0; 216*95c72533SMatthias Ringwald char lineBuffer[30]; 217*95c72533SMatthias Ringwald sprintf(lineBuffer, "BTstack counter %04u\n\r", ++counter); 218*95c72533SMatthias Ringwald puts(lineBuffer); 219*95c72533SMatthias Ringwald if (rfcomm_can_send_packet_now(rfcomm_channel_id)){ 220*95c72533SMatthias Ringwald int err = rfcomm_send(rfcomm_channel_id, (uint8_t*) lineBuffer, strlen(lineBuffer)); 221*95c72533SMatthias Ringwald if (err) { 222*95c72533SMatthias Ringwald printf("rfcomm_send -> error %d", err); 223*95c72533SMatthias Ringwald } 224*95c72533SMatthias Ringwald } 225*95c72533SMatthias Ringwald } 226*95c72533SMatthias Ringwald 227*95c72533SMatthias Ringwald btstack_run_loop_set_timer(ts, HEARTBEAT_PERIOD_MS); 228*95c72533SMatthias Ringwald btstack_run_loop_add_timer(ts); 229*95c72533SMatthias Ringwald } 230*95c72533SMatthias Ringwald 231*95c72533SMatthias Ringwald int btstack_main(int argc, const char * argv[]); 232*95c72533SMatthias Ringwald int btstack_main(int argc, const char * argv[]){ 233*95c72533SMatthias Ringwald 234*95c72533SMatthias Ringwald // register for HCI events 235*95c72533SMatthias Ringwald hci_event_callback_registration.callback = &packet_handler; 236*95c72533SMatthias Ringwald hci_add_event_handler(&hci_event_callback_registration); 237*95c72533SMatthias Ringwald 238*95c72533SMatthias Ringwald // init L2CAP 239*95c72533SMatthias Ringwald l2cap_init(); 240*95c72533SMatthias Ringwald 241*95c72533SMatthias Ringwald // init RFCOMM 242*95c72533SMatthias Ringwald rfcomm_init(); 243*95c72533SMatthias Ringwald rfcomm_register_service(packet_handler, rfcomm_channel_nr, 100); // reserved channel, mtu=100 244*95c72533SMatthias Ringwald 245*95c72533SMatthias Ringwald // init SDP, create record for SPP and register with SDP 246*95c72533SMatthias Ringwald sdp_init(); 247*95c72533SMatthias Ringwald memset(spp_service_buffer, 0, sizeof(spp_service_buffer)); 248*95c72533SMatthias Ringwald spp_create_sdp_record(spp_service_buffer, 0x10001, RFCOMM_SERVER_CHANNEL, "SPP Counter"); 249*95c72533SMatthias Ringwald sdp_register_service(spp_service_buffer); 250*95c72533SMatthias Ringwald printf("SDP service record size: %u\n", de_get_len(spp_service_buffer)); 251*95c72533SMatthias Ringwald 252*95c72533SMatthias Ringwald // set one-shot timer 253*95c72533SMatthias Ringwald heartbeat.process = &heartbeat_handler; 254*95c72533SMatthias Ringwald btstack_run_loop_set_timer(&heartbeat, HEARTBEAT_PERIOD_MS); 255*95c72533SMatthias Ringwald btstack_run_loop_add_timer(&heartbeat); 256*95c72533SMatthias Ringwald 257*95c72533SMatthias Ringwald // set local name 258*95c72533SMatthias Ringwald gap_set_local_name("BlueMSP-Demo"); 259*95c72533SMatthias Ringwald // make discoverable 260*95c72533SMatthias Ringwald gap_discoverable_control(1); 261*95c72533SMatthias Ringwald 262*95c72533SMatthias Ringwald printf("Run...\n\r"); 263*95c72533SMatthias Ringwald // turn on! 264*95c72533SMatthias Ringwald hci_power_control(HCI_POWER_ON); 265*95c72533SMatthias Ringwald return 0; 266*95c72533SMatthias Ringwald } 267*95c72533SMatthias Ringwald 268