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