1 /* 2 * Copyright (C) 2014 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_pts.c" 39 40 #include <stdint.h> 41 #include <stdio.h> 42 #include <stdlib.h> 43 #include <string.h> 44 45 #include "btstack.h" 46 #include "mesh_pts.h" 47 48 // general 49 static void show_usage(void); 50 static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); 51 static void mesh_pts_dump_mesh_options(void); 52 53 #define MESH_BLUEKITCHEN_MODEL_ID_TEST_SERVER 0x0000u 54 55 static btstack_packet_callback_registration_t hci_event_callback_registration; 56 static int provisioned; 57 58 static mesh_model_t mesh_vendor_model; 59 60 static mesh_model_t mesh_generic_on_off_server_model; 61 static mesh_generic_on_off_state_t mesh_generic_on_off_state; 62 static mesh_publication_model_t generic_on_off_server_publication; 63 64 static mesh_model_t mesh_generic_level_server_model; 65 static mesh_generic_level_state_t mesh_generic_level_state; 66 static mesh_publication_model_t generic_level_server_publication; 67 68 static mesh_model_t mesh_configuration_client_model; 69 70 static char gap_name_buffer[30]; 71 static char gap_name_prefix[] = "Mesh "; 72 73 // pts add-on 74 #define PTS_DEFAULT_TTL 10 75 76 static int pts_type; 77 78 static mesh_virtual_address_t * pts_virtual_addresss; 79 80 const char * pts_device_uuid_string = "001BDC0810210B0E0A0C000B0E0A0C00"; 81 82 static uint8_t prov_static_oob_data[16]; 83 static const char * prov_static_oob_string = "00000000000000000102030405060708"; 84 85 static uint8_t prov_public_key_data[64]; 86 static const char * prov_public_key_string = "F465E43FF23D3F1B9DC7DFC04DA8758184DBC966204796ECCF0D6CF5E16500CC0201D048BCBBD899EEEFC424164E33C201C2B010CA6B4D43A8A155CAD8ECB279"; 87 static uint8_t prov_private_key_data[32]; 88 static const char * prov_private_key_string = "529AA0670D72CD6497502ED473502B037E8803B5C60829A5A3CAA219505530BA"; 89 90 static mesh_transport_key_t pts_application_key; 91 92 // pin entry (pts) 93 static int ui_chars_for_pin; 94 static uint8_t ui_pin[17]; 95 static int ui_pin_offset; 96 97 98 static mesh_health_fault_t health_fault; 99 100 static void mesh_provisioning_dump(const mesh_provisioning_data_t * data){ 101 mesh_network_key_t * key = data->network_key; 102 printf("UnicastAddr: 0x%02x\n", data->unicast_address); 103 printf("DevKey: "); printf_hexdump(data->device_key, 16); 104 printf("IV Index: 0x%08x\n", data->iv_index); 105 printf("Flags: 0x%02x\n", data->flags); 106 printf("NetKey: "); printf_hexdump(key->net_key, 16); 107 printf("-- Derived from NetKey --\n"); 108 printf("NID: 0x%02x\n", key->nid); 109 printf("NetworkID: "); printf_hexdump(key->network_id, 8); 110 printf("BeaconKey: "); printf_hexdump(key->beacon_key, 16); 111 printf("EncryptionKey: "); printf_hexdump(key->encryption_key, 16); 112 printf("PrivacyKey: "); printf_hexdump(key->privacy_key, 16); 113 printf("IdentityKey: "); printf_hexdump(key->identity_key, 16); 114 } 115 116 117 static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 118 UNUSED(channel); 119 UNUSED(size); 120 bd_addr_t addr; 121 int i; 122 123 switch (packet_type) { 124 case HCI_EVENT_PACKET: 125 switch (hci_event_packet_get_type(packet)) { 126 case BTSTACK_EVENT_STATE: 127 if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING) break; 128 // dump bd_addr in pts format 129 gap_local_bd_addr(addr); 130 printf("Local addr: %s - ", bd_addr_to_str(addr)); 131 for (i=0;i<6;i++) { 132 printf("%02x", addr[i]); 133 } 134 printf("\n"); 135 136 // setup gap name 137 strcpy(gap_name_buffer, gap_name_prefix); 138 strcat(gap_name_buffer, bd_addr_to_str(addr)); 139 140 // dump PTS MeshOptions.ini 141 mesh_pts_dump_mesh_options(); 142 break; 143 default: 144 break; 145 } 146 break; 147 } 148 } 149 150 static void mesh_provisioning_message_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 151 mesh_provisioning_data_t provisioning_data; 152 153 switch(packet[0]){ 154 case HCI_EVENT_MESH_META: 155 switch(packet[2]){ 156 case MESH_SUBEVENT_PB_TRANSPORT_LINK_OPEN: 157 printf("Provisioner link opened"); 158 break; 159 case MESH_SUBEVENT_PB_TRANSPORT_LINK_CLOSED: 160 printf("Provisioner link close"); 161 break; 162 case MESH_SUBEVENT_ATTENTION_TIMER: 163 printf("Attention Timer: %u\n", mesh_subevent_attention_timer_get_attention_time(packet)); 164 break; 165 case MESH_SUBEVENT_PB_PROV_INPUT_OOB_REQUEST: 166 printf("Enter passphrase: "); 167 fflush(stdout); 168 ui_chars_for_pin = 1; 169 ui_pin_offset = 0; 170 break; 171 case MESH_SUBEVENT_PB_PROV_COMPLETE: 172 printf("Provisioning complete\n"); 173 // dump provisioning data 174 provisioning_device_data_get(&provisioning_data); 175 mesh_provisioning_dump(&provisioning_data); 176 provisioned = 1; 177 break; 178 default: 179 break; 180 } 181 break; 182 default: 183 break; 184 } 185 } 186 187 static void mesh_state_update_message_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 188 if (packet_type != HCI_EVENT_PACKET) return; 189 190 switch(packet[0]){ 191 case HCI_EVENT_MESH_META: 192 switch(packet[2]){ 193 case MESH_SUBEVENT_STATE_UPDATE_BOOL: 194 printf("State update: model identifier 0x%08x, state identifier 0x%08x, reason %u, state %u\n", 195 mesh_subevent_state_update_bool_get_model_identifier(packet), 196 mesh_subevent_state_update_bool_get_state_identifier(packet), 197 mesh_subevent_state_update_bool_get_reason(packet), 198 mesh_subevent_state_update_bool_get_value(packet)); 199 break; 200 default: 201 printf("mesh_state_update_message_handler: event not parsed"); 202 break; 203 } 204 break; 205 default: 206 break; 207 } 208 } 209 210 static void mesh_configuration_message_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 211 if (packet_type != HCI_EVENT_PACKET) return; 212 213 switch(packet[0]){ 214 case HCI_EVENT_MESH_META: 215 switch(packet[2]){ 216 default: 217 printf("mesh_configuration_message_handler: event not parsed"); 218 break; 219 } 220 break; 221 default: 222 break; 223 } 224 } 225 // PTS 226 227 // helper network layer, temp 228 static void mesh_pts_received_network_message(mesh_network_callback_type_t callback_type, mesh_network_pdu_t *network_pdu){ 229 switch (callback_type){ 230 case MESH_NETWORK_PDU_RECEIVED: 231 printf("Received network message. SRC %04x, DST %04x, SEQ %04x\n", 232 mesh_network_src(network_pdu), mesh_network_dst(network_pdu), mesh_network_seq(network_pdu)); 233 printf_hexdump(mesh_network_pdu_data(network_pdu), mesh_network_pdu_len(network_pdu)); 234 mesh_network_message_processed_by_higher_layer(network_pdu); 235 break; 236 default: 237 break; 238 } 239 } 240 241 static uint8_t mesh_network_send(uint8_t ttl, uint16_t dest, const uint8_t * transport_pdu_data, uint8_t transport_pdu_len){ 242 243 uint16_t netkey_index = 0; 244 uint8_t ctl = 0; 245 uint16_t src = mesh_node_get_primary_element_address(); 246 uint32_t seq = mesh_sequence_number_next(); 247 248 // "3.4.5.2: The output filter of the interface connected to advertising or GATT bearers shall drop all messages with TTL value set to 1." 249 // if (ttl <= 1) return 0; 250 251 // TODO: check transport_pdu_len depending on ctl 252 253 // lookup network by netkey_index 254 const mesh_network_key_t * network_key = mesh_network_key_list_get(netkey_index); 255 if (!network_key) return 0; 256 257 // allocate network_pdu 258 mesh_network_pdu_t * network_pdu = mesh_network_pdu_get(); 259 if (!network_pdu) return 0; 260 261 // setup network_pdu 262 mesh_network_setup_pdu(network_pdu, netkey_index, network_key->nid, ctl, ttl, seq, src, dest, transport_pdu_data, transport_pdu_len); 263 264 // send network_pdu 265 mesh_lower_transport_send_pdu((mesh_pdu_t *) network_pdu); 266 return 0; 267 } 268 269 static void printf_hex(const uint8_t * data, uint16_t len){ 270 while (len){ 271 printf("%02x", *data); 272 data++; 273 len--; 274 } 275 printf("\n"); 276 } 277 278 static void mesh_pts_dump_mesh_options(void){ 279 printf("\nMeshOptions.ini - into 'My Decoders' of Bluetooth Protocol Viewer\n"); 280 281 printf("[mesh]\n"); 282 283 printf("{IVindex}\n"); 284 printf("%08x\n", mesh_get_iv_index()); 285 286 mesh_network_key_t * network_key = mesh_network_key_list_get(0); 287 if (network_key){ 288 printf("{NetKey}\n"); 289 printf_hex(network_key->net_key, 16); 290 } 291 292 mesh_transport_key_t * transport_key = mesh_transport_key_get(0); 293 if (transport_key){ 294 printf("{AppKey}\n"); 295 printf_hex(transport_key->key, 16); 296 } 297 298 mesh_transport_key_t * device_key = mesh_transport_key_get(MESH_DEVICE_KEY_INDEX); 299 if (device_key){ 300 printf("{DevKey}\n"); 301 printf_hex(device_key->key, 16); 302 } 303 printf("\n"); 304 } 305 306 static void mesh_unprovisioned_beacon_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 307 if (packet_type != MESH_BEACON_PACKET) return; 308 uint8_t device_uuid[16]; 309 uint16_t oob; 310 memcpy(device_uuid, &packet[1], 16); 311 oob = big_endian_read_16(packet, 17); 312 printf("received unprovisioned device beacon, oob data %x, device uuid: ", oob); 313 printf_hexdump(device_uuid, 16); 314 pb_adv_create_link(device_uuid); 315 } 316 317 static int scan_hex_byte(const char * byte_string){ 318 int upper_nibble = nibble_for_char(*byte_string++); 319 if (upper_nibble < 0) return -1; 320 int lower_nibble = nibble_for_char(*byte_string); 321 if (lower_nibble < 0) return -1; 322 return (upper_nibble << 4) | lower_nibble; 323 } 324 325 static int btstack_parse_hex(const char * string, uint16_t len, uint8_t * buffer){ 326 int i; 327 for (i = 0; i < len; i++) { 328 int single_byte = scan_hex_byte(string); 329 if (single_byte < 0) return 0; 330 string += 2; 331 buffer[i] = (uint8_t)single_byte; 332 // don't check seperator after last byte 333 if (i == len - 1) { 334 return 1; 335 } 336 // optional seperator 337 char separator = *string; 338 if (separator == ':' && separator == '-' && separator == ' ') { 339 string++; 340 } 341 } 342 return 1; 343 } 344 345 static void btstack_print_hex(const uint8_t * data, uint16_t len, char separator){ 346 int i; 347 for (i=0;i<len;i++){ 348 printf("%02x", data[i]); 349 if (separator){ 350 printf("%c", separator); 351 } 352 } 353 printf("\n"); 354 } 355 356 static void load_pts_app_key(void){ 357 // PTS app key 358 btstack_parse_hex("3216D1509884B533248541792B877F98", 16, pts_application_key.key); 359 pts_application_key.aid = 0x38; 360 pts_application_key.internal_index = mesh_transport_key_get_free_index(); 361 mesh_transport_key_add(&pts_application_key); 362 printf("PTS Application Key (AID %02x): ", 0x38); 363 printf_hexdump(pts_application_key.key, 16); 364 } 365 static void send_pts_network_messsage(const char * dst_type, uint16_t dst_addr, int ttl_type){ 366 uint8_t ttl; 367 switch (ttl_type){ 368 case 0: 369 ttl = 0; 370 break; 371 case 1: 372 ttl = PTS_DEFAULT_TTL; 373 break; 374 default: 375 ttl = 0x7f; 376 break; 377 } 378 printf("%s dst %04x, ttl %u\n", dst_type, dst_addr, ttl); 379 int lower_transport_pdu_len = 16; 380 uint8_t lower_transport_pdu_data[16]; 381 memset(lower_transport_pdu_data, 0x55, lower_transport_pdu_len); 382 mesh_network_send(ttl, dst_addr, lower_transport_pdu_data, lower_transport_pdu_len); 383 } 384 385 static void send_pts_unsegmented_access_messsage(void){ 386 uint8_t access_pdu_data[16]; 387 388 load_pts_app_key(); 389 390 uint16_t src = mesh_node_get_primary_element_address(); 391 uint16_t dest = 0x0001; 392 uint8_t ttl = PTS_DEFAULT_TTL; 393 394 int access_pdu_len = 1; 395 memset(access_pdu_data, 0x55, access_pdu_len); 396 uint16_t netkey_index = 0; 397 uint16_t appkey_index = 0; // MESH_DEVICE_KEY_INDEX; 398 399 // send as unsegmented access pdu 400 mesh_pdu_t * pdu = (mesh_pdu_t*) mesh_network_pdu_get(); 401 int status = mesh_upper_transport_setup_access_pdu(pdu, netkey_index, appkey_index, ttl, src, dest, 0, access_pdu_data, access_pdu_len); 402 if (status) return; 403 mesh_access_send_unacknowledged_pdu(pdu); 404 } 405 406 static void send_pts_segmented_access_messsage_unicast(void){ 407 uint8_t access_pdu_data[20]; 408 409 load_pts_app_key(); 410 411 uint16_t src = mesh_node_get_primary_element_address(); 412 uint16_t dest = 0x0001; 413 uint8_t ttl = PTS_DEFAULT_TTL; 414 415 int access_pdu_len = 20; 416 memset(access_pdu_data, 0x55, access_pdu_len); 417 uint16_t netkey_index = 0; 418 uint16_t appkey_index = 0; // MESH_DEVICE_KEY_INDEX; 419 420 // send as segmented access pdu 421 mesh_pdu_t * pdu = (mesh_pdu_t *) mesh_transport_pdu_get(); 422 int status = mesh_upper_transport_setup_access_pdu(pdu, netkey_index, appkey_index, ttl, src, dest, 0, access_pdu_data, access_pdu_len); 423 if (status) return; 424 mesh_access_send_unacknowledged_pdu(pdu); 425 } 426 427 static void send_pts_segmented_access_messsage_group(void){ 428 uint8_t access_pdu_data[20]; 429 430 load_pts_app_key(); 431 432 uint16_t src = mesh_node_get_primary_element_address(); 433 uint16_t dest = 0xd000; 434 uint8_t ttl = PTS_DEFAULT_TTL; 435 436 int access_pdu_len = 20; 437 memset(access_pdu_data, 0x55, access_pdu_len); 438 uint16_t netkey_index = 0; 439 uint16_t appkey_index = 0; 440 441 // send as segmented access pdu 442 mesh_pdu_t * pdu = (mesh_pdu_t *) mesh_transport_pdu_get(); 443 int status = mesh_upper_transport_setup_access_pdu(pdu, netkey_index, appkey_index, ttl, src, dest, 0, access_pdu_data, access_pdu_len); 444 if (status) return; 445 mesh_access_send_unacknowledged_pdu(pdu); 446 } 447 448 static void send_pts_segmented_access_messsage_virtual(void){ 449 uint8_t access_pdu_data[20]; 450 451 load_pts_app_key(); 452 453 uint16_t src = mesh_node_get_primary_element_address(); 454 uint16_t dest = pts_virtual_addresss->pseudo_dst; 455 uint8_t ttl = PTS_DEFAULT_TTL; 456 457 int access_pdu_len = 20; 458 memset(access_pdu_data, 0x55, access_pdu_len); 459 uint16_t netkey_index = 0; 460 uint16_t appkey_index = 0; 461 462 // send as segmented access pdu 463 mesh_transport_pdu_t * transport_pdu = mesh_transport_pdu_get(); 464 int status = mesh_upper_transport_setup_access_pdu((mesh_pdu_t*) transport_pdu, netkey_index, appkey_index, ttl, src, dest, 0, access_pdu_data, access_pdu_len); 465 if (status) return; 466 mesh_access_send_unacknowledged_pdu((mesh_pdu_t*) transport_pdu); 467 } 468 469 static void show_usage(void){ 470 bd_addr_t iut_address; 471 gap_local_bd_addr(iut_address); 472 printf("\n--- Bluetooth Mesh Console at %s ---\n", bd_addr_to_str(iut_address)); 473 printf("0 - Send Network Message Unicast\n"); 474 printf("1 - Send Network Message Virtual 9779\n"); 475 printf("2 - Send Network Message Group D000\n"); 476 printf("3 - Send Network Message All Proxies\n"); 477 printf("4 - Send Network Message All Friends\n"); 478 printf("5 - Send Network Message All Relays\n"); 479 printf("6 - Send Network Message Nodes\n"); 480 printf("7 - Dump Network Messages\n"); 481 printf("? - Send Unsegmented Access Message\n"); 482 printf("? - Send Segmented Access Message - Unicast\n"); 483 printf("? - Send Segmented Access Message - Group D000\n"); 484 printf("? - Send Segmented Access Message - Virtual 9779\n"); 485 printf("? - Clear Replay Protection List\n"); 486 printf("? - Load PTS App key\n"); 487 printf("8 - Delete provisioning data\n"); 488 printf("p - Enable Public Key OOB \n"); 489 printf("o - Enable Output OOB \n"); 490 printf("i - Input Output OOB \n"); 491 printf("s - Static Output OOB \n"); 492 printf("b - Set Secure Network Beacon %s\n", mesh_foundation_beacon_get() ? "Off" : "On"); 493 #ifdef ENABLE_MESH_PROXY_SERVER 494 printf("n - Start Advertising with Node Identity\n"); 495 printf("N - Stop Advertising with Node Identity\n"); 496 #endif 497 printf("g - Generic ON/OFF Server Toggle Value\n"); 498 printf("f - Register Battery Low warning\n"); 499 printf("\n"); 500 } 501 502 static void stdin_process(char cmd){ 503 if (ui_chars_for_pin){ 504 printf("%c", cmd); 505 fflush(stdout); 506 if (cmd == '\n'){ 507 printf("\nSending Pin '%s'\n", ui_pin); 508 provisioning_device_input_oob_complete_alphanumeric(1, ui_pin, ui_pin_offset); 509 ui_chars_for_pin = 0; 510 } else { 511 ui_pin[ui_pin_offset++] = cmd; 512 } 513 return; 514 } 515 switch (cmd){ 516 case '0': 517 send_pts_network_messsage("Unicast", 0x0001, pts_type++); 518 break; 519 case '1': 520 send_pts_network_messsage("Virtual", pts_virtual_addresss->hash, pts_type++); 521 break; 522 case '2': 523 send_pts_network_messsage("Group", 0xd000, pts_type++); 524 break; 525 case '3': 526 send_pts_network_messsage("All Proxies", MESH_ADDRESS_ALL_PROXIES, pts_type++); 527 break; 528 case '4': 529 send_pts_network_messsage("All Friends", MESH_ADDRESS_ALL_FRIENDS, pts_type++); 530 break; 531 case '5': 532 send_pts_network_messsage("All Relays", MESH_ADDRESS_ALL_RELAYS, pts_type++); 533 break; 534 case '6': 535 send_pts_network_messsage("All Nodes", MESH_ADDRESS_ALL_NODES, pts_type++); 536 break; 537 case '7': 538 printf("Dump Network packets\n"); 539 mesh_network_set_higher_layer_handler(&mesh_pts_received_network_message); 540 break; 541 case '8': 542 mesh_node_reset(); 543 printf("Mesh Node Reset!\n"); 544 #ifdef ENABLE_MESH_PROXY_SERVER 545 mesh_proxy_start_advertising_unprovisioned_device(); 546 #endif 547 break; 548 case 'p': 549 printf("+ Public Key OOB Enabled\n"); 550 btstack_parse_hex(prov_public_key_string, 64, prov_public_key_data); 551 btstack_parse_hex(prov_private_key_string, 32, prov_private_key_data); 552 provisioning_device_set_public_key_oob(prov_public_key_data, prov_private_key_data); 553 break; 554 case 'o': 555 printf("+ Output OOB Enabled\n"); 556 provisioning_device_set_output_oob_actions(0x08, 0x08); 557 break; 558 case 'i': 559 printf("+ Input OOB Enabled\n"); 560 provisioning_device_set_input_oob_actions(0x08, 0x08); 561 break; 562 case 's': 563 printf("+ Static OOB Enabled\n"); 564 btstack_parse_hex(prov_static_oob_string, 16, prov_static_oob_data); 565 provisioning_device_set_static_oob(16, prov_static_oob_data); 566 break; 567 case 'g': 568 printf("Generic ON/OFF Server Toggle Value\n"); 569 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); 570 break; 571 case 'b': 572 printf("Turn Secure Network Beacon %s\n", mesh_foundation_beacon_get() ? "Off" : "On"); 573 mesh_foundation_beacon_set(1 - mesh_foundation_beacon_get()); 574 mesh_foundation_state_store(); 575 break; 576 #ifdef ENABLE_MESH_PROXY_SERVER 577 case 'n': 578 printf("Start Advertising with Node ID\n"); 579 mesh_proxy_start_advertising_with_node_id(); 580 break; 581 case 'N': 582 printf("Stop Advertising with Node ID\n"); 583 mesh_proxy_start_advertising_with_node_id(); 584 break; 585 #endif 586 case 'f': 587 // 0x01 = Battery Low 588 mesh_health_server_set_fault(mesh_node_get_health_server(), BLUETOOTH_COMPANY_ID_BLUEKITCHEN_GMBH, 1); 589 case ' ': 590 show_usage(); 591 break; 592 default: 593 printf("Command: '%c' not implemented\n", cmd); 594 show_usage(); 595 break; 596 } 597 } 598 599 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){ 600 UNUSED(connection_handle); 601 if (att_handle == ATT_CHARACTERISTIC_GAP_DEVICE_NAME_01_VALUE_HANDLE){ 602 return att_read_callback_handle_blob((const uint8_t *)gap_name_buffer, strlen(gap_name_buffer), offset, buffer, buffer_size); 603 } 604 return 0; 605 } 606 607 int btstack_main(void); 608 int btstack_main(void) 609 { 610 // console 611 btstack_stdin_setup(stdin_process); 612 613 // crypto 614 btstack_crypto_init(); 615 616 // l2cap 617 l2cap_init(); 618 619 // setup le device db 620 le_device_db_init(); 621 622 // setup ATT server 623 att_server_init(profile_data, &att_read_callback, NULL); 624 625 // 626 sm_init(); 627 628 629 // mesh 630 mesh_init(); 631 632 // setup connectable advertisments 633 bd_addr_t null_addr; 634 memset(null_addr, 0, 6); 635 uint8_t adv_type = 0; // AFV_IND 636 uint16_t adv_int_min = 0x0030; 637 uint16_t adv_int_max = 0x0030; 638 adv_bearer_advertisements_set_params(adv_int_min, adv_int_max, adv_type, 0, null_addr, 0x07, 0x00); 639 640 // Provisioning in device role 641 mesh_register_provisioning_device_packet_handler(&mesh_provisioning_message_handler); 642 643 // Loc - bottom - https://www.bluetooth.com/specifications/assigned-numbers/gatt-namespace-descriptors 644 mesh_node_set_element_location(mesh_node_get_primary_element(), 0x103); 645 646 // Setup node info 647 mesh_node_set_info(BLUETOOTH_COMPANY_ID_BLUEKITCHEN_GMBH, 0, 0); 648 649 // setup health server 650 mesh_health_server_add_fault_state(mesh_node_get_health_server(), BLUETOOTH_COMPANY_ID_BLUEKITCHEN_GMBH, &health_fault); 651 652 // Setup Generic On/Off model 653 mesh_generic_on_off_server_model.model_identifier = mesh_model_get_model_identifier_bluetooth_sig(MESH_SIG_MODEL_ID_GENERIC_ON_OFF_SERVER); 654 mesh_generic_on_off_server_model.operations = mesh_generic_on_off_server_get_operations(); 655 mesh_generic_on_off_server_model.model_data = (void *) &mesh_generic_on_off_state; 656 mesh_generic_on_off_server_register_packet_handler(&mesh_generic_on_off_server_model, &mesh_state_update_message_handler); 657 mesh_generic_on_off_server_set_publication_model(&mesh_generic_on_off_server_model, &generic_on_off_server_publication); 658 mesh_element_add_model(mesh_node_get_primary_element(), &mesh_generic_on_off_server_model); 659 660 // Setup Generic On/Off model 661 mesh_generic_level_server_model.model_identifier = mesh_model_get_model_identifier_bluetooth_sig(MESH_SIG_MODEL_ID_GENERIC_LEVEL_SERVER); 662 mesh_generic_level_server_model.operations = mesh_generic_level_server_get_operations(); 663 mesh_generic_level_server_model.model_data = (void *) &mesh_generic_level_state; 664 mesh_generic_level_server_register_packet_handler(&mesh_generic_level_server_model, &mesh_state_update_message_handler); 665 mesh_generic_level_server_set_publication_model(&mesh_generic_level_server_model, &generic_level_server_publication); 666 mesh_element_add_model(mesh_node_get_primary_element(), &mesh_generic_level_server_model); 667 668 // Setup our custom model 669 mesh_vendor_model.model_identifier = mesh_model_get_model_identifier(BLUETOOTH_COMPANY_ID_BLUEKITCHEN_GMBH, MESH_BLUEKITCHEN_MODEL_ID_TEST_SERVER); 670 mesh_element_add_model(mesh_node_get_primary_element(), &mesh_vendor_model); 671 672 // Setup Configuration Client model 673 mesh_configuration_client_model.model_identifier = mesh_model_get_model_identifier_bluetooth_sig(MESH_SIG_MODEL_ID_GENERIC_LEVEL_SERVER); 674 mesh_configuration_client_register_packet_handler(&mesh_configuration_client_model, &mesh_configuration_message_handler); 675 mesh_element_add_model(mesh_node_get_primary_element(), &mesh_configuration_client_model); 676 677 // Enable PROXY 678 mesh_foundation_gatt_proxy_set(1); 679 680 // register for HCI events 681 hci_event_callback_registration.callback = &packet_handler; 682 hci_add_event_handler(&hci_event_callback_registration); 683 684 #if defined(ENABLE_MESH_ADV_BEARER) 685 // setup scanning when supporting ADV Bearer 686 gap_set_scan_parameters(0, 0x300, 0x300); 687 gap_start_scan(); 688 #endif 689 690 // PTS add-on 691 692 #ifdef ENABLE_MESH_ADV_BEARER 693 // Register for Unprovisioned Device Beacons provisioner 694 beacon_register_for_unprovisioned_device_beacons(&mesh_unprovisioned_beacon_handler); 695 #endif 696 697 // Set PTS Device UUID 698 uint8_t pts_device_uuid[16]; 699 btstack_parse_hex(pts_device_uuid_string, 16, pts_device_uuid); 700 mesh_node_set_device_uuid(pts_device_uuid); 701 btstack_print_hex(pts_device_uuid, 16, 0); 702 703 // PTS Virtual Address Label UUID - without Config Model, PTS uses our device uuid 704 uint8_t label_uuid[16]; 705 btstack_parse_hex("001BDC0810210B0E0A0C000B0E0A0C00", 16, label_uuid); 706 pts_virtual_addresss = mesh_virtual_address_register(label_uuid, 0x9779); 707 708 printf("TSPX_iut_model_id 0x1000 (Generic OnOff Server)\n"); 709 printf("TSPX_vendor_model_id 0x%08x\n", mesh_vendor_model.model_identifier); 710 // turn on! 711 hci_power_control(HCI_POWER_ON); 712 713 return 0; 714 } 715 /* EXAMPLE_END */ 716