/[pcsclite]/trunk/Drivers/ccid/src/ccid_serial.c
ViewVC logotype

Contents of /trunk/Drivers/ccid/src/ccid_serial.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 6252 - (show annotations) (download)
Tue Mar 27 12:58:12 2012 UTC (13 months, 3 weeks ago) by rousseau
File MIME type: text/plain
File size: 22806 byte(s)
Add support of Gemalto firmware features

Gemalto readers support an Escape command to report features supported
(or not) by the reader. The reader can also report if specific bugs are
fixed or not.

One of the fixed bug (in recent readers) is the bNumberMessage
management used in the Secure Modify CCID command.

Thanks to Jean Lusetti for the patch
1 /*
2 * ccid_serial.c: communicate with a GemPC Twin smart card reader
3 * Copyright (C) 2001-2010 Ludovic Rousseau <ludovic.rousseau@free.fr>
4 *
5 * Thanks to Niki W. Waibel <niki.waibel@gmx.net> for a prototype version
6 *
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2.1 of the License, or (at your option) any later version.
11
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with this library; if not, write to the Free Software Foundation,
19 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 */
21
22 /*
23 * $Id$
24 */
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <fcntl.h>
29 #include <unistd.h>
30 #include <termios.h>
31 #include <string.h>
32 #include <errno.h>
33 #include <sys/time.h>
34 #include <sys/types.h>
35 #include <sys/ioctl.h>
36 #include <ifdhandler.h>
37
38 #include "config.h"
39 #include "defs.h"
40 #include "ccid_ifdhandler.h"
41 #include "debug.h"
42 #include "ccid.h"
43 #include "utils.h"
44 #include "commands.h"
45 #include "parser.h"
46 #include "strlcpycat.h"
47
48 #define SYNC 0x03
49 #define CTRL_ACK 0x06
50 #define CTRL_NAK 0x15
51 #define RDR_to_PC_NotifySlotChange 0x50
52 #define CARD_ABSENT 0x02
53 #define CARD_PRESENT 0x03
54
55 /*
56 * normal command:
57 * 1 : SYNC
58 * 1 : CTRL
59 * 10 +data length : CCID command
60 * 1 : LRC
61 *
62 * SYNC : 0x03
63 * CTRL : ACK (0x06) or NAK (0x15)
64 * CCID command : see USB CCID specs
65 * LRC : xor of all the previous byes
66 *
67 * Error message:
68 * 1 : SYNC (0x03)
69 * 1 : CTRL (NAK: 0x15)
70 * 1 : LRC (0x16)
71 *
72 * Card insertion/withdrawal
73 * 1 : RDR_to_PC_NotifySlotChange (0x50)
74 * 1 : bmSlotIccState
75 * 0x02 if card absent
76 * 0x03 is card present
77 *
78 * Time request
79 * T=1 : normal CCID command
80 * T=0 : 1 byte (value between 0x80 and 0xFF)
81 *
82 */
83
84 /*
85 * You may get read timeout after a card movement.
86 * This is because you will get the echo of the CCID command
87 * but not the result of the command.
88 *
89 * This is not an applicative issue since the card is either removed (and
90 * powered off) or just inserted (and not yet powered on).
91 */
92
93 /* 271 = max size for short APDU
94 * 2 bytes for header
95 * 1 byte checksum
96 * doubled for echo
97 */
98 #define GEMPCTWIN_MAXBUF (271 +2 +1) * 2
99
100 typedef struct
101 {
102 /*
103 * File handle on the serial port
104 */
105 int fd;
106
107 /*
108 * device used ("/dev/ttyS?" under Linux)
109 */
110 /*@null@*/ char *device;
111
112 /*
113 * Number of slots using the same device
114 */
115 int real_nb_opened_slots;
116 int *nb_opened_slots;
117
118 /*
119 * does the reader echoes the serial communication bytes?
120 */
121 int echo;
122
123 /*
124 * serial communication buffer
125 */
126 unsigned char buffer[GEMPCTWIN_MAXBUF];
127
128 /*
129 * next available byte
130 */
131 int buffer_offset;
132
133 /*
134 * number of available bytes
135 */
136 int buffer_offset_last;
137
138 /*
139 * CCID infos common to USB and serial
140 */
141 _ccid_descriptor ccid;
142
143 } _serialDevice;
144
145 /* The _serialDevice structure must be defined before including ccid_serial.h */
146 #include "ccid_serial.h"
147
148 /* data rates supported by the GemPC Twin (serial and PCMCIA) */
149 unsigned int SerialTwinDataRates[] = { ISO_DATA_RATES, 0 };
150
151 /* data rates supported by the GemPC PinPad, GemCore Pos Pro & SIM Pro */
152 unsigned int SerialExtendedDataRates[] = { ISO_DATA_RATES, 500000, 0 };
153
154 /* data rates supported by the secondary slots on the GemCore Pos Pro & SIM Pro */
155 unsigned int SerialCustomDataRates[] = { GEMPLUS_CUSTOM_DATA_RATES, 0 };
156
157 /* no need to initialize to 0 since it is static */
158 static _serialDevice serialDevice[CCID_DRIVER_MAX_READERS];
159
160 /* unexported functions */
161 static int ReadChunk(unsigned int reader_index, unsigned char *buffer,
162 int buffer_length, int min_length);
163
164 static int get_bytes(unsigned int reader_index, /*@out@*/ unsigned char *buffer,
165 int length);
166
167
168 /*****************************************************************************
169 *
170 * WriteSerial: Send bytes to the card reader
171 *
172 *****************************************************************************/
173 status_t WriteSerial(unsigned int reader_index, unsigned int length,
174 unsigned char *buffer)
175 {
176 unsigned int i;
177 unsigned char lrc;
178 unsigned char low_level_buffer[GEMPCTWIN_MAXBUF];
179
180 char debug_header[] = "-> 123456 ";
181
182 (void)snprintf(debug_header, sizeof(debug_header), "-> %06X ",
183 reader_index);
184
185 if (length > GEMPCTWIN_MAXBUF-3)
186 {
187 DEBUG_CRITICAL3("command too long: %d for max %d",
188 length, GEMPCTWIN_MAXBUF-3);
189 return STATUS_UNSUCCESSFUL;
190 }
191
192 /* header */
193 low_level_buffer[0] = 0x03; /* SYNC */
194 low_level_buffer[1] = 0x06; /* ACK */
195
196 /* CCID command */
197 memcpy(low_level_buffer+2, buffer, length);
198
199 /* checksum */
200 lrc = 0;
201 for(i=0; i<length+2; i++)
202 lrc ^= low_level_buffer[i];
203 low_level_buffer[length+2] = lrc;
204
205 DEBUG_XXD(debug_header, low_level_buffer, length+3);
206
207 if (write(serialDevice[reader_index].fd, low_level_buffer,
208 length+3) != length+3)
209 {
210 DEBUG_CRITICAL2("write error: %s", strerror(errno));
211 return STATUS_UNSUCCESSFUL;
212 }
213
214 return STATUS_SUCCESS;
215 } /* WriteSerial */
216
217
218 /*****************************************************************************
219 *
220 * ReadSerial: Receive bytes from the card reader
221 *
222 *****************************************************************************/
223 status_t ReadSerial(unsigned int reader_index,
224 unsigned int *length, unsigned char *buffer)
225 {
226 unsigned char c;
227 int rv;
228 int echo;
229 int to_read;
230 int i;
231
232 /* we get the echo first */
233 echo = serialDevice[reader_index].echo;
234
235 start:
236 DEBUG_COMM("start");
237 if ((rv = get_bytes(reader_index, &c, 1)) != STATUS_SUCCESS)
238 return rv;
239
240 if (c == RDR_to_PC_NotifySlotChange)
241 goto slot_change;
242
243 if (c == SYNC)
244 goto sync;
245
246 if (c >= 0x80)
247 {
248 DEBUG_COMM2("time request: 0x%02X", c);
249 goto start;
250 }
251
252 DEBUG_CRITICAL2("Got 0x%02X", c);
253 return STATUS_COMM_ERROR;
254
255 slot_change:
256 DEBUG_COMM("slot change");
257 if ((rv = get_bytes(reader_index, &c, 1)) != STATUS_SUCCESS)
258 return rv;
259
260 if (c == CARD_ABSENT)
261 {
262 DEBUG_COMM("Card removed");
263 }
264 else
265 if (c == CARD_PRESENT)
266 {
267 DEBUG_COMM("Card inserted");
268 }
269 else
270 {
271 DEBUG_COMM2("Unknown card movement: %d", c);
272 }
273 goto start;
274
275 sync:
276 DEBUG_COMM("sync");
277 if ((rv = get_bytes(reader_index, &c, 1)) != STATUS_SUCCESS)
278 return rv;
279
280 if (c == CTRL_ACK)
281 goto ack;
282
283 if (c == CTRL_NAK)
284 goto nak;
285
286 DEBUG_CRITICAL2("Got 0x%02X instead of ACK/NAK", c);
287 return STATUS_COMM_ERROR;
288
289 nak:
290 DEBUG_COMM("nak");
291 if ((rv = get_bytes(reader_index, &c, 1)) != STATUS_SUCCESS)
292 return rv;
293
294 if (c != (SYNC ^ CTRL_NAK))
295 {
296 DEBUG_CRITICAL2("Wrong LRC: 0x%02X", c);
297 return STATUS_COMM_ERROR;
298 }
299 else
300 {
301 DEBUG_COMM("NAK requested");
302 return STATUS_COMM_NAK;
303 }
304
305 ack:
306 DEBUG_COMM("ack");
307 /* normal CCID frame */
308 if ((rv = get_bytes(reader_index, buffer, 5)) != STATUS_SUCCESS)
309 return rv;
310
311 /* total frame size */
312 to_read = 10+dw2i(buffer, 1);
313
314 if ((to_read < 10) || (to_read > (int)*length))
315 {
316 DEBUG_CRITICAL2("Wrong value for frame size: %d", to_read);
317 return STATUS_COMM_ERROR;
318 }
319
320 DEBUG_COMM2("frame size: %d", to_read);
321 if ((rv = get_bytes(reader_index, buffer+5, to_read-5)) != STATUS_SUCCESS)
322 return rv;
323
324 DEBUG_XXD("frame: ", buffer, to_read);
325
326 /* lrc */
327 DEBUG_COMM("lrc");
328 if ((rv = get_bytes(reader_index, &c, 1)) != STATUS_SUCCESS)
329 return rv;
330
331 DEBUG_COMM2("lrc: 0x%02X", c);
332 for (i=0; i<to_read; i++)
333 c ^= buffer[i];
334
335 if (c != (SYNC ^ CTRL_ACK))
336 DEBUG_CRITICAL2("Wrong LRC: 0x%02X", c);
337
338 if (echo)
339 {
340 echo = FALSE;
341 goto start;
342 }
343
344 /* length of data read */
345 *length = to_read;
346
347 return STATUS_SUCCESS;
348 } /* ReadSerial */
349
350
351 /*****************************************************************************
352 *
353 * get_bytes: get n bytes
354 *
355 *****************************************************************************/
356 int get_bytes(unsigned int reader_index, unsigned char *buffer, int length)
357 {
358 int offset = serialDevice[reader_index].buffer_offset;
359 int offset_last = serialDevice[reader_index].buffer_offset_last;
360
361 DEBUG_COMM3("available: %d, needed: %d", offset_last-offset,
362 length);
363 /* enough data are available */
364 if (offset + length <= offset_last)
365 {
366 DEBUG_COMM("data available");
367 memcpy(buffer, serialDevice[reader_index].buffer + offset, length);
368 serialDevice[reader_index].buffer_offset += length;
369 }
370 else
371 {
372 int present, rv;
373
374 /* copy available data */
375 present = offset_last - offset;
376
377 if (present > 0)
378 {
379 DEBUG_COMM2("some data available: %d", present);
380 memcpy(buffer, serialDevice[reader_index].buffer + offset,
381 present);
382 }
383
384 /* get fresh data */
385 DEBUG_COMM2("get more data: %d", length - present);
386 rv = ReadChunk(reader_index, serialDevice[reader_index].buffer,
387 sizeof(serialDevice[reader_index].buffer), length - present);
388 if (rv < 0)
389 return STATUS_COMM_ERROR;
390
391 /* fill the buffer */
392 memcpy(buffer + present, serialDevice[reader_index].buffer,
393 length - present);
394 serialDevice[reader_index].buffer_offset = length - present;
395 serialDevice[reader_index].buffer_offset_last = rv;
396 DEBUG_COMM3("offset: %d, last_offset: %d",
397 serialDevice[reader_index].buffer_offset,
398 serialDevice[reader_index].buffer_offset_last);
399 }
400
401 return STATUS_SUCCESS;
402 } /* get_bytes */
403
404
405 /*****************************************************************************
406 *
407 * ReadChunk: read a minimum number of bytes
408 *
409 *****************************************************************************/
410 static int ReadChunk(unsigned int reader_index, unsigned char *buffer,
411 int buffer_length, int min_length)
412 {
413 int fd = serialDevice[reader_index].fd;
414 # ifndef S_SPLINT_S
415 fd_set fdset;
416 # endif
417 struct timeval t;
418 int i, rv = 0;
419 int already_read;
420 char debug_header[] = "<- 123456 ";
421
422 (void)snprintf(debug_header, sizeof(debug_header), "<- %06X ",
423 reader_index);
424
425 already_read = 0;
426 while (already_read < min_length)
427 {
428 /* use select() to, eventually, timeout */
429 FD_ZERO(&fdset);
430 FD_SET(fd, &fdset);
431 t.tv_sec = serialDevice[reader_index].ccid.readTimeout / 1000;
432 t.tv_usec = (serialDevice[reader_index].ccid.readTimeout - t.tv_sec*1000)*1000;
433
434 i = select(fd+1, &fdset, NULL, NULL, &t);
435 if (i == -1)
436 {
437 DEBUG_CRITICAL2("select: %s", strerror(errno));
438 return -1;
439 }
440 else
441 if (i == 0)
442 {
443 DEBUG_COMM2("Timeout! (%d ms)", serialDevice[reader_index].ccid.readTimeout);
444 return -1;
445 }
446
447 rv = read(fd, buffer + already_read, buffer_length - already_read);
448 if (rv < 0)
449 {
450 DEBUG_COMM2("read error: %s", strerror(errno));
451 return -1;
452 }
453
454 DEBUG_XXD(debug_header, buffer + already_read, rv);
455
456 already_read += rv;
457 DEBUG_COMM3("read: %d, to read: %d", already_read,
458 min_length);
459 }
460
461 return already_read;
462 } /* ReadChunk */
463
464
465 /*****************************************************************************
466 *
467 * OpenSerial: open the port
468 *
469 *****************************************************************************/
470 status_t OpenSerial(unsigned int reader_index, int channel)
471 {
472 char dev_name[FILENAME_MAX];
473
474 DEBUG_COMM3("Reader index: %X, Channel: %d", reader_index, channel);
475
476 /*
477 * Conversion of old-style ifd-hanler 1.0 CHANNELID
478 */
479 if (channel == 0x0103F8)
480 channel = 1;
481 else
482 if (channel == 0x0102F8)
483 channel = 2;
484 else
485 if (channel == 0x0103E8)
486 channel = 3;
487 else
488 if (channel == 0x0102E8)
489 channel = 4;
490
491 if (channel < 0)
492 {
493 DEBUG_CRITICAL2("wrong port number: %d", channel);
494 return STATUS_UNSUCCESSFUL;
495 }
496
497 (void)snprintf(dev_name, sizeof(dev_name), "/dev/pcsc/%d", channel);
498
499 return OpenSerialByName(reader_index, dev_name);
500 } /* OpenSerial */
501
502 /*****************************************************************************
503 *
504 * set_ccid_descriptor: init ccid descriptor
505 * depending on reader type specified in device.
506 *
507 * return: STATUS_UNSUCCESSFUL,
508 * STATUS_SUCCESS,
509 * -1 (Reader already used)
510 *
511 *****************************************************************************/
512 static status_t set_ccid_descriptor(unsigned int reader_index,
513 const char *reader_name, const char *dev_name)
514 {
515 int readerID;
516 int i;
517 int already_used = FALSE;
518 static int previous_reader_index = -1;
519
520 readerID = GEMPCTWIN;
521 if (0 == strcasecmp(reader_name,"GemCorePOSPro"))
522 readerID = GEMCOREPOSPRO;
523 else if (0 == strcasecmp(reader_name,"GemCoreSIMPro"))
524 readerID = GEMCORESIMPRO;
525 else if (0 == strcasecmp(reader_name,"GemPCPinPad"))
526 readerID = GEMPCPINPAD;
527
528 /* check if the same channel is not already used to manage multi-slots readers*/
529 for (i = 0; i < CCID_DRIVER_MAX_READERS; i++)
530 {
531 if (serialDevice[i].device
532 && strcmp(serialDevice[i].device, dev_name) == 0)
533 {
534 already_used = TRUE;
535
536 DEBUG_COMM2("%s already used. Multi-slot reader?", dev_name);
537 break;
538 }
539 }
540
541 /* this reader is already managed by us */
542 if (already_used)
543 {
544 if ((previous_reader_index != -1)
545 && serialDevice[previous_reader_index].device
546 && (strcmp(serialDevice[previous_reader_index].device, dev_name) == 0)
547 && serialDevice[previous_reader_index].ccid.bCurrentSlotIndex < serialDevice[previous_reader_index].ccid.bMaxSlotIndex)
548 {
549 /* we reuse the same device and the reader is multi-slot */
550 serialDevice[reader_index] = serialDevice[previous_reader_index];
551
552 *serialDevice[reader_index].nb_opened_slots += 1;
553 serialDevice[reader_index].ccid.bCurrentSlotIndex++;
554 serialDevice[reader_index].ccid.dwSlotStatus = IFD_ICC_PRESENT;
555 DEBUG_INFO2("Opening slot: %d",
556 serialDevice[reader_index].ccid.bCurrentSlotIndex);
557 switch (readerID)
558 {
559 case GEMCOREPOSPRO:
560 case GEMCORESIMPRO:
561 serialDevice[reader_index].ccid.arrayOfSupportedDataRates = SerialCustomDataRates;
562 serialDevice[reader_index].ccid.dwMaxDataRate = 125000;
563 break;
564
565 /* GemPC Twin or GemPC Card */
566 default:
567 serialDevice[reader_index].ccid.arrayOfSupportedDataRates = SerialTwinDataRates;
568 serialDevice[reader_index].ccid.dwMaxDataRate = 344086;
569 break;
570 }
571 goto end;
572 }
573 else
574 {
575 DEBUG_CRITICAL2("Trying to open too many slots on %s", dev_name);
576 return STATUS_UNSUCCESSFUL;
577 }
578
579 }
580
581 /* Common to all readers */
582 serialDevice[reader_index].ccid.real_bSeq = 0;
583 serialDevice[reader_index].ccid.pbSeq = &serialDevice[reader_index].ccid.real_bSeq;
584 serialDevice[reader_index].real_nb_opened_slots = 1;
585 serialDevice[reader_index].nb_opened_slots = &serialDevice[reader_index].real_nb_opened_slots;
586 serialDevice[reader_index].ccid.bCurrentSlotIndex = 0;
587
588 serialDevice[reader_index].ccid.dwMaxCCIDMessageLength = 271;
589 serialDevice[reader_index].ccid.dwMaxIFSD = 254;
590 serialDevice[reader_index].ccid.dwFeatures = 0x00010230;
591 serialDevice[reader_index].ccid.dwDefaultClock = 4000;
592
593 serialDevice[reader_index].buffer_offset = 0;
594 serialDevice[reader_index].buffer_offset_last = 0;
595
596 serialDevice[reader_index].ccid.readerID = readerID;
597 serialDevice[reader_index].ccid.bPINSupport = 0x0;
598 serialDevice[reader_index].ccid.dwMaxDataRate = 344086;
599 serialDevice[reader_index].ccid.bMaxSlotIndex = 0;
600 serialDevice[reader_index].ccid.arrayOfSupportedDataRates = SerialTwinDataRates;
601 serialDevice[reader_index].ccid.dwSlotStatus = IFD_ICC_PRESENT;
602 serialDevice[reader_index].ccid.bVoltageSupport = 0x07; /* 1.8V, 3V and 5V */
603 serialDevice[reader_index].ccid.gemalto_firmware_features = NULL;
604 serialDevice[reader_index].echo = TRUE;
605
606 /* change some values depending on the reader */
607 switch (readerID)
608 {
609 case GEMCOREPOSPRO:
610 serialDevice[reader_index].ccid.bMaxSlotIndex = 4; /* 5 slots */
611 serialDevice[reader_index].ccid.arrayOfSupportedDataRates = SerialExtendedDataRates;
612 serialDevice[reader_index].echo = FALSE;
613 serialDevice[reader_index].ccid.dwMaxDataRate = 500000;
614 break;
615
616 case GEMCORESIMPRO:
617 serialDevice[reader_index].ccid.bMaxSlotIndex = 1; /* 2 slots */
618 serialDevice[reader_index].ccid.arrayOfSupportedDataRates = SerialExtendedDataRates;
619 serialDevice[reader_index].echo = FALSE;
620 serialDevice[reader_index].ccid.dwMaxDataRate = 500000;
621 break;
622
623 case GEMPCPINPAD:
624 serialDevice[reader_index].ccid.bPINSupport = 0x03;
625 serialDevice[reader_index].ccid.arrayOfSupportedDataRates = SerialExtendedDataRates;
626 serialDevice[reader_index].ccid.dwMaxDataRate = 500000;
627 break;
628 }
629
630 end:
631 /* memorise the current reader_index so we can detect
632 * a new OpenSerialByName on a multi slot reader */
633 previous_reader_index = reader_index;
634
635 /* we just created a secondary slot on a multi-slot reader */
636 if (already_used)
637 return STATUS_SECONDARY_SLOT;
638
639 return STATUS_SUCCESS;
640 } /* set_ccid_descriptor */
641
642
643 /*****************************************************************************
644 *
645 * OpenSerialByName: open the port
646 *
647 *****************************************************************************/
648 status_t OpenSerialByName(unsigned int reader_index, char *dev_name)
649 {
650 struct termios current_termios;
651 unsigned int reader = reader_index;
652 /* 255 is MAX_DEVICENAME in pcscd.h */
653 char reader_name[255] = "GemPCTwin";
654 char *p;
655 status_t ret;
656
657 DEBUG_COMM3("Reader index: %X, Device: %s", reader_index, dev_name);
658
659 /* parse dev_name using the pattern "device:name" */
660 p = strchr(dev_name, ':');
661 if (p)
662 {
663 /* copy the second part of the string */
664 strlcpy(reader_name, p+1, sizeof(reader_name));
665
666 /* replace ':' by '\0' so that dev_name only contains the device name */
667 *p = '\0';
668 }
669
670 ret = set_ccid_descriptor(reader_index, reader_name, dev_name);
671 if (STATUS_UNSUCCESSFUL == ret)
672 return STATUS_UNSUCCESSFUL;
673
674 /* secondary slot so do not physically open the device */
675 if (STATUS_SECONDARY_SLOT == ret)
676 return STATUS_SUCCESS;
677
678 serialDevice[reader].fd = open(dev_name, O_RDWR | O_NOCTTY);
679
680 if (-1 == serialDevice[reader].fd)
681 {
682 DEBUG_CRITICAL3("open %s: %s", dev_name, strerror(errno));
683 return STATUS_UNSUCCESSFUL;
684 }
685
686 /* Set RTS signal to low to prevent the smart card reader
687 * from sending its plug and play string. */
688 {
689 int flags;
690
691 if (ioctl(serialDevice[reader].fd, TIOCMGET, &flags) < 0)
692 {
693 DEBUG_CRITICAL2("Get RS232 signals state failed: %s",
694 strerror(errno));
695 }
696 else
697 {
698 flags &= ~TIOCM_RTS;
699 if (ioctl(serialDevice[reader].fd, TIOCMSET, &flags) < 0)
700 {
701 DEBUG_CRITICAL2("Set RTS to low failed: %s", strerror(errno));
702 }
703 else
704 {
705 DEBUG_COMM("Plug-n-Play inhibition successful");
706 }
707 }
708 }
709
710 /* set channel used */
711 serialDevice[reader].device = strdup(dev_name);
712
713 /* empty in and out serial buffers */
714 if (tcflush(serialDevice[reader].fd, TCIOFLUSH))
715 DEBUG_INFO2("tcflush() function error: %s", strerror(errno));
716
717 /* get config attributes */
718 if (tcgetattr(serialDevice[reader].fd, &current_termios) == -1)
719 {
720 DEBUG_INFO2("tcgetattr() function error: %s", strerror(errno));
721 (void)close(serialDevice[reader].fd);
722 serialDevice[reader].fd = -1;
723
724 return STATUS_UNSUCCESSFUL;
725 }
726
727 /* IGNBRK: ignore BREAK condition on input
728 * IGNPAR: ignore framing errors and parity errors. */
729 current_termios.c_iflag = IGNBRK | IGNPAR;
730 current_termios.c_oflag = 0; /* Raw output modes */
731 /* CS8: 8-bits character size
732 * CSTOPB: set two stop bits
733 * CREAD: enable receiver
734 * CLOCAL: ignore modem control lines */
735 current_termios.c_cflag = CS8 | CSTOPB | CREAD | CLOCAL;
736
737 /* Do not echo characters because if you connect to a host it or your modem
738 * will echo characters for you. Don't generate signals. */
739 current_termios.c_lflag = 0;
740
741 /* set serial port speed to 115200 bauds */
742 (void)cfsetspeed(&current_termios, B115200);
743
744 DEBUG_INFO("Set serial port baudrate to 115200 and correct configuration");
745 if (tcsetattr(serialDevice[reader].fd, TCSANOW, &current_termios) == -1)
746 {
747 (void)close(serialDevice[reader].fd);
748 serialDevice[reader].fd = -1;
749 DEBUG_INFO2("tcsetattr error: %s", strerror(errno));
750
751 return STATUS_UNSUCCESSFUL;
752 }
753
754 /* perform a command to be sure a Gemalto reader is connected
755 * get the reader firmware */
756 {
757 unsigned char tx_buffer[] = { 0x02 };
758 unsigned char rx_buffer[50];
759 unsigned int rx_length = sizeof(rx_buffer);
760
761 /* 2 seconds timeout to not wait too long if no reader is connected */
762 serialDevice[reader].ccid.readTimeout = 2*1000;
763
764 if (IFD_SUCCESS != CmdEscape(reader_index, tx_buffer, sizeof(tx_buffer),
765 rx_buffer, &rx_length))
766 {
767 DEBUG_CRITICAL("Get firmware failed. Maybe the reader is not connected");
768 (void)CloseSerial(reader_index);
769 return STATUS_UNSUCCESSFUL;
770 }
771
772 /* normal timeout: 2 seconds */
773 serialDevice[reader].ccid.readTimeout = DEFAULT_COM_READ_TIMEOUT ;
774
775 rx_buffer[rx_length] = '\0';
776 DEBUG_INFO2("Firmware: %s", rx_buffer);
777 }
778
779 /* perform a command to configure GemPC Twin reader card movement
780 * notification to synchronous mode: the card movement is notified _after_
781 * the host command and _before_ the reader anwser */
782 {
783 unsigned char tx_buffer[] = { 0x01, 0x01, 0x01};
784 unsigned char rx_buffer[50];
785 unsigned int rx_length = sizeof(rx_buffer);
786
787 if (IFD_SUCCESS != CmdEscape(reader_index, tx_buffer, sizeof(tx_buffer),
788 rx_buffer, &rx_length))
789 {
790 DEBUG_CRITICAL("Change card movement notification failed.");
791 (void)CloseSerial(reader_index);
792 return STATUS_UNSUCCESSFUL;
793 }
794 }
795
796 serialDevice[reader_index].ccid.sIFD_serial_number = NULL;
797 serialDevice[reader_index].ccid.sIFD_iManufacturer = NULL;
798 serialDevice[reader_index].ccid.IFD_bcdDevice = 0;
799
800 return STATUS_SUCCESS;
801 } /* OpenSerialByName */
802
803
804 /*****************************************************************************
805 *
806 * CloseSerial: close the port
807 *
808 *****************************************************************************/
809 status_t CloseSerial(unsigned int reader_index)
810 {
811 unsigned int reader = reader_index;
812
813 /* device not opened */
814 if (NULL == serialDevice[reader_index].device)
815 return STATUS_UNSUCCESSFUL;
816
817 DEBUG_COMM2("Closing serial device: %s", serialDevice[reader_index].device);
818
819 /* Decrement number of opened slot */
820 (*serialDevice[reader_index].nb_opened_slots)--;
821
822 /* release the allocated ressources for the last slot only */
823 if (0 == *serialDevice[reader_index].nb_opened_slots)
824 {
825 DEBUG_COMM("Last slot closed. Release resources");
826
827 (void)close(serialDevice[reader].fd);
828 serialDevice[reader].fd = -1;
829
830 free(serialDevice[reader].device);
831 serialDevice[reader].device = NULL;
832 }
833
834 return STATUS_SUCCESS;
835 } /* CloseSerial */
836
837
838 /*****************************************************************************
839 *
840 * get_ccid_descriptor
841 *
842 ****************************************************************************/
843 _ccid_descriptor *get_ccid_descriptor(unsigned int reader_index)
844 {
845 return &serialDevice[reader_index].ccid;
846 } /* get_ccid_descriptor */
847
848

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Revision

  ViewVC Help
Powered by ViewVC 1.1.5