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
40*b795dcd0SMarcel Wappler #include <Windows.h>
417ea7688aSMatthias Ringwald #include <errno.h>
427ea7688aSMatthias Ringwald #include <stdio.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"
49de9c9f72SMatthias Ringwald #include "btstack_stdin_windows.h"
507ea7688aSMatthias Ringwald
517ea7688aSMatthias Ringwald // From MSDN:
527ea7688aSMatthias Ringwald // __WIN32 Defined as 1 when the compilation target is 32-bit ARM, 64-bit ARM, x86, or x64.
537ea7688aSMatthias Ringwald // Otherwise, undefined.
547ea7688aSMatthias Ringwald
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
stdin_reader_thread_process(void * p)6745996a73SMatthias Ringwald static DWORD WINAPI stdin_reader_thread_process(void * p){
68ff3cc4a5SMatthias Ringwald while (true){
6945996a73SMatthias 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
stdin_process(btstack_data_source_t * ds,btstack_data_source_callback_type_t callback_type)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
btstack_stdin_windows_init(void)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
btstack_stdin_window_register_ctrl_c_callback(void (* callback)(void))111de9c9f72SMatthias Ringwald void btstack_stdin_window_register_ctrl_c_callback(void (*callback)(void)){
112de9c9f72SMatthias Ringwald ctrl_c_handler = callback;
113de9c9f72SMatthias Ringwald }
114de9c9f72SMatthias Ringwald
btstack_stdin_setup(void (* handler)(char c))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
btstack_stdin_reset(void)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