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