1 /* $Id: scrw.c,v 1.6 2001/07/20 15:51:45 rees Exp $ */
2
3 /*
4 copyright 1997, 1999, 2000
5 the regents of the university of michigan
6 all rights reserved
7
8 permission is granted to use, copy, create derivative works
9 and redistribute this software and such derivative works
10 for any purpose, so long as the name of the university of
11 michigan is not used in any advertising or publicity
12 pertaining to the use or distribution of this software
13 without specific, written prior authorization. if the
14 above copyright notice or any other identification of the
15 university of michigan is included in any copy of any
16 portion of this software, then the disclaimer below must
17 also be included.
18
19 this software is provided as is, without representation
20 from the university of michigan as to its fitness for any
21 purpose, and without warranty by the university of
22 michigan of any kind, either express or implied, including
23 without limitation the implied warranties of
24 merchantability and fitness for a particular purpose. the
25 regents of the university of michigan shall not be liable
26 for any damages, including special, indirect, incidental, or
27 consequential damages, with respect to any claim arising
28 out of or in connection with the use of the software, even
29 if it has been or is hereafter advised of the possibility of
30 such damages.
31 */
32
33 /*
34 * OS independent part
35 *
36 * Jim Rees, University of Michigan, October 1997
37 */
38
39 #ifdef __palmos__
40 #include <Common.h>
41 #include <System/SysAll.h>
42 #include <System/Unix/unix_stdio.h>
43 #include <System/Unix/unix_stdlib.h>
44 #include <System/Unix/unix_string.h>
45 #include <UI/UIAll.h>
46 #include "field.h"
47 #else
48 #include <stdio.h>
49 #include <string.h>
50 #endif
51 #ifdef SCPERF
52 #define SCPERF_FIRST_APPEARANCE
53 #endif /* SCPERF */
54 #include "sectok.h"
55 #include "sc7816.h"
56 #include "todos_scrw.h"
57
58 /* external variable */
59 #ifdef BYTECOUNT
60 extern int num_getc, num_putc;
61 #endif /* BYTECOUNT */
62
63 struct scparam scparam[4];
64
65 /* reset the card, and return answer to reset (atr) */
66
67 int
todos_scxreset(int ttyn,int flags,unsigned char * atr,int * ep)68 todos_scxreset(int ttyn, int flags, unsigned char *atr, int *ep)
69 {
70 unsigned char buf[33];
71 int n, err;
72
73 if (ep)
74 *ep = SCEOK;
75 else
76 ep = &err;
77
78 if (!todos_sccardpresent(ttyn)) {
79 *ep = SCENOCARD;
80 return 0;
81 }
82
83 if (!atr)
84 atr = buf;
85
86 if (!(flags & SCRTODOS) && (todos_scsetflags(ttyn, 0, 0) & SCOXDTR))
87 flags |= SCRTODOS;
88
89 todos_scsetspeed(ttyn, 9600);
90 todos_scsetflags(ttyn, 0, SCOINVRT);
91
92 if (todos_scdtr(ttyn, (flags & SCRTODOS)) < 0) {
93 *ep = SCENOCARD;
94 return 0;
95 }
96
97 /* 7816-3 sec 5.2 says >= 40000 clock cycles, ~=12 msec */
98 scsleep(20);
99
100 todos_scdtr(ttyn, !(flags & SCRTODOS));
101
102 n = todos_get_atr(ttyn, flags, atr, &scparam[ttyn]);
103 if (!n && ep)
104 *ep = SCESLAG;
105 if (scparam[ttyn].t < 0 && ep)
106 *ep = SCENOSUPP;
107
108 return n;
109 }
110
111 static int
todos_scioproc(int ttyn,int io,unsigned char * cp)112 todos_scioproc(int ttyn, int io, unsigned char *cp)
113 {
114 int code;
115
116 /* Wait extra guard time if needed */
117 if (!io && scparam[ttyn].n)
118 scsleep(((scparam[ttyn].n * scparam[ttyn].etu) + 999) / 1000);
119
120 code = (!io ? scputc(ttyn, *cp) : scgetc(ttyn, cp, scparam[ttyn].cwt));
121
122 return code;
123 }
124
125 /* This does the real work of transferring data to or from the card. Since the ack
126 handling is the same for both send and receive, we do it all here. */
127
128 static int
todos_scioT0(int ttyn,int io,int cla,int ins,int p1,int p2,int p3,unsigned char * buf,int * sw1p,int * sw2p)129 todos_scioT0(int ttyn, int io, int cla, int ins, int p1, int p2, int p3, unsigned char *buf, int *sw1p, int *sw2p)
130 {
131 int n = 0, ack, ackxins;
132 unsigned char *bp = buf, c, apdu[5];
133 #ifdef BYTECOUNT
134 int tmp_num_getc, tmp_num_putc;
135 #endif /* BYTECOUNT */
136
137 #ifdef BYTECOUNT
138 tmp_num_getc = num_getc;
139 tmp_num_putc = num_putc;
140 #endif /* BYTECOUNT */
141
142 #ifdef SCPERF
143 SetTime("SCIO starts");
144 #endif /* SCPERF */
145
146 #ifdef DEBUG
147 printf("scioT0 %3s %02x %02x %02x %02x %02x\n", io ? "out" : "in", cla, ins, p1, p2, p3);
148 #endif
149
150 apdu[0] = cla;
151 apdu[1] = ins;
152 apdu[2] = p1;
153 apdu[3] = p2;
154 apdu[4] = p3;
155 scputblk(ttyn, apdu, 5);
156
157 #ifdef SCPERF
158 SetTime("Finish sending APDU");
159 #endif /* SCPERF */
160
161 while (1) {
162 /* read ack byte; see 7816-3 8.2.2 */
163 if (scgetc(ttyn, &c, scparam[ttyn].cwt) != SCEOK) {
164 #ifdef DEBUG
165 printf("%d ms timeout reading ack\n", scparam[ttyn].cwt);
166 #endif
167 return -1;
168 }
169 ack = c;
170
171 if (ack == 0x60) {
172 /* null (no-op but resets timer) */
173 #ifdef DEBUG
174 printf("got 0x60 (null) ack; reset timer\n");
175 #endif
176 continue;
177 }
178
179 if ((ack & 0xf0) == 0x60 || (ack & 0xf0) == 0x90) {
180 /* SW1; get SW2 and return */
181 *sw1p = ack;
182 if (scgetc(ttyn, &c, scparam[ttyn].cwt) != SCEOK) {
183 #ifdef DEBUG
184 printf("%d ms timeout reading sw2\n", scparam[ttyn].cwt);
185 #endif
186 return -1;
187 }
188 *sw2p = (c & 0xff);
189 break;
190 }
191
192 /* we would set VPP here if the interface supported it */
193
194 ackxins = (ack ^ ins) & 0xfe;
195 if (ackxins == 0xfe) {
196 if (n < p3) {
197 /* xfer next data byte */
198 if (todos_scioproc(ttyn, io, bp++) != SCEOK) {
199 #ifdef DEBUG
200 printf("%d ms timeout reading next data byte\n", scparam[ttyn].cwt);
201 #endif
202 return -1;
203 }
204 n++;
205 }
206
207 } else if (ackxins == 0) {
208 /* xfer all remaining data bytes */
209 while (n < p3) {
210 if (todos_scioproc(ttyn, io, bp++) != SCEOK) {
211 #ifdef DEBUG
212 printf("%d ms timeout reading all remaining data bytes\n", scparam[ttyn].cwt);
213 #endif
214 return -1;
215 }
216 n++;
217 }
218 #ifdef SCPERF
219 SetTime("Finish sending or receiving DATA");
220 #endif /* SCPERF */
221 } else {
222 /* ?? unknown ack byte */
223 #ifdef DEBUG
224 printf("unknown ack %x\n", ack);
225 continue;
226 #else
227 return -1;
228 #endif
229 }
230 }
231
232 #ifdef SCPERF
233 SetTime("Finish scio");
234 #endif /* SCPERF */
235
236 #ifdef BYTECOUNT
237 tmp_num_putc = num_putc - tmp_num_putc;
238 tmp_num_getc = num_getc - tmp_num_getc - tmp_num_putc;
239 MESSAGE3("#getc=%d, #putc=%d\n", tmp_num_getc, tmp_num_putc);
240 #endif /* BYTECOUNT */
241
242 return n;
243 }
244
245 int
todos_scrw(int ttyn,int cla,int ins,int p1,int p2,int ilen,unsigned char * ibuf,int olen,unsigned char * obuf,int * sw1p,int * sw2p)246 todos_scrw(int ttyn, int cla, int ins, int p1, int p2, int ilen, unsigned char *ibuf, int olen, unsigned char *obuf, int *sw1p, int *sw2p)
247 {
248 int r;
249
250 if (scparam[ttyn].t == 0) {
251 if (ilen > 0 && ibuf) {
252 /* Send "in" data */
253 r = (todos_scioT0(ttyn, 0, cla, ins, p1, p2, ilen, ibuf, sw1p, sw2p) >= 0) ? 0 : -1;
254 if (r >= 0 && *sw1p == 0x61 && olen >= *sw2p && obuf) {
255 /* Response available; get it */
256 r = todos_scioT0(ttyn, 1, cla, 0xc0, 0, 0, *sw2p, obuf, sw1p, sw2p);
257 }
258 } else {
259 /* Get "out" data */
260 r = todos_scioT0(ttyn, 1, cla, ins, p1, p2, olen, obuf, sw1p, sw2p);
261 }
262 #ifndef NO_T_EQ_1
263 } else if (scparam[ttyn].t == 1) {
264 r = scioT1(ttyn, cla, ins, p1, p2, ilen, ibuf, olen, obuf, sw1p, sw2p);
265 #endif
266 } else
267 r = -1;
268
269 return r;
270 }
271