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