From 27007ae32a1244db12ba1e8e12352785075010a1 Mon Sep 17 00:00:00 2001 From: hpa Date: Mon, 20 Dec 2004 22:28:30 +0000 Subject: [PATCH] Make the raw input console non-blocking with a timeout, allows handling the [Esc] key. --- com32/include/sys/times.h | 21 ++++++++++++++++++++ com32/lib/Makefile | 2 +- com32/lib/fread.c | 5 +---- com32/lib/fwrite.c | 5 +---- com32/lib/sys/ansicon_write.c | 4 ++-- com32/lib/sys/rawcon_read.c | 37 ++++++++++++++++++++++++----------- com32/lib/sys/times.c | 45 +++++++++++++++++++++++++++++++++++++++++++ com32/libutil/ansiraw.c | 2 ++ com32/libutil/get_key.c | 19 +++++++++++++----- com32/modules/Makefile | 2 +- 10 files changed, 114 insertions(+), 28 deletions(-) create mode 100644 com32/include/sys/times.h create mode 100644 com32/lib/sys/times.c diff --git a/com32/include/sys/times.h b/com32/include/sys/times.h new file mode 100644 index 0000000..173efe2 --- /dev/null +++ b/com32/include/sys/times.h @@ -0,0 +1,21 @@ +/* + * sys/times.h + */ + +#ifndef _SYS_TIMES_H +#define _SYS_TIMES_H + +#include + +struct tms { + /* Empty */ +}; + +#define HZ 18 /* Piddly resolution... */ +#define CLK_TCK HZ + +typedef uint16_t clock_t; + +clock_t times(struct tms *); + +#endif /* _SYS_TIMES_H */ diff --git a/com32/lib/Makefile b/com32/lib/Makefile index 5f7551d..972c63c 100644 --- a/com32/lib/Makefile +++ b/com32/lib/Makefile @@ -17,7 +17,7 @@ LIBOBJS = abort.o atexit.o atoi.o atol.o atoll.o calloc.o creat.o \ libgcc/__negdi2.o libgcc/__ashrdi3.o libgcc/__lshrdi3.o \ libgcc/__muldi3.o libgcc/__udivmoddi4.o libgcc/__umoddi3.o \ libgcc/__divdi3.o libgcc/__moddi3.o \ - sys/entry.o sys/exit.o sys/argv.o \ + sys/entry.o sys/exit.o sys/argv.o sys/times.o \ sys/fileinfo.o sys/opendev.o sys/read.o sys/write.o \ sys/close.o sys/open.o sys/fileread.o sys/fileclose.o \ sys/isatty.o sys/openconsole.o sys/line_input.o \ diff --git a/com32/lib/fread.c b/com32/lib/fread.c index 8f7dba9..76fdda8 100644 --- a/com32/lib/fread.c +++ b/com32/lib/fread.c @@ -15,7 +15,7 @@ size_t _fread(void *buf, size_t count, FILE *f) while ( count ) { rv = read(fileno(f), p, count); if ( rv == -1 ) { - if ( errno == EINTR ) + if ( errno == EINTR || errno == EAGAIN ) continue; else break; @@ -30,6 +30,3 @@ size_t _fread(void *buf, size_t count, FILE *f) return bytes; } - - - diff --git a/com32/lib/fwrite.c b/com32/lib/fwrite.c index 0a73188..fd7dab7 100644 --- a/com32/lib/fwrite.c +++ b/com32/lib/fwrite.c @@ -15,7 +15,7 @@ size_t _fwrite(const void *buf, size_t count, FILE *f) while ( count ) { rv = write(fileno(f), p, count); if ( rv == -1 ) { - if ( errno == EINTR ) + if ( errno == EINTR || errno == EAGAIN ) continue; else break; @@ -30,6 +30,3 @@ size_t _fwrite(const void *buf, size_t count, FILE *f) return bytes; } - - - diff --git a/com32/lib/sys/ansicon_write.c b/com32/lib/sys/ansicon_write.c index f7f0f86..4071087 100644 --- a/com32/lib/sys/ansicon_write.c +++ b/com32/lib/sys/ansicon_write.c @@ -232,8 +232,8 @@ static void ansicon_putchar(int ch) case 'H': case 'f': { - int x = st.parms[0] - 1; - int y = st.parms[1] - 1; + int y = st.parms[0] - 1; + int x = st.parms[1] - 1; xy.x = (x >= cols) ? cols-1 : (x < 0) ? 0 : x; xy.y = (y >= rows) ? rows-1 : (y < 0) ? 0 : y; diff --git a/com32/lib/sys/rawcon_read.c b/com32/lib/sys/rawcon_read.c index 23a742b..e767c7a 100644 --- a/com32/lib/sys/rawcon_read.c +++ b/com32/lib/sys/rawcon_read.c @@ -29,13 +29,15 @@ /* * rawcon_read.c * - * Character-oriented reading from the console without echo + * Character-oriented reading from the console without echo, and with + * a timeout (50-100 ms). */ #include #include #include #include +#include #include "file.h" /* Global, since it's used by stdcon_read */ @@ -44,28 +46,41 @@ ssize_t __rawcon_read(struct file_info *fp, void *buf, size_t count) com32sys_t ireg, oreg; char *bufp = buf; size_t n = 0; + clock_t start; (void)fp; memset(&ireg, 0, sizeof ireg); + start = times(NULL); + while ( count ) { - ireg.eax.b[1] = 0x08; - __intcall(0x21, &ireg, &oreg); - *bufp++ = oreg.eax.b[0]; - n++; - - if ( ! --count ) + if ( (clock_t)(times(NULL) - start) >= 2+CLK_TCK/20 ) break; - /* Only return more than one if there is stuff in the buffer */ + /* Poll */ ireg.eax.b[1] = 0x0B; __intcall(0x21, &ireg, &oreg); - if ( !oreg.eax.b[0] ) - break; + if ( !oreg.eax.b[0] ) { + if ( n ) + break; /* We have data, deliver it */ + else + continue; + } + + /* We have data, go get it */ + ireg.eax.b[1] = 0x08; + __intcall(0x21, &ireg, &oreg); + *bufp++ = oreg.eax.b[0]; + n++; } - return n; + if ( n == 0 ) { + errno = EAGAIN; + return -1; + } else { + return n; + } } const struct input_dev dev_rawcon_r = { diff --git a/com32/lib/sys/times.c b/com32/lib/sys/times.c new file mode 100644 index 0000000..b67a2a7 --- /dev/null +++ b/com32/lib/sys/times.c @@ -0,0 +1,45 @@ +#ident "$Id$" +/* ----------------------------------------------------------------------- * + * + * Copyright 2004 H. Peter Anvin - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- */ + +/* + * sys/times.c + * + * Returns something like a clock. + */ + +#include +#include +#include + +clock_t times(struct tms *buf) +{ + (void)buf; /* Ignored */ + + /* Should we get this via INT 1Ah? */ + return *(uint16_t *)0x46c; +} diff --git a/com32/libutil/ansiraw.c b/com32/libutil/ansiraw.c index 03c5752..0e6675a 100644 --- a/com32/libutil/ansiraw.c +++ b/com32/libutil/ansiraw.c @@ -84,6 +84,8 @@ void console_ansi_raw(void) tio.c_iflag &= ~ICRNL; tio.c_iflag |= IGNCR; tio.c_lflag &= ~(ISIG|ICANON|ECHO); + tio.c_cc[VMIN] = 0; + tio.c_cc[VTIME] = 2; tcsetattr(0, TCSANOW, &tio); fputs("\033[0m\033[20h", stdout); } diff --git a/com32/libutil/get_key.c b/com32/libutil/get_key.c index 0239d23..e243761 100644 --- a/com32/libutil/get_key.c +++ b/com32/libutil/get_key.c @@ -36,6 +36,8 @@ #include #include +#include +#include #include struct keycode { @@ -110,16 +112,24 @@ static const struct keycode keycodes[] = { int get_key(FILE *f) { unsigned char buffer[MAXLEN]; - int nc, ch, i; + int nc, i, rv; const struct keycode *kc; int another; + unsigned char ch; nc = 0; do { - ch = getc(f); - - if ( ch == EOF ) + rv = read(fileno(f), &ch, 1); + if ( rv == 0 ) return EOF; + else if ( rv == -1 && errno == EAGAIN ) { + if ( nc ) + return buffer[0]; /* timeout */ + else { + another = 1; + continue; + } + } buffer[nc++] = ch; @@ -128,7 +138,6 @@ int get_key(FILE *f) if ( nc == kc->seqlen && !memcmp(buffer, kc->seq, nc) ) return kc->code; else if ( nc < kc->seqlen && !memcmp(buffer, kc->seq, nc) ) { - another = 1; break; } } diff --git a/com32/modules/Makefile b/com32/modules/Makefile index 0037523..4b6f335 100644 --- a/com32/modules/Makefile +++ b/com32/modules/Makefile @@ -45,7 +45,7 @@ AUXDIR = $(LIBDIR)/syslinux INCDIR = /usr/include COM32DIR = $(AUXDIR)/com32 -MODULES = chain.c32 # menu.c32 menu.lnx +MODULES = chain.c32 menu.c32 menu.lnx all: $(MODULES) -- 2.7.4