FreeCalypso > hg > fc-sim-tools
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 } |