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 387ea7688aSMatthias Ringwald #define __BTSTACK_FILE__ "btstack_stdin_windows.c" 397ea7688aSMatthias Ringwald 407ea7688aSMatthias Ringwald #include <errno.h> 417ea7688aSMatthias Ringwald #include <stdio.h> 427ea7688aSMatthias Ringwald #include <unistd.h> 437ea7688aSMatthias Ringwald 447ea7688aSMatthias Ringwald #include "btstack_run_loop.h" 4595a8ee01SMatthias Ringwald #include "btstack_defines.h" 467ea7688aSMatthias Ringwald #include <stdlib.h> 477ea7688aSMatthias Ringwald 487ea7688aSMatthias Ringwald #include "btstack_stdin.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); 657ea7688aSMatthias Ringwald 667ea7688aSMatthias Ringwald static WINAPI DWORD stdin_reader_thread_process(void * p){ 677ea7688aSMatthias Ringwald while (1){ 687ea7688aSMatthias Ringwald key_read_buffer = getch(); 69*398a95ecSMatthias Ringwald SignalObjectAndWait(stdin_source.source.handle, key_processed_handle, INFINITE, FALSE); 707ea7688aSMatthias Ringwald } 717ea7688aSMatthias Ringwald return 0; 727ea7688aSMatthias Ringwald } 737ea7688aSMatthias Ringwald 7495a8ee01SMatthias Ringwald static void stdin_process(btstack_data_source_t *ds, btstack_data_source_callback_type_t callback_type){ 7595a8ee01SMatthias Ringwald 7695a8ee01SMatthias Ringwald // raise SIGINT for CTRL-c on main thread 7795a8ee01SMatthias Ringwald if (key_read_buffer == 0x03){ 7895a8ee01SMatthias Ringwald raise(SIGINT); 7995a8ee01SMatthias Ringwald return; 8095a8ee01SMatthias Ringwald } 8195a8ee01SMatthias Ringwald 8295a8ee01SMatthias Ringwald SetEvent(key_processed_handle); 8395a8ee01SMatthias Ringwald 8495a8ee01SMatthias Ringwald if (stdin_handler){ 8595a8ee01SMatthias Ringwald (*stdin_handler)(key_read_buffer); 8695a8ee01SMatthias Ringwald } 8795a8ee01SMatthias Ringwald } 8895a8ee01SMatthias Ringwald 8995a8ee01SMatthias Ringwald void btstack_stdin_setup(void (*handler)(char c)){ 907ea7688aSMatthias Ringwald 917ea7688aSMatthias Ringwald if (activated) return; 927ea7688aSMatthias Ringwald 9395a8ee01SMatthias Ringwald 9495a8ee01SMatthias Ringwald stdin_handler = handler; 9595a8ee01SMatthias Ringwald 967ea7688aSMatthias Ringwald // asynchronous io on stdin via OVERLAPPED seems to be problematic. 977ea7688aSMatthias Ringwald 987ea7688aSMatthias Ringwald // Use separate thread and event objects instead 99*398a95ecSMatthias 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 1117ea7688aSMatthias Ringwald void btstack_stdin_reset(void){ 1127ea7688aSMatthias Ringwald if (!activated) return; 1137ea7688aSMatthias Ringwald activated = 0; 11495a8ee01SMatthias Ringwald stdin_handler = NULL; 1157ea7688aSMatthias Ringwald 1167ea7688aSMatthias Ringwald btstack_run_loop_remove_data_source(&stdin_source); 1177ea7688aSMatthias Ringwald 1187ea7688aSMatthias Ringwald // shutdown thread 1197ea7688aSMatthias Ringwald TerminateThread(stdin_reader_thread_handle, 0); 1207ea7688aSMatthias Ringwald WaitForSingleObject(stdin_reader_thread_handle, INFINITE); 1217ea7688aSMatthias Ringwald CloseHandle(stdin_reader_thread_handle); 1227ea7688aSMatthias Ringwald 1237ea7688aSMatthias Ringwald // free events 124*398a95ecSMatthias Ringwald CloseHandle(stdin_source.source.handle); 1257ea7688aSMatthias Ringwald CloseHandle(key_processed_handle); 1267ea7688aSMatthias Ringwald } 1277ea7688aSMatthias Ringwald 128