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