xref: /btstack/src/hci_transport_h4.c (revision 95fd1475d5729e5bee7a5a0d070566bf890e4c7e)
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 /*
39  *  hci_h4_transport.c
40  *
41  *  HCI Transport API implementation for H4 protocol over POSIX with optional support for eHCILL
42  *
43  *  Created by Matthias Ringwald on 4/29/09.
44  */
45 
46 #include "btstack_config.h"
47 
48 #include "btstack_debug.h"
49 #include "hci.h"
50 #include "hci_transport.h"
51 #include "btstack_uart_block.h"
52 
53 #ifdef ENABLE_EHCILL
54 
55 // eHCILL commands
56 #define EHCILL_GO_TO_SLEEP_IND 0x030
57 #define EHCILL_GO_TO_SLEEP_ACK 0x031
58 #define EHCILL_WAKE_UP_IND     0x032
59 #define EHCILL_WAKE_UP_ACK     0x033
60 
61 static int  hci_transport_h4_ehcill_outgoing_packet_ready(void);
62 static int  hci_transport_h4_ehcill_sleep_mode_active(void);
63 static void hci_transport_h4_echill_send_wakeup_ind(void);
64 static void hci_transport_h4_ehcill_handle_command(uint8_t action);
65 static void hci_transport_h4_ehcill_handle_ehcill_command_sent(void);
66 static void hci_transport_h4_ehcill_handle_packet_sent(void);
67 static void hci_transport_h4_ehcill_open(void);
68 static void hci_transport_h4_ehcill_reset_statemachine(void);
69 static void hci_transport_h4_ehcill_send_ehcill_command(void);
70 static void hci_transport_h4_ehcill_sleep_ack_timer_setup(void);
71 static void hci_transport_h4_ehcill_trigger_wakeup(void);
72 
73 typedef enum {
74     EHCILL_STATE_SLEEP,
75     EHCILL_STATE_W4_ACK,
76     EHCILL_STATE_AWAKE
77 } EHCILL_STATE;
78 
79 // eHCILL state machine
80 static EHCILL_STATE ehcill_state;
81 static uint8_t      ehcill_command_to_send;
82 
83 static btstack_uart_sleep_mode_t btstack_uart_sleep_mode;
84 
85 // work around for eHCILL problem
86 static btstack_timer_source_t ehcill_sleep_ack_timer;
87 
88 #endif
89 
90 
91 // assert pre-buffer for packet type is available
92 #if !defined(HCI_OUTGOING_PRE_BUFFER_SIZE) || (HCI_OUTGOING_PRE_BUFFER_SIZE == 0)
93 #error HCI_OUTGOING_PRE_BUFFER_SIZE not defined. Please update hci.h
94 #endif
95 
96 static void dummy_handler(uint8_t packet_type, uint8_t *packet, uint16_t size);
97 
98 typedef enum {
99     H4_W4_PACKET_TYPE,
100     H4_W4_EVENT_HEADER,
101     H4_W4_ACL_HEADER,
102     H4_W4_SCO_HEADER,
103     H4_W4_PAYLOAD,
104 } H4_STATE;
105 
106 typedef enum {
107     TX_IDLE = 1,
108     TX_W4_PACKET_SENT,
109 #ifdef ENABLE_EHCILL
110     TX_W4_WAKEUP,
111     TX_W2_EHCILL_SEND,
112     TX_W4_EHCILL_SENT,
113 #endif
114 } TX_STATE;
115 
116 // UART Driver + Config
117 static const btstack_uart_block_t * btstack_uart;
118 static btstack_uart_config_t uart_config;
119 
120 // write state
121 static TX_STATE tx_state;
122 static uint8_t * tx_data;
123 static uint16_t  tx_len;   // 0 == no outgoing packet
124 
125 static uint8_t packet_sent_event[] = { HCI_EVENT_TRANSPORT_PACKET_SENT, 0};
126 
127 static  void (*packet_handler)(uint8_t packet_type, uint8_t *packet, uint16_t size) = dummy_handler;
128 
129 // packet reader state machine
130 static  H4_STATE h4_state;
131 static int bytes_to_read;
132 static int read_pos;
133 
134 // incoming packet buffer
135 static uint8_t hci_packet_with_pre_buffer[HCI_INCOMING_PRE_BUFFER_SIZE + 1 + HCI_PACKET_BUFFER_SIZE]; // packet type + max(acl header + acl payload, event header + event data)
136 static uint8_t * hci_packet = &hci_packet_with_pre_buffer[HCI_INCOMING_PRE_BUFFER_SIZE];
137 
138 static int hci_transport_h4_set_baudrate(uint32_t baudrate){
139     log_info("hci_transport_h4_set_baudrate %u", baudrate);
140     return btstack_uart->set_baudrate(baudrate);
141 }
142 
143 static void hci_transport_h4_reset_statemachine(void){
144     h4_state = H4_W4_PACKET_TYPE;
145     read_pos = 0;
146     bytes_to_read = 1;
147 }
148 
149 static void hci_transport_h4_trigger_next_read(void){
150     // log_info("hci_transport_h4_trigger_next_read: %u bytes", bytes_to_read);
151     btstack_uart->receive_block(&hci_packet[read_pos], bytes_to_read);
152 }
153 
154 static void hci_transport_h4_block_read(void){
155 
156     read_pos += bytes_to_read;
157 
158     switch (h4_state) {
159         case H4_W4_PACKET_TYPE:
160             switch (hci_packet[0]){
161                 case HCI_EVENT_PACKET:
162                     bytes_to_read = HCI_EVENT_HEADER_SIZE;
163                     h4_state = H4_W4_EVENT_HEADER;
164                     break;
165                 case HCI_ACL_DATA_PACKET:
166                     bytes_to_read = HCI_ACL_HEADER_SIZE;
167                     h4_state = H4_W4_ACL_HEADER;
168                     break;
169                 case HCI_SCO_DATA_PACKET:
170                     bytes_to_read = HCI_SCO_HEADER_SIZE;
171                     h4_state = H4_W4_SCO_HEADER;
172                     break;
173 #ifdef ENABLE_EHCILL
174                 case EHCILL_GO_TO_SLEEP_IND:
175                 case EHCILL_GO_TO_SLEEP_ACK:
176                 case EHCILL_WAKE_UP_IND:
177                 case EHCILL_WAKE_UP_ACK:
178                     hci_transport_h4_ehcill_handle_command(hci_packet[0]);
179                     hci_transport_h4_reset_statemachine();
180                     break;
181 #endif
182                 default:
183                     log_error("hci_transport_h4: invalid packet type 0x%02x", hci_packet[0]);
184                     hci_transport_h4_reset_statemachine();
185                     break;
186             }
187             break;
188 
189         case H4_W4_EVENT_HEADER:
190             bytes_to_read = hci_packet[2];
191             h4_state = H4_W4_PAYLOAD;
192             break;
193 
194         case H4_W4_ACL_HEADER:
195             bytes_to_read = little_endian_read_16( hci_packet, 3);
196             // check ACL length
197             if (HCI_ACL_HEADER_SIZE + bytes_to_read >  HCI_PACKET_BUFFER_SIZE){
198                 log_error("hci_transport_h4: invalid ACL payload len %u - only space for %u", bytes_to_read, HCI_PACKET_BUFFER_SIZE - HCI_ACL_HEADER_SIZE);
199                 hci_transport_h4_reset_statemachine();
200                 break;
201             }
202             h4_state = H4_W4_PAYLOAD;
203             break;
204 
205         case H4_W4_SCO_HEADER:
206             bytes_to_read = hci_packet[3];
207             h4_state = H4_W4_PAYLOAD;
208             break;
209 
210         case H4_W4_PAYLOAD:
211             packet_handler(hci_packet[0], &hci_packet[1], read_pos-1);
212             hci_transport_h4_reset_statemachine();
213             break;
214         default:
215             break;
216     }
217     hci_transport_h4_trigger_next_read();
218 }
219 
220 static void hci_transport_h4_block_sent(void){
221     switch (tx_state){
222         case TX_W4_PACKET_SENT:
223             // packet fully sent, reset state
224             tx_len = 0;
225             tx_state = TX_IDLE;
226 
227 #ifdef ENABLE_EHCILL
228             // notify eHCILL engine
229             hci_transport_h4_ehcill_handle_packet_sent();
230 #endif
231             // notify upper stack that it can send again
232             packet_handler(HCI_EVENT_PACKET, &packet_sent_event[0], sizeof(packet_sent_event));
233             break;
234 
235 #ifdef ENABLE_EHCILL
236         case TX_W4_EHCILL_SENT:
237             hci_transport_h4_ehcill_handle_ehcill_command_sent();
238             break;
239 #endif
240 
241         default:
242             break;
243     }
244 }
245 
246 static int hci_transport_h4_can_send_now(uint8_t packet_type){
247     return tx_state == TX_IDLE;
248 }
249 
250 static int hci_transport_h4_send_packet(uint8_t packet_type, uint8_t * packet, int size){
251     // store packet type before actual data and increase size
252     size++;
253     packet--;
254     *packet = packet_type;
255 
256     // store request
257     tx_len   = size;
258     tx_data  = packet;
259 
260 #ifdef ENABLE_EHCILL
261     if (hci_transport_h4_ehcill_sleep_mode_active()){
262         hci_transport_h4_ehcill_trigger_wakeup();
263         return 0;
264     }
265 #endif
266 
267     // start sending
268     tx_state = TX_W4_PACKET_SENT;
269     btstack_uart->send_block(packet, size);
270     return 0;
271 }
272 
273 static void hci_transport_h4_init(const void * transport_config){
274     // check for hci_transport_config_uart_t
275     if (!transport_config) {
276         log_error("hci_transport_h4: no config!");
277         return;
278     }
279     if (((hci_transport_config_t*)transport_config)->type != HCI_TRANSPORT_CONFIG_UART) {
280         log_error("hci_transport_h4: config not of type != HCI_TRANSPORT_CONFIG_UART!");
281         return;
282     }
283 
284     // extract UART config from transport config
285     hci_transport_config_uart_t * hci_transport_config_uart = (hci_transport_config_uart_t*) transport_config;
286     uart_config.baudrate    = hci_transport_config_uart->baudrate_init;
287     uart_config.flowcontrol = hci_transport_config_uart->flowcontrol;
288     uart_config.device_name = hci_transport_config_uart->device_name;
289 
290     // setup UART driver
291     btstack_uart->init(&uart_config);
292     btstack_uart->set_block_received(&hci_transport_h4_block_read);
293     btstack_uart->set_block_sent(&hci_transport_h4_block_sent);
294 }
295 
296 static int hci_transport_h4_open(void){
297     int res = btstack_uart->open();
298     if (res){
299         return res;
300     }
301     hci_transport_h4_reset_statemachine();
302     hci_transport_h4_trigger_next_read();
303 
304     tx_state = TX_IDLE;
305 
306 #ifdef ENABLE_EHCILL
307     hci_transport_h4_ehcill_open();
308 #endif
309     return 0;
310 }
311 
312 static int hci_transport_h4_close(void){
313     return btstack_uart->close();
314 }
315 
316 static void hci_transport_h4_register_packet_handler(void (*handler)(uint8_t packet_type, uint8_t *packet, uint16_t size)){
317     packet_handler = handler;
318 }
319 
320 static void dummy_handler(uint8_t packet_type, uint8_t *packet, uint16_t size){
321 }
322 
323 //
324 // --- main part of eHCILL implementation ---
325 //
326 
327 #ifdef ENABLE_EHCILL
328 
329 static void hci_transport_h4_ehcill_open(void){
330     hci_transport_h4_ehcill_reset_statemachine();
331 
332     // find best sleep mode to use: wake on CTS, wake on RX, none
333     btstack_uart_sleep_mode = BTSTACK_UART_SLEEP_OFF;
334     int supported_sleep_modes = 0;
335     if (btstack_uart->get_supported_sleep_modes){
336         supported_sleep_modes = btstack_uart->get_supported_sleep_modes();
337     }
338     if (supported_sleep_modes & BTSTACK_UART_SLEEP_MASK_RTS_HIGH_WAKE_ON_CTS_PULSE){
339         log_info("eHCILL: using wake on CTS");
340         btstack_uart_sleep_mode = BTSTACK_UART_SLEEP_RTS_HIGH_WAKE_ON_CTS_PULSE;
341     } else if (supported_sleep_modes & BTSTACK_UART_SLEEP_MASK_RTS_LOW_WAKE_ON_RX_EDGE){
342         log_info("eHCILL: using wake on RX");
343         btstack_uart_sleep_mode = BTSTACK_UART_SLEEP_RTS_LOW_WAKE_ON_RX_EDGE;
344     } else {
345         log_info("eHCILL: UART driver does not provide compatible sleep mode");
346     }
347 }
348 
349 static void hci_transport_h4_echill_send_wakeup_ind(void){
350     // update state
351     tx_state     = TX_W4_WAKEUP;
352     ehcill_state = EHCILL_STATE_W4_ACK;
353     ehcill_command_to_send = EHCILL_WAKE_UP_IND;
354     btstack_uart->send_block(&ehcill_command_to_send, 1);
355 }
356 
357 static int hci_transport_h4_ehcill_outgoing_packet_ready(void){
358     return tx_len != 0;
359 }
360 
361 static int  hci_transport_h4_ehcill_sleep_mode_active(void){
362     return ehcill_state == EHCILL_STATE_SLEEP;
363 }
364 
365 static void hci_transport_h4_ehcill_reset_statemachine(void){
366     ehcill_state = EHCILL_STATE_AWAKE;
367 }
368 
369 static void hci_transport_h4_ehcill_send_ehcill_command(void){
370     log_debug("eHCILL: send command %02x", ehcill_command_to_send);
371     tx_state = TX_W4_EHCILL_SENT;
372     btstack_uart->send_block(&ehcill_command_to_send, 1);
373 }
374 
375 static void hci_transport_h4_ehcill_sleep_ack_timer_handler(btstack_timer_source_t * timer){
376     log_debug("eHCILL: timer triggered");
377     hci_transport_h4_ehcill_send_ehcill_command();
378 }
379 
380 static void hci_transport_h4_ehcill_sleep_ack_timer_setup(void){
381     // setup timer
382     log_debug("eHCILL: set timer for sending command");
383     btstack_run_loop_set_timer_handler(&ehcill_sleep_ack_timer, &hci_transport_h4_ehcill_sleep_ack_timer_handler);
384     btstack_run_loop_set_timer(&ehcill_sleep_ack_timer, 50);
385     btstack_run_loop_add_timer(&ehcill_sleep_ack_timer);
386 }
387 
388 static void hci_transport_h4_ehcill_trigger_wakeup(void){
389     switch (tx_state){
390         case TX_W2_EHCILL_SEND:
391         case TX_W4_EHCILL_SENT:
392             // wake up / sleep ack in progress, nothing to do now
393             return;
394         case TX_IDLE:
395         default:
396             // all clear, prepare for wakeup
397             break;
398     }
399     // UART needed again
400     if (btstack_uart_sleep_mode){
401         btstack_uart->set_sleep(BTSTACK_UART_SLEEP_OFF);
402     }
403     hci_transport_h4_echill_send_wakeup_ind();
404 }
405 
406 static void hci_transport_h4_ehcill_schedule_ecill_command(uint8_t command){
407     ehcill_command_to_send = command;
408     switch (tx_state){
409         case TX_IDLE:
410             if (ehcill_command_to_send == EHCILL_WAKE_UP_ACK){
411                 // send right away
412                 hci_transport_h4_ehcill_send_ehcill_command();
413             } else {
414                 // change state so BTstack cannot send and setup timer
415                 tx_state = TX_W2_EHCILL_SEND;
416                 hci_transport_h4_ehcill_sleep_ack_timer_setup();
417             }
418             break;
419         default:
420             break;
421     }
422 }
423 
424 static void hci_transport_h4_ehcill_handle_command(uint8_t action){
425     // log_info("hci_transport_h4_ehcill_handle: %x, state %u, defer_rx %u", action, ehcill_state, ehcill_defer_rx_size);
426     switch(ehcill_state){
427         case EHCILL_STATE_AWAKE:
428             switch(action){
429                 case EHCILL_GO_TO_SLEEP_IND:
430                     ehcill_state = EHCILL_STATE_SLEEP;
431                     log_info("eHCILL: GO_TO_SLEEP_IND RX");
432                     hci_transport_h4_ehcill_schedule_ecill_command(EHCILL_GO_TO_SLEEP_ACK);
433                     break;
434                 default:
435                     break;
436             }
437             break;
438 
439         case EHCILL_STATE_SLEEP:
440             switch(action){
441                 case EHCILL_WAKE_UP_IND:
442                     ehcill_state = EHCILL_STATE_AWAKE;
443                     log_info("eHCILL: WAKE_UP_IND RX");
444                     hci_transport_h4_ehcill_schedule_ecill_command(EHCILL_WAKE_UP_ACK);
445                     break;
446 
447                 default:
448                     break;
449             }
450             break;
451 
452         case EHCILL_STATE_W4_ACK:
453             switch(action){
454                 case EHCILL_WAKE_UP_IND:
455                 case EHCILL_WAKE_UP_ACK:
456                     log_info("eHCILL: WAKE_UP_IND or ACK");
457                     tx_state = TX_W4_PACKET_SENT;
458                     ehcill_state = EHCILL_STATE_AWAKE;
459                     btstack_uart->send_block(tx_data, tx_len);
460                     break;
461                 default:
462                     break;
463             }
464             break;
465     }
466 }
467 
468 static void hci_transport_h4_ehcill_handle_packet_sent(void){
469     // now, send pending ehcill command if neccessary
470     switch (ehcill_command_to_send){
471         case EHCILL_GO_TO_SLEEP_ACK:
472             hci_transport_h4_ehcill_sleep_ack_timer_setup();
473             break;
474         case EHCILL_WAKE_UP_IND:
475             hci_transport_h4_ehcill_send_ehcill_command();
476             break;
477         default:
478             break;
479     }
480 }
481 
482 static void hci_transport_h4_ehcill_handle_ehcill_command_sent(void){
483     tx_state = TX_IDLE;
484     int command = ehcill_command_to_send;
485     ehcill_command_to_send = 0;
486     if (command == EHCILL_GO_TO_SLEEP_ACK) {
487         log_info("eHCILL: GO_TO_SLEEP_ACK sent, enter sleep mode");
488         // UART not needed after EHCILL_GO_TO_SLEEP_ACK was sent
489         if (btstack_uart_sleep_mode != BTSTACK_UART_SLEEP_OFF){
490             btstack_uart->set_sleep(btstack_uart_sleep_mode);
491         }
492     }
493     // already packet ready? then start wakeup
494     if (hci_transport_h4_ehcill_outgoing_packet_ready()){
495         if (btstack_uart_sleep_mode){
496             btstack_uart->set_sleep(BTSTACK_UART_SLEEP_OFF);
497         }
498         hci_transport_h4_echill_send_wakeup_ind();
499     }
500 }
501 
502 #endif
503 // --- end of eHCILL implementation ---------
504 
505 static const hci_transport_t hci_transport_h4 = {
506     /* const char * name; */                                        "H4",
507     /* void   (*init) (const void *transport_config); */            &hci_transport_h4_init,
508     /* int    (*open)(void); */                                     &hci_transport_h4_open,
509     /* int    (*close)(void); */                                    &hci_transport_h4_close,
510     /* void   (*register_packet_handler)(void (*handler)(...); */   &hci_transport_h4_register_packet_handler,
511     /* int    (*can_send_packet_now)(uint8_t packet_type); */       &hci_transport_h4_can_send_now,
512     /* int    (*send_packet)(...); */                               &hci_transport_h4_send_packet,
513     /* int    (*set_baudrate)(uint32_t baudrate); */                &hci_transport_h4_set_baudrate,
514     /* void   (*reset_link)(void); */                               NULL,
515 };
516 
517 // configure and return h4 singleton
518 const hci_transport_t * hci_transport_h4_instance(const btstack_uart_block_t * uart_driver) {
519     btstack_uart = uart_driver;
520     return &hci_transport_h4;
521 }
522