Add multitrack and write support
[magstrip.git] / lmain.c
1 /* Test application for Omron card reader
2  * Copyright (C) 2009 Nils Faerber <nils.faerber@kernelconcepts.de>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17  */
18
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <sys/select.h>
22
23 #include "uart.h"
24
25 #define DLE     0x10
26 #define STX     0x02
27 #define ETX     0x03
28 #define ENQ     0x05
29 #define ACK     0x06
30 #define NAK     0x15
31 #define EOT     0x04
32
33
34 void send_command(int fd, char *cmd, int len)
35 {
36 unsigned char bcc;
37 int pos;
38 char *sbuf = NULL;
39 unsigned int sbpos = 0;
40
41         sbuf = (char *)malloc(len + 5);
42         if (sbuf == NULL) {
43                 perror("malloc");
44                 return;
45         }
46
47         sbuf[sbpos++] = DLE;
48         sbuf[sbpos++] = STX;
49         bcc = 0;
50         pos = 0;
51         while (pos < len) {
52                 sbuf[sbpos++] = cmd[pos];
53                 bcc ^= cmd[pos];
54                 if (cmd[pos] == DLE)
55                         sbuf[sbpos++] = cmd[pos];
56                 pos++;
57         }
58         sbuf[sbpos++] = DLE;
59         sbuf[sbpos++] = ETX;
60         bcc ^= ETX;
61         sbuf[sbpos++] = bcc;
62
63         write_uart(sbuf, sbpos);
64         free(sbuf);
65 }
66
67 void print_help(void)
68 {
69         fprintf(stderr, "r      -       initial RESET, required after power-on\n");
70         fprintf(stderr, "i      -       C:2 insert permit request\n");
71         fprintf(stderr, "s      -       C10 C/R status request\n");
72         fprintf(stderr, "S      -       C11 sensor status\n");
73         fprintf(stderr, "1      -       Reads ISO #1 and sends data\n");
74         fprintf(stderr, "2      -       Reads ISO #2 and sends data\n");
75         fprintf(stderr, "3      -       Reads ISO #3 and sends data\n");
76         fprintf(stderr, "m      -       Sends the read data in memory by this command\n");
77         fprintf(stderr, "M      -       Sends multi-tracks data in the memory by this command and parameter\n");
78         fprintf(stderr, "q      -       close serial and quite\n");
79         fprintf(stderr, "h      -       this help\n");
80 }
81
82 int process_user_cmd(char *rxbuf, int len, int ufd)
83 {
84 int in_cmd = 0;
85
86         switch (rxbuf[0]) {
87                 case 'i':
88                         fprintf(stderr, "Insert permit request... ");
89                         send_command(ufd, "C:2", 3);
90                         in_cmd = 1;
91                         break;
92                 case 'r':
93                         fprintf(stderr, "RESET request... ");
94                         send_command(ufd, "C00", 3);
95                         in_cmd = 1;
96                         break;
97                 case 'e':
98                         fprintf(stderr, "Eject request... ");
99                         send_command(ufd, "C30", 3);
100                         in_cmd = 1;
101                         break;
102                 case 'E':
103                         fprintf(stderr, "Eject request... ");
104                         send_command(ufd, "C31", 3);
105                         in_cmd = 1;
106                         break;
107                 case 's':
108                         fprintf(stderr, "Status request... ");
109                         send_command(ufd, "C10", 3);
110                         in_cmd = 1;
111                         break;
112                 case 'S':
113                         fprintf(stderr, "Status request... ");
114                         send_command(ufd, "C11", 3);
115                         in_cmd = 1;
116                         break;
117                 case '1':
118                         fprintf(stderr, "Status request... ");
119                         send_command(ufd, "C61", 3);
120                         in_cmd = 1;
121                         break;
122                 case '2':
123                         fprintf(stderr, "Status request... ");
124                         send_command(ufd, "C62", 3);
125                         in_cmd = 1;
126                         break;
127                 case '3':
128                         fprintf(stderr, "Status request... ");
129                         send_command(ufd, "C63", 3);
130                         in_cmd = 1;
131                         break;
132                 case 'R':
133                         fprintf(stderr, "Status request... ");
134                         send_command(ufd, "C687", 4);
135                         in_cmd = 1;
136                         break;
137                 case 'm':
138                         fprintf(stderr, "Status request... ");
139                         send_command(ufd, "C69", 3);
140                         in_cmd = 1;
141                         break;
142                 case 'M':
143                         fprintf(stderr, "Status request... ");
144                         send_command(ufd, "C6A7", 4);
145                         in_cmd = 1;
146                         break;
147                 case 'w':
148                         fprintf(stderr, "Status request... ");
149                         send_command(ufd, "C731234", 7);
150                         in_cmd = 1;
151                         break;
152                 case 'h':
153                         print_help();
154                         in_cmd = 0;
155                         break;
156                 case 'q':
157                         fprintf(stderr, "Exiting...\n");
158                         in_cmd = -1;
159                         break;
160                 default:
161                         break;
162         }
163
164         return in_cmd;
165 }
166
167 void print_multi_track(char *rxbuf, int len)
168 {
169 int bpos = 0, t, i;
170 int t1len, t2len, t3len;
171 char tmpstr[4];
172
173         fprintf(stderr, "tracks requested:      %c\n", rxbuf[bpos++]);
174         memset(tmpstr, 0, 4);
175         t=0;
176         tmpstr[t++] = rxbuf[bpos++];
177         tmpstr[t++] = rxbuf[bpos++];
178         fprintf(stderr, "t#1 read result:       %s\n", tmpstr);
179         t=0;
180         tmpstr[t++] = rxbuf[bpos++];
181         tmpstr[t++] = rxbuf[bpos++];
182         fprintf(stderr, "t#2 read result:       %s\n", tmpstr);
183         t=0;
184         tmpstr[t++] = rxbuf[bpos++];
185         tmpstr[t++] = rxbuf[bpos++];
186         fprintf(stderr, "t#3 read result:       %s\n", tmpstr);
187         memset(tmpstr, 0, 4);
188
189         t=0;
190         tmpstr[t++] = rxbuf[bpos++];
191         tmpstr[t++] = rxbuf[bpos++];
192         tmpstr[t++] = rxbuf[bpos++];
193         t1len = atoi(tmpstr);
194         fprintf(stderr, "t#1 read len:  %d\n", t1len);
195         t=0;
196         tmpstr[t++] = rxbuf[bpos++];
197         tmpstr[t++] = rxbuf[bpos++];
198         tmpstr[t++] = rxbuf[bpos++];
199         t2len = atoi(tmpstr);
200         fprintf(stderr, "t#2 read len:  %d\n", t2len);
201         t=0;
202         tmpstr[t++] = rxbuf[bpos++];
203         tmpstr[t++] = rxbuf[bpos++];
204         tmpstr[t++] = rxbuf[bpos++];
205         t3len = atoi(tmpstr);
206         fprintf(stderr, "t#3 read len:  %d\n", t3len);
207
208         fprintf(stderr, "t#1 data:      '");
209         for (i=0; i<t1len; i++) {
210                 unsigned char c = rxbuf[bpos++];
211                 if (c > 31 || c < 128)
212                         fprintf(stderr, "%c", c);
213                 else
214                         fprintf(stderr, "0x%02x ", c);
215         }
216         fprintf(stderr, "'\n");
217
218         fprintf(stderr, "t#2 data:      '");
219         for (i=0; i<t2len; i++) {
220                 unsigned char c = rxbuf[bpos++];
221                 if (c > 31 || c < 128)
222                         fprintf(stderr, "%c", c);
223                 else
224                         fprintf(stderr, "0x%02x ", c);
225         }
226         fprintf(stderr, "'\n");
227
228         fprintf(stderr, "t#3 data:      '");
229         for (i=0; i<t3len; i++) {
230                 unsigned char c = rxbuf[bpos++];
231                 if (c > 31 || c < 128)
232                         fprintf(stderr, "%c", c);
233                 else
234                         fprintf(stderr, "0x%02x ", c);
235         }
236         fprintf(stderr, "'\n");
237 }
238
239 void process_read_packet(char *rxbuf, int rxpos)
240 {
241 int bpos;
242 char cmd[2];
243
244         bpos = 2; // index into read buffer
245         if (rxbuf[bpos] == 'P') {
246                 fprintf(stderr, "positive, ");
247                 bpos++;
248                 cmd[0] = rxbuf[bpos++];
249                 cmd[1] = rxbuf[bpos++];
250                 fprintf(stderr, "cmd was '%c%c', ", cmd[0], cmd[1]);
251
252                 if (rxbuf[bpos]=='0' && rxbuf[bpos+1]=='0') {
253                         fprintf(stderr, "no card present, ");
254                 } else if (rxbuf[bpos]=='0' && rxbuf[bpos+1]=='1') {
255                         fprintf(stderr, "card at takeout, ");
256                 } else if (rxbuf[bpos]=='0' && rxbuf[bpos+1]=='2') {
257                         fprintf(stderr, "card present, ");
258                 } else
259                         fprintf(stderr, "stat is '%c%c', ", rxbuf[bpos], rxbuf[bpos+1]);
260         } else if (rxbuf[bpos] == 'N') {
261                 fprintf(stderr, "negative, ");
262                 bpos++;
263                 fprintf(stderr, "cmd was '%c%c', ", rxbuf[bpos], rxbuf[bpos+1]);
264                 bpos += 2;
265                 if (rxbuf[bpos]=='0' && rxbuf[bpos+1]=='0') {
266                         fprintf(stderr, "undefined command, ");
267                 } else if (rxbuf[bpos]=='0' && rxbuf[bpos+1]=='1') {
268                         fprintf(stderr, "command sequence error, ");
269                 } else if (rxbuf[bpos]=='0' && rxbuf[bpos+1]=='2') {
270                         fprintf(stderr, "command data error, ");
271                 } else if (rxbuf[bpos]=='0' && rxbuf[bpos+1]=='3') {
272                         fprintf(stderr, "write track setting error, ");
273                 } else if (rxbuf[bpos]=='4' && rxbuf[bpos+1]=='0') {
274                         fprintf(stderr, "SS read error, ");
275                 } else if (rxbuf[bpos]=='4' && rxbuf[bpos+1]=='1') {
276                         fprintf(stderr, "ES read error, ");
277                 } else if (rxbuf[bpos]=='4' && rxbuf[bpos+1]=='2') {
278                         fprintf(stderr, "VRC read error, ");
279                 } else if (rxbuf[bpos]=='4' && rxbuf[bpos+1]=='3') {
280                         fprintf(stderr, "LRC read error, ");
281                 } else if (rxbuf[bpos]=='4' && rxbuf[bpos+1]=='4') {
282                         fprintf(stderr, "No encode read error, ");
283                 } else if (rxbuf[bpos]=='4' && rxbuf[bpos+1]=='5') {
284                         fprintf(stderr, "No data read error, ");
285                 } else if (rxbuf[bpos]=='4' && rxbuf[bpos+1]=='6') {
286                         fprintf(stderr, "Jitter read error, ");
287                 } else
288                         fprintf(stderr, "unknown stat '%c%c', ", rxbuf[bpos], rxbuf[bpos+1]);
289         }
290
291         bpos += 2;
292         if (bpos < rxpos-3) {
293                 fprintf(stderr, "\ndata: ");
294                 if (cmd[0] == '6' && cmd[1] == 'A') {
295                         print_multi_track((rxbuf+bpos), rxpos-3);
296                 } else {
297                         while (bpos < rxpos-3) {
298                                 unsigned char c = rxbuf[bpos++];
299                                 if (c > 31 || c < 128)
300                                         fprintf(stderr, "%c", c);
301                                 else
302                                         fprintf(stderr, "0x%02x ", c);
303                         }
304                         fprintf(stderr, "\n");
305                 }
306         }
307 }
308
309 int main(int argc, char **argv)
310 {
311 char *ser_dev;
312 char rxbuf[256];
313 int ufd, rxlen=0, rxpos=0, ret=0;
314 int in_cmd = 0;
315 fd_set rfds;
316 struct timeval tval;
317
318         if (argc > 1)
319                 ser_dev = argv[1];
320         else
321                 ser_dev = "/dev/ttyS0";
322         if (open_uart(ser_dev, B9600) != 0)
323                 return -1;
324         ufd = uart_get_fd();
325         // fprintf(stderr, "UART fd = %d\n", ufd);
326
327         FD_ZERO(&rfds);
328         FD_SET(ufd, &rfds);
329         FD_SET(0, &rfds);
330         tval.tv_sec = 0;
331         tval.tv_usec = 5000000;
332
333         fprintf(stderr, "OMRON MVFW card reader terminal\non serial %s\nEnter 'h' for help\n", ser_dev);
334         while (ret >= 0) {
335                 ret = select((ufd+1), &rfds, NULL, NULL, &tval);
336                 if (ret == 0) {
337                         FD_ZERO(&rfds);
338                         FD_SET(ufd, &rfds);
339                         FD_SET(0, &rfds);
340                         tval.tv_sec = 0;
341                         tval.tv_usec = 5000000;
342                         if (rxpos > 0)
343                                 fprintf(stderr, "Select tmo but buffer not empty!\n");
344                         memset(rxbuf, 0, 256);
345                         rxpos = 0; // invalidate buffer
346                 } else if (ret > 0) {
347                         if (FD_ISSET(ufd, &rfds)) {
348                                 // fprintf(stderr, "**** select something to read ****\n");
349                                 rxlen = uart_read(rxbuf+rxpos, 255-rxpos);
350                                 rxpos += rxlen;
351                                 // fprintf(stderr, "  read %d bytes\n", rxlen);
352                                 if (rxpos == 2 && rxbuf[0] == DLE && rxbuf[1] == ACK && in_cmd == 1) {
353                                         fprintf(stderr, "got ACK requesting execute \n");
354                                         put_uart(DLE);
355                                         put_uart(ENQ);
356                                         in_cmd = 0;
357                                         memset(rxbuf, 0, 256);
358                                         rxpos = 0;
359                                 } else if (rxpos > 2 && rxbuf[rxpos-3]==DLE && rxbuf[rxpos-2]==ETX) {
360                                         // data is between DLE-STX and DLE-ETX-BCC
361                                         process_read_packet(rxbuf, rxpos);
362                                         memset(rxbuf, 0, 256);
363                                         rxpos = 0;
364                                 } //else
365                                 //      fprintf(stderr, "buf not complete yet\n");
366                         }
367                         if (FD_ISSET(0, &rfds)) {
368                                 // fprintf(stderr, "**** keypress\n");
369                                 ret = read(0, rxbuf, 255);
370                                 if (ret > 0) {
371                                         in_cmd = process_user_cmd(rxbuf, ret, ufd);
372                                         if (in_cmd == -1) {
373                                                 close(ufd);
374                                                 exit(0);
375                                         }
376                                 }
377                         }
378                         FD_ZERO(&rfds);
379                         FD_SET(ufd, &rfds);
380                         FD_SET(0, &rfds);
381
382                         fprintf(stderr, "\n> ");
383                 } else {
384                         fprintf(stderr, "select error\n");
385                         break;
386                 }
387         }
388
389         close_uart();
390
391 return 0;
392 }
393