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

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.5