1ebdf3c68SMilanka Ringwald /* 2ebdf3c68SMilanka Ringwald * Copyright (C) 2014 BlueKitchen GmbH 3ebdf3c68SMilanka Ringwald * 4ebdf3c68SMilanka Ringwald * Redistribution and use in source and binary forms, with or without 5ebdf3c68SMilanka Ringwald * modification, are permitted provided that the following conditions 6ebdf3c68SMilanka Ringwald * are met: 7ebdf3c68SMilanka Ringwald * 8ebdf3c68SMilanka Ringwald * 1. Redistributions of source code must retain the above copyright 9ebdf3c68SMilanka Ringwald * notice, this list of conditions and the following disclaimer. 10ebdf3c68SMilanka Ringwald * 2. Redistributions in binary form must reproduce the above copyright 11ebdf3c68SMilanka Ringwald * notice, this list of conditions and the following disclaimer in the 12ebdf3c68SMilanka Ringwald * documentation and/or other materials provided with the distribution. 13ebdf3c68SMilanka Ringwald * 3. Neither the name of the copyright holders nor the names of 14ebdf3c68SMilanka Ringwald * contributors may be used to endorse or promote products derived 15ebdf3c68SMilanka Ringwald * from this software without specific prior written permission. 16ebdf3c68SMilanka Ringwald * 4. Any redistribution, use, or modification is done solely for 17ebdf3c68SMilanka Ringwald * personal benefit and not for any commercial purpose or for 18ebdf3c68SMilanka Ringwald * monetary gain. 19ebdf3c68SMilanka Ringwald * 20ebdf3c68SMilanka Ringwald * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS 21ebdf3c68SMilanka Ringwald * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22ebdf3c68SMilanka Ringwald * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23ebdf3c68SMilanka Ringwald * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS 24ebdf3c68SMilanka Ringwald * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25ebdf3c68SMilanka Ringwald * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 26ebdf3c68SMilanka Ringwald * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 27ebdf3c68SMilanka Ringwald * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 28ebdf3c68SMilanka Ringwald * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29ebdf3c68SMilanka Ringwald * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 30ebdf3c68SMilanka Ringwald * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31ebdf3c68SMilanka Ringwald * SUCH DAMAGE. 32ebdf3c68SMilanka Ringwald * 33ebdf3c68SMilanka Ringwald * Please inquire about commercial licensing options at 34ebdf3c68SMilanka Ringwald * [email protected] 35ebdf3c68SMilanka Ringwald * 36ebdf3c68SMilanka Ringwald */ 37ebdf3c68SMilanka Ringwald 38e501bae0SMatthias Ringwald #define BTSTACK_FILE__ "nordic_spp_le_counter.c" 39ebdf3c68SMilanka Ringwald 40ebdf3c68SMilanka Ringwald // ***************************************************************************** 41ec8ae085SMilanka Ringwald /* EXAMPLE_START(nordic_le_counter): LE Nordic SPP-like Heartbeat Server 42ebdf3c68SMilanka Ringwald * 43ebdf3c68SMilanka Ringwald */ 44ebdf3c68SMilanka Ringwald // ***************************************************************************** 45ebdf3c68SMilanka Ringwald 46ebdf3c68SMilanka Ringwald #include <stdint.h> 47ebdf3c68SMilanka Ringwald #include <stdio.h> 48ebdf3c68SMilanka Ringwald #include <stdlib.h> 49ebdf3c68SMilanka Ringwald #include <string.h> 50ebdf3c68SMilanka Ringwald 51ebdf3c68SMilanka Ringwald #include "btstack.h" 52ebdf3c68SMilanka Ringwald #include "ble/gatt-service/nordic_spp_service_server.h" 53ebdf3c68SMilanka Ringwald 54a63a688aSMatthias Ringwald // nordic_spp_le_counter.gatt contains the declaration of the provided GATT Services + Characteristics 55a63a688aSMatthias Ringwald // nordic_spp_le_counter.h contains the binary representation of nordic_spp_le_counter.gatt 56a63a688aSMatthias Ringwald // it is generated by the build system by calling: $BTSTACK_ROOT/tool/compile_gatt.py nordic_spp_le_counter.gatt nordic_spp_le_counter.h 57a63a688aSMatthias Ringwald // it needs to be regenerated when the GATT Database declared in nordic_spp_le_counter.gatt file is modified 58a63a688aSMatthias Ringwald #include "nordic_spp_le_counter.h" 59a63a688aSMatthias Ringwald 60a63a688aSMatthias Ringwald 61ebdf3c68SMilanka Ringwald #define HEARTBEAT_PERIOD_MS 1000 62ebdf3c68SMilanka Ringwald 63ebdf3c68SMilanka Ringwald /* @section Main Application Setup 64ebdf3c68SMilanka Ringwald * 65ebdf3c68SMilanka Ringwald * @text Listing MainConfiguration shows main application code. 66ebdf3c68SMilanka Ringwald * It initializes L2CAP, the Security Manager and configures the ATT Server with the pre-compiled 67ebdf3c68SMilanka Ringwald * ATT Database generated from $nordic_le_counter.gatt$. 68ebdf3c68SMilanka Ringwald * Additionally, it enables the Battery Service Server with the current battery level. 69ebdf3c68SMilanka Ringwald * Finally, it configures the advertisements 70ebdf3c68SMilanka Ringwald * and the heartbeat handler and boots the Bluetooth stack. 71ebdf3c68SMilanka Ringwald * In this example, the Advertisement contains the Flags attribute and the device name. 72ebdf3c68SMilanka Ringwald * The flag 0x06 indicates: LE General Discoverable Mode and BR/EDR not supported. 73ebdf3c68SMilanka Ringwald */ 74ebdf3c68SMilanka Ringwald 75ebdf3c68SMilanka Ringwald /* LISTING_START(MainConfiguration): Init L2CAP SM ATT Server and start heartbeat timer */ 76ebdf3c68SMilanka Ringwald static btstack_timer_source_t heartbeat; 77ebdf3c68SMilanka Ringwald static hci_con_handle_t con_handle = HCI_CON_HANDLE_INVALID; 78ebdf3c68SMilanka Ringwald static btstack_context_callback_registration_t send_request; 79ebdf3c68SMilanka Ringwald static btstack_packet_callback_registration_t hci_event_callback_registration; 80ebdf3c68SMilanka Ringwald 81ebdf3c68SMilanka Ringwald const uint8_t adv_data[] = { 82ebdf3c68SMilanka Ringwald // Flags general discoverable, BR/EDR not supported 83ebdf3c68SMilanka Ringwald 2, BLUETOOTH_DATA_TYPE_FLAGS, 0x06, 84ebdf3c68SMilanka Ringwald // Name 85ba7944beSMilanka Ringwald 8, BLUETOOTH_DATA_TYPE_COMPLETE_LOCAL_NAME, 'n', 'R', 'F',' ', 'S', 'P', 'P', 86ebdf3c68SMilanka Ringwald // UUID ... 874163d2ebSMilanka Ringwald 17, BLUETOOTH_DATA_TYPE_COMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS, 0x9e, 0xca, 0xdc, 0x24, 0xe, 0xe5, 0xa9, 0xe0, 0x93, 0xf3, 0xa3, 0xb5, 0x1, 0x0, 0x40, 0x6e, 88ebdf3c68SMilanka Ringwald }; 89ebdf3c68SMilanka Ringwald const uint8_t adv_data_len = sizeof(adv_data); 90ebdf3c68SMilanka Ringwald 91ebdf3c68SMilanka Ringwald /* LISTING_END */ 92ebdf3c68SMilanka Ringwald 93ebdf3c68SMilanka Ringwald /* 94ebdf3c68SMilanka Ringwald * @section Heartbeat Handler 95ebdf3c68SMilanka Ringwald * 96ebdf3c68SMilanka Ringwald * @text The heartbeat handler updates the value of the single Characteristic provided in this example, 97ebdf3c68SMilanka Ringwald * and request a ATT_EVENT_CAN_SEND_NOW to send a notification if enabled see Listing heartbeat. 98ebdf3c68SMilanka Ringwald */ 99ebdf3c68SMilanka Ringwald 100ebdf3c68SMilanka Ringwald /* LISTING_START(heartbeat): Hearbeat Handler */ 101ebdf3c68SMilanka Ringwald static int counter = 0; 102ebdf3c68SMilanka Ringwald static char counter_string[30]; 103ebdf3c68SMilanka Ringwald static int counter_string_len; 104ebdf3c68SMilanka Ringwald 105ebdf3c68SMilanka Ringwald static void beat(void){ 106ebdf3c68SMilanka Ringwald counter++; 107ebdf3c68SMilanka Ringwald counter_string_len = sprintf(counter_string, "BTstack counter %03u", counter); 108ebdf3c68SMilanka Ringwald } 109ebdf3c68SMilanka Ringwald 110ebdf3c68SMilanka Ringwald static void nordic_can_send(void * context){ 111ebdf3c68SMilanka Ringwald UNUSED(context); 112ebdf3c68SMilanka Ringwald printf("SEND: %s\n", counter_string); 113ebdf3c68SMilanka Ringwald nordic_spp_service_server_send(con_handle, (uint8_t*) counter_string, counter_string_len); 114ebdf3c68SMilanka Ringwald } 115ebdf3c68SMilanka Ringwald 116ebdf3c68SMilanka Ringwald static void heartbeat_handler(struct btstack_timer_source *ts){ 117ebdf3c68SMilanka Ringwald if (con_handle != HCI_CON_HANDLE_INVALID) { 118ebdf3c68SMilanka Ringwald beat(); 119ebdf3c68SMilanka Ringwald send_request.callback = &nordic_can_send; 120ebdf3c68SMilanka Ringwald nordic_spp_service_server_request_can_send_now(&send_request, con_handle); 121ebdf3c68SMilanka Ringwald } 122ebdf3c68SMilanka Ringwald btstack_run_loop_set_timer(ts, HEARTBEAT_PERIOD_MS); 123ebdf3c68SMilanka Ringwald btstack_run_loop_add_timer(ts); 124ebdf3c68SMilanka Ringwald } 125ebdf3c68SMilanka Ringwald /* LISTING_END */ 126ebdf3c68SMilanka Ringwald 127257f2b00SMatthias Ringwald static void nordic_spp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 128*6058cb0dSMatthias Ringwald UNUSED(channel); 129257f2b00SMatthias Ringwald switch (packet_type){ 130257f2b00SMatthias Ringwald case HCI_EVENT_PACKET: 131257f2b00SMatthias Ringwald if (hci_event_packet_get_type(packet) != HCI_EVENT_GATTSERVICE_META) break; 132257f2b00SMatthias Ringwald switch (hci_event_gattservice_meta_get_subevent_code(packet)){ 133257f2b00SMatthias Ringwald case GATTSERVICE_SUBEVENT_SPP_SERVICE_CONNECTED: 134257f2b00SMatthias Ringwald con_handle = gattservice_subevent_spp_service_connected_get_con_handle(packet); 135ebdf3c68SMilanka Ringwald printf("Connected with handle 0x%04x\n", con_handle); 136257f2b00SMatthias Ringwald break; 137257f2b00SMatthias Ringwald case GATTSERVICE_SUBEVENT_SPP_SERVICE_DISCONNECTED: 138257f2b00SMatthias Ringwald con_handle = HCI_CON_HANDLE_INVALID; 139257f2b00SMatthias Ringwald break; 140257f2b00SMatthias Ringwald default: 141257f2b00SMatthias Ringwald break; 142257f2b00SMatthias Ringwald } 143257f2b00SMatthias Ringwald break; 144257f2b00SMatthias Ringwald case RFCOMM_DATA_PACKET: 145ebdf3c68SMilanka Ringwald printf("RECV: "); 146257f2b00SMatthias Ringwald printf_hexdump(packet, size); 147257f2b00SMatthias Ringwald break; 148257f2b00SMatthias Ringwald default: 149257f2b00SMatthias Ringwald break; 150ebdf3c68SMilanka Ringwald } 151ebdf3c68SMilanka Ringwald } 152ebdf3c68SMilanka Ringwald 153ebdf3c68SMilanka Ringwald /* 154ebdf3c68SMilanka Ringwald * @section Packet Handler 155ebdf3c68SMilanka Ringwald * 156ebdf3c68SMilanka Ringwald * @text The packet handler is used to: 157ebdf3c68SMilanka Ringwald * - stop the counter after a disconnect 158ebdf3c68SMilanka Ringwald */ 159ebdf3c68SMilanka Ringwald 160ebdf3c68SMilanka Ringwald /* LISTING_START(packetHandler): Packet Handler */ 161257f2b00SMatthias Ringwald static void hci_packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 162ebdf3c68SMilanka Ringwald UNUSED(channel); 163ebdf3c68SMilanka Ringwald UNUSED(size); 164ebdf3c68SMilanka Ringwald 1657bbeb3adSMilanka Ringwald if (packet_type != HCI_EVENT_PACKET) return; 1667bbeb3adSMilanka Ringwald 167ebdf3c68SMilanka Ringwald switch (hci_event_packet_get_type(packet)) { 168ebdf3c68SMilanka Ringwald case HCI_EVENT_DISCONNECTION_COMPLETE: 169ebdf3c68SMilanka Ringwald con_handle = HCI_CON_HANDLE_INVALID; 170ebdf3c68SMilanka Ringwald break; 171ebdf3c68SMilanka Ringwald default: 172ebdf3c68SMilanka Ringwald break; 173ebdf3c68SMilanka Ringwald } 174ebdf3c68SMilanka Ringwald } 175ebdf3c68SMilanka Ringwald /* LISTING_END */ 176ebdf3c68SMilanka Ringwald 177ebdf3c68SMilanka Ringwald 178ebdf3c68SMilanka Ringwald int btstack_main(void); 179ebdf3c68SMilanka Ringwald int btstack_main(void) 180ebdf3c68SMilanka Ringwald { 181ebdf3c68SMilanka Ringwald // register for HCI events 182257f2b00SMatthias Ringwald hci_event_callback_registration.callback = &hci_packet_handler; 183ebdf3c68SMilanka Ringwald hci_add_event_handler(&hci_event_callback_registration); 184ebdf3c68SMilanka Ringwald 185ebdf3c68SMilanka Ringwald l2cap_init(); 186ebdf3c68SMilanka Ringwald 187ebdf3c68SMilanka Ringwald // setup LE device DB 188ebdf3c68SMilanka Ringwald le_device_db_init(); 189ebdf3c68SMilanka Ringwald 190ebdf3c68SMilanka Ringwald // setup SM: Display only 191ebdf3c68SMilanka Ringwald sm_init(); 192ebdf3c68SMilanka Ringwald 193ebdf3c68SMilanka Ringwald // setup ATT server 194ebdf3c68SMilanka Ringwald att_server_init(profile_data, NULL, NULL); 195ebdf3c68SMilanka Ringwald 196ebdf3c68SMilanka Ringwald // setup Nordic SPP service 197257f2b00SMatthias Ringwald nordic_spp_service_server_init(&nordic_spp_packet_handler); 198ebdf3c68SMilanka Ringwald 199ebdf3c68SMilanka Ringwald // setup advertisements 200ebdf3c68SMilanka Ringwald uint16_t adv_int_min = 0x0030; 201ebdf3c68SMilanka Ringwald uint16_t adv_int_max = 0x0030; 202ebdf3c68SMilanka Ringwald uint8_t adv_type = 0; 203ebdf3c68SMilanka Ringwald bd_addr_t null_addr; 204ebdf3c68SMilanka Ringwald memset(null_addr, 0, 6); 205ebdf3c68SMilanka Ringwald gap_advertisements_set_params(adv_int_min, adv_int_max, adv_type, 0, null_addr, 0x07, 0x00); 206ebdf3c68SMilanka Ringwald gap_advertisements_set_data(adv_data_len, (uint8_t*) adv_data); 207ebdf3c68SMilanka Ringwald gap_advertisements_enable(1); 208ebdf3c68SMilanka Ringwald 209ebdf3c68SMilanka Ringwald // set one-shot timer 210ebdf3c68SMilanka Ringwald heartbeat.process = &heartbeat_handler; 211ebdf3c68SMilanka Ringwald btstack_run_loop_set_timer(&heartbeat, HEARTBEAT_PERIOD_MS); 212ebdf3c68SMilanka Ringwald btstack_run_loop_add_timer(&heartbeat); 213ebdf3c68SMilanka Ringwald 214ebdf3c68SMilanka Ringwald // beat once 215ebdf3c68SMilanka Ringwald beat(); 216ebdf3c68SMilanka Ringwald 217ebdf3c68SMilanka Ringwald // turn on! 218ebdf3c68SMilanka Ringwald hci_power_control(HCI_POWER_ON); 219ebdf3c68SMilanka Ringwald 220ebdf3c68SMilanka Ringwald return 0; 221ebdf3c68SMilanka Ringwald } 222ebdf3c68SMilanka Ringwald /* EXAMPLE_END */ 223