xref: /btstack/src/hci_transport_h5.c (revision df25739fc3ea5a0a90f0f5925e6461d653697d2e)
1 /*
2  * Copyright (C) 2016 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 /*
39  *  hci_transport_h5.c
40  *
41  *  HCI Transport API implementation for basic H5 protocol
42  *
43  *  Created by Matthias Ringwald on 4/29/09.
44  */
45 
46 #include "hci.h"
47 #include "btstack_slip.h"
48 #include "btstack_debug.h"
49 #include "hci_transport.h"
50 #include "btstack_uart_block.h"
51 
52 #ifdef HAVE_EHCILL
53 #error "HCI Transport H5 does not support eHCILL. Please either use (H4 + HAVE_EHCILL) or H5 Transport"
54 #endif
55 
56 /// newer
57 
58 typedef enum {
59     LINK_UNINITIALIZED,
60     LINK_INITIALIZED,
61     LINK_ACTIVE
62 } hci_transport_link_state_t;
63 
64 typedef enum {
65     HCI_TRANSPORT_LINK_SEND_SYNC            = 1 << 0,
66     HCI_TRANSPORT_LINK_SEND_SYNC_RESPONSE   = 1 << 1,
67     HCI_TRANSPORT_LINK_SEND_CONFIG          = 1 << 2,
68     HCI_TRANSPORT_LINK_SEND_CONFIG_RESPONSE = 1 << 3,
69     HCI_TRANSPORT_LINK_SEND_WOKEN           = 1 << 4,
70     HCI_TRANSPORT_LINK_SEND_WAKEUP          = 1 << 5,
71     HCI_TRANSPORT_LINK_SEND_QUEUED_PACKET   = 1 << 6,
72     HCI_TRANSPORT_LINK_SEND_ACK_PACKET      = 1 << 7,
73 } hci_transport_link_actions_t;
74 
75 // Configuration Field. No packet buffers -> sliding window = 1, no OOF flow control, no data integrity check
76 #define LINK_CONFIG_SLIDING_WINDOW_SIZE 1
77 #define LINK_CONFIG_OOF_FLOW_CONTROL 0
78 #define LINK_CONFIG_DATA_INTEGRITY_CHECK 0
79 #define LINK_CONFIG_VERSION_NR 0
80 #define LINK_CONFIG_FIELD (LINK_CONFIG_SLIDING_WINDOW_SIZE | (LINK_CONFIG_OOF_FLOW_CONTROL << 3) | (LINK_CONFIG_DATA_INTEGRITY_CHECK << 4) | (LINK_CONFIG_VERSION_NR << 5))
81 
82 // periodic sending during link establishment
83 #define LINK_PERIOD_MS 250
84 
85 // resend wakeup
86 #define LINK_WAKEUP_MS 50
87 
88 // additional packet types
89 #define LINK_ACKNOWLEDGEMENT_TYPE 0x00
90 #define LINK_CONTROL_PACKET_TYPE 0x0f
91 
92 // ---
93 static const uint8_t link_control_sync[] =   { 0x01, 0x7e};
94 static const uint8_t link_control_sync_response[] = { 0x02, 0x7d};
95 static const uint8_t link_control_config[] = { 0x03, 0xfc, LINK_CONFIG_FIELD};
96 static const uint8_t link_control_config_response[] = { 0x04, 0x7b, LINK_CONFIG_FIELD};
97 static const uint8_t link_control_config_response_prefix_len  = 2;
98 static const uint8_t link_control_wakeup[] = { 0x05, 0xfa};
99 static const uint8_t link_control_woken[] =  { 0x06, 0xf9};
100 static const uint8_t link_control_sleep[] =  { 0x07, 0x78};
101 
102 // incoming pre-bufffer + 4 bytes H5 header + max(acl header + acl payload, event header + event data) + 2 bytes opt CRC
103 static uint8_t   hci_packet_with_pre_buffer[HCI_INCOMING_PRE_BUFFER_SIZE + 6 + HCI_PACKET_BUFFER_SIZE];
104 
105 // Non-optimized outgoing buffer (EOF, 4 bytes header, payload, EOF)
106 static uint8_t slip_outgoing_buffer[2 + 2 * (HCI_PACKET_BUFFER_SIZE + 4)];
107 
108 // H5 Link State
109 static hci_transport_link_state_t link_state;
110 static btstack_timer_source_t link_timer;
111 static uint8_t  link_seq_nr;
112 static uint8_t  link_ack_nr;
113 static uint16_t link_resend_timeout_ms;
114 static uint8_t  link_peer_asleep;
115 
116 // Outgoing packet
117 static uint8_t   hci_packet_type;
118 static uint16_t  hci_packet_size;
119 static uint8_t * hci_packet;
120 
121 // hci packet handler
122 static  void (*packet_handler)(uint8_t packet_type, uint8_t *packet, uint16_t size);
123 
124 static int hci_transport_link_actions;
125 
126 // UART Driver + Config
127 static const btstack_uart_block_t * btstack_uart;
128 static btstack_uart_config_t uart_config;
129 
130 static int uart_write_active;
131 
132 // Prototypes
133 static void hci_transport_h5_process_frame(uint16_t frame_size);
134 static int  hci_transport_link_have_outgoing_packet(void);
135 static void hci_transport_link_send_queued_packet(void);
136 static void hci_transport_link_set_timer(uint16_t timeout_ms);
137 static void hci_transport_link_timeout_handler(btstack_timer_source_t * timer);
138 static void hci_transport_link_run(void);
139 static void hci_transport_slip_init(void);
140 
141 // -----------------------------
142 
143 
144 // SLIP Outgoing
145 
146 // format: 0xc0 HEADER PACKER 0xc0
147 // @param uint8_t header[4]
148 static void hci_transport_slip_send_frame(const uint8_t * header, const uint8_t * packet, uint16_t packet_size){
149 
150     int pos = 0;
151 
152     // Start of Frame
153     slip_outgoing_buffer[pos++] = BTSTACK_SLIP_SOF;
154 
155     // Header
156     btstack_slip_encoder_start(header, 4);
157     while (btstack_slip_encoder_has_data()){
158         slip_outgoing_buffer[pos++] = btstack_slip_encoder_get_byte();
159     }
160 
161     // Packet
162     btstack_slip_encoder_start(packet, packet_size);
163     while (btstack_slip_encoder_has_data()){
164         slip_outgoing_buffer[pos++] = btstack_slip_encoder_get_byte();
165     }
166 
167     // Start of Frame
168     slip_outgoing_buffer[pos++] = BTSTACK_SLIP_SOF;
169 
170     uart_write_active = 1;
171     btstack_uart->send_block(slip_outgoing_buffer, pos);
172 }
173 
174 // SLIP Incoming
175 
176 static void hci_transport_slip_init(void){
177     btstack_slip_decoder_init(&hci_packet_with_pre_buffer[HCI_INCOMING_PRE_BUFFER_SIZE], 6 + HCI_PACKET_BUFFER_SIZE);
178 }
179 
180 // H5 Three-Wire Implementation
181 
182 static void hci_transport_link_calc_header(uint8_t * header,
183     uint8_t  sequence_nr,
184     uint8_t  acknowledgement_nr,
185     uint8_t  data_integrity_check_present,
186     uint8_t  reliable_packet,
187     uint8_t  packet_type,
188     uint16_t payload_length){
189 
190     // reset data integrity flag
191     if (data_integrity_check_present){
192         log_error("hci_transport_link_calc_header: data integrity not supported, dropping flag");
193         data_integrity_check_present = 0;
194     }
195 
196     header[0] = sequence_nr | (acknowledgement_nr << 3) | (data_integrity_check_present << 6) | (reliable_packet << 7);
197     header[1] = packet_type | ((payload_length & 0x0f) << 4);
198     header[2] = payload_length >> 4;
199     header[3] = 0xff - (header[0] + header[1] + header[2]);
200 }
201 
202 static void hci_transport_link_send_control(const uint8_t * message, int message_len){
203     uint8_t header[4];
204     hci_transport_link_calc_header(header, 0, 0, 0, 0, LINK_CONTROL_PACKET_TYPE, message_len);
205     hci_transport_slip_send_frame(header, message, message_len);
206 }
207 
208 static void hci_transport_link_send_sync(void){
209     log_info("link: send sync");
210     hci_transport_link_send_control(link_control_sync, sizeof(link_control_sync));
211 }
212 
213 static void hci_transport_link_send_sync_response(void){
214     log_info("link: send sync response");
215     hci_transport_link_send_control(link_control_sync_response, sizeof(link_control_sync_response));
216 }
217 
218 static void hci_transport_link_send_config(void){
219     log_info("link: send config");
220     hci_transport_link_send_control(link_control_config, sizeof(link_control_config));
221 }
222 
223 static void hci_transport_link_send_config_response(void){
224     log_info("link: send config response");
225     hci_transport_link_send_control(link_control_config_response, sizeof(link_control_config_response));
226 }
227 
228 static void hci_transport_link_send_woken(void){
229     log_info("link: send woken");
230     hci_transport_link_send_control(link_control_woken, sizeof(link_control_woken));
231 }
232 
233 static void hci_transport_link_send_wakeup(void){
234     log_info("link: send wakeup");
235     hci_transport_link_send_control(link_control_wakeup, sizeof(link_control_wakeup));
236 }
237 
238 static void hci_transport_link_send_queued_packet(void){
239     log_info("hci_transport_link_send_queued_packet: seq %u, ack %u, size %u", link_seq_nr, link_ack_nr, hci_packet_size);
240     log_info_hexdump(hci_packet, hci_packet_size);
241 
242     uint8_t header[4];
243     hci_transport_link_calc_header(header, link_seq_nr, link_ack_nr, 0, 1, hci_packet_type, hci_packet_size);
244     hci_transport_slip_send_frame(header, hci_packet, hci_packet_size);
245 }
246 
247 static void hci_transport_link_send_ack_packet(void){
248     log_info("link: send ack %u", link_ack_nr);
249     uint8_t header[4];
250     hci_transport_link_calc_header(header, 0, link_ack_nr, 0, 0, LINK_ACKNOWLEDGEMENT_TYPE, 0);
251     hci_transport_slip_send_frame(header, NULL, 0);
252 }
253 
254 static void hci_transport_link_run(void){
255     // exit if outgoing active
256     if (uart_write_active) return;
257 
258     // process queued requests
259     if (hci_transport_link_actions & HCI_TRANSPORT_LINK_SEND_SYNC){
260         hci_transport_link_actions &= ~HCI_TRANSPORT_LINK_SEND_SYNC;
261         hci_transport_link_send_sync();
262         return;
263     }
264     if (hci_transport_link_actions & HCI_TRANSPORT_LINK_SEND_SYNC_RESPONSE){
265         hci_transport_link_actions &= ~HCI_TRANSPORT_LINK_SEND_SYNC_RESPONSE;
266         hci_transport_link_send_sync_response();
267         return;
268     }
269     if (hci_transport_link_actions & HCI_TRANSPORT_LINK_SEND_CONFIG){
270         hci_transport_link_actions &= ~HCI_TRANSPORT_LINK_SEND_CONFIG;
271         hci_transport_link_send_config();
272         return;
273     }
274     if (hci_transport_link_actions & HCI_TRANSPORT_LINK_SEND_CONFIG_RESPONSE){
275         hci_transport_link_actions &= ~HCI_TRANSPORT_LINK_SEND_CONFIG_RESPONSE;
276         hci_transport_link_send_config_response();
277         return;
278     }
279     if (hci_transport_link_actions & HCI_TRANSPORT_LINK_SEND_WOKEN){
280         hci_transport_link_actions &= ~HCI_TRANSPORT_LINK_SEND_WOKEN;
281         hci_transport_link_send_woken();
282         return;
283     }
284     if (hci_transport_link_actions & HCI_TRANSPORT_LINK_SEND_WAKEUP){
285         hci_transport_link_actions &= ~HCI_TRANSPORT_LINK_SEND_WAKEUP;
286         hci_transport_link_send_wakeup();
287         return;
288     }
289     if (hci_transport_link_actions & HCI_TRANSPORT_LINK_SEND_QUEUED_PACKET){
290         hci_transport_link_actions &= ~HCI_TRANSPORT_LINK_SEND_QUEUED_PACKET;
291         // packet already contains ack, no need to send addtitional one
292         hci_transport_link_actions &= ~HCI_TRANSPORT_LINK_SEND_ACK_PACKET;
293         hci_transport_link_send_queued_packet();
294         return;
295     }
296     if (hci_transport_link_actions & HCI_TRANSPORT_LINK_SEND_ACK_PACKET){
297         hci_transport_link_actions &= ~HCI_TRANSPORT_LINK_SEND_ACK_PACKET;
298         hci_transport_link_send_ack_packet();
299         return;
300     }
301 }
302 
303 static void hci_transport_link_set_timer(uint16_t timeout_ms){
304     btstack_run_loop_set_timer_handler(&link_timer, &hci_transport_link_timeout_handler);
305     btstack_run_loop_set_timer(&link_timer, timeout_ms);
306     btstack_run_loop_add_timer(&link_timer);
307 }
308 
309 static void hci_transport_link_timeout_handler(btstack_timer_source_t * timer){
310     switch (link_state){
311         case LINK_UNINITIALIZED:
312             hci_transport_link_actions |= HCI_TRANSPORT_LINK_SEND_SYNC;
313             hci_transport_link_set_timer(LINK_PERIOD_MS);
314             break;
315         case LINK_INITIALIZED:
316             hci_transport_link_actions |= HCI_TRANSPORT_LINK_SEND_CONFIG;
317             hci_transport_link_set_timer(LINK_PERIOD_MS);
318             break;
319         case LINK_ACTIVE:
320             if (!hci_transport_link_have_outgoing_packet()){
321                 log_info("h5 timeout while active, but no outgoing packet");
322                 return;
323             }
324             if (link_peer_asleep){
325                 hci_transport_link_actions |= HCI_TRANSPORT_LINK_SEND_WAKEUP;
326                 hci_transport_link_set_timer(LINK_WAKEUP_MS);
327                 return;
328             }
329             // resend packet
330             hci_transport_link_actions |= HCI_TRANSPORT_LINK_SEND_QUEUED_PACKET;
331             hci_transport_link_set_timer(link_resend_timeout_ms);
332             break;
333         default:
334             break;
335     }
336 
337     hci_transport_link_run();
338 }
339 
340 static void hci_transport_link_init(void){
341     link_state = LINK_UNINITIALIZED;
342     link_peer_asleep = 0;
343 
344     // get started
345     hci_transport_link_actions |= HCI_TRANSPORT_LINK_SEND_SYNC;
346     hci_transport_link_set_timer(LINK_PERIOD_MS);
347     hci_transport_link_run();
348 }
349 
350 static int hci_transport_link_inc_seq_nr(int seq_nr){
351     return (seq_nr + 1) & 0x07;
352 }
353 
354 static int hci_transport_link_have_outgoing_packet(void){
355     return hci_packet != 0;
356 }
357 
358 static void hci_transport_link_clear_queue(void){
359     btstack_run_loop_remove_timer(&link_timer);
360     hci_packet = NULL;
361 }
362 
363 static void hci_transport_h5_queue_packet(uint8_t packet_type, uint8_t *packet, int size){
364     hci_packet = packet;
365     hci_packet_type = packet_type;
366     hci_packet_size = size;
367 }
368 
369 static void hci_transport_h5_process_frame(uint16_t frame_size){
370 
371     if (frame_size < 4) return;
372 
373     uint8_t * slip_header  = &hci_packet_with_pre_buffer[HCI_INCOMING_PRE_BUFFER_SIZE];
374     uint8_t * slip_payload = &hci_packet_with_pre_buffer[HCI_INCOMING_PRE_BUFFER_SIZE + 4];
375     int       frame_size_without_header = frame_size - 4;
376 
377     int      seq_nr =  slip_header[0] & 0x07;
378     int      ack_nr = (slip_header[0] >> 3)    & 0x07;
379     int      data_integrity_check_present = (slip_header[0] & 0x40) != 0;
380     int      reliable_packet  = (slip_header[0] & 0x80) != 0;
381     uint8_t  link_packet_type = slip_header[1] & 0x0f;
382     uint16_t link_payload_len = (slip_header[1] >> 4) | (slip_header[2] << 4);
383 
384     log_info("hci_transport_h5_process_frame, reliable %u, packet type %u, seq_nr %u, ack_nr %u", reliable_packet, link_packet_type, seq_nr, ack_nr);
385     log_info_hexdump(slip_header, 4);
386     log_info_hexdump(slip_payload, frame_size_without_header);
387 
388     // CSR 8811 does not seem to auto-detect H5 mode and sends data with even parity.
389     // if this byte sequence is detected, just enable even parity
390     const uint8_t sync_response_bcsp[] = {0x01, 0x7a, 0x06, 0x10};
391     if (memcmp(sync_response_bcsp, slip_header, 4) == 0){
392         log_info("h5: detected BSCP SYNC sent with Even Parity -> discard frame and enable Even Parity");
393         btstack_uart->set_parity(1);
394         return;
395     }
396 
397     // validate header checksum
398     uint8_t header_checksum = slip_header[0] + slip_header[1] + slip_header[2] + slip_header[3];
399     if (header_checksum != 0xff){
400         log_info("h5: header checksum 0x%02x (instead of 0xff)", header_checksum);
401         return;
402     }
403 
404     // validate payload length
405     int data_integrity_len = data_integrity_check_present ? 2 : 0;
406     uint16_t received_payload_len = frame_size_without_header - data_integrity_len;
407     if (link_payload_len != received_payload_len){
408         log_info("h5: expected payload len %u but got %u", link_payload_len, received_payload_len);
409         return;
410     }
411 
412     // (TODO data integrity check)
413 
414     switch (link_state){
415         case LINK_UNINITIALIZED:
416             if (link_packet_type != LINK_CONTROL_PACKET_TYPE) break;
417             if (memcmp(slip_payload, link_control_sync, sizeof(link_control_sync)) == 0){
418                 log_info("link: received sync");
419                 hci_transport_link_actions |= HCI_TRANSPORT_LINK_SEND_SYNC_RESPONSE;
420             }
421             if (memcmp(slip_payload, link_control_sync_response, sizeof(link_control_sync_response)) == 0){
422                 log_info("link: received sync response");
423                 link_state = LINK_INITIALIZED;
424                 btstack_run_loop_remove_timer(&link_timer);
425                 log_info("link initialized");
426                 //
427                 hci_transport_link_actions |= HCI_TRANSPORT_LINK_SEND_CONFIG;
428                 hci_transport_link_set_timer(LINK_PERIOD_MS);
429             }
430             break;
431         case LINK_INITIALIZED:
432             if (link_packet_type != LINK_CONTROL_PACKET_TYPE) break;
433             if (memcmp(slip_payload, link_control_sync, sizeof(link_control_sync)) == 0){
434                 log_info("link: received sync");
435                 hci_transport_link_actions |= HCI_TRANSPORT_LINK_SEND_SYNC_RESPONSE;
436             }
437             if (memcmp(slip_payload, link_control_config, sizeof(link_control_config)) == 0){
438                 log_info("link: received config");
439                 hci_transport_link_actions |= HCI_TRANSPORT_LINK_SEND_CONFIG_RESPONSE;
440             }
441             if (memcmp(slip_payload, link_control_config_response, link_control_config_response_prefix_len) == 0){
442                 log_info("link: received config response");
443                 link_state = LINK_ACTIVE;
444                 btstack_run_loop_remove_timer(&link_timer);
445                 log_info("link activated");
446                 //
447                 link_seq_nr = 0;
448                 link_ack_nr = 0;
449                 // notify upper stack that it can start
450                 uint8_t event[] = { HCI_EVENT_TRANSPORT_PACKET_SENT, 0};
451                 packet_handler(HCI_EVENT_PACKET, &event[0], sizeof(event));
452             }
453             break;
454         case LINK_ACTIVE:
455 
456             // validate packet sequence nr in reliable packets (check for out of sequence error)
457             if (reliable_packet){
458                 if (seq_nr != link_ack_nr){
459                     log_info("expected seq nr %u, but received %u", link_ack_nr, seq_nr);
460                     hci_transport_link_actions |= HCI_TRANSPORT_LINK_SEND_ACK_PACKET;
461                     break;
462                 }
463                 // ack packet right away
464                 link_ack_nr = hci_transport_link_inc_seq_nr(link_ack_nr);
465                 hci_transport_link_actions |= HCI_TRANSPORT_LINK_SEND_ACK_PACKET;
466             }
467 
468             // Process ACKs in reliable packet and explicit ack packets
469             if (reliable_packet || link_packet_type == LINK_ACKNOWLEDGEMENT_TYPE){
470                 // our packet is good if the remote expects our seq nr + 1
471                 int next_seq_nr = hci_transport_link_inc_seq_nr(link_seq_nr);
472                 if (hci_transport_link_have_outgoing_packet() && next_seq_nr == ack_nr){
473                     log_info("h5: outoing packet with seq %u ack'ed", link_seq_nr);
474                     link_seq_nr = next_seq_nr;
475                     hci_transport_link_clear_queue();
476 
477                     // notify upper stack that it can send again
478                     uint8_t event[] = { HCI_EVENT_TRANSPORT_PACKET_SENT, 0};
479                     packet_handler(HCI_EVENT_PACKET, &event[0], sizeof(event));
480                 }
481             }
482 
483             switch (link_packet_type){
484                 case LINK_CONTROL_PACKET_TYPE:
485                     if (memcmp(slip_payload, link_control_config, sizeof(link_control_config)) == 0){
486                         log_info("link: received config");
487                         hci_transport_link_actions |= HCI_TRANSPORT_LINK_SEND_CONFIG_RESPONSE;
488                         break;
489                     }
490                     if (memcmp(slip_payload, link_control_sync, sizeof(link_control_sync)) == 0){
491                         log_info("link: received sync in ACTIVE STATE!");
492                         // TODO sync during active indicates peer reset -> full upper layer reset necessary
493                         break;
494                     }
495                     if (memcmp(slip_payload, link_control_sleep, sizeof(link_control_sleep)) == 0){
496                         log_info("link: received sleep message");
497                         link_peer_asleep = 1;
498                         break;
499                     }
500                     if (memcmp(slip_payload, link_control_wakeup, sizeof(link_control_wakeup)) == 0){
501                         log_info("link: received wakupe message -> send woken");
502                         link_peer_asleep = 0;
503                         hci_transport_link_actions |= HCI_TRANSPORT_LINK_SEND_WOKEN;
504                         break;
505                     }
506                     if (memcmp(slip_payload, link_control_woken, sizeof(link_control_woken)) == 0){
507                         log_info("link: received woken message");
508                         link_peer_asleep = 0;
509                         // TODO: send packet if queued....
510                         break;
511                     }
512                     break;
513                 case HCI_EVENT_PACKET:
514                 case HCI_ACL_DATA_PACKET:
515                 case HCI_SCO_DATA_PACKET:
516                     packet_handler(link_packet_type, slip_payload, link_payload_len);
517                     break;
518             }
519 
520             break;
521         default:
522             break;
523     }
524 
525     hci_transport_link_run();
526 }
527 
528 // recommendet time until resend: 3 * time of largest packet
529 static uint16_t hci_transport_link_calc_resend_timeout(uint32_t baudrate){
530     uint32_t max_packet_size_in_bit = (HCI_PACKET_BUFFER_SIZE + 6) << 3;
531     uint32_t t_max_x3_ms = max_packet_size_in_bit * 3000 / baudrate;
532     log_info("resend timeout for %u baud: %u ms", baudrate, t_max_x3_ms);
533     return t_max_x3_ms;
534 }
535 
536 static void hci_transport_link_update_resend_timeout(uint32_t baudrate){
537     link_resend_timeout_ms = hci_transport_link_calc_resend_timeout(baudrate);
538 }
539 
540 /// H5 Interface
541 
542 static uint8_t hci_transport_link_read_byte;
543 
544 static void hci_transport_h5_read_next_byte(void){
545     log_info("hci_transport_h5_read_next_byte");
546     btstack_uart->receive_block(&hci_transport_link_read_byte, 1);
547 }
548 
549 static void hci_transport_h5_block_received(){
550     // log_info("slip: process 0x%02x", hci_transport_link_read_byte);
551     btstack_slip_decoder_process(hci_transport_link_read_byte);
552     uint16_t frame_size = btstack_slip_decoder_frame_size();
553     if (frame_size) {
554         hci_transport_h5_process_frame(frame_size);
555         hci_transport_slip_init();
556     }
557     hci_transport_h5_read_next_byte();
558 }
559 
560 static void hci_transport_h5_block_sent(void){
561     uart_write_active = 0;
562     hci_transport_link_run();
563 }
564 
565 static void hci_transport_h5_init(const void * transport_config){
566     // check for hci_transport_config_uart_t
567     if (!transport_config) {
568         log_error("hci_transport_h5: no config!");
569         return;
570     }
571     if (((hci_transport_config_t*)transport_config)->type != HCI_TRANSPORT_CONFIG_UART) {
572         log_error("hci_transport_h5: config not of type != HCI_TRANSPORT_CONFIG_UART!");
573         return;
574     }
575 
576     // extract UART config from transport config
577     hci_transport_config_uart_t * hci_transport_config_uart = (hci_transport_config_uart_t*) transport_config;
578     uart_config.baudrate    = hci_transport_config_uart->baudrate_init;
579     uart_config.flowcontrol = hci_transport_config_uart->flowcontrol;
580     uart_config.device_name = hci_transport_config_uart->device_name;
581 
582     // setup UART driver
583     btstack_uart->init(&uart_config);
584     btstack_uart->set_block_received(&hci_transport_h5_block_received);
585     btstack_uart->set_block_sent(&hci_transport_h5_block_sent);
586 }
587 
588 static int hci_transport_h5_open(void){
589     int res = btstack_uart->open();
590     if (res){
591         return res;
592     }
593 
594     // setup resend timeout
595     hci_transport_link_update_resend_timeout(uart_config.baudrate);
596 
597     // init slip parser state machine
598     hci_transport_slip_init();
599 
600     // init link management - already starts syncing
601     hci_transport_link_init();
602 
603     // start receiving
604     hci_transport_h5_read_next_byte();
605 
606     return 0;
607 }
608 
609 static int hci_transport_h5_close(void){
610     return btstack_uart->close();
611     return 0;
612 }
613 
614 static void hci_transport_h5_register_packet_handler(void (*handler)(uint8_t packet_type, uint8_t *packet, uint16_t size)){
615     packet_handler = handler;
616 }
617 
618 static int hci_transport_h5_can_send_packet_now(uint8_t packet_type){
619     if (hci_transport_link_have_outgoing_packet()) return 0;
620     return link_state == LINK_ACTIVE;
621 }
622 
623 static int hci_transport_h5_send_packet(uint8_t packet_type, uint8_t *packet, int size){
624     if (!hci_transport_h5_can_send_packet_now(packet_type)){
625         log_error("hci_transport_h5_send_packet called but in state %u", link_state);
626         return -1;
627     }
628 
629     // store request
630     hci_transport_h5_queue_packet(packet_type, packet, size);
631 
632     // send wakeup first
633     if (link_peer_asleep){
634         hci_transport_link_actions |= HCI_TRANSPORT_LINK_SEND_WAKEUP;
635         hci_transport_link_set_timer(LINK_WAKEUP_MS);
636     } else {
637         hci_transport_link_actions |= HCI_TRANSPORT_LINK_SEND_QUEUED_PACKET;
638         hci_transport_link_set_timer(link_resend_timeout_ms);
639     }
640     hci_transport_link_run();
641     return 0;
642 }
643 
644 static int hci_transport_h5_set_baudrate(uint32_t baudrate){
645 
646     log_info("hci_transport_h5_set_baudrate %u", baudrate);
647     int res = btstack_uart->set_baudrate(baudrate);
648 
649     if (res) return res;
650     hci_transport_link_update_resend_timeout(baudrate);
651     return 0;
652 }
653 
654 static void hci_transport_h5_reset_link(void){
655 
656     log_info("hci_transport_h5_reset_link");
657 
658     // clear outgoing queue
659     hci_transport_link_clear_queue();
660 
661     // init slip parser state machine
662     hci_transport_slip_init();
663 
664     // init link management - already starts syncing
665     hci_transport_link_init();
666 }
667 
668 static const hci_transport_t hci_transport_h5 = {
669     /* const char * name; */                                        "H5",
670     /* void   (*init) (const void *transport_config); */            &hci_transport_h5_init,
671     /* int    (*open)(void); */                                     &hci_transport_h5_open,
672     /* int    (*close)(void); */                                    &hci_transport_h5_close,
673     /* void   (*register_packet_handler)(void (*handler)(...); */   &hci_transport_h5_register_packet_handler,
674     /* int    (*can_send_packet_now)(uint8_t packet_type); */       &hci_transport_h5_can_send_packet_now,
675     /* int    (*send_packet)(...); */                               &hci_transport_h5_send_packet,
676     /* int    (*set_baudrate)(uint32_t baudrate); */                &hci_transport_h5_set_baudrate,
677     /* void   (*reset_link)(void); */                               &hci_transport_h5_reset_link,
678 };
679 
680 // configure and return h5 singleton
681 const hci_transport_t * hci_transport_h5_instance(const btstack_uart_block_t * uart_driver) {
682     btstack_uart = uart_driver;
683     return &hci_transport_h5;
684 }
685