/[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 900 by rousseau, Tue May 25 14:46:02 2004 UTC
# Line 33  Line 33 
33  #include <sys/time.h>  #include <sys/time.h>
34  #include <sys/types.h>  #include <sys/types.h>
35    
36  #include "pcscdefines.h"  #include "defs.h"
37    #include "ccid_ifdhandler.h"
38  #include "config.h"  #include "config.h"
39  #include "debug.h"  #include "debug.h"
40  #include "ccid.h"  #include "ccid.h"
41  #include "utils.h"  #include "utils.h"
42    
43  /* communication timeout in seconds */  /* communication timeout in seconds */
44  #define SERIAL_TIMEOUT 10  #define SERIAL_TIMEOUT 2
45    
46  #define SYNC 0x03  #define SYNC 0x03
47  #define CTRL_ACK 0x06  #define CTRL_ACK 0x06
# Line 67  Line 68 
68   * 1 : LRC (0x16)   * 1 : LRC (0x16)
69   *   *
70   * Card insertion/withdrawal   * Card insertion/withdrawal
  * 1 : SYNC  
  * 1 : CTRL  
71   * 1 : RDR_to_PC_NotifySlotChange (0x50)   * 1 : RDR_to_PC_NotifySlotChange (0x50)
72   * 1 : bmSlotIccState   * 1 : bmSlotIccState
73   *     0x02 if card absent   *     0x02 if card absent
74   *     0x03 is card present   *     0x03 is card present
  * 1 : LRC  
75   *   *
76   * Time request   * Time request
77   * T=1 : normal CCID command   * T=1 : normal CCID command
# Line 81  Line 79 
79   *   *
80   */   */
81    
82    /*
83     * You may get read timeout after a card movement.
84     * This is because you will get the echo of the CCID command
85     * but not the result of the command.
86     *
87     * This is not an applicative issue since the card is either removed (and
88     * powered off) or just inserted (and not yet powered on).
89     */
90    
91    /* 271 = max size for short APDU
92     * 2 bytes for header
93     * 1 byte checksum
94     * doubled for echo
95     */
96    #define GEMPCTWIN_MAXBUF (271 +2 +1) * 2
97    
98  typedef struct  typedef struct
99  {  {
100          /*          /*
# Line 89  typedef struct Line 103  typedef struct
103          int fd;          int fd;
104    
105          /*          /*
106           * channel used (1..4)           * device used ("/dev/ttyS?" under Linux)
107             */
108            char *device;
109    
110            /*
111             * serial communication buffer
112           */           */
113          int channel;          unsigned char buffer[GEMPCTWIN_MAXBUF];
114    
115            /*
116             * next available byte
117             */
118            int buffer_offset;
119    
120            /*
121             * number of available bytes
122             */
123            int buffer_offset_last;
124    
125          /*          /*
126           * CCID infos common to USB and serial           * CCID infos common to USB and serial
# Line 103  typedef struct Line 132  typedef struct
132  /* The _serialDevice structure must be defined before including ccid_serial.h */  /* The _serialDevice structure must be defined before including ccid_serial.h */
133  #include "ccid_serial.h"  #include "ccid_serial.h"
134    
135  static _serialDevice serialDevice[PCSCLITE_MAX_READERS] = {  /* no need to initialize to 0 since it is static */
136          [ 0 ... (PCSCLITE_MAX_READERS-1) ] = { -1, -1 }  static _serialDevice serialDevice[PCSCLITE_MAX_READERS];
 };  
   
 /* 271 = max size for short APDU  
  * 2 bytes for header  
  * 1 byte checksum  
  * doubled for echo */  
 #define GEMPCTWIN_MAXBUF (271 +2 +1) *2  
137    
138  /*****************************************************************************  /*****************************************************************************
139   *   *
140   *                              WriteSerial: Send bytes to the card reader   *                              WriteSerial: Send bytes to the card reader
141   *   *
142   *****************************************************************************/   *****************************************************************************/
143  status_t WriteSerial(int lun, int length, unsigned char *buffer)  status_t WriteSerial(int lun, unsigned int length, unsigned char *buffer)
144  {  {
145          int i;          int i;
         int reader = LunToReaderIndex(lun);  
146          unsigned char lrc;          unsigned char lrc;
147          unsigned char low_level_buffer[GEMPCTWIN_MAXBUF];          unsigned char low_level_buffer[GEMPCTWIN_MAXBUF];
148    
# Line 133  status_t WriteSerial(int lun, int length Line 154  status_t WriteSerial(int lun, int length
154    
155          if (length > GEMPCTWIN_MAXBUF-3)          if (length > GEMPCTWIN_MAXBUF-3)
156          {          {
157                  DEBUG_CRITICAL3("WriteSerial: command too long: %d for max %d",                  DEBUG_CRITICAL3("command too long: %d for max %d",
158                          length, GEMPCTWIN_MAXBUF-3);                          length, GEMPCTWIN_MAXBUF-3);
159                  return STATUS_UNSUCCESSFUL;                  return STATUS_UNSUCCESSFUL;
160          }          }
# Line 155  status_t WriteSerial(int lun, int length Line 176  status_t WriteSerial(int lun, int length
176          DEBUG_XXD(debug_header, low_level_buffer, length+3);          DEBUG_XXD(debug_header, low_level_buffer, length+3);
177  #endif  #endif
178    
179          if (write(serialDevice[reader].fd, low_level_buffer, length+3) != length+3)          if (write(serialDevice[LunToReaderIndex(lun)].fd, low_level_buffer,
180                    length+3) != length+3)
181          {          {
182                  DEBUG_CRITICAL2("WriteSerial: write error: %s", strerror(errno));                  DEBUG_CRITICAL2("write error: %s", strerror(errno));
183                  return STATUS_UNSUCCESSFUL;                  return STATUS_UNSUCCESSFUL;
184          }          }
185    
# Line 170  status_t WriteSerial(int lun, int length Line 192  status_t WriteSerial(int lun, int length
192   *                              ReadSerial: Receive bytes from the card reader   *                              ReadSerial: Receive bytes from the card reader
193   *   *
194   *****************************************************************************/   *****************************************************************************/
195  status_t ReadSerial(int lun, int *length, unsigned char *buffer)  status_t ReadSerial(int lun, unsigned int *length, unsigned char *buffer)
196  {  {
197          int fd = serialDevice[LunToReaderIndex(lun)].fd;          unsigned char c;
198          static unsigned char low_level_buffer[GEMPCTWIN_MAXBUF];          int rv;
199          int buffer_size, len, rv, already_read, to_read;          int echo;
200          unsigned char *reader_to_pc;          int to_read;
201          unsigned char lrc;          int i;
         int skipped, i;  
 #ifdef DEBUG_LEVEL_COMM  
         char debug_header[] = "<- 121234 ";  
   
         sprintf(debug_header, "<- %06X ", (int)lun);  
 #endif  
   
         buffer_size = *length;  
202    
203          /* error by default (zero length) */          /* we get the echo first */
204          *length = 0;          echo = TRUE;
205    
206          rv = ReadChunk(fd, low_level_buffer, sizeof(low_level_buffer), 3, lun);  start:
207          if (rv < 0)          DEBUG_COMM("start");
208                  return STATUS_UNSUCCESSFUL;          if ((rv = get_bytes(lun, &c, 1)) != STATUS_SUCCESS)
209                    return rv;
210    
211          /* Nb of bytes already read */          if (c == RDR_to_PC_NotifySlotChange)
212          already_read = rv;                  goto slot_change;
213    
214  #ifdef DEBUG_LEVEL_COMM          if (c == SYNC)
215          DEBUG_XXD(debug_header, low_level_buffer, rv);                  goto sync;
 #endif  
216    
217          /* skip the echo of the previous command */          if (c >= 0x80)
218          skipped = skip_echo(low_level_buffer, sizeof(low_level_buffer));          {
219          if (skipped == 0)                  DEBUG_COMM2("time request: 0x%02X", c);
220                  return STATUS_UNSUCCESSFUL;                  goto start;
221            }
222    
223          /* Nb of bytes until the end of the buffer */          DEBUG_CRITICAL2("Got 0x%02X", c);
224          len = sizeof(low_level_buffer) - skipped;          return STATUS_COMM_ERROR;
         already_read -= skipped;  
         reader_to_pc = low_level_buffer + skipped;  
225    
226          to_read = 2 +1; /* minimal frame size */  slot_change:
227            DEBUG_COMM("slot change");
228            if ((rv = get_bytes(lun, &c, 1)) != STATUS_SUCCESS)
229                    return rv;
230    
231          while (already_read < to_read)          if (c == CARD_ABSENT)
232          {          {
233                  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;  
234          }          }
235            else
236                    if (c == CARD_PRESENT)
237                    {
238                            DEBUG_COMM("Card inserted");
239                    }
240                    else
241                    {
242                            DEBUG_COMM2("Unknown card movement: %d", buffer[3]);
243                    }
244            goto start;
245    
246          if (reader_to_pc[0] != SYNC)  sync:
247          {          DEBUG_COMM("sync");
248                  DEBUG_CRITICAL2("No SYNC byte found: 0x%02X", buffer[0]);          if ((rv = get_bytes(lun, &c, 1)) != STATUS_SUCCESS)
249                  return STATUS_UNSUCCESSFUL;                  return rv;
         }  
250    
251          if (reader_to_pc[1] != CTRL_ACK)          if (c == CTRL_ACK)
252          {                  goto ack;
                 DEBUG_CRITICAL2("No ACK byte found: 0x%02X", buffer[0]);  
                 return 0;  
         }  
253    
254          /* read up to CCID frame length */          if (c == CTRL_NAK)
255          to_read = 5; /* bMessageType + dwLength */                  goto nak;
         while (already_read < to_read)  
         {  
                 rv = ReadChunk(fd, reader_to_pc + already_read, len, 1, lun);  
                 if (rv < 0)  
                         return STATUS_UNSUCCESSFUL;  
256    
257                  already_read += rv;          DEBUG_CRITICAL2("Got 0x%02X instead of ACK/NAK", c);
258                  len -= rv;          return STATUS_COMM_ERROR;
         }  
259    
260          /* normal CCID command */  nak:
261          to_read = 10+3+dw2i(reader_to_pc, 3);          DEBUG_COMM("nak");
262            if ((rv = get_bytes(lun, &c, 1)) != STATUS_SUCCESS)
263                    return rv;
264    
265          while (already_read < to_read)          if (c != (SYNC ^ CTRL_NAK))
266          {          {
267                  rv = ReadChunk(fd, reader_to_pc + already_read, len, 1, lun);                  DEBUG_CRITICAL2("Wrong LRC: 0x%02X", c);
268                  if (rv < 0)                  return STATUS_COMM_ERROR;
                         return STATUS_UNSUCCESSFUL;  
   
                 already_read += rv;  
                 len -= rv;  
269          }          }
270            else
271                    goto start;
272    
273          lrc = 0;  ack:
274          for (i=0; i<to_read; i++)          DEBUG_COMM("ack");
275                  lrc ^= reader_to_pc[i];          /* normal CCID frame */
276            if ((rv = get_bytes(lun, buffer, 5)) != STATUS_SUCCESS)
277          if (lrc != 0)                  return rv;
278                  DEBUG_CRITICAL2("Wrong lrc: 0x%02X", lrc);  
279            /* total frame size */
280            to_read = 10+dw2i(buffer, 1);
281    
282            DEBUG_COMM2("frame size: %d", to_read);
283            if ((rv = get_bytes(lun, buffer+5, to_read-5)) != STATUS_SUCCESS)
284                    return rv;
285    
286  #ifdef DEBUG_LEVEL_COMM  #ifdef DEBUG_LEVEL_COMM
287          DEBUG_XXD(debug_header, reader_to_pc, to_read);                  DEBUG_XXD("frame: ", buffer, to_read);
288  #endif  #endif
289    
290          /* copy up to buffer_size bytes */          /* lrc */
291          *length = to_read-3;          DEBUG_COMM("lrc");
292            if ((rv = get_bytes(lun, &c, 1)) != STATUS_SUCCESS)
293                    return rv;
294    
295          memcpy(buffer, reader_to_pc+2, *length);          DEBUG_COMM2("lrc: 0x%02X", c);
296            for (i=0; i<to_read; i++)
297                    c ^= buffer[i];
298    
299            if (c != (SYNC ^ CTRL_ACK))
300                    DEBUG_CRITICAL2("Wrong LRC: 0x%02X", c);
301    
302            if (echo)
303            {
304                    echo = FALSE;
305                    goto start;
306            }
307    
308          return STATUS_SUCCESS;          return STATUS_SUCCESS;
309  } /* ReadSerial */  } /* ReadSerial */
# Line 281  status_t ReadSerial(int lun, int *length Line 311  status_t ReadSerial(int lun, int *length
311    
312  /*****************************************************************************  /*****************************************************************************
313   *   *
314   *                              skip_echo: skip the echo of the previous command   *                              get_bytes: get n bytes
315   *   *
316   *****************************************************************************/   *****************************************************************************/
317  int skip_echo(unsigned char *buffer, int buffer_length)  int get_bytes(int lun, unsigned char *buffer, int length)
318  {  {
319          unsigned char lrc;          int offset = serialDevice[LunToReaderIndex(lun)].buffer_offset;
320          int i;          int offset_last = serialDevice[LunToReaderIndex(lun)].buffer_offset_last;
321    
322          if (buffer[0] != SYNC)          DEBUG_COMM3("available: %d, needed: %d", offset_last-offset,
323          {                  length);
324                  DEBUG_CRITICAL2("No SYNC byte found: 0x%02X", buffer[0]);          /* enough data are available */
325                  return 0;          if (offset + length <= offset_last)
326            {
327                    DEBUG_COMM("data available");
328                    memcpy(buffer, serialDevice[LunToReaderIndex(lun)].buffer + offset, length);
329                    serialDevice[LunToReaderIndex(lun)].buffer_offset += length;
330          }          }
331            else
         if (buffer[1] != CTRL_ACK)  
332          {          {
333                  DEBUG_CRITICAL2("No ACK byte found: 0x%02X", buffer[0]);                  int present, rv;
                 return 0;  
         }  
334    
335          if (buffer[2] == RDR_to_PC_NotifySlotChange)                  /* copy available data */
336          {                  present = offset_last - offset;
337                  switch (buffer[3])  
338                    if (present > 0)
339                  {                  {
340                          case CARD_PRESENT:                          DEBUG_COMM2("some data available: %d", present);
341                                  DEBUG_INFO("Card inserted");                          memcpy(buffer, serialDevice[LunToReaderIndex(lun)].buffer + offset,
342                                  break;                                  present);
   
                         case CARD_ABSENT:  
                                 DEBUG_INFO("Card removed");  
                                 break;  
   
                         default:  
                                 DEBUG_INFO2("Unknown card movement: %d", buffer[3]);  
                                 break;  
343                  }                  }
   
                 lrc = 0;  
                 for (i=0; i<5; i++)  
                         lrc ^= buffer[i];  
344    
345                  if (lrc != 0)                  /* get fresh data */
346                          DEBUG_CRITICAL2("Wrong lrc: 0x%02", lrc);                  DEBUG_COMM2("get more data: %d", length - present);
347                    rv = ReadChunk(lun, serialDevice[LunToReaderIndex(lun)].buffer, sizeof(serialDevice[LunToReaderIndex(lun)].buffer), length - present);
348                    if (rv < 0)
349                            return STATUS_COMM_ERROR;
350    
351                  /* Card insertion/withdrawal */                  /* fill the buffer */
352                  return 5;                  memcpy(buffer + present, serialDevice[LunToReaderIndex(lun)].buffer,
353                            length - present);
354                    serialDevice[LunToReaderIndex(lun)].buffer_offset = length - present;
355                    serialDevice[LunToReaderIndex(lun)].buffer_offset_last = rv;
356                    DEBUG_COMM3("offset: %d, last_offset: %d",
357                            serialDevice[LunToReaderIndex(lun)].buffer_offset,
358                            serialDevice[LunToReaderIndex(lun)].buffer_offset_last);
359          }          }
360    
361          /* normal CCID command, 2 for SYNC CTRL, 1 for length offset in CCID cmd */          return STATUS_SUCCESS;
362          return 2 + 10 + dw2i(buffer, 2 +1) +1;  } /* get_bytes */
 } /* skip_echo */  
363    
364    
365  /*****************************************************************************  /*****************************************************************************
# Line 339  int skip_echo(unsigned char *buffer, int Line 367  int skip_echo(unsigned char *buffer, int
367   *                              ReadChunk: read a minimum number of bytes   *                              ReadChunk: read a minimum number of bytes
368   *   *
369   *****************************************************************************/   *****************************************************************************/
370  int ReadChunk(int fd, unsigned char *buffer, int buffer_length, int min_length, int lun)  int ReadChunk(int lun, unsigned char *buffer, int buffer_length, int min_length)
371  {  {
372            int fd = serialDevice[LunToReaderIndex(lun)].fd;
373          fd_set fdset;          fd_set fdset;
374          struct timeval t;          struct timeval t;
375          int i, rv;          int i, rv = 0;
376            int already_read;
377  #ifdef DEBUG_LEVEL_COMM  #ifdef DEBUG_LEVEL_COMM
378          char debug_header[] = "<- 121234 ";          char debug_header[] = "<- 121234 ";
379    
380          sprintf(debug_header, "<- %06X ", (int)lun);          sprintf(debug_header, "<- %06X ", (int)lun);
381  #endif  #endif
382    
383  time_request:          already_read = 0;
384          /* use select() to, eventually, timeout */          while (already_read < min_length)
         FD_ZERO(&fdset);  
         FD_SET(fd, &fdset);  
         t.tv_sec = SERIAL_TIMEOUT;  
         t.tv_usec = 0;  
   
         i = select(fd+1, &fdset, NULL, NULL, &t);  
         if (i == -1)  
385          {          {
386                  DEBUG_CRITICAL2("select: %s", strerror(errno));                  /* use select() to, eventually, timeout */
387                  return -1;                  FD_ZERO(&fdset);
388          }                  FD_SET(fd, &fdset);
389          else                  t.tv_sec = SERIAL_TIMEOUT;
390                  if (i == 0)                  t.tv_usec = 0;
391    
392                    i = select(fd+1, &fdset, NULL, NULL, &t);
393                    if (i == -1)
394                  {                  {
395                          DEBUG_COMM2("Timeout! (%d sec)", SERIAL_TIMEOUT);                          DEBUG_CRITICAL2("select: %s", strerror(errno));
396                          return -1;                          return -1;
397                  }                  }
398                    else
399                            if (i == 0)
400                            {
401                                    DEBUG_COMM2("Timeout! (%d sec)", SERIAL_TIMEOUT);
402                                    return -1;
403                            }
404    
405          rv = read(fd, buffer, buffer_length);                  rv = read(fd, buffer + already_read, buffer_length - already_read);
406          if (rv < 0)                  if (rv < 0)
407          {                  {
408                  DEBUG_COMM2("read error: %s", strerror(errno));                          DEBUG_COMM2("read error: %s", strerror(errno));
409                  return -1;                          return -1;
410          }                  }
   
         if ((rv == 1) && (buffer[0] >= 0x80))  
         {  
                 DEBUG_COMM2("Time request: 0x%02X", buffer[0]);  
                 goto time_request;  
         }  
411    
         /* too short */  
         if (rv < min_length)  
         {  
412  #ifdef DEBUG_LEVEL_COMM  #ifdef DEBUG_LEVEL_COMM
413                  DEBUG_XXD(debug_header, buffer, rv);                  DEBUG_XXD(debug_header, buffer + already_read, rv);
414  #endif  #endif
                 DEBUG_COMM3("ReadSerial: only %d byte(s) read, needed %d", rv,  
                         min_length);  
415    
416                  return -1;                  already_read += rv;
417                    DEBUG_COMM3("read: %d, to read: %d", already_read,
418                            min_length);
419          }          }
420    
421          return rv;          return already_read;
422  } /* ReadChunk */  } /* ReadChunk */
423    
424    
# Line 407  time_request: Line 430  time_request:
430  status_t OpenSerial(int lun, int channel)  status_t OpenSerial(int lun, int channel)
431  {  {
432          char dev_name[FILENAME_MAX];          char dev_name[FILENAME_MAX];
         struct termios current_termios;  
         int i;  
         int reader = LunToReaderIndex(lun);  
433    
434          DEBUG_COMM3("OpenSerial: Lun: %X, Channel: %d", lun, channel);          DEBUG_COMM3("Lun: %X, Channel: %d", lun, channel);
435    
436          /*          /*
437           * Conversion of old-style ifd-hanler 1.0 CHANNELID           * Conversion of old-style ifd-hanler 1.0 CHANNELID
# Line 436  status_t OpenSerial(int lun, int channel Line 456  status_t OpenSerial(int lun, int channel
456    
457          sprintf(dev_name, "/dev/pcsc/%d", (int) channel);          sprintf(dev_name, "/dev/pcsc/%d", (int) channel);
458    
459            return OpenSerialByName(lun, dev_name);
460    } /* OpenSerial */
461    
462    /*****************************************************************************
463     *
464     *                              OpenSerialByName: open the port
465     *
466     *****************************************************************************/
467    status_t OpenSerialByName(int lun, char *dev_name)
468    {
469            struct termios current_termios;
470            int i;
471            int reader = LunToReaderIndex(lun);
472    
473            DEBUG_COMM3("Lun: %X, Device: %d", lun, dev_name);
474    
475          /* check if the same channel is not already used */          /* check if the same channel is not already used */
476          for (i=0; i<PCSCLITE_MAX_READERS; i++)          for (i=0; i<PCSCLITE_MAX_READERS; i++)
477          {          {
478                  if (serialDevice[i].channel == channel)                  if (serialDevice[i].device &&
479                            strcmp(serialDevice[i].device, dev_name) == 0)
480                  {                  {
481                          DEBUG_CRITICAL2("Channel %s already in use", dev_name);                          DEBUG_CRITICAL2("Device %s already in use", dev_name);
482                          return STATUS_UNSUCCESSFUL;                          return STATUS_UNSUCCESSFUL;
483                  }                  }
484          }          }
485    
486          serialDevice[reader].fd = open(dev_name, O_RDWR | O_NOCTTY);          serialDevice[reader].fd = open(dev_name, O_RDWR | O_NOCTTY);
487    
488          if (serialDevice[reader].fd <= 0)          if (-1 == serialDevice[reader].fd)
489          {          {
490                  DEBUG_CRITICAL3("open %s: %s", dev_name, strerror(errno));                  DEBUG_CRITICAL3("open %s: %s", dev_name, strerror(errno));
491                  return STATUS_UNSUCCESSFUL;                  return STATUS_UNSUCCESSFUL;
492          }          }
493    
494          /* set channel used */          /* set channel used */
495          serialDevice[reader].channel = channel;          serialDevice[reader].device = strdup(dev_name);
496    
497          /* empty in and out serial buffers */          /* empty in and out serial buffers */
498          if (tcflush(serialDevice[reader].fd, TCIOFLUSH))          if (tcflush(serialDevice[reader].fd, TCIOFLUSH))
# Line 501  status_t OpenSerial(int lun, int channel Line 538  status_t OpenSerial(int lun, int channel
538          serialDevice[reader].ccid.bSeq = 0;          serialDevice[reader].ccid.bSeq = 0;
539          serialDevice[reader].ccid.readerID = GEMPCTWIN;          serialDevice[reader].ccid.readerID = GEMPCTWIN;
540          serialDevice[reader].ccid.dwMaxCCIDMessageLength = 271;          serialDevice[reader].ccid.dwMaxCCIDMessageLength = 271;
541            serialDevice[reader].ccid.dwMaxIFSD = 254;
542          serialDevice[reader].ccid.dwFeatures = 0x00010230;          serialDevice[reader].ccid.dwFeatures = 0x00010230;
543            serialDevice[reader].ccid.bPINSupport = 0x0;
544            serialDevice[reader].ccid.dwDefaultClock = 4000;
545            serialDevice[reader].ccid.dwMaxDataRate = 344086;
546    
547          ccid_open_hack(lun);          serialDevice[reader].buffer_offset = 0;
548            serialDevice[reader].buffer_offset_last = 0;
549    
550          return STATUS_SUCCESS;          return STATUS_SUCCESS;
551  } /* OpenSerial */  } /* OpenSerialByName */
552    
553    
554  /*****************************************************************************  /*****************************************************************************
# Line 519  status_t CloseSerial(int lun) Line 561  status_t CloseSerial(int lun)
561          int reader = LunToReaderIndex(lun);          int reader = LunToReaderIndex(lun);
562    
563          close(serialDevice[reader].fd);          close(serialDevice[reader].fd);
   
564          serialDevice[reader].fd = -1;          serialDevice[reader].fd = -1;
565          serialDevice[reader].channel = -1;  
566            free(serialDevice[reader].device);
567            serialDevice[reader].device = NULL;
568    
569          return STATUS_SUCCESS;          return STATUS_SUCCESS;
570  } /* CloseSerial */  } /* CloseSerial */

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

  ViewVC Help
Powered by ViewVC 1.1.5