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 BLUEKITCHEN 24 * GMBH 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__ "pb_adv.c" 39 40 #include "pb_adv.h" 41 42 #include <inttypes.h> 43 #include <stdint.h> 44 #include <stdio.h> 45 #include <stdlib.h> 46 #include <string.h> 47 48 #include "btstack_debug.h" 49 #include "btstack_event.h" 50 #include "btstack_util.h" 51 52 #include "mesh/adv_bearer.h" 53 #include "mesh/beacon.h" 54 #include "mesh/mesh_node.h" 55 #include "mesh/provisioning.h" 56 57 #define PB_ADV_LINK_OPEN_RETRANSMIT_MS 1000 58 #define PB_ADV_LINK_OPEN_TIMEOUT_MS 60000 59 #define PB_ADV_LINK_OPEN_RETRIES (PB_ADV_LINK_OPEN_TIMEOUT_MS / PB_ADV_LINK_OPEN_RETRANSMIT_MS) 60 static void pb_adv_run(void); 61 62 /* taps: 32 31 29 1; characteristic polynomial: x^32 + x^31 + x^29 + x + 1 */ 63 #define LFSR(a) ((a >> 1) ^ (uint32_t)((0 - (a & 1u)) & 0xd0000001u)) 64 65 // PB-ADV - Provisioning Bearer using Advertisement Bearer 66 67 #define MESH_GENERIC_PROVISIONING_LINK_OPEN 0x00 68 #define MESH_GENERIC_PROVISIONING_LINK_ACK 0x01 69 #define MESH_GENERIC_PROVISIONING_LINK_CLOSE 0x02 70 71 #define MESH_GENERIC_PROVISIONING_TRANSACTION_TIMEOUT_MS 30000 72 73 // TODO: how large are prov messages? => how many segments are required? 74 #define MESH_PB_ADV_MAX_SEGMENTS 8 75 #define MESH_PB_ADV_START_PAYLOAD 20 76 #define MESH_PB_ADV_CONT_PAYLOAD 23 77 #define MESH_PB_ADV_MAX_PDU_SIZE (MESH_PB_ADV_START_PAYLOAD + (MESH_PB_ADV_MAX_SEGMENTS-2) * MESH_PB_ADV_CONT_PAYLOAD) 78 79 80 typedef enum mesh_gpcf_format { 81 MESH_GPCF_TRANSACTION_START = 0, 82 MESH_GPCF_TRANSACTION_ACK, 83 MESH_GPCF_TRANSACTION_CONT, 84 MESH_GPCF_PROV_BEARER_CONTROL, 85 } mesh_gpcf_format_t; 86 87 typedef enum { 88 LINK_STATE_W4_OPEN, 89 LINK_STATE_W2_SEND_ACK, 90 LINK_STATE_W4_ACK, 91 LINK_STATE_OPEN, 92 LINK_STATE_CLOSING, 93 } link_state_t; 94 static link_state_t link_state; 95 96 #ifdef ENABLE_MESH_PROVISIONER 97 static const uint8_t * pb_adv_peer_device_uuid; 98 static uint8_t pb_adv_provisioner_open_countdown; 99 #endif 100 101 static uint8_t pb_adv_msg_in_buffer[MESH_PB_ADV_MAX_PDU_SIZE]; 102 103 // single adv link, roles: provisioner = 1, device = 0 104 static uint16_t pb_adv_cid = 1; 105 static uint8_t pb_adv_provisioner_role; 106 107 // link state 108 static uint32_t pb_adv_link_id; 109 static uint8_t pb_adv_link_close_reason; 110 static uint8_t pb_adv_link_close_countdown; 111 static bool pb_adv_link_establish_timer_active; 112 113 // random delay for outgoing packets 114 static uint32_t pb_adv_lfsr; 115 static uint8_t pb_adv_random_delay_active; 116 117 // adv link timer used for 118 // establishment: 119 // - device: 60s timeout after receiving link open and sending link ack until first provisioning PDU 120 // - provisioner: 1s timer to send link open messages 121 // open: random delay 122 static btstack_timer_source_t pb_adv_link_timer; 123 124 // incoming message 125 static uint8_t pb_adv_msg_in_transaction_nr_prev; 126 static uint16_t pb_adv_msg_in_len; // 127 static uint8_t pb_adv_msg_in_fcs; 128 static uint8_t pb_adv_msg_in_last_segment; 129 static uint8_t pb_adv_msg_in_segments_missing; // bitfield for segmentes 1-n 130 static uint8_t pb_adv_msg_in_transaction_nr; 131 static uint8_t pb_adv_msg_in_send_ack; 132 133 // outgoing message 134 static uint8_t pb_adv_msg_out_active; 135 static uint8_t pb_adv_msg_out_transaction_nr; 136 static uint8_t pb_adv_msg_out_completed_transaction_nr; 137 static uint16_t pb_adv_msg_out_len; 138 static uint16_t pb_adv_msg_out_pos; 139 static uint8_t pb_adv_msg_out_seg; 140 static uint32_t pb_adv_msg_out_start; 141 static const uint8_t * pb_adv_msg_out_buffer; 142 143 static btstack_packet_handler_t pb_adv_device_packet_handler; 144 static btstack_packet_handler_t pb_adv_provisioner_packet_handler; 145 146 // poor man's random number generator 147 static uint32_t pb_adv_random(void){ 148 pb_adv_lfsr = LFSR(pb_adv_lfsr); 149 return pb_adv_lfsr; 150 } 151 152 static void pb_adv_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * packet, uint16_t size){ 153 if (pb_adv_provisioner_role == 0){ 154 (*pb_adv_device_packet_handler)(packet_type, channel, packet, size); 155 } else { 156 (*pb_adv_provisioner_packet_handler)(packet_type, channel, packet, size); 157 } 158 } 159 160 static void pb_adv_emit_pdu_sent(uint8_t status){ 161 uint8_t event[] = { HCI_EVENT_MESH_META, 2, MESH_SUBEVENT_PB_TRANSPORT_PDU_SENT, status}; 162 pb_adv_packet_handler(HCI_EVENT_PACKET, 0, event, sizeof(event)); 163 } 164 165 static void pb_adv_emit_link_open(uint8_t status, uint16_t pb_transport_cid){ 166 uint8_t event[7] = { HCI_EVENT_MESH_META, 5, MESH_SUBEVENT_PB_TRANSPORT_LINK_OPEN, status}; 167 little_endian_store_16(event, 4, pb_transport_cid); 168 event[6] = MESH_PB_TYPE_ADV; 169 pb_adv_packet_handler(HCI_EVENT_PACKET, 0, event, sizeof(event)); 170 } 171 172 static void pb_adv_emit_link_close(uint16_t pb_transport_cid, uint8_t reason){ 173 uint8_t event[6] = { HCI_EVENT_MESH_META, 3, MESH_SUBEVENT_PB_TRANSPORT_LINK_CLOSED}; 174 little_endian_store_16(event, 3, pb_transport_cid); 175 event[5] = reason; 176 pb_adv_packet_handler(HCI_EVENT_PACKET, 0, event, sizeof(event)); 177 } 178 179 static void pb_adv_device_link_timeout(btstack_timer_source_t * ts){ 180 UNUSED(ts); 181 // timeout occured 182 link_state = LINK_STATE_W4_OPEN; 183 log_info("link timeout, %08" PRIx32, pb_adv_link_id); 184 printf("PB-ADV: Link timeout %08" PRIx32 "\n", pb_adv_link_id); 185 pb_adv_emit_link_close(pb_adv_cid, ERROR_CODE_PAGE_TIMEOUT); 186 } 187 188 static void pb_adv_handle_bearer_control(uint32_t link_id, uint8_t transaction_nr, const uint8_t * pdu, uint16_t size){ 189 UNUSED(transaction_nr); 190 UNUSED(size); 191 192 uint8_t bearer_opcode = pdu[0] >> 2; 193 uint8_t reason; 194 const uint8_t * own_device_uuid; 195 switch (bearer_opcode){ 196 case MESH_GENERIC_PROVISIONING_LINK_OPEN: // Open a session on a bearer with a device 197 // does it match our device_uuid? 198 own_device_uuid = mesh_node_get_device_uuid(); 199 if (!own_device_uuid) break; 200 if (memcmp(&pdu[1], own_device_uuid, 16) != 0) break; 201 btstack_run_loop_remove_timer(&pb_adv_link_timer); 202 btstack_run_loop_set_timer(&pb_adv_link_timer, PB_ADV_LINK_OPEN_TIMEOUT_MS); 203 btstack_run_loop_set_timer_handler(&pb_adv_link_timer, &pb_adv_device_link_timeout); 204 btstack_run_loop_add_timer(&pb_adv_link_timer); 205 pb_adv_link_establish_timer_active = true; 206 switch(link_state){ 207 case LINK_STATE_W4_OPEN: 208 pb_adv_link_id = link_id; 209 pb_adv_provisioner_role = 0; 210 pb_adv_msg_in_transaction_nr = 0xff; // first transaction nr will be 0x00 211 pb_adv_msg_in_transaction_nr_prev = 0xff; 212 log_info("link open, id %08" PRIx32, pb_adv_link_id); 213 printf("PB-ADV: Link Open %08" PRIx32 "\n", pb_adv_link_id); 214 link_state = LINK_STATE_W2_SEND_ACK; 215 adv_bearer_request_can_send_now_for_provisioning_pdu(); 216 pb_adv_emit_link_open(ERROR_CODE_SUCCESS, pb_adv_cid); 217 break; 218 case LINK_STATE_OPEN: 219 if (pb_adv_link_id != link_id) break; 220 log_info("link open, resend ACK"); 221 link_state = LINK_STATE_W2_SEND_ACK; 222 adv_bearer_request_can_send_now_for_provisioning_pdu(); 223 break; 224 default: 225 break; 226 } 227 break; 228 #ifdef ENABLE_MESH_PROVISIONER 229 case MESH_GENERIC_PROVISIONING_LINK_ACK: // Acknowledge a session on a bearer 230 if (link_state != LINK_STATE_W4_ACK) break; 231 link_state = LINK_STATE_OPEN; 232 pb_adv_msg_out_transaction_nr = 0; 233 pb_adv_msg_in_transaction_nr = 0x7f; // first transaction nr will be 0x80 234 pb_adv_msg_in_transaction_nr_prev = 0x7f; 235 btstack_run_loop_remove_timer(&pb_adv_link_timer); 236 log_info("link open, id %08" PRIx32, pb_adv_link_id); 237 printf("PB-ADV: Link Open %08" PRIx32 "\n", pb_adv_link_id); 238 pb_adv_emit_link_open(ERROR_CODE_SUCCESS, pb_adv_cid); 239 break; 240 #endif 241 case MESH_GENERIC_PROVISIONING_LINK_CLOSE: // Close a session on a bearer 242 // does it match link id 243 if (link_id != pb_adv_link_id) break; 244 if (link_state == LINK_STATE_W4_OPEN) break; 245 btstack_run_loop_remove_timer(&pb_adv_link_timer); 246 reason = pdu[1]; 247 link_state = LINK_STATE_W4_OPEN; 248 log_info("link close, reason %x", reason); 249 pb_adv_emit_link_close(pb_adv_cid, reason); 250 break; 251 default: 252 log_info("BearerOpcode %x reserved for future use\n", bearer_opcode); 253 break; 254 } 255 } 256 257 static void pb_adv_pdu_complete(void){ 258 259 // Verify FCS 260 uint8_t pdu_crc = btstack_crc8_calc((uint8_t*)pb_adv_msg_in_buffer, pb_adv_msg_in_len); 261 if (pdu_crc != pb_adv_msg_in_fcs){ 262 printf("Incoming PDU: fcs %02x, calculated %02x -> drop packet\n", pb_adv_msg_in_fcs, btstack_crc8_calc(pb_adv_msg_in_buffer, pb_adv_msg_in_len)); 263 return; 264 } 265 266 printf("PB-ADV: %02x complete\n", pb_adv_msg_in_transaction_nr); 267 268 // transaction complete 269 pb_adv_msg_in_transaction_nr_prev = pb_adv_msg_in_transaction_nr; 270 if (pb_adv_provisioner_role){ 271 pb_adv_msg_in_transaction_nr = 0x7f; // invalid 272 } else { 273 pb_adv_msg_in_transaction_nr = 0xff; // invalid 274 } 275 276 // Ack Transaction 277 pb_adv_msg_in_send_ack = 1; 278 pb_adv_run(); 279 280 // Forward to Provisioning 281 pb_adv_packet_handler(PROVISIONING_DATA_PACKET, 0, pb_adv_msg_in_buffer, pb_adv_msg_in_len); 282 } 283 284 static void pb_adv_handle_transaction_start(uint8_t transaction_nr, const uint8_t * pdu, uint16_t size){ 285 286 // resend ack if packet from previous transaction received 287 if (transaction_nr != 0xff && transaction_nr == pb_adv_msg_in_transaction_nr_prev){ 288 printf("PB_ADV: %02x transaction complete, resending ack \n", transaction_nr); 289 pb_adv_msg_in_send_ack = 1; 290 return; 291 } 292 293 // new transaction? 294 if (transaction_nr != pb_adv_msg_in_transaction_nr){ 295 296 // check len 297 if (size < 4) return; 298 299 // check len 300 uint16_t msg_len = big_endian_read_16(pdu, 1); 301 if (msg_len > MESH_PB_ADV_MAX_PDU_SIZE){ 302 // abort transaction 303 return; 304 } 305 306 // check num segments 307 uint8_t last_segment = pdu[0] >> 2; 308 if (last_segment >= MESH_PB_ADV_MAX_SEGMENTS){ 309 // abort transaction 310 return; 311 } 312 313 printf("PB-ADV: %02x started\n", transaction_nr); 314 315 pb_adv_msg_in_transaction_nr = transaction_nr; 316 pb_adv_msg_in_len = msg_len; 317 pb_adv_msg_in_fcs = pdu[3]; 318 pb_adv_msg_in_last_segment = last_segment; 319 320 // set bits for segments 1..n (segment 0 already received in this message) 321 pb_adv_msg_in_segments_missing = (1 << last_segment) - 1; 322 323 // store payload 324 uint16_t payload_len = size - 4; 325 (void)memcpy(pb_adv_msg_in_buffer, &pdu[4], payload_len); 326 327 // complete? 328 if (pb_adv_msg_in_segments_missing == 0){ 329 pb_adv_pdu_complete(); 330 } 331 } 332 } 333 334 static void pb_adv_handle_transaction_cont(uint8_t transaction_nr, const uint8_t * pdu, uint16_t size){ 335 336 // check transaction nr 337 if (transaction_nr != 0xff && transaction_nr == pb_adv_msg_in_transaction_nr_prev){ 338 printf("PB_ADV: %02x transaction complete, resending resending ack\n", transaction_nr); 339 pb_adv_msg_in_send_ack = 1; 340 return; 341 } 342 343 if (transaction_nr != pb_adv_msg_in_transaction_nr){ 344 printf("PB-ADV: %02x received msg for transaction nr %x\n", pb_adv_msg_in_transaction_nr, transaction_nr); 345 return; 346 } 347 348 // validate seg nr 349 uint8_t seg = pdu[0] >> 2; 350 if (seg >= MESH_PB_ADV_MAX_SEGMENTS || seg == 0){ 351 return; 352 } 353 354 // check if segment already received 355 uint8_t seg_mask = 1 << (seg-1); 356 if ((pb_adv_msg_in_segments_missing & seg_mask) == 0){ 357 printf("PB-ADV: %02x, segment %u already received\n", transaction_nr, seg); 358 return; 359 } 360 printf("PB-ADV: %02x, segment %u stored\n", transaction_nr, seg); 361 362 // calculate offset and fragment size 363 uint16_t msg_pos = MESH_PB_ADV_START_PAYLOAD + (seg-1) * MESH_PB_ADV_CONT_PAYLOAD; 364 uint16_t fragment_size = size - 1; 365 366 // check size if last segment 367 if (seg == pb_adv_msg_in_last_segment && (msg_pos + fragment_size) != pb_adv_msg_in_len){ 368 // last segment has invalid size 369 return; 370 } 371 372 // store segment and mark as received 373 (void)memcpy(&pb_adv_msg_in_buffer[msg_pos], &pdu[1], fragment_size); 374 pb_adv_msg_in_segments_missing &= ~seg_mask; 375 376 // last segment 377 if (pb_adv_msg_in_segments_missing == 0){ 378 pb_adv_pdu_complete(); 379 } 380 } 381 382 static void pb_adv_outgoing_transaction_complete(uint8_t status){ 383 // stop sending 384 pb_adv_msg_out_active = 0; 385 // emit done 386 pb_adv_emit_pdu_sent(status); 387 // keep track of ack'ed transactions 388 pb_adv_msg_out_completed_transaction_nr = pb_adv_msg_out_transaction_nr; 389 // increment outgoing transaction nr 390 pb_adv_msg_out_transaction_nr++; 391 if (pb_adv_msg_out_transaction_nr == 0x00){ 392 // Device role 393 pb_adv_msg_out_transaction_nr = 0x80; 394 } 395 if (pb_adv_msg_out_transaction_nr == 0x80){ 396 // Provisioner role 397 pb_adv_msg_out_transaction_nr = 0x00; 398 } 399 } 400 401 static void pb_adv_handle_transaction_ack(uint8_t transaction_nr, const uint8_t * pdu, uint16_t size){ 402 UNUSED(pdu); 403 UNUSED(size); 404 if (transaction_nr == pb_adv_msg_out_transaction_nr){ 405 printf("PB-ADV: %02x ACK received\n", transaction_nr); 406 pb_adv_outgoing_transaction_complete(ERROR_CODE_SUCCESS); 407 } else if (transaction_nr == pb_adv_msg_out_completed_transaction_nr){ 408 // Transaction ack received again 409 } else { 410 printf("PB-ADV: %02x unexpected Transaction ACK %x recevied\n", pb_adv_msg_out_transaction_nr, transaction_nr); 411 } 412 } 413 414 static int pb_adv_packet_to_send(void){ 415 return pb_adv_msg_in_send_ack || pb_adv_msg_out_active || (link_state == LINK_STATE_W4_ACK); 416 } 417 418 static void pb_adv_timer_handler(btstack_timer_source_t * ts){ 419 UNUSED(ts); 420 pb_adv_random_delay_active = 0; 421 if (!pb_adv_packet_to_send()) return; 422 adv_bearer_request_can_send_now_for_provisioning_pdu(); 423 } 424 425 static void pb_adv_run(void){ 426 if (!pb_adv_packet_to_send()) return; 427 if (pb_adv_random_delay_active) return; 428 429 // spec recommends 20-50 ms, we use 20-51 ms 430 pb_adv_random_delay_active = 1; 431 uint16_t random_delay_ms = 20 + (pb_adv_random() & 0x1f); 432 log_info("random delay %u ms", random_delay_ms); 433 btstack_run_loop_set_timer_handler(&pb_adv_link_timer, &pb_adv_timer_handler); 434 btstack_run_loop_set_timer(&pb_adv_link_timer, random_delay_ms); 435 btstack_run_loop_add_timer(&pb_adv_link_timer); 436 } 437 438 static void pb_adv_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 439 UNUSED(channel); 440 441 if (packet_type != HCI_EVENT_PACKET) return; 442 if (size < 3) return; 443 444 const uint8_t * data; 445 uint8_t length; 446 uint32_t link_id; 447 uint8_t transaction_nr; 448 uint8_t generic_provisioning_control; 449 switch(packet[0]){ 450 case GAP_EVENT_ADVERTISING_REPORT: 451 // check minimal size 452 if (size < (12 + 8)) return; 453 454 // data starts at offset 12 455 data = &packet[12]; 456 // PDB ADV PDU 457 length = data[0]; 458 459 // validate length field 460 if ((12 + length) > size) return; 461 462 link_id = big_endian_read_32(data, 2); 463 transaction_nr = data[6]; 464 // generic provision PDU 465 generic_provisioning_control = data[7]; 466 mesh_gpcf_format_t generic_provisioning_control_format = (mesh_gpcf_format_t) generic_provisioning_control & 3; 467 468 // unless, we're waiting for LINK_OPEN, check link_id 469 if (link_state != LINK_STATE_W4_OPEN){ 470 if (link_id != pb_adv_link_id) break; 471 } 472 473 if (generic_provisioning_control_format == MESH_GPCF_PROV_BEARER_CONTROL){ 474 pb_adv_handle_bearer_control(link_id, transaction_nr, &data[7], length-6); 475 break; 476 } 477 478 // verify link id and link state 479 if (link_state != LINK_STATE_OPEN) break; 480 481 // stop link establishment timer 482 if (pb_adv_link_establish_timer_active) { 483 pb_adv_link_establish_timer_active = false; 484 btstack_run_loop_remove_timer(&pb_adv_link_timer); 485 } 486 487 switch (generic_provisioning_control_format){ 488 case MESH_GPCF_TRANSACTION_START: 489 pb_adv_handle_transaction_start(transaction_nr, &data[7], length-6); 490 break; 491 case MESH_GPCF_TRANSACTION_CONT: 492 pb_adv_handle_transaction_cont(transaction_nr, &data[7], length-6); 493 break; 494 case MESH_GPCF_TRANSACTION_ACK: 495 pb_adv_handle_transaction_ack(transaction_nr, &data[7], length-6); 496 break; 497 default: 498 break; 499 } 500 pb_adv_run(); 501 break; 502 case HCI_EVENT_MESH_META: 503 switch(packet[2]){ 504 case MESH_SUBEVENT_CAN_SEND_NOW: 505 #ifdef ENABLE_MESH_PROVISIONER 506 if (link_state == LINK_STATE_W4_ACK){ 507 pb_adv_provisioner_open_countdown--; 508 if (pb_adv_provisioner_open_countdown == 0){ 509 pb_adv_emit_link_open(ERROR_CODE_PAGE_TIMEOUT, pb_adv_cid); 510 break; 511 } 512 // build packet 513 uint8_t buffer[22]; 514 big_endian_store_32(buffer, 0, pb_adv_link_id); 515 buffer[4] = 0; // Transaction ID = 0 516 buffer[5] = (0 << 2) | 3; // Link Open | Provisioning Bearer Control 517 (void)memcpy(&buffer[6], pb_adv_peer_device_uuid, 16); 518 adv_bearer_send_provisioning_pdu(buffer, sizeof(buffer)); 519 log_info("link open %08" PRIx32, pb_adv_link_id); 520 printf("PB-ADV: Sending Link Open for device uuid: "); 521 printf_hexdump(pb_adv_peer_device_uuid, 16); 522 btstack_run_loop_set_timer_handler(&pb_adv_link_timer, &pb_adv_timer_handler); 523 btstack_run_loop_set_timer(&pb_adv_link_timer, PB_ADV_LINK_OPEN_RETRANSMIT_MS); 524 btstack_run_loop_add_timer(&pb_adv_link_timer); 525 break; 526 } 527 #endif 528 if (link_state == LINK_STATE_CLOSING){ 529 log_info("link close %08" PRIx32, pb_adv_link_id); 530 printf("PB-ADV: Sending Link Close %08" PRIx32 "\n", pb_adv_link_id); 531 // build packet 532 uint8_t buffer[7]; 533 big_endian_store_32(buffer, 0, pb_adv_link_id); 534 buffer[4] = 0; // Transaction ID = 0 535 buffer[5] = (2 << 2) | 3; // Link Close | Provisioning Bearer Control 536 buffer[6] = pb_adv_link_close_reason; 537 adv_bearer_send_provisioning_pdu(buffer, sizeof(buffer)); 538 pb_adv_link_close_countdown--; 539 if (pb_adv_link_close_countdown) { 540 adv_bearer_request_can_send_now_for_provisioning_pdu(); 541 } else { 542 link_state = LINK_STATE_W4_OPEN; 543 } 544 break; 545 } 546 if (link_state == LINK_STATE_W2_SEND_ACK){ 547 link_state = LINK_STATE_OPEN; 548 pb_adv_msg_out_transaction_nr = 0x80; 549 // build packet 550 uint8_t buffer[6]; 551 big_endian_store_32(buffer, 0, pb_adv_link_id); 552 buffer[4] = 0; 553 buffer[5] = (1 << 2) | 3; // Link Ack | Provisioning Bearer Control 554 adv_bearer_send_provisioning_pdu(buffer, sizeof(buffer)); 555 log_info("link ack %08" PRIx32, pb_adv_link_id); 556 printf("PB-ADV: Sending Link Open Ack %08" PRIx32 "\n", pb_adv_link_id); 557 break; 558 } 559 if (pb_adv_msg_in_send_ack){ 560 pb_adv_msg_in_send_ack = 0; 561 uint8_t buffer[6]; 562 big_endian_store_32(buffer, 0, pb_adv_link_id); 563 buffer[4] = pb_adv_msg_in_transaction_nr_prev; 564 buffer[5] = MESH_GPCF_TRANSACTION_ACK; 565 adv_bearer_send_provisioning_pdu(buffer, sizeof(buffer)); 566 log_info("transaction ack %08" PRIx32, pb_adv_link_id); 567 printf("PB-ADV: %02x sending ACK\n", pb_adv_msg_in_transaction_nr_prev); 568 pb_adv_run(); 569 break; 570 } 571 if (pb_adv_msg_out_active){ 572 573 // check timeout for outgoing message 574 // since uint32_t is used and time now must be greater than pb_adv_msg_out_start, 575 // this claculation is correct even when the run loop time overruns 576 uint32_t transaction_time_ms = btstack_run_loop_get_time_ms() - pb_adv_msg_out_start; 577 if (transaction_time_ms >= MESH_GENERIC_PROVISIONING_TRANSACTION_TIMEOUT_MS){ 578 pb_adv_outgoing_transaction_complete(ERROR_CODE_CONNECTION_TIMEOUT); 579 return; 580 } 581 582 uint8_t buffer[29]; // ADV MTU 583 big_endian_store_32(buffer, 0, pb_adv_link_id); 584 buffer[4] = pb_adv_msg_out_transaction_nr; 585 uint16_t bytes_left; 586 uint16_t pos; 587 if (pb_adv_msg_out_pos == 0){ 588 // Transaction start 589 int seg_n = pb_adv_msg_out_len / 24; 590 pb_adv_msg_out_seg = 0; 591 buffer[5] = seg_n << 2 | MESH_GPCF_TRANSACTION_START; 592 big_endian_store_16(buffer, 6, pb_adv_msg_out_len); 593 buffer[8] = btstack_crc8_calc((uint8_t*)pb_adv_msg_out_buffer, pb_adv_msg_out_len); 594 pos = 9; 595 bytes_left = 24 - 4; 596 printf("PB-ADV: %02x Sending Start: ", pb_adv_msg_out_transaction_nr); 597 } else { 598 // Transaction continue 599 buffer[5] = pb_adv_msg_out_seg << 2 | MESH_GPCF_TRANSACTION_CONT; 600 pos = 6; 601 bytes_left = 24 - 1; 602 printf("PB-ADV: %02x Sending Cont: ", pb_adv_msg_out_transaction_nr); 603 } 604 pb_adv_msg_out_seg++; 605 uint16_t bytes_to_copy = btstack_min(bytes_left, pb_adv_msg_out_len - pb_adv_msg_out_pos); 606 (void)memcpy(&buffer[pos], 607 &pb_adv_msg_out_buffer[pb_adv_msg_out_pos], 608 bytes_to_copy); 609 pos += bytes_to_copy; 610 printf("bytes %02u, pos %02u, len %02u: ", bytes_to_copy, pb_adv_msg_out_pos, pb_adv_msg_out_len); 611 printf_hexdump(buffer, pos); 612 pb_adv_msg_out_pos += bytes_to_copy; 613 614 if (pb_adv_msg_out_pos == pb_adv_msg_out_len){ 615 // done 616 pb_adv_msg_out_pos = 0; 617 } 618 adv_bearer_send_provisioning_pdu(buffer, pos); 619 pb_adv_run(); 620 break; 621 } 622 break; 623 default: 624 break; 625 } 626 default: 627 break; 628 } 629 } 630 631 void pb_adv_init(void){ 632 adv_bearer_register_for_provisioning_pdu(&pb_adv_handler); 633 pb_adv_lfsr = 0x12345678; 634 pb_adv_random(); 635 } 636 637 void pb_adv_register_device_packet_handler(btstack_packet_handler_t packet_handler){ 638 pb_adv_device_packet_handler = packet_handler; 639 } 640 641 void pb_adv_register_provisioner_packet_handler(btstack_packet_handler_t packet_handler){ 642 pb_adv_provisioner_packet_handler = packet_handler; 643 } 644 645 void pb_adv_send_pdu(uint16_t pb_transport_cid, const uint8_t * pdu, uint16_t size){ 646 UNUSED(pb_transport_cid); 647 printf("PB-ADV: Send packet "); 648 printf_hexdump(pdu, size); 649 pb_adv_msg_out_buffer = pdu; 650 pb_adv_msg_out_len = size; 651 pb_adv_msg_out_pos = 0; 652 pb_adv_msg_out_start = btstack_run_loop_get_time_ms(); 653 pb_adv_msg_out_active = 1; 654 pb_adv_run(); 655 } 656 657 /** 658 * Close Link 659 * @param pb_transport_cid 660 */ 661 void pb_adv_close_link(uint16_t pb_transport_cid, uint8_t reason){ 662 switch (link_state){ 663 case LINK_STATE_W4_ACK: 664 case LINK_STATE_OPEN: 665 case LINK_STATE_W2_SEND_ACK: 666 pb_adv_emit_link_close(pb_transport_cid, 0); 667 link_state = LINK_STATE_CLOSING; 668 pb_adv_link_close_countdown = 3; 669 pb_adv_link_close_reason = reason; 670 adv_bearer_request_can_send_now_for_provisioning_pdu(); 671 break; 672 case LINK_STATE_W4_OPEN: 673 case LINK_STATE_CLOSING: 674 // nothing to do 675 break; 676 default: 677 btstack_assert(false); 678 break; 679 } 680 } 681 682 #ifdef ENABLE_MESH_PROVISIONER 683 uint16_t pb_adv_create_link(const uint8_t * device_uuid){ 684 if (link_state != LINK_STATE_W4_OPEN) return 0; 685 686 pb_adv_peer_device_uuid = device_uuid; 687 pb_adv_provisioner_role = 1; 688 pb_adv_provisioner_open_countdown = PB_ADV_LINK_OPEN_RETRIES; 689 690 // create new 32-bit link id 691 pb_adv_link_id = pb_adv_random(); 692 693 // after sending OPEN, we wait for an ACK 694 link_state = LINK_STATE_W4_ACK; 695 696 // request outgoing 697 adv_bearer_request_can_send_now_for_provisioning_pdu(); 698 699 // dummy pb_adv_cid 700 return pb_adv_cid; 701 } 702 #endif 703 704