eqemu

diff src/dev.cc @ 2:48dce4ee4850

the fake device is working
author John Tsiombikas <nuclear@member.fsf.org>
date Tue, 15 Jul 2014 14:37:51 +0300
parents
children 977bc1cb055b
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/dev.cc	Tue Jul 15 14:37:51 2014 +0300
     1.3 @@ -0,0 +1,177 @@
     1.4 +#include <stdio.h>
     1.5 +#include <string.h>
     1.6 +#include <errno.h>
     1.7 +#include <signal.h>
     1.8 +#include <limits.h>
     1.9 +#include <string>
    1.10 +#include <unistd.h>
    1.11 +#include <sys/stat.h>
    1.12 +#include <sys/wait.h>
    1.13 +#include <fcntl.h>
    1.14 +#include <termios.h>
    1.15 +#include "dev.h"
    1.16 +#include "timer.h"
    1.17 +
    1.18 +int customer, ticket;
    1.19 +static int report_inputs, cmd_echo;
    1.20 +static long last_ticket_msec = LONG_MIN;
    1.21 +
    1.22 +static void runcmd(const char *cmd);
    1.23 +
    1.24 +static int fd = -1;
    1.25 +static FILE *fp;
    1.26 +static std::string cur_line;
    1.27 +
    1.28 +int start_dev(const char *devpath)
    1.29 +{
    1.30 +	if((fd = open(devpath, O_RDWR | O_NONBLOCK)) == -1) {
    1.31 +		fprintf(stderr, "failed to open device: %s: %s\n", devpath, strerror(errno));
    1.32 +		return -1;
    1.33 +	}
    1.34 +	if(isatty(fd)) {
    1.35 +		struct termios term;
    1.36 +
    1.37 +		if(tcgetattr(fd, &term) == -1) {
    1.38 +			perror("failed to retrieve terminal attributes");
    1.39 +			stop_dev();
    1.40 +			return -1;
    1.41 +		}
    1.42 +		term.c_cflag = CS8 | CLOCAL;
    1.43 +		term.c_iflag &= ~(IXON | IXOFF);
    1.44 +		term.c_lflag = 0;
    1.45 +
    1.46 +		cfsetispeed(&term, B38400);
    1.47 +		cfsetospeed(&term, B38400);
    1.48 +
    1.49 +		if(tcsetattr(fd, TCSANOW, &term) == -1) {
    1.50 +			perror("failed to set terminal attributes");
    1.51 +			stop_dev();
    1.52 +			return -1;
    1.53 +		}
    1.54 +	}
    1.55 +
    1.56 +	if(!(fp = fdopen(fd, "r+"))) {
    1.57 +		perror("failed to attach an I/O stream to the device file\n");
    1.58 +		stop_dev();
    1.59 +		return -1;
    1.60 +	}
    1.61 +	setvbuf(fp, 0, _IONBF, 0);
    1.62 +
    1.63 +	return fd;
    1.64 +}
    1.65 +
    1.66 +void stop_dev()
    1.67 +{
    1.68 +	if(fp)
    1.69 +		fclose(fp);
    1.70 +	else if(fd >= 0)
    1.71 +		close(fd);
    1.72 +}
    1.73 +
    1.74 +
    1.75 +void proc_dev_input()
    1.76 +{
    1.77 +	int rdbytes;
    1.78 +	char buf[256];
    1.79 +	static bool skip_line;
    1.80 +
    1.81 +	while((rdbytes = read(fd, buf, sizeof buf - 1)) > 0) {
    1.82 +		buf[rdbytes] = 0;
    1.83 +
    1.84 +		/* ignore our own crap */
    1.85 +		if(memcmp(buf, "OK,", 3) == 0 || memcmp(buf, "ERR,", 4) == 0) {
    1.86 +			skip_line = true;
    1.87 +		}
    1.88 +
    1.89 +		for(int i=0; i<rdbytes; i++) {
    1.90 +			if(buf[i] == '\n' || buf[i] == '\r') {
    1.91 +				if(!cur_line.empty()) {
    1.92 +					runcmd(cur_line.c_str());
    1.93 +					cur_line.clear();
    1.94 +				}
    1.95 +				skip_line = false;
    1.96 +			} else {
    1.97 +				if(!skip_line) {
    1.98 +					cur_line.push_back(buf[i]);
    1.99 +				}
   1.100 +			}
   1.101 +		}
   1.102 +	}
   1.103 +}
   1.104 +
   1.105 +void issue_ticket()
   1.106 +{
   1.107 +	ticket++;
   1.108 +	last_ticket_msec = get_msec();
   1.109 +	if(report_inputs) {
   1.110 +		fprintf(fp, "ticket: %d\n", ticket);
   1.111 +	}
   1.112 +}
   1.113 +
   1.114 +void next_customer()
   1.115 +{
   1.116 +	if(customer < ticket) {
   1.117 +		customer++;
   1.118 +		last_ticket_msec = LONG_MIN;
   1.119 +		if(report_inputs) {
   1.120 +			fprintf(fp, "customer: %d\n", customer);
   1.121 +		}
   1.122 +	}
   1.123 +}
   1.124 +
   1.125 +#define VERSTR \
   1.126 +	"Queue system emulator v0.1 by John Tsiombikas <nuclear@member.fsf.org>"
   1.127 +
   1.128 +static void runcmd(const char *cmd)
   1.129 +{
   1.130 +	printf("DBG: runcmd(\"%s\")\n", cmd);
   1.131 +
   1.132 +	switch(cmd[0]) {
   1.133 +	case 'e':
   1.134 +		cmd_echo = !cmd_echo;
   1.135 +		fprintf(fp, "OK,turning echo %s\n", cmd_echo ? "on" : "off");
   1.136 +		break;
   1.137 +
   1.138 +	case 'i':
   1.139 +		report_inputs = !report_inputs;
   1.140 +		fprintf(fp, "OK,turning input reports %s\n", report_inputs ? "on" : "off");
   1.141 +		break;
   1.142 +
   1.143 +	case 'v':
   1.144 +		fprintf(fp, "OK,%s\n", VERSTR);
   1.145 +		break;
   1.146 +
   1.147 +	case 'r':
   1.148 +		fprintf(fp, "OK,reseting queues\n");
   1.149 +		customer = 0;
   1.150 +		ticket = 0;
   1.151 +		last_ticket_msec = LONG_MIN;
   1.152 +		break;
   1.153 +
   1.154 +	case 't':
   1.155 +		fprintf(fp, "OK,ticket: %d\r\n", ticket);
   1.156 +		break;
   1.157 +
   1.158 +	case 'c':
   1.159 +		fprintf(fp, "OK,customer: %d\r\n", customer);
   1.160 +		break;
   1.161 +
   1.162 +	case 'q':
   1.163 +		fprintf(fp, "OK,issuing queue ticket\n");
   1.164 +		issue_ticket();
   1.165 +		break;
   1.166 +
   1.167 +	case 'n':
   1.168 +		fprintf(fp, "OK,next customer\n");
   1.169 +		next_customer();
   1.170 +		break;
   1.171 +
   1.172 +	case 'h':
   1.173 +		fprintf(fp, "OK,commands: (e)cho, (v)ersion, (t)icket, (c)ustomer, "
   1.174 +				"(n)ext, (q)ueue, (r)eset, (i)nput-reports, (h)elp.\n");
   1.175 +		break;
   1.176 +
   1.177 +	default:
   1.178 +		fprintf(fp, "ERR,unknown command: %s\n", cmd);
   1.179 +	}
   1.180 +}