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