xref: /btstack/platform/posix/btstack_stdin_posix.c (revision cc3bbb4c333814dcd6781fe3095dcfdf02167ee2)
1  /*
2   * Copyright (C) 2014 BlueKitchen GmbH
3   *
4   * Redistribution and use in source and binary forms, with or without
5   * modification, are permitted provided that the following conditions
6   * are met:
7   *
8   * 1. Redistributions of source code must retain the above copyright
9   *    notice, this list of conditions and the following disclaimer.
10   * 2. Redistributions in binary form must reproduce the above copyright
11   *    notice, this list of conditions and the following disclaimer in the
12   *    documentation and/or other materials provided with the distribution.
13   * 3. Neither the name of the copyright holders nor the names of
14   *    contributors may be used to endorse or promote products derived
15   *    from this software without specific prior written permission.
16   * 4. Any redistribution, use, or modification is done solely for
17   *    personal benefit and not for any commercial purpose or for
18   *    monetary gain.
19   *
20   * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
21   * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22   * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23   * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN
24   * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25   * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26   * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27   * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28   * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
30   * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31   * SUCH DAMAGE.
32   *
33   * Please inquire about commercial licensing options at
34   * contact@bluekitchen-gmbh.com
35   *
36   */
37  
38  #define BTSTACK_FILE__ "btstack_stdin_posix.c"
39  
40  #include <stdio.h>
41  #include <unistd.h>
42  
43  #include "btstack_debug.h"
44  #include "btstack_run_loop.h"
45  
46  #include "btstack_stdin.h"
47  #include <termios.h>
48  
49  static btstack_data_source_t stdin_source;
50  static int activated = 0;
51  static void (*stdin_handler)(char c);
52  
53  // read single byte after data source callback was triggered
stdin_process(btstack_data_source_t * ds,btstack_data_source_callback_type_t callback_type)54  static void stdin_process(btstack_data_source_t *ds, btstack_data_source_callback_type_t callback_type){
55      UNUSED(ds);
56      UNUSED(callback_type);
57  
58      char data;
59      int result = read(stdin_source.source.fd, &data, 1);
60      if (result < 1) return;
61      if (stdin_handler == NULL) return;
62  
63  #ifdef ENABLE_BTSTACK_STDIN_LOGGING
64      log_info("stdin: %c", data);
65  #endif
66  
67      (*stdin_handler)(data);
68  }
69  
btstack_stdin_setup(void (* handler)(char c))70  void btstack_stdin_setup(void (*handler)(char c)){
71  
72      if (activated) return;
73  
74      // disable line buffering
75      struct termios term = {0};
76      if (tcgetattr(0, &term) < 0)
77              perror("tcsetattr()");
78      term.c_lflag &= ~ICANON;
79      term.c_lflag &= ~ECHO;
80      if (tcsetattr(0, TCSANOW, &term) < 0) {
81          perror("tcsetattr ICANON");
82      }
83  
84      stdin_handler = handler;
85  
86      btstack_run_loop_set_data_source_fd(&stdin_source, 0); // stdin
87  
88      btstack_run_loop_enable_data_source_callbacks(&stdin_source, DATA_SOURCE_CALLBACK_READ);
89      btstack_run_loop_set_data_source_handler(&stdin_source, stdin_process);
90      btstack_run_loop_add_data_source(&stdin_source);
91  
92      activated = 1;
93  }
94  
btstack_stdin_reset(void)95  void btstack_stdin_reset(void){
96      if (!activated) return;
97      activated = 0;
98      stdin_handler = NULL;
99  
100      btstack_run_loop_remove_data_source(&stdin_source);
101  
102      struct termios term = {0};
103      if (tcgetattr(0, &term) < 0){
104          perror("tcsetattr()");
105      }
106      term.c_lflag |= ICANON;
107      term.c_lflag |= ECHO;
108      if (tcsetattr(0, TCSANOW, &term) < 0){
109          perror("tcsetattr ICANON");
110      }
111  }
112  
113