1 /* 2 * Copyright (C) 2019 BlueKitchen GmbH 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of the copyright holders nor the names of 14 * contributors may be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * 4. Any redistribution, use, or modification is done solely for 17 * personal benefit and not for any commercial purpose or for 18 * monetary gain. 19 * 20 * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS 24 * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 27 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 28 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 30 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * Please inquire about commercial licensing options at 34 * [email protected] 35 * 36 */ 37 38 #define __BTSTACK_FILE__ "mesh.c" 39 40 #include <string.h> 41 #include <stdio.h> 42 43 #include "mesh/mesh.h" 44 45 #include "btstack_util.h" 46 #include "btstack_config.h" 47 #include "btstack_event.h" 48 49 #include "mesh/adv_bearer.h" 50 #include "mesh/beacon.h" 51 #include "mesh/gatt_bearer.h" 52 #include "mesh/mesh_access.h" 53 #include "mesh/mesh_configuration_server.h" 54 #include "mesh/mesh_foundation.h" 55 #include "mesh/mesh_generic_model.h" 56 #include "mesh/mesh_generic_server.h" 57 #include "mesh/mesh_iv_index_seq_number.h" 58 #include "mesh/mesh_lower_transport.h" 59 #include "mesh/mesh_peer.h" 60 #include "mesh/mesh_proxy.h" 61 #include "mesh/mesh_upper_transport.h" 62 #include "mesh/mesh_virtual_addresses.h" 63 #include "mesh/pb_adv.h" 64 #include "mesh/pb_gatt.h" 65 #include "mesh/provisioning.h" 66 #include "mesh/provisioning_device.h" 67 68 static btstack_packet_handler_t provisioning_device_packet_handler; 69 static btstack_packet_callback_registration_t hci_event_callback_registration; 70 static int provisioned; 71 72 static void mesh_provisioning_message_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 73 mesh_provisioning_data_t provisioning_data; 74 75 switch(packet[0]){ 76 case HCI_EVENT_MESH_META: 77 switch(packet[2]){ 78 case MESH_SUBEVENT_PB_PROV_COMPLETE: 79 // get provisioning data 80 provisioning_device_data_get(&provisioning_data); 81 82 // and store in TLV 83 mesh_node_store_provisioning_data(&provisioning_data); 84 85 // setup node after provisioned 86 mesh_access_setup_from_provisioning_data(&provisioning_data); 87 88 // start advertising with node id after provisioning 89 mesh_proxy_set_advertising_with_node_id(provisioning_data.network_key->netkey_index, MESH_NODE_IDENTITY_STATE_ADVERTISING_RUNNING); 90 91 provisioned = 1; 92 break; 93 default: 94 break; 95 } 96 break; 97 default: 98 break; 99 } 100 if (provisioning_device_packet_handler == NULL) return; 101 102 // forward 103 (*provisioning_device_packet_handler)(packet_type, channel, packet, size); 104 } 105 106 static void hci_packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 107 UNUSED(channel); 108 UNUSED(size); 109 110 switch (packet_type) { 111 case HCI_EVENT_PACKET: 112 switch (hci_event_packet_get_type(packet)) { 113 case BTSTACK_EVENT_STATE: 114 if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING) break; 115 // startup from provisioning data stored in TLV 116 provisioned = mesh_node_startup_from_tlv(); 117 break; 118 119 case HCI_EVENT_DISCONNECTION_COMPLETE: 120 // enable PB_GATT 121 if (provisioned == 0){ 122 mesh_proxy_start_advertising_unprovisioned_device(); 123 } else { 124 #ifdef ENABLE_MESH_PROXY_SERVER 125 mesh_proxy_start_advertising_with_network_id(); 126 #endif 127 } 128 break; 129 130 case HCI_EVENT_LE_META: 131 if (hci_event_le_meta_get_subevent_code(packet) != HCI_SUBEVENT_LE_CONNECTION_COMPLETE) break; 132 // disable PB_GATT 133 mesh_proxy_stop_advertising_unprovisioned_device(); 134 break; 135 default: 136 break; 137 } 138 break; 139 } 140 } 141 142 static mesh_model_t mesh_configuration_server_model; 143 static mesh_model_t mesh_health_server_model; 144 145 static mesh_configuration_server_model_context_t mesh_configuration_server_model_context; 146 147 static void mesh_node_setup_default_models(void){ 148 // configure Config Server 149 mesh_configuration_server_model.model_identifier = mesh_model_get_model_identifier_bluetooth_sig(MESH_SIG_MODEL_ID_CONFIGURATION_SERVER); 150 mesh_configuration_server_model.model_data = &mesh_configuration_server_model_context; 151 mesh_configuration_server_model.operations = mesh_configuration_server_get_operations(); 152 mesh_element_add_model(mesh_node_get_primary_element(), &mesh_configuration_server_model); 153 154 // Config Health Server 155 mesh_health_server_model.model_identifier = mesh_model_get_model_identifier_bluetooth_sig(MESH_SIG_MODEL_ID_HEALTH_SERVER); 156 mesh_element_add_model(mesh_node_get_primary_element(), &mesh_health_server_model); 157 } 158 159 void mesh_init(void){ 160 161 // register for HCI events 162 hci_event_callback_registration.callback = &hci_packet_handler; 163 hci_add_event_handler(&hci_event_callback_registration); 164 165 // ADV Bearer also used for GATT Proxy Advertisements and PB-GATT 166 adv_bearer_init(); 167 168 #ifdef ENABLE_MESH_GATT_BEARER 169 // Setup GATT bearer 170 gatt_bearer_init(); 171 #endif 172 173 #ifdef ENABLE_MESH_ADV_BEARER 174 // Setup Unprovisioned Device Beacon 175 beacon_init(); 176 #endif 177 178 provisioning_device_init(); 179 180 // Node Configuration 181 mesh_node_init(); 182 183 // Network layer 184 mesh_network_init(); 185 186 // Transport layers (lower + upper)) 187 mesh_lower_transport_init(); 188 mesh_upper_transport_init(); 189 190 // Access layer 191 mesh_access_init(); 192 193 mesh_node_setup_default_models(); 194 } 195 196 /** 197 * Register for Mesh Provisioning Device events 198 * @param packet_handler 199 */ 200 void mesh_register_provisioning_device_packet_handler(btstack_packet_handler_t packet_handler){ 201 provisioning_device_packet_handler = packet_handler; 202 provisioning_device_register_packet_handler(&mesh_provisioning_message_handler); 203 } 204