1*7ea7688aSMatthias Ringwald /* 2*7ea7688aSMatthias Ringwald * Copyright (C) 2014 BlueKitchen GmbH 3*7ea7688aSMatthias Ringwald * 4*7ea7688aSMatthias Ringwald * Redistribution and use in source and binary forms, with or without 5*7ea7688aSMatthias Ringwald * modification, are permitted provided that the following conditions 6*7ea7688aSMatthias Ringwald * are met: 7*7ea7688aSMatthias Ringwald * 8*7ea7688aSMatthias Ringwald * 1. Redistributions of source code must retain the above copyright 9*7ea7688aSMatthias Ringwald * notice, this list of conditions and the following disclaimer. 10*7ea7688aSMatthias Ringwald * 2. Redistributions in binary form must reproduce the above copyright 11*7ea7688aSMatthias Ringwald * notice, this list of conditions and the following disclaimer in the 12*7ea7688aSMatthias Ringwald * documentation and/or other materials provided with the distribution. 13*7ea7688aSMatthias Ringwald * 3. Neither the name of the copyright holders nor the names of 14*7ea7688aSMatthias Ringwald * contributors may be used to endorse or promote products derived 15*7ea7688aSMatthias Ringwald * from this software without specific prior written permission. 16*7ea7688aSMatthias Ringwald * 4. Any redistribution, use, or modification is done solely for 17*7ea7688aSMatthias Ringwald * personal benefit and not for any commercial purpose or for 18*7ea7688aSMatthias Ringwald * monetary gain. 19*7ea7688aSMatthias Ringwald * 20*7ea7688aSMatthias Ringwald * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS 21*7ea7688aSMatthias Ringwald * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22*7ea7688aSMatthias Ringwald * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23*7ea7688aSMatthias Ringwald * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS 24*7ea7688aSMatthias Ringwald * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25*7ea7688aSMatthias Ringwald * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 26*7ea7688aSMatthias Ringwald * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 27*7ea7688aSMatthias Ringwald * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 28*7ea7688aSMatthias Ringwald * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29*7ea7688aSMatthias Ringwald * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 30*7ea7688aSMatthias Ringwald * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31*7ea7688aSMatthias Ringwald * SUCH DAMAGE. 32*7ea7688aSMatthias Ringwald * 33*7ea7688aSMatthias Ringwald * Please inquire about commercial licensing options at 34*7ea7688aSMatthias Ringwald * [email protected] 35*7ea7688aSMatthias Ringwald * 36*7ea7688aSMatthias Ringwald */ 37*7ea7688aSMatthias Ringwald 38*7ea7688aSMatthias Ringwald #define __BTSTACK_FILE__ "btstack_stdin_windows.c" 39*7ea7688aSMatthias Ringwald 40*7ea7688aSMatthias Ringwald #include <errno.h> 41*7ea7688aSMatthias Ringwald #include <stdio.h> 42*7ea7688aSMatthias Ringwald #include <unistd.h> 43*7ea7688aSMatthias Ringwald 44*7ea7688aSMatthias Ringwald #include "btstack_run_loop.h" 45*7ea7688aSMatthias Ringwald #include <stdlib.h> 46*7ea7688aSMatthias Ringwald 47*7ea7688aSMatthias Ringwald #include "btstack_stdin.h" 48*7ea7688aSMatthias Ringwald 49*7ea7688aSMatthias Ringwald // From MSDN: 50*7ea7688aSMatthias Ringwald // __WIN32 Defined as 1 when the compilation target is 32-bit ARM, 64-bit ARM, x86, or x64. 51*7ea7688aSMatthias Ringwald // Otherwise, undefined. 52*7ea7688aSMatthias Ringwald 53*7ea7688aSMatthias Ringwald #include <Windows.h> 54*7ea7688aSMatthias Ringwald #include <conio.h> //provides non standard getch() function 55*7ea7688aSMatthias Ringwald #include <signal.h> 56*7ea7688aSMatthias Ringwald 57*7ea7688aSMatthias Ringwald static btstack_data_source_t stdin_source; 58*7ea7688aSMatthias Ringwald static int activated = 0; 59*7ea7688aSMatthias Ringwald 60*7ea7688aSMatthias Ringwald static HANDLE stdin_reader_thread_handle; 61*7ea7688aSMatthias Ringwald static char key_read_buffer; 62*7ea7688aSMatthias Ringwald static HANDLE key_processed_handle; 63*7ea7688aSMatthias Ringwald 64*7ea7688aSMatthias Ringwald static WINAPI DWORD stdin_reader_thread_process(void * p){ 65*7ea7688aSMatthias Ringwald while (1){ 66*7ea7688aSMatthias Ringwald key_read_buffer = getch(); 67*7ea7688aSMatthias Ringwald SignalObjectAndWait(stdin_source.handle , key_processed_handle, INFINITE, FALSE); 68*7ea7688aSMatthias Ringwald } 69*7ea7688aSMatthias Ringwald return 0; 70*7ea7688aSMatthias Ringwald } 71*7ea7688aSMatthias Ringwald 72*7ea7688aSMatthias Ringwald void btstack_stdin_setup(void (*stdin_process)(btstack_data_source_t *_ds, btstack_data_source_callback_type_t callback_type)){ 73*7ea7688aSMatthias Ringwald 74*7ea7688aSMatthias Ringwald if (activated) return; 75*7ea7688aSMatthias Ringwald 76*7ea7688aSMatthias Ringwald // asynchronous io on stdin via OVERLAPPED seems to be problematic. 77*7ea7688aSMatthias Ringwald 78*7ea7688aSMatthias Ringwald // Use separate thread and event objects instead 79*7ea7688aSMatthias Ringwald stdin_source.handle = CreateEvent(NULL, FALSE, FALSE, NULL); 80*7ea7688aSMatthias Ringwald key_processed_handle = CreateEvent(NULL, FALSE, FALSE, NULL); 81*7ea7688aSMatthias Ringwald // default attributes, default stack size, proc, args, start immediately, don't care for thread id 82*7ea7688aSMatthias Ringwald stdin_reader_thread_handle = CreateThread(NULL, 0, &stdin_reader_thread_process, NULL, 0, NULL); 83*7ea7688aSMatthias Ringwald 84*7ea7688aSMatthias Ringwald btstack_run_loop_enable_data_source_callbacks(&stdin_source, DATA_SOURCE_CALLBACK_READ); 85*7ea7688aSMatthias Ringwald btstack_run_loop_set_data_source_handler(&stdin_source, stdin_process); 86*7ea7688aSMatthias Ringwald btstack_run_loop_add_data_source(&stdin_source); 87*7ea7688aSMatthias Ringwald 88*7ea7688aSMatthias Ringwald activated = 1; 89*7ea7688aSMatthias Ringwald } 90*7ea7688aSMatthias Ringwald 91*7ea7688aSMatthias Ringwald void btstack_stdin_reset(void){ 92*7ea7688aSMatthias Ringwald if (!activated) return; 93*7ea7688aSMatthias Ringwald activated = 0; 94*7ea7688aSMatthias Ringwald 95*7ea7688aSMatthias Ringwald btstack_run_loop_remove_data_source(&stdin_source); 96*7ea7688aSMatthias Ringwald 97*7ea7688aSMatthias Ringwald // shutdown thread 98*7ea7688aSMatthias Ringwald TerminateThread(stdin_reader_thread_handle, 0); 99*7ea7688aSMatthias Ringwald WaitForSingleObject(stdin_reader_thread_handle, INFINITE); 100*7ea7688aSMatthias Ringwald CloseHandle(stdin_reader_thread_handle); 101*7ea7688aSMatthias Ringwald 102*7ea7688aSMatthias Ringwald // free events 103*7ea7688aSMatthias Ringwald CloseHandle(stdin_source.handle); 104*7ea7688aSMatthias Ringwald CloseHandle(key_processed_handle); 105*7ea7688aSMatthias Ringwald } 106*7ea7688aSMatthias Ringwald 107*7ea7688aSMatthias Ringwald // read single byte after data source callback was triggered 108*7ea7688aSMatthias Ringwald char btstack_stdin_read(void){ 109*7ea7688aSMatthias Ringwald 110*7ea7688aSMatthias Ringwald // raise SIGINT for CTRL-c on main thread 111*7ea7688aSMatthias Ringwald if (key_read_buffer == 0x03){ 112*7ea7688aSMatthias Ringwald raise(SIGINT); 113*7ea7688aSMatthias Ringwald return 0; 114*7ea7688aSMatthias Ringwald } 115*7ea7688aSMatthias Ringwald 116*7ea7688aSMatthias Ringwald char data = key_read_buffer; 117*7ea7688aSMatthias Ringwald SetEvent(key_processed_handle); 118*7ea7688aSMatthias Ringwald 119*7ea7688aSMatthias Ringwald return data; 120*7ea7688aSMatthias Ringwald } 121*7ea7688aSMatthias Ringwald 122