1 /*
2 * Protocol selection
3 *
4 * Copyright (C) 2003, Olaf Kirch <okir@suse.de>
5 */
6
7 #include "internal.h"
8 #include <stdlib.h>
9 #include <string.h>
10
11 struct ifd_protocol_info {
12 struct ifd_protocol_info *next;
13 struct ifd_protocol_ops *ops;
14 };
15
16 static struct ifd_protocol_info *list = NULL;
17
18 /*
19 * Register a protocol
20 */
ifd_protocol_register(struct ifd_protocol_ops * ops)21 int ifd_protocol_register(struct ifd_protocol_ops *ops)
22 {
23 struct ifd_protocol_info *info, **ptr;
24
25 info = (struct ifd_protocol_info *)calloc(1, sizeof(*info));
26 if (!info) {
27 ct_error("out of memory");
28 return IFD_ERROR_NO_MEMORY;
29 }
30 info->ops = ops;
31
32 for (ptr = &list; *ptr; ptr = &(*ptr)->next) ;
33 *ptr = info;
34 return 0;
35 }
36
37 /*
38 * Look up protocol based on its ID
39 */
ifd_protocol_by_id(int id)40 static struct ifd_protocol_ops *ifd_protocol_by_id(int id)
41 {
42 struct ifd_protocol_info *info;
43
44 for (info = list; info; info = info->next) {
45 if (info->ops->id == id)
46 return info->ops;
47 }
48
49 /* Autoload protocols defined in external modules? */
50
51 return NULL;
52 }
53
54 /*
55 * Select a protocol
56 */
ifd_protocol_select(ifd_reader_t * reader,int nslot,int preferred)57 ifd_protocol_t *ifd_protocol_select(ifd_reader_t * reader, int nslot,
58 int preferred)
59 {
60 const ifd_driver_t *drv;
61 ifd_slot_t *slot = &reader->slot[nslot];
62 unsigned char *atr, TDi;
63 unsigned int supported = 0;
64 int def_proto = -1, n, len;
65
66 ifd_debug(1, "atr=%s", ct_hexdump(slot->atr, slot->atr_len));
67
68 /* FIXME: use ifd_atr_parse() instead */
69 atr = slot->atr;
70 len = slot->atr_len;
71 if (len < 2)
72 return NULL;
73
74 /* Ignore hysterical bytes */
75 len -= atr[1] & 0x0f;
76
77 n = 2;
78 do {
79 int prot;
80
81 TDi = atr[n - 1];
82 if (n != 2) {
83 prot = TDi & 0x0f;
84 supported |= (1 << prot);
85 if (def_proto < 0)
86 def_proto = prot;
87 }
88
89 n += ifd_count_bits(TDi & 0xF0);
90 } while (n < len && (TDi & 0x80));
91
92 if (supported == 0)
93 supported |= 0x01;
94 if (def_proto < 0)
95 def_proto = IFD_PROTOCOL_T0;
96
97 ifd_debug(1, "default T=%d, supported protocols=0x%x",
98 def_proto, supported);
99
100 if (preferred >= 0
101 && preferred != def_proto && (supported & (1 << preferred))) {
102 /* XXX perform PTS */
103 ifd_debug(1, "protocol selection not supported");
104 }
105
106 if ((drv = reader->driver) && drv->ops && drv->ops->set_protocol) {
107 if (drv->ops->set_protocol(reader, nslot, def_proto) < 0)
108 return NULL;
109 } else {
110 slot->proto = ifd_protocol_new(def_proto, reader, slot->dad);
111 }
112
113 return slot->proto;
114 }
115
116 /*
117 * Force the protocol driver to resynchronize
118 */
ifd_protocol_resynchronize(ifd_protocol_t * p,int nad)119 int ifd_protocol_resynchronize(ifd_protocol_t * p, int nad)
120 {
121 ifd_debug(1, "called.");
122 if (!p || !p->ops || !p->ops->resynchronize)
123 return IFD_ERROR_NOT_SUPPORTED;
124
125 return p->ops->resynchronize(p, nad);
126 }
127
128 /*
129 * Protocol transceive
130 */
ifd_protocol_transceive(ifd_protocol_t * p,int dad,const void * sbuf,size_t slen,void * rbuf,size_t rlen)131 int ifd_protocol_transceive(ifd_protocol_t * p, int dad, const void *sbuf,
132 size_t slen, void *rbuf, size_t rlen)
133 {
134 int rc;
135
136 if (!p || !p->ops || !p->ops->transceive)
137 return IFD_ERROR_NOT_SUPPORTED;
138
139 ifd_debug(1, "cmd: %s", ct_hexdump(sbuf, slen));
140 rc = p->ops->transceive(p, dad, sbuf, slen, rbuf, rlen);
141
142 if (rc >= 0)
143 ifd_debug(1, "resp:%s", ct_hexdump(rbuf, rc));
144 else
145 ifd_debug(1, "transceive error: %s", ct_strerror(rc));
146
147 return rc;
148 }
149
150 /*
151 * Read/write synchronous ICCs
152 */
ifd_protocol_read_memory(ifd_protocol_t * p,int slot,unsigned short addr,unsigned char * rbuf,size_t rlen)153 int ifd_protocol_read_memory(ifd_protocol_t * p, int slot, unsigned short addr,
154 unsigned char *rbuf, size_t rlen)
155 {
156 int rc;
157
158 if (!p || !p->ops || !p->ops->sync_read)
159 return IFD_ERROR_NOT_SUPPORTED;
160
161 ifd_debug(1, "read %u@%04x (%s)", (unsigned int)rlen, addr,
162 p->ops->name);
163 rc = p->ops->sync_read(p, slot, addr, rbuf, rlen);
164
165 if (rc >= 0)
166 ifd_debug(1, "resp:%s", ct_hexdump(rbuf, rc));
167
168 return rc;
169 }
170
ifd_protocol_write_memory(ifd_protocol_t * p,int slot,unsigned short addr,const unsigned char * sbuf,size_t slen)171 int ifd_protocol_write_memory(ifd_protocol_t * p, int slot, unsigned short addr,
172 const unsigned char *sbuf, size_t slen)
173 {
174 int rc;
175
176 if (!p || !p->ops || !p->ops->sync_write)
177 return IFD_ERROR_NOT_SUPPORTED;
178
179 ifd_debug(1, "write %u@%04x (%s):%s",
180 (unsigned int)slen, addr,
181 p->ops->name, ct_hexdump(sbuf, slen));
182 rc = p->ops->sync_write(p, slot, addr, sbuf, slen);
183
184 ifd_debug(1, "resp = %d", rc);
185 return rc;
186 }
187
188 /*
189 * Create new protocol object
190 */
ifd_protocol_new(int id,ifd_reader_t * reader,unsigned int dad)191 ifd_protocol_t *ifd_protocol_new(int id, ifd_reader_t * reader,
192 unsigned int dad)
193 {
194 struct ifd_protocol_ops *ops;
195 ifd_protocol_t *p;
196
197 if (reader == NULL)
198 return NULL;
199
200 if (!(ops = ifd_protocol_by_id(id))) {
201 ct_error("unknown protocol id %d", id);
202 return NULL;
203 }
204
205 p = (ifd_protocol_t *) calloc(1, ops->size);
206 if (!p) {
207 ct_error("out of memory");
208 return p;
209 }
210 p->reader = reader;
211 p->ops = ops;
212 p->dad = dad;
213
214 if (ops->init && ops->init(p) < 0) {
215 ct_error("Protocol initialization failed");
216 ifd_protocol_free(p);
217 return NULL;
218 }
219
220 return p;
221 }
222
223 /*
224 * Set a protocol specific parameter
225 */
ifd_protocol_set_parameter(ifd_protocol_t * p,int type,long value)226 int ifd_protocol_set_parameter(ifd_protocol_t * p, int type, long value)
227 {
228 if (!p || !p->ops || !p->ops->set_param)
229 return -1;
230 return p->ops->set_param(p, type, value);
231 }
232
ifd_protocol_get_parameter(ifd_protocol_t * p,int type,long * value)233 int ifd_protocol_get_parameter(ifd_protocol_t * p, int type, long *value)
234 {
235 if (!p || !p->ops || !p->ops->get_param)
236 return -1;
237 return p->ops->get_param(p, type, value);
238 }
239
240 /*
241 * Free protocol object
242 */
ifd_protocol_free(ifd_protocol_t * p)243 void ifd_protocol_free(ifd_protocol_t * p)
244 {
245 if (p->ops) {
246 if (p->ops->release)
247 p->ops->release(p);
248 memset(p, 0, p->ops->size);
249 } else {
250 memset(p, 0, sizeof(*p));
251 }
252 free(p);
253 }
254
255 /*
256 * List available protocols
257 */
ifd_protocols_list(const char ** names,unsigned int max)258 unsigned int ifd_protocols_list(const char **names, unsigned int max)
259 {
260 struct ifd_protocol_info *info;
261 unsigned int n;
262
263 for (info = list, n = 0; info && n < max; info = info->next, n++) {
264 names[n] = info->ops->name;
265 }
266 return n;
267 }
268