source: trunk/csctapi/cardterminal.c@ 1253

Last change on this file since 1253 was 1253, checked in by dingo35, 11 years ago

Move Reset to ifd_phoenix.c and cleanup lot of overhead

File size: 17.8 KB
Line 
1/*
2 cardterminal.c
3 Card Terminal handling and CT-BCS functions
4
5 This file is part of the Unix driver for Towitoko smartcard readers
6 Copyright (C) 2000 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 "defines.h"
26#include "cardterminal.h"
27#include "atr.h"
28#include <stdlib.h>
29#include <string.h>
30
31/*
32 * Not exported constants definition
33 */
34
35#define CARDTERMINAL_RESETCT_BUFFER_SIZE 35
36#define CARDTERMINAL_REQUESTICC_BUFFER_SIZE 35
37#define CARDTERMINAL_GETSTATUS_BUFFER_SIZE 19
38#define CARDTERMINAL_EJECTICC_BUFFER_SIZE 2
39#define CARDTERMINAL_MANUFACTURER "DETWK"
40
41/*
42 * Not exported functions declaration
43 */
44
45static char CardTerminal_ResetCT (CardTerminal * ct, APDU_Cmd * cmd, APDU_Rsp ** rsp);
46
47static char CardTerminal_RequestICC (CardTerminal * ct, APDU_Cmd * cmd, APDU_Rsp ** rsp);
48
49static char CardTerminal_GetStatus (CardTerminal * ct, APDU_Cmd * cmd, APDU_Rsp ** rsp);
50
51static char CardTerminal_SetParity (APDU_Cmd * cmd, APDU_Rsp ** rsp);
52
53static char CardTerminal_EjectICC (CardTerminal * ct, APDU_Cmd * cmd, APDU_Rsp ** rsp);
54
55static void CardTerminal_Clear (CardTerminal * ct);
56
57/*
58 * Exported functions definition
59 */
60
61CardTerminal * CardTerminal_New (void)
62{
63 CardTerminal *ct;
64
65 ct = (CardTerminal *) malloc (sizeof (CardTerminal));
66
67 if (ct != NULL)
68 CardTerminal_Clear (ct);
69
70 return ct;
71}
72
73char CardTerminal_Init (CardTerminal * ct)
74{
75 char ret;
76 int i;
77
78 /* Initialise serial port */
79 if (ICC_Async_Device_Init ())
80 return ERR_TRANS;
81
82 /* Cearte all reader slots */
83 ct->num_slots = 0;
84 do
85 {
86 i = ct->num_slots++;
87
88 /* Create one slot */
89 ct->slots[i] = CT_Slot_New ();
90
91 if (ct->slots[i] == NULL)
92 {
93 ret = ERR_MEMORY;
94 break;
95 }
96
97 /* Initialise slot */
98 ret = CT_Slot_Init (ct->slots[i], i);
99
100 if (ret != OK)
101 break;
102 }
103 while (!CT_Slot_IsLast(ct->slots[i]));
104
105 /* On error restore initial state */
106 if (ret != OK)
107 {
108 while (ct->num_slots > 0)
109 {
110 if (ct->slots[i] != NULL)
111 {
112 CT_Slot_Delete (ct->slots[i]);
113 ct->slots[i] = NULL;
114 }
115
116 ct->num_slots --;
117 i--;
118 }
119
120 IO_Serial_Close ();
121 }
122#ifdef HAVE_PTHREAD_H
123 else
124 {
125 pthread_mutex_init(&(ct->mutex), NULL);
126 }
127#endif
128 return ret;
129}
130
131char CardTerminal_Command (CardTerminal * ct, APDU_Cmd * cmd, APDU_Rsp ** rsp)
132{
133 BYTE buffer[CTBCS_MIN_RESPONSE_SIZE], cla, ins;
134 long length;
135 char ret;
136
137 /* Get class of command */
138 cla = APDU_Cmd_Cla (cmd);
139
140 if (cla != CTBCS_CLA)
141 {
142 length = CTBCS_MIN_RESPONSE_SIZE;
143 buffer[0] = CTBCS_SW1_WRONG_CLA;
144 buffer[1] = CTBCS_SW2_WRONG_CLA;
145
146 (*rsp) = APDU_Rsp_New (buffer, length);
147 ret = OK;
148 }
149 else
150 {
151 /* Get instruction */
152 ins = APDU_Cmd_Ins (cmd);
153
154 /* Reset CT */
155 if (ins == CTBCS_INS_RESET)
156 ret = CardTerminal_ResetCT (ct, cmd, rsp);
157 else if (ins == CTBCS_INS_REQUEST) /* Request ICC */
158 ret = CardTerminal_RequestICC (ct, cmd, rsp);
159 else if (ins == CTBCS_INS_STATUS) /* Get Status */
160 ret = CardTerminal_GetStatus (ct, cmd, rsp);
161 else if (ins == CTBCS_INS_PARITY) /* Get Status */
162 ret = CardTerminal_SetParity (cmd, rsp);
163 else if (ins == CTBCS_INS_EJECT) /* Eject ICC */
164 ret = CardTerminal_EjectICC (ct, cmd, rsp);
165 else /* Wrong instruction */
166 {
167 length = CTBCS_MIN_RESPONSE_SIZE;
168 buffer[0] = CTBCS_SW1_WRONG_INS;
169 buffer[1] = CTBCS_SW2_WRONG_INS;
170
171 (*rsp) = APDU_Rsp_New (buffer, length);
172 ret = OK;
173 }
174 }
175
176 return ret;
177}
178
179char CardTerminal_Close (CardTerminal * ct)
180{
181 char ret, aux;
182 unsigned int i;
183
184 ret = OK;
185
186 for (i = 0; i < ct->num_slots; i++)
187 {
188 if (ct->slots[i] != NULL)
189 {
190 aux = CT_Slot_Close (ct->slots[i]);
191 if (aux != OK)
192 ret = aux;
193
194 CT_Slot_Delete (ct->slots[i]);
195 }
196 }
197
198 if (!IO_Serial_Close ())
199 ret = ERR_TRANS;
200
201 CardTerminal_Clear (ct);
202
203#ifdef HAVE_PTHREAD_H
204 pthread_mutex_destroy(&(ct->mutex));
205#endif
206 return ret;
207}
208
209void CardTerminal_Delete (CardTerminal * ct)
210{
211 free (ct);
212}
213
214CT_Slot * CardTerminal_GetSlot (CardTerminal * ct, unsigned int number)
215{
216 if (number < (ct->num_slots))
217 return ct->slots[number];
218
219 return NULL;
220}
221
222#ifdef HAVE_PTHREAD_H
223pthread_mutex_t * CardTerminal_GetMutex (CardTerminal * ct)
224{
225 return &(ct->mutex);
226}
227#endif
228
229/*
230 * Not exported functions definition
231 */
232
233static char CardTerminal_ResetCT (CardTerminal * ct, APDU_Cmd * cmd, APDU_Rsp ** rsp)
234{
235 BYTE buffer[CARDTERMINAL_RESETCT_BUFFER_SIZE], p1, p2;
236 bool card, change;
237 unsigned sn, length;
238 void *atr;
239 char ret = OK;
240
241 /* Get functional unit */
242 p1 = APDU_Cmd_P1 (cmd);
243
244 /* Funcional unit is the card-terminal */
245 if (p1 == CTBCS_P1_CT_KERNEL)
246 {
247 /* Get command cualifier */
248 p2 = APDU_Cmd_P2 (cmd);
249
250 /* Wrong command cualifier */
251 if (p2 != CTBCS_P2_RESET_NO_RESP && p2 != CTBCS_P2_RESET_GET_ATR && p2 != CTBCS_P2_RESET_GET_HIST)
252 {
253 buffer[0] = CTBCS_SW1_WRONG_PARAM;
254 buffer[1] = CTBCS_SW2_WRONG_PARAM;
255
256 (*rsp) = APDU_Rsp_New (buffer, 2);
257 return OK;
258 }
259
260 /* Close slots */
261 for (sn = 0; sn < ct->num_slots; sn++)
262 {
263 /* Close this slot */
264 ret = CT_Slot_Close (ct->slots[sn]);
265
266 if (ret != OK)
267 {
268 buffer[0] = CTBCS_SW1_RESET_ERROR;
269 buffer[1] = CTBCS_SW2_RESET_ERROR;
270
271 (*rsp) = APDU_Rsp_New (buffer, 2);
272 return ret;
273 }
274
275 /* Initialise this slot */
276 ret = CT_Slot_Init (ct->slots[sn],sn);
277
278 if (ret != OK)
279 {
280 buffer[0] = CTBCS_SW1_RESET_ERROR;
281 buffer[1] = CTBCS_SW2_RESET_ERROR;
282
283 (*rsp) = APDU_Rsp_New (buffer, 2);
284 return ret;
285 }
286 }
287
288 length = 2;
289 buffer[0] = CTBCS_SW1_RESET_CT_OK;
290 buffer[1] = CTBCS_SW2_RESET_CT_OK;
291 }
292 else if ((p1 == CTBCS_P1_INTERFACE1) || (p1 == CTBCS_P1_INTERFACE2)) /* Funtional unit is an ICC */
293 {
294 /* Get slot number */
295 sn = (p1 == CTBCS_P1_INTERFACE1) ? 0 : 1;
296
297 if (!(sn < ct->num_slots))
298 {
299 buffer[0] = CTBCS_SW1_WRONG_PARAM;
300 buffer[1] = CTBCS_SW2_WRONG_PARAM;
301
302 (*rsp) = APDU_Rsp_New (buffer, 2);
303 return ERR_INVALID;
304 }
305
306 /* Release the slot */
307 ret = CT_Slot_Release (ct->slots[sn]);
308
309 if (ret != OK)
310 {
311 buffer[0] = CTBCS_SW1_RESET_ERROR;
312 buffer[1] = CTBCS_SW2_RESET_ERROR;
313
314 (*rsp) = APDU_Rsp_New (buffer, 2);
315 return ret;
316 }
317
318 /* Check for card */
319 ret = CT_Slot_Check (ct->slots[sn], 0, &card, &change);
320
321 if (ret != OK)
322 {
323 buffer[0] = CTBCS_SW1_RESET_ERROR;
324 buffer[1] = CTBCS_SW2_RESET_ERROR;
325
326 (*rsp) = APDU_Rsp_New (buffer, 2);
327 return ret;
328 }
329
330 /* No card present */
331 if (!card)
332 {
333 buffer[0] = CTBCS_SW1_RESET_ERROR;
334 buffer[1] = CTBCS_SW2_RESET_ERROR;;
335
336 (*rsp) = APDU_Rsp_New (buffer, 2);
337 return OK;
338 }
339
340 /* Probe card type */
341 if (APDU_Cmd_Lc (cmd) > 1)
342 ret = CT_Slot_Probe (ct->slots[sn], APDU_Cmd_Data(cmd), APDU_Cmd_Lc(cmd));
343 else
344 ret = CT_Slot_Probe (ct->slots[sn], NULL, 0);
345
346 if (ret != OK || (CT_Slot_GetICCType (ct->slots[sn]) == CT_SLOT_NULL))
347 {
348 buffer[0] = CTBCS_SW1_RESET_ERROR;
349 buffer[1] = CTBCS_SW2_RESET_ERROR;
350
351 (*rsp) = APDU_Rsp_New (buffer, 2);
352 return ret;
353 }
354
355 /* Get command cualifier */
356 p2 = APDU_Cmd_P2 (cmd);
357
358 /* Do not return data */
359 if (p2 == CTBCS_P2_RESET_NO_RESP)
360 {
361 if (CT_Slot_GetICCType (ct->slots[sn]) == CT_SLOT_ICC_ASYNC)
362 {
363 buffer[0] = CTBCS_SW1_RESET_ASYNC_OK;
364 buffer[1] = CTBCS_SW2_RESET_ASYNC_OK;
365 length = 2;
366 }
367 else
368 {
369 buffer[0] = CTBCS_SW1_RESET_SYNC_OK;
370 buffer[1] = CTBCS_SW2_RESET_SYNC_OK;
371 length = 2;
372 }
373 }
374 else if (p2 == CTBCS_P2_RESET_GET_ATR) /* Return complete ATR of ICC */
375 {
376 atr = CT_Slot_GetAtr (ct->slots[sn]);
377
378 if (CT_Slot_GetICCType (ct->slots[sn]) == CT_SLOT_ICC_ASYNC)
379 {
380 if (atr != NULL)
381 ATR_GetRaw ((ATR *) atr, buffer, &length);
382 else
383 length = 0;
384
385 buffer[length] = CTBCS_SW1_RESET_ASYNC_OK;
386 buffer[length + 1] = CTBCS_SW2_RESET_ASYNC_OK;
387// buffer[length + 1] = ct->slots[sn]->protocol_type;
388 length += 2;
389 }
390 }
391 else if (p2 == CTBCS_P2_RESET_GET_HIST) /* Return historical bytes of ATR */
392 {
393 atr = CT_Slot_GetAtr (ct->slots[sn]);
394
395 if (CT_Slot_GetICCType (ct->slots[sn]) == CT_SLOT_ICC_ASYNC)
396 {
397 if (atr != NULL)
398 ATR_GetHistoricalBytes ((ATR *) atr, buffer, &length);
399 else
400 length = 0;
401
402 buffer[length] = CTBCS_SW1_RESET_ASYNC_OK;
403 buffer[length + 1] = CTBCS_SW2_RESET_ASYNC_OK;
404 length += 2;
405 }
406 }
407 else /* Wrong command cualifier */
408 {
409 length = 2;
410 buffer[0] = CTBCS_SW1_WRONG_PARAM;
411 buffer[1] = CTBCS_SW2_WRONG_PARAM;
412 ret = OK;
413 }
414 }
415 else /* Wrong functional unit */
416 {
417 length = 2;
418 buffer[0] = CTBCS_SW1_WRONG_PARAM;
419 buffer[1] = CTBCS_SW2_WRONG_PARAM;
420 ret = OK;
421 }
422
423 (*rsp) = APDU_Rsp_New (buffer, length);
424 return ret;
425}
426
427static char CardTerminal_RequestICC (CardTerminal * ct, APDU_Cmd * cmd, APDU_Rsp ** rsp)
428{
429 BYTE buffer[CARDTERMINAL_REQUESTICC_BUFFER_SIZE], p1, p2;
430 unsigned timeout, sn, length;
431 bool card, change;
432 void * atr;
433 char ret;
434
435 /* Get functional unit */
436 p1 = APDU_Cmd_P1 (cmd);
437
438 if ((p1 == CTBCS_P1_INTERFACE1) || (p1 == CTBCS_P1_INTERFACE2))
439 {
440 /* Get the slot number */
441 sn = (p1 == CTBCS_P1_INTERFACE1) ? 0 : 1;
442
443 if (CT_Slot_GetICCType (ct->slots[sn]) != CT_SLOT_NULL)
444 {
445 buffer[0] = CTBCS_SW1_REQUEST_CARD_PRESENT;
446 buffer[1] = CTBCS_SW2_REQUEST_CARD_PRESENT;
447
448 (*rsp) = APDU_Rsp_New (buffer, 2);
449 return OK;
450 }
451
452 /* Get the card insertion timeout */
453 if (APDU_Cmd_Lc (cmd) == 1)
454 timeout = (APDU_Cmd_Data (cmd)[0]);
455 else
456 timeout = 0;
457
458 /* Check for card */
459 ret = CT_Slot_Check (ct->slots[sn], timeout, &card, &change);
460
461 if (ret != OK)
462 {
463 buffer[0] = CTBCS_SW1_REQUEST_ERROR;
464 buffer[1] = CTBCS_SW2_REQUEST_ERROR;
465
466 (*rsp) = APDU_Rsp_New (buffer, 2);
467 return ret;
468 }
469
470 /* No card present */
471 if (!card)
472 {
473 buffer[0] = CTBCS_SW1_REQUEST_NO_CARD;
474 buffer[1] = CTBCS_SW2_REQUEST_NO_CARD;
475
476 (*rsp) = APDU_Rsp_New (buffer, 2);
477 return OK;
478 }
479
480 /* Probe card type */
481 if (APDU_Cmd_Lc (cmd) > 1)
482 ret = CT_Slot_Probe (ct->slots[sn], APDU_Cmd_Data(cmd), APDU_Cmd_Lc(cmd));
483 else
484 ret = CT_Slot_Probe (ct->slots[sn], NULL, 0);
485
486 if (ret != OK || (CT_Slot_GetICCType (ct->slots[sn]) == CT_SLOT_NULL))
487 {
488 buffer[0] = CTBCS_SW1_REQUEST_ERROR;
489 buffer[1] = CTBCS_SW2_REQUEST_ERROR;
490
491 (*rsp) = APDU_Rsp_New (buffer, 2);
492 return ret;
493 }
494
495 /* Get command cualifier */
496 p2 = APDU_Cmd_P2 (cmd);
497
498 /* Do not return data */
499 if (p2 == CTBCS_P2_REQUEST_NO_RESP)
500 {
501 if (CT_Slot_GetICCType (ct->slots[sn]) == CT_SLOT_ICC_ASYNC)
502 {
503 buffer[0] = CTBCS_SW1_REQUEST_ASYNC_OK;
504 buffer[1] = CTBCS_SW2_REQUEST_ASYNC_OK;
505 length = 2;
506 }
507 else
508 {
509 buffer[0] = CTBCS_SW1_REQUEST_SYNC_OK;
510 buffer[1] = CTBCS_SW2_REQUEST_SYNC_OK;
511 length = 2;
512 }
513 }
514 else if (p2 == CTBCS_P2_REQUEST_GET_ATR) /* Return whole atr */
515 {
516 atr = CT_Slot_GetAtr (ct->slots[sn]);
517
518 if (CT_Slot_GetICCType (ct->slots[sn]) == CT_SLOT_ICC_ASYNC)
519 {
520 if (atr != NULL)
521 ATR_GetRaw ((ATR *) atr, buffer, &length);
522 else
523 length = 0;
524
525 buffer[length] = CTBCS_SW1_REQUEST_ASYNC_OK;
526 buffer[length + 1] = CTBCS_SW2_REQUEST_ASYNC_OK;
527 length += 2;
528 }
529 }
530 else if (p2 == CTBCS_P2_REQUEST_GET_HIST) /* Return historical bytes */
531 {
532 atr = CT_Slot_GetAtr (ct->slots[sn]);
533
534 if (CT_Slot_GetICCType (ct->slots[sn]) == CT_SLOT_ICC_ASYNC)
535 {
536 if (atr != NULL)
537 ATR_GetHistoricalBytes ((ATR *) atr, buffer, &length);
538 else
539 length = 0;
540
541 buffer[length] = CTBCS_SW1_REQUEST_ASYNC_OK;
542 buffer[length + 1] = CTBCS_SW2_REQUEST_ASYNC_OK;
543 length += 2;
544 }
545 }
546 else /* Wrong command cualifier */
547 {
548 length = 2;
549 buffer[0] = CTBCS_SW1_WRONG_PARAM;
550 buffer[1] = CTBCS_SW2_WRONG_PARAM;
551 ret = OK;
552 }
553 }
554 else /* Wrong functional unit */
555 {
556 length = 2;
557 buffer[0] = CTBCS_SW1_WRONG_PARAM;
558 buffer[1] = CTBCS_SW2_WRONG_PARAM;
559 ret = OK;
560 }
561
562 (*rsp) = APDU_Rsp_New (buffer, (long)length);
563 return ret;
564}
565
566static char CardTerminal_GetStatus (CardTerminal * ct, APDU_Cmd * cmd, APDU_Rsp ** rsp)
567{
568 BYTE buffer[CARDTERMINAL_GETSTATUS_BUFFER_SIZE], p1, p2;
569 bool card, change;
570 unsigned int i;
571 unsigned length;
572 char ret = OK;
573
574 /* Get functional unit */
575 p1 = APDU_Cmd_P1 (cmd);
576
577 /* Wrong functional unit */
578 if (p1 != CTBCS_P1_CT_KERNEL)
579 {
580 length = 2;
581 buffer[0] = CTBCS_SW1_WRONG_PARAM;
582 buffer[1] = CTBCS_SW2_WRONG_PARAM;
583 ret = OK;
584 }
585
586 /* Get command cualifier */
587 p2 = APDU_Cmd_P2 (cmd);
588
589 if (p2 == CTBCS_P2_STATUS_MANUFACTURER)
590 {
591 length = 17;
592
593 /* CT Manufacturer */
594 memcpy(buffer,CARDTERMINAL_MANUFACTURER,5);
595
596 /* CT type */
597 if (ct->slots[0] != NULL)
598 CT_Slot_GetType(ct->slots[0], buffer + 5,5);
599
600 /* CT version */
601 memcpy(buffer+10,VERSION,5);
602
603 buffer[15] = CTBCS_SW1_OK;
604 buffer[16] = CTBCS_SW2_OK;
605 ret = OK;
606 }
607 else if (p2 == CTBCS_P2_STATUS_ICC)
608 {
609 for (i = 0; i < ct->num_slots; i++)
610 {
611 ret = CT_Slot_Check (ct->slots[i], 0, &card, &change);
612
613 if (ret != OK)
614 {
615 /* There are no status bytes defined to be returned on error */
616 (*rsp) = NULL;
617 return ret;
618 }
619
620 /* Resynchronise the driver status with the actual status of slot */
621 if ((CT_Slot_GetICCType (ct->slots[i]) != CT_SLOT_NULL) && (!card || change))
622 {
623 ret = CT_Slot_Release (ct->slots[i]);
624
625 if (ret != OK)
626 {
627 (*rsp) = NULL;
628 return ret;
629 }
630 }
631
632 buffer[i] = card? CTBCS_DATA_STATUS_CARD_CONNECT: CTBCS_DATA_STATUS_NOCARD;
633 }
634
635 length = i+2;
636 buffer[i] = CTBCS_SW1_OK;
637 buffer[i+1] = CTBCS_SW2_OK;
638 }
639 else if (p2 == CTBCS_P2_STATUS_PROTOCOL)
640 {
641 for (i = 0; i < ct->num_slots; i++)
642 {
643 if(ct->slots[i]->protocol_type == CT_SLOT_PROTOCOL_T0)
644 buffer[i] = 0x00;
645 else if(ct->slots[i]->protocol_type == CT_SLOT_PROTOCOL_T1)
646 buffer[i] = 0x01;
647 else if(ct->slots[i]->protocol_type == CT_SLOT_PROTOCOL_T14)
648 buffer[i] = 0x0E;
649 else
650 buffer[i] = 0xFF;
651 }
652
653 length = i+2;
654 buffer[i] = CTBCS_SW1_OK;
655 buffer[i+1] = CTBCS_SW2_OK;
656 ret = OK;
657 }
658 else /* Wrong command cualifier */
659 {
660 length = 2;
661 buffer[0] = CTBCS_SW1_WRONG_PARAM;
662 buffer[1] = CTBCS_SW2_WRONG_PARAM;
663 ret = OK;
664 }
665
666 (*rsp) = APDU_Rsp_New (buffer, length);
667 return ret;
668}
669
670static char CardTerminal_SetParity (APDU_Cmd * cmd, APDU_Rsp ** rsp)
671{
672 BYTE buffer[2], p1, p2;
673 unsigned length;
674 char ret = OK;
675
676 /* Get functional unit */
677 p1 = APDU_Cmd_P1 (cmd);
678
679 /* Wrong functional unit */
680 if (p1 != CTBCS_P1_CT_KERNEL)
681 {
682 length = 2;
683 buffer[0] = CTBCS_SW1_WRONG_PARAM;
684 buffer[1] = CTBCS_SW2_WRONG_PARAM;
685 ret = OK;
686 }
687
688 /* Get command cualifier */
689 p2 = APDU_Cmd_P2 (cmd);
690
691 if (p2 == CTBCS_P2_PARITY_ODD)
692 {
693 length = 2;
694 IO_Serial_SetParity (PARITY_ODD);
695 buffer[0] = CTBCS_SW1_OK;
696 buffer[1] = CTBCS_SW2_OK;
697 ret = OK;
698 }
699 else if(p2 == CTBCS_P2_PARITY_EVEN)
700 {
701 length = 2;
702 IO_Serial_SetParity (PARITY_EVEN);
703 buffer[0] = CTBCS_SW1_OK;
704 buffer[1] = CTBCS_SW2_OK;
705 ret = OK;
706 }
707 else if (p2 == CTBCS_P2_PARITY_NONE)
708 {
709 length = 2;
710 IO_Serial_SetParity (PARITY_NONE);
711 buffer[0] = CTBCS_SW1_OK;
712 buffer[1] = CTBCS_SW2_OK;
713 ret = OK;
714 }
715 else /* Wrong command cualifier */
716 {
717 length = 2;
718 buffer[0] = CTBCS_SW1_WRONG_PARAM;
719 buffer[1] = CTBCS_SW2_WRONG_PARAM;
720 ret = OK;
721 }
722
723 (*rsp) = APDU_Rsp_New (buffer, length);
724 return ret;
725}
726
727static char CardTerminal_EjectICC (CardTerminal * ct, APDU_Cmd * cmd, APDU_Rsp ** rsp)
728{
729 BYTE buffer[CARDTERMINAL_EJECTICC_BUFFER_SIZE], p1, p2;
730 unsigned int sn, timeout;
731 unsigned length;
732 bool card, change;
733 char ret;
734
735 /* Get functional unit */
736 p1 = APDU_Cmd_P1 (cmd);
737
738 /* Wrong functional unit */
739 if ((p1 != CTBCS_P1_INTERFACE1) && (p1 != CTBCS_P1_INTERFACE2))
740 {
741 buffer[0] = CTBCS_SW1_WRONG_PARAM;
742 buffer[1] = CTBCS_SW2_WRONG_PARAM;
743
744 (*rsp) = APDU_Rsp_New (buffer, 2);
745 return OK;
746 }
747
748 /* Get the slot number */
749 sn = (p1 == CTBCS_P1_INTERFACE1) ? 0 : 1;
750
751 if (!(sn < ct->num_slots))
752 {
753 buffer[0] = CTBCS_SW1_WRONG_PARAM;
754 buffer[1] = CTBCS_SW2_WRONG_PARAM;
755
756 (*rsp) = APDU_Rsp_New (buffer, 2);
757 return ERR_INVALID;
758 }
759
760 /* Get command cualifier */
761 p2 = APDU_Cmd_P2 (cmd);
762
763#if 0
764 /* Wrong command cualifier */
765 if (p2 != 0)
766 {
767 buffer[0] = CTBCS_SW1_WRONG_PARAM;
768 buffer[1] = CTBCS_SW2_WRONG_PARAM;
769
770 (*rsp) = APDU_Rsp_New (buffer, 2);
771 return OK;
772 }
773#endif
774
775 if (CT_Slot_GetICCType (ct->slots[sn]) == CT_SLOT_NULL)
776 {
777 buffer[0] = CTBCS_SW1_EJECT_OK;
778 buffer[1] = CTBCS_SW2_EJECT_OK;
779
780 (*rsp) = APDU_Rsp_New (buffer, 2);
781 return OK;
782 }
783
784 /* Get the card removal timeout */
785 if (APDU_Cmd_Lc (cmd) == 1)
786 timeout = (unsigned int) (*APDU_Cmd_Data (cmd));
787 else
788 timeout = 0;
789
790 /* Check for card removal */
791 ret = CT_Slot_Check (ct->slots[sn], timeout, &card, &change);
792
793 if (ret != OK)
794 {
795 (*rsp) = NULL;
796 return ret;
797 }
798
799 /* Release ICC (always or only when card is removed?) */
800 ret = CT_Slot_Release (ct->slots[sn]);
801
802 if (ret != OK)
803 {
804 (*rsp) = NULL;
805 return ret;
806 }
807
808 if (timeout != 0)
809 {
810 if (card)
811 {
812 buffer[0] = CTBCS_SW1_EJECT_NOT_REMOVED;
813 buffer[1] = CTBCS_SW2_EJECT_NOT_REMOVED;
814 length = 2;
815 }
816 else
817 {
818 buffer[0] = CTBCS_SW1_EJECT_REMOVED;
819 buffer[1] = CTBCS_SW2_EJECT_REMOVED;
820 length = 2;
821 }
822 }
823 else
824 {
825 buffer[0] = CTBCS_SW1_EJECT_OK;;
826 buffer[1] = CTBCS_SW2_EJECT_OK;;
827 length = 2;
828 }
829
830 (*rsp) = APDU_Rsp_New (buffer, length);
831 return ret;
832}
833
834static void CardTerminal_Clear (CardTerminal * ct)
835{
836 int i;
837
838 ct->num_slots = 0;
839
840 for (i = 0; i < CARDTERMINAL_MAX_SLOTS; i++)
841 ct->slots[i] = NULL;
842}
Note: See TracBrowser for help on using the repository browser.