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