eqemu

view src/dev.cc @ 6:977bc1cb055b

almost done
author John Tsiombikas <nuclear@member.fsf.org>
date Fri, 18 Jul 2014 02:35:06 +0300
parents 48dce4ee4850
children 2b559dc24c7b
line source
1 #include <stdio.h>
2 #include <string.h>
3 #include <errno.h>
4 #include <signal.h>
5 #include <limits.h>
6 #include <string>
7 #include <unistd.h>
8 #include <sys/stat.h>
9 #include <sys/wait.h>
10 #include <fcntl.h>
11 #include <termios.h>
12 #include "dev.h"
13 #include "timer.h"
15 int customer, ticket;
16 static int report_inputs, cmd_echo;
17 static long last_ticket_msec = LONG_MIN;
19 static void runcmd(const char *cmd);
21 static int fd = -1;
22 static FILE *fp;
23 static std::string cur_line;
25 int start_dev(const char *devpath)
26 {
27 if((fd = open(devpath, O_RDWR | O_NONBLOCK)) == -1) {
28 fprintf(stderr, "failed to open device: %s: %s\n", devpath, strerror(errno));
29 return -1;
30 }
31 if(isatty(fd)) {
32 struct termios term;
34 if(tcgetattr(fd, &term) == -1) {
35 perror("failed to retrieve terminal attributes");
36 stop_dev();
37 return -1;
38 }
39 term.c_cflag = CS8 | CLOCAL;
40 term.c_iflag &= ~(IXON | IXOFF);
41 term.c_lflag = 0;
43 cfsetispeed(&term, B38400);
44 cfsetospeed(&term, B38400);
46 if(tcsetattr(fd, TCSANOW, &term) == -1) {
47 perror("failed to set terminal attributes");
48 stop_dev();
49 return -1;
50 }
51 }
53 if(!(fp = fdopen(fd, "r+"))) {
54 perror("failed to attach an I/O stream to the device file\n");
55 stop_dev();
56 return -1;
57 }
58 setvbuf(fp, 0, _IONBF, 0);
60 return fd;
61 }
63 void stop_dev()
64 {
65 if(fp)
66 fclose(fp);
67 else if(fd >= 0)
68 close(fd);
69 }
72 void proc_dev_input()
73 {
74 int rdbytes;
75 char buf[256];
76 static bool skip_line;
78 while((rdbytes = read(fd, buf, sizeof buf - 1)) > 0) {
79 buf[rdbytes] = 0;
81 /* ignore our own crap */
82 if(memcmp(buf, "OK,", 3) == 0 || memcmp(buf, "ERR,", 4) == 0) {
83 skip_line = true;
84 }
86 for(int i=0; i<rdbytes; i++) {
87 if(buf[i] == '\n' || buf[i] == '\r') {
88 if(!cur_line.empty()) {
89 runcmd(cur_line.c_str());
90 cur_line.clear();
91 }
92 skip_line = false;
93 } else {
94 if(!skip_line) {
95 cur_line.push_back(buf[i]);
96 }
97 }
98 }
99 }
100 }
102 void issue_ticket()
103 {
104 ticket++;
105 last_ticket_msec = get_msec();
106 if(report_inputs) {
107 fprintf(fp, "ticket: %d\n", ticket);
108 }
109 }
111 void next_customer()
112 {
113 if(customer < ticket) {
114 customer++;
115 last_ticket_msec = LONG_MIN;
116 if(report_inputs) {
117 fprintf(fp, "customer: %d\n", customer);
118 }
119 }
120 }
122 #define TICKET_SHOW_DUR 1000
124 int get_display_number()
125 {
126 if(get_msec() - last_ticket_msec < TICKET_SHOW_DUR) {
127 return ticket;
128 }
129 return customer;
130 }
132 int get_led_state(int led)
133 {
134 int ledon = get_msec() - last_ticket_msec < TICKET_SHOW_DUR ? 0 : 1;
135 return led == ledon ? 1 : 0;
136 }
138 #define VERSTR \
139 "Queue system emulator v0.1 by John Tsiombikas <nuclear@member.fsf.org>"
141 static void runcmd(const char *cmd)
142 {
143 printf("DBG: runcmd(\"%s\")\n", cmd);
145 switch(cmd[0]) {
146 case 'e':
147 cmd_echo = !cmd_echo;
148 fprintf(fp, "OK,turning echo %s\n", cmd_echo ? "on" : "off");
149 break;
151 case 'i':
152 report_inputs = !report_inputs;
153 fprintf(fp, "OK,turning input reports %s\n", report_inputs ? "on" : "off");
154 break;
156 case 'v':
157 fprintf(fp, "OK,%s\n", VERSTR);
158 break;
160 case 'r':
161 fprintf(fp, "OK,reseting queues\n");
162 customer = 0;
163 ticket = 0;
164 last_ticket_msec = LONG_MIN;
165 break;
167 case 't':
168 fprintf(fp, "OK,ticket: %d\r\n", ticket);
169 break;
171 case 'c':
172 fprintf(fp, "OK,customer: %d\r\n", customer);
173 break;
175 case 'q':
176 fprintf(fp, "OK,issuing queue ticket\n");
177 issue_ticket();
178 break;
180 case 'n':
181 fprintf(fp, "OK,next customer\n");
182 next_customer();
183 break;
185 case 'h':
186 fprintf(fp, "OK,commands: (e)cho, (v)ersion, (t)icket, (c)ustomer, "
187 "(n)ext, (q)ueue, (r)eset, (i)nput-reports, (h)elp.\n");
188 break;
190 default:
191 fprintf(fp, "ERR,unknown command: %s\n", cmd);
192 }
193 }