diff --git a/platform/posix/stdin_support.c b/platform/posix/stdin_support.c index 57c9d2743..d1047c083 100644 --- a/platform/posix/stdin_support.c +++ b/platform/posix/stdin_support.c @@ -44,52 +44,34 @@ #include "stdin_support.h" -#ifndef _WIN32 +// From MSDN: +// __WIN32 Defined as 1 when the compilation target is 32-bit ARM, 64-bit ARM, x86, or x64. +// Otherwise, undefined. + +#ifdef _WIN32 +#include +#include //provides non standard getch() function +#include +#else #include #endif static btstack_data_source_t stdin_source; static int activated = 0; -void btstack_stdin_setup(void (*stdin_process)(btstack_data_source_t *_ds, btstack_data_source_callback_type_t callback_type)){ +#ifdef _WIN32 +static HANDLE stdin_reader_thread_handle; +static char key_read_buffer; +static HANDLE key_processed_handle; -#ifndef _WIN32 - struct termios term = {0}; - if (tcgetattr(0, &term) < 0) - perror("tcsetattr()"); - term.c_lflag &= ~ICANON; - term.c_lflag &= ~ECHO; - if (tcsetattr(0, TCSANOW, &term) < 0) { - perror("tcsetattr ICANON"); +static WINAPI DWORD stdin_reader_thread_process(void * p){ + while (1){ + key_read_buffer = getch(); + SignalObjectAndWait(stdin_source.handle , key_processed_handle, INFINITE, FALSE); } -#endif - - btstack_run_loop_set_data_source_fd(&stdin_source, 0); // stdin - btstack_run_loop_set_data_source_handler(&stdin_source, stdin_process); - btstack_run_loop_enable_data_source_callbacks(&stdin_source, DATA_SOURCE_CALLBACK_READ); - btstack_run_loop_add_data_source(&stdin_source); - - activated = 1; + return 0; } - -void btstack_stdin_reset(void){ - if (!activated) return; - activated = 0; - - btstack_run_loop_remove_data_source(&stdin_source); - -#ifndef _WIN32 - struct termios term = {0}; - if (tcgetattr(0, &term) < 0){ - perror("tcsetattr()"); - } - term.c_lflag |= ICANON; - term.c_lflag |= ECHO; - if (tcsetattr(0, TCSANOW, &term) < 0){ - perror("tcsetattr ICANON"); - } #endif -} #if 0 static int getstring(char *line, int size) @@ -114,10 +96,87 @@ static int getstring(char *line, int size) } #endif -// read single byte after data source callback was triggered -char btstack_stdin_read(void){ - char buffer; - read(stdin_source.fd, &buffer, 1); - return buffer; +void btstack_stdin_setup(void (*stdin_process)(btstack_data_source_t *_ds, btstack_data_source_callback_type_t callback_type)){ + + if (activated) return; + +#ifdef _WIN32 + + // asynchronous io on stdin via OVERLAPPED seems to be problematic. + + // Use separate thread and event objects instead + stdin_source.handle = CreateEvent(NULL, FALSE, FALSE, NULL); + key_processed_handle = CreateEvent(NULL, FALSE, FALSE, NULL); + // default attributes, default stack size, proc, args, start immediately, don't care for thread id + stdin_reader_thread_handle = CreateThread(NULL, 0, &stdin_reader_thread_process, NULL, 0, NULL); + +#else + // disable line buffering + struct termios term = {0}; + if (tcgetattr(0, &term) < 0) + perror("tcsetattr()"); + term.c_lflag &= ~ICANON; + term.c_lflag &= ~ECHO; + if (tcsetattr(0, TCSANOW, &term) < 0) { + perror("tcsetattr ICANON"); + } + + btstack_run_loop_set_data_source_fd(&stdin_source, 0); // stdin +#endif + + btstack_run_loop_enable_data_source_callbacks(&stdin_source, DATA_SOURCE_CALLBACK_READ); + btstack_run_loop_set_data_source_handler(&stdin_source, stdin_process); + btstack_run_loop_add_data_source(&stdin_source); + + activated = 1; +} + +void btstack_stdin_reset(void){ + if (!activated) return; + activated = 0; + + btstack_run_loop_remove_data_source(&stdin_source); + +#ifdef _WIN32 + // shutdown thread + TerminateThread(stdin_reader_thread_handle, 0); + WaitForSingleObject(stdin_reader_thread_handle, INFINITE); + CloseHandle(stdin_reader_thread_handle); + + // free events + CloseHandle(stdin_source.handle); + CloseHandle(key_processed_handle); +#else + struct termios term = {0}; + if (tcgetattr(0, &term) < 0){ + perror("tcsetattr()"); + } + term.c_lflag |= ICANON; + term.c_lflag |= ECHO; + if (tcsetattr(0, TCSANOW, &term) < 0){ + perror("tcsetattr ICANON"); + } +#endif +} + +// read single byte after data source callback was triggered +char btstack_stdin_read(void){ + char data; +#ifdef _WIN32 + + // raise SIGINT for CTRL-c on main thread + if (key_read_buffer == 0x03){ + raise(SIGINT); + return 0; + } + + data = key_read_buffer; + SetEvent(key_processed_handle); + +#else + read(stdin_source.fd, &data, 1); +#endif + + return data; }