/[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 2983 - (hide annotations) (download)
Sun Jun 8 08:31:47 2008 UTC (4 years, 11 months ago) by rousseau
File MIME type: text/plain
File size: 22031 byte(s)
ReadSerial(): return the length of data read in *length

Thanks to Alexander Georg for the bug report
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 rousseau 2983 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 rousseau 2983 /* length of data read */
337     *length = to_read;
338    
339 rousseau 414 return STATUS_SUCCESS;
340     } /* ReadSerial */
341    
342    
343     /*****************************************************************************
344 rousseau 2152 *
345 rousseau 453 * get_bytes: get n bytes
346 rousseau 414 *
347     *****************************************************************************/
348 rousseau 1106 int get_bytes(unsigned int reader_index, unsigned char *buffer, int length)
349 rousseau 414 {
350 rousseau 1106 int offset = serialDevice[reader_index].buffer_offset;
351     int offset_last = serialDevice[reader_index].buffer_offset_last;
352 rousseau 414
353 rousseau 608 DEBUG_COMM3("available: %d, needed: %d", offset_last-offset,
354 rousseau 462 length);
355 rousseau 453 /* enough data are available */
356     if (offset + length <= offset_last)
357 rousseau 414 {
358 rousseau 608 DEBUG_COMM("data available");
359 rousseau 1106 memcpy(buffer, serialDevice[reader_index].buffer + offset, length);
360     serialDevice[reader_index].buffer_offset += length;
361 rousseau 414 }
362 rousseau 453 else
363 rousseau 414 {
364 rousseau 453 int present, rv;
365 rousseau 414
366 rousseau 453 /* copy available data */
367     present = offset_last - offset;
368 rousseau 414
369 rousseau 453 if (present > 0)
370 rousseau 462 {
371 rousseau 608 DEBUG_COMM2("some data available: %d", present);
372 rousseau 1106 memcpy(buffer, serialDevice[reader_index].buffer + offset,
373 rousseau 462 present);
374     }
375 rousseau 414
376 rousseau 453 /* get fresh data */
377 rousseau 608 DEBUG_COMM2("get more data: %d", length - present);
378 rousseau 1106 rv = ReadChunk(reader_index, serialDevice[reader_index].buffer,
379     sizeof(serialDevice[reader_index].buffer), length - present);
380 rousseau 453 if (rv < 0)
381     return STATUS_COMM_ERROR;
382 rousseau 414
383 rousseau 453 /* fill the buffer */
384 rousseau 1106 memcpy(buffer + present, serialDevice[reader_index].buffer,
385 rousseau 453 length - present);
386 rousseau 1106 serialDevice[reader_index].buffer_offset = length - present;
387     serialDevice[reader_index].buffer_offset_last = rv;
388 rousseau 608 DEBUG_COMM3("offset: %d, last_offset: %d",
389 rousseau 1106 serialDevice[reader_index].buffer_offset,
390     serialDevice[reader_index].buffer_offset_last);
391 rousseau 414 }
392    
393 rousseau 453 return STATUS_SUCCESS;
394     } /* get_bytes */
395 rousseau 414
396 rousseau 453
397 rousseau 414 /*****************************************************************************
398 rousseau 2152 *
399 rousseau 414 * ReadChunk: read a minimum number of bytes
400     *
401     *****************************************************************************/
402 rousseau 1106 static int ReadChunk(unsigned int reader_index, unsigned char *buffer,
403 rousseau 1050 int buffer_length, int min_length)
404 rousseau 414 {
405 rousseau 1106 int fd = serialDevice[reader_index].fd;
406 rousseau 1045 # ifndef S_SPLINT_S
407 rousseau 414 fd_set fdset;
408 rousseau 1045 # endif
409 rousseau 414 struct timeval t;
410 rousseau 462 int i, rv = 0;
411     int already_read;
412 rousseau 1047 char debug_header[] = "<- 123456 ";
413 rousseau 414
414 rousseau 1106 sprintf(debug_header, "<- %06X ", reader_index);
415 rousseau 414
416 rousseau 462 already_read = 0;
417     while (already_read < min_length)
418     {
419     /* use select() to, eventually, timeout */
420     FD_ZERO(&fdset);
421     FD_SET(fd, &fdset);
422 rousseau 1453 t.tv_sec = serialDevice[reader_index].ccid.readTimeout;
423 rousseau 462 t.tv_usec = 0;
424 rousseau 414
425 rousseau 462 i = select(fd+1, &fdset, NULL, NULL, &t);
426     if (i == -1)
427 rousseau 414 {
428 rousseau 462 DEBUG_CRITICAL2("select: %s", strerror(errno));
429 rousseau 414 return -1;
430     }
431 rousseau 462 else
432     if (i == 0)
433     {
434 rousseau 1453 DEBUG_COMM2("Timeout! (%d sec)", serialDevice[reader_index].ccid.readTimeout);
435 rousseau 462 return -1;
436     }
437 rousseau 414
438 rousseau 462 rv = read(fd, buffer + already_read, buffer_length - already_read);
439     if (rv < 0)
440     {
441     DEBUG_COMM2("read error: %s", strerror(errno));
442     return -1;
443     }
444 rousseau 414
445 rousseau 462 DEBUG_XXD(debug_header, buffer + already_read, rv);
446 rousseau 414
447 rousseau 462 already_read += rv;
448 rousseau 608 DEBUG_COMM3("read: %d, to read: %d", already_read,
449 rousseau 414 min_length);
450     }
451    
452 rousseau 462 return already_read;
453 rousseau 414 } /* ReadChunk */
454    
455    
456     /*****************************************************************************
457 rousseau 2152 *
458 rousseau 414 * OpenSerial: open the port
459     *
460     *****************************************************************************/
461 rousseau 1106 status_t OpenSerial(unsigned int reader_index, int channel)
462 rousseau 414 {
463     char dev_name[FILENAME_MAX];
464    
465 rousseau 1106 DEBUG_COMM3("Reader index: %X, Channel: %d", reader_index, channel);
466 rousseau 414
467     /*
468 rousseau 2152 * Conversion of old-style ifd-hanler 1.0 CHANNELID
469 rousseau 414 */
470     if (channel == 0x0103F8)
471     channel = 1;
472     else
473     if (channel == 0x0102F8)
474     channel = 2;
475     else
476     if (channel == 0x0103E8)
477     channel = 3;
478     else
479     if (channel == 0x0102E8)
480     channel = 4;
481    
482     if (channel < 0)
483     {
484     DEBUG_CRITICAL2("wrong port number: %d", (int) channel);
485     return STATUS_UNSUCCESSFUL;
486     }
487    
488     sprintf(dev_name, "/dev/pcsc/%d", (int) channel);
489    
490 rousseau 1106 return OpenSerialByName(reader_index, dev_name);
491 rousseau 649 } /* OpenSerial */
492    
493     /*****************************************************************************
494 rousseau 2152 *
495     * set_ccid_descriptor: init ccid descriptor
496 rousseau 1808 * depending on reader type specified in device.
497     *
498     * return: STATUS_UNSUCCESSFUL,
499     * STATUS_SUCCESS,
500     * -1 (Reader already used)
501     *
502     *****************************************************************************/
503     static status_t set_ccid_descriptor(unsigned int reader_index,
504     const char *reader_name, const char *dev_name)
505     {
506     long readerID;
507     int i;
508     int already_used = FALSE;
509     static int previous_reader_index = -1;
510    
511     readerID = GEMPCTWIN;
512 rousseau 2152 if (0 == strcasecmp(reader_name,"GemCorePOSPro"))
513 rousseau 1808 readerID = GEMCOREPOSPRO;
514     else if (0 == strcasecmp(reader_name,"GemCoreSIMPro"))
515     readerID = GEMCORESIMPRO;
516     else if (0 == strcasecmp(reader_name,"GemPCPinPad"))
517     readerID = GEMPCPINPAD;
518    
519     /* check if the same channel is not already used to manage multi-slots readers*/
520     for (i = 0; i < CCID_DRIVER_MAX_READERS; i++)
521     {
522     if (serialDevice[i].device
523     && strcmp(serialDevice[i].device, dev_name) == 0)
524     {
525     already_used = TRUE;
526    
527     DEBUG_COMM2("%s already used. Multi-slot reader?", dev_name);
528     break;
529     }
530     }
531    
532     /* this reader is already managed by us */
533     if (already_used)
534     {
535     if ((previous_reader_index != -1)
536     && serialDevice[previous_reader_index].device
537     && (strcmp(serialDevice[previous_reader_index].device, dev_name) == 0)
538     && serialDevice[previous_reader_index].ccid.bCurrentSlotIndex < serialDevice[previous_reader_index].ccid.bMaxSlotIndex)
539     {
540     /* we reuse the same device and the reader is multi-slot */
541     serialDevice[reader_index] = serialDevice[previous_reader_index];
542    
543     *serialDevice[reader_index].nb_opened_slots += 1;
544     serialDevice[reader_index].ccid.bCurrentSlotIndex++;
545     DEBUG_INFO2("Opening slot: %d",
546     serialDevice[reader_index].ccid.bCurrentSlotIndex);
547     switch (readerID)
548     {
549     case GEMCOREPOSPRO:
550     case GEMCORESIMPRO:
551     serialDevice[reader_index].ccid.arrayOfSupportedDataRates = SerialCustomDataRates;
552     serialDevice[reader_index].ccid.dwMaxDataRate = 125000;
553     break;
554    
555     /* GemPC Twin or GemPC Card */
556     default:
557     serialDevice[reader_index].ccid.arrayOfSupportedDataRates = SerialTwinDataRates;
558     serialDevice[reader_index].ccid.dwMaxDataRate = 344086;
559     break;
560     }
561     goto end;
562     }
563     else
564     {
565     DEBUG_CRITICAL2("Trying to open too many slots on %s", dev_name);
566     return STATUS_UNSUCCESSFUL;
567     }
568    
569     }
570    
571     /* Common to all readers */
572     serialDevice[reader_index].ccid.real_bSeq = 0;
573     serialDevice[reader_index].ccid.pbSeq = &serialDevice[reader_index].ccid.real_bSeq;
574     serialDevice[reader_index].real_nb_opened_slots = 1;
575     serialDevice[reader_index].nb_opened_slots = &serialDevice[reader_index].real_nb_opened_slots;
576     serialDevice[reader_index].ccid.bCurrentSlotIndex = 0;
577    
578     serialDevice[reader_index].ccid.dwMaxCCIDMessageLength = 271;
579     serialDevice[reader_index].ccid.dwMaxIFSD = 254;
580     serialDevice[reader_index].ccid.dwFeatures = 0x00010230;
581     serialDevice[reader_index].ccid.dwDefaultClock = 4000;
582    
583     serialDevice[reader_index].buffer_offset = 0;
584     serialDevice[reader_index].buffer_offset_last = 0;
585    
586     serialDevice[reader_index].ccid.readerID = readerID;
587     serialDevice[reader_index].ccid.bPINSupport = 0x0;
588     serialDevice[reader_index].ccid.dwMaxDataRate = 344086;
589     serialDevice[reader_index].ccid.bMaxSlotIndex = 0;
590     serialDevice[reader_index].ccid.arrayOfSupportedDataRates = SerialTwinDataRates;
591 rousseau 2871 serialDevice[reader_index].ccid.dwSlotStatus = IFD_ICC_PRESENT;
592 rousseau 1808 serialDevice[reader_index].echo = TRUE;
593    
594     /* change some values depending on the reader */
595     switch (readerID)
596     {
597     case GEMCOREPOSPRO:
598     serialDevice[reader_index].ccid.bMaxSlotIndex = 4; /* 5 slots */
599     serialDevice[reader_index].ccid.arrayOfSupportedDataRates = SerialExtendedDataRates;
600     serialDevice[reader_index].echo = FALSE;
601     serialDevice[reader_index].ccid.dwMaxDataRate = 500000;
602     break;
603    
604     case GEMCORESIMPRO:
605     serialDevice[reader_index].ccid.bMaxSlotIndex = 1; /* 2 slots */
606     serialDevice[reader_index].ccid.arrayOfSupportedDataRates = SerialExtendedDataRates;
607     serialDevice[reader_index].echo = FALSE;
608     serialDevice[reader_index].ccid.dwMaxDataRate = 500000;
609     break;
610    
611     case GEMPCPINPAD:
612     serialDevice[reader_index].ccid.bPINSupport = 0x03;
613     serialDevice[reader_index].ccid.arrayOfSupportedDataRates = SerialExtendedDataRates;
614     serialDevice[reader_index].ccid.dwMaxDataRate = 500000;
615     break;
616     }
617    
618     end:
619     /* memorise the current reader_index so we can detect
620     * a new OpenSerialByName on a multi slot reader */
621     previous_reader_index = reader_index;
622    
623     /* we just created a secondary slot on a multi-slot reader */
624     if (already_used)
625     return STATUS_SECONDARY_SLOT;
626    
627     return STATUS_SUCCESS;
628     } /* set_ccid_descriptor */
629    
630    
631     /*****************************************************************************
632 rousseau 2152 *
633 rousseau 649 * OpenSerialByName: open the port
634     *
635     *****************************************************************************/
636 rousseau 1106 status_t OpenSerialByName(unsigned int reader_index, char *dev_name)
637 rousseau 649 {
638     struct termios current_termios;
639 rousseau 1106 unsigned int reader = reader_index;
640 rousseau 1808 char reader_name[TOKEN_MAX_VALUE_SIZE] = "GemPCTwin";
641     char *p;
642     status_t ret;
643 rousseau 649
644 rousseau 1292 DEBUG_COMM3("Reader index: %X, Device: %s", reader_index, dev_name);
645 rousseau 649
646 rousseau 1808 /* parse dev_name using the pattern "device:name" */
647     p = strchr(dev_name, ':');
648     if (p)
649 rousseau 414 {
650 rousseau 1808 /* copy the second part of the string */
651     strncpy(reader_name, p+1, sizeof(reader_name));
652    
653     /* replace ':' by '\0' so that dev_name only contains the device name */
654     *p = '\0';
655 rousseau 414 }
656    
657 rousseau 1808 ret = set_ccid_descriptor(reader_index, reader_name, dev_name);
658     if (STATUS_UNSUCCESSFUL == ret)
659     return STATUS_UNSUCCESSFUL;
660    
661     /* secondary slot so do not physically open the device */
662     if (STATUS_SECONDARY_SLOT == ret)
663     return STATUS_SUCCESS;
664    
665 rousseau 414 serialDevice[reader].fd = open(dev_name, O_RDWR | O_NOCTTY);
666    
667 rousseau 892 if (-1 == serialDevice[reader].fd)
668 rousseau 414 {
669     DEBUG_CRITICAL3("open %s: %s", dev_name, strerror(errno));
670     return STATUS_UNSUCCESSFUL;
671     }
672    
673 rousseau 1472 /* Set RTS signal to low to prevent the smart card reader
674     * from sending its plug and play string. */
675     {
676     int flags;
677    
678     if (ioctl(serialDevice[reader].fd, TIOCMGET, &flags) < 0)
679     {
680     DEBUG_CRITICAL2("Get RS232 signals state failed: %s",
681     strerror(errno));
682     }
683     else
684     {
685     flags &= ~TIOCM_RTS;
686     if (ioctl(serialDevice[reader].fd, TIOCMSET, &flags) < 0)
687     {
688     DEBUG_CRITICAL2("Set RTS to low failed: %s", strerror(errno));
689     }
690     else
691     {
692     DEBUG_COMM("Plug-n-Play inhibition successful");
693     }
694     }
695     }
696    
697 rousseau 414 /* set channel used */
698 rousseau 649 serialDevice[reader].device = strdup(dev_name);
699 rousseau 414
700     /* empty in and out serial buffers */
701     if (tcflush(serialDevice[reader].fd, TCIOFLUSH))
702     DEBUG_INFO2("tcflush() function error: %s", strerror(errno));
703    
704     /* get config attributes */
705     if (tcgetattr(serialDevice[reader].fd, &current_termios) == -1)
706     {
707     DEBUG_INFO2("tcgetattr() function error: %s", strerror(errno));
708     close(serialDevice[reader].fd);
709     serialDevice[reader].fd = -1;
710    
711     return STATUS_UNSUCCESSFUL;
712     }
713    
714     /* IGNBRK: ignore BREAK condition on input
715     * IGNPAR: ignore framing errors and parity errors. */
716     current_termios.c_iflag = IGNBRK | IGNPAR;
717     current_termios.c_oflag = 0; /* Raw output modes */
718     /* CS8: 8-bits character size
719     * CSTOPB: set two stop bits
720     * CREAD: enable receiver
721     * CLOCAL: ignore modem control lines */
722     current_termios.c_cflag = CS8 | CSTOPB | CREAD | CLOCAL;
723    
724     /* Do not echo characters because if you connect to a host it or your modem
725     * will echo characters for you. Don't generate signals. */
726     current_termios.c_lflag = 0;
727    
728     /* set serial port speed to 115200 bauds */
729     cfsetspeed(&current_termios, B115200);
730    
731     DEBUG_INFO("Set serial port baudrate to 115200 and correct configuration");
732     if (tcsetattr(serialDevice[reader].fd, TCSANOW, &current_termios) == -1)
733     {
734     close(serialDevice[reader].fd);
735     serialDevice[reader].fd = -1;
736     DEBUG_INFO2("tcsetattr error: %s", strerror(errno));
737    
738     return STATUS_UNSUCCESSFUL;
739     }
740    
741 rousseau 1808 /* perform a command to be sure a Gemplus reader is connected
742 rousseau 1022 * get the reader firmware */
743     {
744 rousseau 1330 unsigned char tx_buffer[] = { 0x02 };
745 rousseau 1048 unsigned char rx_buffer[50];
746     unsigned int rx_length = sizeof(rx_buffer);
747 rousseau 1022
748 rousseau 1147 /* 2 seconds timeout to not wait too long if no reader is connected */
749 rousseau 1453 serialDevice[reader].ccid.readTimeout = 2;
750 rousseau 1147
751 rousseau 1106 if (IFD_SUCCESS != CmdEscape(reader_index, tx_buffer, sizeof(tx_buffer),
752 rousseau 1022 rx_buffer, &rx_length))
753     {
754 rousseau 1147 DEBUG_CRITICAL("Get firmware failed. Maybe the reader is not connected");
755 rousseau 1801 CloseSerial(reader_index);
756 rousseau 1022 return STATUS_UNSUCCESSFUL;
757     }
758    
759 rousseau 1453 /* normal timeout: 2 seconds */
760     serialDevice[reader].ccid.readTimeout = DEFAULT_COM_READ_TIMEOUT ;
761 rousseau 1147
762 rousseau 1022 rx_buffer[rx_length] = '\0';
763     DEBUG_INFO2("Firmware: %s", rx_buffer);
764     }
765    
766 rousseau 1444 /* perform a command to configure GemPC Twin reader card movement
767     * notification to synchronous mode: the card movement is notified _after_
768     * the host command and _before_ the reader anwser */
769     {
770     unsigned char tx_buffer[] = { 0x01, 0x01, 0x01};
771     unsigned char rx_buffer[50];
772     unsigned int rx_length = sizeof(rx_buffer);
773    
774     if (IFD_SUCCESS != CmdEscape(reader_index, tx_buffer, sizeof(tx_buffer),
775     rx_buffer, &rx_length))
776     {
777     DEBUG_CRITICAL("Change card movement notification failed.");
778 rousseau 1801 CloseSerial(reader_index);
779 rousseau 1444 return STATUS_UNSUCCESSFUL;
780     }
781     }
782    
783 rousseau 414 return STATUS_SUCCESS;
784 rousseau 649 } /* OpenSerialByName */
785 rousseau 414
786    
787     /*****************************************************************************
788 rousseau 2152 *
789 rousseau 414 * CloseSerial: close the port
790     *
791     *****************************************************************************/
792 rousseau 1106 status_t CloseSerial(unsigned int reader_index)
793 rousseau 414 {
794 rousseau 1106 unsigned int reader = reader_index;
795 rousseau 414
796 rousseau 1808 /* device not opened */
797     if (NULL == serialDevice[reader_index].device)
798     return STATUS_UNSUCCESSFUL;
799 rousseau 414
800 rousseau 1808 DEBUG_COMM2("Closing serial device: %s", serialDevice[reader_index].device);
801 rousseau 649
802 rousseau 1808 /* Decrement number of opened slot */
803     (*serialDevice[reader_index].nb_opened_slots)--;
804    
805     /* release the allocated ressources for the last slot only */
806     if (0 == *serialDevice[reader_index].nb_opened_slots)
807     {
808     DEBUG_COMM("Last slot closed. Release resources");
809    
810     close(serialDevice[reader].fd);
811     serialDevice[reader].fd = -1;
812    
813     free(serialDevice[reader].device);
814     serialDevice[reader].device = NULL;
815     }
816    
817 rousseau 414 return STATUS_SUCCESS;
818     } /* CloseSerial */
819    
820    
821     /*****************************************************************************
822     *
823     * get_ccid_descriptor
824     *
825     ****************************************************************************/
826 rousseau 1106 _ccid_descriptor *get_ccid_descriptor(unsigned int reader_index)
827 rousseau 414 {
828 rousseau 1106 return &serialDevice[reader_index].ccid;
829 rousseau 414 } /* get_ccid_descriptor */
830    
831    

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.5