source: trunk/csctapi/pps.c@ 1288

Last change on this file since 1288 was 1288, checked in by dingo35, 11 years ago

Remove dynamic datastructure PPS

File size: 17.0 KB
Line 
1/*
2 pps.c
3 Protocol Parameters Selection
4
5 This file is part of the Unix driver for Towitoko smartcard readers
6 Copyright (C) 2000 2001 Carlos Prados <cprados@yahoo.com>
7
8 This version is modified by doz21 to work in a special manner ;)
9
10 This library is free software; you can redistribute it and/or
11 modify it under the terms of the GNU Lesser General Public
12 License as published by the Free Software Foundation; either
13 version 2 of the License, or (at your option) any later version.
14
15 This library is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 Lesser General Public License for more details.
19
20 You should have received a copy of the GNU Lesser General Public
21 License along with this library; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23*/
24
25#include "pps.h"
26#include "atr.h"
27#include "protocol_t0.h"
28#include "protocol_t1.h"
29#include <stdlib.h>
30#include <stdio.h>
31#include <string.h>
32#include "ifd.h"
33#include "../globals.h"
34
35/*
36 * Not exported constants definition
37 */
38
39#define PPS_DEFAULT_PROTOCOL 0x00
40#define PROTOCOL_T0_DEFAULT_WI 10
41
42#define PROTOCOL_T1_DEFAULT_IFSC 32
43#define PROTOCOL_T1_DEFAULT_IFSD 32
44#define PROTOCOL_T1_MAX_IFSC 251 /* Cannot send > 255 buffer */
45#define PROTOCOL_T1_DEFAULT_CWI 13
46#define PROTOCOL_T1_DEFAULT_BWI 4
47#define PROTOCOL_T1_EDC_LRC 0
48#define PROTOCOL_T1_EDC_CRC 1
49/*
50 * Not exported macros definition
51 */
52
53#define PPS_HAS_PPS1(block) ((block[1] & 0x10) == 0x10)
54#define PPS_HAS_PPS2(block) ((block[1] & 0x20) == 0x20)
55#define PPS_HAS_PPS3(block) ((block[1] & 0x40) == 0x40)
56
57/*
58 * Not exported funtions declaration
59 */
60
61static int PPS_Exchange (BYTE * params, unsigned *length);
62
63static bool PPS_Match (BYTE * request, unsigned len_request, BYTE * reply, unsigned len_reply);
64
65static unsigned PPS_GetLength (BYTE * block);
66
67static int PPS_InitICC ();
68
69static int PPS_InitProtocol ();
70
71static BYTE PPS_GetPCK (BYTE * block, unsigned length);
72
73/*
74 * Exported functions definition
75 */
76
77void PPS_New ()
78{
79 protocol = NULL;
80 parameters.t = PPS_DEFAULT_PROTOCOL;
81 parameters.FI = ATR_DEFAULT_FI;
82 parameters.d = ATR_DEFAULT_D;
83 parameters.n = ATR_DEFAULT_N;
84}
85
86int PPS_Perform (BYTE * params, unsigned *length)
87{
88 //Performs PPS Exchange on command when *length >0
89 //If unsuccesfull, or when length <= 0
90 //Gets parametes from ATR
91 //If necessary perform PPS session
92 //
93 //Output is pps->params.FI,n,d,t set with correct values
94 //and switched SC-device conform these values to correct baudrate
95 //
96 //We need to store FI instread of F, because SCI_DEV works with FI
97 //and it is easier to overclock then
98 //also from FI -> F is easy, other way around not
99
100 int ret;
101 bool PPS_success;
102
103 /* Perform PPS Exchange if requested by command */
104 if ((*length) > 0)
105 {
106 ret = PPS_Exchange (params, length);
107
108 /* Get parameters from PPS handsake */
109 if (ret == PPS_OK)
110 {
111 parameters.t = params[1] & 0x0F;
112
113 if (PPS_HAS_PPS1 (params))
114 {
115 parameters.FI = (params[2] >> 4);
116 parameters.d = atr_d_table[(params[2] & 0x0F)];
117 }
118
119/*
120 ret = PPS_InitICC();
121
122 if (ret != PPS_OK)
123 return ret;
124*/
125 }
126/*
127 else
128 {
129 return ret;
130 }
131*/
132 }
133 PPS_success = PPS_OK;
134 int protocol_selected = 0; //stores which TAi,TBi etc. bytes must be used 0 means not set
135 if ((*length) <= 0 || !PPS_success) // If not by command, or PPS Exchange by command failed: Try PPS Exchange by ATR or Get parameters from ATR
136 {
137 int numprot = atr->pn;
138 //if there is a trailing TD, this number is one too high
139 BYTE tx;
140 if (ATR_GetInterfaceByte (atr, numprot-1, ATR_INTERFACE_BYTE_TD, &tx) == ATR_OK)
141 if ((tx & 0xF0) == 0)
142 numprot--;
143 cs_debug("ATR reports %i protocol lines:",numprot);
144 int i,point;
145 char txt[50];
146 bool OffersT[3]; //T14 stored as T2
147 for (i = 0; i <= 2; i++)
148 OffersT[i] = FALSE;
149 for (i=1; i<= numprot; i++) {
150 point = 0;
151 if (ATR_GetInterfaceByte (atr, i, ATR_INTERFACE_BYTE_TA, &tx) == ATR_OK) {
152 sprintf((char *)txt+point,"TA%i=%02X ",i,tx);
153 point +=7;
154 }
155 if (ATR_GetInterfaceByte (atr, i, ATR_INTERFACE_BYTE_TB, &tx) == ATR_OK) {
156 sprintf((char *)txt+point,"TB%i=%02X ",i,tx);
157 point +=7;
158 }
159 if (ATR_GetInterfaceByte (atr, i, ATR_INTERFACE_BYTE_TC, &tx) == ATR_OK) {
160 sprintf((char *)txt+point,"TC%i=%02X ",i,tx);
161 point +=7;
162 }
163 if (ATR_GetInterfaceByte (atr, i, ATR_INTERFACE_BYTE_TD, &tx) == ATR_OK) {
164 sprintf((char *)txt+point,"TD%i=%02X ",i,tx);
165 point +=7;
166 tx &= 0X0F;
167 sprintf((char *)txt+point,"(T%i)",tx);
168 if (tx == 14)
169 OffersT[2] = TRUE;
170 else
171 OffersT[tx] = TRUE;
172 }
173 else {
174 sprintf((char *)txt+point,"no TD%i means T0",i);
175 OffersT[0] = TRUE;
176 }
177 cs_debug("%s",txt);
178 }
179
180 int numprottype = 0;
181 for (i = 0; i <= 2; i++)
182 if (OffersT[i])
183 numprottype ++;
184 cs_debug("%i protocol types detected. Historical bytes: %s",numprottype, cs_hexdump(1,atr->hb,atr->hbn));
185
186//If more than one protocol type and/or TA1 parameter values other than the default values and/or N equeal to 255 is/are indicated in the answer to reset, the card shall know unambiguously, after having sent the answer to reset, which protocol type or/and transmission parameter values (FI, D, N) will be used. Consequently a selection of the protocol type and/or the transmission parameters values shall be specified.
187 ATR_GetParameter (atr, ATR_PARAMETER_N, &(parameters.n));
188 ATR_GetProtocolType(atr,1,&(parameters.t)); //get protocol from TD1
189 BYTE TA2;
190 bool SpecificMode = (ATR_GetInterfaceByte (atr, 2, ATR_INTERFACE_BYTE_TA, &TA2) == ATR_OK); //if TA2 present, specific mode, else negotiable mode
191 if (SpecificMode) {
192 parameters.t = TA2 & 0x0F;
193 if ((TA2 & 0x10) != 0x10) { //bit 5 set to 0 means F and D explicitly defined in interface characters
194 BYTE TA1;
195 if (ATR_GetInterfaceByte (atr, 1 , ATR_INTERFACE_BYTE_TA, &TA1) == ATR_OK) {
196 parameters.FI = TA1 >> 4;
197 ATR_GetParameter (atr, ATR_PARAMETER_D, &(parameters.d));
198 }
199 else {
200 parameters.FI = ATR_DEFAULT_FI;
201 parameters.d = ATR_DEFAULT_D;
202 }
203 }
204 else {
205 cs_log("Specific mode: speed 'implicitly defined', not sure how to proceed, assuming default values");
206 parameters.FI = ATR_DEFAULT_FI;
207 parameters.d = ATR_DEFAULT_D;
208 }
209 cs_debug("Specific mode: T%i, F=%.0f, D=%.6f, N=%.0f\n", parameters.t, (double) atr_f_table[parameters.FI], parameters.d, parameters.n);
210 }
211 else { //negotiable mode
212
213 bool NeedsPTS = ((parameters.t != 14) && (numprottype > 1 || (atr->ib[0][ATR_INTERFACE_BYTE_TA].present == TRUE && atr->ib[0][ATR_INTERFACE_BYTE_TA].value != 0x11) || parameters.n == 255)); //needs PTS according to ISO 7816 , SCI gets stuck on our PTS
214 if (NeedsPTS) {
215 // PTSS PTS0 PTS1 PTS2 PTS3 PCK
216 // PTSS PTS0 PTS1 PCK
217 BYTE req[] = { 0xFF, 0x10, 0x00, 0x00 }; //we currently do not support PTS2, standard guardtimes
218 req[1]=0x10 | parameters.t; //PTS0 always flags PTS1 to be sent always
219 if (ATR_GetInterfaceByte (atr, 1, ATR_INTERFACE_BYTE_TA, &req[2]) != ATR_OK) //PTS1
220 req[2] = 0x11; //defaults FI and DI to 1
221 //req[3]=PPS_GetPCK(req,sizeof(req)-1); will be set by PPS_Exchange
222 unsigned int len = sizeof(req);
223 ret = PPS_Exchange (req, &len);
224 if (ret == PPS_OK) {
225 parameters.FI = req[2] >> 4;
226 BYTE DI = req[2] & 0x0F;
227 parameters.d = (double) (atr_d_table[DI]);
228 PPS_success = TRUE;
229 cs_debug("PTS Succesfull, selected protocol: T%i, F=%.0f, D=%.6f, N=%.0f\n", parameters.t, (double) atr_f_table[parameters.FI], parameters.d, parameters.n);
230 }
231 else
232 cs_ddump(req,4,"PTS Failure, response:");
233 }
234
235 //FIXME Currently InitICC sets baudrate to 9600 for all T14 cards (=no switching);
236 //When for SCI, T14 protocol, TA1 is obeyed, this goes OK for mosts devices, but somehow on DM7025 Sky S02 card goes wrong when setting ETU (ok on DM800/DM8000)
237 if (!PPS_success) {//last PPS not succesfull
238 BYTE TA1;
239 if (ATR_GetInterfaceByte (atr, 1 , ATR_INTERFACE_BYTE_TA, &TA1) == ATR_OK) {
240 parameters.FI = TA1 >> 4;
241 ATR_GetParameter (atr, ATR_PARAMETER_D, &(parameters.d));
242 }
243 else { //do not obey TA1
244 parameters.FI = ATR_DEFAULT_FI;
245 parameters.d = ATR_DEFAULT_D;
246 }
247 ATR_GetProtocolType (atr, 1, &(parameters.t));
248 protocol_selected = 1;
249
250 if (NeedsPTS) {
251 if ((parameters.d == 32) || (parameters.d == 12) || (parameters.d == 20))
252 parameters.d = 0; //behave conform "old" atr_d_table; viaccess cards that fail PTS need this
253 }
254 /////Here all non-ISO behaviour
255 /////End all non-ISO behaviour
256
257 cs_debug("No PTS %s, selected protocol T%i, F=%.0f, D=%.6f, N=%.0f\n", NeedsPTS?"happened":"needed", parameters.t, (double) atr_f_table[parameters.FI], parameters.d, parameters.n);
258 }
259 }//end negotiable mode
260 }//end length<0
261
262 //make sure no zero values
263 double F = (double) atr_f_table[parameters.FI];
264 if (!F) {
265 parameters.FI = ATR_DEFAULT_FI;
266 cs_log("Warning: F=0 is invalid, forcing FI=%d", parameters.FI);
267 }
268 if (!parameters.d) {
269 parameters.d = ATR_DEFAULT_D;
270 cs_log("Warning: D=0 is invalid, forcing D=%.0f",parameters.d);
271 }
272
273 protocol_type = parameters.t;
274
275#ifdef DEBUG_PROTOCOL
276 printf("PPS: T=%i, F=%.0f, D=%.6f, N=%.0f\n",
277 parameters.t,
278 F,
279 parameters.d,
280 parameters.n);
281#endif
282
283 ret = PPS_InitICC();
284
285 if (ret != PPS_OK)
286 return ret;
287
288 /* Initialize selected protocol with selected parameters */
289 return PPS_InitProtocol ();
290}
291
292PPS_ProtocolParameters *PPS_GetProtocolParameters ()
293{
294 /* User must Remember not to reference this struct after removing PPS */
295 return &(parameters);
296}
297
298/*
299 * Not exported funtions definition
300 */
301
302static int PPS_Exchange (BYTE * params, unsigned *length)
303{
304 BYTE confirm[PPS_MAX_LENGTH];
305 unsigned len_request, len_confirm;
306 int ret;
307#ifdef DEBUG_PROTOCOL
308 int i;
309#endif
310
311 len_request = PPS_GetLength (params);
312 params[len_request - 1] = PPS_GetPCK(params, len_request - 1);
313
314#ifdef DEBUG_PROTOCOL
315 printf ("PPS: Sending request: ");
316 for (i = 0; i < len_request; i++)
317 printf ("%X ", params[i]);
318 printf ("\n");
319#endif
320
321 cs_debug("PTS: Sending request: %s", cs_hexdump(1, params, len_request));
322
323 /* Send PPS request */
324#ifdef COOL
325 //unsigned char ptsAck[10];
326 //u_int8 ptsLen = len_request;
327 unsigned short int ptsLen = len_request;
328 int Status = cnxt_smc_start_pps(handle, params, confirm, &ptsLen, TRUE);
329 printf ("cnxt_smc_start_pps Status=%i\n", Status);
330 len_confirm = ptsLen;
331#ifdef DEBUG_PROTOCOL
332 printf("COOL: confirm: \n");
333 for (i = 0; i < ptsLen; i++)
334 printf ("%02X", confirm[i]);
335 printf ("\n");
336 fflush(stdout);
337 printf("COOL: req: \n");
338 for (i = 0; i < len_request; i++)
339 printf ("%02X", params[i]);
340 printf ("\n");
341 fflush(stdout);
342#endif
343 if (Status)
344 return PPS_HANDSAKE_ERROR;
345#else
346 if (ICC_Async_Transmit (len_request, params) != ICC_ASYNC_OK)
347 return PPS_ICC_ERROR;
348
349 /* Get PPS confirm */
350 if (ICC_Async_Receive (2, confirm) != ICC_ASYNC_OK)
351 return PPS_ICC_ERROR;
352
353 len_confirm = PPS_GetLength (confirm);
354
355 if (ICC_Async_Receive (len_confirm - 2, confirm + 2) != ICC_ASYNC_OK)
356 return PPS_ICC_ERROR;
357
358#ifdef DEBUG_PROTOCOL
359 printf ("PPS: Receivig confirm: ");
360 for (i = 0; i < len_confirm; i++)
361 printf ("%X ", confirm[i]);
362 printf ("\n");
363#endif
364
365 cs_debug("PTS: Receiving confirm: %s", cs_hexdump(1, confirm, len_confirm));
366
367 if (!PPS_Match (params, len_request, confirm, len_confirm))
368 ret = PPS_HANDSAKE_ERROR;
369 else
370 ret = PPS_OK;
371#endif
372
373 /* Copy PPS handsake */
374 memcpy (params, confirm, len_confirm);
375 (*length) = len_confirm;
376
377 return ret;
378}
379
380static bool PPS_Match (BYTE * request, unsigned len_request, BYTE * confirm, unsigned len_confirm)
381{
382 /* See if the reply differs from request */
383 if ((len_request != len_confirm) || (memcmp (request, confirm, len_request)))
384 {
385 /* See if the card specifies other than default FI and D */
386 //if ((PPS_HAS_PPS1 (confirm)) && (confirm[2] != request[2]))
387 return FALSE;
388 }
389
390 return TRUE;
391}
392
393static unsigned PPS_GetLength (BYTE * block)
394{
395 unsigned length = 3;
396
397 if (PPS_HAS_PPS1 (block))
398 length++;
399
400 if (PPS_HAS_PPS2 (block))
401 length++;
402
403 if (PPS_HAS_PPS3 (block))
404 length++;
405
406 return length;
407}
408
409static int PPS_InitICC ()
410{
411#ifdef SCI_DEV
412#include <sys/ioctl.h>
413#include "sci_global.h"
414#include "sci_ioctl.h"
415 if(reader[ridx].typ == R_INTERNAL)
416 {
417 int n;
418 SCI_PARAMETERS params;
419 //memset(&params,0,sizeof(SCI_PARAMETERS));
420 if (ioctl(reader[ridx].handle, IOCTL_GET_PARAMETERS, &params) < 0 )
421 return PPS_ICC_ERROR;
422
423 params.T = parameters.t;
424 params.fs = atr_fs_table[parameters.FI] / 1000000;
425 double F = (double) atr_f_table[parameters.FI];
426 //for Irdeto T14 cards, do not set ETU
427 if (!(atr->hbn >= 6 && !memcmp(atr->hb, "IRDETO", 6) && params.T == 14))
428 params.ETU = F / parameters.d;
429 if (parameters.n == 255) //only for T0 or also for T1?
430 params.EGT = 0;
431 else
432 params.EGT = parameters.n;
433
434 double a;
435 ATR_GetParameter(atr, ATR_PARAMETER_P, &a);
436 params.P=(unsigned char)a;
437 ATR_GetParameter(atr, ATR_PARAMETER_I, &a);
438 params.I=(unsigned char)a;
439
440 cs_debug("Setting T=%d fs=%lu mhz ETU=%d WWT=%d CWT=%d BWT=%d EGT=%d clock=%d check=%d P=%d I=%d U=%d", (int)params.T, params.fs, (int)params.ETU, (int)params.WWT, (int)params.CWT, (int)params.BWT, (int)params.EGT, (int)params.clock_stop_polarity, (int)params.check, (int)params.P, (int)params.I, (int)params.U);
441
442 if (ioctl(reader[ridx].handle, IOCTL_SET_PARAMETERS, &params)!=0)
443 return PPS_ICC_ERROR;
444
445 }
446#elif COOL
447 if(reader[ridx].typ == R_INTERNAL) {
448 int mhz = atr_fs_table[parameters.FI] / 10000;
449 if (!Cool_SetBaudrate(mhz))
450 return PPS_ICC_ERROR;
451#ifdef DEBUG_PROTOCOL
452 printf("Coolstream: set clock to %i * 10kHz\n", mhz);
453#endif
454 return PPS_OK;
455 }
456#endif
457 {
458 unsigned long baudrate;
459 double F = (double) atr_f_table[parameters.FI];
460 if (parameters.t == 14)
461 baudrate = 9600;
462 else
463 baudrate = parameters.d * ICC_Async_GetClockRate () / F;
464
465#ifdef DEBUG_PROTOCOL
466 printf ("PPS: Baudrate = %d\n", (int)baudrate);
467#endif
468
469
470 if (ICC_Async_SetBaudrate (baudrate) != ICC_ASYNC_OK)
471 return PPS_ICC_ERROR;
472
473 return PPS_OK;
474 }
475}
476
477int Protocol_T1_Init ()
478{
479 BYTE ta, tb, tc, cwi, bwi;
480 unsigned long baudrate;
481 double work_etu;
482
483 // Set IFSC
484 if (ATR_GetInterfaceByte (atr, 3, ATR_INTERFACE_BYTE_TA, &ta) == ATR_NOT_FOUND)
485 ifsc = PROTOCOL_T1_DEFAULT_IFSC;
486 else if ((ta != 0x00) && (ta != 0xFF))
487 ifsc = ta;
488 else
489 ifsc = PROTOCOL_T1_DEFAULT_IFSC;
490
491 // Towitoko does not allow IFSC > 251 //FIXME not sure whether this limitation still exists
492 ifsc = MIN (ifsc, PROTOCOL_T1_MAX_IFSC);
493
494 // Set IFSD
495 ifsd = PROTOCOL_T1_DEFAULT_IFSD;
496
497#ifndef PROTOCOL_T1_USE_DEFAULT_TIMINGS
498 // Calculate CWI and BWI
499 if (ATR_GetInterfaceByte (atr, 3, ATR_INTERFACE_BYTE_TB, &tb) == ATR_NOT_FOUND)
500 {
501#endif
502 cwi = PROTOCOL_T1_DEFAULT_CWI;
503 bwi = PROTOCOL_T1_DEFAULT_BWI;
504#ifndef PROTOCOL_T1_USE_DEFAULT_TIMINGS
505 }
506 else
507 {
508 cwi = tb & 0x0F;
509 bwi = tb >> 4;
510 }
511#endif
512
513 // Work etu = (1000 / baudrate) milliseconds
514 ICC_Async_GetBaudrate (&baudrate);
515 work_etu = 1000 / (double)baudrate;
516
517 // Set CWT = (2^CWI + 11) work etu
518 cwt = (unsigned short) (((1<<cwi) + 11) * work_etu);
519
520 // Set BWT = (2^BWI * 960 + 11) work etu
521 bwt = (unsigned short) (((1<<bwi) * 960 + 11) * work_etu);
522
523 // Set BGT = 22 * work etu
524 bgt = (unsigned short) (22 * work_etu);
525
526 // Set the error detection code type
527 if (ATR_GetInterfaceByte (atr, 3, ATR_INTERFACE_BYTE_TC, &tc) == ATR_NOT_FOUND)
528 edc = PROTOCOL_T1_EDC_LRC;
529 else
530 edc = tc & 0x01;
531
532 // Set initial send sequence (NS)
533 ns = 1;
534
535 // Set timings
536 icc_timings.block_timeout = bwt;
537 icc_timings.char_timeout = cwt;
538 icc_timings.block_delay = bgt;
539 ICC_Async_SetTimings ();
540
541#ifdef DEBUG_PROTOCOL
542 printf ("Protocol: T=1: IFSC=%d, IFSD=%d, CWT=%d, BWT=%d, BGT=%d, EDC=%s\n",
543 ifsc, ifsd, cwt, bwt, t1->bgt,
544 (edc == PROTOCOL_T1_EDC_LRC) ? "LRC" : "CRC");
545#endif
546
547 return PROTOCOL_T1_OK;
548}
549
550static int PPS_InitProtocol ()
551{
552 switch (parameters.t) {
553 case ATR_PROTOCOL_TYPE_T0:
554 case ATR_PROTOCOL_TYPE_T14:
555 {
556 BYTE wi;
557 /* Integer value WI = TC2, by default 10 */
558#ifndef PROTOCOL_T0_USE_DEFAULT_TIMINGS
559 if (ATR_GetInterfaceByte (atr, 2, ATR_INTERFACE_BYTE_TC, &(wi)) != ATR_OK)
560#endif
561 wi = PROTOCOL_T0_DEFAULT_WI;
562
563 /* WWT = 960 * WI * (Fi / f) * 1000 milliseconds */
564 double F = (double) atr_f_table[parameters.FI];
565 unsigned long wwt = (long unsigned int) (960 * wi * (F / ICC_Async_GetClockRate ()) * 1000);
566 if (parameters.t == 14)
567 wwt >>= 1; //is this correct?
568
569 /* Set timings */
570 icc_timings.block_timeout = wwt;
571 icc_timings.char_timeout = wwt;
572 ICC_Async_SetTimings ();
573#ifdef DEBUG_PROTOCOL
574 printf ("Protocol: T=%i: WWT=%d, Clockrate=%lu\n", params->t, (int)(wwt),ICC_Async_GetClockRate());
575#endif
576 }
577 break;
578 case ATR_PROTOCOL_TYPE_T1:
579 Protocol_T1_Init ();//always returns ok
580 break;
581 default:
582 protocol = NULL;
583 return PPS_PROTOCOL_ERROR;
584 break;
585 }
586 return PPS_OK;
587}
588
589static BYTE PPS_GetPCK (BYTE * block, unsigned length)
590{
591 BYTE pck;
592 unsigned i;
593
594 pck = block[0];
595 for (i = 1; i < length; i++)
596 pck ^= block[i];
597
598 return pck;
599}
Note: See TracBrowser for help on using the repository browser.