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 +}