eqemu

annotate src/dev.cc @ 12:2656099aff12

added copyright notices and license
author John Tsiombikas <nuclear@member.fsf.org>
date Fri, 18 Jul 2014 07:04:21 +0300
parents 2b559dc24c7b
children
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 }