17ea7688aSMatthias Ringwald /* 27ea7688aSMatthias Ringwald * Copyright (C) 2014 BlueKitchen GmbH 37ea7688aSMatthias Ringwald * 47ea7688aSMatthias Ringwald * Redistribution and use in source and binary forms, with or without 57ea7688aSMatthias Ringwald * modification, are permitted provided that the following conditions 67ea7688aSMatthias Ringwald * are met: 77ea7688aSMatthias Ringwald * 87ea7688aSMatthias Ringwald * 1. Redistributions of source code must retain the above copyright 97ea7688aSMatthias Ringwald * notice, this list of conditions and the following disclaimer. 107ea7688aSMatthias Ringwald * 2. Redistributions in binary form must reproduce the above copyright 117ea7688aSMatthias Ringwald * notice, this list of conditions and the following disclaimer in the 127ea7688aSMatthias Ringwald * documentation and/or other materials provided with the distribution. 137ea7688aSMatthias Ringwald * 3. Neither the name of the copyright holders nor the names of 147ea7688aSMatthias Ringwald * contributors may be used to endorse or promote products derived 157ea7688aSMatthias Ringwald * from this software without specific prior written permission. 167ea7688aSMatthias Ringwald * 4. Any redistribution, use, or modification is done solely for 177ea7688aSMatthias Ringwald * personal benefit and not for any commercial purpose or for 187ea7688aSMatthias Ringwald * monetary gain. 197ea7688aSMatthias Ringwald * 207ea7688aSMatthias Ringwald * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS 217ea7688aSMatthias Ringwald * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 227ea7688aSMatthias Ringwald * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 232fca4dadSMilanka Ringwald * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN 242fca4dadSMilanka Ringwald * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 257ea7688aSMatthias Ringwald * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 267ea7688aSMatthias Ringwald * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 277ea7688aSMatthias Ringwald * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 287ea7688aSMatthias Ringwald * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 297ea7688aSMatthias Ringwald * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 307ea7688aSMatthias Ringwald * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 317ea7688aSMatthias Ringwald * SUCH DAMAGE. 327ea7688aSMatthias Ringwald * 337ea7688aSMatthias Ringwald * Please inquire about commercial licensing options at 347ea7688aSMatthias Ringwald * [email protected] 357ea7688aSMatthias Ringwald * 367ea7688aSMatthias Ringwald */ 377ea7688aSMatthias Ringwald 38e501bae0SMatthias Ringwald #define BTSTACK_FILE__ "btstack_stdin_windows.c" 397ea7688aSMatthias Ringwald 407ea7688aSMatthias Ringwald #include <errno.h> 417ea7688aSMatthias Ringwald #include <stdio.h> 427ea7688aSMatthias Ringwald 437ea7688aSMatthias Ringwald #include "btstack_run_loop.h" 4495a8ee01SMatthias Ringwald #include "btstack_defines.h" 457ea7688aSMatthias Ringwald #include <stdlib.h> 467ea7688aSMatthias Ringwald 477ea7688aSMatthias Ringwald #include "btstack_stdin.h" 48de9c9f72SMatthias Ringwald #include "btstack_stdin_windows.h" 497ea7688aSMatthias Ringwald 507ea7688aSMatthias Ringwald // From MSDN: 517ea7688aSMatthias Ringwald // __WIN32 Defined as 1 when the compilation target is 32-bit ARM, 64-bit ARM, x86, or x64. 527ea7688aSMatthias Ringwald // Otherwise, undefined. 537ea7688aSMatthias Ringwald 547ea7688aSMatthias Ringwald #include <Windows.h> 557ea7688aSMatthias Ringwald #include <conio.h> //provides non standard getch() function 567ea7688aSMatthias Ringwald #include <signal.h> 577ea7688aSMatthias Ringwald 587ea7688aSMatthias Ringwald static btstack_data_source_t stdin_source; 597ea7688aSMatthias Ringwald static int activated = 0; 607ea7688aSMatthias Ringwald 617ea7688aSMatthias Ringwald static HANDLE stdin_reader_thread_handle; 627ea7688aSMatthias Ringwald static char key_read_buffer; 637ea7688aSMatthias Ringwald static HANDLE key_processed_handle; 6495a8ee01SMatthias Ringwald static void (*stdin_handler)(char c); 65de9c9f72SMatthias Ringwald static void (*ctrl_c_handler)(void); 667ea7688aSMatthias Ringwald 67*45996a73SMatthias Ringwald static DWORD WINAPI stdin_reader_thread_process(void * p){ 68ff3cc4a5SMatthias Ringwald while (true){ 69*45996a73SMatthias Ringwald key_read_buffer = _getch(); 70398a95ecSMatthias Ringwald SignalObjectAndWait(stdin_source.source.handle, key_processed_handle, INFINITE, FALSE); 717ea7688aSMatthias Ringwald } 727ea7688aSMatthias Ringwald return 0; 737ea7688aSMatthias Ringwald } 747ea7688aSMatthias Ringwald 7595a8ee01SMatthias Ringwald static void stdin_process(btstack_data_source_t *ds, btstack_data_source_callback_type_t callback_type){ 7695a8ee01SMatthias Ringwald 77de9c9f72SMatthias Ringwald // handle CTRL-C 7895a8ee01SMatthias Ringwald if (key_read_buffer == 0x03){ 79de9c9f72SMatthias Ringwald if (ctrl_c_handler != NULL){ 80de9c9f72SMatthias Ringwald (*ctrl_c_handler)(); 81de9c9f72SMatthias Ringwald } else { 82de9c9f72SMatthias Ringwald printf("Ignore CTRL-c\n"); 8395a8ee01SMatthias Ringwald } 84de9c9f72SMatthias Ringwald } else { 8595a8ee01SMatthias Ringwald if (stdin_handler){ 8695a8ee01SMatthias Ringwald (*stdin_handler)(key_read_buffer); 8795a8ee01SMatthias Ringwald } 8895a8ee01SMatthias Ringwald } 8995a8ee01SMatthias Ringwald 90de9c9f72SMatthias Ringwald SetEvent(key_processed_handle); 91de9c9f72SMatthias Ringwald } 927ea7688aSMatthias Ringwald 93de9c9f72SMatthias Ringwald void btstack_stdin_windows_init(void){ 947ea7688aSMatthias Ringwald if (activated) return; 957ea7688aSMatthias Ringwald 967ea7688aSMatthias Ringwald // asynchronous io on stdin via OVERLAPPED seems to be problematic. 977ea7688aSMatthias Ringwald 987ea7688aSMatthias Ringwald // Use separate thread and event objects instead 99398a95ecSMatthias Ringwald stdin_source.source.handle = CreateEvent(NULL, FALSE, FALSE, NULL); 1007ea7688aSMatthias Ringwald key_processed_handle = CreateEvent(NULL, FALSE, FALSE, NULL); 1017ea7688aSMatthias Ringwald // default attributes, default stack size, proc, args, start immediately, don't care for thread id 1027ea7688aSMatthias Ringwald stdin_reader_thread_handle = CreateThread(NULL, 0, &stdin_reader_thread_process, NULL, 0, NULL); 1037ea7688aSMatthias Ringwald 1047ea7688aSMatthias Ringwald btstack_run_loop_enable_data_source_callbacks(&stdin_source, DATA_SOURCE_CALLBACK_READ); 1057ea7688aSMatthias Ringwald btstack_run_loop_set_data_source_handler(&stdin_source, stdin_process); 1067ea7688aSMatthias Ringwald btstack_run_loop_add_data_source(&stdin_source); 1077ea7688aSMatthias Ringwald 1087ea7688aSMatthias Ringwald activated = 1; 1097ea7688aSMatthias Ringwald } 1107ea7688aSMatthias Ringwald 111de9c9f72SMatthias Ringwald void btstack_stdin_window_register_ctrl_c_callback(void (*callback)(void)){ 112de9c9f72SMatthias Ringwald ctrl_c_handler = callback; 113de9c9f72SMatthias Ringwald } 114de9c9f72SMatthias Ringwald 115de9c9f72SMatthias Ringwald void btstack_stdin_setup(void (*handler)(char c)){ 116de9c9f72SMatthias Ringwald btstack_stdin_windows_init(); 117de9c9f72SMatthias Ringwald stdin_handler = handler; 118de9c9f72SMatthias Ringwald } 119de9c9f72SMatthias Ringwald 1207ea7688aSMatthias Ringwald void btstack_stdin_reset(void){ 1217ea7688aSMatthias Ringwald if (!activated) return; 1227ea7688aSMatthias Ringwald activated = 0; 12395a8ee01SMatthias Ringwald stdin_handler = NULL; 1247ea7688aSMatthias Ringwald 1257ea7688aSMatthias Ringwald btstack_run_loop_remove_data_source(&stdin_source); 1267ea7688aSMatthias Ringwald 1277ea7688aSMatthias Ringwald // shutdown thread 1287ea7688aSMatthias Ringwald TerminateThread(stdin_reader_thread_handle, 0); 1297ea7688aSMatthias Ringwald WaitForSingleObject(stdin_reader_thread_handle, INFINITE); 1307ea7688aSMatthias Ringwald CloseHandle(stdin_reader_thread_handle); 1317ea7688aSMatthias Ringwald 1327ea7688aSMatthias Ringwald // free events 133398a95ecSMatthias Ringwald CloseHandle(stdin_source.source.handle); 1347ea7688aSMatthias Ringwald CloseHandle(key_processed_handle); 1357ea7688aSMatthias Ringwald } 1367ea7688aSMatthias Ringwald 137