source: branches/monitor-improvement/csctapi/cardterminal.c@ 1228

Last change on this file since 1228 was 1228, checked in by alno, 13 years ago

WebIf:

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