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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

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

Legend:
Removed from v.414  
changed lines
  Added in v.3270

  ViewVC Help
Powered by ViewVC 1.1.5