devices/terminal.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
#include <stdio.h>
#include "../xyw.h"
#ifndef _WIN32
#include <termios.h>
#include <unistd.h>
static struct termios terminal_orig_termios;
static int terminal_raw_mode_active = 0;
#endif
/* terminal device */
#define TERMINAL_INPUT 0x0
#define TERMINAL_OUTPUT 0x1
#define TERMINAL_ON_KEYPRESS 0x2
#define TERMINAL_ON_ARGUMENT 0x4
void terminal_init(xyw_byte *data)
{
(void)data;
#ifndef _WIN32
struct termios raw;
if (!isatty(STDIN_FILENO))
{
// Not a real terminal (e.g. piped input/tests) — nothing to save or set
return;
}
if (tcgetattr(STDIN_FILENO, &terminal_orig_termios) != 0)
{
XYW_DBG("terminal: tcgetattr failed, raw mode not enabled\n");
return;
}
raw = terminal_orig_termios;
raw.c_lflag &= ~(ICANON | ECHO | ISIG);
// Non-blocking read: return after 100ms even if no input (for polling)
raw.c_cc[VMIN] = 0;
raw.c_cc[VTIME] = 1;
if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw) != 0)
{
XYW_DBG("terminal: tcsetattr failed, raw mode not enabled\n");
return;
}
terminal_raw_mode_active = 1;
#endif
}
void terminal_teardown(xyw_byte *data)
{
(void)data;
#ifndef _WIN32
if (terminal_raw_mode_active)
{
tcsetattr(STDIN_FILENO, TCSAFLUSH, &terminal_orig_termios);
terminal_raw_mode_active = 0;
}
#endif
}
void terminal_output(xyw_byte *data, xyw_byte addr, xyw_byte *error)
{
(void)error;
if (addr == TERMINAL_OUTPUT) {
fputc(data[addr], stdout);
fflush(stdout);
}
}
xyw_byte terminal_input(xyw_byte *data, xyw_byte addr, xyw_byte *error)
{
(void)error;
return data[addr];
}
|