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