source: trunk/src/ifd/ifd-ccid.c @ 1190

Revision 1190, 38.6 KB checked in by alonbl, 4 weeks ago (diff)

epass2003 transmits >255 APDUs

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2 * driver for some CCID-compliant devices
3 *
4 * Copyright 2003, Chaskiel Grundman <cg2v@andrew.cmu.edu>
5 *
6 * 2005-04-20: Harald Welte <laforge@gnumonks.org>
7 *      Add support for PCMCIA based CCID Device (CardMan 4040)
8 *
9 * 2005-05-22: Harald Welte <laforge@gnumonks.org>
10 *      Add suport for OmniKey Cardman 5121 RFID extensions
11 */
12
13#include "internal.h"
14#include "usb-descriptors.h"
15#include "atr.h"
16#include <stdlib.h>
17#include <string.h>
18#include <sys/stat.h>
19#include <unistd.h>
20
21#define CCID_ERR_ABORTED        0xFF    /* CMD ABORTED */
22#define CCID_ERR_ICC_MUTE       0xFE
23#define CCID_ERR_XFR_PARITY     0xFD    /* XFR PARITY ERROR */
24#define CCID_ERR_OVERRUN        0xFC    /* XFR OVERRUN */
25#define CCID_ERR_HW_ERROR       0xFB
26#define CCID_ERR_BAD_ATR_TS     0xF8
27#define CCID_ERR_BAD_ATR_TCK    0xF7
28#define CCID_ERR_PROT_NOSUP     0xF6    /* ICC PROTOCOL NOT SUPPORTED */
29#define CCID_ERR_CLASS_NOSUP    0xF5    /* ICC CLASS NOT SUPPORTED */
30#define CCID_ERR_BAD_PROC_BYTE  0xF4    /* PROCEDURE BYTE CONFLICT */
31#define CCID_ERR_XXX            0xF3    /* DEACTIVATED PROTOCOL (?) */
32#define CCID_ERR_BUSY_AUTO_SEQ  0xF2    /* BUSY WITH AUTO SEQUENCE */
33#define CCID_ERR_PIN_TIMEOUT    0xF0
34#define CCID_ERR_PIN_CANCELED   0xEF
35#define CCID_ERR_SLOT_BUSY      0xE0    /* CMD SLOT BUSY */
36
37#define CCID_OFFSET_MSGTYPE     0
38#define CCID_OFFSET_LENGTH      1
39#define CCID_OFFSET_SLOT        5
40#define CCID_OFFSET_SEQ         6
41
42#define CCID_REQ_ABORT          1
43#define CCID_REQ_GETCLOCKRATE   2
44#define CCID_REQ_GETDATARATE    3
45
46#define CCID_CMD_FIRST          0x60
47
48#define CCID_CMD_ICCPOWERON     0x62
49#define CCID_CMD_ICCPOWEROFF    0x63
50#define CCID_CMD_GETSLOTSTAT    0x65
51#define CCID_CMD_XFRBLOCK       0x6F
52#define CCID_CMD_GETPARAMS      0x6C
53#define CCID_CMD_RESETPARAMS    0x6D
54#define CCID_CMD_SETPARAMS      0x61
55#define CCID_CMD_ESCAPE         0x6B
56#define CCID_CMD_ICCCLOCK       0x6E
57#define CCID_CMD_T0APDU         0x6A
58#define CCID_CMD_SECURE         0x69
59#define CCID_CMD_MECHANICAL     0x71
60#define CCID_CMD_ABORT          0x72
61#define CCID_CMD_SET_DR_FREQ    0x73
62
63#define CCID_RESP_DATA          0x80
64#define CCID_RESP_SLOTSTAT      0x81
65#define CCID_RESP_PARAMS        0x82
66#define CCID_RESP_ESCAPE        0x83
67#define CCID_RESP_DR_FREQ       0x84
68
69/* maximum sensical size:
70 *  10 bytes ccid header + 4 bytes command header +
71 *  1 byte Lc + 255 bytes data + 1 byte Le = 271
72 *  @ALON: Added +256 as APDUs grew at some point
73 */
74#define CCID_MAX_MSG_LEN        (271+256)
75
76static int msg_expected[] = {
77        0,
78        CCID_RESP_PARAMS,
79        CCID_RESP_DATA,
80        CCID_RESP_SLOTSTAT,
81        0,
82        CCID_RESP_SLOTSTAT,
83        0, 0, 0,
84        CCID_RESP_DATA,
85        CCID_RESP_SLOTSTAT,
86        CCID_RESP_ESCAPE,
87        CCID_RESP_PARAMS,
88        CCID_RESP_PARAMS,
89        CCID_RESP_SLOTSTAT,
90        CCID_RESP_DATA,
91        0,
92        CCID_RESP_SLOTSTAT,
93        CCID_RESP_SLOTSTAT,
94        CCID_RESP_DR_FREQ
95};
96
97enum {
98        TYPE_APDU,
99        TYPE_TPDU,
100        TYPE_CHAR
101};
102
103/* Some "ccid" devices have non-compliant descriptors. (perhaps their
104   design predates the approval of the standard?)
105   Attempt to recognize them anyway.
106*/
107static struct force_parse_device_st {
108        unsigned short vendor;
109        unsigned short product;
110} force_parse_devices[] = {
111        {
112        0x04e6, 0xe003},        /* SCM SPR 532 */
113        {
114        0x046a, 0x003e},        /* Cherry SmartTerminal ST-2XXX */
115        {
116        0x413c, 0x2100},        /* Dell USB Smartcard Keyboard */
117        {
118        0x04e6, 0x5120},        /* SCM SCR331-DI (NTT) */
119        {
120        0x04e6, 0x5111},        /* SCM SCR331-DI */
121        {
122        0x08e6, 0x1359},        /* Verisign secure storage token */
123        {
124        0x08e6, 0xACE0},        /* Verisign secure token */
125        {
126        0, 0}
127};
128
129#define SUPPORT_T0      0x1
130#define SUPPORT_T1      0x2
131#define SUPPORT_ESCAPE  0x80
132
133#define SUPPORT_50V     1
134#define SUPPORT_33V     2
135#define SUPPORT_18V     4
136#define AUTO_VOLTAGE    0x80
137
138#define FLAG_NO_PTS             1
139#define FLAG_NO_SETPARAM        2
140#define FLAG_AUTO_ACTIVATE      4
141#define FLAG_AUTO_ATRPARSE      8
142
143#define USB_CCID_DESCRIPTOR_LENGTH 54
144struct usb_ccid_descriptor {
145        uint8_t bLength;
146        uint8_t bDescriptorType;
147        uint16_t bcdCCID;
148        uint8_t bMaxSlotIndex;
149        uint8_t bVoltageSupport;
150        uint32_t dwProtocols;
151        uint32_t dwDefaultClock;
152        uint32_t dwMaximumClock;
153        uint8_t bNumClockRatesSupported;
154        uint32_t dwDataRate;
155        uint32_t dwMaxDataRate;
156        uint8_t bNumDataRatesSupported;
157        uint32_t dwMaxIFSD;
158        uint32_t dwSynchProtocols;
159        uint32_t dwMechanical;
160        uint32_t dwFeatures;
161        uint32_t dwMaxCCIDMessageLength;
162        uint8_t bClassGetResponse;
163        uint8_t bClassEnvelope;
164        uint16_t wLcdLayout;
165        uint8_t bPINSupport;
166        uint8_t bMaxCCIDBusySlots;
167};
168
169static int ccid_parse_descriptor(struct usb_ccid_descriptor *ret,
170                                 unsigned char *in, size_t inlen)
171{
172        if (inlen < USB_CCID_DESCRIPTOR_LENGTH)
173                return 1;
174
175        ret->bLength = in[0];
176        if (ret->bLength < USB_CCID_DESCRIPTOR_LENGTH)
177                return 1;
178        ret->bDescriptorType = in[1];
179        ret->bcdCCID = in[3] << 8 | in[2];
180        ret->bMaxSlotIndex = in[4];
181        ret->bVoltageSupport = in[5];
182        ret->dwProtocols = in[9] << 24 | in[8] << 16 | in[7] << 8 | in[6];
183        ret->dwDefaultClock =
184            in[13] << 24 | in[12] << 16 | in[11] << 8 | in[10];
185        ret->dwMaximumClock =
186            in[17] << 24 | in[16] << 16 | in[15] << 8 | in[14];
187        ret->bNumClockRatesSupported = in[18];
188        ret->dwDataRate = in[22] << 24 | in[21] << 16 | in[20] << 8 | in[19];
189        ret->dwMaxDataRate = in[26] << 24 | in[25] << 16 | in[24] << 8 | in[23];
190        ret->bNumDataRatesSupported = in[27];
191        ret->dwMaxIFSD = in[31] << 24 | in[30] << 16 | in[29] << 8 | in[28];
192        ret->dwSynchProtocols =
193            in[35] << 24 | in[34] << 16 | in[33] << 8 | in[32];
194        ret->dwMechanical = in[39] << 24 | in[38] << 16 | in[37] << 8 | in[36];
195        ret->dwFeatures = in[43] << 24 | in[42] << 16 | in[41] << 8 | in[40];
196        ret->dwMaxCCIDMessageLength = in[47] << 24 | in[46] << 16 |
197            in[45] << 8 | in[44];
198        ret->bClassGetResponse = in[48];
199        ret->bClassEnvelope = in[49];
200        ret->wLcdLayout = in[51] << 8 | in[50];
201        ret->bPINSupport = in[52];
202        ret->bMaxCCIDBusySlots = in[53];
203
204        return 0;
205}
206
207/*
208 * CT status
209 */
210typedef struct ccid_status {
211        int reader_type;
212        int usb_interface;
213        int proto_support;
214        int voltage_support;
215        int ifsd;
216        int maxmsg;
217        int flags;
218        unsigned char icc_present[OPENCT_MAX_SLOTS];
219        unsigned char icc_proto[OPENCT_MAX_SLOTS];
220        unsigned char *sbuf[OPENCT_MAX_SLOTS];
221        size_t slen[OPENCT_MAX_SLOTS];
222        unsigned char seq;
223        int support_events;
224        int events_active;
225        ifd_usb_capture_t *event_cap;
226} ccid_status_t;
227
228static int ccid_checkresponse(void *status, int r)
229{
230        unsigned char *p = (unsigned char *)status;
231        int ret;
232
233        if ((p[7] >> 6 & 3) == 0) {
234                ret = 0;
235        }
236        /* XXX */
237        else if ((p[7] >> 6 & 3) == 2) {
238                /*ct_error("card requests more time"); */
239                ret = -300;
240        }
241        else {
242                switch (p[8]) {
243                case CCID_ERR_ICC_MUTE:
244                        ret = IFD_ERROR_NO_CARD;
245                        break;
246                case CCID_ERR_XFR_PARITY:
247                case CCID_ERR_OVERRUN:
248                        ret = IFD_ERROR_COMM_ERROR;
249                        break;
250                case CCID_ERR_BAD_ATR_TS:
251                case CCID_ERR_BAD_ATR_TCK:
252                        ret = IFD_ERROR_NO_ATR;
253                        break;
254                case CCID_ERR_PROT_NOSUP:
255                case CCID_ERR_CLASS_NOSUP:
256                        ret = IFD_ERROR_INCOMPATIBLE_DEVICE;
257                        break;
258                case CCID_ERR_BAD_PROC_BYTE:
259                        ret = IFD_ERROR_INVALID_ARG;
260                        break;
261                case CCID_ERR_BUSY_AUTO_SEQ:
262                case CCID_ERR_SLOT_BUSY:
263                        ret = IFD_ERROR_TIMEOUT;
264                        break;
265                case CCID_ERR_PIN_TIMEOUT:
266                        ret = IFD_ERROR_USER_TIMEOUT;
267                        break;
268                case CCID_ERR_PIN_CANCELED:
269                        ret = IFD_ERROR_USER_ABORT;
270                        break;
271                case CCID_OFFSET_MSGTYPE:
272                        ret = IFD_ERROR_NOT_SUPPORTED;
273                        break;
274                case CCID_OFFSET_SLOT:
275                        ret = IFD_ERROR_INVALID_SLOT;
276                        break;
277                default:
278                        ret = IFD_ERROR_GENERIC;
279                        break;
280                }
281        }
282
283        ifd_debug(1, "r: %d", ret);
284        return ret;
285}
286
287static int ccid_prepare_cmd(ifd_reader_t * reader, unsigned char *out,
288                            size_t outsz, int slot, unsigned char cmd,
289                            const void *ctl, const void *snd, size_t sendlen)
290{
291        ccid_status_t *st = (ccid_status_t *) reader->driver_data;
292        unsigned char *p = out;
293
294        if (slot >= reader->nslots)
295                return IFD_ERROR_INVALID_SLOT;
296        if (sendlen + 10 > outsz) {     /* this probably means the apdu is larger
297                                           than the supported MaxMessageSize - 10  */
298                ifd_debug(1, "error: unsupported (apdu larger than max outsz: %d, sendlen: %d)", outsz, sendlen);
299                return IFD_ERROR_NOT_SUPPORTED;
300        }
301        *p++ = cmd;
302        *p++ = sendlen & 0xFF;
303        *p++ = (sendlen >> 8) & 0xFF;
304        *p++ = (sendlen >> 16) & 0xFF;
305        *p++ = (sendlen >> 24) & 0xFF;
306        *p++ = slot;
307        *p++ = st->seq++;
308        if (ctl)
309                memcpy(p, (unsigned char *)ctl, 3);
310        else
311                memset(p, 0, 3);
312
313        if (sendlen)
314                memcpy(&p[3], (unsigned char *)snd, sendlen);
315        return sendlen + 10;
316}
317
318static int ccid_extract_data(const void *in, size_t inlen, void *out,
319                             size_t outlen)
320{
321        unsigned char dlen[4];
322        size_t len;
323
324        if (inlen < 5) {
325                ct_error("short response from reader?!");
326                return IFD_ERROR_BUFFER_TOO_SMALL;
327        }
328
329        memcpy(dlen, ((char *)in) + 1, 4);
330        len = dlen[0] | dlen[1] << 8 | dlen[2] << 16 | dlen[3] << 24;
331        if (len == 0)
332                return 0;
333        if (inlen < len + 10) {
334                ct_error("truncated response from reader");
335                return IFD_ERROR_BUFFER_TOO_SMALL;
336        }
337        if (outlen < len) {
338                ct_error("user buffer too small (%d < %d)", outlen, len);
339                return IFD_ERROR_BUFFER_TOO_SMALL;
340        }
341        memcpy(out, ((char *)in) + 10, len);
342        return len;
343}
344
345static int ccid_command(ifd_reader_t * reader, const unsigned char *cmd,
346                        size_t cmd_len, unsigned char *res, size_t res_len)
347{
348        int rc;
349        size_t req_len;
350
351        if (!cmd_len || !res_len) {
352                ct_error("missing parameters to ccid_command");
353                return IFD_ERROR_INVALID_ARG;
354        }
355        req_len = res_len;
356        if (ct_config.debug >= 3)
357                ifd_debug(3, "sending:%s", ct_hexdump(cmd, cmd_len));
358
359        rc = ifd_device_send(reader->device, cmd, cmd_len);
360        if (rc < 0) {
361                ifd_debug(1, "ifd_device_send failed %d", rc);
362                return rc;
363        }
364        while (1) {
365                rc = ifd_device_recv(reader->device, res, req_len, 10000);
366                if (rc < 0)
367                        return rc;
368                if (rc == 0) {
369                        ct_error("zero length response from reader?!");
370                        return IFD_ERROR_GENERIC;
371                }
372                if (ct_config.debug >= 3)
373                        ifd_debug(3, "received:%s", ct_hexdump(res, rc));
374
375                if (rc < 9) {
376                        return IFD_ERROR_GENERIC;
377                }
378                if (cmd[CCID_OFFSET_SLOT] == res[CCID_OFFSET_SLOT] &&
379                    cmd[CCID_OFFSET_SEQ] == res[CCID_OFFSET_SEQ]) {
380                        res_len = rc;
381                        rc = ccid_checkresponse(res, res_len);
382                        if (rc == -300) {
383                                continue;
384                        }
385                        if (rc < 0)
386                                return rc;
387                        break;
388                }
389
390        }
391        return res_len;
392}
393
394static int ccid_simple_rcommand(ifd_reader_t * reader, int slot, int cmd,
395                                void *ctl, void *res, size_t res_len)
396{
397        ccid_status_t *st = reader->driver_data;
398        unsigned char cmdbuf[10];
399        unsigned char resbuf[CCID_MAX_MSG_LEN + 1];
400        int r;
401
402        r = ccid_prepare_cmd(reader, cmdbuf, 10, slot, cmd, ctl, NULL, 0);
403        if (r < 0)
404                return r;
405
406        r = ccid_command(reader, cmdbuf, 10, resbuf, st->maxmsg);
407        if (r < 0)
408                return r;
409        if (resbuf[0] != msg_expected[cmd - CCID_CMD_FIRST]) {
410                ct_error("Received a message of type x%02x instead of x%02x",
411                         resbuf[0], msg_expected[cmd - CCID_CMD_FIRST]);
412                return -1;
413        }
414
415        if (res_len)
416                r = ccid_extract_data(&resbuf, r, res, res_len);
417        return r;
418}
419
420static int ccid_simple_wcommand(ifd_reader_t * reader, int slot, int cmd,
421                                void *ctl, void *data, size_t data_len)
422{
423        ccid_status_t *st = reader->driver_data;
424        unsigned char cmdbuf[CCID_MAX_MSG_LEN + 1];
425        unsigned char resbuf[CCID_MAX_MSG_LEN + 1];
426        int r;
427
428        r = ccid_prepare_cmd(reader, cmdbuf, st->maxmsg, slot, cmd, ctl, data,
429                             data_len);
430        if (r < 0)
431                return r;
432
433        r = ccid_command(reader, cmdbuf, r, resbuf, st->maxmsg);
434        if (r < 0)
435                return r;
436        if (resbuf[0] != msg_expected[cmd - CCID_CMD_FIRST]) {
437                ct_error("Received a message of type x%02x instead of x%02x",
438                         resbuf[0], msg_expected[cmd - CCID_CMD_FIRST]);
439                return -1;
440        }
441
442        return r;
443}
444
445#ifdef notyet
446static int ccid_abort(ifd_reader_t * reader, int slot)
447{
448        ccid_status_t *st = (ccid_status_t *) reader->driver_data;
449
450        int r;
451        if (ifd_device_type(reader->device) == IFD_DEVICE_TYPE_USB) {
452                r = ifd_usb_control(reader->device, 0x21
453                                    /*USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE */
454                                    ,
455                                    CCID_REQ_ABORT, st->seq << 8 | slot,
456                                    st->usb_interface, NULL, 0, 10000);
457                if (r < 0)
458                        return r;
459                r = ccid_simple_wcommand(reader, slot, CCID_CMD_ABORT, NULL,
460                                         NULL, 0);
461                return r;
462        } else
463            if (ifd_device_type(reader->device == IFD_DEVICE_TYPE_PCMCIA_BLOCK))
464        {
465                /* FIXME */
466                return IFD_ERROR_NOT_SUPPORTED;
467        }
468        return IFD_ERROR_NOT_SUPPORTED;
469}
470#endif
471
472static int ccid_exchange(ifd_reader_t * reader, int slot,
473                         const void *sbuf, size_t slen, void *rbuf, size_t rlen)
474{
475        ccid_status_t *st = reader->driver_data;
476        unsigned char sendbuf[CCID_MAX_MSG_LEN + 1];
477        unsigned char recvbuf[CCID_MAX_MSG_LEN + 1];
478        int r;
479        unsigned char ctlbuf[3], *ctlptr=NULL;
480
481        ctlptr=NULL;
482        if (st->reader_type == TYPE_CHAR) {
483                ctlbuf[0] = 0;
484                ctlbuf[1] = rlen & 0xff;
485                ctlbuf[2] = (rlen >> 8) & 0xff;
486                ctlptr = ctlbuf;
487        }
488
489        r = ccid_prepare_cmd(reader, sendbuf, st->maxmsg,
490                             slot, CCID_CMD_XFRBLOCK, ctlptr, sbuf, slen);
491        if (r < 0)
492                return r;
493
494        r = ccid_command(reader, &sendbuf[0], r, recvbuf, st->maxmsg);
495        if (r < 0)
496                return r;
497        return ccid_extract_data(&recvbuf, r, rbuf, rlen);
498}
499
500static int ccid_open_usb(ifd_device_t * dev, ifd_reader_t * reader)
501{
502        ccid_status_t *st;
503        ifd_device_params_t params;
504        int r, i, c, ifc, alt, num_alt;
505        struct ifd_usb_device_descriptor de;
506        struct ifd_usb_config_descriptor conf;
507        struct ifd_usb_interface_descriptor *intf;
508        struct usb_ccid_descriptor ccid = { 0 };
509        int force_parse;
510        struct force_parse_device_st *force_dev;
511        unsigned char *_class;
512        unsigned char *p;
513        int support_events = 0;
514
515#define PCSCLITE_FILE "/var/run/pcscd/pcscd.comm"
516        struct stat buf;
517
518        /* give priority to pcsc-lite for CCID devices */
519        if (0 == stat(PCSCLITE_FILE, &buf))
520                sleep(3);
521
522        if (ifd_usb_get_device(dev, &de)) {
523                ct_error("ccid: device descriptor not found");
524                ifd_device_close(dev);
525                return -1;
526        }
527
528        force_parse = 0;
529        for (force_dev = force_parse_devices; force_dev->vendor; force_dev++) {
530                if (de.idVendor == force_dev->vendor &&
531                    de.idProduct == force_dev->product) {
532                        force_parse = 1;
533                        break;
534                }
535        }
536
537        intf = NULL;
538        p = NULL;
539        r = i = 0;
540        memset(&conf, 0, sizeof(conf));
541        for (c = 0; c < de.bNumConfigurations; c++) {
542                if (ifd_usb_get_config(dev, c, &conf)) {
543                        ct_error("ccid: config descriptor %d not found", c);
544                        continue;
545                }
546                if (!conf.interface)
547                        continue;
548
549                for (ifc = 0; ifc < conf.bNumInterfaces; ifc++) {
550                        num_alt = conf.interface[ifc].num_altsetting;
551                        for (alt = 0; alt < num_alt; alt++) {
552                                int typeok = 0;
553                                int ok = 0;
554                                intf = &conf.interface[ifc].altsetting[alt];
555                                if (intf->bInterfaceClass == 0xb ||
556                                    intf->bInterfaceSubClass == 0 ||
557                                    intf->bInterfaceProtocol == 0)
558                                        typeok = 1;
559                                /* accept class 0xFF if force_parse != 0 */
560                                if (force_parse
561                                    && intf->bInterfaceClass == 0xff)
562                                        typeok = 1;
563                                if (intf->bNumEndpoints < 2
564                                    || intf->bNumEndpoints > 3)
565                                        typeok = 0;
566                                if (typeok == 0) {
567                                        intf = NULL;
568                                        continue;
569                                }
570                                if (intf->bNumEndpoints == 2) {
571                                        params.usb.ep_intr = 0;
572                                        ok |= 4;
573                                }
574                                if (intf->bNumEndpoints == 3) {
575                                        support_events = 1;
576                                }
577                                for (i = 0; i < intf->bNumEndpoints; i++) {
578                                        if (((intf->endpoint[i].bmAttributes &
579                                              IFD_USB_ENDPOINT_TYPE_MASK) ==
580                                             IFD_USB_ENDPOINT_TYPE_BULK) &&
581                                            (intf->endpoint[i].
582                                             bEndpointAddress &
583                                             IFD_USB_ENDPOINT_DIR_MASK) ==
584                                            IFD_USB_ENDPOINT_OUT) {
585                                                ok |= 1;
586                                                params.usb.ep_o =
587                                                    intf->endpoint[i].
588                                                    bEndpointAddress;
589                                        }
590                                        if (((intf->endpoint[i].bmAttributes &
591                                              IFD_USB_ENDPOINT_TYPE_MASK) ==
592                                             IFD_USB_ENDPOINT_TYPE_BULK) &&
593                                            (intf->endpoint[i].
594                                             bEndpointAddress &
595                                             IFD_USB_ENDPOINT_DIR_MASK) ==
596                                            IFD_USB_ENDPOINT_IN) {
597                                                ok |= 2;
598                                                params.usb.ep_i =
599                                                    intf->endpoint[i].
600                                                    bEndpointAddress;
601                                        }
602                                        if (((intf->endpoint[i].bmAttributes &
603                                              IFD_USB_ENDPOINT_TYPE_MASK) ==
604                                             IFD_USB_ENDPOINT_TYPE_INTERRUPT) &&
605                                            (intf->endpoint[i].
606                                             bEndpointAddress &
607                                             IFD_USB_ENDPOINT_DIR_MASK) ==
608                                            IFD_USB_ENDPOINT_IN) {
609                                                ok |= 4;
610                                                params.usb.ep_intr =
611                                                    intf->endpoint[i].
612                                                    bEndpointAddress;
613                                        }
614                                }
615                                if (ok == 7)
616                                        break;
617                                intf = NULL;
618                        }
619                        if (!intf)
620                                continue;
621                        if (!intf->extralen) {
622                                int i;
623                                /* Buggy O2 Micro CCID SC Reader has zero extra len at interface level but not endpoint descriptor.
624                                 * Patch the interface level field and proceed.
625                                 * ProdID 7762 reader is in Dell Latitude D620 and 7772 is in D630.
626                                 */
627                                if( de.idVendor == 0x0b97 && (de.idProduct == 0x7762 || de.idProduct == 0x7772) )  {
628                                        ct_error("ccid: extra len is zero, patching O2 Micro support");
629                                        for (i=0; i<intf->bNumEndpoints; i++)  {
630                                                /* find the extra[] array */
631                                                if( intf->endpoint[i].extralen == 54 )  {
632                                                        /* get the extra[] from the endpoint */
633                                                        intf->extralen = 54;
634                                                        /* avoid double free on close, allocate here */
635                                                        intf->extra = malloc(54);
636                                                        if( intf->extra )  {
637                                                                memcpy( intf->extra, intf->endpoint[i].extra, 54 );
638                                                                break;
639                                                        }
640                                                        else  {
641                                                                intf = NULL;
642                                                                continue;
643                                                        }
644                                                }
645                                        }
646                                }
647                                else  {
648                                        intf = NULL;
649                                        ct_error("ccid: extra len is zero, continuing");
650                                        continue;
651                                }
652                        }
653
654                        r = intf->extralen;
655                        _class = intf->extra;
656                        i = 0;
657                        p = _class + i;
658                        /* 0x21 == USB_TYPE_CLASS | 0x1 */
659                        /* accept descriptor type 0xFF if force_parse != 0 */
660                        while (i < r && p[0] > 2 &&
661                               (p[1] != 0x21 &&
662                                (force_parse == 0 || p[1] != 0xff))) {
663                                i += p[0];
664                                p = _class + i;
665                        }
666                        if (i >= r || p[0] < 2 ||
667                            (p[1] != 0x21 &&
668                             (force_parse == 0 || p[1] != 0xff))) {
669                                intf = NULL;
670                        }
671                        if (intf)
672                                break;
673                }
674                if (intf)
675                        break;
676                ifd_usb_free_configuration(&conf);
677        }
678
679        if (!intf) {
680                ct_error("ccid: class descriptor not found");
681                ifd_device_close(dev);
682                return -1;
683        }
684
685        /* Don't touch the device configuration if it's the one and only.
686         * The reason for this is that in multi purpose devices (eg keyboards
687         * with an integrated reader) some interfaces might already be in use.
688         * Trying to change the device configuration in such a case will produce
689         * this kernel message on Linux:
690         * usbfs: interface X claimed while 'ifdhandler' sets config #N
691         * and often the call will fail with EBUSY.
692         * Actually a bit better fix could be implemented in usb_set_params.
693         * The code there should check if the device is already in the requested
694         * configuration and thus if the change is needed after all. However
695         * implementing this would need a bunch of new sysdep functions to
696         * determine the current device configuration.
697         * So IMHO we should postpone this hard work until some USB device
698         * surfaces that really needs such magic.
699         *
700         * Antti Andreimann <Antti.Andreimann@mail.ee> Thu Feb 2 2006
701         */
702        if (de.bNumConfigurations > 1)
703                params.usb.configuration = conf.bConfigurationValue;
704        else
705                params.usb.configuration = -1;
706
707        params.usb.interface = intf->bInterfaceNumber;
708        if (num_alt > 1 || intf->bAlternateSetting > 0)
709                params.usb.altsetting = intf->bAlternateSetting;
710        else
711                params.usb.altsetting = -1;
712
713        r = ccid_parse_descriptor(&ccid, p, r - i);
714        ifd_usb_free_configuration(&conf);
715        if (r) {
716                ct_error("ccid: class descriptor is invalid");
717                ifd_device_close(dev);
718                return -1;
719        }
720
721        if (ccid.bcdCCID != 0x100 && ccid.bcdCCID != 0x110) {
722                ct_error("ccid: unknown ccid version %02x.%02x supported only 1.00, 1.10",
723                        (ccid.bcdCCID >> 8) & 0xff,
724                        (ccid.bcdCCID >> 0) & 0xff
725                );
726                ifd_device_close(dev);
727                return -1;
728        }
729
730        if ((st = (ccid_status_t *) calloc(1, sizeof(*st))) == NULL) {
731                ct_error("out of memory");
732                return IFD_ERROR_NO_MEMORY;
733        }
734
735        st->usb_interface = intf->bInterfaceNumber;
736        memset(st->icc_present, -1, OPENCT_MAX_SLOTS);
737        st->voltage_support = ccid.bVoltageSupport & 0x7;
738        st->proto_support = ccid.dwProtocols;
739        if ((st->proto_support & 3) == 0) {
740                ct_error
741                    ("ccid: device does not provide any supported protocols");
742                free(st);
743                ifd_device_close(dev);
744                return -1;
745        }
746
747/* "When a CCID doesn't declare the values 00000010h and 00000020h, the
748 * frequency or the baud rate must be made via manufacturer proprietary
749 * PC_to_RDR_Escape command." - ccid class specification v1.00
750 *
751 * "The value of the lower word (=0840) indicates that the host will only
752 * send requests that are valid for the USB-ICC." - ISO/IEC 7816-12:2005
753 * 7.2/Table 8
754 */
755        if ((ccid.dwFeatures & 0xFFFF) != 0x0840
756            && ~ccid.dwFeatures & (0x10 | 0x20)) {
757                ct_error("ccid: required card initialization features missing");
758                free(st);
759                ifd_device_close(dev);
760                return -1;
761        }
762
763        st->reader_type = TYPE_CHAR;
764
765        if (ccid.dwFeatures & 0x10000) {
766                st->reader_type = TYPE_TPDU;
767        } else if (ccid.dwFeatures & 0x60000) {
768                st->reader_type = TYPE_APDU;
769        }
770        if (ccid.dwFeatures & 0x2)
771                st->flags |= FLAG_AUTO_ATRPARSE;
772        if (ccid.dwFeatures & 0x4)
773                st->flags |= FLAG_AUTO_ACTIVATE;
774        if (ccid.dwFeatures & 0x8)
775                st->voltage_support |= AUTO_VOLTAGE;
776        if (ccid.dwFeatures & 0x40)
777                st->flags |= FLAG_NO_PTS | FLAG_NO_SETPARAM;
778        if (ccid.dwFeatures & 0x80)
779                st->flags |= FLAG_NO_PTS;
780        st->ifsd = ccid.dwMaxIFSD;
781
782        /* must provide AUTO or at least one of 5/3.3/1.8 */
783        if (st->voltage_support == 0) {
784                ct_error
785                    ("ccid: device does not provide any supported voltages");
786                free(st);
787                ifd_device_close(dev);
788                return -1;
789        }
790
791        if (ccid.dwMaxCCIDMessageLength > CCID_MAX_MSG_LEN) {
792                st->maxmsg = CCID_MAX_MSG_LEN;
793        } else {
794                st->maxmsg = ccid.dwMaxCCIDMessageLength;
795        }
796
797        reader->driver_data = st;
798        reader->device = dev;
799        reader->nslots = ccid.bMaxSlotIndex + 1;
800
801        if (ifd_device_set_parameters(dev, &params) < 0) {
802                ifd_device_close(dev);
803                return -1;
804        }
805        if (de.idVendor == 0x08e6 && de.idProduct == 0x3437) {
806                unsigned char settpdu[] = { 0xA0, 0x1 };
807                unsigned char setiso[] = { 0x1F, 0x1 };
808                r = ccid_simple_wcommand(reader, 0, CCID_CMD_ESCAPE, NULL,
809                                         settpdu, 2);
810                if (r < 0) {
811                        ct_error("ccid: cannot set GemPlus TPDU mode");
812                        ifd_device_close(dev);
813                        return -1;
814                }
815                r = ccid_simple_wcommand(reader, 0, CCID_CMD_ESCAPE, NULL,
816                                         setiso, 2);
817                if (r < 0) {
818                        ct_error("ccid: cannot set GemPlus ISO APDU mode");
819                        ifd_device_close(dev);
820                        return -1;
821                }
822                st->reader_type = TYPE_TPDU;
823        }
824
825        if (de.idVendor == 0x076b && de.idProduct == 0x5121) {
826                /* special handling of RFID part of OmniKey 5121 */
827                reader->nslots++;       /* one virtual slot for RFID escape */
828                st->proto_support |= SUPPORT_ESCAPE;
829        }
830
831        st->support_events = support_events;
832
833        ifd_debug(3, "Accepted %04x:%04x with features 0x%x and protocols 0x%x events=%d", de.idVendor, de.idProduct, ccid.dwFeatures, ccid.dwProtocols, st->support_events);
834        return 0;
835}
836
837static int ccid_open_pcmcia_block(ifd_device_t * dev, ifd_reader_t * reader)
838{
839        ccid_status_t *st;
840        /* unfortunately I know of no sanity checks that we could do with the
841         * hardware to confirm we're actually accessing a real pcmcia/ccid
842         * device -HW */
843
844        if ((st = (ccid_status_t *) calloc(1, sizeof(*st))) == NULL)
845                return IFD_ERROR_NO_MEMORY;
846
847        /* setup fake ccid_status_t based on totally guessed values */
848        memset(st->icc_present, -1, OPENCT_MAX_SLOTS);
849        st->voltage_support = 0x7;
850        st->proto_support = SUPPORT_T0 | SUPPORT_T1;
851        st->reader_type = TYPE_APDU;
852        st->voltage_support |= AUTO_VOLTAGE;
853        st->ifsd = 1;           /* ? */
854        st->maxmsg = CCID_MAX_MSG_LEN;
855        st->flags = FLAG_AUTO_ATRPARSE | FLAG_NO_PTS;   /*|FLAG_NO_SETPARAM; */
856
857        reader->driver_data = st;
858        reader->device = dev;
859        reader->nslots = 1;
860
861        return 0;
862}
863
864/*
865 * Initialize the device
866 */
867static int ccid_open(ifd_reader_t * reader, const char *device_name)
868{
869        ifd_device_t *dev;
870        reader->name = "CCID Compatible";
871        if (!(dev = ifd_device_open(device_name)))
872                return -1;
873        if (ifd_device_type(dev) == IFD_DEVICE_TYPE_USB)
874                return ccid_open_usb(dev, reader);
875        else if (ifd_device_type(dev) == IFD_DEVICE_TYPE_PCMCIA_BLOCK)
876                return ccid_open_pcmcia_block(dev, reader);
877        else {
878                ct_error("ccid: device %s is not a supported device",
879                         device_name);
880                ifd_device_close(dev);
881                return -1;
882        }
883}
884
885/*
886 * Close the device
887 */
888static int ccid_close(ifd_reader_t * reader)
889{
890        ccid_status_t *st = (ccid_status_t *) reader->driver_data;
891       
892        ifd_debug(1, "called.");
893
894        if (st->event_cap != NULL) {
895                ifd_usb_end_capture(reader->device, st->event_cap);
896                st->event_cap = NULL;
897        }
898
899        return 0;
900}
901
902static int ccid_activate(ifd_reader_t * reader)
903{
904        ifd_debug(1, "called.");
905        return 0;
906}
907
908static int ccid_deactivate(ifd_reader_t * reader)
909{
910        ifd_debug(1, "called.");
911        return 0;
912}
913
914static int ccid_card_status(ifd_reader_t * reader, int slot, int *status)
915{
916        ccid_status_t *st = (ccid_status_t *) reader->driver_data;
917        int r, stat;
918        unsigned char ret[20];
919        unsigned char cmdbuf[10];
920
921        if (ifd_device_type(reader->device) == IFD_DEVICE_TYPE_USB &&
922            reader->device->settings.usb.ep_intr) {
923                ifd_usb_capture_t *cap;
924                int any = 0;
925                int i, j, bits;
926
927                if (st->proto_support & SUPPORT_ESCAPE
928                    && slot == reader->nslots - 1) {
929                        ifd_debug(1,
930                                  "virtual escape slot, setting card present\n");
931                        *status = IFD_CARD_PRESENT;
932                        return 0;
933                }
934
935                i = 1 + (slot / 4);
936                j = 2 * (slot % 4);
937                stat = 0;
938
939                r = ifd_usb_begin_capture(reader->device,
940                                          IFD_USB_URB_TYPE_INTERRUPT,
941                                          reader->device->settings.usb.ep_intr,
942                                          8, &cap);
943                if (r < 0) {
944                        ct_error("ccid: begin capture: %d", r);
945                        return r;
946                }
947                /* read any bufferred interrupt pipe messages */
948                while (1) {
949                        r = ifd_usb_capture(reader->device, cap, ret, 8, 100);
950                        if (r < 0)
951                                break;
952                        if (ret[0] != 0x50)
953                                continue;
954                        ifd_debug(3, "status received:%s", ct_hexdump(ret, r));
955                        bits = (ret[i] >> j) & 0x3;
956                        if (bits & 2)
957                                stat |= IFD_CARD_STATUS_CHANGED;
958                        if (bits & 1)
959                                stat |= IFD_CARD_PRESENT;
960                        else
961                                stat &= ~IFD_CARD_PRESENT;
962                        any = 1;
963                }
964                ifd_usb_end_capture(reader->device, cap);
965                if (any) {
966                        ifd_debug(1, "polled result: %d", stat);
967                        st->icc_present[slot] = stat & IFD_CARD_PRESENT;
968                        *status = stat;
969                        return 0;
970                }
971                if (st->icc_present[slot] != 0xFF) {
972                        ifd_debug(1, "cached result: %d",
973                                  st->icc_present[slot]);
974                        *status = st->icc_present[slot];
975                        return 0;
976                }
977        }
978
979        r = ccid_prepare_cmd(reader, cmdbuf, 10, 0, CCID_CMD_GETSLOTSTAT,
980                             NULL, NULL, 0);
981        if (r < 0)
982                return r;
983        r = ccid_command(reader, cmdbuf, 10, ret, 10);
984        if (r == IFD_ERROR_NO_CARD) {
985                stat = 0;
986        }
987        else if (r < 0) {
988                return r;
989        }
990        else {
991                switch (ret[7] & 3) {
992                case 2:
993                        stat = 0;
994                        break;
995                default:
996                        stat = IFD_CARD_PRESENT;
997                        break;
998                }
999        }
1000
1001        ifd_debug(1, "probed result: %d, cached: %d", stat, st->icc_present[slot]);
1002
1003        *status = stat;
1004        if (
1005                st->icc_present[slot] == 0xFF ||
1006                (stat&IFD_CARD_PRESENT) != (st->icc_present[slot]&IFD_CARD_PRESENT)
1007        ) {
1008                *status |= IFD_CARD_STATUS_CHANGED;
1009        }
1010        st->icc_present[slot] = stat;
1011        return 0;
1012}
1013
1014static int ccid_set_protocol(ifd_reader_t * reader, int s, int proto);
1015
1016/*
1017 * Reset
1018 */
1019static int
1020ccid_card_reset(ifd_reader_t * reader, int slot, void *atr, size_t size)
1021{
1022        ccid_status_t *st = (ccid_status_t *) reader->driver_data;
1023        unsigned char buffer[IFD_MAX_ATR_LEN];
1024        char ctlbuf[3];
1025        int n, r, i;
1026        int status;
1027
1028        r = ccid_card_status(reader, slot, &status);
1029        if (r < 0)
1030                return r;
1031        if (!(status & IFD_CARD_PRESENT))
1032                return IFD_ERROR_NO_CARD;
1033
1034        if (st->proto_support & SUPPORT_ESCAPE && slot == reader->nslots - 1) {
1035                ifd_debug(1, "slot: %d, setting atr to 0xff", slot);
1036                *((char *)atr) = 0xff;
1037                ccid_set_protocol(reader, slot, IFD_PROTOCOL_ESCAPE);
1038                return 1;
1039        }
1040        memset(ctlbuf, 0, 3);
1041
1042        n = -1;
1043        if (st->voltage_support & AUTO_VOLTAGE
1044            || st->flags & FLAG_AUTO_ACTIVATE) {
1045                ifd_debug(1, "called. powering on with auto voltage selection");
1046                n = ccid_simple_rcommand(reader, slot, CCID_CMD_ICCPOWERON,
1047                                         ctlbuf, buffer, IFD_MAX_ATR_LEN);
1048        }
1049        if (n < 0 && (st->voltage_support & AUTO_VOLTAGE) == 0) {
1050                ifd_debug(1,
1051                          "called. powering on with manual voltage selection");
1052                for (i = 1; i <= 3; i++) {
1053                        if ((st->voltage_support & (1 << (i - 1))) == 0)
1054                                continue;
1055                        ifd_debug(3, "Trying voltage parameter %d", i);
1056                        ctlbuf[0] = i;
1057                        n = ccid_simple_rcommand(reader, slot,
1058                                                 CCID_CMD_ICCPOWERON, ctlbuf,
1059                                                 buffer, IFD_MAX_ATR_LEN);
1060                        if (n > 0)
1061                                break;
1062                }
1063        }
1064        if (n < 0)
1065                return n;
1066        if (n > size)
1067                return IFD_ERROR_BUFFER_TOO_SMALL;
1068        memcpy(atr, buffer, n);
1069
1070        return n;
1071}
1072
1073static int ccid_set_protocol(ifd_reader_t * reader, int s, int proto)
1074{
1075        ccid_status_t *st = (ccid_status_t *) reader->driver_data;
1076        unsigned char parambuf[17], ctl[3];
1077        ifd_slot_t *slot;
1078        ifd_protocol_t *p;
1079        ifd_atr_info_t atr_info;
1080        int r, paramlen;
1081
1082        slot = &reader->slot[s];
1083
1084        /* If we support RFID escaping, we only allow ESCAPE protocol
1085         * at the last (== virtual) slot */
1086        if ((st->proto_support & SUPPORT_ESCAPE)
1087            && (proto != IFD_PROTOCOL_ESCAPE)
1088            && (s == reader->nslots - 1)) {
1089                ct_error("reader doesn't support this protocol at this slot\n");
1090                return IFD_ERROR_NOT_SUPPORTED;
1091        }
1092
1093        switch (proto) {
1094        case IFD_PROTOCOL_T0:
1095                if (!(st->proto_support & SUPPORT_T0)) {
1096                        ct_error("reader does not support this protocol");
1097                        return IFD_ERROR_NOT_SUPPORTED;
1098                }
1099                break;
1100        case IFD_PROTOCOL_T1:
1101                if (!(st->proto_support & SUPPORT_T1)) {
1102                        ct_error("reader does not support this protocol");
1103                        return IFD_ERROR_NOT_SUPPORTED;
1104                }
1105                break;
1106        case IFD_PROTOCOL_ESCAPE:
1107                /* virtual "escape" fallthrough protocol for stacking RFID
1108                 * protocol stack on top of openct */
1109                if (!(st->proto_support & SUPPORT_ESCAPE)) {
1110                        ct_error("reader does not support this protocol");
1111                        return IFD_ERROR_NOT_SUPPORTED;
1112                }
1113                if (s != reader->nslots - 1) {
1114                        ct_error
1115                            ("reader doesn't support this protocol at this slot");
1116                        return IFD_ERROR_NOT_SUPPORTED;
1117                }
1118                p = ifd_protocol_new(IFD_PROTOCOL_ESCAPE, reader, slot->dad);
1119                if (!p) {
1120                        ct_error("%s: internal error", reader->name);
1121                        return -1;
1122                }
1123                if (slot->proto) {
1124                        ifd_protocol_free(slot->proto);
1125                        slot->proto = NULL;
1126                }
1127                slot->proto = p;
1128                st->icc_proto[s] = proto;
1129                ifd_debug(1, "set protocol to ESCAPE\n");
1130                return 0;
1131                break;
1132        default:
1133                ct_error("protocol unknown");
1134                return IFD_ERROR_NOT_SUPPORTED;
1135        }
1136
1137        if (st->reader_type == TYPE_APDU) {
1138                p = ifd_protocol_new(IFD_PROTOCOL_TRANSPARENT,
1139                                     reader, slot->dad);
1140                if (p == NULL) {
1141                        ct_error("%s: internal error", reader->name);
1142                        return -1;
1143                }
1144                if (slot->proto) {
1145                        ifd_protocol_free(slot->proto);
1146                        slot->proto = NULL;
1147                }
1148                slot->proto = p;
1149                st->icc_proto[s] = proto;
1150                return 0;
1151        }
1152
1153        r = ifd_atr_parse(&atr_info, slot->atr, slot->atr_len);
1154        if (r < 0) {
1155                ct_error("%s: Bad ATR", reader->name);
1156                return r;
1157        }
1158        /* ccid doesn't have a parameter for this */
1159        if (atr_info.TC[0] == 255)
1160                atr_info.TC[0] = -1;
1161
1162        /*
1163         * guard time increase must precede PTS
1164         * we don't need to do this separate step if
1165         * a) the ccid does automatic parameter setting, or
1166         * b) the ccid parses the atr itself, or
1167         * c) the ccid does pts itself when we set parameters, or
1168         * d) the ICC does not require extra guard time
1169         * In all but the first case, we'll do parameter setting later,
1170         * so fetch the default parameters now.
1171         */
1172        if ((st->flags & FLAG_NO_SETPARAM) == 0) {
1173                memset(parambuf, 0, sizeof(parambuf));
1174                memset(ctl, 0, 3);
1175                r = ccid_simple_rcommand(reader, s, CCID_CMD_GETPARAMS,
1176                        ctl, parambuf, 7);
1177                if (r < 0)
1178                        return r;
1179                if (proto == IFD_PROTOCOL_T0) {
1180                        paramlen = 5;
1181                        ctl[0] = 0;
1182                }
1183                else {
1184                        paramlen = 7;
1185                        ctl[0] = 1;
1186                }
1187                if ((st->flags & (FLAG_NO_PTS | FLAG_AUTO_ATRPARSE)) == 0 &&
1188                        atr_info.TC[0] != -1) {
1189
1190                        parambuf[2] = atr_info.TC[0];
1191                        r = ccid_simple_wcommand(reader, s, CCID_CMD_SETPARAMS,
1192                                ctl, parambuf, paramlen);
1193                        if (r < 0)
1194                                return r;
1195                }
1196        }
1197
1198        if ((st->flags & FLAG_NO_PTS) == 0 &&
1199                (proto == IFD_PROTOCOL_T1 || atr_info.TA[0] != -1)) {
1200
1201                unsigned char pts[7], ptsret[7];
1202                int ptslen;
1203
1204                ptslen = ifd_build_pts(&atr_info, proto, pts, sizeof(pts));
1205                if (ptslen < 0) {
1206                        ct_error("%s: Could not perform PTS: %s", reader->name,
1207                                 ct_strerror(r));
1208                        return ptslen;
1209                }
1210                r = ccid_exchange(reader, s, pts, ptslen, ptsret,
1211                                  ptslen);
1212                if (r < 0)
1213                        return r;
1214                r = ifd_verify_pts(&atr_info, proto, ptsret, r);
1215                if (r) {
1216                        ct_error("%s: Bad PTS response", reader->name);
1217                        return r;
1218                }
1219        }
1220
1221        if ((st->flags & FLAG_NO_SETPARAM) == 0 &&
1222                ((st->flags & FLAG_AUTO_ATRPARSE) == 0 ||
1223                proto != IFD_PROTOCOL_T0)) {
1224
1225                /* if FLAG_AUTO_ATRPARSE, only set the protocol. */
1226                if ((st->flags & FLAG_AUTO_ATRPARSE) == 0) {
1227                        if (proto == IFD_PROTOCOL_T0) {
1228                                /* TA1 -> Fi | Di */
1229                                if (atr_info.TA[0] != -1)
1230                                        parambuf[0] = atr_info.TA[0];
1231                                /* TC1 -> N */
1232                                if (atr_info.TC[0] != -1)
1233                                        parambuf[2] = atr_info.TC[0];
1234                                /* TC2 -> WI */
1235                                if (atr_info.TC[1] != -1)
1236                                        parambuf[3] = atr_info.TC[1];
1237                                /* TA3 -> clock stop parameter */
1238                                /* XXX check for IFD clock stop support */
1239                                if (atr_info.TA[2] != -1)
1240                                        parambuf[4] = atr_info.TA[2] >> 6;
1241                        }
1242                        else if (proto == IFD_PROTOCOL_T1) {
1243                                if (atr_info.TA[0] != -1)
1244                                        parambuf[0] = atr_info.TA[0];
1245                                parambuf[1] = 0x10;
1246                                /* TC3 -> LRC/CRC selection */
1247                                if (atr_info.TC[2] == 1)
1248                                        parambuf[1] |= 0x1;
1249                                else
1250                                        parambuf[1] &= 0xfe;
1251                                /* TC1 -> N */
1252                                if (atr_info.TC[0] != -1)
1253                                        parambuf[2] = atr_info.TC[0];
1254                                /* atr_info->TB3 -> BWI/CWI */
1255                                if (atr_info.TB[2] != -1)
1256                                        parambuf[3] = atr_info.TB[2];
1257                                /* TA3 -> IFSC */
1258                                if (atr_info.TA[2] != -1)
1259                                        parambuf[5] = atr_info.TA[2];
1260                                /*
1261                                 * XXX CCID supports setting up clock stop for T=1, but the
1262                                 * T=1 ATR does not define a clock-stop byte.
1263                                 */
1264                        }
1265                }
1266                r = ccid_simple_wcommand(reader, s, CCID_CMD_SETPARAMS, ctl,
1267                        parambuf, paramlen);
1268                if (r < 0)
1269                        return r;
1270        }
1271
1272        memset(&parambuf[r], 0, sizeof(parambuf) - r);
1273        if (proto == IFD_PROTOCOL_T0) {
1274                if (st->reader_type == TYPE_CHAR) {
1275                        p = ifd_protocol_new(proto,
1276                                             reader, slot->dad);
1277                } else {
1278                        p = ifd_protocol_new(IFD_PROTOCOL_TRANSPARENT,
1279                                             reader, slot->dad);
1280                }
1281        } else {
1282                p = ifd_protocol_new(proto, reader, slot->dad);
1283                if (p) {
1284                        /* guessing that ifsc is limited by ifsd */
1285                        if (atr_info.TA[2] != -1)
1286                                ifd_protocol_set_parameter(p,
1287                                                           IFD_PROTOCOL_T1_IFSC,
1288                                                           atr_info.TA[2] >
1289                                                           st->ifsd ? st->
1290                                                           ifsd : atr_info.
1291                                                           TA[2]);
1292                        ifd_protocol_set_parameter(p, IFD_PROTOCOL_T1_IFSD,
1293                                                   st->ifsd);
1294                        if (atr_info.TC[2] == 1)
1295                                ifd_protocol_set_parameter(p,
1296                                                           IFD_PROTOCOL_T1_CHECKSUM_CRC,
1297                                                           0);
1298                }
1299        }
1300        if (p == NULL) {
1301                ct_error("%s: internal error", reader->name);
1302                return -1;
1303        }
1304        /* ccid_recv needs to know the exact expected data length */
1305        if (st->reader_type == TYPE_CHAR)
1306                ifd_protocol_set_parameter(p, IFD_PROTOCOL_BLOCK_ORIENTED, 0);
1307        if (slot->proto) {
1308                ifd_protocol_free(slot->proto);
1309                slot->proto = NULL;
1310        }
1311        slot->proto = p;
1312        st->icc_proto[s] = proto;
1313        return 0;
1314}
1315
1316static int ccid_escape(ifd_reader_t * reader, int slot, const void *sbuf,
1317                       size_t slen, void *rbuf, size_t rlen)
1318{
1319        unsigned char sendbuf[CCID_MAX_MSG_LEN];
1320        unsigned char recvbuf[CCID_MAX_MSG_LEN];
1321        int r;
1322
1323        ifd_debug(1, "slot: %d, slen %d, rlen %d", slot, slen, rlen);
1324
1325        r = ccid_prepare_cmd(reader, sendbuf, sizeof(sendbuf), slot,
1326                             CCID_CMD_ESCAPE, NULL, sbuf, slen);
1327        if (r < 0)
1328                return r;
1329
1330        r = ccid_command(reader, &sendbuf[0], r, recvbuf, sizeof(recvbuf));
1331        if (r < 0)
1332                return r;
1333
1334        return ccid_extract_data(&recvbuf, r, rbuf, rlen);
1335}
1336
1337static int
1338ccid_transparent(ifd_reader_t * reader, int slot,
1339                 const void *sbuf, size_t slen, void *rbuf, size_t rlen)
1340{
1341        ccid_status_t *st = (ccid_status_t *) reader->driver_data;
1342
1343        ifd_debug(1, "called. reader_type: %d, icc_proto[slot]=%d", st->reader_type, st->icc_proto[slot]);
1344        if (st->reader_type == TYPE_APDU ||
1345            (st->reader_type == TYPE_TPDU &&
1346             st->icc_proto[slot] == IFD_PROTOCOL_T0))
1347                return ccid_exchange(reader, slot, sbuf, slen, rbuf, rlen);
1348
1349        ifd_debug(1, "error: unsupported (slot settings)");
1350        return IFD_ERROR_NOT_SUPPORTED;
1351}
1352
1353static int ccid_send(ifd_reader_t * reader, unsigned int dad,
1354                     const unsigned char *buffer, size_t len)
1355{
1356        ccid_status_t *st = (ccid_status_t *) reader->driver_data;
1357        unsigned char *apdu;
1358
1359        ifd_debug(1, "called.");
1360        if (st->sbuf[dad]) {
1361                free(st->sbuf[dad]);
1362                st->sbuf[dad] = NULL;
1363                st->slen[dad] = 0;
1364        }
1365
1366        apdu = (unsigned char *)calloc(1, len);
1367        if (!apdu) {
1368                ct_error("out of memory");
1369                return IFD_ERROR_NO_MEMORY;
1370        }
1371        memcpy(apdu, buffer, len);
1372        st->sbuf[dad] = apdu;
1373        st->slen[dad] = len;
1374        return 0;
1375}
1376
1377static int ccid_recv(ifd_reader_t * reader, unsigned int dad,
1378                     unsigned char *buffer, size_t len, long timeout)
1379{
1380        ccid_status_t *st = (ccid_status_t *) reader->driver_data;
1381        int r;
1382
1383        ifd_debug(1, "called.");
1384
1385        r = ccid_exchange(reader, dad, st->sbuf[dad], st->slen[dad], buffer,
1386                          len);
1387        if (st->sbuf[dad])
1388                free(st->sbuf[dad]);
1389        st->sbuf[dad] = NULL;
1390        st->slen[dad] = 0;
1391        if (r < 0)
1392                ifd_debug(3, "failed: %d", r);
1393        return r;
1394}
1395
1396static int ccid_before_command(ifd_reader_t * reader)
1397{
1398        ccid_status_t *st = (ccid_status_t *) reader->driver_data;
1399        int rc;
1400
1401        ifd_debug(1, "called.");
1402
1403        if (!st->events_active) {
1404                return 0;
1405        }
1406
1407        if (st->event_cap == NULL) {
1408                return 0;
1409        }
1410
1411        rc = ifd_usb_end_capture(reader->device, st->event_cap);
1412        st->event_cap = NULL;
1413
1414        return rc;
1415}
1416
1417static int ccid_after_command(ifd_reader_t * reader)
1418{
1419        ccid_status_t *st = (ccid_status_t *) reader->driver_data;
1420
1421        ifd_debug(1, "called.");
1422
1423        if (!st->events_active) {
1424                return 0;
1425        }
1426
1427        if (st->event_cap != NULL) {
1428                return 0;
1429        }
1430
1431        return ifd_usb_begin_capture(
1432                reader->device,
1433                IFD_USB_URB_TYPE_INTERRUPT,
1434                reader->device->settings.usb.ep_intr,
1435                8, &st->event_cap
1436        );
1437}
1438
1439static int ccid_get_eventfd(ifd_reader_t * reader, short *events)
1440{
1441        ccid_status_t *st = (ccid_status_t *) reader->driver_data;
1442        int fd;
1443
1444        ifd_debug(1, "called.");
1445
1446        if (!st->support_events) {
1447                return -1;
1448        }
1449
1450        fd = ifd_device_get_eventfd(reader->device, events);
1451
1452        if (fd != -1) {
1453                st->events_active = 1;
1454        }
1455
1456        return fd;
1457}
1458
1459static int ccid_event(ifd_reader_t * reader, int *status, size_t status_size)
1460{
1461        ccid_status_t *st = (ccid_status_t *) reader->driver_data;
1462        unsigned char ret[20];
1463        int bytes;
1464
1465        ifd_debug(1, "called.");
1466
1467        if (status_size < reader->nslots) {
1468                return IFD_ERROR_BUFFER_TOO_SMALL;
1469        }
1470
1471        bytes = ifd_usb_capture_event(reader->device, st->event_cap, ret, 8);
1472        if (bytes < 0) {
1473                return bytes;
1474        }
1475
1476        if (bytes > 0 && ret[0] == 0x50) {
1477                int slot;
1478                ifd_debug(3, "status received:%s", ct_hexdump(ret, bytes));
1479                for (slot=0;slot<reader->nslots;slot++) {
1480                        if (1 + (slot / 4) < bytes) {
1481                                int bits = (ret[1 + (slot / 4)] >> (2 * (slot % 4))) & 0x3;
1482                                if (bits & 2)
1483                                        status[slot] |= IFD_CARD_STATUS_CHANGED;
1484                                if (bits & 1)
1485                                        status[slot] |= IFD_CARD_PRESENT;
1486                                else
1487                                        status[slot] &= ~IFD_CARD_PRESENT;
1488
1489                                ifd_debug(1, "slot %d event result: %08x", slot, status[slot]);
1490                                st->icc_present[slot] = status[slot] & IFD_CARD_PRESENT;
1491                        }
1492                }
1493        }
1494
1495        return 0;
1496}
1497
1498static int ccid_error(ifd_reader_t * reader)
1499{
1500        (void)reader;
1501
1502        ifd_debug(1, "called.");
1503
1504        return IFD_ERROR_DEVICE_DISCONNECTED;
1505}
1506
1507/*
1508 * Driver operations
1509 */
1510static struct ifd_driver_ops ccid_driver;
1511
1512/*
1513 * Initialize this module
1514 */
1515void ifd_ccid_register(void)
1516{
1517        ccid_driver.open = ccid_open;
1518        ccid_driver.close = ccid_close;
1519        ccid_driver.activate = ccid_activate;
1520        ccid_driver.deactivate = ccid_deactivate;
1521        ccid_driver.card_status = ccid_card_status;
1522        ccid_driver.card_reset = ccid_card_reset;
1523        ccid_driver.set_protocol = ccid_set_protocol;
1524        ccid_driver.transparent = ccid_transparent;
1525        ccid_driver.send = ccid_send;
1526        ccid_driver.recv = ccid_recv;
1527        ccid_driver.escape = ccid_escape;
1528        ccid_driver.before_command = ccid_before_command;
1529        ccid_driver.after_command = ccid_after_command;
1530        ccid_driver.get_eventfd = ccid_get_eventfd;
1531        ccid_driver.event = ccid_event;
1532        ccid_driver.error = ccid_error;
1533
1534        ifd_driver_register("ccid", &ccid_driver);
1535}
Note: See TracBrowser for help on using the repository browser.