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