rev |
line source |
nuclear@12
|
1 /*
|
nuclear@12
|
2 eqemu - electronic queue system emulator
|
nuclear@12
|
3 Copyright (C) 2014 John Tsiombikas <nuclear@member.fsf.org>,
|
nuclear@12
|
4 Eleni-Maria Stea <eleni@mutantstargoat.com>
|
nuclear@12
|
5
|
nuclear@12
|
6 This program is free software: you can redistribute it and/or modify
|
nuclear@12
|
7 it under the terms of the GNU General Public License as published by
|
nuclear@12
|
8 the Free Software Foundation, either version 3 of the License, or
|
nuclear@12
|
9 (at your option) any later version.
|
nuclear@12
|
10
|
nuclear@12
|
11 This program is distributed in the hope that it will be useful,
|
nuclear@12
|
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
|
nuclear@12
|
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
nuclear@12
|
14 GNU General Public License for more details.
|
nuclear@12
|
15
|
nuclear@12
|
16 You should have received a copy of the GNU General Public License
|
nuclear@12
|
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
|
nuclear@12
|
18 */
|
nuclear@2
|
19 #include <stdio.h>
|
nuclear@2
|
20 #include <string.h>
|
nuclear@2
|
21 #include <errno.h>
|
nuclear@2
|
22 #include <signal.h>
|
nuclear@2
|
23 #include <limits.h>
|
nuclear@2
|
24 #include <string>
|
nuclear@2
|
25 #include <unistd.h>
|
nuclear@2
|
26 #include <sys/stat.h>
|
nuclear@2
|
27 #include <sys/wait.h>
|
nuclear@2
|
28 #include <fcntl.h>
|
nuclear@2
|
29 #include <termios.h>
|
nuclear@2
|
30 #include "dev.h"
|
nuclear@2
|
31 #include "timer.h"
|
nuclear@2
|
32
|
nuclear@11
|
33 void post_redisplay(); // defined in main.cc
|
nuclear@11
|
34
|
nuclear@2
|
35 int customer, ticket;
|
nuclear@2
|
36 static int report_inputs, cmd_echo;
|
nuclear@2
|
37 static long last_ticket_msec = LONG_MIN;
|
nuclear@2
|
38
|
nuclear@2
|
39 static void runcmd(const char *cmd);
|
nuclear@2
|
40
|
nuclear@2
|
41 static int fd = -1;
|
nuclear@2
|
42 static FILE *fp;
|
nuclear@2
|
43 static std::string cur_line;
|
nuclear@2
|
44
|
nuclear@2
|
45 int start_dev(const char *devpath)
|
nuclear@2
|
46 {
|
nuclear@2
|
47 if((fd = open(devpath, O_RDWR | O_NONBLOCK)) == -1) {
|
nuclear@2
|
48 fprintf(stderr, "failed to open device: %s: %s\n", devpath, strerror(errno));
|
nuclear@2
|
49 return -1;
|
nuclear@2
|
50 }
|
nuclear@2
|
51 if(isatty(fd)) {
|
nuclear@2
|
52 struct termios term;
|
nuclear@2
|
53
|
nuclear@2
|
54 if(tcgetattr(fd, &term) == -1) {
|
nuclear@2
|
55 perror("failed to retrieve terminal attributes");
|
nuclear@2
|
56 stop_dev();
|
nuclear@2
|
57 return -1;
|
nuclear@2
|
58 }
|
nuclear@2
|
59 term.c_cflag = CS8 | CLOCAL;
|
nuclear@2
|
60 term.c_iflag &= ~(IXON | IXOFF);
|
nuclear@2
|
61 term.c_lflag = 0;
|
nuclear@2
|
62
|
nuclear@2
|
63 cfsetispeed(&term, B38400);
|
nuclear@2
|
64 cfsetospeed(&term, B38400);
|
nuclear@2
|
65
|
nuclear@2
|
66 if(tcsetattr(fd, TCSANOW, &term) == -1) {
|
nuclear@2
|
67 perror("failed to set terminal attributes");
|
nuclear@2
|
68 stop_dev();
|
nuclear@2
|
69 return -1;
|
nuclear@2
|
70 }
|
nuclear@2
|
71 }
|
nuclear@2
|
72
|
nuclear@2
|
73 if(!(fp = fdopen(fd, "r+"))) {
|
nuclear@2
|
74 perror("failed to attach an I/O stream to the device file\n");
|
nuclear@2
|
75 stop_dev();
|
nuclear@2
|
76 return -1;
|
nuclear@2
|
77 }
|
nuclear@2
|
78 setvbuf(fp, 0, _IONBF, 0);
|
nuclear@2
|
79
|
nuclear@2
|
80 return fd;
|
nuclear@2
|
81 }
|
nuclear@2
|
82
|
nuclear@2
|
83 void stop_dev()
|
nuclear@2
|
84 {
|
nuclear@2
|
85 if(fp)
|
nuclear@2
|
86 fclose(fp);
|
nuclear@2
|
87 else if(fd >= 0)
|
nuclear@2
|
88 close(fd);
|
nuclear@2
|
89 }
|
nuclear@2
|
90
|
nuclear@2
|
91
|
nuclear@2
|
92 void proc_dev_input()
|
nuclear@2
|
93 {
|
nuclear@2
|
94 int rdbytes;
|
nuclear@2
|
95 char buf[256];
|
nuclear@2
|
96 static bool skip_line;
|
nuclear@2
|
97
|
nuclear@2
|
98 while((rdbytes = read(fd, buf, sizeof buf - 1)) > 0) {
|
nuclear@2
|
99 buf[rdbytes] = 0;
|
nuclear@2
|
100
|
nuclear@2
|
101 /* ignore our own crap */
|
nuclear@2
|
102 if(memcmp(buf, "OK,", 3) == 0 || memcmp(buf, "ERR,", 4) == 0) {
|
nuclear@2
|
103 skip_line = true;
|
nuclear@2
|
104 }
|
nuclear@2
|
105
|
nuclear@2
|
106 for(int i=0; i<rdbytes; i++) {
|
nuclear@2
|
107 if(buf[i] == '\n' || buf[i] == '\r') {
|
nuclear@2
|
108 if(!cur_line.empty()) {
|
nuclear@2
|
109 runcmd(cur_line.c_str());
|
nuclear@2
|
110 cur_line.clear();
|
nuclear@2
|
111 }
|
nuclear@2
|
112 skip_line = false;
|
nuclear@2
|
113 } else {
|
nuclear@2
|
114 if(!skip_line) {
|
nuclear@2
|
115 cur_line.push_back(buf[i]);
|
nuclear@2
|
116 }
|
nuclear@2
|
117 }
|
nuclear@2
|
118 }
|
nuclear@2
|
119 }
|
nuclear@2
|
120 }
|
nuclear@2
|
121
|
nuclear@2
|
122 void issue_ticket()
|
nuclear@2
|
123 {
|
nuclear@2
|
124 ticket++;
|
nuclear@2
|
125 last_ticket_msec = get_msec();
|
nuclear@2
|
126 if(report_inputs) {
|
nuclear@2
|
127 fprintf(fp, "ticket: %d\n", ticket);
|
nuclear@2
|
128 }
|
nuclear@11
|
129
|
nuclear@11
|
130 post_redisplay();
|
nuclear@2
|
131 }
|
nuclear@2
|
132
|
nuclear@2
|
133 void next_customer()
|
nuclear@2
|
134 {
|
nuclear@2
|
135 if(customer < ticket) {
|
nuclear@2
|
136 customer++;
|
nuclear@2
|
137 last_ticket_msec = LONG_MIN;
|
nuclear@2
|
138 if(report_inputs) {
|
nuclear@2
|
139 fprintf(fp, "customer: %d\n", customer);
|
nuclear@2
|
140 }
|
nuclear@11
|
141
|
nuclear@11
|
142 post_redisplay();
|
nuclear@2
|
143 }
|
nuclear@2
|
144 }
|
nuclear@2
|
145
|
nuclear@6
|
146 #define TICKET_SHOW_DUR 1000
|
nuclear@6
|
147
|
nuclear@6
|
148 int get_display_number()
|
nuclear@6
|
149 {
|
nuclear@6
|
150 if(get_msec() - last_ticket_msec < TICKET_SHOW_DUR) {
|
nuclear@6
|
151 return ticket;
|
nuclear@6
|
152 }
|
nuclear@6
|
153 return customer;
|
nuclear@6
|
154 }
|
nuclear@6
|
155
|
nuclear@6
|
156 int get_led_state(int led)
|
nuclear@6
|
157 {
|
nuclear@6
|
158 int ledon = get_msec() - last_ticket_msec < TICKET_SHOW_DUR ? 0 : 1;
|
nuclear@6
|
159 return led == ledon ? 1 : 0;
|
nuclear@6
|
160 }
|
nuclear@6
|
161
|
nuclear@2
|
162 #define VERSTR \
|
nuclear@12
|
163 "Queue system emulator v0.1"
|
nuclear@2
|
164
|
nuclear@2
|
165 static void runcmd(const char *cmd)
|
nuclear@2
|
166 {
|
nuclear@2
|
167 printf("DBG: runcmd(\"%s\")\n", cmd);
|
nuclear@2
|
168
|
nuclear@2
|
169 switch(cmd[0]) {
|
nuclear@2
|
170 case 'e':
|
nuclear@2
|
171 cmd_echo = !cmd_echo;
|
nuclear@2
|
172 fprintf(fp, "OK,turning echo %s\n", cmd_echo ? "on" : "off");
|
nuclear@2
|
173 break;
|
nuclear@2
|
174
|
nuclear@2
|
175 case 'i':
|
nuclear@2
|
176 report_inputs = !report_inputs;
|
nuclear@2
|
177 fprintf(fp, "OK,turning input reports %s\n", report_inputs ? "on" : "off");
|
nuclear@2
|
178 break;
|
nuclear@2
|
179
|
nuclear@2
|
180 case 'v':
|
nuclear@2
|
181 fprintf(fp, "OK,%s\n", VERSTR);
|
nuclear@2
|
182 break;
|
nuclear@2
|
183
|
nuclear@2
|
184 case 'r':
|
nuclear@2
|
185 fprintf(fp, "OK,reseting queues\n");
|
nuclear@2
|
186 customer = 0;
|
nuclear@2
|
187 ticket = 0;
|
nuclear@2
|
188 last_ticket_msec = LONG_MIN;
|
nuclear@11
|
189 post_redisplay();
|
nuclear@2
|
190 break;
|
nuclear@2
|
191
|
nuclear@2
|
192 case 't':
|
nuclear@2
|
193 fprintf(fp, "OK,ticket: %d\r\n", ticket);
|
nuclear@2
|
194 break;
|
nuclear@2
|
195
|
nuclear@2
|
196 case 'c':
|
nuclear@2
|
197 fprintf(fp, "OK,customer: %d\r\n", customer);
|
nuclear@2
|
198 break;
|
nuclear@2
|
199
|
nuclear@2
|
200 case 'q':
|
nuclear@2
|
201 fprintf(fp, "OK,issuing queue ticket\n");
|
nuclear@2
|
202 issue_ticket();
|
nuclear@2
|
203 break;
|
nuclear@2
|
204
|
nuclear@2
|
205 case 'n':
|
nuclear@2
|
206 fprintf(fp, "OK,next customer\n");
|
nuclear@2
|
207 next_customer();
|
nuclear@2
|
208 break;
|
nuclear@2
|
209
|
nuclear@2
|
210 case 'h':
|
nuclear@2
|
211 fprintf(fp, "OK,commands: (e)cho, (v)ersion, (t)icket, (c)ustomer, "
|
nuclear@2
|
212 "(n)ext, (q)ueue, (r)eset, (i)nput-reports, (h)elp.\n");
|
nuclear@2
|
213 break;
|
nuclear@2
|
214
|
nuclear@2
|
215 default:
|
nuclear@2
|
216 fprintf(fp, "ERR,unknown command: %s\n", cmd);
|
nuclear@2
|
217 }
|
nuclear@2
|
218 }
|