source: trunk/csctapi/pps.c@ 1235

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

Cleanup reader_type code in csctapi

File size: 16.3 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
41/*
42 * Not exported macros definition
43 */
44
45#define PPS_HAS_PPS1(block) ((block[1] & 0x10) == 0x10)
46#define PPS_HAS_PPS2(block) ((block[1] & 0x20) == 0x20)
47#define PPS_HAS_PPS3(block) ((block[1] & 0x40) == 0x40)
48
49/*
50 * Not exported funtions declaration
51 */
52
53static int PPS_Exchange (PPS * pps, BYTE * params, unsigned *length);
54
55static bool PPS_Match (BYTE * request, unsigned len_request, BYTE * reply, unsigned len_reply);
56
57static unsigned PPS_GetLength (BYTE * block);
58
59static int PPS_InitICC (PPS * pps);
60
61static int PPS_InitProtocol (PPS * pps, int protocol_selected);
62
63static BYTE PPS_GetPCK (BYTE * block, unsigned length);
64
65/*
66 * Exported functions definition
67 */
68
69PPS * PPS_New (ICC_Async * icc)
70{
71 PPS *pps;
72
73 pps = (PPS *) malloc (sizeof (PPS));
74
75 if (pps != NULL)
76 {
77 pps->icc = icc;
78 pps->protocol = NULL;
79 pps->parameters.t = PPS_DEFAULT_PROTOCOL;
80 pps->parameters.FI = ATR_DEFAULT_FI;
81 pps->parameters.d = ATR_DEFAULT_D;
82 pps->parameters.n = ATR_DEFAULT_N;
83 }
84
85 return pps;
86}
87
88int PPS_Perform (PPS * pps, BYTE * params, unsigned *length)
89{
90 //Performs PPS Exchange on command when *length >0
91 //If unsuccesfull, or when length <= 0
92 //Gets parametes from ATR
93 //If necessary perform PPS session
94 //
95 //Output is pps->params.FI,n,d,t set with correct values
96 //and switched SC-device conform these values to correct baudrate
97 //
98 //We need to store FI instread of F, because SCI_DEV works with FI
99 //and it is easier to overclock then
100 //also from FI -> F is easy, other way around not
101
102 ATR *atr;
103 int ret;
104 bool PPS_success;
105
106 /* Perform PPS Exchange if requested by command */
107 if ((*length) > 0)
108 {
109 ret = PPS_Exchange (pps, params, length);
110
111 /* Get parameters from PPS handsake */
112 if (ret == PPS_OK)
113 {
114 pps->parameters.t = params[1] & 0x0F;
115
116 if (PPS_HAS_PPS1 (params))
117 {
118 pps->parameters.FI = (params[2] >> 4);
119 pps->parameters.d = atr_d_table[(params[2] & 0x0F)];
120 }
121
122/*
123 ret = PPS_InitICC(pps);
124
125 if (ret != PPS_OK)
126 return ret;
127*/
128 }
129/*
130 else
131 {
132 return ret;
133 }
134*/
135 }
136 PPS_success = PPS_OK;
137 int protocol_selected = 0; //stores which TAi,TBi etc. bytes must be used 0 means not set
138 atr = ICC_Async_GetAtr (pps->icc);
139 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
140 {
141 int numprot = atr->pn;
142 //if there is a trailing TD, this number is one too high
143 BYTE tx;
144 if (ATR_GetInterfaceByte (atr, numprot-1, ATR_INTERFACE_BYTE_TD, &tx) == ATR_OK)
145 if ((tx & 0xF0) == 0)
146 numprot--;
147 cs_debug("ATR reports %i protocol lines:",numprot);
148 int i,point;
149 char txt[50];
150 bool OffersT[3]; //T14 stored as T2
151 for (i = 0; i <= 2; i++)
152 OffersT[i] = FALSE;
153 for (i=1; i<= numprot; i++) {
154 point = 0;
155 if (ATR_GetInterfaceByte (atr, i, ATR_INTERFACE_BYTE_TA, &tx) == ATR_OK) {
156 sprintf((char *)txt+point,"TA%i=%02X ",i,tx);
157 point +=7;
158 }
159 if (ATR_GetInterfaceByte (atr, i, ATR_INTERFACE_BYTE_TB, &tx) == ATR_OK) {
160 sprintf((char *)txt+point,"TB%i=%02X ",i,tx);
161 point +=7;
162 }
163 if (ATR_GetInterfaceByte (atr, i, ATR_INTERFACE_BYTE_TC, &tx) == ATR_OK) {
164 sprintf((char *)txt+point,"TC%i=%02X ",i,tx);
165 point +=7;
166 }
167 if (ATR_GetInterfaceByte (atr, i, ATR_INTERFACE_BYTE_TD, &tx) == ATR_OK) {
168 sprintf((char *)txt+point,"TD%i=%02X ",i,tx);
169 point +=7;
170 tx &= 0X0F;
171 sprintf((char *)txt+point,"(T%i)",tx);
172 if (tx == 14)
173 OffersT[2] = TRUE;
174 else
175 OffersT[tx] = TRUE;
176 }
177 else {
178 sprintf((char *)txt+point,"no TD%i means T0",i);
179 OffersT[0] = TRUE;
180 }
181 cs_debug("%s",txt);
182 }
183
184 int numprottype = 0;
185 for (i = 0; i <= 2; i++)
186 if (OffersT[i])
187 numprottype ++;
188 cs_debug("%i protocol types detected. Historical bytes: %s",numprottype, cs_hexdump(1,atr->hb,atr->hbn));
189
190//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.
191 ATR_GetParameter (atr, ATR_PARAMETER_N, &(pps->parameters.n));
192 ATR_GetProtocolType(atr,1,&(pps->parameters.t)); //get protocol from TD1
193 BYTE TA2;
194 bool SpecificMode = (ATR_GetInterfaceByte (atr, 2, ATR_INTERFACE_BYTE_TA, &TA2) == ATR_OK); //if TA2 present, specific mode, else negotiable mode
195 if (SpecificMode) {
196 pps->parameters.t = TA2 & 0x0F;
197 if ((TA2 & 0x10) != 0x10) { //bit 5 set to 0 means F and D explicitly defined in interface characters
198 BYTE TA1;
199 if (ATR_GetInterfaceByte (atr, 1 , ATR_INTERFACE_BYTE_TA, &TA1) == ATR_OK) {
200 pps->parameters.FI = TA1 >> 4;
201 ATR_GetParameter (atr, ATR_PARAMETER_D, &(pps->parameters.d));
202 }
203 else {
204 pps->parameters.FI = ATR_DEFAULT_FI;
205 pps->parameters.d = ATR_DEFAULT_D;
206 }
207 }
208 else {
209 cs_log("Specific mode: speed 'implicitly defined', not sure how to proceed, assuming default values");
210 pps->parameters.FI = ATR_DEFAULT_FI;
211 pps->parameters.d = ATR_DEFAULT_D;
212 }
213 cs_debug("Specific mode: T%i, F=%.0f, D=%.6f, N=%.0f\n", pps->parameters.t, (double) atr_f_table[pps->parameters.FI], pps->parameters.d, pps->parameters.n);
214 }
215 else { //negotiable mode
216
217 bool NeedsPTS = ((pps->parameters.t != 14) && (numprottype > 1 || (atr->ib[0][ATR_INTERFACE_BYTE_TA].present == TRUE && atr->ib[0][ATR_INTERFACE_BYTE_TA].value != 0x11) || pps->parameters.n == 255)); //needs PTS according to ISO 7816 , SCI gets stuck on our PTS
218 if (NeedsPTS) {
219 // PTSS PTS0 PTS1 PTS2 PTS3 PCK
220 // PTSS PTS0 PTS1 PCK
221 BYTE req[] = { 0xFF, 0x10, 0x00, 0x00 }; //we currently do not support PTS2, standard guardtimes
222 req[1]=0x10 | pps->parameters.t; //PTS0 always flags PTS1 to be sent always
223 if (ATR_GetInterfaceByte (atr, 1, ATR_INTERFACE_BYTE_TA, &req[2]) != ATR_OK) //PTS1
224 req[2] = 0x11; //defaults FI and DI to 1
225 //req[3]=PPS_GetPCK(req,sizeof(req)-1); will be set by PPS_Exchange
226 unsigned int len = sizeof(req);
227 ret = PPS_Exchange (pps, req, &len);
228 if (ret == PPS_OK) {
229 pps->parameters.FI = req[2] >> 4;
230 BYTE DI = req[2] & 0x0F;
231 pps->parameters.d = (double) (atr_d_table[DI]);
232 PPS_success = TRUE;
233 cs_debug("PTS Succesfull, selected protocol: T%i, F=%.0f, D=%.6f, N=%.0f\n", pps->parameters.t, (double) atr_f_table[pps->parameters.FI], pps->parameters.d, pps->parameters.n);
234 }
235 else
236 cs_ddump(req,4,"PTS Failure, response:");
237 }
238
239 //FIXME Currently InitICC sets baudrate to 9600 for all T14 cards (=no switching);
240 //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)
241 if (!PPS_success) {//last PPS not succesfull
242 BYTE TA1;
243 if (ATR_GetInterfaceByte (atr, 1 , ATR_INTERFACE_BYTE_TA, &TA1) == ATR_OK) {
244 pps->parameters.FI = TA1 >> 4;
245 ATR_GetParameter (atr, ATR_PARAMETER_D, &(pps->parameters.d));
246 }
247 else { //do not obey TA1
248 pps->parameters.FI = ATR_DEFAULT_FI;
249 pps->parameters.d = ATR_DEFAULT_D;
250 }
251 ATR_GetProtocolType (atr, 1, &(pps->parameters.t));
252 protocol_selected = 1;
253
254 if (NeedsPTS) {
255 if ((pps->parameters.d == 32) || (pps->parameters.d == 12) || (pps->parameters.d == 20))
256 pps->parameters.d = 0; //behave conform "old" atr_d_table; viaccess cards that fail PTS need this
257 }
258 /////Here all non-ISO behaviour
259 /////End all non-ISO behaviour
260
261 cs_debug("No PTS %s, selected protocol T%i, F=%.0f, D=%.6f, N=%.0f\n", NeedsPTS?"happened":"needed", pps->parameters.t, (double) atr_f_table[pps->parameters.FI], pps->parameters.d, pps->parameters.n);
262 }
263 }//end negotiable mode
264 }//end length<0
265
266 //make sure no zero values
267 double F = (double) atr_f_table[pps->parameters.FI];
268 if (!F) {
269 pps->parameters.FI = ATR_DEFAULT_FI;
270 cs_log("Warning: F=0 is invalid, forcing FI=%d", pps->parameters.FI);
271 }
272 if (!pps->parameters.d) {
273 pps->parameters.d = ATR_DEFAULT_D;
274 cs_log("Warning: D=0 is invalid, forcing D=%.0f",pps->parameters.d);
275 }
276
277 pps->icc->protocol_type = pps->parameters.t;
278
279#ifdef DEBUG_PROTOCOL
280 printf("PPS: T=%i, F=%.0f, D=%.6f, N=%.0f\n",
281 pps->parameters.t,
282 F,
283 pps->parameters.d,
284 pps->parameters.n);
285#endif
286
287 ret = PPS_InitICC(pps);
288
289 if (ret != PPS_OK)
290 return ret;
291
292 /* Initialize selected protocol with selected parameters */
293 if (pps->parameters.t == 1)
294 ret = PPS_InitProtocol (pps, 3); //FIXME in practice most T1 cards carry timing parameters in TA3, TB3 and TC3
295 else
296 ret = PPS_InitProtocol (pps, 2); //FIXME T0 cards carry timing parameters in TC2
297
298 return ret;
299}
300
301void * PPS_GetProtocol (PPS * pps)
302{
303 return pps->protocol;
304}
305
306PPS_ProtocolParameters *PPS_GetProtocolParameters (PPS * pps)
307{
308 /* User must Remember not to reference this struct after removing PPS */
309 return &(pps->parameters);
310}
311
312void PPS_Delete (PPS * pps)
313{
314 free (pps);
315}
316
317/*
318 * Not exported funtions definition
319 */
320
321static int PPS_Exchange (PPS * pps, BYTE * params, unsigned *length)
322{
323 BYTE confirm[PPS_MAX_LENGTH];
324 unsigned len_request, len_confirm;
325 int ret;
326#ifdef DEBUG_PROTOCOL
327 int i;
328#endif
329
330 len_request = PPS_GetLength (params);
331 params[len_request - 1] = PPS_GetPCK(params, len_request - 1);
332
333#ifdef DEBUG_PROTOCOL
334 printf ("PPS: Sending request: ");
335 for (i = 0; i < len_request; i++)
336 printf ("%X ", params[i]);
337 printf ("\n");
338#endif
339
340 cs_debug("PTS: Sending request: %s", cs_hexdump(1, params, len_request));
341
342 /* Send PPS request */
343#ifdef COOL
344 //unsigned char ptsAck[10];
345 //u_int8 ptsLen = len_request;
346 unsigned short int ptsLen = len_request;
347 int Status = cnxt_smc_start_pps(handle, params, confirm, &ptsLen, TRUE);
348 printf ("cnxt_smc_start_pps Status=%i\n", Status);
349 len_confirm = ptsLen;
350#ifdef DEBUG_PROTOCOL
351 printf("COOL: confirm: \n");
352 for (i = 0; i < ptsLen; i++)
353 printf ("%02X", confirm[i]);
354 printf ("\n");
355 fflush(stdout);
356 printf("COOL: req: \n");
357 for (i = 0; i < len_request; i++)
358 printf ("%02X", params[i]);
359 printf ("\n");
360 fflush(stdout);
361#endif
362 if (Status)
363 return PPS_HANDSAKE_ERROR;
364#else
365 if (ICC_Async_Transmit (pps->icc, len_request, params) != ICC_ASYNC_OK)
366 return PPS_ICC_ERROR;
367
368 /* Get PPS confirm */
369 if (ICC_Async_Receive (pps->icc, 2, confirm) != ICC_ASYNC_OK)
370 return PPS_ICC_ERROR;
371
372 len_confirm = PPS_GetLength (confirm);
373
374 if (ICC_Async_Receive (pps->icc, len_confirm - 2, confirm + 2) != ICC_ASYNC_OK)
375 return PPS_ICC_ERROR;
376
377#ifdef DEBUG_PROTOCOL
378 printf ("PPS: Receivig confirm: ");
379 for (i = 0; i < len_confirm; i++)
380 printf ("%X ", confirm[i]);
381 printf ("\n");
382#endif
383
384 cs_debug("PTS: Receiving confirm: %s", cs_hexdump(1, confirm, len_confirm));
385
386 if (!PPS_Match (params, len_request, confirm, len_confirm))
387 ret = PPS_HANDSAKE_ERROR;
388 else
389 ret = PPS_OK;
390#endif
391
392 /* Copy PPS handsake */
393 memcpy (params, confirm, len_confirm);
394 (*length) = len_confirm;
395
396 return ret;
397}
398
399static bool PPS_Match (BYTE * request, unsigned len_request, BYTE * confirm, unsigned len_confirm)
400{
401 /* See if the reply differs from request */
402 if ((len_request != len_confirm) || (memcmp (request, confirm, len_request)))
403 {
404 /* See if the card specifies other than default FI and D */
405 //if ((PPS_HAS_PPS1 (confirm)) && (confirm[2] != request[2]))
406 return FALSE;
407 }
408
409 return TRUE;
410}
411
412static unsigned PPS_GetLength (BYTE * block)
413{
414 unsigned length = 3;
415
416 if (PPS_HAS_PPS1 (block))
417 length++;
418
419 if (PPS_HAS_PPS2 (block))
420 length++;
421
422 if (PPS_HAS_PPS3 (block))
423 length++;
424
425 return length;
426}
427
428static int PPS_InitICC (PPS * pps)
429{
430#ifdef SCI_DEV
431#include <sys/ioctl.h>
432#include "sci_global.h"
433#include "sci_ioctl.h"
434 if(reader[ridx].typ == R_INTERNAL)
435 {
436 int n;
437 SCI_PARAMETERS params;
438 //memset(&params,0,sizeof(SCI_PARAMETERS));
439 if (ioctl(reader[ridx].handle, IOCTL_GET_PARAMETERS, &params) < 0 )
440 return PPS_ICC_ERROR;
441
442 ATR *atr = ICC_Async_GetAtr (pps->icc);
443
444 params.T = pps->parameters.t;
445 params.fs = atr_fs_table[pps->parameters.FI] / 1000000;
446 double F = (double) atr_f_table[pps->parameters.FI];
447 //for Irdeto T14 cards, do not set ETU
448 if (!(atr->hbn >= 6 && !memcmp(atr->hb, "IRDETO", 6) && params.T == 14))
449 params.ETU = F / pps->parameters.d;
450 if (pps->parameters.n == 255) //only for T0 or also for T1?
451 params.EGT = 0;
452 else
453 params.EGT = pps->parameters.n;
454
455 double a;
456 ATR_GetParameter(atr, ATR_PARAMETER_P, &a);
457 params.P=(unsigned char)a;
458 ATR_GetParameter(atr, ATR_PARAMETER_I, &a);
459 params.I=(unsigned char)a;
460
461 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);
462
463 if (ioctl(reader[ridx].handle, IOCTL_SET_PARAMETERS, &params)!=0)
464 return PPS_ICC_ERROR;
465
466 }
467#elif COOL
468 if(reader[ridx].typ == R_INTERNAL) {
469 int mhz = atr_fs_table[pps->parameters.FI] / 10000;
470 if (!Cool_SetBaudrate(mhz))
471 return PPS_ICC_ERROR;
472#ifdef DEBUG_PROTOCOL
473 printf("Coolstream: set clock to %i * 10kHz\n", mhz);
474#endif
475 return PPS_OK;
476 }
477#endif
478 {
479 unsigned long baudrate;
480 double F = (double) atr_f_table[pps->parameters.FI];
481 if (pps->parameters.t == 14)
482 baudrate = 9600;
483 else
484 baudrate = pps->parameters.d * ICC_Async_GetClockRate () / F;
485
486#ifdef DEBUG_PROTOCOL
487 printf ("PPS: Baudrate = %d\n", (int)baudrate);
488#endif
489
490
491 if (ICC_Async_SetBaudrate (pps->icc, baudrate) != ICC_ASYNC_OK)
492 return PPS_ICC_ERROR;
493
494 return PPS_OK;
495 }
496}
497
498static int PPS_InitProtocol (PPS * pps, int selected_protocol)
499{
500 int ret;
501
502 if (pps->parameters.t == ATR_PROTOCOL_TYPE_T0)
503 {
504 pps->protocol = Protocol_T0_New ();
505
506 if ((pps->protocol) != NULL)
507 {
508 ret = Protocol_T0_Init ((Protocol_T0 *) pps->protocol, (ICC_Async *) pps->icc, &(pps->parameters), selected_protocol);
509
510 if (ret != PROTOCOL_T0_OK)
511 {
512 Protocol_T0_Delete ((Protocol_T0 *) pps->protocol);
513 pps->protocol = NULL;
514 return PPS_PROTOCOL_ERROR;
515 }
516
517 return PPS_OK;
518 }
519 }
520 else if (pps->parameters.t == ATR_PROTOCOL_TYPE_T1)
521 {
522 pps->protocol = Protocol_T1_New ();
523
524 if (pps->protocol != NULL)
525 {
526 ret = Protocol_T1_Init ((Protocol_T1 *) pps->protocol, (ICC_Async *) pps->icc, selected_protocol);
527
528 if (ret != PROTOCOL_T1_OK)
529 {
530 Protocol_T1_Delete ((Protocol_T1 *) pps->protocol);
531 pps->protocol = NULL;
532 return PPS_PROTOCOL_ERROR;
533 }
534
535 return PPS_OK;
536 }
537 }
538 else if (pps->parameters.t == ATR_PROTOCOL_TYPE_T14)
539 {
540 pps->protocol = Protocol_T14_New ();
541
542 if ((pps->protocol) != NULL)
543 {
544 ret = Protocol_T14_Init ((Protocol_T14 *) pps->protocol, (ICC_Async *) pps->icc, &(pps->parameters), selected_protocol);
545
546 if (ret != PROTOCOL_T14_OK)
547 {
548 Protocol_T14_Delete ((Protocol_T14 *) pps->protocol);
549 pps->protocol = NULL;
550 return PPS_PROTOCOL_ERROR;
551 }
552
553 return PPS_OK;
554 }
555 }
556 else
557 {
558 pps->protocol = NULL;
559 }
560
561 return PPS_PROTOCOL_ERROR;
562}
563
564static BYTE PPS_GetPCK (BYTE * block, unsigned length)
565{
566 BYTE pck;
567 unsigned i;
568
569 pck = block[0];
570 for (i = 1; i < length; i++)
571 pck ^= block[i];
572
573 return pck;
574}
Note: See TracBrowser for help on using the repository browser.