/[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 453 by rousseau, Fri Sep 19 12:08:09 2003 UTC revision 1046 by rousseau, Fri Jul 9 08:21:07 2004 UTC
# 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 <PCSC/ifdhandler.h>
36    
37  #include "pcscdefines.h"  #include "defs.h"
38    #include "ccid_ifdhandler.h"
39  #include "config.h"  #include "config.h"
40  #include "debug.h"  #include "debug.h"
41  #include "ccid.h"  #include "ccid.h"
42  #include "utils.h"  #include "utils.h"
43    #include "commands.h"
44    
45  /* communication timeout in seconds */  /* communication timeout in seconds */
46  #define SERIAL_TIMEOUT 2  #define SERIAL_TIMEOUT 2
# Line 102  typedef struct Line 105  typedef struct
105          int fd;          int fd;
106    
107          /*          /*
108           * channel used (1..4)           * device used ("/dev/ttyS?" under Linux)
109           */           */
110          int channel;          char *device;
111    
112          /*          /*
113           * serial communication buffer           * serial communication buffer
# Line 131  typedef struct Line 134  typedef struct
134  /* The _serialDevice structure must be defined before including ccid_serial.h */  /* The _serialDevice structure must be defined before including ccid_serial.h */
135  #include "ccid_serial.h"  #include "ccid_serial.h"
136    
137  static _serialDevice serialDevice[PCSCLITE_MAX_READERS] = {  /* no need to initialize to 0 since it is static */
138          [ 0 ... (PCSCLITE_MAX_READERS-1) ] = { -1, -1 }  static _serialDevice serialDevice[PCSCLITE_MAX_READERS];
 };  
139    
140  /*****************************************************************************  /*****************************************************************************
141   *   *
142   *                              WriteSerial: Send bytes to the card reader   *                              WriteSerial: Send bytes to the card reader
143   *   *
144   *****************************************************************************/   *****************************************************************************/
145  status_t WriteSerial(int lun, int length, unsigned char *buffer)  status_t WriteSerial(unsigned int lun, unsigned int length, unsigned char *buffer)
146  {  {
147          int i;          int i;
148          unsigned char lrc;          unsigned char lrc;
# Line 149  status_t WriteSerial(int lun, int length Line 151  status_t WriteSerial(int lun, int length
151  #ifdef DEBUG_LEVEL_COMM  #ifdef DEBUG_LEVEL_COMM
152          char debug_header[] = "-> 121234 ";          char debug_header[] = "-> 121234 ";
153    
154          sprintf(debug_header, "-> %06X ", (int)lun);          sprintf(debug_header, "-> %06X ", lun);
155  #endif  #endif
156    
157          if (length > GEMPCTWIN_MAXBUF-3)          if (length > GEMPCTWIN_MAXBUF-3)
158          {          {
159                  DEBUG_CRITICAL3("WriteSerial: command too long: %d for max %d",                  DEBUG_CRITICAL3("command too long: %d for max %d",
160                          length, GEMPCTWIN_MAXBUF-3);                          length, GEMPCTWIN_MAXBUF-3);
161                  return STATUS_UNSUCCESSFUL;                  return STATUS_UNSUCCESSFUL;
162          }          }
# Line 179  status_t WriteSerial(int lun, int length Line 181  status_t WriteSerial(int lun, int length
181          if (write(serialDevice[LunToReaderIndex(lun)].fd, low_level_buffer,          if (write(serialDevice[LunToReaderIndex(lun)].fd, low_level_buffer,
182                  length+3) != length+3)                  length+3) != length+3)
183          {          {
184                  DEBUG_CRITICAL2("WriteSerial: write error: %s", strerror(errno));                  DEBUG_CRITICAL2("write error: %s", strerror(errno));
185                  return STATUS_UNSUCCESSFUL;                  return STATUS_UNSUCCESSFUL;
186          }          }
187    
# Line 192  status_t WriteSerial(int lun, int length Line 194  status_t WriteSerial(int lun, int length
194   *                              ReadSerial: Receive bytes from the card reader   *                              ReadSerial: Receive bytes from the card reader
195   *   *
196   *****************************************************************************/   *****************************************************************************/
197  status_t ReadSerial(int lun, int *length, unsigned char *buffer)  status_t ReadSerial(unsigned int lun, unsigned int *length, unsigned char *buffer)
198  {  {
199          unsigned char c;          unsigned char c;
200          int rv;          int rv;
# Line 204  status_t ReadSerial(int lun, int *length Line 206  status_t ReadSerial(int lun, int *length
206          echo = TRUE;          echo = TRUE;
207    
208  start:  start:
209            DEBUG_COMM("start");
210          if ((rv = get_bytes(lun, &c, 1)) != STATUS_SUCCESS)          if ((rv = get_bytes(lun, &c, 1)) != STATUS_SUCCESS)
211                  return rv;                  return rv;
212    
# Line 214  start: Line 217  start:
217                  goto sync;                  goto sync;
218    
219          if (c >= 0x80)          if (c >= 0x80)
220            {
221                    DEBUG_COMM2("time request: 0x%02X", c);
222                  goto start;                  goto start;
223            }
224    
225          DEBUG_CRITICAL2("Got 0x%02X", c);          DEBUG_CRITICAL2("Got 0x%02X", c);
226          return STATUS_COMM_ERROR;          return STATUS_COMM_ERROR;
227    
228  slot_change:  slot_change:
229            DEBUG_COMM("slot change");
230          if ((rv = get_bytes(lun, &c, 1)) != STATUS_SUCCESS)          if ((rv = get_bytes(lun, &c, 1)) != STATUS_SUCCESS)
231                  return rv;                  return rv;
232    
233          if (c == CARD_ABSENT)          if (c == CARD_ABSENT)
234            {
235                  DEBUG_COMM("Card removed");                  DEBUG_COMM("Card removed");
236            }
237          else          else
238                  if (c == CARD_PRESENT)                  if (c == CARD_PRESENT)
239                    {
240                          DEBUG_COMM("Card inserted");                          DEBUG_COMM("Card inserted");
241                    }
242                  else                  else
243                          DEBUG_COMM2("Unknown card movement: %d", buffer[3]);                  {
244                            DEBUG_COMM2("Unknown card movement: %d", c);
245                    }
246          goto start;          goto start;
247    
248  sync:  sync:
249            DEBUG_COMM("sync");
250          if ((rv = get_bytes(lun, &c, 1)) != STATUS_SUCCESS)          if ((rv = get_bytes(lun, &c, 1)) != STATUS_SUCCESS)
251                  return rv;                  return rv;
252    
# Line 246  sync: Line 260  sync:
260          return STATUS_COMM_ERROR;          return STATUS_COMM_ERROR;
261    
262  nak:  nak:
263            DEBUG_COMM("nak");
264          if ((rv = get_bytes(lun, &c, 1)) != STATUS_SUCCESS)          if ((rv = get_bytes(lun, &c, 1)) != STATUS_SUCCESS)
265                  return rv;                  return rv;
266    
# Line 258  nak: Line 273  nak:
273                  goto start;                  goto start;
274    
275  ack:  ack:
276            DEBUG_COMM("ack");
277          /* normal CCID frame */          /* normal CCID frame */
278          if ((rv = get_bytes(lun, buffer, 5)) != STATUS_SUCCESS)          if ((rv = get_bytes(lun, buffer, 5)) != STATUS_SUCCESS)
279                  return rv;                  return rv;
# Line 265  ack: Line 281  ack:
281          /* total frame size */          /* total frame size */
282          to_read = 10+dw2i(buffer, 1);          to_read = 10+dw2i(buffer, 1);
283    
284            DEBUG_COMM2("frame size: %d", to_read);
285          if ((rv = get_bytes(lun, buffer+5, to_read-5)) != STATUS_SUCCESS)          if ((rv = get_bytes(lun, buffer+5, to_read-5)) != STATUS_SUCCESS)
286                  return rv;                  return rv;
287    
288    #ifdef DEBUG_LEVEL_COMM
289                    DEBUG_XXD("frame: ", buffer, to_read);
290    #endif
291    
292          /* lrc */          /* lrc */
293            DEBUG_COMM("lrc");
294          if ((rv = get_bytes(lun, &c, 1)) != STATUS_SUCCESS)          if ((rv = get_bytes(lun, &c, 1)) != STATUS_SUCCESS)
295                  return rv;                  return rv;
296    
297            DEBUG_COMM2("lrc: 0x%02X", c);
298          for (i=0; i<to_read; i++)          for (i=0; i<to_read; i++)
299                  c ^= buffer[i];                  c ^= buffer[i];
300    
301          if (c != (SYNC ^ CTRL_ACK))          if (c != (SYNC ^ CTRL_ACK))
         {  
302                  DEBUG_CRITICAL2("Wrong LRC: 0x%02X", c);                  DEBUG_CRITICAL2("Wrong LRC: 0x%02X", c);
                 //return STATUS_COMM_ERROR;  
         }  
303    
304          if (echo)          if (echo)
305          {          {
# Line 296  ack: Line 316  ack:
316   *                              get_bytes: get n bytes   *                              get_bytes: get n bytes
317   *   *
318   *****************************************************************************/   *****************************************************************************/
319  int get_bytes(int lun, unsigned char *buffer, int length)  int get_bytes(unsigned int lun, unsigned char *buffer, int length)
320  {  {
321          int offset = serialDevice[LunToReaderIndex(lun)].buffer_offset;          int offset = serialDevice[LunToReaderIndex(lun)].buffer_offset;
322          int offset_last = serialDevice[LunToReaderIndex(lun)].buffer_offset_last;          int offset_last = serialDevice[LunToReaderIndex(lun)].buffer_offset_last;
323    
324            DEBUG_COMM3("available: %d, needed: %d", offset_last-offset,
325                    length);
326          /* enough data are available */          /* enough data are available */
327          if (offset + length <= offset_last)          if (offset + length <= offset_last)
328          {          {
329                    DEBUG_COMM("data available");
330                  memcpy(buffer, serialDevice[LunToReaderIndex(lun)].buffer + offset, length);                  memcpy(buffer, serialDevice[LunToReaderIndex(lun)].buffer + offset, length);
331                  serialDevice[LunToReaderIndex(lun)].buffer_offset += length;                  serialDevice[LunToReaderIndex(lun)].buffer_offset += length;
332          }          }
# Line 315  int get_bytes(int lun, unsigned char *bu Line 338  int get_bytes(int lun, unsigned char *bu
338                  present = offset_last - offset;                  present = offset_last - offset;
339    
340                  if (present > 0)                  if (present > 0)
341                          memcpy(buffer, serialDevice[LunToReaderIndex(lun)].buffer + offset, present);                  {
342                            DEBUG_COMM2("some data available: %d", present);
343                            memcpy(buffer, serialDevice[LunToReaderIndex(lun)].buffer + offset,
344                                    present);
345                    }
346    
347                  /* get fresh data */                  /* get fresh data */
348                    DEBUG_COMM2("get more data: %d", length - present);
349                  rv = ReadChunk(lun, serialDevice[LunToReaderIndex(lun)].buffer, sizeof(serialDevice[LunToReaderIndex(lun)].buffer), length - present);                  rv = ReadChunk(lun, serialDevice[LunToReaderIndex(lun)].buffer, sizeof(serialDevice[LunToReaderIndex(lun)].buffer), length - present);
350                  if (rv < 0)                  if (rv < 0)
351                          return STATUS_COMM_ERROR;                          return STATUS_COMM_ERROR;
# Line 327  int get_bytes(int lun, unsigned char *bu Line 355  int get_bytes(int lun, unsigned char *bu
355                          length - present);                          length - present);
356                  serialDevice[LunToReaderIndex(lun)].buffer_offset = length - present;                  serialDevice[LunToReaderIndex(lun)].buffer_offset = length - present;
357                  serialDevice[LunToReaderIndex(lun)].buffer_offset_last = rv;                  serialDevice[LunToReaderIndex(lun)].buffer_offset_last = rv;
358                    DEBUG_COMM3("offset: %d, last_offset: %d",
359                            serialDevice[LunToReaderIndex(lun)].buffer_offset,
360                            serialDevice[LunToReaderIndex(lun)].buffer_offset_last);
361          }          }
362    
 DEBUG_XXD("pouet: ", buffer, length);  
   
363          return STATUS_SUCCESS;          return STATUS_SUCCESS;
364  } /* get_bytes */  } /* get_bytes */
365    
# Line 340  DEBUG_XXD("pouet: ", buffer, length); Line 369  DEBUG_XXD("pouet: ", buffer, length);
369   *                              ReadChunk: read a minimum number of bytes   *                              ReadChunk: read a minimum number of bytes
370   *   *
371   *****************************************************************************/   *****************************************************************************/
372  int ReadChunk(int lun, unsigned char *buffer, int buffer_length, int min_length)  int ReadChunk(unsigned int lun, unsigned char *buffer, int buffer_length, int min_length)
373  {  {
374          int fd = serialDevice[LunToReaderIndex(lun)].fd;          int fd = serialDevice[LunToReaderIndex(lun)].fd;
375    # ifndef S_SPLINT_S
376          fd_set fdset;          fd_set fdset;
377    # endif
378          struct timeval t;          struct timeval t;
379          int i, rv;          int i, rv = 0;
380            int already_read;
381  #ifdef DEBUG_LEVEL_COMM  #ifdef DEBUG_LEVEL_COMM
382          char debug_header[] = "<- 121234 ";          char debug_header[] = "<- 121234 ";
383    
384          sprintf(debug_header, "<- %06X ", (int)lun);          sprintf(debug_header, "<- %06X ", lun);
385  #endif  #endif
386    
387          /* use select() to, eventually, timeout */          already_read = 0;
388          FD_ZERO(&fdset);          while (already_read < min_length)
         FD_SET(fd, &fdset);  
         t.tv_sec = SERIAL_TIMEOUT;  
         t.tv_usec = 0;  
   
         i = select(fd+1, &fdset, NULL, NULL, &t);  
         if (i == -1)  
389          {          {
390                  DEBUG_CRITICAL2("select: %s", strerror(errno));                  /* use select() to, eventually, timeout */
391                  return -1;                  FD_ZERO(&fdset);
392          }                  FD_SET(fd, &fdset);
393          else                  t.tv_sec = SERIAL_TIMEOUT;
394                  if (i == 0)                  t.tv_usec = 0;
395    
396                    i = select(fd+1, &fdset, NULL, NULL, &t);
397                    if (i == -1)
398                  {                  {
399                          DEBUG_COMM2("Timeout! (%d sec)", SERIAL_TIMEOUT);                          DEBUG_CRITICAL2("select: %s", strerror(errno));
400                          return -1;                          return -1;
401                  }                  }
402                    else
403                            if (i == 0)
404                            {
405                                    DEBUG_COMM2("Timeout! (%d sec)", SERIAL_TIMEOUT);
406                                    return -1;
407                            }
408    
409          rv = read(fd, buffer, buffer_length);                  rv = read(fd, buffer + already_read, buffer_length - already_read);
410          if (rv < 0)                  if (rv < 0)
411          {                  {
412                  DEBUG_COMM2("read error: %s", strerror(errno));                          DEBUG_COMM2("read error: %s", strerror(errno));
413                  return -1;                          return -1;
414          }                  }
415    
416  #ifdef DEBUG_LEVEL_COMM  #ifdef DEBUG_LEVEL_COMM
417          DEBUG_XXD(debug_header, buffer, rv);                  DEBUG_XXD(debug_header, buffer + already_read, rv);
418  #endif  #endif
419    
420          /* too short */                  already_read += rv;
421          if (rv < min_length)                  DEBUG_COMM3("read: %d, to read: %d", already_read,
         {  
                 DEBUG_COMM3("ReadSerial: only %d byte(s) read, needed %d", rv,  
422                          min_length);                          min_length);
   
                 return -1;  
423          }          }
424    
425          return rv;          return already_read;
426  } /* ReadChunk */  } /* ReadChunk */
427    
428    
# Line 400  int ReadChunk(int lun, unsigned char *bu Line 431  int ReadChunk(int lun, unsigned char *bu
431   *                              OpenSerial: open the port   *                              OpenSerial: open the port
432   *   *
433   *****************************************************************************/   *****************************************************************************/
434  status_t OpenSerial(int lun, int channel)  status_t OpenSerial(unsigned int lun, int channel)
435  {  {
436          char dev_name[FILENAME_MAX];          char dev_name[FILENAME_MAX];
         struct termios current_termios;  
         int i;  
         int reader = LunToReaderIndex(lun);  
437    
438          DEBUG_COMM3("OpenSerial: Lun: %X, Channel: %d", lun, channel);          DEBUG_COMM3("Lun: %X, Channel: %d", lun, channel);
439    
440          /*          /*
441           * Conversion of old-style ifd-hanler 1.0 CHANNELID           * Conversion of old-style ifd-hanler 1.0 CHANNELID
# Line 432  status_t OpenSerial(int lun, int channel Line 460  status_t OpenSerial(int lun, int channel
460    
461          sprintf(dev_name, "/dev/pcsc/%d", (int) channel);          sprintf(dev_name, "/dev/pcsc/%d", (int) channel);
462    
463            return OpenSerialByName(lun, dev_name);
464    } /* OpenSerial */
465    
466    /*****************************************************************************
467     *
468     *                              OpenSerialByName: open the port
469     *
470     *****************************************************************************/
471    status_t OpenSerialByName(unsigned int lun, char *dev_name)
472    {
473            struct termios current_termios;
474            int i;
475            int reader = LunToReaderIndex(lun);
476    
477            DEBUG_COMM3("Lun: %X, Device: %d", lun, dev_name);
478    
479          /* check if the same channel is not already used */          /* check if the same channel is not already used */
480          for (i=0; i<PCSCLITE_MAX_READERS; i++)          for (i=0; i<PCSCLITE_MAX_READERS; i++)
481          {          {
482                  if (serialDevice[i].channel == channel)                  if (serialDevice[i].device &&
483                            strcmp(serialDevice[i].device, dev_name) == 0)
484                  {                  {
485                          DEBUG_CRITICAL2("Channel %s already in use", dev_name);                          DEBUG_CRITICAL2("Device %s already in use", dev_name);
486                          return STATUS_UNSUCCESSFUL;                          return STATUS_UNSUCCESSFUL;
487                  }                  }
488          }          }
489    
490          serialDevice[reader].fd = open(dev_name, O_RDWR | O_NOCTTY);          serialDevice[reader].fd = open(dev_name, O_RDWR | O_NOCTTY);
491    
492          if (serialDevice[reader].fd <= 0)          if (-1 == serialDevice[reader].fd)
493          {          {
494                  DEBUG_CRITICAL3("open %s: %s", dev_name, strerror(errno));                  DEBUG_CRITICAL3("open %s: %s", dev_name, strerror(errno));
495                  return STATUS_UNSUCCESSFUL;                  return STATUS_UNSUCCESSFUL;
496          }          }
497    
498          /* set channel used */          /* set channel used */
499          serialDevice[reader].channel = channel;          serialDevice[reader].device = strdup(dev_name);
500    
501          /* empty in and out serial buffers */          /* empty in and out serial buffers */
502          if (tcflush(serialDevice[reader].fd, TCIOFLUSH))          if (tcflush(serialDevice[reader].fd, TCIOFLUSH))
# Line 497  status_t OpenSerial(int lun, int channel Line 542  status_t OpenSerial(int lun, int channel
542          serialDevice[reader].ccid.bSeq = 0;          serialDevice[reader].ccid.bSeq = 0;
543          serialDevice[reader].ccid.readerID = GEMPCTWIN;          serialDevice[reader].ccid.readerID = GEMPCTWIN;
544          serialDevice[reader].ccid.dwMaxCCIDMessageLength = 271;          serialDevice[reader].ccid.dwMaxCCIDMessageLength = 271;
545            serialDevice[reader].ccid.dwMaxIFSD = 254;
546          serialDevice[reader].ccid.dwFeatures = 0x00010230;          serialDevice[reader].ccid.dwFeatures = 0x00010230;
547            serialDevice[reader].ccid.bPINSupport = 0x0;
548            serialDevice[reader].ccid.dwDefaultClock = 4000;
549            serialDevice[reader].ccid.dwMaxDataRate = 344086;
550    
551          serialDevice[reader].buffer_offset = 0;          serialDevice[reader].buffer_offset = 0;
552          serialDevice[reader].buffer_offset_last = 0;          serialDevice[reader].buffer_offset_last = 0;
553    
554          ccid_open_hack(lun);          /* perform a command to be sure a GemPC Twin reader is connected
555             * get the reader firmware */
556            {
557                    char tx_buffer[] = "\x02";
558                    char rx_buffer[50];
559                    int rx_length = sizeof(rx_buffer);
560    
561                    if (IFD_SUCCESS != CmdEscape(lun, tx_buffer, sizeof(tx_buffer),
562                            rx_buffer, &rx_length))
563                    {
564                            DEBUG_CRITICAL("Get firmware failed. Maybe the reader is not co,,ected");
565                            return STATUS_UNSUCCESSFUL;
566                    }
567    
568                    rx_buffer[rx_length] = '\0';
569                    DEBUG_INFO2("Firmware: %s", rx_buffer);
570            }
571    
572          return STATUS_SUCCESS;          return STATUS_SUCCESS;
573  } /* OpenSerial */  } /* OpenSerialByName */
574    
575    
576  /*****************************************************************************  /*****************************************************************************
# Line 513  status_t OpenSerial(int lun, int channel Line 578  status_t OpenSerial(int lun, int channel
578   *                              CloseSerial: close the port   *                              CloseSerial: close the port
579   *   *
580   *****************************************************************************/   *****************************************************************************/
581  status_t CloseSerial(int lun)  status_t CloseSerial(unsigned int lun)
582  {  {
583          int reader = LunToReaderIndex(lun);          int reader = LunToReaderIndex(lun);
584    
585          close(serialDevice[reader].fd);          close(serialDevice[reader].fd);
   
586          serialDevice[reader].fd = -1;          serialDevice[reader].fd = -1;
587          serialDevice[reader].channel = -1;  
588            free(serialDevice[reader].device);
589            serialDevice[reader].device = NULL;
590    
591          return STATUS_SUCCESS;          return STATUS_SUCCESS;
592  } /* CloseSerial */  } /* CloseSerial */
# Line 531  status_t CloseSerial(int lun) Line 597  status_t CloseSerial(int lun)
597   *                                      get_ccid_descriptor   *                                      get_ccid_descriptor
598   *   *
599   ****************************************************************************/   ****************************************************************************/
600  _ccid_descriptor *get_ccid_descriptor(int lun)  _ccid_descriptor *get_ccid_descriptor(unsigned int lun)
601  {  {
602          return &serialDevice[LunToReaderIndex(lun)].ccid;          return &serialDevice[LunToReaderIndex(lun)].ccid;
603  } /* get_ccid_descriptor */  } /* get_ccid_descriptor */

Legend:
Removed from v.453  
changed lines
  Added in v.1046

  ViewVC Help
Powered by ViewVC 1.1.5