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