support lower and upper case hex chars
[librfid] / utils / send_script.c
1 /*
2  *  This program is free software; you can redistribute it and/or modify
3  *  it under the terms of the GNU General Public License version 2 
4  *  as published by the Free Software Foundation
5  *
6  *  This program is distributed in the hope that it will be useful,
7  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
8  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
9  *  GNU General Public License for more details.
10  *
11  *  You should have received a copy of the GNU General Public License
12  *  along with this program; if not, write to the Free Software
13  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
14  */
15
16 #include <stdio.h>
17 #include <unistd.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <errno.h>
21 #include <ctype.h>
22
23 #define _GNU_SOURCE
24 #include <getopt.h>
25
26 #include <librfid/rfid.h>
27 #include <librfid/rfid_reader.h>
28 #include <librfid/rfid_layer2.h>
29 #include <librfid/rfid_protocol.h>
30
31 #include <librfid/rfid_protocol_mifare_classic.h>
32 #include <librfid/rfid_protocol_mifare_ul.h>
33
34 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
35
36 static const char *
37 hexdump(const void *data, unsigned int len)
38 {
39         static char string[2048];
40         unsigned char *d = (unsigned char *) data;
41         unsigned int i, left, llen = len;
42
43         string[0] = '\0';
44         left = sizeof(string);
45         for (i = 0; llen--; i += 3) {
46                 if (i >= sizeof(string) -4)
47                         break;
48                 snprintf(string+i, 4, " %02x", *d++);
49         } return string;
50         
51         if (i >= sizeof(string) -2)
52                 return string;
53         snprintf(string+i, 2, " ");
54         i++; llen = len;
55         
56         d = (unsigned char *) data;
57         for (; llen--; i += 1) {
58                 if (i >= sizeof(string) -2)
59                         break;
60                 snprintf(string+i, 2, "%c", isprint(*d) ? *d : '.');
61                 d++;
62         }
63         return string;
64 }
65
66 static struct rfid_reader_handle *rh;
67 static struct rfid_layer2_handle *l2h;
68 static struct rfid_protocol_handle *ph;
69
70 static int init()
71 {
72         unsigned char buf[0x3f];
73         int rc;
74
75         printf("initializing librfid\n");
76         rfid_init();
77
78         printf("opening reader handle\n");
79         rh = rfid_reader_open(NULL, RFID_READER_CM5121);
80         if (!rh) {
81                 fprintf(stderr, "error, no cm5121 handle\n");
82                 return -1;
83         }
84
85         printf("opening layer2 handle\n");
86         l2h = rfid_layer2_init(rh, RFID_LAYER2_ISO14443A);
87         //l2h = rfid_layer2_init(rh, RFID_LAYER2_ISO14443B);
88         if (!l2h) {
89                 fprintf(stderr, "error during iso14443a_init\n");
90                 return -1;
91         }
92
93         //rc632_register_dump(rh->ah, buf);
94
95         printf("running layer2 anticol\n");
96         rc = rfid_layer2_open(l2h);
97         if (rc < 0) {
98                 fprintf(stderr, "error during layer2_open\n");
99                 return rc;
100         }
101
102         return 0;
103 }
104
105 static int l3(int protocol)
106 {
107         printf("running layer3 (ats)\n");
108         ph = rfid_protocol_init(l2h, protocol);
109         if (!ph) {
110                 fprintf(stderr, "error during protocol_init\n");
111                 return -1;
112         }
113         if (rfid_protocol_open(ph) < 0) {
114                 fprintf(stderr, "error during protocol_open\n");
115                 return -1;
116         }
117
118         printf("we now have layer3 up and running\n");
119
120         return 0;
121 }
122
123 static int send_command(char* sbuf, int slen, char* rbuf, int rlen)
124 {
125         int rv;
126         static int doit;
127         int answer, c = 0;
128
129         if(doit == 0) {
130                 fprintf(stderr, "?? %s (%i bytes)\n", hexdump(sbuf, slen), slen);
131                 fprintf(stderr, "Execute? (Yes/No/All/Exit) ");
132                 answer = getc(stdin);
133                 if(answer != '\n') do {
134                         c = getc(stdin);
135                 } while(c != '\n' && c != EOF);
136                 switch(answer) {
137                 case 'y': // Fall-through
138                 case 'Y':
139                 case '\n':
140                         // Do nothing
141                         break;
142                 case 'n': // Fall-through
143                 case 'N':
144                         return 0;
145                         break;
146                 case 'a': // Fall-through
147                 case 'A':
148                         doit = 1;
149                         break;
150                 case 'e': // Fall-through
151                 case 'E':
152                         return -1;
153                         break;
154                 default:
155                         return 0; // Default to 'n'
156                         break;
157                 }
158         }
159
160         printf(">> %s (%i bytes)\n", hexdump(sbuf, slen), slen);
161
162         rv = rfid_protocol_transceive(ph, sbuf, slen, rbuf, &rlen, 0, 0);
163         if (rv < 0) {
164                 fprintf(stderr, "Error from transceive: %i\n", rv);
165                 return rv;
166         }
167
168         printf("<< %s (%i bytes)\n", hexdump(rbuf, rlen), rlen);
169
170         if(rlen < 2 || rbuf[rlen-2] != (char)0x90 || rbuf[rlen-1] != 0x00) {
171                 fprintf(stderr, "SW is not 90 00. Ignore (i) or Abort (a)? ");
172                 answer = getc(stdin);
173                 if(answer != '\n') do {
174                         c = getc(stdin);
175                 } while(c != '\n' && c != EOF);
176                 switch(answer) {
177                 case 'i': // Fall-through
178                 case 'I':
179                 case '\n':
180                         // Do nothing
181                         break;
182                 case 'a': // Fall-through
183                 case 'A':
184                         return -1;
185                         break;
186                 default:
187                         return -1; // Default to 'a'
188                 }
189         }
190
191         return rlen;
192 }
193
194 static char *nextline(FILE* fh)
195 {
196         int buflen = 1024; // FIXME Might want to increase dynamically?
197         char *buffer = malloc(buflen);
198         if (!buffer) {
199                 perror("malloc"); 
200                 return 0;
201         }
202
203         if (!fgets(buffer, buflen, fh)) {
204                 perror("fgets");
205                 free(buffer);
206                 return 0;
207         }
208
209         return buffer;
210 }
211
212 static int unhexchar(char c) {
213         if ((c - '0') >= 0 && (c - '0') < 10) 
214                 return c-'0';
215         if ((c - 'a') >= 0 && (c - 'a') < 6)
216                 return 10 + c-'a';
217         if ((c - 'A') >= 0 && (c - 'A') < 6)
218                 return 10 + c-'A';
219         return -1;
220 }
221
222 int make_command( const char *line, char **buffer, int *blen ) 
223 {
224         int len = strlen(line), pos;
225         *buffer = malloc( len );
226         *blen = 0;
227         if(!*buffer) {
228                 perror("malloc");
229                 return 0;
230         }
231
232         for(pos = 0; pos < len; pos++) {
233                 if(!isxdigit(line[pos]))
234                         continue;
235                 if(! (pos+1 < len) )
236                         continue;
237
238                 (*buffer)[*blen] = unhexchar(line[pos]) * 16 + unhexchar(line[pos+1]);
239                 pos += 1;
240                 *blen += 1;
241         }
242         return 1;
243 }
244
245 int main(int argc, char **argv)
246 {
247         FILE *fh;
248         int slen, rlen, retval = 0;
249         char *next, *sbuf, *rbuf;
250
251         if (argc != 2) {
252                 fprintf(stderr, "Syntax: %s scriptfile\n", argv[0]);
253                 exit(1);
254         }
255
256         fh = fopen(argv[1], "r");
257         if (!fh) {
258                 perror("fopen");
259                 exit(1);
260         }
261
262         if (init() < 0)
263                 exit(1);
264
265         if (l3(RFID_PROTOCOL_TCL) < 0)
266                 exit(1);
267
268         printf("Protocol T=CL\n");
269         /* we've established T=CL at this point */
270
271         while (next = nextline(fh)) {
272                 if (!(strlen(next) >= 2 && strncmp(next, "//", 2) == 0)) {
273                         if (make_command(next, &sbuf, &slen)) {
274                                 rlen = 1024;
275                                 rbuf = calloc(rlen, 1);
276                                 
277                                 retval = send_command(sbuf, slen, rbuf, rlen);
278
279                                 free(sbuf);
280                                 free(rbuf);
281                         }
282                 }
283                 free(next);
284
285                 if (retval < 0)
286                         break;
287         }
288
289         rfid_reader_close(rh);
290         
291         exit(0);
292 }