Initial commit
[platform/upstream/ccid.git] / src / ccid_serial.c
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 #include <stdio.h>
23 #include <stdlib.h>
24 #include <fcntl.h>
25 #include <unistd.h>
26 #include <termios.h>
27 #include <string.h>
28 #include <errno.h>
29 #include <sys/time.h>
30 #include <sys/types.h>
31 #include <sys/ioctl.h>
32 #include <ifdhandler.h>
33
34 #include <config.h>
35 #include "defs.h"
36 #include "ccid_ifdhandler.h"
37 #include "debug.h"
38 #include "ccid.h"
39 #include "utils.h"
40 #include "commands.h"
41 #include "parser.h"
42 #include "strlcpycat.h"
43
44 #define SYNC 0x03
45 #define CTRL_ACK 0x06
46 #define CTRL_NAK 0x15
47 #define RDR_to_PC_NotifySlotChange 0x50
48 #define CARD_ABSENT 0x02
49 #define CARD_PRESENT 0x03
50
51 /*
52  * normal command:
53  * 1 : SYNC
54  * 1 : CTRL
55  * 10 +data length : CCID command
56  * 1 : LRC
57  *
58  * SYNC : 0x03
59  * CTRL : ACK (0x06) or NAK (0x15)
60  * CCID command : see USB CCID specs
61  * LRC : xor of all the previous byes
62  *
63  * Error message:
64  * 1 : SYNC (0x03)
65  * 1 : CTRL (NAK: 0x15)
66  * 1 : LRC (0x16)
67  *
68  * Card insertion/withdrawal
69  * 1 : RDR_to_PC_NotifySlotChange (0x50)
70  * 1 : bmSlotIccState
71  *     0x02 if card absent
72  *     0x03 is card present
73  *
74  * Time request
75  * T=1 : normal CCID command
76  * T=0 : 1 byte (value between 0x80 and 0xFF)
77  *
78  */
79
80 /*
81  * You may get read timeout after a card movement.
82  * This is because you will get the echo of the CCID command
83  * but not the result of the command.
84  *
85  * This is not an applicative issue since the card is either removed (and
86  * powered off) or just inserted (and not yet powered on).
87  */
88
89 /* 271 = max size for short APDU
90  * 2 bytes for header
91  * 1 byte checksum
92  * doubled for echo
93  */
94 #define GEMPCTWIN_MAXBUF (271 +2 +1) * 2
95
96 typedef struct
97 {
98         /*
99          * File handle on the serial port
100          */
101         int fd;
102
103         /*
104          * device used ("/dev/ttyS?" under Linux)
105          */
106         /*@null@*/ char *device;
107
108         /*
109          * Number of slots using the same device
110          */
111         int real_nb_opened_slots;
112         int *nb_opened_slots;
113
114         /*
115          * does the reader echoes the serial communication bytes?
116          */
117         int echo;
118
119         /*
120          * serial communication buffer
121          */
122         unsigned char buffer[GEMPCTWIN_MAXBUF];
123
124         /*
125          * next available byte
126          */
127         int buffer_offset;
128
129         /*
130          * number of available bytes
131          */
132         int buffer_offset_last;
133
134         /*
135          * CCID infos common to USB and serial
136          */
137         _ccid_descriptor ccid;
138
139 } _serialDevice;
140
141 /* The _serialDevice structure must be defined before including ccid_serial.h */
142 #include "ccid_serial.h"
143
144 /* data rates supported by the GemPC Twin (serial and PCMCIA) */
145 unsigned int SerialTwinDataRates[] = { ISO_DATA_RATES, 0 };
146
147 /* data rates supported by the GemPC PinPad, GemCore Pos Pro & SIM Pro */
148 unsigned int SerialExtendedDataRates[] = { ISO_DATA_RATES, 500000, 0 };
149
150 /* data rates supported by the secondary slots on the GemCore Pos Pro & SIM Pro */
151 unsigned int SerialCustomDataRates[] = { GEMPLUS_CUSTOM_DATA_RATES, 0 };
152
153 /* data rates supported by the GemCore SIM Pro 2 */
154 unsigned int SIMPro2DataRates[] = { SIMPRO2_ISO_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         if ((to_read < 10) || (to_read > (int)*length))
314         {
315                 DEBUG_CRITICAL2("Wrong value for frame size: %d", to_read);
316                 return STATUS_COMM_ERROR;
317         }
318
319         DEBUG_COMM2("frame size: %d", to_read);
320         if ((rv = get_bytes(reader_index, buffer+5, to_read-5)) != STATUS_SUCCESS)
321                 return rv;
322
323         DEBUG_XXD("frame: ", buffer, to_read);
324
325         /* lrc */
326         DEBUG_COMM("lrc");
327         if ((rv = get_bytes(reader_index, &c, 1)) != STATUS_SUCCESS)
328                 return rv;
329
330         DEBUG_COMM2("lrc: 0x%02X", c);
331         for (i=0; i<to_read; i++)
332                 c ^= buffer[i];
333
334         if (c != (SYNC ^ CTRL_ACK))
335                 DEBUG_CRITICAL2("Wrong LRC: 0x%02X", c);
336
337         if (echo)
338         {
339                 echo = FALSE;
340                 goto start;
341         }
342
343         /* length of data read */
344         *length = to_read;
345
346         return STATUS_SUCCESS;
347 } /* ReadSerial */
348
349
350 /*****************************************************************************
351  *
352  *                              get_bytes: get n bytes
353  *
354  *****************************************************************************/
355 int get_bytes(unsigned int reader_index, unsigned char *buffer, int length)
356 {
357         int offset = serialDevice[reader_index].buffer_offset;
358         int offset_last = serialDevice[reader_index].buffer_offset_last;
359
360         DEBUG_COMM3("available: %d, needed: %d", offset_last-offset,
361                 length);
362         /* enough data are available */
363         if (offset + length <= offset_last)
364         {
365                 DEBUG_COMM("data available");
366                 memcpy(buffer, serialDevice[reader_index].buffer + offset, length);
367                 serialDevice[reader_index].buffer_offset += length;
368         }
369         else
370         {
371                 int present, rv;
372
373                 /* copy available data */
374                 present = offset_last - offset;
375
376                 if (present > 0)
377                 {
378                         DEBUG_COMM2("some data available: %d", present);
379                         memcpy(buffer, serialDevice[reader_index].buffer + offset,
380                                 present);
381                 }
382
383                 /* get fresh data */
384                 DEBUG_COMM2("get more data: %d", length - present);
385                 rv = ReadChunk(reader_index, serialDevice[reader_index].buffer,
386                         sizeof(serialDevice[reader_index].buffer), length - present);
387                 if (rv < 0)
388                         return STATUS_COMM_ERROR;
389
390                 /* fill the buffer */
391                 memcpy(buffer + present, serialDevice[reader_index].buffer,
392                         length - present);
393                 serialDevice[reader_index].buffer_offset = length - present;
394                 serialDevice[reader_index].buffer_offset_last = rv;
395                 DEBUG_COMM3("offset: %d, last_offset: %d",
396                         serialDevice[reader_index].buffer_offset,
397                         serialDevice[reader_index].buffer_offset_last);
398         }
399
400         return STATUS_SUCCESS;
401 } /* get_bytes */
402
403
404 /*****************************************************************************
405  *
406  *                              ReadChunk: read a minimum number of bytes
407  *
408  *****************************************************************************/
409 static int ReadChunk(unsigned int reader_index, unsigned char *buffer,
410         int buffer_length, int min_length)
411 {
412         int fd = serialDevice[reader_index].fd;
413 # ifndef S_SPLINT_S
414         fd_set fdset;
415 # endif
416         struct timeval t;
417         int i, rv = 0;
418         int already_read;
419         char debug_header[] = "<- 123456 ";
420
421         (void)snprintf(debug_header, sizeof(debug_header), "<- %06X ",
422                 reader_index);
423
424         already_read = 0;
425         while (already_read < min_length)
426         {
427                 /* use select() to, eventually, timeout */
428                 FD_ZERO(&fdset);
429                 FD_SET(fd, &fdset);
430                 t.tv_sec = serialDevice[reader_index].ccid.readTimeout / 1000;
431                 t.tv_usec = (serialDevice[reader_index].ccid.readTimeout - t.tv_sec*1000)*1000;
432
433                 i = select(fd+1, &fdset, NULL, NULL, &t);
434                 if (i == -1)
435                 {
436                         DEBUG_CRITICAL2("select: %s", strerror(errno));
437                         return -1;
438                 }
439                 else
440                         if (i == 0)
441                         {
442                                 DEBUG_COMM2("Timeout! (%d ms)", serialDevice[reader_index].ccid.readTimeout);
443                                 return -1;
444                         }
445
446                 rv = read(fd, buffer + already_read, buffer_length - already_read);
447                 if (rv < 0)
448                 {
449                         DEBUG_COMM2("read error: %s", strerror(errno));
450                         return -1;
451                 }
452
453                 DEBUG_XXD(debug_header, buffer + already_read, rv);
454
455                 already_read += rv;
456                 DEBUG_COMM3("read: %d, to read: %d", already_read,
457                         min_length);
458         }
459
460         return already_read;
461 } /* ReadChunk */
462
463
464 /*****************************************************************************
465  *
466  *                              OpenSerial: open the port
467  *
468  *****************************************************************************/
469 status_t OpenSerial(unsigned int reader_index, int channel)
470 {
471         char dev_name[FILENAME_MAX];
472
473         DEBUG_COMM3("Reader index: %X, Channel: %d", reader_index, channel);
474
475         /*
476          * Conversion of old-style ifd-hanler 1.0 CHANNELID
477          */
478         if (channel == 0x0103F8)
479                 channel = 1;
480         else
481                 if (channel == 0x0102F8)
482                         channel = 2;
483                 else
484                         if (channel == 0x0103E8)
485                                 channel = 3;
486                         else
487                                 if (channel == 0x0102E8)
488                                         channel = 4;
489
490         if (channel < 0)
491         {
492                 DEBUG_CRITICAL2("wrong port number: %d", channel);
493                 return STATUS_UNSUCCESSFUL;
494         }
495
496         (void)snprintf(dev_name, sizeof(dev_name), "/dev/pcsc/%d", channel);
497
498         return OpenSerialByName(reader_index, dev_name);
499 } /* OpenSerial */
500
501 /*****************************************************************************
502  *
503  *                              set_ccid_descriptor: init ccid descriptor
504  *                              depending on reader type specified in device.
505  *
506  *                              return: STATUS_UNSUCCESSFUL,
507  *                                              STATUS_SUCCESS,
508  *                                              -1 (Reader already used)
509  *
510  *****************************************************************************/
511 static status_t set_ccid_descriptor(unsigned int reader_index,
512         const char *reader_name, const char *dev_name)
513 {
514         int readerID;
515         int i;
516         int already_used = FALSE;
517         static int previous_reader_index = -1;
518
519         readerID = GEMPCTWIN;
520         if (0 == strcasecmp(reader_name,"GemCorePOSPro"))
521                 readerID = GEMCOREPOSPRO;
522         else if (0 == strcasecmp(reader_name,"GemCoreSIMPro"))
523                 readerID = GEMCORESIMPRO;
524         else if (0 == strcasecmp(reader_name,"GemCoreSIMPro2"))
525                 readerID = GEMCORESIMPRO2;
526         else if (0 == strcasecmp(reader_name,"GemPCPinPad"))
527                 readerID = GEMPCPINPAD;
528         else if (0 == strcasecmp(reader_name,"SEC1210"))
529                 readerID = SEC1210;
530
531         /* check if the same channel is not already used to manage multi-slots readers*/
532         for (i = 0; i < CCID_DRIVER_MAX_READERS; i++)
533         {
534                 if (serialDevice[i].device
535                         && strcmp(serialDevice[i].device, dev_name) == 0)
536                 {
537                         already_used = TRUE;
538
539                         DEBUG_COMM2("%s already used. Multi-slot reader?", dev_name);
540                         break;
541                 }
542         }
543
544         /* this reader is already managed by us */
545         if (already_used)
546         {
547                 if ((previous_reader_index != -1)
548                         && serialDevice[previous_reader_index].device
549                         && (strcmp(serialDevice[previous_reader_index].device, dev_name) == 0)
550                         && serialDevice[previous_reader_index].ccid.bCurrentSlotIndex < serialDevice[previous_reader_index].ccid.bMaxSlotIndex)
551                 {
552                         /* we reuse the same device and the reader is multi-slot */
553                         serialDevice[reader_index] = serialDevice[previous_reader_index];
554
555                         *serialDevice[reader_index].nb_opened_slots += 1;
556                         serialDevice[reader_index].ccid.bCurrentSlotIndex++;
557                         serialDevice[reader_index].ccid.dwSlotStatus = IFD_ICC_PRESENT;
558                         DEBUG_INFO2("Opening slot: %d",
559                                         serialDevice[reader_index].ccid.bCurrentSlotIndex);
560                         switch (readerID)
561                         {
562                                 case GEMCOREPOSPRO:
563                                 case GEMCORESIMPRO:
564                                         {
565                                                 /* Allocate a memory buffer that will be
566                                                  * released in CloseUSB() */
567                                                 void *ptr = malloc(sizeof SerialCustomDataRates);
568                                                 if (ptr)
569                                                 {
570                                                         memcpy(ptr, SerialCustomDataRates,
571                                                                         sizeof SerialCustomDataRates);
572                                                 }
573
574                                                 serialDevice[reader_index].ccid.arrayOfSupportedDataRates = ptr;
575                                         }
576                                         serialDevice[reader_index].ccid.dwMaxDataRate = 125000;
577                                         break;
578
579                                 case SEC1210:
580                                         serialDevice[reader_index].ccid.arrayOfSupportedDataRates = NULL;
581                                         serialDevice[reader_index].ccid.dwMaxDataRate = 826000;
582                                         break;
583
584                                 /* GemPC Twin or GemPC Card */
585                                 default:
586                                         serialDevice[reader_index].ccid.arrayOfSupportedDataRates = SerialTwinDataRates;
587                                         serialDevice[reader_index].ccid.dwMaxDataRate = 344086;
588                                         break;
589                         }
590                         goto end;
591                 }
592                 else
593                 {
594                         DEBUG_CRITICAL2("Trying to open too many slots on %s", dev_name);
595                         return STATUS_UNSUCCESSFUL;
596                 }
597
598         }
599
600         /* Common to all readers */
601         serialDevice[reader_index].ccid.real_bSeq = 0;
602         serialDevice[reader_index].ccid.pbSeq = &serialDevice[reader_index].ccid.real_bSeq;
603         serialDevice[reader_index].real_nb_opened_slots = 1;
604         serialDevice[reader_index].nb_opened_slots = &serialDevice[reader_index].real_nb_opened_slots;
605         serialDevice[reader_index].ccid.bCurrentSlotIndex = 0;
606
607         serialDevice[reader_index].ccid.dwMaxCCIDMessageLength = 271;
608         serialDevice[reader_index].ccid.dwMaxIFSD = 254;
609         serialDevice[reader_index].ccid.dwFeatures = 0x00010230;
610         serialDevice[reader_index].ccid.dwDefaultClock = 4000;
611
612         serialDevice[reader_index].buffer_offset = 0;
613         serialDevice[reader_index].buffer_offset_last = 0;
614
615         serialDevice[reader_index].ccid.readerID = readerID;
616         serialDevice[reader_index].ccid.bPINSupport = 0x0;
617         serialDevice[reader_index].ccid.dwMaxDataRate = 344086;
618         serialDevice[reader_index].ccid.bMaxSlotIndex = 0;
619         serialDevice[reader_index].ccid.arrayOfSupportedDataRates = SerialTwinDataRates;
620         serialDevice[reader_index].ccid.readTimeout = DEFAULT_COM_READ_TIMEOUT;
621         serialDevice[reader_index].ccid.dwSlotStatus = IFD_ICC_PRESENT;
622         serialDevice[reader_index].ccid.bVoltageSupport = 0x07; /* 1.8V, 3V and 5V */
623         serialDevice[reader_index].ccid.gemalto_firmware_features = NULL;
624 #ifdef ENABLE_ZLP
625         serialDevice[reader_index].ccid.zlp = FALSE;
626 #endif
627         serialDevice[reader_index].echo = TRUE;
628
629         /* change some values depending on the reader */
630         switch (readerID)
631         {
632                 case GEMCOREPOSPRO:
633                         serialDevice[reader_index].ccid.bMaxSlotIndex = 4;      /* 5 slots */
634                         serialDevice[reader_index].ccid.arrayOfSupportedDataRates = SerialExtendedDataRates;
635                         serialDevice[reader_index].echo = FALSE;
636                         serialDevice[reader_index].ccid.dwMaxDataRate = 500000;
637                         break;
638
639                 case GEMCORESIMPRO:
640                         serialDevice[reader_index].ccid.bMaxSlotIndex = 1; /* 2 slots */
641                         serialDevice[reader_index].ccid.arrayOfSupportedDataRates = SerialExtendedDataRates;
642                         serialDevice[reader_index].echo = FALSE;
643                         serialDevice[reader_index].ccid.dwMaxDataRate = 500000;
644                         break;
645
646                 case GEMCORESIMPRO2:
647                         serialDevice[reader_index].ccid.dwDefaultClock = 4800;
648                         serialDevice[reader_index].ccid.bMaxSlotIndex = 1; /* 2 slots */
649                         serialDevice[reader_index].ccid.arrayOfSupportedDataRates = SIMPro2DataRates;
650                         serialDevice[reader_index].echo = FALSE;
651                         serialDevice[reader_index].ccid.dwMaxDataRate = 825806;
652                         break;
653
654                 case GEMPCPINPAD:
655                         serialDevice[reader_index].ccid.bPINSupport = 0x03;
656                         serialDevice[reader_index].ccid.arrayOfSupportedDataRates = SerialExtendedDataRates;
657                         serialDevice[reader_index].ccid.dwMaxDataRate = 500000;
658                         break;
659
660                 case SEC1210:
661                         serialDevice[reader_index].ccid.dwFeatures = 0x000100B2;
662                         serialDevice[reader_index].ccid.dwDefaultClock = 4800;
663                         serialDevice[reader_index].ccid.dwMaxDataRate = 826000;
664                         serialDevice[reader_index].ccid.arrayOfSupportedDataRates = NULL;
665                         serialDevice[reader_index].ccid.bMaxSlotIndex = 1;      /* 2 slots */
666                         serialDevice[reader_index].echo = FALSE;
667                         break;
668
669         }
670
671 end:
672         /* memorise the current reader_index so we can detect
673          * a new OpenSerialByName on a multi slot reader */
674         previous_reader_index = reader_index;
675
676         /* we just created a secondary slot on a multi-slot reader */
677         if (already_used)
678                 return STATUS_SECONDARY_SLOT;
679
680         return STATUS_SUCCESS;
681 } /* set_ccid_descriptor  */
682
683
684 /*****************************************************************************
685  *
686  *                              OpenSerialByName: open the port
687  *
688  *****************************************************************************/
689 status_t OpenSerialByName(unsigned int reader_index, char *dev_name)
690 {
691         struct termios current_termios;
692         unsigned int reader = reader_index;
693         /* 255 is MAX_DEVICENAME in pcscd.h */
694         char reader_name[255] = "GemPCTwin";
695         char *p;
696         status_t ret;
697
698         DEBUG_COMM3("Reader index: %X, Device: %s", reader_index, dev_name);
699
700         /* parse dev_name using the pattern "device:name" */
701         p = strchr(dev_name, ':');
702         if (p)
703         {
704                 /* copy the second part of the string */
705                 strlcpy(reader_name, p+1, sizeof(reader_name));
706
707                 /* replace ':' by '\0' so that dev_name only contains the device name */
708                 *p = '\0';
709         }
710
711         ret = set_ccid_descriptor(reader_index, reader_name, dev_name);
712         if (STATUS_UNSUCCESSFUL == ret)
713                 return STATUS_UNSUCCESSFUL;
714
715         /* secondary slot so do not physically open the device */
716         if (STATUS_SECONDARY_SLOT == ret)
717                 return STATUS_SUCCESS;
718
719         serialDevice[reader].fd = open(dev_name, O_RDWR | O_NOCTTY);
720
721         if (-1 == serialDevice[reader].fd)
722         {
723                 DEBUG_CRITICAL3("open %s: %s", dev_name, strerror(errno));
724                 return STATUS_UNSUCCESSFUL;
725         }
726
727         /* Set RTS signal to low to prevent the smart card reader
728          * from sending its plug and play string. */
729         {
730                 int flags;
731
732                 if (ioctl(serialDevice[reader].fd, TIOCMGET, &flags) < 0)
733                 {
734                         DEBUG_CRITICAL2("Get RS232 signals state failed: %s",
735                                 strerror(errno));
736                 }
737                 else
738                 {
739                         flags &= ~TIOCM_RTS;
740                         if (ioctl(serialDevice[reader].fd, TIOCMSET, &flags) < 0)
741                         {
742                                 DEBUG_CRITICAL2("Set RTS to low failed: %s", strerror(errno));
743                         }
744                         else
745                         {
746                                 DEBUG_COMM("Plug-n-Play inhibition successful");
747                         }
748                 }
749         }
750
751         /* set channel used */
752         serialDevice[reader].device = strdup(dev_name);
753
754         /* empty in and out serial buffers */
755         if (tcflush(serialDevice[reader].fd, TCIOFLUSH))
756                         DEBUG_INFO2("tcflush() function error: %s", strerror(errno));
757
758         /* get config attributes */
759         if (tcgetattr(serialDevice[reader].fd, &current_termios) == -1)
760         {
761                 DEBUG_INFO2("tcgetattr() function error: %s", strerror(errno));
762                 (void)close(serialDevice[reader].fd);
763                 serialDevice[reader].fd = -1;
764
765                 return STATUS_UNSUCCESSFUL;
766         }
767
768         /* IGNBRK: ignore BREAK condition on input
769          * IGNPAR: ignore framing errors and parity errors. */
770         current_termios.c_iflag = IGNBRK | IGNPAR;
771         current_termios.c_oflag = 0;    /* Raw output modes */
772         /* CS8: 8-bits character size
773          * CSTOPB: set two stop bits
774          * CREAD: enable receiver
775          * CLOCAL: ignore modem control lines */
776         current_termios.c_cflag = CS8 | CSTOPB | CREAD | CLOCAL;
777
778         /* Do not echo characters because if you connect to a host it or your modem
779          * will echo characters for you.  Don't generate signals. */
780         current_termios.c_lflag = 0;
781
782         if (0 == strcasecmp(reader_name,"GemCoreSIMPro2"))
783         {
784                 unsigned char pcbuffer[SIZE_GET_SLOT_STATUS];
785                 unsigned int old_timeout;
786                 RESPONSECODE r;
787
788                 /* Unless we resume from a stand-by condition, GemCoreSIMPro2
789                  * starts at 9600 bauds, so let's first try this speed */
790                 /* set serial port speed to 9600 bauds */
791                 (void)cfsetspeed(&current_termios, B9600);
792                 DEBUG_INFO1("Set serial port baudrate to 9600 and correct configuration");
793                 if (tcsetattr(serialDevice[reader_index].fd, TCSANOW, &current_termios) == -1)
794                 {
795                         (void)close(serialDevice[reader_index].fd);
796                         serialDevice[reader_index].fd = -1;
797                         DEBUG_CRITICAL2("tcsetattr error: %s", strerror(errno));
798
799                         return STATUS_UNSUCCESSFUL;
800                 }
801
802                 /* Test current speed issuing a CmdGetSlotStatus with a very
803                  * short time out of 1 seconds */
804                 old_timeout = serialDevice[reader_index].ccid.readTimeout;
805
806                 serialDevice[reader_index].ccid.readTimeout = 1*1000;
807                 r = CmdGetSlotStatus(reader_index, pcbuffer);
808
809                 /* Restore default time out value */
810                 serialDevice[reader_index].ccid.readTimeout = old_timeout;
811
812                 if (IFD_SUCCESS == r)
813                 {
814                         /* We are at 9600 bauds, let's move to 115200 */
815                         unsigned char tx_buffer[] = { 0x01, 0x10, 0x20 };
816                         unsigned char rx_buffer[50];
817                         unsigned int rx_length = sizeof(rx_buffer);
818
819                         if (IFD_SUCCESS == CmdEscape(reader_index, tx_buffer,
820                                 sizeof(tx_buffer), rx_buffer, &rx_length, 0))
821                         {
822                                 /* Let the reader setup its new communication speed */
823                                 (void)usleep(250*1000);
824                         }
825                         else
826                         {
827                                 DEBUG_INFO1("CmdEscape to configure 115200 bauds failed");
828                         }
829                 }
830                 /* In case of a failure, reader is probably already at 115200
831                  * bauds as code below assumes */
832         }
833
834         /* set serial port speed to 115200 bauds */
835         (void)cfsetspeed(&current_termios, B115200);
836
837         DEBUG_INFO1("Set serial port baudrate to 115200 and correct configuration");
838         if (tcsetattr(serialDevice[reader].fd, TCSANOW, &current_termios) == -1)
839         {
840                 (void)close(serialDevice[reader].fd);
841                 serialDevice[reader].fd = -1;
842                 DEBUG_INFO2("tcsetattr error: %s", strerror(errno));
843
844                 return STATUS_UNSUCCESSFUL;
845         }
846
847         /* perform a command to be sure a Gemalto reader is connected
848          * get the reader firmware */
849         {
850                 unsigned char tx_buffer[1];
851                 unsigned char rx_buffer[50];
852                 unsigned int rx_length = sizeof(rx_buffer);
853
854                 if (0 == strcasecmp(reader_name,"SEC1210"))
855                         tx_buffer[0] = 0x06; // unknown but supported command
856                 else
857                         tx_buffer[0] = 0x02; // get reader firmware
858
859                 /* 2 seconds timeout to not wait too long if no reader is connected */
860                 if (IFD_SUCCESS != CmdEscape(reader_index, tx_buffer, sizeof(tx_buffer),
861                         rx_buffer, &rx_length, 2*1000))
862                 {
863                         DEBUG_CRITICAL("Get firmware failed. Maybe the reader is not connected");
864                         (void)CloseSerial(reader_index);
865                         return STATUS_UNSUCCESSFUL;
866                 }
867
868                 rx_buffer[rx_length] = '\0';
869                 DEBUG_INFO2("Firmware: %s", rx_buffer);
870         }
871
872         /* perform a command to configure GemPC Twin reader card movement
873          * notification to synchronous mode: the card movement is notified _after_
874          * the host command and _before_ the reader anwser */
875         if (0 != strcasecmp(reader_name,"SEC1210"))
876         {
877                 unsigned char tx_buffer[] = { 0x01, 0x01, 0x01};
878                 unsigned char rx_buffer[50];
879                 unsigned int rx_length = sizeof(rx_buffer);
880
881                 if (IFD_SUCCESS != CmdEscape(reader_index, tx_buffer, sizeof(tx_buffer),
882                         rx_buffer, &rx_length, 0))
883                 {
884                         DEBUG_CRITICAL("Change card movement notification failed.");
885                         (void)CloseSerial(reader_index);
886                         return STATUS_UNSUCCESSFUL;
887                 }
888         }
889
890         serialDevice[reader_index].ccid.sIFD_serial_number = NULL;
891         serialDevice[reader_index].ccid.sIFD_iManufacturer = NULL;
892         serialDevice[reader_index].ccid.IFD_bcdDevice = 0;
893
894         return STATUS_SUCCESS;
895 } /* OpenSerialByName */
896
897
898 /*****************************************************************************
899  *
900  *                              CloseSerial: close the port
901  *
902  *****************************************************************************/
903 status_t CloseSerial(unsigned int reader_index)
904 {
905         unsigned int reader = reader_index;
906
907         /* device not opened */
908         if (NULL == serialDevice[reader_index].device)
909                 return STATUS_UNSUCCESSFUL;
910
911         DEBUG_COMM2("Closing serial device: %s", serialDevice[reader_index].device);
912
913         /* Decrement number of opened slot */
914         (*serialDevice[reader_index].nb_opened_slots)--;
915
916         /* release the allocated ressources for the last slot only */
917         if (0 == *serialDevice[reader_index].nb_opened_slots)
918         {
919                 DEBUG_COMM("Last slot closed. Release resources");
920
921                 (void)close(serialDevice[reader].fd);
922                 serialDevice[reader].fd = -1;
923
924                 free(serialDevice[reader].device);
925                 serialDevice[reader].device = NULL;
926         }
927
928         return STATUS_SUCCESS;
929 } /* CloseSerial */
930
931
932 /*****************************************************************************
933  *
934  *                                      get_ccid_descriptor
935  *
936  ****************************************************************************/
937 _ccid_descriptor *get_ccid_descriptor(unsigned int reader_index)
938 {
939         return &serialDevice[reader_index].ccid;
940 } /* get_ccid_descriptor */
941
942