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 // Mandatory Confiuration Server 73 static mesh_model_t mesh_configuration_server_model; 74 75 // Mandatory Health Server 76 static mesh_model_t mesh_health_server_model; 77 static mesh_configuration_server_model_context_t mesh_configuration_server_model_context; 78 79 // Random UUID on start 80 static btstack_crypto_random_t mesh_access_crypto_random; 81 static uint8_t random_device_uuid[16]; 82 83 void mesh_access_setup_from_provisioning_data(const mesh_provisioning_data_t * provisioning_data){ 84 85 // set iv_index and iv index update active 86 int iv_index_update_active = (provisioning_data->flags & 2) >> 1; 87 mesh_iv_index_recovered(iv_index_update_active, provisioning_data->iv_index); 88 89 // set unicast address 90 mesh_node_primary_element_address_set(provisioning_data->unicast_address); 91 92 // set device_key 93 mesh_transport_set_device_key(provisioning_data->device_key); 94 95 if (provisioning_data->network_key){ 96 97 // setup primary network with provisioned netkey 98 mesh_network_key_add(provisioning_data->network_key); 99 100 // setup primary network 101 mesh_subnet_setup_for_netkey_index(provisioning_data->network_key->netkey_index); 102 103 // start sending Secure Network Beacons 104 mesh_subnet_t * provisioned_subnet = mesh_subnet_get_by_netkey_index(provisioning_data->network_key->netkey_index); 105 beacon_secure_network_start(provisioned_subnet); 106 } 107 108 // Mesh Proxy 109 #ifdef ENABLE_MESH_PROXY_SERVER 110 // Setup Proxy 111 mesh_proxy_init(provisioning_data->unicast_address); 112 mesh_proxy_start_advertising_with_network_id(); 113 #endif 114 } 115 116 static void mesh_access_setup_unprovisioned_device(void * arg){ 117 // set random value 118 if (arg == NULL){ 119 mesh_node_set_device_uuid(random_device_uuid); 120 } 121 122 #ifdef ENABLE_MESH_PB_ADV 123 // PB-ADV 124 beacon_unprovisioned_device_start(mesh_node_get_device_uuid(), 0); 125 #endif 126 #ifdef ENABLE_MESH_PB_GATT 127 mesh_proxy_start_advertising_unprovisioned_device(); 128 #endif 129 } 130 131 void mesh_access_setup_without_provisiong_data(void){ 132 const uint8_t * device_uuid = mesh_node_get_device_uuid(); 133 if (device_uuid){ 134 mesh_access_setup_unprovisioned_device((void *)device_uuid); 135 } else{ 136 btstack_crypto_random_generate(&mesh_access_crypto_random, random_device_uuid, 16, &mesh_access_setup_unprovisioned_device, NULL); 137 } 138 } 139 140 static void mesh_provisioning_message_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 141 mesh_provisioning_data_t provisioning_data; 142 143 switch(packet[0]){ 144 case HCI_EVENT_MESH_META: 145 switch(packet[2]){ 146 case MESH_SUBEVENT_PB_PROV_COMPLETE: 147 // get provisioning data 148 provisioning_device_data_get(&provisioning_data); 149 150 // and store in TLV 151 mesh_node_store_provisioning_data(&provisioning_data); 152 153 // setup node after provisioned 154 mesh_access_setup_from_provisioning_data(&provisioning_data); 155 156 // start advertising with node id after provisioning 157 mesh_proxy_set_advertising_with_node_id(provisioning_data.network_key->netkey_index, MESH_NODE_IDENTITY_STATE_ADVERTISING_RUNNING); 158 159 provisioned = 1; 160 break; 161 default: 162 break; 163 } 164 break; 165 default: 166 break; 167 } 168 if (provisioning_device_packet_handler == NULL) return; 169 170 // forward 171 (*provisioning_device_packet_handler)(packet_type, channel, packet, size); 172 } 173 174 static void hci_packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 175 UNUSED(channel); 176 UNUSED(size); 177 178 switch (packet_type) { 179 case HCI_EVENT_PACKET: 180 switch (hci_event_packet_get_type(packet)) { 181 case BTSTACK_EVENT_STATE: 182 if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING) break; 183 // startup from provisioning data stored in TLV 184 provisioned = mesh_node_startup_from_tlv(); 185 break; 186 187 case HCI_EVENT_DISCONNECTION_COMPLETE: 188 // enable PB_GATT 189 if (provisioned == 0){ 190 mesh_proxy_start_advertising_unprovisioned_device(); 191 } else { 192 #ifdef ENABLE_MESH_PROXY_SERVER 193 mesh_proxy_start_advertising_with_network_id(); 194 #endif 195 } 196 break; 197 198 case HCI_EVENT_LE_META: 199 if (hci_event_le_meta_get_subevent_code(packet) != HCI_SUBEVENT_LE_CONNECTION_COMPLETE) break; 200 // disable PB_GATT 201 mesh_proxy_stop_advertising_unprovisioned_device(); 202 break; 203 default: 204 break; 205 } 206 break; 207 } 208 } 209 210 static void mesh_node_setup_default_models(void){ 211 // configure Config Server 212 mesh_configuration_server_model.model_identifier = mesh_model_get_model_identifier_bluetooth_sig(MESH_SIG_MODEL_ID_CONFIGURATION_SERVER); 213 mesh_configuration_server_model.model_data = &mesh_configuration_server_model_context; 214 mesh_configuration_server_model.operations = mesh_configuration_server_get_operations(); 215 mesh_element_add_model(mesh_node_get_primary_element(), &mesh_configuration_server_model); 216 217 // Config Health Server 218 mesh_health_server_model.model_identifier = mesh_model_get_model_identifier_bluetooth_sig(MESH_SIG_MODEL_ID_HEALTH_SERVER); 219 mesh_element_add_model(mesh_node_get_primary_element(), &mesh_health_server_model); 220 } 221 222 void mesh_init(void){ 223 224 // register for HCI events 225 hci_event_callback_registration.callback = &hci_packet_handler; 226 hci_add_event_handler(&hci_event_callback_registration); 227 228 // ADV Bearer also used for GATT Proxy Advertisements and PB-GATT 229 adv_bearer_init(); 230 231 #ifdef ENABLE_MESH_GATT_BEARER 232 // Setup GATT bearer 233 gatt_bearer_init(); 234 #endif 235 236 #ifdef ENABLE_MESH_ADV_BEARER 237 // Setup Unprovisioned Device Beacon 238 beacon_init(); 239 #endif 240 241 provisioning_device_init(); 242 243 // Node Configuration 244 mesh_node_init(); 245 246 // Network layer 247 mesh_network_init(); 248 249 // Transport layers (lower + upper)) 250 mesh_lower_transport_init(); 251 mesh_upper_transport_init(); 252 253 // Access layer 254 mesh_access_init(); 255 256 mesh_node_setup_default_models(); 257 } 258 259 /** 260 * Register for Mesh Provisioning Device events 261 * @param packet_handler 262 */ 263 void mesh_register_provisioning_device_packet_handler(btstack_packet_handler_t packet_handler){ 264 provisioning_device_packet_handler = packet_handler; 265 provisioning_device_register_packet_handler(&mesh_provisioning_message_handler); 266 } 267