xref: /btstack/src/hci_transport_h4.c (revision b6fc147f78a37f3479b846963ca40c9b931f6e2f)
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__ "hci_transport_h4.c"
39 
40 /*
41  *  hci_h4_transport.c
42  *
43  *  HCI Transport API implementation for H4 protocol over POSIX with optional support for eHCILL
44  *
45  *  Created by Matthias Ringwald on 4/29/09.
46  */
47 
48 #include <inttypes.h>
49 
50 #include "btstack_config.h"
51 
52 #include "btstack_debug.h"
53 #include "hci.h"
54 #include "hci_transport.h"
55 #include "bluetooth_company_id.h"
56 #include "btstack_uart_block.h"
57 
58 #define ENABLE_LOG_EHCILL
59 
60 #ifdef ENABLE_EHCILL
61 
62 // eHCILL commands
63 enum EHCILL_MESSAGES {
64 	EHCILL_GO_TO_SLEEP_IND = 0x030,
65 	EHCILL_GO_TO_SLEEP_ACK = 0x031,
66 	EHCILL_WAKE_UP_IND     = 0x032,
67 	EHCILL_WAKE_UP_ACK     = 0x033,
68 	EHCILL_WAKEUP_SIGNAL   = 0x034,
69 };
70 
71 static int  hci_transport_h4_ehcill_outgoing_packet_ready(void);
72 static void hci_transport_h4_echill_send_wakeup_ind(void);
73 static void hci_transport_h4_ehcill_handle_command(uint8_t action);
74 static void hci_transport_h4_ehcill_handle_ehcill_command_sent(void);
75 static void hci_transport_h4_ehcill_handle_packet_sent(void);
76 static void hci_transport_h4_ehcill_open(void);
77 static void hci_transport_h4_ehcill_reset_statemachine(void);
78 static void hci_transport_h4_ehcill_send_ehcill_command(void);
79 static void hci_transport_h4_ehcill_sleep_ack_timer_setup(void);
80 static void hci_transport_h4_ehcill_trigger_wakeup(void);
81 
82 typedef enum {
83     EHCILL_STATE_W2_SEND_SLEEP_ACK,
84     EHCILL_STATE_SLEEP,
85     EHCILL_STATE_W4_WAKEUP_IND_OR_ACK,
86     EHCILL_STATE_AWAKE
87 } EHCILL_STATE;
88 
89 // eHCILL state machine
90 static EHCILL_STATE ehcill_state;
91 static uint8_t      ehcill_command_to_send;
92 
93 static btstack_uart_sleep_mode_t btstack_uart_sleep_mode;
94 
95 // work around for eHCILL problem
96 static btstack_timer_source_t ehcill_sleep_ack_timer;
97 
98 #endif
99 
100 
101 // assert pre-buffer for packet type is available
102 #if !defined(HCI_OUTGOING_PRE_BUFFER_SIZE) || (HCI_OUTGOING_PRE_BUFFER_SIZE == 0)
103 #error HCI_OUTGOING_PRE_BUFFER_SIZE not defined. Please update hci.h
104 #endif
105 
106 static void dummy_handler(uint8_t packet_type, uint8_t *packet, uint16_t size);
107 
108 typedef enum {
109     H4_W4_PACKET_TYPE,
110     H4_W4_EVENT_HEADER,
111     H4_W4_ACL_HEADER,
112     H4_W4_SCO_HEADER,
113     H4_W4_PAYLOAD,
114 } H4_STATE;
115 
116 typedef enum {
117     TX_IDLE = 1,
118     TX_W4_PACKET_SENT,
119 #ifdef ENABLE_EHCILL
120     TX_W4_WAKEUP,
121     TX_W2_EHCILL_SEND,
122     TX_W4_EHCILL_SENT,
123 #endif
124 } TX_STATE;
125 
126 // UART Driver + Config
127 static const btstack_uart_block_t * btstack_uart;
128 static btstack_uart_config_t uart_config;
129 
130 // write state
131 static TX_STATE tx_state;
132 #ifdef ENABLE_EHCILL
133 static uint8_t * ehcill_tx_data;
134 static uint16_t  ehcill_tx_len;   // 0 == no outgoing packet
135 #endif
136 
137 static uint8_t packet_sent_event[] = { HCI_EVENT_TRANSPORT_PACKET_SENT, 0};
138 
139 static  void (*packet_handler)(uint8_t packet_type, uint8_t *packet, uint16_t size) = dummy_handler;
140 
141 // packet reader state machine
142 static  H4_STATE h4_state;
143 static uint16_t bytes_to_read;
144 static uint16_t read_pos;
145 
146 // incoming packet buffer
147 static uint8_t hci_packet_with_pre_buffer[HCI_INCOMING_PRE_BUFFER_SIZE + HCI_INCOMING_PACKET_BUFFER_SIZE + 1]; // packet type + max(acl header + acl payload, event header + event data)
148 static uint8_t * hci_packet = &hci_packet_with_pre_buffer[HCI_INCOMING_PRE_BUFFER_SIZE];
149 
150 // Baudrate change bugs in TI CC256x and CYW20704
151 #ifdef ENABLE_CC256X_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND
152 #define ENABLE_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND
153 static const uint8_t baud_rate_command_prefix[]   = { 0x01, 0x36, 0xff, 0x04};
154 #endif
155 
156 #ifdef ENABLE_CYPRESS_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND
157 #ifdef ENABLE_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND
158 #error "Please enable either ENABLE_CC256X_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND or ENABLE_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND"
159 #endif
160 #define ENABLE_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND
161 static const uint8_t baud_rate_command_prefix[]   = { 0x01, 0x18, 0xfc, 0x06};
162 #endif
163 
164 #ifdef ENABLE_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND
165 static const uint8_t local_version_event_prefix[] = { 0x04, 0x0e, 0x0c, 0x01, 0x01, 0x10};
166 static enum {
167     BAUDRATE_CHANGE_WORKAROUND_IDLE,
168     BAUDRATE_CHANGE_WORKAROUND_CHIPSET_DETECTED,
169     BAUDRATE_CHANGE_WORKAROUND_BAUDRATE_COMMAND_SENT,
170     BAUDRATE_CHANGE_WORKAROUND_DONE
171 } baudrate_change_workaround_state;
172 #endif
173 
174 static int hci_transport_h4_set_baudrate(uint32_t baudrate){
175     log_info("hci_transport_h4_set_baudrate %"PRIu32, baudrate);
176     return btstack_uart->set_baudrate(baudrate);
177 }
178 
179 static void hci_transport_h4_reset_statemachine(void){
180     h4_state = H4_W4_PACKET_TYPE;
181     read_pos = 0;
182     bytes_to_read = 1;
183 }
184 
185 static void hci_transport_h4_trigger_next_read(void){
186     // log_info("hci_transport_h4_trigger_next_read: %u bytes", bytes_to_read);
187     btstack_uart->receive_block(&hci_packet[read_pos], bytes_to_read);
188 }
189 
190 static void hci_transport_h4_block_read(void){
191 
192     read_pos += bytes_to_read;
193 
194     switch (h4_state) {
195         case H4_W4_PACKET_TYPE:
196             switch (hci_packet[0]){
197                 case HCI_EVENT_PACKET:
198                     bytes_to_read = HCI_EVENT_HEADER_SIZE;
199                     h4_state = H4_W4_EVENT_HEADER;
200                     break;
201                 case HCI_ACL_DATA_PACKET:
202                     bytes_to_read = HCI_ACL_HEADER_SIZE;
203                     h4_state = H4_W4_ACL_HEADER;
204                     break;
205                 case HCI_SCO_DATA_PACKET:
206                     bytes_to_read = HCI_SCO_HEADER_SIZE;
207                     h4_state = H4_W4_SCO_HEADER;
208                     break;
209 #ifdef ENABLE_EHCILL
210                 case EHCILL_GO_TO_SLEEP_IND:
211                 case EHCILL_GO_TO_SLEEP_ACK:
212                 case EHCILL_WAKE_UP_IND:
213                 case EHCILL_WAKE_UP_ACK:
214                     hci_transport_h4_ehcill_handle_command(hci_packet[0]);
215                     hci_transport_h4_reset_statemachine();
216                     break;
217 #endif
218                 default:
219                     log_error("hci_transport_h4: invalid packet type 0x%02x", hci_packet[0]);
220                     hci_transport_h4_reset_statemachine();
221                     break;
222             }
223             break;
224 
225         case H4_W4_EVENT_HEADER:
226             bytes_to_read = hci_packet[2];
227             // check Event length
228             if (bytes_to_read > (HCI_INCOMING_PACKET_BUFFER_SIZE - HCI_EVENT_HEADER_SIZE)){
229                 log_error("hci_transport_h4: invalid Event len %d - only space for %u", bytes_to_read, HCI_INCOMING_PACKET_BUFFER_SIZE - HCI_EVENT_HEADER_SIZE);
230                 hci_transport_h4_reset_statemachine();
231                 break;
232             }
233             h4_state = H4_W4_PAYLOAD;
234             break;
235 
236         case H4_W4_ACL_HEADER:
237             bytes_to_read = little_endian_read_16( hci_packet, 3);
238             // check ACL length
239             if (bytes_to_read > (HCI_INCOMING_PACKET_BUFFER_SIZE - HCI_ACL_HEADER_SIZE)){
240                 log_error("hci_transport_h4: invalid ACL payload len %d - only space for %u", bytes_to_read, HCI_INCOMING_PACKET_BUFFER_SIZE - HCI_ACL_HEADER_SIZE);
241                 hci_transport_h4_reset_statemachine();
242                 break;
243             }
244             h4_state = H4_W4_PAYLOAD;
245             break;
246 
247         case H4_W4_SCO_HEADER:
248             bytes_to_read = hci_packet[3];
249             // check SCO length
250             if (bytes_to_read > (HCI_INCOMING_PACKET_BUFFER_SIZE - HCI_SCO_HEADER_SIZE)){
251                 log_error("hci_transport_h4: invalid SCO payload len %d - only space for %u", bytes_to_read, HCI_INCOMING_PACKET_BUFFER_SIZE - HCI_SCO_HEADER_SIZE);
252                 hci_transport_h4_reset_statemachine();
253                 break;
254             }
255             h4_state = H4_W4_PAYLOAD;
256             break;
257 
258         case H4_W4_PAYLOAD:
259 #ifdef ENABLE_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND
260             if (baudrate_change_workaround_state == BAUDRATE_CHANGE_WORKAROUND_IDLE
261             && memcmp(hci_packet, local_version_event_prefix, sizeof(local_version_event_prefix)) == 0){
262 #ifdef ENABLE_CC256X_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND
263                 if (little_endian_read_16(hci_packet, 11) == BLUETOOTH_COMPANY_ID_TEXAS_INSTRUMENTS_INC){
264                     // detect TI CC256x controller based on manufacturer
265                     log_info("Detected CC256x controller");
266                     baudrate_change_workaround_state = BAUDRATE_CHANGE_WORKAROUND_CHIPSET_DETECTED;
267                 } else {
268                     // work around not needed
269                     log_info("Bluetooth controller not by TI");
270                     baudrate_change_workaround_state = BAUDRATE_CHANGE_WORKAROUND_DONE;
271                 }
272 #endif
273 #ifdef ENABLE_CYPRESS_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND
274                 if (little_endian_read_16(hci_packet, 11) == BLUETOOTH_COMPANY_ID_CYPRESS_SEMICONDUCTOR){
275                     // detect Cypress controller based on manufacturer
276                     log_info("Detected Cypress controller");
277                     baudrate_change_workaround_state = BAUDRATE_CHANGE_WORKAROUND_CHIPSET_DETECTED;
278                 } else {
279                     // work around not needed
280                     log_info("Bluetooth controller not by Cypress");
281                     baudrate_change_workaround_state = BAUDRATE_CHANGE_WORKAROUND_DONE;
282                 }
283 #endif
284             }
285 #endif
286             packet_handler(hci_packet[0], &hci_packet[1], read_pos-1);
287             hci_transport_h4_reset_statemachine();
288             break;
289         default:
290             break;
291     }
292 
293 #ifdef ENABLE_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND
294     if (baudrate_change_workaround_state == BAUDRATE_CHANGE_WORKAROUND_BAUDRATE_COMMAND_SENT){
295         baudrate_change_workaround_state = BAUDRATE_CHANGE_WORKAROUND_IDLE;
296         // avoid flowcontrol problem by reading expected hci command complete event of 7 bytes in a single block read
297         h4_state = H4_W4_PAYLOAD;
298         bytes_to_read = 7;
299     }
300 #endif
301 
302     hci_transport_h4_trigger_next_read();
303 }
304 
305 static void hci_transport_h4_block_sent(void){
306     switch (tx_state){
307         case TX_W4_PACKET_SENT:
308             // packet fully sent, reset state
309 #ifdef ENABLE_EHCILL
310             ehcill_tx_len = 0;
311 #endif
312             tx_state = TX_IDLE;
313 
314 #ifdef ENABLE_EHCILL
315             // notify eHCILL engine
316             hci_transport_h4_ehcill_handle_packet_sent();
317 #endif
318             // notify upper stack that it can send again
319             packet_handler(HCI_EVENT_PACKET, &packet_sent_event[0], sizeof(packet_sent_event));
320             break;
321 
322 #ifdef ENABLE_EHCILL
323         case TX_W4_EHCILL_SENT:
324         case TX_W4_WAKEUP:
325             hci_transport_h4_ehcill_handle_ehcill_command_sent();
326             break;
327 #endif
328 
329         default:
330             break;
331     }
332 }
333 
334 static int hci_transport_h4_can_send_now(uint8_t packet_type){
335     return tx_state == TX_IDLE;
336 }
337 
338 static int hci_transport_h4_send_packet(uint8_t packet_type, uint8_t * packet, int size){
339 
340     // store packet type before actual data and increase size
341     size++;
342     packet--;
343     *packet = packet_type;
344 
345 #ifdef ENABLE_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND
346     if ((baudrate_change_workaround_state == BAUDRATE_CHANGE_WORKAROUND_CHIPSET_DETECTED)
347     && (memcmp(packet, baud_rate_command_prefix, sizeof(baud_rate_command_prefix)) == 0)) {
348         log_info("Baud rate command detected, expect command complete event next");
349         baudrate_change_workaround_state = BAUDRATE_CHANGE_WORKAROUND_BAUDRATE_COMMAND_SENT;
350     }
351 #endif
352 
353 #ifdef ENABLE_EHCILL
354     // store request for later
355     ehcill_tx_len   = size;
356     ehcill_tx_data  = packet;
357     switch (ehcill_state){
358         case EHCILL_STATE_SLEEP:
359             hci_transport_h4_ehcill_trigger_wakeup();
360             return 0;
361         case EHCILL_STATE_W2_SEND_SLEEP_ACK:
362             log_info("eHILL: send next packet, state EHCILL_STATE_W2_SEND_SLEEP_ACK");
363             return 0;
364         default:
365             break;
366     }
367 #endif
368 
369     // start sending
370     tx_state = TX_W4_PACKET_SENT;
371     btstack_uart->send_block(packet, size);
372     return 0;
373 }
374 
375 static void hci_transport_h4_init(const void * transport_config){
376     // check for hci_transport_config_uart_t
377     if (!transport_config) {
378         log_error("hci_transport_h4: no config!");
379         return;
380     }
381     if (((hci_transport_config_t*)transport_config)->type != HCI_TRANSPORT_CONFIG_UART) {
382         log_error("hci_transport_h4: config not of type != HCI_TRANSPORT_CONFIG_UART!");
383         return;
384     }
385 
386     // extract UART config from transport config
387     hci_transport_config_uart_t * hci_transport_config_uart = (hci_transport_config_uart_t*) transport_config;
388     uart_config.baudrate    = hci_transport_config_uart->baudrate_init;
389     uart_config.flowcontrol = hci_transport_config_uart->flowcontrol;
390     uart_config.device_name = hci_transport_config_uart->device_name;
391 
392     // setup UART driver
393     btstack_uart->init(&uart_config);
394     btstack_uart->set_block_received(&hci_transport_h4_block_read);
395     btstack_uart->set_block_sent(&hci_transport_h4_block_sent);
396 }
397 
398 static int hci_transport_h4_open(void){
399     int res = btstack_uart->open();
400     if (res){
401         return res;
402     }
403     hci_transport_h4_reset_statemachine();
404     hci_transport_h4_trigger_next_read();
405 
406     tx_state = TX_IDLE;
407 
408 #ifdef ENABLE_EHCILL
409     hci_transport_h4_ehcill_open();
410 #endif
411     return 0;
412 }
413 
414 static int hci_transport_h4_close(void){
415     return btstack_uart->close();
416 }
417 
418 static void hci_transport_h4_register_packet_handler(void (*handler)(uint8_t packet_type, uint8_t *packet, uint16_t size)){
419     packet_handler = handler;
420 }
421 
422 static void dummy_handler(uint8_t packet_type, uint8_t *packet, uint16_t size){
423 }
424 
425 //
426 // --- main part of eHCILL implementation ---
427 //
428 
429 #ifdef ENABLE_EHCILL
430 
431 static void hci_transport_h4_ehcill_emit_sleep_state(int sleep_active){
432     static int last_state = 0;
433     if (sleep_active == last_state) return;
434     last_state = sleep_active;
435 
436     log_info("hci_transport_h4_ehcill_emit_sleep_state: %u", sleep_active);
437     uint8_t event[3];
438     event[0] = HCI_EVENT_TRANSPORT_SLEEP_MODE;
439     event[1] = sizeof(event) - 2;
440     event[2] = sleep_active;
441     packet_handler(HCI_EVENT_PACKET, &event[0], sizeof(event));
442 }
443 
444 static void hci_transport_h4_ehcill_wakeup_handler(void){
445 #ifdef ENABLE_LOG_EHCILL
446     log_info("eHCILL: UART wakeup received");
447 #endif
448     hci_transport_h4_ehcill_handle_command(EHCILL_WAKEUP_SIGNAL);
449 }
450 
451 static void hci_transport_h4_ehcill_open(void){
452     hci_transport_h4_ehcill_reset_statemachine();
453 
454     // find best sleep mode to use: wake on CTS, wake on RX, none
455     btstack_uart_sleep_mode = BTSTACK_UART_SLEEP_OFF;
456     int supported_sleep_modes = 0;
457     if (btstack_uart->get_supported_sleep_modes){
458         supported_sleep_modes = btstack_uart->get_supported_sleep_modes();
459     }
460     if (supported_sleep_modes & BTSTACK_UART_SLEEP_MASK_RTS_HIGH_WAKE_ON_CTS_PULSE){
461         log_info("eHCILL: using wake on CTS");
462         btstack_uart_sleep_mode = BTSTACK_UART_SLEEP_RTS_HIGH_WAKE_ON_CTS_PULSE;
463     } else if (supported_sleep_modes & BTSTACK_UART_SLEEP_MASK_RTS_LOW_WAKE_ON_RX_EDGE){
464         log_info("eHCILL: using wake on RX");
465         btstack_uart_sleep_mode = BTSTACK_UART_SLEEP_RTS_LOW_WAKE_ON_RX_EDGE;
466     } else {
467         log_info("eHCILL: UART driver does not provide compatible sleep mode");
468     }
469     if (btstack_uart->set_wakeup_handler){
470         btstack_uart->set_wakeup_handler(&hci_transport_h4_ehcill_wakeup_handler);
471     }
472 }
473 
474 static void hci_transport_h4_echill_send_wakeup_ind(void){
475 #ifdef ENABLE_LOG_EHCILL
476     log_info("eHCILL: send WAKEUP_IND");
477 #endif
478     // update state
479     tx_state     = TX_W4_WAKEUP;
480     ehcill_state = EHCILL_STATE_W4_WAKEUP_IND_OR_ACK;
481     ehcill_command_to_send = EHCILL_WAKE_UP_IND;
482     btstack_uart->send_block(&ehcill_command_to_send, 1);
483 }
484 
485 static int hci_transport_h4_ehcill_outgoing_packet_ready(void){
486     return ehcill_tx_len != 0;
487 }
488 
489 static void hci_transport_h4_ehcill_reset_statemachine(void){
490     ehcill_state = EHCILL_STATE_AWAKE;
491 }
492 
493 static void hci_transport_h4_ehcill_send_ehcill_command(void){
494 #ifdef ENABLE_LOG_EHCILL
495     log_info("eHCILL: send command %02x", ehcill_command_to_send);
496 #endif
497     tx_state = TX_W4_EHCILL_SENT;
498     if (ehcill_command_to_send == EHCILL_GO_TO_SLEEP_ACK){
499         ehcill_state = EHCILL_STATE_SLEEP;
500     }
501     btstack_uart->send_block(&ehcill_command_to_send, 1);
502 }
503 
504 static void hci_transport_h4_ehcill_sleep_ack_timer_handler(btstack_timer_source_t * timer){
505 	UNUSED(timer);
506 #ifdef ENABLE_LOG_EHCILL
507     log_info("eHCILL: timer triggered");
508 #endif
509     hci_transport_h4_ehcill_send_ehcill_command();
510 }
511 
512 static void hci_transport_h4_ehcill_sleep_ack_timer_setup(void){
513     // setup timer
514 #ifdef ENABLE_LOG_EHCILL
515     log_info("eHCILL: set timer for sending command %02x", ehcill_command_to_send);
516 #endif
517     btstack_run_loop_set_timer_handler(&ehcill_sleep_ack_timer, &hci_transport_h4_ehcill_sleep_ack_timer_handler);
518     btstack_run_loop_set_timer(&ehcill_sleep_ack_timer, 50);
519     btstack_run_loop_add_timer(&ehcill_sleep_ack_timer);
520 }
521 
522 static void hci_transport_h4_ehcill_trigger_wakeup(void){
523     switch (tx_state){
524         case TX_W2_EHCILL_SEND:
525         case TX_W4_EHCILL_SENT:
526             // wake up / sleep ack in progress, nothing to do now
527             return;
528         case TX_IDLE:
529         default:
530             // all clear, prepare for wakeup
531             break;
532     }
533     // UART needed again
534     hci_transport_h4_ehcill_emit_sleep_state(0);
535     if (btstack_uart_sleep_mode){
536         btstack_uart->set_sleep(BTSTACK_UART_SLEEP_OFF);
537     }
538     hci_transport_h4_echill_send_wakeup_ind();
539 }
540 
541 static void hci_transport_h4_ehcill_schedule_ehcill_command(uint8_t command){
542 #ifdef ENABLE_LOG_EHCILL
543     log_info("eHCILL: schedule eHCILL command %02x", command);
544 #endif
545     ehcill_command_to_send = command;
546     switch (tx_state){
547         case TX_IDLE:
548             if (ehcill_command_to_send == EHCILL_WAKE_UP_ACK){
549                 // send right away
550                 hci_transport_h4_ehcill_send_ehcill_command();
551             } else {
552                 // change state so BTstack cannot send and setup timer
553                 tx_state = TX_W2_EHCILL_SEND;
554                 hci_transport_h4_ehcill_sleep_ack_timer_setup();
555             }
556             break;
557         default:
558             break;
559     }
560 }
561 
562 static void hci_transport_h4_ehcill_handle_command(uint8_t action){
563     // log_info("hci_transport_h4_ehcill_handle: %x, state %u, defer_rx %u", action, ehcill_state, ehcill_defer_rx_size);
564     switch(ehcill_state){
565         case EHCILL_STATE_AWAKE:
566             switch(action){
567                 case EHCILL_GO_TO_SLEEP_IND:
568                     ehcill_state = EHCILL_STATE_W2_SEND_SLEEP_ACK;
569 #ifdef ENABLE_LOG_EHCILL
570                     log_info("eHCILL: Received GO_TO_SLEEP_IND RX");
571 #endif
572                     hci_transport_h4_ehcill_schedule_ehcill_command(EHCILL_GO_TO_SLEEP_ACK);
573                     break;
574                 default:
575                     break;
576             }
577             break;
578 
579         case EHCILL_STATE_W2_SEND_SLEEP_ACK:
580             switch(action){
581                 case EHCILL_WAKE_UP_IND:
582                     ehcill_state = EHCILL_STATE_AWAKE;
583                     hci_transport_h4_ehcill_emit_sleep_state(0);
584                     if (btstack_uart_sleep_mode){
585                         btstack_uart->set_sleep(BTSTACK_UART_SLEEP_OFF);
586                     }
587 #ifdef ENABLE_LOG_EHCILL
588                     log_info("eHCILL: Received WAKE_UP_IND RX");
589 #endif
590                     hci_transport_h4_ehcill_schedule_ehcill_command(EHCILL_WAKE_UP_ACK);
591                     break;
592 
593                 default:
594                     break;
595             }
596             break;
597 
598         case EHCILL_STATE_SLEEP:
599             switch(action){
600                 case EHCILL_WAKEUP_SIGNAL:
601                     hci_transport_h4_ehcill_emit_sleep_state(0);
602                     if (btstack_uart_sleep_mode){
603                         btstack_uart->set_sleep(BTSTACK_UART_SLEEP_OFF);
604                     }
605                     break;
606                 case EHCILL_WAKE_UP_IND:
607                     ehcill_state = EHCILL_STATE_AWAKE;
608                     hci_transport_h4_ehcill_emit_sleep_state(0);
609                     if (btstack_uart_sleep_mode){
610                         btstack_uart->set_sleep(BTSTACK_UART_SLEEP_OFF);
611                     }
612 #ifdef ENABLE_LOG_EHCILL
613                     log_info("eHCILL: Received WAKE_UP_IND RX");
614 #endif
615                     hci_transport_h4_ehcill_schedule_ehcill_command(EHCILL_WAKE_UP_ACK);
616                     break;
617 
618                 default:
619                     break;
620             }
621             break;
622 
623         case EHCILL_STATE_W4_WAKEUP_IND_OR_ACK:
624             switch(action){
625                 case EHCILL_WAKE_UP_IND:
626                 case EHCILL_WAKE_UP_ACK:
627 #ifdef ENABLE_LOG_EHCILL
628                     log_info("eHCILL: Received WAKE_UP (%02x)", action);
629 #endif
630                     tx_state = TX_W4_PACKET_SENT;
631                     ehcill_state = EHCILL_STATE_AWAKE;
632                     btstack_uart->send_block(ehcill_tx_data, ehcill_tx_len);
633                     break;
634                 default:
635                     break;
636             }
637             break;
638     }
639 }
640 
641 static void hci_transport_h4_ehcill_handle_packet_sent(void){
642 #ifdef ENABLE_LOG_EHCILL
643         log_info("eHCILL: handle packet sent, command to send %02x", ehcill_command_to_send);
644 #endif
645     // now, send pending ehcill command if neccessary
646     switch (ehcill_command_to_send){
647         case EHCILL_GO_TO_SLEEP_ACK:
648             hci_transport_h4_ehcill_sleep_ack_timer_setup();
649             break;
650         case EHCILL_WAKE_UP_IND:
651             hci_transport_h4_ehcill_send_ehcill_command();
652             break;
653         default:
654             break;
655     }
656 }
657 
658 static void hci_transport_h4_ehcill_handle_ehcill_command_sent(void){
659     tx_state = TX_IDLE;
660     int command = ehcill_command_to_send;
661     ehcill_command_to_send = 0;
662 
663 #ifdef ENABLE_LOG_EHCILL
664         log_info("eHCILL: handle eHCILL sent, command was %02x", command);
665 #endif
666 
667     if (command == EHCILL_GO_TO_SLEEP_ACK) {
668 #ifdef ENABLE_LOG_EHCILL
669         log_info("eHCILL: GO_TO_SLEEP_ACK sent, enter sleep mode");
670 #endif
671         // UART not needed after EHCILL_GO_TO_SLEEP_ACK was sent
672         if (btstack_uart_sleep_mode != BTSTACK_UART_SLEEP_OFF){
673             btstack_uart->set_sleep(btstack_uart_sleep_mode);
674         }
675         hci_transport_h4_ehcill_emit_sleep_state(1);
676     }
677     // already packet ready? then start wakeup
678     if (hci_transport_h4_ehcill_outgoing_packet_ready()){
679         hci_transport_h4_ehcill_emit_sleep_state(0);
680         if (btstack_uart_sleep_mode != BTSTACK_UART_SLEEP_OFF){
681             btstack_uart->set_sleep(BTSTACK_UART_SLEEP_OFF);
682         }
683         if (command != EHCILL_WAKE_UP_IND){
684             hci_transport_h4_echill_send_wakeup_ind();
685         }
686     }
687 }
688 
689 #endif
690 // --- end of eHCILL implementation ---------
691 
692 static const hci_transport_t hci_transport_h4 = {
693     /* const char * name; */                                        "H4",
694     /* void   (*init) (const void *transport_config); */            &hci_transport_h4_init,
695     /* int    (*open)(void); */                                     &hci_transport_h4_open,
696     /* int    (*close)(void); */                                    &hci_transport_h4_close,
697     /* void   (*register_packet_handler)(void (*handler)(...); */   &hci_transport_h4_register_packet_handler,
698     /* int    (*can_send_packet_now)(uint8_t packet_type); */       &hci_transport_h4_can_send_now,
699     /* int    (*send_packet)(...); */                               &hci_transport_h4_send_packet,
700     /* int    (*set_baudrate)(uint32_t baudrate); */                &hci_transport_h4_set_baudrate,
701     /* void   (*reset_link)(void); */                               NULL,
702     /* void   (*set_sco_config)(uint16_t voice_setting, int num_connections); */ NULL,
703 };
704 
705 // configure and return h4 singleton
706 const hci_transport_t * hci_transport_h4_instance(const btstack_uart_block_t * uart_driver) {
707     btstack_uart = uart_driver;
708     return &hci_transport_h4;
709 }
710