1 /*
2 acr38cmd.c: Emulated CCID reader commands for ACR38 non-CCID reader
3 Copyright (C) 2011-2017 Advanced Card Systems Ltd.
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public License
16 along with this library; if not, write to the Free Software Foundation,
17 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include <config.h>
21
22 #ifdef HAVE_STRING_H
23 #include <string.h>
24 #endif
25 #ifdef HAVE_STDLIB_H
26 #include <stdlib.h>
27 #endif
28 #ifdef HAVE_ERRNO_H
29 #include <errno.h>
30 #endif
31 #ifdef HAVE_UNISTD_H
32 #include <unistd.h>
33 #endif
34
35 #include <pcsclite.h>
36 #include <ifdhandler.h>
37 #include <reader.h>
38
39 #include "misc.h"
40 #include "acr38cmd.h"
41 #include "openct/proto-t1.h"
42 #include "ccid.h"
43 #include "defs.h"
44 #include "ccid_ifdhandler.h"
45 #include "debug.h"
46
47 #define ACR38_HEADER_SIZE 4
48 #define ACR38_STATUS_OFFSET 1
49
50 // Card type
51 #define CARD_TYPE_MCU_AUTO 0
52 #define CARD_TYPE_I2C_AUTO 1 // Not supported
53 #define CARD_TYPE_I2C_1K 2
54 #define CARD_TYPE_I2C_2K 3
55 #define CARD_TYPE_I2C_4K 4
56 #define CARD_TYPE_I2C_8K 5
57 #define CARD_TYPE_I2C_16K 6
58 #define CARD_TYPE_I2C_32K 7
59 #define CARD_TYPE_I2C_64K 8
60 #define CARD_TYPE_I2C_128K 9
61 #define CARD_TYPE_I2C_256K 10
62 #define CARD_TYPE_I2C_512K 11
63 #define CARD_TYPE_I2C_1024K 12
64 #define CARD_TYPE_AT88SC153 13
65 #define CARD_TYPE_AT88SC1608 14
66 #define CARD_TYPE_SLE4418 15
67 #define CARD_TYPE_SLE4428 16
68 #define CARD_TYPE_SLE4432 17
69 #define CARD_TYPE_SLE4442 18
70 #define CARD_TYPE_SLE4406 19
71 #define CARD_TYPE_SLE4436 20
72 #define CARD_TYPE_SLE5536 21
73 #define CARD_TYPE_MCU_T0 22
74 #define CARD_TYPE_MCU_T1 23
75 #define CARD_TYPE_AUTO 24 // Not supported
76
77 // ACR38 card type
78 #define ACR38_CARD_TYPE_MCU_AUTO 0x00
79 #define ACR38_CARD_TYPE_I2C_1K_16K 0x01
80 #define ACR38_CARD_TYPE_I2C_32K_1024K 0x02
81 #define ACR38_CARD_TYPE_AT88SC153 0x03
82 #define ACR38_CARD_TYPE_AT88SC1608 0x04
83 #define ACR38_CARD_TYPE_SLE4418_4428 0x05
84 #define ACR38_CARD_TYPE_SLE4432_4442 0x06
85 #define ACR38_CARD_TYPE_SLE4406_4436_5536 0x07
86 #define ACR38_CARD_TYPE_MCU_T0 0x0C
87 #define ACR38_CARD_TYPE_MCU_T1 0x0D
88
89 // ACR38 option
90 #define ACR38_OPTION_NONE 0x00 // No option
91 #define ACR38_OPTION_EMV_MODE 0x10 // EMV mode
92 #define ACR38_OPTION_MEMCARD_MODE 0x20 // Memory card mode
93
94 #define CHECK_STATUS(res) \
95 if (STATUS_NO_SUCH_DEVICE == res) \
96 return IFD_NO_SUCH_DEVICE; \
97 if (STATUS_SUCCESS != res) \
98 return IFD_COMMUNICATION_ERROR;
99
100 static RESPONSECODE ACR38_CmdXfrBlockTPDU_T0(unsigned int reader_index,
101 unsigned int tx_length, unsigned char tx_buffer[], unsigned int *rx_length,
102 unsigned char rx_buffer[]);
103
104 static RESPONSECODE ACR38_CmdXfrBlockTPDU_T1(unsigned int reader_index,
105 unsigned int tx_length, unsigned char tx_buffer[], unsigned int *rx_length,
106 unsigned char rx_buffer[]);
107
108 static RESPONSECODE ACR38_CmdSelectCardType(unsigned int reader_index, unsigned char card_type);
109
110 static RESPONSECODE ACR38_CmdSetOption(unsigned int reader_index, unsigned char option);
111
ACR38_CmdPowerOn(unsigned int reader_index,unsigned int * nlength,unsigned char buffer[],int voltage)112 RESPONSECODE ACR38_CmdPowerOn(unsigned int reader_index, unsigned int *nlength,
113 /*@out@*/ unsigned char buffer[], int voltage)
114 {
115 unsigned char cmd[6];
116 unsigned int cmdLen;
117 status_t res;
118 unsigned int length;
119 RESPONSECODE return_value = IFD_SUCCESS;
120 _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
121 unsigned char option = ACR38_OPTION_NONE;
122
123 /* store length of buffer[] */
124 length = *nlength;
125
126 if (ccid_descriptor->bCurrentSlotIndex == 0)
127 {
128 // Set option
129 if ((ccid_descriptor->cardType == ACR38_CARD_TYPE_MCU_AUTO) ||
130 (ccid_descriptor->cardType == ACR38_CARD_TYPE_MCU_T0) ||
131 (ccid_descriptor->cardType == ACR38_CARD_TYPE_MCU_T1))
132 {
133 option = ACR38_OPTION_NONE;
134 }
135 else
136 {
137 option = ACR38_OPTION_MEMCARD_MODE;
138 }
139 (void)ACR38_CmdSetOption(reader_index, option);
140
141 // Select card type
142 (void)ACR38_CmdSelectCardType(reader_index, ccid_descriptor->cardType);
143 }
144
145 if (ccid_descriptor->bCurrentSlotIndex == 0)
146 {
147 // RESET_WITH_SPECIFIC_VOLTAGE
148 cmd[0] = 0x01;
149 cmd[1] = 0x80;
150 cmd[2] = 0x00;
151 cmd[3] = 0x01;
152 cmd[4] = ccid_descriptor->cardVoltage;
153 cmdLen = 5;
154 }
155 else
156 {
157 // Power off SAM
158 (void)ACR38_CmdPowerOff(reader_index);
159 usleep(10 * 1000);
160
161 // RESET_WITH_5_VOLTS_DEFAULT_SAM
162 cmd[0] = 0x01;
163 cmd[1] = 0x90;
164 cmd[2] = 0x00;
165 cmd[3] = 0x00;
166 cmdLen = 4;
167 }
168
169 res = WritePort(reader_index, cmdLen, cmd);
170 CHECK_STATUS(res)
171
172 /* reset available buffer size */
173 /* needed if we go back after a switch to ISO mode */
174 *nlength = length;
175
176 res = ReadPort(reader_index, nlength, buffer);
177 CHECK_STATUS(res)
178
179 if (buffer[ACR38_STATUS_OFFSET] != 0)
180 {
181 acr38_error(buffer[ACR38_STATUS_OFFSET], __FILE__, __LINE__, __FUNCTION__);
182 return IFD_COMMUNICATION_ERROR;
183 }
184
185 // If memory card had been selected
186 if ((ccid_descriptor->bCurrentSlotIndex == 0) &&
187 (option == ACR38_OPTION_MEMCARD_MODE))
188 {
189 unsigned char buffer_tmp[16];
190 unsigned int bufferLen = sizeof(buffer_tmp);
191
192 // SELECT_CARD_TYPE
193 cmd[0] = 0xFF;
194 cmd[1] = 0xA4;
195 cmd[2] = 0x00;
196 cmd[3] = 0x00;
197 cmd[4] = 0x01;
198 cmd[5] = ccid_descriptor->cardType;
199 cmdLen = 6;
200
201 (void)ACR38_CmdXfrBlockTPDU_T0(reader_index, cmdLen, cmd, &bufferLen, buffer_tmp);
202 }
203
204 /* extract the ATR */
205 *nlength -= ACR38_HEADER_SIZE;
206 memmove(buffer, buffer + ACR38_HEADER_SIZE, *nlength);
207
208 return return_value;
209 }
210
ACR38_CmdPowerOff(unsigned int reader_index)211 RESPONSECODE ACR38_CmdPowerOff(unsigned int reader_index)
212 {
213 unsigned char cmd[4];
214 status_t res;
215 unsigned int length;
216 RESPONSECODE return_value = IFD_SUCCESS;
217 _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
218
219 // POWER_OFF or POWER_OFF_SAM
220 cmd[0] = 0x01;
221 cmd[1] = ccid_descriptor->bCurrentSlotIndex == 0 ? 0x81 : 0x91;
222 cmd[2] = 0x00;
223 cmd[3] = 0x00;
224
225 res = WritePort(reader_index, sizeof(cmd), cmd);
226 CHECK_STATUS(res)
227
228 length = sizeof(cmd);
229 res = ReadPort(reader_index, &length, cmd);
230 CHECK_STATUS(res)
231
232 if (cmd[ACR38_STATUS_OFFSET] != 0)
233 {
234 acr38_error(cmd[ACR38_STATUS_OFFSET], __FILE__, __LINE__, __FUNCTION__);
235 return_value = IFD_COMMUNICATION_ERROR;
236 }
237
238 return return_value;
239 }
240
ACR38_CmdGetSlotStatus(unsigned int reader_index,unsigned char buffer[])241 RESPONSECODE ACR38_CmdGetSlotStatus(unsigned int reader_index,
242 /*@out@*/ unsigned char buffer[])
243 {
244 unsigned char cmd[4];
245 status_t res;
246 unsigned int length;
247 RESPONSECODE return_value = IFD_SUCCESS;
248 unsigned char buffer_tmp[20];
249 _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
250
251 if (ccid_descriptor->bCurrentSlotIndex == 0)
252 {
253 // GET_ACR_STAT
254 cmd[0] = 0x01;
255 cmd[1] = 0x01;
256 cmd[2] = 0x00;
257 cmd[3] = 0x00;
258
259 res = WritePort(reader_index, sizeof(cmd), cmd);
260 CHECK_STATUS(res)
261
262 length = sizeof(buffer_tmp);
263 res = ReadPort(reader_index, &length, buffer_tmp);
264 CHECK_STATUS(res)
265
266 if (length < sizeof(buffer_tmp))
267 {
268 DEBUG_CRITICAL2("Not enough data received: %d bytes", length);
269 return IFD_COMMUNICATION_ERROR;
270 }
271
272 if (buffer_tmp[ACR38_STATUS_OFFSET] != 0)
273 {
274 acr38_error(buffer_tmp[ACR38_STATUS_OFFSET], __FILE__, __LINE__, __FUNCTION__);
275 return IFD_COMMUNICATION_ERROR;
276 }
277
278 /* simulate a CCID bStatus */
279 switch (buffer_tmp[19])
280 {
281 case 3:
282 buffer[7] = CCID_ICC_PRESENT_ACTIVE;
283 break;
284
285 case 1:
286 buffer[7] = CCID_ICC_PRESENT_INACTIVE;
287 break;
288
289 case 0:
290 buffer[7] = CCID_ICC_ABSENT;
291 break;
292
293 default:
294 return_value = IFD_COMMUNICATION_ERROR;
295 break;
296 }
297 }
298 else
299 {
300 // SAM card is always present
301 buffer[7] = CCID_ICC_PRESENT_ACTIVE;
302 }
303
304 return return_value;
305 }
306
ACR38_CmdXfrBlock(unsigned int reader_index,unsigned int tx_length,unsigned char tx_buffer[],unsigned int * rx_length,unsigned char rx_buffer[],int protocol)307 RESPONSECODE ACR38_CmdXfrBlock(unsigned int reader_index, unsigned int tx_length,
308 unsigned char tx_buffer[], unsigned int *rx_length,
309 unsigned char rx_buffer[], int protocol)
310 {
311 RESPONSECODE return_value = IFD_SUCCESS;
312 _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
313 int old_read_timeout;
314
315 // Use infinite timeout in T=0, short APDU and extended APDU
316 old_read_timeout = ccid_descriptor->readTimeout;
317
318 /* APDU or TPDU? */
319 switch (ccid_descriptor->dwFeatures & CCID_CLASS_EXCHANGE_MASK)
320 {
321 case CCID_CLASS_TPDU:
322 if (protocol == T_0)
323 {
324 ccid_descriptor->readTimeout = 0; // Infinite
325 return_value = ACR38_CmdXfrBlockTPDU_T0(reader_index,
326 tx_length, tx_buffer, rx_length, rx_buffer);
327 }
328 else if (protocol == T_1)
329 {
330 return_value = ACR38_CmdXfrBlockTPDU_T1(reader_index, tx_length,
331 tx_buffer, rx_length, rx_buffer);
332 }
333 else
334 return_value = IFD_PROTOCOL_NOT_SUPPORTED;
335 break;
336
337 default:
338 return_value = IFD_COMMUNICATION_ERROR;
339 break;
340 }
341
342 ccid_descriptor->readTimeout = old_read_timeout;
343 return return_value;
344 }
345
ACR38_TransmitT0(unsigned int reader_index,unsigned int tx_length,const unsigned char tx_buffer[],unsigned short rx_length,unsigned char bBWI)346 RESPONSECODE ACR38_TransmitT0(unsigned int reader_index, unsigned int tx_length,
347 const unsigned char tx_buffer[], unsigned short rx_length, unsigned char bBWI)
348 {
349 unsigned char cmd[ACR38_HEADER_SIZE + tx_length]; /* Header + APDU buffer */
350 status_t ret;
351 _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
352
353 // EXCHANGE_TPDU_T0 or EXCHANGE_SAM_TPDU_T0
354 cmd[0] = 0x01;
355 cmd[1] = ccid_descriptor->bCurrentSlotIndex == 0 ? 0xA0 : 0xB0;
356 cmd[2] = (tx_length >> 8) & 0xFF;
357 cmd[3] = tx_length & 0xFF;
358 memcpy(cmd + ACR38_HEADER_SIZE, tx_buffer, tx_length);
359
360 ret = WritePort(reader_index, ACR38_HEADER_SIZE + tx_length, cmd);
361 CHECK_STATUS(ret)
362
363 return IFD_SUCCESS;
364 }
365
ACR38_TransmitT1(unsigned int reader_index,unsigned int tx_length,const unsigned char tx_buffer[],unsigned short rx_length,unsigned char bBWI)366 RESPONSECODE ACR38_TransmitT1(unsigned int reader_index, unsigned int tx_length,
367 const unsigned char tx_buffer[], unsigned short rx_length, unsigned char bBWI)
368 {
369 unsigned char cmd[ACR38_HEADER_SIZE + tx_length]; /* Header + APDU buffer */
370 status_t ret;
371 _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
372
373 // EXCHANGE_TPDU_T1 or EXCHANGE_SAM_TPDU_T1
374 cmd[0] = 0x01;
375 cmd[1] = ccid_descriptor->bCurrentSlotIndex == 0 ? 0xA1 : 0xB1;
376 cmd[2] = (tx_length >> 8) & 0xFF;
377 cmd[3] = tx_length & 0xFF;
378 memcpy(cmd + ACR38_HEADER_SIZE, tx_buffer, tx_length);
379
380 ret = WritePort(reader_index, ACR38_HEADER_SIZE + tx_length, cmd);
381 CHECK_STATUS(ret)
382
383 return IFD_SUCCESS;
384 }
385
ACR38_TransmitPPS(unsigned int reader_index,unsigned int tx_length,const unsigned char tx_buffer[],unsigned short rx_length,unsigned char bBWI)386 RESPONSECODE ACR38_TransmitPPS(unsigned int reader_index, unsigned int tx_length,
387 const unsigned char tx_buffer[], unsigned short rx_length, unsigned char bBWI)
388 {
389 unsigned char cmd[ACR38_HEADER_SIZE + tx_length]; /* Header + APDU buffer */
390 status_t ret;
391 _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
392
393 // SET_CARD_PPS or SET_SAM_CARD_PPS
394 cmd[0] = 0x01;
395 cmd[1] = ccid_descriptor->bCurrentSlotIndex == 0 ? 0x0A : 0x0C;
396 cmd[2] = (tx_length >> 8) & 0xFF;
397 cmd[3] = tx_length & 0xFF;
398 memcpy(cmd + ACR38_HEADER_SIZE, tx_buffer, tx_length);
399
400 ret = WritePort(reader_index, ACR38_HEADER_SIZE + tx_length, cmd);
401 CHECK_STATUS(ret)
402
403 return IFD_SUCCESS;
404 }
405
ACR38_Receive(unsigned int reader_index,unsigned int * rx_length,unsigned char rx_buffer[],unsigned char * chain_parameter)406 RESPONSECODE ACR38_Receive(unsigned int reader_index,
407 /*@out@*/ unsigned int *rx_length,
408 /*@out@*/ unsigned char rx_buffer[], unsigned char *chain_parameter)
409 {
410 unsigned char cmd[ACR38_HEADER_SIZE + CMD_BUF_SIZE]; /* Header + APDU buffer */
411 unsigned int length;
412 RESPONSECODE return_value = IFD_SUCCESS;
413 status_t ret;
414
415 length = sizeof(cmd);
416 ret = ReadPort(reader_index, &length, cmd);
417 CHECK_STATUS(ret)
418
419 if (cmd[ACR38_STATUS_OFFSET] != 0)
420 {
421 acr38_error(cmd[ACR38_STATUS_OFFSET], __FILE__, __LINE__, __FUNCTION__);
422 return IFD_COMMUNICATION_ERROR;
423 }
424
425 length -= ACR38_HEADER_SIZE;
426 if (length <= *rx_length)
427 *rx_length = length;
428 else
429 {
430 DEBUG_CRITICAL2("overrun by %d bytes", length - *rx_length);
431 length = *rx_length;
432 return_value = IFD_ERROR_INSUFFICIENT_BUFFER;
433 }
434
435 memcpy(rx_buffer, cmd + ACR38_HEADER_SIZE, length);
436
437 return return_value;
438 }
439
ACR38_SetParameters(unsigned int reader_index,char protocol,unsigned int length,unsigned char buffer[])440 RESPONSECODE ACR38_SetParameters(unsigned int reader_index, char protocol,
441 unsigned int length, unsigned char buffer[])
442 {
443 unsigned char cmd[8];
444 int i;
445 _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
446 status_t res;
447
448 DEBUG_COMM2("length: %d bytes", length);
449
450 // SET_READER_PPS or SET_SAM_READER_PPS
451 cmd[0] = 0x01;
452 cmd[1] = ccid_descriptor->bCurrentSlotIndex == 0 ? 0x0B : 0x0D;
453 cmd[2] = 0x00;
454 cmd[3] = 0x04;
455 cmd[4] = 0xFF; // PPSS
456 cmd[5] = protocol == 0 ? 0x10 : 0x11; // PPS0: 0x10 (T=0), 0x11 (T=1)
457 cmd[6] = buffer[0]; // PPS1: TA(1)
458 cmd[7] = 0; // PCK: XOR checksum
459 for (i = 4; i < 7; i++)
460 cmd[7] ^= cmd[i];
461
462 res = WritePort(reader_index, sizeof(cmd), cmd);
463 CHECK_STATUS(res)
464
465 length = sizeof(cmd);
466 res = ReadPort(reader_index, &length, cmd);
467 CHECK_STATUS(res)
468
469 if (cmd[ACR38_STATUS_OFFSET] != 0)
470 {
471 acr38_error(cmd[ACR38_STATUS_OFFSET], __FILE__, __LINE__, __FUNCTION__);
472 return IFD_COMMUNICATION_ERROR;
473 }
474
475 return IFD_SUCCESS;
476 }
477
ACR38_SetCardVoltage(unsigned int reader_index,unsigned char TxBuffer[],unsigned int TxLength,unsigned char RxBuffer[],unsigned int * RxLength)478 RESPONSECODE ACR38_SetCardVoltage(unsigned int reader_index,
479 unsigned char TxBuffer[], unsigned int TxLength,
480 unsigned char RxBuffer[], unsigned int *RxLength)
481 {
482 RESPONSECODE return_value = IFD_SUCCESS;
483 BYTE cardVoltage;
484 _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
485
486 if ((TxBuffer != NULL) && (TxLength >= 1))
487 {
488 cardVoltage = TxBuffer[0];
489 if (cardVoltage <= 3)
490 ccid_descriptor->cardVoltage = cardVoltage;
491 else
492 {
493 DEBUG_CRITICAL2("Card voltage %d is not supported", cardVoltage);
494 ccid_descriptor->cardVoltage = 0;
495 return_value = IFD_COMMUNICATION_ERROR;
496 }
497 }
498
499 if (RxLength != NULL)
500 *RxLength = 0;
501
502 DEBUG_INFO2("cardVoltage: %d", ccid_descriptor->cardVoltage);
503 return return_value;
504 }
505
ACR38_SetCardType(unsigned int reader_index,unsigned char TxBuffer[],unsigned int TxLength,unsigned char RxBuffer[],unsigned int * RxLength)506 RESPONSECODE ACR38_SetCardType(unsigned int reader_index,
507 unsigned char TxBuffer[], unsigned int TxLength,
508 unsigned char RxBuffer[], unsigned int *RxLength)
509 {
510 RESPONSECODE return_value = IFD_SUCCESS;
511 DWORD cardType;
512 _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
513
514 if ((TxBuffer != NULL) && (TxLength >= sizeof(cardType)))
515 {
516 cardType = *((PDWORD) TxBuffer);
517 switch (cardType)
518 {
519 case CARD_TYPE_MCU_AUTO:
520 ccid_descriptor->cardType = ACR38_CARD_TYPE_MCU_AUTO;
521 break;
522
523 case CARD_TYPE_I2C_1K:
524 case CARD_TYPE_I2C_2K:
525 case CARD_TYPE_I2C_4K:
526 case CARD_TYPE_I2C_8K:
527 case CARD_TYPE_I2C_16K:
528 ccid_descriptor->cardType = ACR38_CARD_TYPE_I2C_1K_16K;
529 break;
530
531 case CARD_TYPE_I2C_32K:
532 case CARD_TYPE_I2C_64K:
533 case CARD_TYPE_I2C_128K:
534 case CARD_TYPE_I2C_256K:
535 case CARD_TYPE_I2C_512K:
536 case CARD_TYPE_I2C_1024K:
537 ccid_descriptor->cardType = ACR38_CARD_TYPE_I2C_32K_1024K;
538 break;
539
540 case CARD_TYPE_AT88SC153:
541 ccid_descriptor->cardType = ACR38_CARD_TYPE_AT88SC153;
542 break;
543
544 case CARD_TYPE_AT88SC1608:
545 ccid_descriptor->cardType = ACR38_CARD_TYPE_AT88SC1608;
546 break;
547
548 case CARD_TYPE_SLE4418:
549 case CARD_TYPE_SLE4428:
550 ccid_descriptor->cardType = ACR38_CARD_TYPE_SLE4418_4428;
551 break;
552
553 case CARD_TYPE_SLE4432:
554 case CARD_TYPE_SLE4442:
555 ccid_descriptor->cardType = ACR38_CARD_TYPE_SLE4432_4442;
556 break;
557
558 case CARD_TYPE_SLE4406:
559 case CARD_TYPE_SLE4436:
560 case CARD_TYPE_SLE5536:
561 ccid_descriptor->cardType = ACR38_CARD_TYPE_SLE4406_4436_5536;
562 break;
563
564 case CARD_TYPE_MCU_T0:
565 ccid_descriptor->cardType = ACR38_CARD_TYPE_MCU_T0;
566 break;
567
568 case CARD_TYPE_MCU_T1:
569 ccid_descriptor->cardType = ACR38_CARD_TYPE_MCU_T1;
570 break;
571
572 default:
573 DEBUG_CRITICAL2("Card type " DWORD_D " is not supported", cardType);
574 ccid_descriptor->cardType = ACR38_CARD_TYPE_MCU_AUTO;
575 return_value = IFD_COMMUNICATION_ERROR;
576 break;
577 }
578 }
579
580 if (RxLength != NULL)
581 *RxLength = 0;
582
583 DEBUG_INFO2("cardType: %d", ccid_descriptor->cardType);
584 return return_value;
585 }
586
ACR38_GetFirmwareVersion(unsigned int reader_index,char firmwareVersion[])587 RESPONSECODE ACR38_GetFirmwareVersion(unsigned int reader_index,
588 char firmwareVersion[])
589 {
590 unsigned char cmd[4];
591 status_t res;
592 unsigned int length;
593 RESPONSECODE return_value = IFD_SUCCESS;
594 unsigned char buffer_tmp[20];
595
596 // GET_ACR_STAT
597 cmd[0] = 0x01;
598 cmd[1] = 0x01;
599 cmd[2] = 0x00;
600 cmd[3] = 0x00;
601
602 res = WritePort(reader_index, sizeof(cmd), cmd);
603 CHECK_STATUS(res)
604
605 length = sizeof(buffer_tmp);
606 res = ReadPort(reader_index, &length, buffer_tmp);
607 CHECK_STATUS(res)
608
609 if (length < sizeof(buffer_tmp))
610 {
611 DEBUG_CRITICAL2("Not enough data received: %d bytes", length);
612 return IFD_COMMUNICATION_ERROR;
613 }
614
615 if (buffer_tmp[ACR38_STATUS_OFFSET] != 0)
616 {
617 acr38_error(buffer_tmp[ACR38_STATUS_OFFSET], __FILE__, __LINE__, __FUNCTION__);
618 return IFD_COMMUNICATION_ERROR;
619 }
620
621 memcpy(firmwareVersion, buffer_tmp + ACR38_HEADER_SIZE, 10);
622 return return_value;
623 }
624
ACR38_CmdXfrBlockTPDU_T0(unsigned int reader_index,unsigned int tx_length,unsigned char tx_buffer[],unsigned int * rx_length,unsigned char rx_buffer[])625 static RESPONSECODE ACR38_CmdXfrBlockTPDU_T0(unsigned int reader_index,
626 unsigned int tx_length, unsigned char tx_buffer[], unsigned int *rx_length,
627 unsigned char rx_buffer[])
628 {
629 RESPONSECODE return_value = IFD_SUCCESS;
630
631 DEBUG_COMM2("T=0: %d bytes", tx_length);
632
633 return_value = ACR38_TransmitT0(reader_index, tx_length, tx_buffer, 0, 0);
634 if (return_value != IFD_SUCCESS)
635 return return_value;
636
637 return ACR38_Receive(reader_index, rx_length, rx_buffer, NULL);
638 }
639
ACR38_CmdXfrBlockTPDU_T1(unsigned int reader_index,unsigned int tx_length,unsigned char tx_buffer[],unsigned int * rx_length,unsigned char rx_buffer[])640 static RESPONSECODE ACR38_CmdXfrBlockTPDU_T1(unsigned int reader_index,
641 unsigned int tx_length, unsigned char tx_buffer[], unsigned int *rx_length,
642 unsigned char rx_buffer[])
643 {
644 RESPONSECODE return_value = IFD_SUCCESS;
645 int ret;
646
647 DEBUG_COMM3("T=1: %d and %d bytes", tx_length, *rx_length);
648
649 ret = t1_transceive(&((get_ccid_slot(reader_index)) -> t1), 0,
650 tx_buffer, tx_length, rx_buffer, *rx_length);
651
652 if (ret < 0)
653 return_value = IFD_COMMUNICATION_ERROR;
654 else
655 *rx_length = ret;
656
657 return return_value;
658 }
659
ACR38_CmdSelectCardType(unsigned int reader_index,unsigned char card_type)660 static RESPONSECODE ACR38_CmdSelectCardType(unsigned int reader_index, unsigned char card_type)
661 {
662 unsigned char cmd[5];
663 status_t res;
664 unsigned int length;
665 RESPONSECODE return_value = IFD_SUCCESS;
666
667 // SELECT_CARD_TYPE
668 cmd[0] = 0x01;
669 cmd[1] = 0x02;
670 cmd[2] = 0x00;
671 cmd[3] = 0x01;
672 cmd[4] = card_type;
673
674 res = WritePort(reader_index, sizeof(cmd), cmd);
675 CHECK_STATUS(res)
676
677 length = sizeof(cmd);
678 res = ReadPort(reader_index, &length, cmd);
679 CHECK_STATUS(res)
680
681 if (cmd[ACR38_STATUS_OFFSET] != 0)
682 {
683 acr38_error(cmd[ACR38_STATUS_OFFSET], __FILE__, __LINE__, __FUNCTION__);
684 return_value = IFD_COMMUNICATION_ERROR;
685 }
686
687 return return_value;
688 }
689
ACR38_CmdSetOption(unsigned int reader_index,unsigned char option)690 static RESPONSECODE ACR38_CmdSetOption(unsigned int reader_index, unsigned char option)
691 {
692 unsigned char cmd[5];
693 status_t res;
694 unsigned int length;
695 RESPONSECODE return_value = IFD_SUCCESS;
696
697 // SET_OPTION
698 cmd[0] = 0x01;
699 cmd[1] = 0x07;
700 cmd[2] = 0x00;
701 cmd[3] = 0x01;
702 cmd[4] = option;
703
704 res = WritePort(reader_index, sizeof(cmd), cmd);
705 CHECK_STATUS(res)
706
707 length = sizeof(cmd);
708 res = ReadPort(reader_index, &length, cmd);
709 CHECK_STATUS(res)
710
711 if (cmd[ACR38_STATUS_OFFSET] != 0)
712 {
713 acr38_error(cmd[ACR38_STATUS_OFFSET], __FILE__, __LINE__, __FUNCTION__);
714 return_value = IFD_COMMUNICATION_ERROR;
715 }
716
717 return return_value;
718 }
719