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 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__ "btstack_uart_posix.c"
39
40 /*
41 * btstack_uart_posix.c
42 *
43 * Common code to access serial port via asynchronous block read/write commands
44 *
45 */
46
47 #include "btstack_uart.h"
48 #include "btstack_run_loop.h"
49 #include "btstack_debug.h"
50
51 #include <termios.h> /* POSIX terminal control definitions */
52 #include <fcntl.h> /* File control definitions */
53 #include <unistd.h> /* UNIX standard function definitions */
54 #include <string.h>
55 #include <errno.h>
56 #include <stdlib.h>
57 #ifdef __APPLE__
58 #include <sys/ioctl.h>
59 #include <IOKit/serial/ioss.h>
60 #endif
61
62 // uart config
63 static const btstack_uart_config_t * uart_config;
64
65 // on macOS 12.1, CTS/RTS control flags are always read back as zero.
66 // To work around this, we cache our terios settings
67 struct termios btstack_uart_block_termios;
68
69 // data source for integration with BTstack Runloop
70 static btstack_data_source_t transport_data_source;
71
72 // block write
73 static int btstack_uart_block_write_bytes_len;
74 static const uint8_t * btstack_uart_block_write_bytes_data;
75
76 // block read
77 static uint16_t btstack_uart_block_read_bytes_len;
78 static uint8_t * btstack_uart_block_read_bytes_data;
79
80 // callbacks
81 static void (*block_sent)(void);
82 static void (*block_received)(void);
83
84
btstack_uart_posix_init(const btstack_uart_config_t * config)85 static int btstack_uart_posix_init(const btstack_uart_config_t * config){
86 uart_config = config;
87 return 0;
88 }
89
90 static void hci_uart_posix_process(btstack_data_source_t *ds, btstack_data_source_callback_type_t callback_type);
91
btstack_uart_block_posix_process_write(btstack_data_source_t * ds)92 static void btstack_uart_block_posix_process_write(btstack_data_source_t *ds) {
93
94 if (btstack_uart_block_write_bytes_len == 0) return;
95
96 uint32_t start = btstack_run_loop_get_time_ms();
97
98 // write up to write_bytes_len to fd
99 int bytes_written = (int) write(ds->source.fd, btstack_uart_block_write_bytes_data, btstack_uart_block_write_bytes_len);
100 uint32_t end = btstack_run_loop_get_time_ms();
101 if (end - start > 10){
102 log_info("write took %u ms", end - start);
103 }
104 if (bytes_written == 0){
105 log_error("wrote zero bytes\n");
106 exit(EXIT_FAILURE);
107 }
108 if (bytes_written < 0) {
109 log_error("write returned error\n");
110 btstack_run_loop_enable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_WRITE);
111 exit(EXIT_FAILURE);
112 }
113
114 btstack_uart_block_write_bytes_data += bytes_written;
115 btstack_uart_block_write_bytes_len -= bytes_written;
116
117 if (btstack_uart_block_write_bytes_len){
118 btstack_run_loop_enable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_WRITE);
119 return;
120 }
121
122 btstack_run_loop_disable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_WRITE);
123
124 // notify done
125 if (block_sent){
126 block_sent();
127 }
128 }
129
btstack_uart_block_posix_process_read(btstack_data_source_t * ds)130 static void btstack_uart_block_posix_process_read(btstack_data_source_t *ds) {
131
132 if (btstack_uart_block_read_bytes_len == 0) {
133 log_info("called but no read pending");
134 btstack_run_loop_disable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_READ);
135 }
136
137 uint32_t start = btstack_run_loop_get_time_ms();
138
139 // read up to bytes_to_read data in
140 ssize_t bytes_read = read(ds->source.fd, btstack_uart_block_read_bytes_data, btstack_uart_block_read_bytes_len);
141 // log_info("read need %u bytes, got %d", btstack_uart_block_read_bytes_len, (int) bytes_read);
142 uint32_t end = btstack_run_loop_get_time_ms();
143 if (end - start > 10){
144 log_info("read took %u ms", end - start);
145 }
146 if (bytes_read == 0){
147 log_error("read zero bytes\n");
148 return;
149 }
150 if (bytes_read < 0) {
151 log_error("read returned error\n");
152 return;
153 }
154
155 btstack_uart_block_read_bytes_len -= bytes_read;
156 btstack_uart_block_read_bytes_data += bytes_read;
157 if (btstack_uart_block_read_bytes_len > 0) return;
158
159 btstack_run_loop_disable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_READ);
160
161 if (block_received){
162 block_received();
163 }
164 }
165
btstack_uart_posix_set_baudrate(uint32_t baudrate)166 static int btstack_uart_posix_set_baudrate(uint32_t baudrate){
167
168 int fd = transport_data_source.source.fd;
169
170 log_info("h4_set_baudrate %u", baudrate);
171
172 #ifndef __APPLE__
173
174 speed_t brate = baudrate; // let you override switch below if needed
175 switch(baudrate) {
176 case 9600: brate=B9600; break;
177 case 19200: brate=B19200; break;
178 case 38400: brate=B38400; break;
179 case 57600: brate=B57600; break;
180 case 115200: brate=B115200; break;
181 #ifdef B230400
182 case 230400: brate=B230400; break;
183 #endif
184 #ifdef B460800
185 case 460800: brate=B460800; break;
186 #endif
187 #ifdef B500000
188 case 500000: brate=B500000; break;
189 #endif
190 #ifdef B576000
191 case 576000: brate=B576000; break;
192 #endif
193 #ifdef B921600
194 case 921600: brate=B921600; break;
195 #endif
196 #ifdef B1000000
197 case 1000000: brate=B1000000; break;
198 #endif
199 #ifdef B1152000
200 case 1152000: brate=B1152000; break;
201 #endif
202 #ifdef B1500000
203 case 1500000: brate=B1500000; break;
204 #endif
205 #ifdef B2000000
206 case 2000000: brate=B2000000; break;
207 #endif
208 #ifdef B2500000
209 case 2500000: brate=B2500000; break;
210 #endif
211 #ifdef B3000000
212 case 3000000: brate=B3000000; break;
213 #endif
214 #ifdef B3500000
215 case 3500000: brate=B3500000; break;
216 #endif
217 #ifdef B400000
218 case 4000000: brate=B4000000; break;
219 #endif
220 default:
221 log_error("can't set baudrate %dn", baudrate );
222 return -1;
223 }
224 cfsetospeed(&btstack_uart_block_termios, brate);
225 cfsetispeed(&btstack_uart_block_termios, brate);
226 #endif
227
228 // also set options for __APPLE__ to enforce write drain
229 // Mac OS Mojave: tcsdrain did not work as expected
230
231 if( tcsetattr(fd, TCSADRAIN, &btstack_uart_block_termios) < 0) {
232 log_error("Couldn't set term attributes");
233 return -1;
234 }
235
236 #ifdef __APPLE__
237 // From https://developer.apple.com/library/content/samplecode/SerialPortSample/Listings/SerialPortSample_SerialPortSample_c.html
238
239 // The IOSSIOSPEED ioctl can be used to set arbitrary baud rates
240 // other than those specified by POSIX. The driver for the underlying serial hardware
241 // ultimately determines which baud rates can be used. This ioctl sets both the input
242 // and output speed.
243
244 speed_t speed = baudrate;
245 if (ioctl(fd, IOSSIOSPEED, &speed) == -1) {
246 log_error("btstack_uart_posix_set_baudrate: error calling ioctl(..., IOSSIOSPEED, %u) - %s(%d).\n", baudrate, strerror(errno), errno);
247 return -1;
248 }
249 #endif
250
251 return 0;
252 }
253
btstack_uart_posix_set_parity_option(struct termios * toptions,int parity)254 static void btstack_uart_posix_set_parity_option(struct termios * toptions, int parity){
255 switch (parity){
256 case BTSTACK_UART_PARITY_OFF:
257 toptions->c_cflag &= ~PARENB;
258 toptions->c_cflag &= ~PARODD;
259 break;
260 case BTSTACK_UART_PARITY_EVEN:
261 toptions->c_cflag |= PARENB;
262 toptions->c_cflag &= ~PARODD;
263 break;
264 case BTSTACK_UART_PARITY_ODD:
265 toptions->c_cflag |= PARENB;
266 toptions->c_cflag |= PARODD;
267 default:
268 break;
269 }
270 }
271
btstack_uart_posix_set_flowcontrol_option(struct termios * toptions,int flowcontrol)272 static void btstack_uart_posix_set_flowcontrol_option(struct termios * toptions, int flowcontrol){
273 if (flowcontrol) {
274 // with flow control
275 toptions->c_cflag |= CRTSCTS;
276 } else {
277 // no flow control
278 toptions->c_cflag &= ~CRTSCTS;
279 }
280 }
281
btstack_uart_posix_set_parity(int parity)282 static int btstack_uart_posix_set_parity(int parity){
283 int fd = transport_data_source.source.fd;
284 btstack_uart_posix_set_parity_option(&btstack_uart_block_termios, parity);
285 if(tcsetattr(fd, TCSANOW, &btstack_uart_block_termios) < 0) {
286 log_error("Couldn't set term attributes");
287 return -1;
288 }
289 return 0;
290 }
291
292
btstack_uart_posix_set_flowcontrol(int flowcontrol)293 static int btstack_uart_posix_set_flowcontrol(int flowcontrol){
294 int fd = transport_data_source.source.fd;
295 btstack_uart_posix_set_flowcontrol_option(&btstack_uart_block_termios, flowcontrol);
296 if(tcsetattr(fd, TCSANOW, &btstack_uart_block_termios) < 0) {
297 log_error("Couldn't set term attributes");
298 return -1;
299 }
300 return 0;
301 }
302
btstack_uart_posix_open(void)303 static int btstack_uart_posix_open(void){
304
305 const char * device_name = uart_config->device_name;
306 const uint32_t baudrate = uart_config->baudrate;
307 const int flowcontrol = uart_config->flowcontrol;
308 const int parity = uart_config->parity;
309
310 int flags = O_RDWR | O_NOCTTY | O_NONBLOCK;
311 int fd = open(device_name, flags);
312 if (fd == -1) {
313 log_error("Unable to open port %s", device_name);
314 return -1;
315 }
316
317 if (tcgetattr(fd, &btstack_uart_block_termios) < 0) {
318 log_error("Couldn't get term attributes");
319 return -1;
320 }
321 cfmakeraw(&btstack_uart_block_termios); // make raw
322
323 // 8N1
324 btstack_uart_block_termios.c_cflag &= ~CSTOPB;
325 btstack_uart_block_termios.c_cflag |= CS8;
326
327 btstack_uart_block_termios.c_cflag |= CREAD | CLOCAL; // turn on READ & ignore ctrl lines
328 btstack_uart_block_termios.c_iflag &= ~(IXON | IXOFF | IXANY); // turn off s/w flow ctrl
329
330 // see: http://unixwiz.net/techtips/termios-vmin-vtime.html
331 btstack_uart_block_termios.c_cc[VMIN] = 1;
332 btstack_uart_block_termios.c_cc[VTIME] = 0;
333
334 // no parity
335 btstack_uart_posix_set_parity_option(&btstack_uart_block_termios, parity);
336
337 // flowcontrol
338 btstack_uart_posix_set_flowcontrol_option(&btstack_uart_block_termios, flowcontrol);
339
340 if(tcsetattr(fd, TCSANOW, &btstack_uart_block_termios) < 0) {
341 log_error("Couldn't set term attributes");
342 return -1;
343 }
344
345 // store fd in data source
346 transport_data_source.source.fd = fd;
347
348 // also set baudrate
349 if (btstack_uart_posix_set_baudrate(baudrate) < 0){
350 return -1;
351 }
352
353 // set up data_source
354 btstack_run_loop_set_data_source_fd(&transport_data_source, fd);
355 btstack_run_loop_set_data_source_handler(&transport_data_source, &hci_uart_posix_process);
356 btstack_run_loop_add_data_source(&transport_data_source);
357
358 // wait a bit - at least cheap FTDI232 clones might send the first byte out incorrectly
359 usleep(100000);
360
361 log_info("Open tty %s", device_name);
362 return 0;
363 }
364
btstack_uart_posix_close_new(void)365 static int btstack_uart_posix_close_new(void){
366
367 // first remove run loop handler
368 btstack_run_loop_remove_data_source(&transport_data_source);
369
370 // then close device
371 close(transport_data_source.source.fd);
372 transport_data_source.source.fd = -1;
373 return 0;
374 }
375
btstack_uart_posix_set_block_received(void (* block_handler)(void))376 static void btstack_uart_posix_set_block_received( void (*block_handler)(void)){
377 btstack_uart_block_read_bytes_len = 0;
378 block_received = block_handler;
379 }
380
btstack_uart_posix_set_block_sent(void (* block_handler)(void))381 static void btstack_uart_posix_set_block_sent( void (*block_handler)(void)){
382 btstack_uart_block_write_bytes_len = 0;
383 block_sent = block_handler;
384 }
385
btstack_uart_posix_send_block(const uint8_t * data,uint16_t size)386 static void btstack_uart_posix_send_block(const uint8_t *data, uint16_t size){
387 btstack_assert(btstack_uart_block_write_bytes_len == 0);
388
389 // setup async write
390 btstack_uart_block_write_bytes_data = data;
391 btstack_uart_block_write_bytes_len = size;
392 btstack_run_loop_enable_data_source_callbacks(&transport_data_source, DATA_SOURCE_CALLBACK_WRITE);
393 }
394
btstack_uart_posix_receive_block(uint8_t * buffer,uint16_t len)395 static void btstack_uart_posix_receive_block(uint8_t *buffer, uint16_t len){
396 btstack_assert(btstack_uart_block_read_bytes_len == 0);
397
398 // setup async read
399 btstack_uart_block_read_bytes_data = buffer;
400 btstack_uart_block_read_bytes_len = len;
401 btstack_run_loop_enable_data_source_callbacks(&transport_data_source, DATA_SOURCE_CALLBACK_READ);
402 }
403
404 #ifdef ENABLE_H5
405
406 // SLIP Implementation Start
407 #include "btstack_slip.h"
408
409 // max size of outgoing SLIP chunks
410 #define SLIP_TX_CHUNK_LEN 128
411
412 #define SLIP_RECEIVE_BUFFER_SIZE 128
413
414 // encoded SLIP chunk
415 static uint8_t btstack_uart_slip_outgoing_buffer[SLIP_TX_CHUNK_LEN+1];
416
417 // block write
418 static int btstack_uart_slip_write_bytes_len;
419 static const uint8_t * btstack_uart_slip_write_bytes_data;
420 static int btstack_uart_slip_write_active;
421
422 // block read
423 static uint8_t btstack_uart_slip_receive_buffer[SLIP_RECEIVE_BUFFER_SIZE];
424 static uint16_t btstack_uart_slip_receive_pos;
425 static uint16_t btstack_uart_slip_receive_len;
426 static uint8_t btstack_uart_slip_receive_track_start;
427 static uint32_t btstack_uart_slip_receive_start_time;
428 static int btstack_uart_slip_receive_active;
429
430 // callbacks
431 static void (*frame_sent)(void);
432 static void (*frame_received)(uint16_t frame_size);
433
434 static void btstack_uart_slip_posix_block_sent(void);
435
btstack_uart_slip_posix_process_write(btstack_data_source_t * ds)436 static void btstack_uart_slip_posix_process_write(btstack_data_source_t *ds) {
437
438 if (btstack_uart_slip_write_bytes_len == 0) return;
439
440 uint32_t start = btstack_run_loop_get_time_ms();
441
442 // write up to btstack_uart_slip_write_bytes_len to fd
443 int bytes_written = (int) write(ds->source.fd, btstack_uart_slip_write_bytes_data, btstack_uart_slip_write_bytes_len);
444 if (bytes_written < 0) {
445 btstack_run_loop_enable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_WRITE);
446 return;
447 }
448
449 uint32_t end = btstack_run_loop_get_time_ms();
450 if (end - start > 10){
451 log_info("write took %u ms", end - start);
452 }
453
454 btstack_uart_slip_write_bytes_data += bytes_written;
455 btstack_uart_slip_write_bytes_len -= bytes_written;
456
457 if (btstack_uart_slip_write_bytes_len){
458 btstack_run_loop_enable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_WRITE);
459 return;
460 }
461
462 btstack_run_loop_disable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_WRITE);
463
464 // done with TX chunk
465 btstack_uart_slip_posix_block_sent();
466 }
467
468 // @returns frame size if complete frame decoded and delivered
btstack_uart_slip_posix_process_buffer(void)469 static uint16_t btstack_uart_slip_posix_process_buffer(void){
470 log_debug("process buffer: pos %u, len %u", btstack_uart_slip_receive_pos, btstack_uart_slip_receive_len);
471
472 uint16_t frame_size = 0;
473 while (btstack_uart_slip_receive_pos < btstack_uart_slip_receive_len && frame_size == 0){
474 btstack_slip_decoder_process(btstack_uart_slip_receive_buffer[btstack_uart_slip_receive_pos++]);
475 frame_size = btstack_slip_decoder_frame_size();
476 }
477
478 // reset buffer if fully processed
479 if (btstack_uart_slip_receive_pos == btstack_uart_slip_receive_len ){
480 btstack_uart_slip_receive_len = 0;
481 btstack_uart_slip_receive_pos = 0;
482 }
483
484 // deliver frame if frame complete
485 if (frame_size) {
486
487 // receive done
488 btstack_uart_slip_receive_active = 0;
489
490 // only print if read was involved
491 if (btstack_uart_slip_receive_track_start == 0){
492 log_info("frame receive time %u ms", btstack_run_loop_get_time_ms() - btstack_uart_slip_receive_start_time);
493 btstack_uart_slip_receive_start_time = 0;
494 }
495
496 (*frame_received)(frame_size);
497 }
498
499 return frame_size;
500 }
501
btstack_uart_slip_posix_process_read(btstack_data_source_t * ds)502 static void btstack_uart_slip_posix_process_read(btstack_data_source_t *ds) {
503
504 uint32_t start = btstack_run_loop_get_time_ms();
505
506 if (btstack_uart_slip_receive_track_start){
507 btstack_uart_slip_receive_track_start = 0;
508 btstack_uart_slip_receive_start_time = start;
509 }
510
511 // read up to bytes_to_read data in
512 ssize_t bytes_read = read(ds->source.fd, btstack_uart_slip_receive_buffer, SLIP_RECEIVE_BUFFER_SIZE);
513
514 log_debug("requested %u bytes, got %d", SLIP_RECEIVE_BUFFER_SIZE, (int) bytes_read);
515 uint32_t end = btstack_run_loop_get_time_ms();
516 if (end - start > 10){
517 log_info("read took %u ms", end - start);
518 }
519 if (bytes_read < 0) return;
520
521 btstack_uart_slip_receive_pos = 0;
522 btstack_uart_slip_receive_len = (uint16_t ) bytes_read;
523
524 btstack_uart_slip_posix_process_buffer();
525 }
526
527 // -----------------------------
528 // SLIP ENCODING
529
btstack_uart_slip_posix_encode_chunk_and_send(void)530 static void btstack_uart_slip_posix_encode_chunk_and_send(void){
531 uint16_t pos = 0;
532 while (btstack_slip_encoder_has_data() & (pos < SLIP_TX_CHUNK_LEN)) {
533 btstack_uart_slip_outgoing_buffer[pos++] = btstack_slip_encoder_get_byte();
534 }
535
536 // setup async write and start sending
537 log_debug("slip: send %d bytes", pos);
538 btstack_uart_slip_write_bytes_data = btstack_uart_slip_outgoing_buffer;
539 btstack_uart_slip_write_bytes_len = pos;
540 btstack_run_loop_enable_data_source_callbacks(&transport_data_source, DATA_SOURCE_CALLBACK_WRITE);
541 }
542
btstack_uart_slip_posix_block_sent(void)543 static void btstack_uart_slip_posix_block_sent(void){
544 // check if more data to send
545 if (btstack_slip_encoder_has_data()){
546 btstack_uart_slip_posix_encode_chunk_and_send();
547 return;
548 }
549
550 // write done
551 btstack_uart_slip_write_active = 0;
552
553 // notify done
554 if (frame_sent){
555 frame_sent();
556 }
557 }
558
btstack_uart_slip_posix_send_frame(const uint8_t * frame,uint16_t frame_size)559 static void btstack_uart_slip_posix_send_frame(const uint8_t * frame, uint16_t frame_size){
560
561 // write started
562 btstack_uart_slip_write_active = 1;
563
564 // Prepare encoding of Header + Packet (+ DIC)
565 btstack_slip_encoder_start(frame, frame_size);
566
567 // Fill rest of chunk from packet and send
568 btstack_uart_slip_posix_encode_chunk_and_send();
569 }
570
571 // SLIP ENCODING
572 // -----------------------------
573
btstack_uart_slip_posix_receive_frame(uint8_t * buffer,uint16_t len)574 static void btstack_uart_slip_posix_receive_frame(uint8_t *buffer, uint16_t len){
575
576 // receive started
577 btstack_uart_slip_receive_active = 1;
578
579 log_debug("receive block, size %u", len);
580 btstack_uart_slip_receive_track_start = 1;
581
582 // setup SLIP decoder
583 btstack_slip_decoder_init(buffer, len);
584
585 // process bytes received in earlier read. might deliver packet, which in turn will call us again.
586 // just make sure to exit right away
587 if (btstack_uart_slip_receive_len){
588 int frame_found = btstack_uart_slip_posix_process_buffer();
589 if (frame_found) return;
590 }
591
592 // no frame delivered, enable posix read
593 btstack_run_loop_enable_data_source_callbacks(&transport_data_source, DATA_SOURCE_CALLBACK_READ);
594 }
595
596
597
btstack_uart_slip_posix_set_frame_received(void (* block_handler)(uint16_t frame_size))598 static void btstack_uart_slip_posix_set_frame_received( void (*block_handler)(uint16_t frame_size)){
599 frame_received = block_handler;
600 }
601
btstack_uart_slip_posix_set_frame_sent(void (* block_handler)(void))602 static void btstack_uart_slip_posix_set_frame_sent( void (*block_handler)(void)){
603 frame_sent = block_handler;
604 }
605
606 // SLIP Implementation End
607 #endif
608
609 // dispatch into block or SLIP code
hci_uart_posix_process(btstack_data_source_t * ds,btstack_data_source_callback_type_t callback_type)610 static void hci_uart_posix_process(btstack_data_source_t *ds, btstack_data_source_callback_type_t callback_type) {
611 if (ds->source.fd < 0) return;
612 switch (callback_type){
613 case DATA_SOURCE_CALLBACK_READ:
614 #ifdef ENABLE_H5
615 if (btstack_uart_slip_receive_active){
616 btstack_uart_slip_posix_process_read(ds);
617 } else
618 #endif
619 {
620 btstack_uart_block_posix_process_read(ds);
621 }
622 break;
623 case DATA_SOURCE_CALLBACK_WRITE:
624 #ifdef ENABLE_H5
625 if (btstack_uart_slip_write_active){
626 btstack_uart_slip_posix_process_write(ds);
627 } else
628 #endif
629 {
630 btstack_uart_block_posix_process_write(ds);
631 }
632 break;
633 default:
634 break;
635 }
636 }
637
638 static const btstack_uart_t btstack_uart_posix = {
639 /* int (*init)(hci_transport_config_uart_t * config); */ &btstack_uart_posix_init,
640 /* int (*open)(void); */ &btstack_uart_posix_open,
641 /* int (*close)(void); */ &btstack_uart_posix_close_new,
642 /* void (*set_block_received)(void (*handler)(void)); */ &btstack_uart_posix_set_block_received,
643 /* void (*set_block_sent)(void (*handler)(void)); */ &btstack_uart_posix_set_block_sent,
644 /* int (*set_baudrate)(uint32_t baudrate); */ &btstack_uart_posix_set_baudrate,
645 /* int (*set_parity)(int parity); */ &btstack_uart_posix_set_parity,
646 /* int (*set_flowcontrol)(int flowcontrol); */ &btstack_uart_posix_set_flowcontrol,
647 /* void (*receive_block)(uint8_t *buffer, uint16_t len); */ &btstack_uart_posix_receive_block,
648 /* void (*send_block)(const uint8_t *buffer, uint16_t length); */ &btstack_uart_posix_send_block,
649 /* int (*get_supported_sleep_modes); */ NULL,
650 /* void (*set_sleep)(btstack_uart_sleep_mode_t sleep_mode); */ NULL,
651 /* void (*set_wakeup_handler)(void (*handler)(void)); */ NULL,
652
653 #ifdef ENABLE_H5
654 /* void (*set_frame_received)(void (*handler)(uint16_t frame_size); */ &btstack_uart_slip_posix_set_frame_received,
655 /* void (*set_fraae_sent)(void (*handler)(void)); */ &btstack_uart_slip_posix_set_frame_sent,
656 /* void (*receive_frame)(uint8_t *buffer, uint16_t len); */ &btstack_uart_slip_posix_receive_frame,
657 /* void (*send_frame)(const uint8_t *buffer, uint16_t length); */ &btstack_uart_slip_posix_send_frame,
658 #else
659 NULL, NULL, NULL, NULL,
660 #endif
661 };
662
btstack_uart_posix_instance(void)663 const btstack_uart_t * btstack_uart_posix_instance(void){
664 return &btstack_uart_posix;
665 }
666