comparison serial/collect_atr.c @ 38:1d96f3b4f155

serial: started with fcsim-serial-atr
author Mychaela Falconia <falcon@freecalypso.org>
date Sat, 20 Mar 2021 19:19:46 +0000
parents
children
comparison
equal deleted inserted replaced
37:4e5586c7f275 38:1d96f3b4f155
1 /*
2 * This module contains the code for collecting ATR bytes from the SIM,
3 * as well as subsequent byte Rx.
4 */
5
6 #include <sys/types.h>
7 #include <sys/time.h>
8 #include <sys/errno.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <unistd.h>
12
13 extern int target_fd;
14
15 #define MAX_ATR_BYTES 33
16
17 extern unsigned char inverse_coding_table[256];
18
19 u_char atr_buf[MAX_ATR_BYTES];
20 unsigned atr_length;
21 int inverse_coding;
22
23 void
24 invert_bytes(buf, nbytes)
25 u_char *buf;
26 unsigned nbytes;
27 {
28 unsigned n;
29
30 for (n = 0; n < nbytes; n++)
31 buf[n] = inverse_coding_table[buf[n]];
32 }
33
34 collect_bytes_from_sim(buf, expect_len)
35 u_char *buf;
36 unsigned expect_len;
37 {
38 fd_set fds;
39 struct timeval tv;
40 unsigned rcvd;
41 int cc;
42
43 for (rcvd = 0; rcvd < expect_len; ) {
44 FD_ZERO(&fds);
45 FD_SET(target_fd, &fds);
46 tv.tv_sec = 2;
47 tv.tv_usec = 0;
48 cc = select(target_fd+1, &fds, NULL, NULL, &tv);
49 if (cc < 0) {
50 if (errno == EINTR)
51 continue;
52 perror("select");
53 return(-1);
54 }
55 if (cc < 1) {
56 fprintf(stderr,
57 "error: timeout waiting for byte(s) from SIM\n");
58 return(-1);
59 }
60 cc = read(target_fd, buf + rcvd, expect_len - rcvd);
61 if (cc <= 0) {
62 perror("read after successful select");
63 return(-1);
64 }
65 rcvd += cc;
66 }
67 if (inverse_coding)
68 invert_bytes(buf, rcvd);
69 return(0);
70 }
71
72 check_atr_tck()
73 {
74 unsigned b, p;
75
76 b = 0;
77 for (p = 1; p < atr_length; p++)
78 b ^= atr_buf[p];
79 if (b) {
80 fprintf(stderr, "error: ATR checksum is bad\n");
81 return(-1);
82 }
83 return(0);
84 }
85
86 collect_atr()
87 {
88 int rc;
89 unsigned count, y, nhist, have_tck;
90
91 rc = collect_bytes_from_sim(atr_buf, 2);
92 if (rc < 0)
93 return(rc);
94 if (atr_buf[0] == 0x3B) {
95 /* direct convention */
96 } else if (atr_buf[0] == 0x03) {
97 /* inverse convention */
98 inverse_coding = 1;
99 atr_buf[0] = 0x3F;
100 atr_buf[1] = inverse_coding_table[atr_buf[1]];
101 } else {
102 fprintf(stderr,
103 "error: received TS=0x%02X, matches neither convention\n",
104 atr_buf[0]);
105 return(-1);
106 }
107 atr_length = 2;
108 nhist = atr_buf[1] & 0x0F;
109 y = atr_buf[1] & 0xF0;
110 have_tck = 0;
111 while (y) {
112 count = 0;
113 if (y & 0x10)
114 count++;
115 if (y & 0x20)
116 count++;
117 if (y & 0x40)
118 count++;
119 if (y & 0x80)
120 count++;
121 if (atr_length + count > MAX_ATR_BYTES) {
122 atr_too_long: fprintf(stderr, "error: ATR exceeds 33 byte limit\n");
123 return(-1);
124 }
125 rc = collect_bytes_from_sim(atr_buf + atr_length, count);
126 if (rc < 0)
127 return(rc);
128 atr_length += count;
129 if (y & 0x80) {
130 y = atr_buf[atr_length-1] & 0xF0;
131 if (atr_buf[atr_length-1] & 0x0F)
132 have_tck = 1;
133 } else
134 y = 0;
135 }
136 count = nhist + have_tck;
137 if (count) {
138 if (atr_length + count > MAX_ATR_BYTES)
139 goto atr_too_long;
140 rc = collect_bytes_from_sim(atr_buf + atr_length, count);
141 if (rc < 0)
142 return(rc);
143 atr_length += count;
144 }
145 if (have_tck)
146 return check_atr_tck();
147 else
148 return 0;
149 }
150
151 void
152 print_atr(head)
153 char *head;
154 {
155 unsigned n;
156
157 fputs(head, stdout);
158 for (n = 0; n < atr_length; n++) {
159 printf(" %02X", atr_buf[n]);
160 }
161 putchar('\n');
162 }