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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 892 - (hide annotations) (download)
Mon May 24 12:58:43 2004 UTC (9 years ago) by rousseau
File MIME type: text/plain
File size: 13999 byte(s)
recompile using gcc -pedantic and correct:
- some C++ syntax comments
- many signedness "problems"
1 rousseau 414 /*
2     * ccid_serial.c: communicate with a GemPC Twin smart card reader
3     * Copyright (C) 2001-2003 Ludovic Rousseau <ludovic.rousseau@free.fr>
4     *
5     * 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
8     * under the terms of the GNU General Public License as published by the
9     * Free Software Foundation; either version 2 of the License, or (at your
10     * option) any later version.
11     *
12     * This program is distributed in the hope that it will be useful, but
13     * WITHOUT ANY WARRANTY; without even the implied warranty of
14     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15     * General Public License for more details.
16     *
17     * You should have received a copy of the GNU General Public License along
18     * with this program; if not, write to the Free Software Foundation, Inc.,
19     * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20     */
21    
22     /*
23     * $Id$
24     */
25    
26     #include <stdio.h>
27     #include <stdlib.h>
28     #include <fcntl.h>
29     #include <unistd.h>
30     #include <termios.h>
31     #include <string.h>
32     #include <errno.h>
33     #include <sys/time.h>
34     #include <sys/types.h>
35    
36 rousseau 877 #include "defs.h"
37     #include "ccid_ifdhandler.h"
38 rousseau 414 #include "config.h"
39     #include "debug.h"
40     #include "ccid.h"
41     #include "utils.h"
42    
43     /* communication timeout in seconds */
44 rousseau 453 #define SERIAL_TIMEOUT 2
45 rousseau 414
46     #define SYNC 0x03
47     #define CTRL_ACK 0x06
48     #define CTRL_NAK 0x15
49     #define RDR_to_PC_NotifySlotChange 0x50
50     #define CARD_ABSENT 0x02
51     #define CARD_PRESENT 0x03
52    
53     /*
54     * normal command:
55     * 1 : SYNC
56     * 1 : CTRL
57     * 10 +data length : CCID command
58     * 1 : LRC
59     *
60     * SYNC : 0x03
61     * CTRL : ACK (0x06) or NAK (0x15)
62     * CCID command : see USB CCID specs
63     * LRC : xor of all the previous byes
64     *
65     * Error message:
66     * 1 : SYNC (0x03)
67     * 1 : CTRL (NAK: 0x15)
68     * 1 : LRC (0x16)
69     *
70     * Card insertion/withdrawal
71     * 1 : RDR_to_PC_NotifySlotChange (0x50)
72     * 1 : bmSlotIccState
73     * 0x02 if card absent
74     * 0x03 is card present
75     *
76     * Time request
77     * T=1 : normal CCID command
78     * T=0 : 1 byte (value between 0x80 and 0xFF)
79     *
80     */
81    
82 rousseau 453 /*
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 rousseau 414 typedef struct
99     {
100     /*
101     * File handle on the serial port
102     */
103     int fd;
104    
105     /*
106 rousseau 649 * device used ("/dev/ttyS?" under Linux)
107 rousseau 414 */
108 rousseau 649 char *device;
109 rousseau 414
110     /*
111 rousseau 453 * serial communication buffer
112     */
113     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 rousseau 414 * CCID infos common to USB and serial
127     */
128     _ccid_descriptor ccid;
129    
130     } _serialDevice;
131    
132     /* The _serialDevice structure must be defined before including ccid_serial.h */
133     #include "ccid_serial.h"
134    
135 rousseau 892 /* no need to initialize to 0 since it is static */
136     static _serialDevice serialDevice[PCSCLITE_MAX_READERS];
137 rousseau 414
138     /*****************************************************************************
139     *
140     * WriteSerial: Send bytes to the card reader
141     *
142     *****************************************************************************/
143 rousseau 892 status_t WriteSerial(int lun, unsigned int length, unsigned char *buffer)
144 rousseau 414 {
145     int i;
146     unsigned char lrc;
147     unsigned char low_level_buffer[GEMPCTWIN_MAXBUF];
148    
149     #ifdef DEBUG_LEVEL_COMM
150     char debug_header[] = "-> 121234 ";
151    
152     sprintf(debug_header, "-> %06X ", (int)lun);
153     #endif
154    
155     if (length > GEMPCTWIN_MAXBUF-3)
156     {
157 rousseau 608 DEBUG_CRITICAL3("command too long: %d for max %d",
158 rousseau 414 length, GEMPCTWIN_MAXBUF-3);
159     return STATUS_UNSUCCESSFUL;
160     }
161    
162     /* header */
163     low_level_buffer[0] = 0x03; /* SYNC */
164     low_level_buffer[1] = 0x06; /* ACK */
165    
166     /* CCID command */
167     memcpy(low_level_buffer+2, buffer, length);
168    
169     /* checksum */
170     lrc = 0;
171     for(i=0; i<length+2; i++)
172     lrc ^= low_level_buffer[i];
173     low_level_buffer[length+2] = lrc;
174    
175     #ifdef DEBUG_LEVEL_COMM
176     DEBUG_XXD(debug_header, low_level_buffer, length+3);
177     #endif
178    
179 rousseau 453 if (write(serialDevice[LunToReaderIndex(lun)].fd, low_level_buffer,
180     length+3) != length+3)
181 rousseau 414 {
182 rousseau 608 DEBUG_CRITICAL2("write error: %s", strerror(errno));
183 rousseau 414 return STATUS_UNSUCCESSFUL;
184     }
185    
186     return STATUS_SUCCESS;
187     } /* WriteSerial */
188    
189    
190     /*****************************************************************************
191     *
192     * ReadSerial: Receive bytes from the card reader
193     *
194     *****************************************************************************/
195 rousseau 892 status_t ReadSerial(int lun, unsigned int *length, unsigned char *buffer)
196 rousseau 414 {
197 rousseau 453 unsigned char c;
198     int rv;
199     int echo;
200     int to_read;
201     int i;
202 rousseau 414
203 rousseau 453 /* we get the echo first */
204     echo = TRUE;
205 rousseau 414
206 rousseau 453 start:
207 rousseau 462 DEBUG_COMM("start");
208 rousseau 453 if ((rv = get_bytes(lun, &c, 1)) != STATUS_SUCCESS)
209     return rv;
210 rousseau 414
211 rousseau 453 if (c == RDR_to_PC_NotifySlotChange)
212     goto slot_change;
213 rousseau 414
214 rousseau 453 if (c == SYNC)
215     goto sync;
216 rousseau 414
217 rousseau 453 if (c >= 0x80)
218 rousseau 462 {
219     DEBUG_COMM2("time request: 0x%02X", c);
220 rousseau 453 goto start;
221 rousseau 462 }
222 rousseau 414
223 rousseau 453 DEBUG_CRITICAL2("Got 0x%02X", c);
224     return STATUS_COMM_ERROR;
225 rousseau 414
226 rousseau 453 slot_change:
227 rousseau 462 DEBUG_COMM("slot change");
228 rousseau 453 if ((rv = get_bytes(lun, &c, 1)) != STATUS_SUCCESS)
229     return rv;
230 rousseau 414
231 rousseau 453 if (c == CARD_ABSENT)
232 rousseau 774 {
233 rousseau 453 DEBUG_COMM("Card removed");
234 rousseau 774 }
235 rousseau 453 else
236     if (c == CARD_PRESENT)
237 rousseau 774 {
238 rousseau 453 DEBUG_COMM("Card inserted");
239 rousseau 774 }
240 rousseau 453 else
241 rousseau 774 {
242 rousseau 453 DEBUG_COMM2("Unknown card movement: %d", buffer[3]);
243 rousseau 774 }
244 rousseau 453 goto start;
245 rousseau 414
246 rousseau 453 sync:
247 rousseau 462 DEBUG_COMM("sync");
248 rousseau 453 if ((rv = get_bytes(lun, &c, 1)) != STATUS_SUCCESS)
249     return rv;
250 rousseau 414
251 rousseau 453 if (c == CTRL_ACK)
252     goto ack;
253 rousseau 414
254 rousseau 453 if (c == CTRL_NAK)
255     goto nak;
256 rousseau 414
257 rousseau 453 DEBUG_CRITICAL2("Got 0x%02X instead of ACK/NAK", c);
258     return STATUS_COMM_ERROR;
259 rousseau 414
260 rousseau 453 nak:
261 rousseau 462 DEBUG_COMM("nak");
262 rousseau 453 if ((rv = get_bytes(lun, &c, 1)) != STATUS_SUCCESS)
263     return rv;
264 rousseau 414
265 rousseau 453 if (c != (SYNC ^ CTRL_NAK))
266 rousseau 414 {
267 rousseau 453 DEBUG_CRITICAL2("Wrong LRC: 0x%02X", c);
268     return STATUS_COMM_ERROR;
269 rousseau 414 }
270 rousseau 453 else
271     goto start;
272 rousseau 414
273 rousseau 453 ack:
274 rousseau 462 DEBUG_COMM("ack");
275 rousseau 453 /* normal CCID frame */
276     if ((rv = get_bytes(lun, buffer, 5)) != STATUS_SUCCESS)
277     return rv;
278 rousseau 414
279 rousseau 453 /* total frame size */
280     to_read = 10+dw2i(buffer, 1);
281 rousseau 414
282 rousseau 462 DEBUG_COMM2("frame size: %d", to_read);
283 rousseau 453 if ((rv = get_bytes(lun, buffer+5, to_read-5)) != STATUS_SUCCESS)
284     return rv;
285 rousseau 414
286 rousseau 462 #ifdef DEBUG_LEVEL_COMM
287     DEBUG_XXD("frame: ", buffer, to_read);
288     #endif
289    
290 rousseau 453 /* lrc */
291 rousseau 462 DEBUG_COMM("lrc");
292 rousseau 453 if ((rv = get_bytes(lun, &c, 1)) != STATUS_SUCCESS)
293     return rv;
294    
295 rousseau 462 DEBUG_COMM2("lrc: 0x%02X", c);
296 rousseau 414 for (i=0; i<to_read; i++)
297 rousseau 453 c ^= buffer[i];
298 rousseau 414
299 rousseau 453 if (c != (SYNC ^ CTRL_ACK))
300     DEBUG_CRITICAL2("Wrong LRC: 0x%02X", c);
301 rousseau 414
302 rousseau 453 if (echo)
303     {
304     echo = FALSE;
305     goto start;
306     }
307 rousseau 414
308     return STATUS_SUCCESS;
309     } /* ReadSerial */
310    
311    
312     /*****************************************************************************
313     *
314 rousseau 453 * get_bytes: get n bytes
315 rousseau 414 *
316     *****************************************************************************/
317 rousseau 453 int get_bytes(int lun, unsigned char *buffer, int length)
318 rousseau 414 {
319 rousseau 453 int offset = serialDevice[LunToReaderIndex(lun)].buffer_offset;
320     int offset_last = serialDevice[LunToReaderIndex(lun)].buffer_offset_last;
321 rousseau 414
322 rousseau 608 DEBUG_COMM3("available: %d, needed: %d", offset_last-offset,
323 rousseau 462 length);
324 rousseau 453 /* enough data are available */
325     if (offset + length <= offset_last)
326 rousseau 414 {
327 rousseau 608 DEBUG_COMM("data available");
328 rousseau 453 memcpy(buffer, serialDevice[LunToReaderIndex(lun)].buffer + offset, length);
329     serialDevice[LunToReaderIndex(lun)].buffer_offset += length;
330 rousseau 414 }
331 rousseau 453 else
332 rousseau 414 {
333 rousseau 453 int present, rv;
334 rousseau 414
335 rousseau 453 /* copy available data */
336     present = offset_last - offset;
337 rousseau 414
338 rousseau 453 if (present > 0)
339 rousseau 462 {
340 rousseau 608 DEBUG_COMM2("some data available: %d", present);
341 rousseau 462 memcpy(buffer, serialDevice[LunToReaderIndex(lun)].buffer + offset,
342     present);
343     }
344 rousseau 414
345 rousseau 453 /* get fresh data */
346 rousseau 608 DEBUG_COMM2("get more data: %d", length - present);
347 rousseau 453 rv = ReadChunk(lun, serialDevice[LunToReaderIndex(lun)].buffer, sizeof(serialDevice[LunToReaderIndex(lun)].buffer), length - present);
348     if (rv < 0)
349     return STATUS_COMM_ERROR;
350 rousseau 414
351 rousseau 453 /* fill the buffer */
352     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 rousseau 608 DEBUG_COMM3("offset: %d, last_offset: %d",
357 rousseau 462 serialDevice[LunToReaderIndex(lun)].buffer_offset,
358     serialDevice[LunToReaderIndex(lun)].buffer_offset_last);
359 rousseau 414 }
360    
361 rousseau 453 return STATUS_SUCCESS;
362     } /* get_bytes */
363 rousseau 414
364 rousseau 453
365 rousseau 414 /*****************************************************************************
366     *
367     * ReadChunk: read a minimum number of bytes
368     *
369     *****************************************************************************/
370 rousseau 453 int ReadChunk(int lun, unsigned char *buffer, int buffer_length, int min_length)
371 rousseau 414 {
372 rousseau 453 int fd = serialDevice[LunToReaderIndex(lun)].fd;
373 rousseau 414 fd_set fdset;
374     struct timeval t;
375 rousseau 462 int i, rv = 0;
376     int already_read;
377 rousseau 414 #ifdef DEBUG_LEVEL_COMM
378     char debug_header[] = "<- 121234 ";
379    
380     sprintf(debug_header, "<- %06X ", (int)lun);
381     #endif
382    
383 rousseau 462 already_read = 0;
384     while (already_read < min_length)
385     {
386     /* use select() to, eventually, timeout */
387     FD_ZERO(&fdset);
388     FD_SET(fd, &fdset);
389     t.tv_sec = SERIAL_TIMEOUT;
390     t.tv_usec = 0;
391 rousseau 414
392 rousseau 462 i = select(fd+1, &fdset, NULL, NULL, &t);
393     if (i == -1)
394 rousseau 414 {
395 rousseau 462 DEBUG_CRITICAL2("select: %s", strerror(errno));
396 rousseau 414 return -1;
397     }
398 rousseau 462 else
399     if (i == 0)
400     {
401     DEBUG_COMM2("Timeout! (%d sec)", SERIAL_TIMEOUT);
402     return -1;
403     }
404 rousseau 414
405 rousseau 462 rv = read(fd, buffer + already_read, buffer_length - already_read);
406     if (rv < 0)
407     {
408     DEBUG_COMM2("read error: %s", strerror(errno));
409     return -1;
410     }
411 rousseau 414
412 rousseau 453 #ifdef DEBUG_LEVEL_COMM
413 rousseau 462 DEBUG_XXD(debug_header, buffer + already_read, rv);
414 rousseau 453 #endif
415 rousseau 414
416 rousseau 462 already_read += rv;
417 rousseau 608 DEBUG_COMM3("read: %d, to read: %d", already_read,
418 rousseau 414 min_length);
419     }
420    
421 rousseau 462 return already_read;
422 rousseau 414 } /* ReadChunk */
423    
424    
425     /*****************************************************************************
426     *
427     * OpenSerial: open the port
428     *
429     *****************************************************************************/
430     status_t OpenSerial(int lun, int channel)
431     {
432     char dev_name[FILENAME_MAX];
433    
434 rousseau 608 DEBUG_COMM3("Lun: %X, Channel: %d", lun, channel);
435 rousseau 414
436     /*
437     * Conversion of old-style ifd-hanler 1.0 CHANNELID
438     */
439     if (channel == 0x0103F8)
440     channel = 1;
441     else
442     if (channel == 0x0102F8)
443     channel = 2;
444     else
445     if (channel == 0x0103E8)
446     channel = 3;
447     else
448     if (channel == 0x0102E8)
449     channel = 4;
450    
451     if (channel < 0)
452     {
453     DEBUG_CRITICAL2("wrong port number: %d", (int) channel);
454     return STATUS_UNSUCCESSFUL;
455     }
456    
457     sprintf(dev_name, "/dev/pcsc/%d", (int) channel);
458    
459 rousseau 649 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 rousseau 414 /* check if the same channel is not already used */
476     for (i=0; i<PCSCLITE_MAX_READERS; i++)
477     {
478 rousseau 649 if (serialDevice[i].device &&
479     strcmp(serialDevice[i].device, dev_name) == 0)
480 rousseau 414 {
481 rousseau 649 DEBUG_CRITICAL2("Device %s already in use", dev_name);
482 rousseau 414 return STATUS_UNSUCCESSFUL;
483     }
484     }
485    
486     serialDevice[reader].fd = open(dev_name, O_RDWR | O_NOCTTY);
487    
488 rousseau 892 if (-1 == serialDevice[reader].fd)
489 rousseau 414 {
490     DEBUG_CRITICAL3("open %s: %s", dev_name, strerror(errno));
491     return STATUS_UNSUCCESSFUL;
492     }
493    
494     /* set channel used */
495 rousseau 649 serialDevice[reader].device = strdup(dev_name);
496 rousseau 414
497     /* empty in and out serial buffers */
498     if (tcflush(serialDevice[reader].fd, TCIOFLUSH))
499     DEBUG_INFO2("tcflush() function error: %s", strerror(errno));
500    
501     /* get config attributes */
502     if (tcgetattr(serialDevice[reader].fd, &current_termios) == -1)
503     {
504     DEBUG_INFO2("tcgetattr() function error: %s", strerror(errno));
505     close(serialDevice[reader].fd);
506     serialDevice[reader].fd = -1;
507    
508     return STATUS_UNSUCCESSFUL;
509     }
510    
511     /* IGNBRK: ignore BREAK condition on input
512     * IGNPAR: ignore framing errors and parity errors. */
513     current_termios.c_iflag = IGNBRK | IGNPAR;
514     current_termios.c_oflag = 0; /* Raw output modes */
515     /* CS8: 8-bits character size
516     * CSTOPB: set two stop bits
517     * CREAD: enable receiver
518     * CLOCAL: ignore modem control lines */
519     current_termios.c_cflag = CS8 | CSTOPB | CREAD | CLOCAL;
520    
521     /* Do not echo characters because if you connect to a host it or your modem
522     * will echo characters for you. Don't generate signals. */
523     current_termios.c_lflag = 0;
524    
525     /* set serial port speed to 115200 bauds */
526     cfsetspeed(&current_termios, B115200);
527    
528     DEBUG_INFO("Set serial port baudrate to 115200 and correct configuration");
529     if (tcsetattr(serialDevice[reader].fd, TCSANOW, &current_termios) == -1)
530     {
531     close(serialDevice[reader].fd);
532     serialDevice[reader].fd = -1;
533     DEBUG_INFO2("tcsetattr error: %s", strerror(errno));
534    
535     return STATUS_UNSUCCESSFUL;
536     }
537    
538     serialDevice[reader].ccid.bSeq = 0;
539     serialDevice[reader].ccid.readerID = GEMPCTWIN;
540     serialDevice[reader].ccid.dwMaxCCIDMessageLength = 271;
541 rousseau 672 serialDevice[reader].ccid.dwMaxIFSD = 254;
542 rousseau 414 serialDevice[reader].ccid.dwFeatures = 0x00010230;
543 rousseau 694 serialDevice[reader].ccid.dwDefaultClock = 4000;
544     serialDevice[reader].ccid.dwMaxDataRate = 344086;
545 rousseau 414
546 rousseau 453 serialDevice[reader].buffer_offset = 0;
547     serialDevice[reader].buffer_offset_last = 0;
548    
549 rousseau 414 return STATUS_SUCCESS;
550 rousseau 649 } /* OpenSerialByName */
551 rousseau 414
552    
553     /*****************************************************************************
554     *
555     * CloseSerial: close the port
556     *
557     *****************************************************************************/
558     status_t CloseSerial(int lun)
559     {
560     int reader = LunToReaderIndex(lun);
561    
562     close(serialDevice[reader].fd);
563     serialDevice[reader].fd = -1;
564    
565 rousseau 649 free(serialDevice[reader].device);
566     serialDevice[reader].device = NULL;
567    
568 rousseau 414 return STATUS_SUCCESS;
569     } /* CloseSerial */
570    
571    
572     /*****************************************************************************
573     *
574     * get_ccid_descriptor
575     *
576     ****************************************************************************/
577     _ccid_descriptor *get_ccid_descriptor(int lun)
578     {
579     return &serialDevice[LunToReaderIndex(lun)].ccid;
580     } /* get_ccid_descriptor */
581    
582    

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.5