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