xref: /btstack/src/mesh/pb_adv.c (revision cd5f23a3250874824c01a2b3326a9522fea3f99f)
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