source: trunk/src/ifd/ifd-acr30u.c @ 951

Revision 951, 12.7 KB checked in by aj, 5 years ago (diff)

and more static definitions.

Line 
1/*
2 * ACR30U driver
3 * Copyright (C) 2005, Laurent Pinchart <laurent.pinchart@skynet.be>
4 */
5
6#include "internal.h"
7#include "usb-descriptors.h"
8
9#include <stdlib.h>
10#include <string.h>
11
12/* Maximum buffer sizes
13 *
14 * The send buffer must be able to contain a short APDU. In the worst case
15 * (Case 4S, Lc = 255), the APDU will be 5 (CLA + INS + P1 + P2 + Lc) +
16 * 255 (Data) + 1 (Le) = 261 bytes long. The send buffer must then be big
17 * enough to contain an extended command with 261 bytes of data, which gives
18 * us a total of 5 (HDR + INS + LEN) + 261 (APDU) + 1 (CHK) = 267 bytes.
19 *
20 * The receive buffer must be able to contain a short APDU response. In the
21 * worst case (Case 2S or Case 4S, Le = 256), the APDU will be 256 (Data) +
22 * 2 (SW1, SW2) = 258 bytes long. The receive buffer must then be big enough
23 * to contain an extended response with 258 bytes of data, which gives us a
24 * total of 6 (HDR + SW1 + SW2 + LEN) + 258 (APDU) + 1 (CHK) = 265 bytes.
25 *
26 * The ASCII buffer must be able to contain either the command or the reply
27 * with the STX and ETX bytes.
28 */
29typedef struct acr_priv {
30        int icc_proto;
31        unsigned char sw1, sw2;
32        unsigned char abuf[267 * 2 + 2];
33        unsigned char sbuf[267];
34        unsigned char rbuf[265];
35        unsigned int head, tail;
36} acr_priv_t;
37
38typedef int complete_fn_t(const void *, size_t);
39
40#define ACR_GET_STATUS                  0x01
41#define ACR_SELECT_CARD_TYPE            0x02
42#define ACR_SET_PROTOCOL                0x03
43#define ACR_SET_NOTIFICATION            0x06
44#define ACR_SET_OPTION                  0x07
45#define ACR_RESET                       0x80
46#define ACR_POWER_OFF                   0x81
47#define ACR_ACTIVATE_SAM                0X88
48#define ACR_DEACTIVATE_SAM              0X89
49#define ACR_READ_DATA                   0x90
50#define ACR_WRITE_DATA                  0x91
51#define ACR_PRESENT_CODE                0x92
52#define ACR_CHANGE_CODE                 0X93
53#define ACR_WRITE_PROTECTION            0x94
54#define ACR_EXCHANGE_APDU               0xa0
55#define ACR_EXCHANGE_T1                 0xa1
56#define ACR_EXCHANGE_SAM_APDU           0xb0
57#define ACR_EXCHANGE_SAM_T1             0xb1
58
59#define ACR_CARD_AUTO                   0x00
60#define ACR_CARD_GPM103                 0x01
61#define ACR_CARD_I2C                    0x02
62#define ACR_CARD_SLE44x8                0x05
63#define ACR_CARD_SLE44x2                0x06
64#define ACR_CARD_MCU_T0                 0x0c
65#define ACR_CARD_MCU_T1                 0x0d
66#define ACR_CARD_SAM_T0                 0xc0
67#define ACR_CARD_SAM_T1                 0xd0
68
69#define ACR_STATUS_DATA_ERROR           0x60
70#define ACR_STATUS_COMMAND_ERROR        0x67
71#define ACR_STATUS_OK                   0x90
72#define ACR_STATUS_STATUS               0xff
73
74#define ACR_STATUS_LENGTH               16
75
76/*
77 * Send USB control message, and receive data via
78 * Interrupt URBs.
79 */
80static int
81acr_usb_int(ifd_device_t * dev, int requesttype, int request,
82            int value, int idx,
83            const void *sbuf, size_t slen,
84            void *rbuf, size_t rlen, complete_fn_t complete, long timeout)
85{
86        ifd_usb_capture_t *cap;
87        struct timeval begin;
88        unsigned int total = 0;
89        unsigned char *etx;
90        int rc;
91
92        if (timeout < 0)
93                timeout = dev->timeout;
94
95        rc = ifd_usb_begin_capture(dev,
96                                   IFD_USB_URB_TYPE_INTERRUPT, 0x81, 8, &cap);
97        if (rc < 0)
98                return rc;
99
100        gettimeofday(&begin, NULL);
101        ifd_debug(3, "sending %u bytes:%s", slen, ct_hexdump(sbuf, slen));
102        rc = ifd_usb_control(dev, requesttype, request,
103                             value, idx, (void *)sbuf, slen, timeout);
104        if (rc < 0)
105                goto out;
106
107        /* Capture URBs until we have a complete answer */
108        while (rc >= 0 && total < rlen) {
109                unsigned char temp[8];
110                long wait;
111
112                wait = timeout - ifd_time_elapsed(&begin);
113                if (wait <= 0)
114                        return IFD_ERROR_TIMEOUT;
115                memset(temp, 0, sizeof temp);
116                rc = ifd_usb_capture(dev, cap, temp, sizeof(temp), wait);
117                if (rc > 0) {
118                        if (rc > (int)(rlen - total))
119                                rc = rlen - total;
120                        memcpy((caddr_t) rbuf + total, temp, rc);
121                        total += rc;
122
123                        if (complete && complete(rbuf, total))
124                                break;
125                }
126        }
127
128        /* Why does the USB spec provide short packets if the device doesn't
129         * use them ? Every interrupt URB contains 8 bytes, which means we
130         * must discard everything after the ETX marker or we will end up
131         * with garbage.
132         */
133        if ((etx = memchr(rbuf, 0x03, total)) != NULL)
134                total = etx - (unsigned char *)rbuf + 1;
135
136        if (rc >= 0) {
137                ifd_debug(3, "received %u bytes:%s", total,
138                          ct_hexdump(rbuf, total));
139                rc = total;
140        }
141
142      out:
143        ifd_usb_end_capture(dev, cap);
144        return rc;
145}
146
147static int acr_reply_complete(const void *ptr, size_t len)
148{
149        return memchr(ptr, 0x03, len) != NULL;
150}
151
152/*
153 * Transmit a command to the reader.
154 */
155static int
156acr_transmit(ifd_reader_t * reader,
157             const void *sbuf, size_t slen, void *rbuf, size_t rlen)
158{
159        static const char acr_hex[16] = "0123456789ABCDEF";
160
161        acr_priv_t *priv = (acr_priv_t *) reader->driver_data;
162        ifd_device_t *dev = reader->device;
163        unsigned char *abuf = priv->abuf;
164        unsigned char *cbuf = (unsigned char *)sbuf;
165        unsigned char checksum;
166        unsigned char c;
167        int requesttype;
168        int rc;
169        int i;
170
171        if (slen > 261)
172                return IFD_ERROR_GENERIC;
173
174        /* Convert the command to ascii and compute the checksum */
175        *abuf++ = 0x02;
176
177        checksum = 0x01;
178        *abuf++ = '0';
179        *abuf++ = '1';
180
181        for (i = 0; i < (int)slen; ++i) {
182                checksum ^= cbuf[i];
183                *abuf++ = acr_hex[cbuf[i] >> 4];
184                *abuf++ = acr_hex[cbuf[i] & 0x0f];
185        }
186
187        *abuf++ = acr_hex[checksum >> 4];
188        *abuf++ = acr_hex[checksum & 0x0f];
189        *abuf++ = 0x03;
190
191        /* Transmit the encoded command */
192        requesttype = IFD_USB_RECIP_DEVICE
193            | IFD_USB_TYPE_VENDOR | IFD_USB_ENDPOINT_OUT;
194        rc = acr_usb_int(dev, requesttype, 0, 0, 0, priv->abuf, slen * 2 + 6,
195                         priv->abuf, sizeof priv->abuf, acr_reply_complete, -1);
196
197        if (rc <= 0)
198                return rc;
199
200        if (rc < 12) {
201                ct_error("acr: communication error: short response received");
202                return IFD_ERROR_COMM_ERROR;
203        }
204
205        /* Decode and verify the response */
206        abuf = priv->abuf;
207        if (abuf[0] != 0x02 || abuf[rc - 1] != 0x03) {
208                ifd_debug(1, "data: %s", ct_hexdump(abuf, rc));
209                ct_error("acr: communication error: invalid header/footer");
210                return IFD_ERROR_COMM_ERROR;
211        }
212
213        abuf++;
214        rc = (rc - 2) / 2;
215        checksum = 0;
216
217        for (i = 0; i < rc; ++i) {
218                *abuf -= '0';
219                if (*abuf > 9)
220                        *abuf -= 'A' - '0' - 10;
221                c = (*abuf++ & 0x0f) << 4;
222                *abuf -= '0';
223                if (*abuf > 9)
224                        *abuf -= 'A' - '0' - 10;
225                c += *abuf++ & 0x0f;
226
227                priv->abuf[i] = c;
228                checksum ^= c;
229        }
230
231        if (checksum != 0) {
232                ct_error("acr: communication error: invalid checksum");
233                return IFD_ERROR_COMM_ERROR;
234        }
235
236        priv->sw1 = priv->abuf[1];
237        priv->sw2 = priv->abuf[2];
238        if (priv->abuf[3] == 0xff) {
239                rc = (priv->abuf[4] << 8) + priv->abuf[5];
240                abuf = &priv->abuf[6];
241        } else {
242                rc = priv->abuf[3];
243                abuf = &priv->abuf[4];
244        }
245
246        if (rc > (int)rlen) {
247                ifd_debug(1, "received more data than requested, "
248                          "discarding data: %s", ct_hexdump(abuf, rlen - rc));
249        }
250
251        rc = rc > (int)rlen ? (int)rlen : rc;
252        memcpy(rbuf, abuf, rc);
253        return rc;
254}
255
256/*
257 * Read the reader status
258 */
259static int acr_reader_status(ifd_reader_t * reader, void *status, size_t len)
260{
261        unsigned char cmd[2];
262        int rc;
263
264        cmd[0] = ACR_GET_STATUS;
265        cmd[1] = 0x00;
266
267        rc = acr_transmit(reader, &cmd, sizeof cmd, status, len);
268        if (rc < 0)
269                return rc;
270
271        if (rc != ACR_STATUS_LENGTH) {
272                ct_error("acr: invalid status length");
273                return IFD_ERROR_COMM_ERROR;
274        }
275
276        return rc;
277}
278
279/*
280 * Initialize the device
281 */
282static int acr_open(ifd_reader_t * reader, const char *device_name)
283{
284        ifd_device_t *dev;
285        acr_priv_t *priv;
286        ifd_device_params_t params;
287        unsigned char status[ACR_STATUS_LENGTH];
288        int rc;
289
290        if (!(dev = ifd_device_open(device_name)))
291                return -1;
292        if (ifd_device_type(dev) != IFD_DEVICE_TYPE_USB) {
293                ct_error("acr30u: device %s is not a USB device", device_name);
294                ifd_device_close(dev);
295                return -1;
296        }
297
298        params = dev->settings;
299        params.usb.interface = 0;
300        if (ifd_device_set_parameters(dev, &params) < 0) {
301                ct_error("acr30u: setting parameters failed", device_name);
302                ifd_device_close(dev);
303                return -1;
304        }
305        priv = (acr_priv_t *) calloc(1, sizeof(acr_priv_t));
306
307        reader->driver_data = priv;
308        reader->device = dev;
309        reader->name = NULL;
310        reader->nslots = 1;
311
312        dev->timeout = 2000;
313
314        if ((rc = acr_reader_status(reader, status, sizeof status)) < 0)
315                return rc;
316
317        /* strndup is a GNU extension, so it might not be available on all
318         * the target platforms. Use malloc and memcpy instead.
319         */
320        reader->name = (char *)calloc(1, 11);
321        memcpy((char *)reader->name, status, 10);
322        ifd_debug(1, "found %s reader.", reader->name);
323        ifd_debug(1, "supported cards: %02x%02x", status[12], status[13]);
324
325        return 0;
326}
327
328/*
329 * Close the device
330 */
331static int acr_close(ifd_reader_t * reader)
332{
333        free((char *)reader->name);
334        free(reader->driver_data);
335        return 0;
336}
337
338/*
339 * Power up the reader - always powered up.
340 * TODO: What about an USB standby mode ?
341 */
342static int acr_activate(ifd_reader_t * reader)
343{
344        ifd_debug(1, "called.");
345        return 0;
346}
347
348static int acr_deactivate(ifd_reader_t * reader)
349{
350        ifd_debug(1, "called.");
351        return -1;
352}
353
354/*
355 * Card status
356 */
357static int acr_card_status(ifd_reader_t * reader, int slot, int *status)
358{
359        unsigned char acr_status[ACR_STATUS_LENGTH];
360        int rc;
361
362        *status = 0;
363
364        if ((rc = acr_reader_status(reader, acr_status, sizeof acr_status)) < 0) {
365                ct_error("acr: failed to get card status");
366                return -1;
367        }
368
369        ifd_debug(2, "C_SEL: %02x C_STAT: %02x",
370                  acr_status[14], acr_status[15]);
371
372        if (acr_status[15])
373                *status = IFD_CARD_PRESENT;
374
375        ifd_debug(2, "card %spresent", *status ? "" : "not ");
376        return 0;
377}
378
379/*
380 * Reset
381 */
382static int
383acr_card_reset(ifd_reader_t * reader, int slot, void *atr, size_t size)
384{
385        unsigned char buffer[IFD_MAX_ATR_LEN];
386        unsigned char cmd[2];
387        int rc;
388
389        cmd[0] = ACR_RESET;
390        cmd[1] = 0x00;
391
392        rc = acr_transmit(reader, &cmd, sizeof cmd, buffer, sizeof buffer);
393        if (rc < 0)
394                return rc;
395
396        if (rc < (int)size)
397                size = rc;
398
399        memcpy(atr, buffer, size);
400        return size;
401}
402
403/*
404 * Select a protocol for communication with the ICC.
405 */
406static int acr_set_protocol(ifd_reader_t * reader, int nslot, int proto)
407{
408        ifd_slot_t *slot;
409        acr_priv_t *priv;
410        unsigned char cmd[3];
411        int rc;
412
413        ifd_debug(1, "called, proto=%d", proto);
414
415        cmd[0] = ACR_SELECT_CARD_TYPE;
416        cmd[1] = 0x01;
417
418        switch (proto) {
419        case IFD_PROTOCOL_T0:
420                cmd[2] = ACR_CARD_MCU_T0;
421                break;
422        case IFD_PROTOCOL_T1:
423                cmd[2] = ACR_CARD_MCU_T1;
424                break;
425        default:
426                return IFD_ERROR_NOT_SUPPORTED;
427        }
428
429        if ((rc = acr_transmit(reader, cmd, sizeof cmd, NULL, 0)) < 0) {
430                ct_error("acr: unable to set the protocol");
431                return IFD_ERROR_COMM_ERROR;
432        }
433
434        slot = &reader->slot[nslot];
435        slot->proto = ifd_protocol_new(proto, reader, slot->dad);
436        if (slot->proto == NULL) {
437                ct_error("acr: unable to create protocol");
438                return -1;
439        }
440        ifd_protocol_set_parameter(slot->proto, IFD_PROTOCOL_BLOCK_ORIENTED, 1);
441
442        priv = (acr_priv_t *) reader->driver_data;
443        priv->icc_proto = proto;
444
445        return 0;
446}
447
448/*
449 * Send/receive routines
450 */
451static int
452acr_send_t0(ifd_reader_t * reader, unsigned int dad, const unsigned char *sbuf,
453            size_t slen)
454{
455        acr_priv_t *priv = (acr_priv_t *) reader->driver_data;
456        ifd_iso_apdu_t iso;
457        int rc;
458
459        if (slen > 260)
460                return IFD_ERROR_GENERIC;
461
462        /* The reader expects Lc and Le to always be present, so fix the
463         * APDU to add a null Le byte for Case 1, Case 3S and Case 4S and
464         * insert a null Lc byte for Case 2S. The T=0 protocol handler already
465         * took care of inserting a null Lc byte for Case 1, and removed the
466         * Le byte for Case 4S.
467         */
468        priv->sbuf[0] = ACR_EXCHANGE_APDU;
469        priv->sbuf[1] = slen + 1;
470        memcpy(&priv->sbuf[2], sbuf, slen);
471
472        if ((rc = ifd_iso_apdu_parse(sbuf, slen, &iso)) < 0)
473                return rc;
474
475        if (iso.cse == IFD_APDU_CASE_2S) {
476                priv->sbuf[slen + 2] = priv->sbuf[slen + 1];
477                priv->sbuf[slen + 1] = 0;
478        } else
479                priv->sbuf[slen + 2] = 0;
480
481        priv->head = priv->tail = 0;
482        rc = acr_transmit(reader, priv->sbuf, slen + 3, priv->rbuf,
483                          sizeof priv->rbuf);
484        if (rc >= 0) {
485                priv->tail = rc;
486                rc = slen;
487        }
488        return rc;
489}
490
491static int
492acr_send(ifd_reader_t * reader, unsigned int dad, const unsigned char *buffer,
493         size_t len)
494{
495        acr_priv_t *priv = (acr_priv_t *) reader->driver_data;
496
497        switch (priv->icc_proto) {
498        case IFD_PROTOCOL_T0:
499                return acr_send_t0(reader, dad, buffer, len);
500        }
501
502        return IFD_ERROR_NOT_SUPPORTED;
503}
504
505static int
506acr_recv(ifd_reader_t * reader, unsigned int dad, unsigned char *buffer,
507         size_t len, long timeout)
508{
509        acr_priv_t *priv = (acr_priv_t *) reader->driver_data;
510
511        switch (priv->icc_proto) {
512        case IFD_PROTOCOL_T0:
513                if (priv->tail - priv->head < len)
514                        len = priv->tail - priv->head;
515                memcpy(buffer, priv->rbuf + priv->head, len);
516                priv->head += len;
517                return len;
518        }
519        return IFD_ERROR_NOT_SUPPORTED; /* not yet */
520}
521
522#if 0
523/*
524 * Set the card's baud rate etc
525 */
526static int acr_set_card_parameters(ifd_device_t * dev, unsigned int baudrate)
527{
528        return 0;
529}
530#endif
531
532/*
533 * Driver operations
534 */
535static struct ifd_driver_ops acr30u_driver;
536
537/*
538 * Initialize this module
539 */
540void ifd_acr30u_register(void)
541{
542        memset(&acr30u_driver, 0, sizeof acr30u_driver);
543
544        acr30u_driver.open = acr_open;
545        acr30u_driver.close = acr_close;
546        acr30u_driver.activate = acr_activate;
547        acr30u_driver.deactivate = acr_deactivate;
548        acr30u_driver.card_status = acr_card_status;
549        acr30u_driver.card_reset = acr_card_reset;
550        acr30u_driver.send = acr_send;
551        acr30u_driver.recv = acr_recv;
552        acr30u_driver.set_protocol = acr_set_protocol;
553
554        ifd_driver_register("acr30u", &acr30u_driver);
555}
Note: See TracBrowser for help on using the repository browser.