source: trunk/src/ifd/proto-sync.c @ 950

Revision 950, 5.4 KB checked in by aj, 5 years ago (diff)

work on lots of warnings, mostly things once declared with static and later without.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2 * Implementation of synchronous protocols
3 *
4 * Copyright (C) 2003, Olaf Kirch <okir@suse.de>
5 */
6
7#include "internal.h"
8#include <sys/poll.h>
9#include <unistd.h>
10#include <stdlib.h>
11#include <string.h>
12
13typedef struct {
14        ifd_protocol_t base;
15} sync_state_t;
16
17/*
18 * Detach protocol
19 */
20static void sync_release(ifd_protocol_t * prot)
21{
22        /* NOP */
23}
24
25/*
26 * Read/write operations
27 */
28static int sync_read(ifd_protocol_t * prot, int slot, unsigned short addr,
29                     unsigned char *rbuf, size_t rlen)
30{
31        ifd_reader_t *reader = prot->reader;
32        const ifd_driver_t *drv;
33
34        if (!(drv = reader->driver) || !drv->ops || !drv->ops->sync_read)
35                return IFD_ERROR_NOT_SUPPORTED;
36
37        return drv->ops->sync_read(reader, slot, prot->ops->id,
38                                   addr, rbuf, rlen);
39}
40
41static int sync_write(ifd_protocol_t * prot, int slot, unsigned short addr,
42                      const unsigned char *sbuf, size_t slen)
43{
44        ifd_reader_t *reader = prot->reader;
45        const ifd_driver_t *drv;
46        unsigned int retries = 1;
47        int prot_id;
48
49        if (!(drv = reader->driver) || !drv->ops || !drv->ops->sync_read)
50                return IFD_ERROR_NOT_SUPPORTED;
51
52        prot_id = prot->ops->id;
53        if ((prot_id == IFD_PROTOCOL_I2C_SHORT
54             || prot_id == IFD_PROTOCOL_I2C_LONG) && slen > 1)
55                retries = 2;
56
57        while (slen) {
58                unsigned char temp[256];
59                size_t count;
60                int r;
61
62                /* All bytes must be within a 256 page.
63                 * Is this generic, or a Towitoko requirement?
64                 */
65                count = 256 - (addr & 255);
66                if (count > slen)
67                        count = slen;
68
69                ifd_debug(2, "writing %u@%04x", count, addr);
70                r = drv->ops->sync_write(reader, slot,
71                                         prot_id, addr, sbuf, count);
72
73                if (r < 0)
74                        return r;
75
76                /* Verify that data was written correctly */
77                ifd_debug(2, "verifying %u@%04x", count, addr);
78                r = drv->ops->sync_read(reader, slot,
79                                        prot_id, addr, temp, count);
80
81                if (memcmp(sbuf, temp, count)) {
82                        ifd_debug(2, "failed to verify write");
83                        if (retries--)
84                                continue;
85                        return -1;
86                }
87
88                addr += count;
89                sbuf += count;
90                slen -= count;
91        }
92
93        return 0;
94}
95
96/*
97 * Probe for sync ICC type
98 */
99static ifd_protocol_t *ifd_sync_probe_icc(ifd_reader_t * reader, int slot,
100                                          int proto)
101{
102        ifd_protocol_t *p;
103        unsigned char byte;
104        int res = 0;
105
106        if (ifd_deactivate(reader) < 0 || ifd_activate(reader) < 0)
107                return NULL;
108
109        if (!(p = ifd_protocol_new(proto, reader, slot)))
110                return NULL;
111
112        if (ifd_protocol_read_memory(p, slot, 0, &byte, 1) != 1)
113                goto out;
114
115        if (proto == IFD_PROTOCOL_2WIRE || proto == IFD_PROTOCOL_3WIRE) {
116                if (byte != 0x00 && byte != 0x0FF)
117                        res = 1;
118        } else {
119                byte = ~byte;
120                if (ifd_protocol_write_memory(p, slot, 0, &byte, 1) >= 0) {
121                        byte = ~byte;
122                        ifd_protocol_write_memory(p, slot, 0, &byte, 1);
123                        res = 1;
124                }
125        }
126
127      out:
128        if (!res) {
129                ifd_protocol_free(p);
130                p = NULL;
131        }
132        return p;
133}
134
135/*
136 * Detect synchronous ICC
137 */
138int ifd_sync_detect_icc(ifd_reader_t * reader, int slot, void *atr, size_t size)
139{
140        ifd_protocol_t *p = NULL;
141        int n;
142
143        if ((p = ifd_sync_probe_icc(reader, slot, IFD_PROTOCOL_I2C_SHORT))
144            || (p = ifd_sync_probe_icc(reader, slot, IFD_PROTOCOL_I2C_LONG))) {
145                /* I2C card. Empty ATR */
146                n = 0;
147        } else if ((p = ifd_sync_probe_icc(reader, slot, IFD_PROTOCOL_2WIRE))
148                   || (p =
149                       ifd_sync_probe_icc(reader, slot, IFD_PROTOCOL_3WIRE))) {
150                /* Try to read the ATR */
151                if (ifd_deactivate(reader) < 0 || ifd_activate(reader) < 0)
152                        goto failed;
153                n = ifd_protocol_read_memory(p, slot, 0, (unsigned char *)atr,
154                                             size);
155                if (n < 0)
156                        goto failed;
157        } else {
158                goto failed;
159        }
160
161        reader->slot[slot].proto = p;
162
163        ifd_debug(1, "Detected synchronous card (%s), %satr%s",
164                  p->ops->name, n ? "" : "no ", ct_hexdump(atr, n));
165
166        return n;
167
168      failed:
169        if (p != NULL)
170                ifd_protocol_free(p);
171        return IFD_ERROR_NO_ATR;
172}
173
174/*
175 * Protocol structs
176 */
177struct ifd_protocol_ops ifd_protocol_i2c_short = {
178        IFD_PROTOCOL_I2C_SHORT, /* id */
179        "I2C short",            /* name */
180        sizeof(sync_state_t),   /* size */
181        NULL,                   /* init */
182        sync_release,           /* release */
183        NULL,                   /* set_param */
184        NULL,                   /* get_param */
185        NULL,                   /* resynchronize */
186        NULL,                   /* transceive */
187        sync_read,              /* sync_read */
188        sync_write,             /* sync_write */
189};
190
191struct ifd_protocol_ops ifd_protocol_i2c_long = {
192        IFD_PROTOCOL_I2C_LONG,  /* id */
193        "I2C long",             /* name */
194        sizeof(sync_state_t),   /* size */
195        NULL,                   /* init */
196        sync_release,           /* release */
197        NULL,                   /* set_param */
198        NULL,                   /* get_param */
199        NULL,                   /* resynchronize */
200        NULL,                   /* transceive */
201        sync_read,              /* sync_read */
202        sync_write,             /* sync_write */
203};
204
205struct ifd_protocol_ops ifd_protocol_2wire = {
206        IFD_PROTOCOL_2WIRE,     /* id */
207        "2Wire",                /* name */
208        sizeof(sync_state_t),   /* size */
209        NULL,                   /* init */
210        sync_release,           /* release */
211        NULL,                   /* set_param */
212        NULL,                   /* get_param */
213        NULL,                   /* resynchronize */
214        NULL,                   /* transceive */
215        sync_read,              /* sync_read */
216        sync_write,             /* sync_write */
217};
218
219struct ifd_protocol_ops ifd_protocol_3wire = {
220        IFD_PROTOCOL_3WIRE,     /* id */
221        "3Wire",                /* name */
222        sizeof(sync_state_t),   /* size */
223        NULL,                   /* init */
224        sync_release,           /* release */
225        NULL,                   /* set_param */
226        NULL,                   /* get_param */
227        NULL,                   /* resynchronize */
228        NULL,                   /* transceive */
229        sync_read,              /* sync_read */
230        sync_write,             /* sync_write */
231};
232
233struct ifd_protocol_ops ifd_protocol_eurochip = {
234        IFD_PROTOCOL_EUROCHIP,  /* id */
235        "Eurochip Countercard", /* name */
236        sizeof(sync_state_t),   /* size */
237        NULL,                   /* init */
238        sync_release,           /* release */
239        NULL,                   /* set_param */
240        NULL,                   /* get_param */
241        NULL,                   /* resynchronize */
242        NULL,                   /* transceive */
243        sync_read,              /* sync_read */
244        sync_write,             /* sync_write */
245};
Note: See TracBrowser for help on using the repository browser.