/[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 1491 - (show annotations) (download)
Mon May 2 11:33:04 2005 UTC (8 years ago) by rousseau
File MIME type: text/plain
File size: 17066 byte(s)
ReadSerial(): if we get a NAK we return STATUS_COMM_NAK to the above
layer to replay the command instead of just restarting the read
1 /*
2 * ccid_serial.c: communicate with a GemPC Twin smart card reader
3 * 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
6 *
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2.1 of the License, or (at your option) any later version.
11
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public
18 License along with this library; if not, write to the Free Software
19 Foundation, Inc., 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 #include <sys/ioctl.h>
36 #include <PCSC/ifdhandler.h>
37
38 #include "defs.h"
39 #include "ccid_ifdhandler.h"
40 #include "config.h"
41 #include "debug.h"
42 #include "ccid.h"
43 #include "utils.h"
44 #include "commands.h"
45
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 /*
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
99 {
100 /*
101 * File handle on the serial port
102 */
103 int fd;
104
105 /*
106 * device used ("/dev/ttyS?" under Linux)
107 */
108 /*@null@*/ char *device;
109
110 /*
111 * 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 * 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 unsigned int SerialDataRates[] = {
136 10753,
137 14337,
138 15625,
139 17204,
140 20833,
141 21505,
142 23438,
143 25806,
144 28674,
145 31250,
146 32258,
147 34409,
148 39063,
149 41667,
150 43011,
151 46875,
152 52083,
153 53763,
154 57348,
155 62500,
156 64516,
157 68817,
158 71685,
159 78125,
160 83333,
161 86022,
162 93750,
163 104667,
164 107527,
165 114695,
166 125000,
167 129032,
168 143369,
169 156250,
170 166667,
171 172043,
172 215054,
173 229391,
174 250000,
175 344086,
176 0
177 };
178
179 /* no need to initialize to 0 since it is static */
180 static _serialDevice serialDevice[CCID_DRIVER_MAX_READERS];
181
182 /* unexported functions */
183 static int ReadChunk(unsigned int reader_index, unsigned char *buffer,
184 int buffer_length, int min_length);
185
186 static int get_bytes(unsigned int reader_index, unsigned char *buffer,
187 int length);
188
189
190 /*****************************************************************************
191 *
192 * WriteSerial: Send bytes to the card reader
193 *
194 *****************************************************************************/
195 status_t WriteSerial(unsigned int reader_index, unsigned int length,
196 unsigned char *buffer)
197 {
198 int i;
199 unsigned char lrc;
200 unsigned char low_level_buffer[GEMPCTWIN_MAXBUF];
201
202 #ifdef DEBUG_LEVEL_COMM
203 char debug_header[] = "-> 123456 ";
204
205 sprintf(debug_header, "-> %06X ", reader_index);
206 #endif
207
208 if (length > GEMPCTWIN_MAXBUF-3)
209 {
210 DEBUG_CRITICAL3("command too long: %d for max %d",
211 length, GEMPCTWIN_MAXBUF-3);
212 return STATUS_UNSUCCESSFUL;
213 }
214
215 /* header */
216 low_level_buffer[0] = 0x03; /* SYNC */
217 low_level_buffer[1] = 0x06; /* ACK */
218
219 /* CCID command */
220 memcpy(low_level_buffer+2, buffer, length);
221
222 /* checksum */
223 lrc = 0;
224 for(i=0; i<length+2; i++)
225 lrc ^= low_level_buffer[i];
226 low_level_buffer[length+2] = lrc;
227
228 #ifdef DEBUG_LEVEL_COMM
229 DEBUG_XXD(debug_header, low_level_buffer, length+3);
230 #endif
231
232 if (write(serialDevice[reader_index].fd, low_level_buffer,
233 length+3) != length+3)
234 {
235 DEBUG_CRITICAL2("write error: %s", strerror(errno));
236 return STATUS_UNSUCCESSFUL;
237 }
238
239 return STATUS_SUCCESS;
240 } /* WriteSerial */
241
242
243 /*****************************************************************************
244 *
245 * ReadSerial: Receive bytes from the card reader
246 *
247 *****************************************************************************/
248 status_t ReadSerial(unsigned int reader_index,
249 /*@unused@*/ unsigned int *length, unsigned char *buffer)
250 {
251 unsigned char c;
252 int rv;
253 int echo;
254 int to_read;
255 int i;
256
257 /* we get the echo first */
258 echo = TRUE;
259
260 start:
261 DEBUG_COMM("start");
262 if ((rv = get_bytes(reader_index, &c, 1)) != STATUS_SUCCESS)
263 return rv;
264
265 if (c == RDR_to_PC_NotifySlotChange)
266 goto slot_change;
267
268 if (c == SYNC)
269 goto sync;
270
271 if (c >= 0x80)
272 {
273 DEBUG_COMM2("time request: 0x%02X", c);
274 goto start;
275 }
276
277 DEBUG_CRITICAL2("Got 0x%02X", c);
278 return STATUS_COMM_ERROR;
279
280 slot_change:
281 DEBUG_COMM("slot change");
282 if ((rv = get_bytes(reader_index, &c, 1)) != STATUS_SUCCESS)
283 return rv;
284
285 if (c == CARD_ABSENT)
286 {
287 DEBUG_COMM("Card removed");
288 }
289 else
290 if (c == CARD_PRESENT)
291 {
292 DEBUG_COMM("Card inserted");
293 }
294 else
295 {
296 DEBUG_COMM2("Unknown card movement: %d", c);
297 }
298 goto start;
299
300 sync:
301 DEBUG_COMM("sync");
302 if ((rv = get_bytes(reader_index, &c, 1)) != STATUS_SUCCESS)
303 return rv;
304
305 if (c == CTRL_ACK)
306 goto ack;
307
308 if (c == CTRL_NAK)
309 goto nak;
310
311 DEBUG_CRITICAL2("Got 0x%02X instead of ACK/NAK", c);
312 return STATUS_COMM_ERROR;
313
314 nak:
315 DEBUG_COMM("nak");
316 if ((rv = get_bytes(reader_index, &c, 1)) != STATUS_SUCCESS)
317 return rv;
318
319 if (c != (SYNC ^ CTRL_NAK))
320 {
321 DEBUG_CRITICAL2("Wrong LRC: 0x%02X", c);
322 return STATUS_COMM_ERROR;
323 }
324 else
325 {
326 DEBUG_COMM("NAK requested");
327 return STATUS_COMM_NAK;
328 }
329
330 ack:
331 DEBUG_COMM("ack");
332 /* normal CCID frame */
333 if ((rv = get_bytes(reader_index, buffer, 5)) != STATUS_SUCCESS)
334 return rv;
335
336 /* total frame size */
337 to_read = 10+dw2i(buffer, 1);
338
339 DEBUG_COMM2("frame size: %d", to_read);
340 if ((rv = get_bytes(reader_index, buffer+5, to_read-5)) != STATUS_SUCCESS)
341 return rv;
342
343 #ifdef DEBUG_LEVEL_COMM
344 DEBUG_XXD("frame: ", buffer, to_read);
345 #endif
346
347 /* lrc */
348 DEBUG_COMM("lrc");
349 if ((rv = get_bytes(reader_index, &c, 1)) != STATUS_SUCCESS)
350 return rv;
351
352 DEBUG_COMM2("lrc: 0x%02X", c);
353 for (i=0; i<to_read; i++)
354 c ^= buffer[i];
355
356 if (c != (SYNC ^ CTRL_ACK))
357 DEBUG_CRITICAL2("Wrong LRC: 0x%02X", c);
358
359 if (echo)
360 {
361 echo = FALSE;
362 goto start;
363 }
364
365 return STATUS_SUCCESS;
366 } /* ReadSerial */
367
368
369 /*****************************************************************************
370 *
371 * get_bytes: get n bytes
372 *
373 *****************************************************************************/
374 int get_bytes(unsigned int reader_index, unsigned char *buffer, int length)
375 {
376 int offset = serialDevice[reader_index].buffer_offset;
377 int offset_last = serialDevice[reader_index].buffer_offset_last;
378
379 DEBUG_COMM3("available: %d, needed: %d", offset_last-offset,
380 length);
381 /* enough data are available */
382 if (offset + length <= offset_last)
383 {
384 DEBUG_COMM("data available");
385 memcpy(buffer, serialDevice[reader_index].buffer + offset, length);
386 serialDevice[reader_index].buffer_offset += length;
387 }
388 else
389 {
390 int present, rv;
391
392 /* copy available data */
393 present = offset_last - offset;
394
395 if (present > 0)
396 {
397 DEBUG_COMM2("some data available: %d", present);
398 memcpy(buffer, serialDevice[reader_index].buffer + offset,
399 present);
400 }
401
402 /* get fresh data */
403 DEBUG_COMM2("get more data: %d", length - present);
404 rv = ReadChunk(reader_index, serialDevice[reader_index].buffer,
405 sizeof(serialDevice[reader_index].buffer), length - present);
406 if (rv < 0)
407 return STATUS_COMM_ERROR;
408
409 /* fill the buffer */
410 memcpy(buffer + present, serialDevice[reader_index].buffer,
411 length - present);
412 serialDevice[reader_index].buffer_offset = length - present;
413 serialDevice[reader_index].buffer_offset_last = rv;
414 DEBUG_COMM3("offset: %d, last_offset: %d",
415 serialDevice[reader_index].buffer_offset,
416 serialDevice[reader_index].buffer_offset_last);
417 }
418
419 return STATUS_SUCCESS;
420 } /* get_bytes */
421
422
423 /*****************************************************************************
424 *
425 * ReadChunk: read a minimum number of bytes
426 *
427 *****************************************************************************/
428 static int ReadChunk(unsigned int reader_index, unsigned char *buffer,
429 int buffer_length, int min_length)
430 {
431 int fd = serialDevice[reader_index].fd;
432 # ifndef S_SPLINT_S
433 fd_set fdset;
434 # endif
435 struct timeval t;
436 int i, rv = 0;
437 int already_read;
438 #ifdef DEBUG_LEVEL_COMM
439 char debug_header[] = "<- 123456 ";
440
441 sprintf(debug_header, "<- %06X ", reader_index);
442 #endif
443
444 already_read = 0;
445 while (already_read < min_length)
446 {
447 /* use select() to, eventually, timeout */
448 FD_ZERO(&fdset);
449 FD_SET(fd, &fdset);
450 t.tv_sec = serialDevice[reader_index].ccid.readTimeout;
451 t.tv_usec = 0;
452
453 i = select(fd+1, &fdset, NULL, NULL, &t);
454 if (i == -1)
455 {
456 DEBUG_CRITICAL2("select: %s", strerror(errno));
457 return -1;
458 }
459 else
460 if (i == 0)
461 {
462 DEBUG_COMM2("Timeout! (%d sec)", serialDevice[reader_index].ccid.readTimeout);
463 return -1;
464 }
465
466 rv = read(fd, buffer + already_read, buffer_length - already_read);
467 if (rv < 0)
468 {
469 DEBUG_COMM2("read error: %s", strerror(errno));
470 return -1;
471 }
472
473 #ifdef DEBUG_LEVEL_COMM
474 DEBUG_XXD(debug_header, buffer + already_read, rv);
475 #endif
476
477 already_read += rv;
478 DEBUG_COMM3("read: %d, to read: %d", already_read,
479 min_length);
480 }
481
482 return already_read;
483 } /* ReadChunk */
484
485
486 /*****************************************************************************
487 *
488 * OpenSerial: open the port
489 *
490 *****************************************************************************/
491 status_t OpenSerial(unsigned int reader_index, int channel)
492 {
493 char dev_name[FILENAME_MAX];
494
495 DEBUG_COMM3("Reader index: %X, Channel: %d", reader_index, channel);
496
497 /*
498 * Conversion of old-style ifd-hanler 1.0 CHANNELID
499 */
500 if (channel == 0x0103F8)
501 channel = 1;
502 else
503 if (channel == 0x0102F8)
504 channel = 2;
505 else
506 if (channel == 0x0103E8)
507 channel = 3;
508 else
509 if (channel == 0x0102E8)
510 channel = 4;
511
512 if (channel < 0)
513 {
514 DEBUG_CRITICAL2("wrong port number: %d", (int) channel);
515 return STATUS_UNSUCCESSFUL;
516 }
517
518 sprintf(dev_name, "/dev/pcsc/%d", (int) channel);
519
520 return OpenSerialByName(reader_index, dev_name);
521 } /* OpenSerial */
522
523 /*****************************************************************************
524 *
525 * OpenSerialByName: open the port
526 *
527 *****************************************************************************/
528 status_t OpenSerialByName(unsigned int reader_index, char *dev_name)
529 {
530 struct termios current_termios;
531 int i;
532 unsigned int reader = reader_index;
533
534 DEBUG_COMM3("Reader index: %X, Device: %s", reader_index, dev_name);
535
536 /* check if the same channel is not already used */
537 for (i=0; i<CCID_DRIVER_MAX_READERS; i++)
538 {
539 if (serialDevice[i].device &&
540 strcmp(serialDevice[i].device, dev_name) == 0)
541 {
542 DEBUG_CRITICAL2("Device %s already in use", dev_name);
543 return STATUS_UNSUCCESSFUL;
544 }
545 }
546
547 serialDevice[reader].fd = open(dev_name, O_RDWR | O_NOCTTY);
548
549 if (-1 == serialDevice[reader].fd)
550 {
551 DEBUG_CRITICAL3("open %s: %s", dev_name, strerror(errno));
552 return STATUS_UNSUCCESSFUL;
553 }
554
555 /* Set RTS signal to low to prevent the smart card reader
556 * from sending its plug and play string. */
557 {
558 int flags;
559
560 if (ioctl(serialDevice[reader].fd, TIOCMGET, &flags) < 0)
561 {
562 DEBUG_CRITICAL2("Get RS232 signals state failed: %s",
563 strerror(errno));
564 }
565 else
566 {
567 flags &= ~TIOCM_RTS;
568 if (ioctl(serialDevice[reader].fd, TIOCMSET, &flags) < 0)
569 {
570 DEBUG_CRITICAL2("Set RTS to low failed: %s", strerror(errno));
571 }
572 else
573 {
574 DEBUG_COMM("Plug-n-Play inhibition successful");
575 }
576 }
577 }
578
579 /* set channel used */
580 serialDevice[reader].device = strdup(dev_name);
581
582 /* empty in and out serial buffers */
583 if (tcflush(serialDevice[reader].fd, TCIOFLUSH))
584 DEBUG_INFO2("tcflush() function error: %s", strerror(errno));
585
586 /* get config attributes */
587 if (tcgetattr(serialDevice[reader].fd, &current_termios) == -1)
588 {
589 DEBUG_INFO2("tcgetattr() function error: %s", strerror(errno));
590 close(serialDevice[reader].fd);
591 serialDevice[reader].fd = -1;
592
593 return STATUS_UNSUCCESSFUL;
594 }
595
596 /* IGNBRK: ignore BREAK condition on input
597 * IGNPAR: ignore framing errors and parity errors. */
598 current_termios.c_iflag = IGNBRK | IGNPAR;
599 current_termios.c_oflag = 0; /* Raw output modes */
600 /* CS8: 8-bits character size
601 * CSTOPB: set two stop bits
602 * CREAD: enable receiver
603 * CLOCAL: ignore modem control lines */
604 current_termios.c_cflag = CS8 | CSTOPB | CREAD | CLOCAL;
605
606 /* Do not echo characters because if you connect to a host it or your modem
607 * will echo characters for you. Don't generate signals. */
608 current_termios.c_lflag = 0;
609
610 /* set serial port speed to 115200 bauds */
611 cfsetspeed(&current_termios, B115200);
612
613 DEBUG_INFO("Set serial port baudrate to 115200 and correct configuration");
614 if (tcsetattr(serialDevice[reader].fd, TCSANOW, &current_termios) == -1)
615 {
616 close(serialDevice[reader].fd);
617 serialDevice[reader].fd = -1;
618 DEBUG_INFO2("tcsetattr error: %s", strerror(errno));
619
620 return STATUS_UNSUCCESSFUL;
621 }
622
623 serialDevice[reader].ccid.real_bSeq = 0;
624 serialDevice[reader].ccid.pbSeq = &serialDevice[reader].ccid.real_bSeq;
625 serialDevice[reader].ccid.readerID = GEMPCTWIN;
626 serialDevice[reader].ccid.dwMaxCCIDMessageLength = 271;
627 serialDevice[reader].ccid.dwMaxIFSD = 254;
628 serialDevice[reader].ccid.dwFeatures = 0x00010230;
629 serialDevice[reader].ccid.bPINSupport = 0x0;
630 serialDevice[reader].ccid.dwDefaultClock = 4000;
631 serialDevice[reader].ccid.dwMaxDataRate = 344086;
632 serialDevice[reader].ccid.bMaxSlotIndex = 0;
633 serialDevice[reader].ccid.bCurrentSlotIndex = 0;
634 serialDevice[reader].ccid.arrayOfSupportedDataRates = SerialDataRates;
635
636 serialDevice[reader].buffer_offset = 0;
637 serialDevice[reader].buffer_offset_last = 0;
638
639 /* perform a command to be sure a GemPC Twin reader is connected
640 * get the reader firmware */
641 {
642 unsigned char tx_buffer[] = { 0x02 };
643 unsigned char rx_buffer[50];
644 unsigned int rx_length = sizeof(rx_buffer);
645
646 /* 2 seconds timeout to not wait too long if no reader is connected */
647 serialDevice[reader].ccid.readTimeout = 2;
648
649 if (IFD_SUCCESS != CmdEscape(reader_index, tx_buffer, sizeof(tx_buffer),
650 rx_buffer, &rx_length))
651 {
652 DEBUG_CRITICAL("Get firmware failed. Maybe the reader is not connected");
653 return STATUS_UNSUCCESSFUL;
654 }
655
656 /* normal timeout: 2 seconds */
657 serialDevice[reader].ccid.readTimeout = DEFAULT_COM_READ_TIMEOUT ;
658
659 rx_buffer[rx_length] = '\0';
660 DEBUG_INFO2("Firmware: %s", rx_buffer);
661 }
662
663 /* perform a command to configure GemPC Twin reader card movement
664 * notification to synchronous mode: the card movement is notified _after_
665 * the host command and _before_ the reader anwser */
666 {
667 unsigned char tx_buffer[] = { 0x01, 0x01, 0x01};
668 unsigned char rx_buffer[50];
669 unsigned int rx_length = sizeof(rx_buffer);
670
671 if (IFD_SUCCESS != CmdEscape(reader_index, tx_buffer, sizeof(tx_buffer),
672 rx_buffer, &rx_length))
673 {
674 DEBUG_CRITICAL("Change card movement notification failed.");
675 return STATUS_UNSUCCESSFUL;
676 }
677 }
678
679 return STATUS_SUCCESS;
680 } /* OpenSerialByName */
681
682
683 /*****************************************************************************
684 *
685 * CloseSerial: close the port
686 *
687 *****************************************************************************/
688 status_t CloseSerial(unsigned int reader_index)
689 {
690 unsigned int reader = reader_index;
691
692 close(serialDevice[reader].fd);
693 serialDevice[reader].fd = -1;
694
695 free(serialDevice[reader].device);
696 serialDevice[reader].device = NULL;
697
698 return STATUS_SUCCESS;
699 } /* CloseSerial */
700
701
702 /*****************************************************************************
703 *
704 * get_ccid_descriptor
705 *
706 ****************************************************************************/
707 _ccid_descriptor *get_ccid_descriptor(unsigned int reader_index)
708 {
709 return &serialDevice[reader_index].ccid;
710 } /* get_ccid_descriptor */
711
712

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.5