xref: /btstack/platform/windows/btstack_stdin_windows.c (revision 398a95ec8e0d408db97ed8e80c67c74e30698a03)
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