--- /dev/null
+#include <stdio.h>
+#include <termios.h>
+#include <stdint.h>
+#include <sys/io.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <unistd.h>
+#include <poll.h>
+
+static const int port=0x37a;
+
+#define LENGTH(x) (sizeof(x)/sizeof(*(x)))
+
+static volatile struct termios tios;
+
+static void cleanup(void) {
+ tcsetattr(0,TCSANOW,(struct termios *)&tios);
+}
+
+int main(void) {
+ uint8_t out=0x24;
+ if (ioperm(port,1,1)!=0) {
+ fprintf(stderr,"ioperm 0x%x: %m\n",port);
+ exit(EXIT_FAILURE);
+ }
+ int i=tcgetattr(0,(struct termios *)&tios);
+ assert(i==0);
+ atexit(cleanup);
+ struct termios tios_raw=tios;
+ cfmakeraw(&tios_raw);
+ i=tcsetattr(0,TCSANOW,&tios_raw);
+ assert(i==0);
+ for (;;) {
+ static const struct item {
+ const char *name;
+ uint8_t mask;
+ char key;
+ } items[]={
+ {"DAV=pin1" ,0x01,'1'},
+ {"NRFD=pin14",0x02,'2'},
+ {"NDAC=pin16",0x04,'4'},
+ {"ATN=pin17" ,0x08,'8'},
+ {"bidir" ,0x20,'b'},
+ };
+ outb(out,port);
+ usleep(1000000/10);
+ uint8_t in=inb(port);
+ printf("out=0x%02x in=0x%02x",out,in);
+ for (const struct item *item=items;item<items+LENGTH(items);item++)
+ printf(" %s:out=%d,in=%d;'%c'",item->name,!!(out&item->mask),!!(in&item->mask),item->key);
+ putchar('\r');
+ fflush(stdout);
+ struct pollfd pollfd;
+ pollfd.fd=STDIN_FILENO;
+ pollfd.events=POLLIN;
+ switch (poll(&pollfd,1,0)) {
+ case 1: {
+ char c;
+ ssize_t got=read(STDIN_FILENO,&c,1);
+ assert(got==1);
+ if (c==27||c==3||c=='\r') {
+ putchar('\n');
+ exit(EXIT_FAILURE);
+ }
+ for (const struct item *item=items;item<items+LENGTH(items);item++)
+ if (c==item->key)
+ out^=item->mask;
+ } break;
+ case 0:
+ break;
+ case -1:
+ abort();
+ }
+ }
+}