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