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