source: branches/monitor-improvement/csctapi/pps.c@ 1189

Last change on this file since 1189 was 1189, checked in by alno, 12 years ago

WebIf:

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