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 237ea7688aSMatthias Ringwald * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS 247ea7688aSMatthias Ringwald * RINGWALD 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" 487ea7688aSMatthias Ringwald 497ea7688aSMatthias Ringwald // From MSDN: 507ea7688aSMatthias Ringwald // __WIN32 Defined as 1 when the compilation target is 32-bit ARM, 64-bit ARM, x86, or x64. 517ea7688aSMatthias Ringwald // Otherwise, undefined. 527ea7688aSMatthias Ringwald 537ea7688aSMatthias Ringwald #include <Windows.h> 547ea7688aSMatthias Ringwald #include <conio.h> //provides non standard getch() function 557ea7688aSMatthias Ringwald #include <signal.h> 567ea7688aSMatthias Ringwald 577ea7688aSMatthias Ringwald static btstack_data_source_t stdin_source; 587ea7688aSMatthias Ringwald static int activated = 0; 597ea7688aSMatthias Ringwald 607ea7688aSMatthias Ringwald static HANDLE stdin_reader_thread_handle; 617ea7688aSMatthias Ringwald static char key_read_buffer; 627ea7688aSMatthias Ringwald static HANDLE key_processed_handle; 6395a8ee01SMatthias Ringwald static void (*stdin_handler)(char c); 647ea7688aSMatthias Ringwald 657ea7688aSMatthias Ringwald static WINAPI DWORD stdin_reader_thread_process(void * p){ 66*ff3cc4a5SMatthias Ringwald while (true){ 677ea7688aSMatthias Ringwald key_read_buffer = getch(); 68398a95ecSMatthias Ringwald SignalObjectAndWait(stdin_source.source.handle, key_processed_handle, INFINITE, FALSE); 697ea7688aSMatthias Ringwald } 707ea7688aSMatthias Ringwald return 0; 717ea7688aSMatthias Ringwald } 727ea7688aSMatthias Ringwald 7395a8ee01SMatthias Ringwald static void stdin_process(btstack_data_source_t *ds, btstack_data_source_callback_type_t callback_type){ 7495a8ee01SMatthias Ringwald 7595a8ee01SMatthias Ringwald // raise SIGINT for CTRL-c on main thread 7695a8ee01SMatthias Ringwald if (key_read_buffer == 0x03){ 7795a8ee01SMatthias Ringwald raise(SIGINT); 7895a8ee01SMatthias Ringwald return; 7995a8ee01SMatthias Ringwald } 8095a8ee01SMatthias Ringwald 8195a8ee01SMatthias Ringwald SetEvent(key_processed_handle); 8295a8ee01SMatthias Ringwald 8395a8ee01SMatthias Ringwald if (stdin_handler){ 8495a8ee01SMatthias Ringwald (*stdin_handler)(key_read_buffer); 8595a8ee01SMatthias Ringwald } 8695a8ee01SMatthias Ringwald } 8795a8ee01SMatthias Ringwald 8895a8ee01SMatthias Ringwald void btstack_stdin_setup(void (*handler)(char c)){ 897ea7688aSMatthias Ringwald 907ea7688aSMatthias Ringwald if (activated) return; 917ea7688aSMatthias Ringwald 9295a8ee01SMatthias Ringwald 9395a8ee01SMatthias Ringwald stdin_handler = handler; 9495a8ee01SMatthias Ringwald 957ea7688aSMatthias Ringwald // asynchronous io on stdin via OVERLAPPED seems to be problematic. 967ea7688aSMatthias Ringwald 977ea7688aSMatthias Ringwald // Use separate thread and event objects instead 98398a95ecSMatthias Ringwald stdin_source.source.handle = CreateEvent(NULL, FALSE, FALSE, NULL); 997ea7688aSMatthias Ringwald key_processed_handle = CreateEvent(NULL, FALSE, FALSE, NULL); 1007ea7688aSMatthias Ringwald // default attributes, default stack size, proc, args, start immediately, don't care for thread id 1017ea7688aSMatthias Ringwald stdin_reader_thread_handle = CreateThread(NULL, 0, &stdin_reader_thread_process, NULL, 0, NULL); 1027ea7688aSMatthias Ringwald 1037ea7688aSMatthias Ringwald btstack_run_loop_enable_data_source_callbacks(&stdin_source, DATA_SOURCE_CALLBACK_READ); 1047ea7688aSMatthias Ringwald btstack_run_loop_set_data_source_handler(&stdin_source, stdin_process); 1057ea7688aSMatthias Ringwald btstack_run_loop_add_data_source(&stdin_source); 1067ea7688aSMatthias Ringwald 1077ea7688aSMatthias Ringwald activated = 1; 1087ea7688aSMatthias Ringwald } 1097ea7688aSMatthias Ringwald 1107ea7688aSMatthias Ringwald void btstack_stdin_reset(void){ 1117ea7688aSMatthias Ringwald if (!activated) return; 1127ea7688aSMatthias Ringwald activated = 0; 11395a8ee01SMatthias Ringwald stdin_handler = NULL; 1147ea7688aSMatthias Ringwald 1157ea7688aSMatthias Ringwald btstack_run_loop_remove_data_source(&stdin_source); 1167ea7688aSMatthias Ringwald 1177ea7688aSMatthias Ringwald // shutdown thread 1187ea7688aSMatthias Ringwald TerminateThread(stdin_reader_thread_handle, 0); 1197ea7688aSMatthias Ringwald WaitForSingleObject(stdin_reader_thread_handle, INFINITE); 1207ea7688aSMatthias Ringwald CloseHandle(stdin_reader_thread_handle); 1217ea7688aSMatthias Ringwald 1227ea7688aSMatthias Ringwald // free events 123398a95ecSMatthias Ringwald CloseHandle(stdin_source.source.handle); 1247ea7688aSMatthias Ringwald CloseHandle(key_processed_handle); 1257ea7688aSMatthias Ringwald } 1267ea7688aSMatthias Ringwald 127