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

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.5