eqemu

changeset 2:48dce4ee4850

the fake device is working
author John Tsiombikas <nuclear@member.fsf.org>
date Tue, 15 Jul 2014 14:37:51 +0300
parents 374d91dd2996
children f9274bebe55e
files Makefile README src/dev.cc src/dev.h src/main.cc src/timer.cc src/timer.h
diffstat 7 files changed, 261 insertions(+), 5 deletions(-) [+]
line diff
     1.1 --- a/Makefile	Tue Jul 15 05:44:26 2014 +0300
     1.2 +++ b/Makefile	Tue Jul 15 14:37:51 2014 +0300
     1.3 @@ -5,7 +5,7 @@
     1.4  
     1.5  CFLAGS = -pedantic -Wall -g
     1.6  CXXFLAGS = $(CFLAGS)
     1.7 -LDFLAGS = -lGL -lGLU -lglut -lGLEW -lX11 -lm
     1.8 +LDFLAGS = -lGL -lGLU -lglut -lGLEW -lX11 -lm -lpthread
     1.9  
    1.10  $(bin): $(obj)
    1.11  	$(CXX) -o $@ $(obj) $(LDFLAGS)
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/README	Tue Jul 15 14:37:51 2014 +0300
     2.3 @@ -0,0 +1,4 @@
     2.4 +1. Create 2 pseudoterminals: socat -d -d PTY PTY
     2.5 +2. start ./equeue_dummy /dev/pts/one
     2.6 +3. set the php script to use /dev/pts/theother (make sure apache has permission
     2.7 +   to rw it).
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/src/dev.cc	Tue Jul 15 14:37:51 2014 +0300
     3.3 @@ -0,0 +1,177 @@
     3.4 +#include <stdio.h>
     3.5 +#include <string.h>
     3.6 +#include <errno.h>
     3.7 +#include <signal.h>
     3.8 +#include <limits.h>
     3.9 +#include <string>
    3.10 +#include <unistd.h>
    3.11 +#include <sys/stat.h>
    3.12 +#include <sys/wait.h>
    3.13 +#include <fcntl.h>
    3.14 +#include <termios.h>
    3.15 +#include "dev.h"
    3.16 +#include "timer.h"
    3.17 +
    3.18 +int customer, ticket;
    3.19 +static int report_inputs, cmd_echo;
    3.20 +static long last_ticket_msec = LONG_MIN;
    3.21 +
    3.22 +static void runcmd(const char *cmd);
    3.23 +
    3.24 +static int fd = -1;
    3.25 +static FILE *fp;
    3.26 +static std::string cur_line;
    3.27 +
    3.28 +int start_dev(const char *devpath)
    3.29 +{
    3.30 +	if((fd = open(devpath, O_RDWR | O_NONBLOCK)) == -1) {
    3.31 +		fprintf(stderr, "failed to open device: %s: %s\n", devpath, strerror(errno));
    3.32 +		return -1;
    3.33 +	}
    3.34 +	if(isatty(fd)) {
    3.35 +		struct termios term;
    3.36 +
    3.37 +		if(tcgetattr(fd, &term) == -1) {
    3.38 +			perror("failed to retrieve terminal attributes");
    3.39 +			stop_dev();
    3.40 +			return -1;
    3.41 +		}
    3.42 +		term.c_cflag = CS8 | CLOCAL;
    3.43 +		term.c_iflag &= ~(IXON | IXOFF);
    3.44 +		term.c_lflag = 0;
    3.45 +
    3.46 +		cfsetispeed(&term, B38400);
    3.47 +		cfsetospeed(&term, B38400);
    3.48 +
    3.49 +		if(tcsetattr(fd, TCSANOW, &term) == -1) {
    3.50 +			perror("failed to set terminal attributes");
    3.51 +			stop_dev();
    3.52 +			return -1;
    3.53 +		}
    3.54 +	}
    3.55 +
    3.56 +	if(!(fp = fdopen(fd, "r+"))) {
    3.57 +		perror("failed to attach an I/O stream to the device file\n");
    3.58 +		stop_dev();
    3.59 +		return -1;
    3.60 +	}
    3.61 +	setvbuf(fp, 0, _IONBF, 0);
    3.62 +
    3.63 +	return fd;
    3.64 +}
    3.65 +
    3.66 +void stop_dev()
    3.67 +{
    3.68 +	if(fp)
    3.69 +		fclose(fp);
    3.70 +	else if(fd >= 0)
    3.71 +		close(fd);
    3.72 +}
    3.73 +
    3.74 +
    3.75 +void proc_dev_input()
    3.76 +{
    3.77 +	int rdbytes;
    3.78 +	char buf[256];
    3.79 +	static bool skip_line;
    3.80 +
    3.81 +	while((rdbytes = read(fd, buf, sizeof buf - 1)) > 0) {
    3.82 +		buf[rdbytes] = 0;
    3.83 +
    3.84 +		/* ignore our own crap */
    3.85 +		if(memcmp(buf, "OK,", 3) == 0 || memcmp(buf, "ERR,", 4) == 0) {
    3.86 +			skip_line = true;
    3.87 +		}
    3.88 +
    3.89 +		for(int i=0; i<rdbytes; i++) {
    3.90 +			if(buf[i] == '\n' || buf[i] == '\r') {
    3.91 +				if(!cur_line.empty()) {
    3.92 +					runcmd(cur_line.c_str());
    3.93 +					cur_line.clear();
    3.94 +				}
    3.95 +				skip_line = false;
    3.96 +			} else {
    3.97 +				if(!skip_line) {
    3.98 +					cur_line.push_back(buf[i]);
    3.99 +				}
   3.100 +			}
   3.101 +		}
   3.102 +	}
   3.103 +}
   3.104 +
   3.105 +void issue_ticket()
   3.106 +{
   3.107 +	ticket++;
   3.108 +	last_ticket_msec = get_msec();
   3.109 +	if(report_inputs) {
   3.110 +		fprintf(fp, "ticket: %d\n", ticket);
   3.111 +	}
   3.112 +}
   3.113 +
   3.114 +void next_customer()
   3.115 +{
   3.116 +	if(customer < ticket) {
   3.117 +		customer++;
   3.118 +		last_ticket_msec = LONG_MIN;
   3.119 +		if(report_inputs) {
   3.120 +			fprintf(fp, "customer: %d\n", customer);
   3.121 +		}
   3.122 +	}
   3.123 +}
   3.124 +
   3.125 +#define VERSTR \
   3.126 +	"Queue system emulator v0.1 by John Tsiombikas <nuclear@member.fsf.org>"
   3.127 +
   3.128 +static void runcmd(const char *cmd)
   3.129 +{
   3.130 +	printf("DBG: runcmd(\"%s\")\n", cmd);
   3.131 +
   3.132 +	switch(cmd[0]) {
   3.133 +	case 'e':
   3.134 +		cmd_echo = !cmd_echo;
   3.135 +		fprintf(fp, "OK,turning echo %s\n", cmd_echo ? "on" : "off");
   3.136 +		break;
   3.137 +
   3.138 +	case 'i':
   3.139 +		report_inputs = !report_inputs;
   3.140 +		fprintf(fp, "OK,turning input reports %s\n", report_inputs ? "on" : "off");
   3.141 +		break;
   3.142 +
   3.143 +	case 'v':
   3.144 +		fprintf(fp, "OK,%s\n", VERSTR);
   3.145 +		break;
   3.146 +
   3.147 +	case 'r':
   3.148 +		fprintf(fp, "OK,reseting queues\n");
   3.149 +		customer = 0;
   3.150 +		ticket = 0;
   3.151 +		last_ticket_msec = LONG_MIN;
   3.152 +		break;
   3.153 +
   3.154 +	case 't':
   3.155 +		fprintf(fp, "OK,ticket: %d\r\n", ticket);
   3.156 +		break;
   3.157 +
   3.158 +	case 'c':
   3.159 +		fprintf(fp, "OK,customer: %d\r\n", customer);
   3.160 +		break;
   3.161 +
   3.162 +	case 'q':
   3.163 +		fprintf(fp, "OK,issuing queue ticket\n");
   3.164 +		issue_ticket();
   3.165 +		break;
   3.166 +
   3.167 +	case 'n':
   3.168 +		fprintf(fp, "OK,next customer\n");
   3.169 +		next_customer();
   3.170 +		break;
   3.171 +
   3.172 +	case 'h':
   3.173 +		fprintf(fp, "OK,commands: (e)cho, (v)ersion, (t)icket, (c)ustomer, "
   3.174 +				"(n)ext, (q)ueue, (r)eset, (i)nput-reports, (h)elp.\n");
   3.175 +		break;
   3.176 +
   3.177 +	default:
   3.178 +		fprintf(fp, "ERR,unknown command: %s\n", cmd);
   3.179 +	}
   3.180 +}
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/src/dev.h	Tue Jul 15 14:37:51 2014 +0300
     4.3 @@ -0,0 +1,16 @@
     4.4 +#ifndef DEV_H_
     4.5 +#define DEV_H_
     4.6 +
     4.7 +extern int customer, ticket;
     4.8 +
     4.9 +int start_dev(const char *devpath);
    4.10 +void stop_dev();
    4.11 +void proc_dev_input();
    4.12 +
    4.13 +void next_customer();
    4.14 +void issue_ticket();
    4.15 +
    4.16 +int get_display_number();
    4.17 +int get_led_state(int led);
    4.18 +
    4.19 +#endif	/* DEV_H_ */
     5.1 --- a/src/main.cc	Tue Jul 15 05:44:26 2014 +0300
     5.2 +++ b/src/main.cc	Tue Jul 15 14:37:51 2014 +0300
     5.3 @@ -20,6 +20,8 @@
     5.4  static void process_events();
     5.5  static int translate_keysym(KeySym sym);
     5.6  
     5.7 +static int proc_args(int argc, char **argv);
     5.8 +
     5.9  static Display *dpy;
    5.10  static Window win;
    5.11  static GLXContext ctx;
    5.12 @@ -30,10 +32,15 @@
    5.13  static bool redisplay_pending;
    5.14  static bool win_mapped;
    5.15  
    5.16 -int main()
    5.17 +static int fakefd = -1;
    5.18 +static char *fake_devpath;
    5.19 +
    5.20 +int main(int argc, char **argv)
    5.21  {
    5.22 +	if(proc_args(argc, argv) == -1) {
    5.23 +		return 1;
    5.24 +	}
    5.25  	if(!init()) {
    5.26 -		fprintf(stderr, "X11/OpenGL initialization failed\n");
    5.27  		return 1;
    5.28  	}
    5.29  	atexit(cleanup);
    5.30 @@ -45,12 +52,18 @@
    5.31  		FD_ZERO(&rd);
    5.32  
    5.33  		FD_SET(xfd, &rd);
    5.34 +		FD_SET(fakefd, &rd);
    5.35  
    5.36 -		while(select(xfd + 1, &rd, 0, 0, 0) == -1 && errno == EINTR);
    5.37 +		int maxfd = xfd > fakefd ? xfd : fakefd;
    5.38 +
    5.39 +		while(select(maxfd + 1, &rd, 0, 0, 0) == -1 && errno == EINTR);
    5.40  
    5.41  		if(FD_ISSET(xfd, &rd)) {
    5.42  			process_events();
    5.43  		}
    5.44 +		if(FD_ISSET(fakefd, &rd)) {
    5.45 +			proc_dev_input();
    5.46 +		}
    5.47  
    5.48  		if(redisplay_pending) {
    5.49  			display();
    5.50 @@ -62,7 +75,11 @@
    5.51  
    5.52  static bool init()
    5.53  {
    5.54 -	start_dev();
    5.55 +	if(fake_devpath) {
    5.56 +		if((fakefd = start_dev(fake_devpath)) == -1) {
    5.57 +			return false;
    5.58 +		}
    5.59 +	}
    5.60  
    5.61  	if(!(dpy = XOpenDisplay(0))) {
    5.62  		fprintf(stderr, "failed to connect to the X server!\n");
    5.63 @@ -290,3 +307,24 @@
    5.64  	}
    5.65  	return (int)sym;
    5.66  }
    5.67 +
    5.68 +static int proc_args(int argc, char **argv)
    5.69 +{
    5.70 +	for(int i=1; i<argc; i++) {
    5.71 +		if(argv[i][0] == '-') {
    5.72 +			fprintf(stderr, "unexpected option: %s\n", argv[i]);
    5.73 +			return -1;
    5.74 +
    5.75 +		} else {
    5.76 +			if(fake_devpath) {
    5.77 +				fprintf(stderr, "unexpected argument: %s\n", argv[i]);
    5.78 +				return -1;
    5.79 +			}
    5.80 +			fake_devpath = argv[i];
    5.81 +		}
    5.82 +	}
    5.83 +	if(!fake_devpath) {
    5.84 +		fprintf(stderr, "no device path specified, running standalone\n");
    5.85 +	}
    5.86 +	return 0;
    5.87 +}
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/src/timer.cc	Tue Jul 15 14:37:51 2014 +0300
     6.3 @@ -0,0 +1,15 @@
     6.4 +#include <unistd.h>
     6.5 +#include <sys/time.h>
     6.6 +
     6.7 +unsigned long get_msec()
     6.8 +{
     6.9 +	static struct timeval tv0;
    6.10 +	struct timeval tv;
    6.11 +
    6.12 +	gettimeofday(&tv, 0);
    6.13 +	if(tv0.tv_sec == 0 && tv0.tv_usec == 0) {
    6.14 +		tv0 = tv;
    6.15 +		return 0;
    6.16 +	}
    6.17 +	return (tv.tv_sec - tv0.tv_sec) * 1000 + (tv.tv_usec - tv0.tv_usec) / 1000;
    6.18 +}
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/src/timer.h	Tue Jul 15 14:37:51 2014 +0300
     7.3 @@ -0,0 +1,6 @@
     7.4 +#ifndef TIMER_H_
     7.5 +#define TIMER_H_
     7.6 +
     7.7 +unsigned long get_msec();
     7.8 +
     7.9 +#endif	/* TIMER_H_ */