1cf862b36SMatthias Ringwald /* 2cf862b36SMatthias Ringwald * Copyright (C) 2019 BlueKitchen GmbH 3cf862b36SMatthias Ringwald * 4cf862b36SMatthias Ringwald * Redistribution and use in source and binary forms, with or without 5cf862b36SMatthias Ringwald * modification, are permitted provided that the following conditions 6cf862b36SMatthias Ringwald * are met: 7cf862b36SMatthias Ringwald * 8cf862b36SMatthias Ringwald * 1. Redistributions of source code must retain the above copyright 9cf862b36SMatthias Ringwald * notice, this list of conditions and the following disclaimer. 10cf862b36SMatthias Ringwald * 2. Redistributions in binary form must reproduce the above copyright 11cf862b36SMatthias Ringwald * notice, this list of conditions and the following disclaimer in the 12cf862b36SMatthias Ringwald * documentation and/or other materials provided with the distribution. 13cf862b36SMatthias Ringwald * 3. Neither the name of the copyright holders nor the names of 14cf862b36SMatthias Ringwald * contributors may be used to endorse or promote products derived 15cf862b36SMatthias Ringwald * from this software without specific prior written permission. 16cf862b36SMatthias Ringwald * 4. Any redistribution, use, or modification is done solely for 17cf862b36SMatthias Ringwald * personal benefit and not for any commercial purpose or for 18cf862b36SMatthias Ringwald * monetary gain. 19cf862b36SMatthias Ringwald * 20cf862b36SMatthias Ringwald * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS 21cf862b36SMatthias Ringwald * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22cf862b36SMatthias Ringwald * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23*2fca4dadSMilanka Ringwald * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN 24*2fca4dadSMilanka Ringwald * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25cf862b36SMatthias Ringwald * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 26cf862b36SMatthias Ringwald * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 27cf862b36SMatthias Ringwald * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 28cf862b36SMatthias Ringwald * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29cf862b36SMatthias Ringwald * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 30cf862b36SMatthias Ringwald * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31cf862b36SMatthias Ringwald * SUCH DAMAGE. 32cf862b36SMatthias Ringwald * 33cf862b36SMatthias Ringwald * Please inquire about commercial licensing options at 34cf862b36SMatthias Ringwald * [email protected] 35cf862b36SMatthias Ringwald * 36cf862b36SMatthias Ringwald */ 37cf862b36SMatthias Ringwald 38cf862b36SMatthias Ringwald /** 39cf862b36SMatthias Ringwald * Basic Mesh Node demo 40cf862b36SMatthias Ringwald */ 41cf862b36SMatthias Ringwald 42cf862b36SMatthias Ringwald #define __BTSTACK_FILE__ "mesh_node_demo.c" 43cf862b36SMatthias Ringwald 44cf862b36SMatthias Ringwald #include <stdint.h> 45cf862b36SMatthias Ringwald #include <stdio.h> 46cf862b36SMatthias Ringwald #include <stdlib.h> 47cf862b36SMatthias Ringwald #include <string.h> 48cf862b36SMatthias Ringwald 49cf862b36SMatthias Ringwald #include "btstack.h" 50cf862b36SMatthias Ringwald #include "mesh_node_demo.h" 51cf862b36SMatthias Ringwald 52cf862b36SMatthias Ringwald // general 53cf862b36SMatthias Ringwald #define MESH_BLUEKITCHEN_MODEL_ID_TEST_SERVER 0x0000u 54cf862b36SMatthias Ringwald 55cf862b36SMatthias Ringwald static mesh_model_t mesh_vendor_model; 56cf862b36SMatthias Ringwald 57cf862b36SMatthias Ringwald static mesh_model_t mesh_generic_on_off_server_model; 58cf862b36SMatthias Ringwald static mesh_generic_on_off_state_t mesh_generic_on_off_state; 59cf862b36SMatthias Ringwald 60f2229d0eSMatthias Ringwald static char gap_name_buffer[30]; 61f2229d0eSMatthias Ringwald static char gap_name_prefix[] = "Mesh "; 62f2229d0eSMatthias Ringwald 63f2229d0eSMatthias Ringwald static btstack_packet_callback_registration_t hci_event_callback_registration; 64f2229d0eSMatthias Ringwald 655127fa8aSMatthias Ringwald #ifdef ENABLE_MESH_GATT_BEARER 66f2229d0eSMatthias Ringwald static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 67f2229d0eSMatthias Ringwald UNUSED(channel); 68f2229d0eSMatthias Ringwald UNUSED(size); 697bbeb3adSMilanka Ringwald 707bbeb3adSMilanka Ringwald if (packet_type != HCI_EVENT_PACKET) return; 717bbeb3adSMilanka Ringwald 72f2229d0eSMatthias Ringwald bd_addr_t addr; 737bbeb3adSMilanka Ringwald 74f2229d0eSMatthias Ringwald switch (hci_event_packet_get_type(packet)) { 75f2229d0eSMatthias Ringwald case BTSTACK_EVENT_STATE: 76f2229d0eSMatthias Ringwald if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING) break; 77f2229d0eSMatthias Ringwald // setup gap name 78f2229d0eSMatthias Ringwald gap_local_bd_addr(addr); 79f2229d0eSMatthias Ringwald strcpy(gap_name_buffer, gap_name_prefix); 80f2229d0eSMatthias Ringwald strcat(gap_name_buffer, bd_addr_to_str(addr)); 81f2229d0eSMatthias Ringwald break; 82f2229d0eSMatthias Ringwald default: 83f2229d0eSMatthias Ringwald break; 84f2229d0eSMatthias Ringwald } 85f2229d0eSMatthias Ringwald } 86f2229d0eSMatthias Ringwald 87f2229d0eSMatthias Ringwald static uint16_t att_read_callback(hci_con_handle_t connection_handle, uint16_t att_handle, uint16_t offset, uint8_t * buffer, uint16_t buffer_size){ 88f2229d0eSMatthias Ringwald UNUSED(connection_handle); 89f2229d0eSMatthias Ringwald if (att_handle == ATT_CHARACTERISTIC_GAP_DEVICE_NAME_01_VALUE_HANDLE){ 90f2229d0eSMatthias Ringwald return att_read_callback_handle_blob((const uint8_t *)gap_name_buffer, strlen(gap_name_buffer), offset, buffer, buffer_size); 91f2229d0eSMatthias Ringwald } 92f2229d0eSMatthias Ringwald return 0; 93f2229d0eSMatthias Ringwald } 945127fa8aSMatthias Ringwald #endif 95cf862b36SMatthias Ringwald 96cf862b36SMatthias Ringwald static void mesh_provisioning_message_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 97cf862b36SMatthias Ringwald UNUSED(packet_type); 98cf862b36SMatthias Ringwald UNUSED(channel); 99cf862b36SMatthias Ringwald UNUSED(size); 100cf862b36SMatthias Ringwald 101cf862b36SMatthias Ringwald if (packet_type != HCI_EVENT_PACKET) return; 102cf862b36SMatthias Ringwald 103cf862b36SMatthias Ringwald switch(packet[0]){ 104cf862b36SMatthias Ringwald case HCI_EVENT_MESH_META: 105cf862b36SMatthias Ringwald switch(packet[2]){ 106cf862b36SMatthias Ringwald case MESH_SUBEVENT_PB_TRANSPORT_LINK_OPEN: 107cf862b36SMatthias Ringwald printf("Provisioner link opened"); 108cf862b36SMatthias Ringwald break; 1090728b042SMatthias Ringwald case MESH_SUBEVENT_ATTENTION_TIMER: 1100728b042SMatthias Ringwald printf("Attention Timer: %u\n", mesh_subevent_attention_timer_get_attention_time(packet)); 1110728b042SMatthias Ringwald break; 112cf862b36SMatthias Ringwald case MESH_SUBEVENT_PB_TRANSPORT_LINK_CLOSED: 113cf862b36SMatthias Ringwald printf("Provisioner link close"); 114cf862b36SMatthias Ringwald break; 115cf862b36SMatthias Ringwald case MESH_SUBEVENT_PB_PROV_COMPLETE: 116cf862b36SMatthias Ringwald printf("Provisioning complete\n"); 117cf862b36SMatthias Ringwald break; 118cf862b36SMatthias Ringwald default: 119cf862b36SMatthias Ringwald break; 120cf862b36SMatthias Ringwald } 121cf862b36SMatthias Ringwald break; 122cf862b36SMatthias Ringwald default: 123cf862b36SMatthias Ringwald break; 124cf862b36SMatthias Ringwald } 125cf862b36SMatthias Ringwald } 126cf862b36SMatthias Ringwald 127cf862b36SMatthias Ringwald static void mesh_state_update_message_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 128cf862b36SMatthias Ringwald UNUSED(channel); 129cf862b36SMatthias Ringwald UNUSED(size); 130cf862b36SMatthias Ringwald 131cf862b36SMatthias Ringwald if (packet_type != HCI_EVENT_PACKET) return; 132cf862b36SMatthias Ringwald 133cf862b36SMatthias Ringwald switch(packet[0]){ 134cf862b36SMatthias Ringwald case HCI_EVENT_MESH_META: 135cf862b36SMatthias Ringwald switch(packet[2]){ 136cf862b36SMatthias Ringwald case MESH_SUBEVENT_STATE_UPDATE_BOOL: 137cf862b36SMatthias Ringwald printf("State update: model identifier 0x%08x, state identifier 0x%08x, reason %u, state %u\n", 138cf862b36SMatthias Ringwald mesh_subevent_state_update_bool_get_model_identifier(packet), 139cf862b36SMatthias Ringwald mesh_subevent_state_update_bool_get_state_identifier(packet), 140cf862b36SMatthias Ringwald mesh_subevent_state_update_bool_get_reason(packet), 141cf862b36SMatthias Ringwald mesh_subevent_state_update_bool_get_value(packet)); 142cf862b36SMatthias Ringwald break; 143cf862b36SMatthias Ringwald default: 144cf862b36SMatthias Ringwald break; 145cf862b36SMatthias Ringwald } 146cf862b36SMatthias Ringwald break; 147cf862b36SMatthias Ringwald default: 148cf862b36SMatthias Ringwald break; 149cf862b36SMatthias Ringwald } 150cf862b36SMatthias Ringwald } 151cf862b36SMatthias Ringwald 152cf862b36SMatthias Ringwald static void show_usage(void){ 153cf862b36SMatthias Ringwald bd_addr_t iut_address; 154cf862b36SMatthias Ringwald gap_local_bd_addr(iut_address); 155cf862b36SMatthias Ringwald printf("\n--- Bluetooth Mesh Console at %s ---\n", bd_addr_to_str(iut_address)); 156cf862b36SMatthias Ringwald printf("8 - Delete provisioning data\n"); 157cf862b36SMatthias Ringwald printf("g - Generic ON/OFF Server Toggle Value\n"); 158cf862b36SMatthias Ringwald printf("\n"); 159cf862b36SMatthias Ringwald } 160cf862b36SMatthias Ringwald 161cf862b36SMatthias Ringwald static void stdin_process(char cmd){ 162cf862b36SMatthias Ringwald switch (cmd){ 163cf862b36SMatthias Ringwald case '8': 164cf862b36SMatthias Ringwald mesh_node_reset(); 165cf862b36SMatthias Ringwald printf("Mesh Node Reset!\n"); 166cf862b36SMatthias Ringwald mesh_proxy_start_advertising_unprovisioned_device(); 167cf862b36SMatthias Ringwald break; 168cf862b36SMatthias Ringwald case 'g': 169cf862b36SMatthias Ringwald printf("Generic ON/OFF Server Toggle Value\n"); 170cf862b36SMatthias Ringwald mesh_generic_on_off_server_set(&mesh_generic_on_off_server_model, 1-mesh_generic_on_off_server_get(&mesh_generic_on_off_server_model), 0, 0); 171cf862b36SMatthias Ringwald break; 172cf862b36SMatthias Ringwald case ' ': 173cf862b36SMatthias Ringwald show_usage(); 174cf862b36SMatthias Ringwald break; 175cf862b36SMatthias Ringwald default: 176cf862b36SMatthias Ringwald printf("Command: '%c' not implemented\n", cmd); 177cf862b36SMatthias Ringwald show_usage(); 178cf862b36SMatthias Ringwald break; 179cf862b36SMatthias Ringwald } 180cf862b36SMatthias Ringwald } 181cf862b36SMatthias Ringwald 182cf862b36SMatthias Ringwald int btstack_main(void); 183cf862b36SMatthias Ringwald int btstack_main(void) 184cf862b36SMatthias Ringwald { 1855127fa8aSMatthias Ringwald #ifdef HAVE_BTSTACK_STDIN 186cf862b36SMatthias Ringwald // console 187cf862b36SMatthias Ringwald btstack_stdin_setup(stdin_process); 1885127fa8aSMatthias Ringwald #endif 189cf862b36SMatthias Ringwald 190cf862b36SMatthias Ringwald // crypto 191cf862b36SMatthias Ringwald btstack_crypto_init(); 192cf862b36SMatthias Ringwald 19388dd0c2fSMatthias Ringwald #ifdef ENABLE_MESH_GATT_BEARER 194cf862b36SMatthias Ringwald // l2cap 195cf862b36SMatthias Ringwald l2cap_init(); 196cf862b36SMatthias Ringwald 197cf862b36SMatthias Ringwald // setup le device db 198cf862b36SMatthias Ringwald le_device_db_init(); 199cf862b36SMatthias Ringwald 200cf862b36SMatthias Ringwald // setup ATT server 201f2229d0eSMatthias Ringwald att_server_init(profile_data, &att_read_callback, NULL); 202cf862b36SMatthias Ringwald 203cf862b36SMatthias Ringwald // 204cf862b36SMatthias Ringwald sm_init(); 2055127fa8aSMatthias Ringwald #endif 206cf862b36SMatthias Ringwald 2075127fa8aSMatthias Ringwald #ifdef ENABLE_MESH_GATT_BEARER 208f2229d0eSMatthias Ringwald // register for HCI events 209f2229d0eSMatthias Ringwald hci_event_callback_registration.callback = &packet_handler; 210f2229d0eSMatthias Ringwald hci_add_event_handler(&hci_event_callback_registration); 2115127fa8aSMatthias Ringwald #endif 212cf862b36SMatthias Ringwald 213cf862b36SMatthias Ringwald // mesh 214cf862b36SMatthias Ringwald mesh_init(); 215cf862b36SMatthias Ringwald 21688dd0c2fSMatthias Ringwald #ifdef ENABLE_MESH_GATT_BEARER 217cf862b36SMatthias Ringwald // setup connectable advertisments 218cf862b36SMatthias Ringwald bd_addr_t null_addr; 219cf862b36SMatthias Ringwald memset(null_addr, 0, 6); 220cf862b36SMatthias Ringwald uint8_t adv_type = 0; // AFV_IND 221cf862b36SMatthias Ringwald uint16_t adv_int_min = 0x0030; 222cf862b36SMatthias Ringwald uint16_t adv_int_max = 0x0030; 223cf862b36SMatthias Ringwald adv_bearer_advertisements_set_params(adv_int_min, adv_int_max, adv_type, 0, null_addr, 0x07, 0x00); 2245127fa8aSMatthias Ringwald #endif 225cf862b36SMatthias Ringwald 226cf862b36SMatthias Ringwald // Track Provisioning as device role 227cf862b36SMatthias Ringwald mesh_register_provisioning_device_packet_handler(&mesh_provisioning_message_handler); 228cf862b36SMatthias Ringwald 229cf862b36SMatthias Ringwald // Loc - bottom - https://www.bluetooth.com/specifications/assigned-numbers/gatt-namespace-descriptors 230cf862b36SMatthias Ringwald mesh_node_set_element_location(mesh_node_get_primary_element(), 0x103); 231cf862b36SMatthias Ringwald 232cf862b36SMatthias Ringwald // Setup Generic On/Off model 233cf862b36SMatthias Ringwald mesh_generic_on_off_server_model.model_identifier = mesh_model_get_model_identifier_bluetooth_sig(MESH_SIG_MODEL_ID_GENERIC_ON_OFF_SERVER); 234cf862b36SMatthias Ringwald mesh_generic_on_off_server_model.operations = mesh_generic_on_off_server_get_operations(); 235cf862b36SMatthias Ringwald mesh_generic_on_off_server_model.model_data = (void *) &mesh_generic_on_off_state; 236cf862b36SMatthias Ringwald mesh_generic_on_off_server_register_packet_handler(&mesh_generic_on_off_server_model, &mesh_state_update_message_handler); 237cf862b36SMatthias Ringwald mesh_element_add_model(mesh_node_get_primary_element(), &mesh_generic_on_off_server_model); 238cf862b36SMatthias Ringwald 239cf862b36SMatthias Ringwald // Setup our custom model 240cf862b36SMatthias Ringwald mesh_vendor_model.model_identifier = mesh_model_get_model_identifier(BLUETOOTH_COMPANY_ID_BLUEKITCHEN_GMBH, MESH_BLUEKITCHEN_MODEL_ID_TEST_SERVER); 241cf862b36SMatthias Ringwald mesh_element_add_model(mesh_node_get_primary_element(), &mesh_vendor_model); 242cf862b36SMatthias Ringwald 243cf862b36SMatthias Ringwald // Enable Output OOB 244cf862b36SMatthias Ringwald provisioning_device_set_output_oob_actions(0x08, 0x08); 245cf862b36SMatthias Ringwald 246cf862b36SMatthias Ringwald // Enable PROXY 247cf862b36SMatthias Ringwald mesh_foundation_gatt_proxy_set(1); 248cf862b36SMatthias Ringwald 249cf862b36SMatthias Ringwald #if defined(ENABLE_MESH_ADV_BEARER) 250cf862b36SMatthias Ringwald // setup scanning when supporting ADV Bearer 251cf862b36SMatthias Ringwald gap_set_scan_parameters(0, 0x300, 0x300); 252cf862b36SMatthias Ringwald gap_start_scan(); 253cf862b36SMatthias Ringwald #endif 254cf862b36SMatthias Ringwald 255cf862b36SMatthias Ringwald // turn on! 256cf862b36SMatthias Ringwald hci_power_control(HCI_POWER_ON); 257cf862b36SMatthias Ringwald 258cf862b36SMatthias Ringwald return 0; 259cf862b36SMatthias Ringwald } 260cf862b36SMatthias Ringwald /* EXAMPLE_END */ 261