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