source: trunk/csctapi/cardterminal.c@ 1137

Last change on this file since 1137 was 1137, checked in by C.H.A.D.o, 12 years ago

Fix compiler warnings
Add Wextra flag

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