[8] | 1 | /*
|
---|
| 2 | icc_async.c
|
---|
| 3 | Asynchronous ICC's handling functions
|
---|
| 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 <stdlib.h>
|
---|
| 26 | #include <stdio.h>
|
---|
| 27 | #include <string.h>
|
---|
[1381] | 28 | #include "../globals.h"
|
---|
| 29 | #include "defines.h"
|
---|
| 30 | #include "icc_async.h"
|
---|
[1171] | 31 | #include "ifd.h"
|
---|
[1266] | 32 | #include "mc_global.h"
|
---|
[1381] | 33 | #include "apdu.h"
|
---|
| 34 | #include "protocol_t0.h"
|
---|
| 35 | #include "protocol_t1.h"
|
---|
[8] | 36 |
|
---|
[1389] | 37 | // Default T0/T14 settings
|
---|
| 38 | #define DEFAULT_WI 10
|
---|
| 39 | // Default T1 settings
|
---|
| 40 | #define DEFAULT_IFSC 32
|
---|
| 41 | #define MAX_IFSC 251 /* Cannot send > 255 buffer */
|
---|
| 42 | #define DEFAULT_CWI 13
|
---|
| 43 | #define DEFAULT_BWI 4
|
---|
| 44 | #define EDC_LRC 0
|
---|
[8] | 45 |
|
---|
[1389] | 46 | #define PPS_MAX_LENGTH 6
|
---|
| 47 | #define PPS_HAS_PPS1(block) ((block[1] & 0x10) == 0x10)
|
---|
| 48 | #define PPS_HAS_PPS2(block) ((block[1] & 0x20) == 0x20)
|
---|
| 49 | #define PPS_HAS_PPS3(block) ((block[1] & 0x40) == 0x40)
|
---|
| 50 |
|
---|
| 51 |
|
---|
[8] | 52 | /*
|
---|
| 53 | * Not exported functions declaration
|
---|
| 54 | */
|
---|
| 55 |
|
---|
| 56 | static void ICC_Async_InvertBuffer (unsigned size, BYTE * buffer);
|
---|
[1419] | 57 | static int Parse_ATR (ATR * atr, unsigned short deprecated);
|
---|
[1389] | 58 | static int PPS_Exchange (BYTE * params, unsigned *length);
|
---|
| 59 | static unsigned PPS_GetLength (BYTE * block);
|
---|
[1419] | 60 | static int InitCard (ATR * atr, BYTE FI, double d, double n, unsigned short deprecated);
|
---|
[1389] | 61 | static unsigned int ETU_to_ms(unsigned long WWT);
|
---|
| 62 | static BYTE PPS_GetPCK (BYTE * block, unsigned length);
|
---|
[1559] | 63 | static int Protocol_Command (unsigned char * command, unsigned long command_len, APDU_Rsp ** rsp);
|
---|
[1389] | 64 | static int SetRightParity (void);
|
---|
[8] | 65 |
|
---|
[1221] | 66 | int fdmc=(-1);
|
---|
[1220] | 67 |
|
---|
[8] | 68 | /*
|
---|
| 69 | * Exported functions definition
|
---|
| 70 | */
|
---|
| 71 |
|
---|
[1220] | 72 | int ICC_Async_Device_Init ()
|
---|
| 73 | {
|
---|
[1399] | 74 | cs_debug_mask (D_IFD, "IFD: Opening device %s\n", reader[ridx].device);
|
---|
[1466] | 75 |
|
---|
| 76 | wr = 0;
|
---|
| 77 |
|
---|
| 78 | switch(reader[ridx].typ) {
|
---|
| 79 | case R_MOUSE:
|
---|
[1653] | 80 | reader[ridx].handle = open (reader[ridx].device, O_RDWR | O_NOCTTY| O_NONBLOCK);
|
---|
| 81 | if (reader[ridx].handle < 0) {
|
---|
| 82 | cs_log("ERROR opening device %s",reader[ridx].device);
|
---|
| 83 | return ERROR;
|
---|
| 84 | }
|
---|
[1466] | 85 | break;
|
---|
| 86 | #if defined(TUXBOX) && defined(PPC)
|
---|
| 87 | case R_DB2COM1:
|
---|
| 88 | case R_DB2COM2:
|
---|
[1653] | 89 | reader[ridx].handle = open (reader[ridx].device, O_RDWR | O_NOCTTY| O_SYNC);
|
---|
| 90 | if (reader[ridx].handle < 0) {
|
---|
| 91 | cs_log("ERROR opening device %s",reader[ridx].device);
|
---|
| 92 | return ERROR;
|
---|
| 93 | }
|
---|
[1466] | 94 | if ((fdmc = open(DEV_MULTICAM, O_RDWR)) < 0) {
|
---|
| 95 | close(reader[ridx].handle);
|
---|
[1477] | 96 | cs_log("ERROR opening device %s",DEV_MULTICAM);
|
---|
[1466] | 97 | return ERROR;
|
---|
| 98 | }
|
---|
| 99 | break;
|
---|
[1389] | 100 | #endif
|
---|
[1476] | 101 | case R_SMART:
|
---|
[1466] | 102 | #if defined(LIBUSB)
|
---|
[1477] | 103 | call (SR_Init(&reader[ridx]));
|
---|
[1466] | 104 | break;
|
---|
[1476] | 105 | #else
|
---|
| 106 | cs_log("ERROR, you have specified 'protocol = smartreader' in oscam.server,");
|
---|
| 107 | cs_log("recompile with SmartReader support.");
|
---|
| 108 | return ERROR;
|
---|
[1220] | 109 | #endif
|
---|
[1466] | 110 | case R_INTERNAL:
|
---|
| 111 | #ifdef COOL
|
---|
| 112 | return Cool_Init();
|
---|
| 113 | #elif SCI_DEV
|
---|
| 114 | #if defined(SH4) || defined(STB04SCI)
|
---|
| 115 | reader[ridx].handle = open (reader[ridx].device, O_RDWR|O_NONBLOCK|O_NOCTTY);
|
---|
| 116 | #else
|
---|
| 117 | reader[ridx].handle = open (reader[ridx].device, O_RDWR);
|
---|
| 118 | #endif
|
---|
[1477] | 119 | if (reader[ridx].handle < 0) {
|
---|
| 120 | cs_log("ERROR opening device %s",reader[ridx].device);
|
---|
[1466] | 121 | return ERROR;
|
---|
[1477] | 122 | }
|
---|
[1476] | 123 | #else//SCI_DEV
|
---|
| 124 | cs_log("ERROR, you have specified 'protocol = internal' in oscam.server,");
|
---|
| 125 | cs_log("recompile with internal reader support.");
|
---|
| 126 | return ERROR;
|
---|
[1466] | 127 | #endif//SCI_DEV
|
---|
| 128 | break;
|
---|
| 129 | default:
|
---|
| 130 | cs_log("ERROR ICC_Device_Init: unknow reader type %i",reader[ridx].typ);
|
---|
[1476] | 131 | return ERROR;
|
---|
[1466] | 132 | }
|
---|
[1220] | 133 |
|
---|
[1466] | 134 | if (reader[ridx].typ <= R_MOUSE)
|
---|
| 135 | if (Phoenix_Init()) {
|
---|
[1477] | 136 | cs_log("ERROR: Phoenix_Init returns error");
|
---|
[1511] | 137 | Phoenix_Close ();
|
---|
[1389] | 138 | return ERROR;
|
---|
[1220] | 139 | }
|
---|
[1399] | 140 | cs_debug_mask (D_IFD, "IFD: Device %s succesfully opened\n", reader[ridx].device);
|
---|
[1389] | 141 | return OK;
|
---|
[1220] | 142 | }
|
---|
| 143 |
|
---|
[1389] | 144 | int ICC_Async_GetStatus (int * card)
|
---|
[1220] | 145 | {
|
---|
| 146 | int in;
|
---|
| 147 |
|
---|
| 148 | // printf("\n%08X\n", (int)ifd->io);
|
---|
| 149 |
|
---|
[1466] | 150 | switch(reader[ridx].typ) {
|
---|
| 151 | case R_DB2COM1:
|
---|
| 152 | case R_DB2COM2:
|
---|
| 153 | #if defined(TUXBOX) && defined(PPC)
|
---|
| 154 | {
|
---|
| 155 | ushort msr=1;
|
---|
| 156 | extern int fdmc;
|
---|
| 157 | IO_Serial_Ioctl_Lock(1);
|
---|
| 158 | ioctl(fdmc, GET_PCDAT, &msr);
|
---|
| 159 | if (reader[ridx].typ == R_DB2COM2)
|
---|
| 160 | in=(!(msr & 1));
|
---|
| 161 | else
|
---|
| 162 | in=((msr & 0x0f00) == 0x0f00);
|
---|
| 163 | IO_Serial_Ioctl_Lock(0);
|
---|
| 164 | }
|
---|
| 165 | break;
|
---|
| 166 | #endif
|
---|
| 167 | case R_MOUSE:
|
---|
[1477] | 168 | call (Phoenix_GetStatus(&in));
|
---|
[1466] | 169 | break;
|
---|
| 170 | #if defined(LIBUSB)
|
---|
| 171 | case R_SMART:
|
---|
[1477] | 172 | call (SR_GetStatus(&reader[ridx],&in));
|
---|
[1466] | 173 | break;
|
---|
| 174 | #endif
|
---|
| 175 | case R_INTERNAL:
|
---|
[1220] | 176 | #ifdef SCI_DEV
|
---|
[1477] | 177 | call (Sci_GetStatus(reader[ridx].handle, &in));
|
---|
[1220] | 178 | #elif COOL
|
---|
[1477] | 179 | call (Cool_GetStatus(&in));
|
---|
[1220] | 180 | #endif
|
---|
[1466] | 181 | break;
|
---|
| 182 | default:
|
---|
| 183 | cs_log("ERROR ICC_Device_Init: unknow reader type %i",reader[ridx].typ);
|
---|
[1476] | 184 | return ERROR;
|
---|
[1389] | 185 | }
|
---|
[1220] | 186 |
|
---|
[1489] | 187 | if (in)
|
---|
[1389] | 188 | *card = TRUE;
|
---|
[1489] | 189 | else
|
---|
[1389] | 190 | *card = FALSE;
|
---|
[1220] | 191 |
|
---|
[1601] | 192 | //cs_debug_mask (D_TRACE, "IFD: Status = %s", in ? "card": "no card");
|
---|
[1220] | 193 |
|
---|
[1389] | 194 | return OK;
|
---|
[1220] | 195 | }
|
---|
| 196 |
|
---|
[1419] | 197 | int ICC_Async_Activate (ATR * atr, unsigned short deprecated)
|
---|
[8] | 198 | {
|
---|
[1399] | 199 | cs_debug_mask (D_IFD, "IFD: Activating card in reader %s\n", reader[ridx].label);
|
---|
[1389] | 200 | int card;
|
---|
[8] | 201 |
|
---|
[1477] | 202 | call (ICC_Async_GetStatus (&card));
|
---|
| 203 | if (card == 0) {
|
---|
| 204 | cs_log("ERROR: Trying to activate card but no card inside");
|
---|
[1389] | 205 | return ERROR;
|
---|
[1477] | 206 | }
|
---|
[1371] | 207 |
|
---|
[1466] | 208 | current_baudrate = DEFAULT_BAUDRATE; //this is needed for all readers to calculate work_etu for timings
|
---|
| 209 | switch(reader[ridx].typ) {
|
---|
| 210 | case R_DB2COM1:
|
---|
| 211 | case R_DB2COM2:
|
---|
| 212 | case R_MOUSE:
|
---|
[1477] | 213 | call (Phoenix_Reset(atr));
|
---|
[1466] | 214 | break;
|
---|
[1389] | 215 | #if defined(LIBUSB)
|
---|
[1466] | 216 | case R_SMART:
|
---|
[1477] | 217 | call (SR_Reset(&reader[ridx],atr));
|
---|
[1466] | 218 | break;
|
---|
[1389] | 219 | #endif
|
---|
[1466] | 220 | case R_INTERNAL:
|
---|
[1266] | 221 | #ifdef SCI_DEV
|
---|
[1477] | 222 | call (Sci_Activate());
|
---|
| 223 | call (Sci_Reset(atr));
|
---|
[1466] | 224 | #elif COOL
|
---|
[1477] | 225 | call (Cool_Reset(atr));
|
---|
[1205] | 226 | #endif
|
---|
[1466] | 227 | break;
|
---|
| 228 | default:
|
---|
| 229 | cs_log("ERROR ICC_Async_Activate: unknow reader type %i",reader[ridx].typ);
|
---|
[1476] | 230 | return ERROR;
|
---|
[1466] | 231 | }
|
---|
[1389] | 232 |
|
---|
| 233 | unsigned char atrarr[64];
|
---|
| 234 | unsigned int atr_size;
|
---|
| 235 | ATR_GetRaw(atr, atrarr, &atr_size);
|
---|
| 236 | cs_ri_log("ATR: %s", cs_hexdump(1, atrarr, atr_size));
|
---|
| 237 |
|
---|
| 238 | /* Get ICC convention */
|
---|
| 239 | if (ATR_GetConvention (atr, &(convention)) != ATR_OK) {
|
---|
[1477] | 240 | cs_log("ERROR: Could not read convention");
|
---|
[1278] | 241 | convention = 0;
|
---|
[1389] | 242 | protocol_type = 0;
|
---|
| 243 | return ERROR;
|
---|
[8] | 244 | }
|
---|
| 245 |
|
---|
[1278] | 246 | protocol_type = ATR_PROTOCOL_TYPE_T0;
|
---|
[8] | 247 |
|
---|
[1399] | 248 | unsigned short cs_ptyp_orig=cs_ptyp;
|
---|
| 249 | cs_ptyp=D_ATR;
|
---|
[1419] | 250 | int ret = Parse_ATR(atr, deprecated);
|
---|
[1477] | 251 | if (ret)
|
---|
| 252 | cs_log("ERROR: Parse_ATR returned error");
|
---|
[1399] | 253 | cs_ptyp=cs_ptyp_orig;
|
---|
| 254 | if (ret)
|
---|
[1389] | 255 | return ERROR;
|
---|
[1399] | 256 | cs_debug_mask (D_IFD, "IFD: Card in reader %s succesfully activated\n", reader[ridx].label);
|
---|
[1389] | 257 | return OK;
|
---|
[8] | 258 | }
|
---|
| 259 |
|
---|
[1381] | 260 | int ICC_Async_CardWrite (unsigned char *cmd, unsigned short lc, unsigned char *rsp, unsigned short *lr)
|
---|
[8] | 261 | {
|
---|
[1381] | 262 | APDU_Rsp *apdu_rsp = NULL;
|
---|
| 263 | int remain;
|
---|
| 264 | bool err = FALSE;
|
---|
[1321] | 265 |
|
---|
[1559] | 266 | call (Protocol_Command (cmd, lc, &apdu_rsp));
|
---|
[1477] | 267 | {
|
---|
[1381] | 268 | if (apdu_rsp != NULL) {
|
---|
| 269 | /* Copy APDU data to rsp */
|
---|
| 270 | remain = MAX ((short)APDU_Rsp_RawLen(apdu_rsp) - (*lr),0);
|
---|
| 271 | if (remain > 0) {
|
---|
| 272 | cs_log("MEMORY ERROR");
|
---|
| 273 | err = TRUE; //FIXME do I need this?
|
---|
| 274 | }
|
---|
| 275 | (*lr) = MIN ((*lr), (short)APDU_Rsp_RawLen (apdu_rsp));
|
---|
| 276 | memcpy (rsp, APDU_Rsp_Raw (apdu_rsp) + remain, (*lr));
|
---|
| 277 | APDU_Rsp_Delete (apdu_rsp);
|
---|
| 278 | }
|
---|
| 279 | else
|
---|
| 280 | (*lr) = 0;
|
---|
| 281 | }
|
---|
| 282 |
|
---|
[1477] | 283 | if (err) {
|
---|
| 284 | cs_log("ERROR creating APDU response");
|
---|
[1389] | 285 | return ERROR;
|
---|
[1477] | 286 | }
|
---|
[1381] | 287 |
|
---|
[1389] | 288 | return OK;
|
---|
[8] | 289 | }
|
---|
| 290 |
|
---|
[1559] | 291 | int Protocol_Command (unsigned char * command, unsigned long command_len, APDU_Rsp ** rsp)
|
---|
[1381] | 292 | {
|
---|
| 293 | switch (protocol_type) {
|
---|
| 294 | case ATR_PROTOCOL_TYPE_T0:
|
---|
[1559] | 295 | call (Protocol_T0_Command (command, command_len, rsp));
|
---|
[1381] | 296 | break;
|
---|
| 297 | case ATR_PROTOCOL_TYPE_T1:
|
---|
[1588] | 298 | {
|
---|
| 299 | int try = 1;
|
---|
| 300 | do {
|
---|
| 301 | if (Protocol_T1_Command (command, command_len, rsp) == OK)
|
---|
| 302 | break;
|
---|
| 303 | try++;
|
---|
| 304 | //try to resync
|
---|
| 305 | APDU_Rsp ** rsp;
|
---|
| 306 | unsigned char resync[] = { 0x21, 0xC0, 0x00, 0xE1 };
|
---|
| 307 | Protocol_T1_Command (resync, sizeof(resync), rsp);
|
---|
| 308 | ifsc = DEFAULT_IFSC;
|
---|
| 309 | } while (try <= 3);
|
---|
[1381] | 310 | break;
|
---|
[1588] | 311 | }
|
---|
[1381] | 312 | case ATR_PROTOCOL_TYPE_T14:
|
---|
[1559] | 313 | call (Protocol_T14_ExchangeTPDU (command, command_len, rsp));
|
---|
[1381] | 314 | break;
|
---|
| 315 | default:
|
---|
| 316 | cs_log("Error, unknown protocol type %i",protocol_type);
|
---|
[1389] | 317 | return ERROR;
|
---|
[1381] | 318 | }
|
---|
[1389] | 319 | return OK;
|
---|
[1381] | 320 | }
|
---|
| 321 |
|
---|
[1389] | 322 | int ICC_Async_SetTimings (unsigned wait_etu)
|
---|
[1381] | 323 | {
|
---|
[1514] | 324 | read_timeout = ETU_to_ms(wait_etu);
|
---|
| 325 | cs_debug_mask(D_IFD, "Setting timeout to %i", wait_etu);
|
---|
[1389] | 326 | return OK;
|
---|
[1381] | 327 | }
|
---|
| 328 |
|
---|
[1278] | 329 | int ICC_Async_Transmit (unsigned size, BYTE * data)
|
---|
[8] | 330 | {
|
---|
[1399] | 331 | cs_ddump_mask(D_IFD, data, size, "IFD Transmit: ");
|
---|
[8] | 332 | BYTE *buffer = NULL, *sent;
|
---|
| 333 |
|
---|
[1466] | 334 | if (convention == ATR_CONVENTION_INVERSE && reader[ridx].typ <= R_MOUSE) {
|
---|
[8] | 335 | buffer = (BYTE *) calloc(sizeof (BYTE), size);
|
---|
| 336 | memcpy (buffer, data, size);
|
---|
| 337 | ICC_Async_InvertBuffer (size, buffer);
|
---|
| 338 | sent = buffer;
|
---|
| 339 | }
|
---|
| 340 | else
|
---|
| 341 | sent = data;
|
---|
[1466] | 342 |
|
---|
| 343 | switch(reader[ridx].typ) {
|
---|
| 344 | case R_DB2COM1:
|
---|
| 345 | case R_DB2COM2:
|
---|
| 346 | case R_MOUSE:
|
---|
[1477] | 347 | call (Phoenix_Transmit (sent, size, icc_timings.block_delay, icc_timings.char_delay));
|
---|
[1466] | 348 | break;
|
---|
[1389] | 349 | #if defined(LIBUSB)
|
---|
[1466] | 350 | case R_SMART:
|
---|
[1477] | 351 | call (SR_Transmit(&reader[ridx], sent, size));
|
---|
[1466] | 352 | break;
|
---|
[1389] | 353 | #endif
|
---|
[1466] | 354 | case R_INTERNAL:
|
---|
[1171] | 355 | #ifdef COOL
|
---|
[1477] | 356 | call (Cool_Transmit(sent, size));
|
---|
[1466] | 357 | #elif SCI_DEV
|
---|
[1477] | 358 | call (Phoenix_Transmit (sent, size, 0, 0)); //the internal reader will provide the delay
|
---|
[1466] | 359 | #endif
|
---|
| 360 | break;
|
---|
| 361 | default:
|
---|
| 362 | cs_log("ERROR ICC_Async_Transmit: unknow reader type %i",reader[ridx].typ);
|
---|
[1476] | 363 | return ERROR;
|
---|
[1171] | 364 | }
|
---|
[1389] | 365 |
|
---|
[1466] | 366 | if (convention == ATR_CONVENTION_INVERSE && reader[ridx].typ <= R_MOUSE)
|
---|
[8] | 367 | free (buffer);
|
---|
[1399] | 368 | cs_debug_mask(D_IFD, "IFD Transmit succesful");
|
---|
[1389] | 369 | return OK;
|
---|
[8] | 370 | }
|
---|
| 371 |
|
---|
[1278] | 372 | int ICC_Async_Receive (unsigned size, BYTE * data)
|
---|
[8] | 373 | {
|
---|
[1466] | 374 | switch(reader[ridx].typ) {
|
---|
| 375 | case R_DB2COM1:
|
---|
| 376 | case R_DB2COM2:
|
---|
| 377 | case R_MOUSE:
|
---|
[1477] | 378 | call (Phoenix_Receive (data, size, read_timeout));
|
---|
[1466] | 379 | break;
|
---|
| 380 | #if defined(LIBUSB)
|
---|
| 381 | case R_SMART:
|
---|
[1477] | 382 | call (SR_Receive(&reader[ridx], data, size));
|
---|
[1466] | 383 | break;
|
---|
| 384 | #endif
|
---|
| 385 | case R_INTERNAL:
|
---|
[1171] | 386 | #ifdef COOL
|
---|
[1477] | 387 | call (Cool_Receive(data, size));
|
---|
[1466] | 388 | #elif SCI_DEV
|
---|
[1477] | 389 | call (Phoenix_Receive (data, size, read_timeout));
|
---|
[1389] | 390 | #endif
|
---|
[1466] | 391 | break;
|
---|
| 392 | default:
|
---|
| 393 | cs_log("ERROR ICC_Async_Receive: unknow reader type %i",reader[ridx].typ);
|
---|
[1476] | 394 | return ERROR;
|
---|
[1399] | 395 | }
|
---|
[1389] | 396 |
|
---|
[1466] | 397 | if (convention == ATR_CONVENTION_INVERSE && reader[ridx].typ <= R_MOUSE)
|
---|
[8] | 398 | ICC_Async_InvertBuffer (size, data);
|
---|
[1399] | 399 |
|
---|
| 400 | cs_ddump_mask(D_IFD, data, size, "IFD Received: ");
|
---|
[1389] | 401 | return OK;
|
---|
[8] | 402 | }
|
---|
| 403 |
|
---|
[1279] | 404 | int ICC_Async_Close ()
|
---|
[1466] | 405 | { //FIXME this routine is never called!
|
---|
[1399] | 406 | cs_debug_mask (D_IFD, "IFD: Closing device %s", reader[ridx].device);
|
---|
[1466] | 407 |
|
---|
| 408 | switch(reader[ridx].typ) {
|
---|
| 409 | case R_DB2COM1:
|
---|
| 410 | case R_DB2COM2:
|
---|
| 411 | case R_MOUSE:
|
---|
[1511] | 412 | call (Phoenix_Close());
|
---|
[1466] | 413 | break;
|
---|
[1389] | 414 | #if defined(LIBUSB)
|
---|
[1466] | 415 | case R_SMART:
|
---|
[1477] | 416 | call (SR_Close(&reader[ridx]));
|
---|
[1466] | 417 | break;
|
---|
[1389] | 418 | #endif
|
---|
[1466] | 419 | case R_INTERNAL:
|
---|
[1266] | 420 | #ifdef SCI_DEV
|
---|
[1466] | 421 | /* Dectivate ICC */
|
---|
[1477] | 422 | call (Sci_Deactivate());
|
---|
[1511] | 423 | call (Phoenix_Close());
|
---|
[1266] | 424 | #endif
|
---|
[1466] | 425 | break;
|
---|
| 426 | default:
|
---|
| 427 | cs_log("ERROR ICC_Async_Close: unknow reader type %i",reader[ridx].typ);
|
---|
[1476] | 428 | return ERROR;
|
---|
[1466] | 429 | }
|
---|
[8] | 430 |
|
---|
[1399] | 431 | cs_debug_mask (D_IFD, "IFD: Device %s succesfully closed", reader[ridx].device);
|
---|
[1389] | 432 | return OK;
|
---|
[8] | 433 | }
|
---|
| 434 |
|
---|
[1224] | 435 | unsigned long ICC_Async_GetClockRate ()
|
---|
[8] | 436 | {
|
---|
[1220] | 437 | switch (reader[ridx].cardmhz) {
|
---|
[746] | 438 | case 357:
|
---|
| 439 | case 358:
|
---|
| 440 | return (372L * 9600L);
|
---|
| 441 | case 368:
|
---|
| 442 | return (384L * 9600L);
|
---|
| 443 | default:
|
---|
[1220] | 444 | return reader[ridx].cardmhz * 10000L;
|
---|
[746] | 445 | }
|
---|
[8] | 446 | }
|
---|
| 447 |
|
---|
| 448 | static void ICC_Async_InvertBuffer (unsigned size, BYTE * buffer)
|
---|
| 449 | {
|
---|
[1137] | 450 | uint i;
|
---|
[8] | 451 |
|
---|
| 452 | for (i = 0; i < size; i++)
|
---|
| 453 | buffer[i] = ~(INVERT_BYTE (buffer[i]));
|
---|
| 454 | }
|
---|
[1389] | 455 |
|
---|
[1419] | 456 | static int Parse_ATR (ATR * atr, unsigned short deprecated)
|
---|
[1389] | 457 | {
|
---|
| 458 | BYTE FI = ATR_DEFAULT_FI;
|
---|
| 459 | //BYTE t = ATR_PROTOCOL_TYPE_T0;
|
---|
| 460 | double d = ATR_DEFAULT_D;
|
---|
| 461 | double n = ATR_DEFAULT_N;
|
---|
| 462 | int ret;
|
---|
| 463 |
|
---|
| 464 | int numprot = atr->pn;
|
---|
| 465 | //if there is a trailing TD, this number is one too high
|
---|
| 466 | BYTE tx;
|
---|
| 467 | if (ATR_GetInterfaceByte (atr, numprot-1, ATR_INTERFACE_BYTE_TD, &tx) == ATR_OK)
|
---|
| 468 | if ((tx & 0xF0) == 0)
|
---|
| 469 | numprot--;
|
---|
| 470 | int i,point;
|
---|
| 471 | char txt[50];
|
---|
| 472 | bool OffersT[3]; //T14 stored as T2
|
---|
| 473 | for (i = 0; i <= 2; i++)
|
---|
| 474 | OffersT[i] = FALSE;
|
---|
| 475 | for (i=1; i<= numprot; i++) {
|
---|
| 476 | point = 0;
|
---|
| 477 | if (ATR_GetInterfaceByte (atr, i, ATR_INTERFACE_BYTE_TA, &tx) == ATR_OK) {
|
---|
| 478 | sprintf((char *)txt+point,"TA%i=%02X ",i,tx);
|
---|
| 479 | point +=7;
|
---|
| 480 | }
|
---|
| 481 | if (ATR_GetInterfaceByte (atr, i, ATR_INTERFACE_BYTE_TB, &tx) == ATR_OK) {
|
---|
| 482 | sprintf((char *)txt+point,"TB%i=%02X ",i,tx);
|
---|
| 483 | point +=7;
|
---|
| 484 | }
|
---|
| 485 | if (ATR_GetInterfaceByte (atr, i, ATR_INTERFACE_BYTE_TC, &tx) == ATR_OK) {
|
---|
| 486 | sprintf((char *)txt+point,"TC%i=%02X ",i,tx);
|
---|
| 487 | point +=7;
|
---|
| 488 | }
|
---|
| 489 | if (ATR_GetInterfaceByte (atr, i, ATR_INTERFACE_BYTE_TD, &tx) == ATR_OK) {
|
---|
| 490 | sprintf((char *)txt+point,"TD%i=%02X ",i,tx);
|
---|
| 491 | point +=7;
|
---|
| 492 | tx &= 0X0F;
|
---|
| 493 | sprintf((char *)txt+point,"(T%i)",tx);
|
---|
| 494 | if (tx == 14)
|
---|
| 495 | OffersT[2] = TRUE;
|
---|
| 496 | else
|
---|
| 497 | OffersT[tx] = TRUE;
|
---|
| 498 | }
|
---|
| 499 | else {
|
---|
| 500 | sprintf((char *)txt+point,"no TD%i means T0",i);
|
---|
| 501 | OffersT[0] = TRUE;
|
---|
| 502 | }
|
---|
| 503 | cs_debug("%s",txt);
|
---|
| 504 | }
|
---|
| 505 |
|
---|
| 506 | int numprottype = 0;
|
---|
| 507 | for (i = 0; i <= 2; i++)
|
---|
| 508 | if (OffersT[i])
|
---|
| 509 | numprottype ++;
|
---|
| 510 | cs_debug("%i protocol types detected. Historical bytes: %s",numprottype, cs_hexdump(1,atr->hb,atr->hbn));
|
---|
| 511 |
|
---|
| 512 | ATR_GetParameter (atr, ATR_PARAMETER_N, &(n));
|
---|
| 513 | ATR_GetProtocolType(atr,1,&(protocol_type)); //get protocol from TD1
|
---|
| 514 | BYTE TA2;
|
---|
| 515 | bool SpecificMode = (ATR_GetInterfaceByte (atr, 2, ATR_INTERFACE_BYTE_TA, &TA2) == ATR_OK); //if TA2 present, specific mode, else negotiable mode
|
---|
| 516 | if (SpecificMode) {
|
---|
| 517 | protocol_type = TA2 & 0x0F;
|
---|
| 518 | if ((TA2 & 0x10) != 0x10) { //bit 5 set to 0 means F and D explicitly defined in interface characters
|
---|
| 519 | BYTE TA1;
|
---|
| 520 | if (ATR_GetInterfaceByte (atr, 1 , ATR_INTERFACE_BYTE_TA, &TA1) == ATR_OK) {
|
---|
| 521 | FI = TA1 >> 4;
|
---|
| 522 | ATR_GetParameter (atr, ATR_PARAMETER_D, &(d));
|
---|
| 523 | }
|
---|
| 524 | else {
|
---|
| 525 | FI = ATR_DEFAULT_FI;
|
---|
| 526 | d = ATR_DEFAULT_D;
|
---|
| 527 | }
|
---|
| 528 | }
|
---|
| 529 | else {
|
---|
| 530 | cs_log("Specific mode: speed 'implicitly defined', not sure how to proceed, assuming default values");
|
---|
| 531 | FI = ATR_DEFAULT_FI;
|
---|
| 532 | d = ATR_DEFAULT_D;
|
---|
| 533 | }
|
---|
| 534 | cs_debug("Specific mode: T%i, F=%.0f, D=%.6f, N=%.0f\n", protocol_type, (double) atr_f_table[FI], d, n);
|
---|
| 535 | }
|
---|
| 536 | else { //negotiable mode
|
---|
| 537 |
|
---|
[1391] | 538 | bool PPS_success = FALSE;
|
---|
[1514] | 539 | bool NeedsPTS = ((protocol_type != ATR_PROTOCOL_TYPE_T14) && (numprottype > 1 || (atr->ib[0][ATR_INTERFACE_BYTE_TA].present == TRUE && atr->ib[0][ATR_INTERFACE_BYTE_TA].value != 0x11) || n == 255)); //needs PTS according to old ISO 7816
|
---|
[1419] | 540 | if (NeedsPTS && deprecated == 0) {
|
---|
[1389] | 541 | // PTSS PTS0 PTS1 PCK
|
---|
| 542 | BYTE req[] = { 0xFF, 0x10, 0x00, 0x00 }; //we currently do not support PTS2, standard guardtimes
|
---|
| 543 | req[1]=0x10 | protocol_type; //PTS0 always flags PTS1 to be sent always
|
---|
| 544 | if (ATR_GetInterfaceByte (atr, 1, ATR_INTERFACE_BYTE_TA, &req[2]) != ATR_OK) //PTS1
|
---|
| 545 | req[2] = 0x11; //defaults FI and DI to 1
|
---|
| 546 | unsigned int len = sizeof(req);
|
---|
| 547 | ret = PPS_Exchange (req, &len);
|
---|
| 548 | if (ret == OK) {
|
---|
| 549 | FI = req[2] >> 4;
|
---|
| 550 | BYTE DI = req[2] & 0x0F;
|
---|
| 551 | d = (double) (atr_d_table[DI]);
|
---|
| 552 | PPS_success = TRUE;
|
---|
| 553 | cs_debug("PTS Succesfull, selected protocol: T%i, F=%.0f, D=%.6f, N=%.0f\n", protocol_type, (double) atr_f_table[FI], d, n);
|
---|
| 554 | }
|
---|
| 555 | else
|
---|
| 556 | cs_ddump(req,4,"PTS Failure, response:");
|
---|
| 557 | }
|
---|
| 558 |
|
---|
| 559 | //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)
|
---|
| 560 | if (!PPS_success) {//last PPS not succesfull
|
---|
| 561 | BYTE TA1;
|
---|
| 562 | if (ATR_GetInterfaceByte (atr, 1 , ATR_INTERFACE_BYTE_TA, &TA1) == ATR_OK) {
|
---|
| 563 | FI = TA1 >> 4;
|
---|
| 564 | ATR_GetParameter (atr, ATR_PARAMETER_D, &(d));
|
---|
| 565 | }
|
---|
| 566 | else { //do not obey TA1
|
---|
| 567 | FI = ATR_DEFAULT_FI;
|
---|
| 568 | d = ATR_DEFAULT_D;
|
---|
| 569 | }
|
---|
| 570 | if (NeedsPTS) {
|
---|
| 571 | if ((d == 32) || (d == 12) || (d == 20)) //those values were RFU in old table
|
---|
| 572 | d = 0; // viaccess cards that fail PTS need this
|
---|
| 573 | }
|
---|
| 574 |
|
---|
| 575 | cs_debug("No PTS %s, selected protocol T%i, F=%.0f, D=%.6f, N=%.0f\n", NeedsPTS?"happened":"needed", protocol_type, (double) atr_f_table[FI], d, n);
|
---|
| 576 | }
|
---|
| 577 | }//end negotiable mode
|
---|
| 578 |
|
---|
| 579 | //make sure no zero values
|
---|
| 580 | double F = (double) atr_f_table[FI];
|
---|
| 581 | if (!F) {
|
---|
| 582 | FI = ATR_DEFAULT_FI;
|
---|
| 583 | cs_log("Warning: F=0 is invalid, forcing FI=%d", FI);
|
---|
| 584 | }
|
---|
| 585 | if (!d) {
|
---|
| 586 | d = ATR_DEFAULT_D;
|
---|
| 587 | cs_log("Warning: D=0 is invalid, forcing D=%.0f",d);
|
---|
| 588 | }
|
---|
| 589 |
|
---|
[1419] | 590 | if (deprecated == 0)
|
---|
| 591 | return InitCard (atr, FI, d, n, deprecated);
|
---|
| 592 | else
|
---|
| 593 | return InitCard (atr, ATR_DEFAULT_FI, ATR_DEFAULT_D, n, deprecated);
|
---|
[1389] | 594 | }
|
---|
| 595 |
|
---|
| 596 | static int PPS_Exchange (BYTE * params, unsigned *length)
|
---|
| 597 | {
|
---|
| 598 | BYTE confirm[PPS_MAX_LENGTH];
|
---|
| 599 | unsigned len_request, len_confirm;
|
---|
| 600 | int ret;
|
---|
| 601 |
|
---|
| 602 | len_request = PPS_GetLength (params);
|
---|
| 603 | params[len_request - 1] = PPS_GetPCK(params, len_request - 1);
|
---|
[1399] | 604 | cs_debug_mask (D_IFD,"PTS: Sending request: %s", cs_hexdump(1, params, len_request));
|
---|
[1389] | 605 |
|
---|
| 606 | /* Send PPS request */
|
---|
[1477] | 607 | call (ICC_Async_Transmit (len_request, params));
|
---|
[1389] | 608 |
|
---|
| 609 | /* Get PPS confirm */
|
---|
[1477] | 610 | call (ICC_Async_Receive (2, confirm));
|
---|
[1389] | 611 | len_confirm = PPS_GetLength (confirm);
|
---|
[1477] | 612 | call (ICC_Async_Receive (len_confirm - 2, confirm + 2));
|
---|
[1389] | 613 |
|
---|
[1399] | 614 | cs_debug_mask(D_IFD, "PTS: Receiving confirm: %s", cs_hexdump(1, confirm, len_confirm));
|
---|
[1389] | 615 | if ((len_request != len_confirm) || (memcmp (params, confirm, len_request)))
|
---|
| 616 | ret = ERROR;
|
---|
| 617 | else
|
---|
| 618 | ret = OK;
|
---|
| 619 |
|
---|
| 620 | /* Copy PPS handsake */
|
---|
| 621 | memcpy (params, confirm, len_confirm);
|
---|
| 622 | (*length) = len_confirm;
|
---|
| 623 | return ret;
|
---|
| 624 | }
|
---|
| 625 |
|
---|
| 626 | static unsigned PPS_GetLength (BYTE * block)
|
---|
| 627 | {
|
---|
| 628 | unsigned length = 3;
|
---|
| 629 |
|
---|
| 630 | if (PPS_HAS_PPS1 (block))
|
---|
| 631 | length++;
|
---|
| 632 |
|
---|
| 633 | if (PPS_HAS_PPS2 (block))
|
---|
| 634 | length++;
|
---|
| 635 |
|
---|
| 636 | if (PPS_HAS_PPS3 (block))
|
---|
| 637 | length++;
|
---|
| 638 |
|
---|
| 639 | return length;
|
---|
| 640 | }
|
---|
| 641 |
|
---|
| 642 | static unsigned int ETU_to_ms(unsigned long WWT)
|
---|
| 643 | {
|
---|
| 644 | #define CHAR_LEN 10L //character length in ETU, perhaps should be 9 when parity = none?
|
---|
| 645 | if (WWT > CHAR_LEN)
|
---|
| 646 | WWT -= CHAR_LEN;
|
---|
| 647 | else
|
---|
| 648 | WWT = 0;
|
---|
| 649 | double work_etu = 1000 / (double)current_baudrate;//FIXME sometimes work_etu should be used, sometimes initial etu
|
---|
| 650 | return (unsigned int) WWT * work_etu * reader[ridx].cardmhz / reader[ridx].mhz;
|
---|
| 651 | }
|
---|
| 652 |
|
---|
[1435] | 653 | static int ICC_Async_SetParity (unsigned short parity)
|
---|
| 654 | {
|
---|
[1466] | 655 | switch(reader[ridx].typ) {
|
---|
| 656 | case R_DB2COM1:
|
---|
| 657 | case R_DB2COM2:
|
---|
| 658 | case R_MOUSE:
|
---|
[1477] | 659 | call (IO_Serial_SetParity (parity));
|
---|
[1466] | 660 | break;
|
---|
[1435] | 661 | #if defined(LIBUSB)
|
---|
[1466] | 662 | case R_SMART:
|
---|
| 663 | reader[ridx].sr_config.inv= (convention == ATR_CONVENTION_INVERSE) ? 1: 0;
|
---|
| 664 | reader[ridx].sr_config.parity=parity;
|
---|
[1477] | 665 | call (SR_SetParity(&reader[ridx]));
|
---|
[1466] | 666 | break;
|
---|
| 667 | #endif
|
---|
| 668 | case R_INTERNAL:
|
---|
| 669 | return OK;
|
---|
| 670 | default:
|
---|
| 671 | cs_log("ERROR ICC_Async_SetParity: unknow reader type %i",reader[ridx].typ);
|
---|
[1476] | 672 | return ERROR;
|
---|
[1435] | 673 | }
|
---|
| 674 | return OK;
|
---|
| 675 | }
|
---|
| 676 |
|
---|
[1389] | 677 | static int SetRightParity (void)
|
---|
| 678 | {
|
---|
| 679 | //set right parity
|
---|
[1435] | 680 | unsigned short parity = PARITY_EVEN;
|
---|
[1389] | 681 | if (convention == ATR_CONVENTION_INVERSE)
|
---|
[1435] | 682 | parity = PARITY_ODD;
|
---|
[1389] | 683 | else if(protocol_type == ATR_PROTOCOL_TYPE_T14)
|
---|
[1435] | 684 | parity = PARITY_NONE;
|
---|
| 685 |
|
---|
[1477] | 686 | call (ICC_Async_SetParity(parity));
|
---|
[1435] | 687 |
|
---|
[1389] | 688 | #ifdef COOL
|
---|
| 689 | if (reader[ridx].typ != R_INTERNAL)
|
---|
| 690 | #endif
|
---|
| 691 | #if defined(LIBUSB)
|
---|
[1466] | 692 | if (reader[ridx].typ != R_SMART)
|
---|
[1389] | 693 | #endif
|
---|
| 694 | IO_Serial_Flush();
|
---|
| 695 | return OK;
|
---|
| 696 | }
|
---|
| 697 |
|
---|
[1419] | 698 | static int InitCard (ATR * atr, BYTE FI, double d, double n, unsigned short deprecated)
|
---|
[1389] | 699 | {
|
---|
[1398] | 700 | double P,I;
|
---|
| 701 | double F;
|
---|
| 702 | unsigned long BGT, edc, EGT, CGT, WWT = 0;
|
---|
| 703 | unsigned int GT;
|
---|
| 704 | unsigned long gt_ms;
|
---|
[1430] | 705 | current_baudrate = DEFAULT_BAUDRATE;
|
---|
[1398] | 706 |
|
---|
[1389] | 707 | //set the amps and the volts according to ATR
|
---|
| 708 | if (ATR_GetParameter(atr, ATR_PARAMETER_P, &P) != ATR_OK)
|
---|
| 709 | P = 0;
|
---|
| 710 | if (ATR_GetParameter(atr, ATR_PARAMETER_I, &I) != ATR_OK)
|
---|
| 711 | I = 0;
|
---|
| 712 |
|
---|
| 713 | //set clock speed to max if internal reader
|
---|
[1466] | 714 | if(reader[ridx].typ > R_MOUSE)
|
---|
[1389] | 715 | if (reader[ridx].mhz == 357 || reader[ridx].mhz == 358) //no overclocking
|
---|
| 716 | reader[ridx].mhz = atr_fs_table[FI] / 10000; //we are going to clock the card to this nominal frequency
|
---|
| 717 |
|
---|
[1466] | 718 | //set clock speed/baudrate must be done before timings
|
---|
| 719 | //because current_baudrate is used in calculation of timings
|
---|
| 720 | F = (double) atr_f_table[FI];
|
---|
[1389] | 721 |
|
---|
[1466] | 722 | if (deprecated == 0)
|
---|
| 723 | if (protocol_type != ATR_PROTOCOL_TYPE_T14) { //dont switch for T14
|
---|
| 724 | unsigned long baud_temp = d * ICC_Async_GetClockRate () / F;
|
---|
| 725 | if (reader[ridx].typ <= R_MOUSE)
|
---|
[1477] | 726 | call (Phoenix_SetBaudrate (baud_temp));
|
---|
[1466] | 727 | cs_debug_mask(D_IFD, "Setting baudrate to %lu", baud_temp);
|
---|
| 728 | current_baudrate = baud_temp; //this is needed for all readers to calculate work_etu for timings
|
---|
| 729 | }
|
---|
| 730 |
|
---|
[1389] | 731 | //set timings according to ATR
|
---|
| 732 | read_timeout = 0;
|
---|
| 733 | icc_timings.block_delay = 0;
|
---|
| 734 | icc_timings.char_delay = 0;
|
---|
| 735 |
|
---|
| 736 | if (n == 255) //Extra Guard Time
|
---|
| 737 | EGT = 0;
|
---|
| 738 | else
|
---|
| 739 | EGT = n;
|
---|
[1398] | 740 | GT = EGT + 12; //Guard Time in ETU
|
---|
| 741 | gt_ms = ETU_to_ms(GT);
|
---|
[1389] | 742 |
|
---|
| 743 | switch (protocol_type) {
|
---|
| 744 | case ATR_PROTOCOL_TYPE_T0:
|
---|
| 745 | case ATR_PROTOCOL_TYPE_T14:
|
---|
| 746 | {
|
---|
| 747 | BYTE wi;
|
---|
| 748 | /* Integer value WI = TC2, by default 10 */
|
---|
| 749 | #ifndef PROTOCOL_T0_USE_DEFAULT_TIMINGS
|
---|
| 750 | if (ATR_GetInterfaceByte (atr, 2, ATR_INTERFACE_BYTE_TC, &(wi)) != ATR_OK)
|
---|
| 751 | #endif
|
---|
| 752 | wi = DEFAULT_WI;
|
---|
| 753 |
|
---|
| 754 | // WWT = 960 * WI * (Fi / f) * 1000 milliseconds
|
---|
| 755 | WWT = (unsigned long) 960 * wi; //in ETU
|
---|
| 756 | if (protocol_type == ATR_PROTOCOL_TYPE_T14)
|
---|
| 757 | WWT >>= 1; //is this correct?
|
---|
| 758 |
|
---|
| 759 | read_timeout = ETU_to_ms(WWT);
|
---|
| 760 | icc_timings.block_delay = gt_ms;
|
---|
| 761 | icc_timings.char_delay = gt_ms;
|
---|
| 762 | cs_debug("Setting timings: timeout=%u ms, block_delay=%u ms, char_delay=%u ms", read_timeout, icc_timings.block_delay, icc_timings.char_delay);
|
---|
[1399] | 763 | cs_debug_mask (D_IFD,"Protocol: T=%i: WWT=%d, Clockrate=%lu\n", protocol_type, (int)(WWT), ICC_Async_GetClockRate());
|
---|
[1389] | 764 | }
|
---|
| 765 | break;
|
---|
| 766 | case ATR_PROTOCOL_TYPE_T1:
|
---|
| 767 | {
|
---|
| 768 | BYTE ta, tb, tc, cwi, bwi;
|
---|
| 769 |
|
---|
| 770 | // Set IFSC
|
---|
| 771 | if (ATR_GetInterfaceByte (atr, 3, ATR_INTERFACE_BYTE_TA, &ta) == ATR_NOT_FOUND)
|
---|
| 772 | ifsc = DEFAULT_IFSC;
|
---|
| 773 | else if ((ta != 0x00) && (ta != 0xFF))
|
---|
| 774 | ifsc = ta;
|
---|
| 775 | else
|
---|
| 776 | ifsc = DEFAULT_IFSC;
|
---|
| 777 |
|
---|
| 778 | // Towitoko does not allow IFSC > 251 //FIXME not sure whether this limitation still exists
|
---|
[1658] | 779 | // ifsc = MIN (ifsc, MAX_IFSC);
|
---|
| 780 |
|
---|
| 781 | //FIXME workaround for Smargo until native mode works
|
---|
| 782 | if(reader[ridx].smargopatch == 1)
|
---|
| 783 | ifsc = MIN (ifsc, 28);
|
---|
| 784 | else
|
---|
| 785 | ifsc = MIN (ifsc, MAX_IFSC);
|
---|
[1389] | 786 |
|
---|
| 787 | #ifndef PROTOCOL_T1_USE_DEFAULT_TIMINGS
|
---|
| 788 | // Calculate CWI and BWI
|
---|
| 789 | if (ATR_GetInterfaceByte (atr, 3, ATR_INTERFACE_BYTE_TB, &tb) == ATR_NOT_FOUND)
|
---|
| 790 | {
|
---|
| 791 | #endif
|
---|
| 792 | cwi = DEFAULT_CWI;
|
---|
| 793 | bwi = DEFAULT_BWI;
|
---|
| 794 | #ifndef PROTOCOL_T1_USE_DEFAULT_TIMINGS
|
---|
| 795 | }
|
---|
| 796 | else
|
---|
| 797 | {
|
---|
| 798 | cwi = tb & 0x0F;
|
---|
| 799 | bwi = tb >> 4;
|
---|
| 800 | }
|
---|
| 801 | #endif
|
---|
| 802 |
|
---|
| 803 | // Set CWT = (2^CWI + 11) work etu
|
---|
| 804 | CWT = (unsigned short) (((1<<cwi) + 11)); // in ETU
|
---|
| 805 |
|
---|
| 806 | // Set BWT = (2^BWI * 960 + 11) work etu
|
---|
| 807 | BWT = (unsigned short)((1<<bwi) * 960 * 372 * 9600 / ICC_Async_GetClockRate() ) + 11 ;
|
---|
| 808 |
|
---|
| 809 | // Set BGT = 22 * work etu
|
---|
| 810 | BGT = 22L; //in ETU
|
---|
| 811 |
|
---|
| 812 | if (n == 255)
|
---|
| 813 | CGT = 11L; //in ETU
|
---|
| 814 | else
|
---|
| 815 | CGT = GT;
|
---|
| 816 |
|
---|
| 817 | // Set the error detection code type
|
---|
| 818 | if (ATR_GetInterfaceByte (atr, 3, ATR_INTERFACE_BYTE_TC, &tc) == ATR_NOT_FOUND)
|
---|
| 819 | edc = EDC_LRC;
|
---|
| 820 | else
|
---|
| 821 | edc = tc & 0x01;
|
---|
| 822 |
|
---|
| 823 | // Set initial send sequence (NS)
|
---|
| 824 | ns = 1;
|
---|
| 825 |
|
---|
| 826 | cs_debug ("Protocol: T=1: IFSC=%d, CWT=%d etu, BWT=%d etu, BGT=%d etu, EDC=%s\n", ifsc, CWT, BWT, BGT, (edc == EDC_LRC) ? "LRC" : "CRC");
|
---|
| 827 |
|
---|
| 828 | read_timeout = ETU_to_ms(BWT);
|
---|
| 829 | icc_timings.block_delay = ETU_to_ms(BGT);
|
---|
| 830 | icc_timings.char_delay = ETU_to_ms(CGT);
|
---|
| 831 | cs_debug("Setting timings: timeout=%u ms, block_delay=%u ms, char_delay=%u ms", read_timeout, icc_timings.block_delay, icc_timings.char_delay);
|
---|
| 832 | }
|
---|
| 833 | break;
|
---|
| 834 | default:
|
---|
| 835 | return ERROR;
|
---|
| 836 | break;
|
---|
| 837 | }//switch
|
---|
| 838 |
|
---|
[1477] | 839 | call (SetRightParity ());
|
---|
[1389] | 840 |
|
---|
| 841 | //write settings to internal device
|
---|
| 842 | if(reader[ridx].typ == R_INTERNAL) {
|
---|
| 843 | #ifdef SCI_DEV
|
---|
| 844 | double F = (double) atr_f_table[FI];
|
---|
| 845 | unsigned long ETU = 0;
|
---|
| 846 | //for Irdeto T14 cards, do not set ETU
|
---|
[1419] | 847 | if (!(atr->hbn >= 6 && !memcmp(atr->hb, "IRDETO", 6) && protocol_type == ATR_PROTOCOL_TYPE_T14))
|
---|
[1389] | 848 | ETU = F / d;
|
---|
[1477] | 849 | call (Sci_WriteSettings (protocol_type, reader[ridx].mhz / 100, ETU, WWT, BWT, CWT, EGT, (unsigned char)P, (unsigned char)I));
|
---|
[1389] | 850 | #elif COOL
|
---|
[1477] | 851 | call (Cool_SetClockrate(reader[ridx].mhz));
|
---|
| 852 | call (Cool_WriteSettings (BWT, CWT, EGT, BGT));
|
---|
[1389] | 853 | #endif //COOL
|
---|
| 854 | }
|
---|
[1435] | 855 | #if defined(LIBUSB)
|
---|
[1466] | 856 | if (reader[ridx].typ == R_SMART)
|
---|
[1435] | 857 | SR_WriteSettings(&reader[ridx], (unsigned short) atr_f_table[FI], (BYTE)d, (BYTE)EGT, (BYTE)protocol_type);
|
---|
| 858 | #endif
|
---|
[1466] | 859 | cs_log("Maximum frequency for this card is formally %i Mhz, clocking it to %.2f Mhz", atr_fs_table[FI] / 1000000, (float) reader[ridx].mhz / 100);
|
---|
[1389] | 860 |
|
---|
| 861 | //IFS setting in case of T1
|
---|
| 862 | if ((protocol_type == ATR_PROTOCOL_TYPE_T1) && (ifsc != DEFAULT_IFSC)) {
|
---|
| 863 | APDU_Rsp ** rsp;
|
---|
| 864 | unsigned char tmp[] = { 0x21, 0xC1, 0x01, 0x00, 0x00 };
|
---|
| 865 | tmp[3] = ifsc; // Information Field size
|
---|
| 866 | tmp[4] = ifsc ^ 0xE1;
|
---|
[1559] | 867 | Protocol_T1_Command (tmp, sizeof(tmp), rsp);
|
---|
[1389] | 868 | }
|
---|
[1391] | 869 | return OK;
|
---|
[1389] | 870 | }
|
---|
| 871 |
|
---|
| 872 | static BYTE PPS_GetPCK (BYTE * block, unsigned length)
|
---|
| 873 | {
|
---|
| 874 | BYTE pck;
|
---|
| 875 | unsigned i;
|
---|
| 876 |
|
---|
| 877 | pck = block[0];
|
---|
| 878 | for (i = 1; i < length; i++)
|
---|
| 879 | pck ^= block[i];
|
---|
| 880 |
|
---|
| 881 | return pck;
|
---|
| 882 | }
|
---|