Racket extension for using tcsetattr() to induce raw mode

This commit is contained in:
Tony Garnock-Jones 2011-12-19 15:47:58 -05:00
parent 479f82857a
commit c3d9c0d6ad
3 changed files with 107 additions and 0 deletions

16
Makefile Normal file
View File

@ -0,0 +1,16 @@
SYSTEM_LIBRARY_SUBPATH:=compiled/native/$(shell racket -e '(display (path->string (system-library-subpath)))')
all: $(SYSTEM_LIBRARY_SUBPATH)/tty-raw-extension.so
clean:
rm -rf compiled
$(SYSTEM_LIBRARY_SUBPATH):
mkdir -p $@
$(SYSTEM_LIBRARY_SUBPATH)/%.so: %.c $(SYSTEM_LIBRARY_SUBPATH)
mzc --xform $*.c
mzc --3m --cc $*.3m.c
mzc --3m --ld $@ $*_3m.o
rm -f $*.3m.c
rm -f $*_3m.o

15
test-raw.rkt Normal file
View File

@ -0,0 +1,15 @@
#lang racket/base
(require "tty-raw-extension")
(define (main)
(tty-raw!)
(let loop ()
(define ch (read-byte))
(printf "Byte: ~v\015\012" ch)
;;(flush-output)
(if (member ch '(4 8 127)) ;; EOF, C-h, DEL
(exit)
(loop))))
(main)

76
tty-raw-extension.c Normal file
View File

@ -0,0 +1,76 @@
/* PLT Racket extension for selecting "raw" TTY mode */
#include "escheme.h"
#include <stdio.h>
#include <signal.h>
#include <termios.h>
#include <stdlib.h>
#include <unistd.h>
#define STDIN_FD 0
static int is_raw = 0;
static struct termios saved;
static int ttyraw(void) {
/* Based on the settings given in http://www.minek.com/files/unix_examples/raw.html */
struct termios t;
if (is_raw) return 0;
if (tcgetattr(STDIN_FD, &saved) < 0) return -1;
t = saved;
t.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);
t.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
t.c_cflag &= ~(CSIZE | PARENB);
t.c_cflag |= CS8;
t.c_oflag &= ~(OPOST);
t.c_cc[VMIN] = 1;
t.c_cc[VTIME] = 0;
if (tcsetattr(STDIN_FD, TCSAFLUSH, &t) < 0) return -1;
is_raw = 1;
return 0;
}
static int ttyrestore(void) {
if (!is_raw) return 0;
if (tcsetattr(STDIN_FD, TCSAFLUSH, &saved) < 0) return -1;
is_raw = 0;
return 0;
}
static Scheme_Object *sch_ttyraw(int argc, Scheme_Object **argv) {
return ttyraw() == 0 ? scheme_true : scheme_false;
}
static Scheme_Object *sch_ttyrestore(int argc, Scheme_Object **argv) {
return ttyrestore() == 0 ? scheme_true : scheme_false;
}
Scheme_Object *scheme_reload(Scheme_Env *env) {
Scheme_Env *mod_env;
mod_env = scheme_primitive_module(scheme_intern_symbol("tty-raw-extension"), env);
scheme_add_global("tty-raw!",
scheme_make_prim_w_arity(sch_ttyraw, "tty-raw!", 0, 0),
mod_env);
scheme_add_global("tty-restore!",
scheme_make_prim_w_arity(sch_ttyrestore, "tty-restore!", 0, 0),
mod_env);
scheme_finish_primitive_module(mod_env);
return scheme_void;
}
Scheme_Object *scheme_initialize(Scheme_Env *env) {
atexit(ttyrestore);
return scheme_reload(env);
}
Scheme_Object *scheme_module_name(void) {
return scheme_intern_symbol("tty-raw-extension");
}