use autoconf/automake
[librfid] / src / rfid_proto_tcl.c
1 /* ISO 14443-4 (T=CL) implementation, PCD side.
2  *
3  * (C) 2005 by Harald Welte <laforge@gnumonks.org>
4  *
5  */
6
7 /*
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License version 2 
10  *  as published by the Free Software Foundation
11  *
12  *  This program is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *
17  *  You should have received a copy of the GNU General Public License
18  *  along with this program; if not, write to the Free Software
19  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <unistd.h>
25 #include <string.h>
26 #include <errno.h>
27
28 #include <rfid/rfid.h>
29 #include <rfid/rfid_protocol_tcl.h>
30 #include <rfid/rfid_protocol.h>
31 #include <rfid/rfid_layer2.h>
32 #include <rfid/rfid_layer2_iso14443b.h>
33
34 #include <rfid/rfid_asic.h>
35 #include <rfid/rfid_reader.h>
36
37 #include "rfid_iso14443_common.h"
38
39 #if 1
40 #ifdef DEBUGP
41 #undef DEBUGP
42 #define DEBUGP(x, ...)
43 #define DEBUGPC(x, ...)
44 #endif
45 #endif
46
47 static enum rfid_frametype l2_to_frame(unsigned int layer2)
48 {
49         switch (layer2) {
50                 case RFID_LAYER2_ISO14443A:
51                         return RFID_14443A_FRAME_REGULAR;
52                         break;
53                 case RFID_LAYER2_ISO14443B:
54                         return RFID_14443B_FRAME_REGULAR;
55                         break;
56         }
57         return 0;
58 }
59
60 static unsigned int sfgi_to_sfgt(struct rfid_protocol_handle *h, 
61                                  unsigned char sfgi)
62 {
63         unsigned int multiplier;
64         unsigned int tmp;
65
66         if (sfgi > 14)
67                 sfgi = 14;
68
69         multiplier = 1 << sfgi; /* 2 to the power of sfgi */
70
71         /* ISO 14443-4:2000(E) Section 5.2.5:
72          * (256 * 16 / h->l2h->rh->ah->fc) * (2 ^ sfgi) */
73         tmp = (unsigned int) 1000000 * 256 * 16;
74
75         return (tmp / h->l2h->rh->ah->fc) * multiplier;
76 }
77
78 static unsigned int fwi_to_fwt(struct rfid_protocol_handle *h, 
79                                 unsigned char fwi)
80 {
81         unsigned int multiplier, tmp;
82
83         if (fwi > 14)
84                 fwi = 14;
85
86         multiplier  = 1 << fwi; /* 2 to the power of fwi */
87
88         /* ISO 14443-4:2000(E) Section 7.2.:
89          * (256*16 / h->l2h->rh->ah->fc) * (2 ^ fwi) */
90
91         tmp = (unsigned int) 1000000 * 256 * 16;
92
93         return (tmp / h->l2h->rh->ah->fc) * multiplier;
94 }
95
96 /* 4.9seconds as microseconds (4.9 billion seconds) exceeds 2^32 */
97 #define activation_fwt(x) (((u_int64_t)1000000 * 65536 / x->l2h->rh->ah->fc))
98 #define deactivation_fwt(x) activation_fwt(x)
99
100 static int
101 tcl_parse_ats(struct rfid_protocol_handle *h, 
102                 unsigned char *ats, unsigned int size)
103 {
104         unsigned char len = ats[0];
105         unsigned char t0;
106         unsigned char *cur;
107
108         if (len == 0 || size == 0) 
109                 return -1;
110
111         if (size < len)
112                 len = size;
113
114         h->priv.tcl.ta = 0;
115
116         if (len == 1) {
117                 /* FIXME: assume some default values */
118                 h->priv.tcl.fsc = 32;
119                 h->priv.tcl.ta = 0x80;  /* 0x80 (same d for both dirs) */
120                 h->priv.tcl.sfgt = sfgi_to_sfgt(h, 0);
121                 if (h->l2h->l2->id == RFID_LAYER2_ISO14443A) {
122                         /* Section 7.2: fwi default for type A is 4 */
123                         h->priv.tcl.fwt = fwi_to_fwt(h, 4);
124                 } else {
125                         /* Section 7.2: fwi for type B is always in ATQB */
126                         /* Value is assigned in tcl_connect() */
127                         /* This function is never called for Type B, since it has no (R)ATS */
128                 }
129                 return 0;
130         }
131
132         /* guarateed to be at least 2 bytes in size */
133
134         t0 = ats[1];
135         cur = &ats[2];
136
137         iso14443_fsdi_to_fsd(&h->priv.tcl.fsc, t0 & 0x0f);
138
139         if (t0 & (1 << 4)) {
140                 /* TA is transmitted */
141                 h->priv.tcl.ta = *cur++;
142         }
143
144         if (t0 & (1 << 5)) {
145                 /* TB is transmitted */
146                 h->priv.tcl.sfgt = sfgi_to_sfgt(h, *cur & 0x0f);
147                 h->priv.tcl.fwt = fwi_to_fwt(h, (*cur & 0xf0) >> 4);
148                 cur++;
149         }
150
151         if (t0 & (1 << 6)) {
152                 /* TC is transmitted */
153                 if (*cur & 0x01)
154                         h->priv.tcl.flags |= TCL_HANDLE_F_NAD_SUPPORTED;
155                 if (*cur & 0x02)
156                         h->priv.tcl.flags |= TCL_HANDLE_F_CID_SUPPORTED;
157                 cur++;
158         }
159
160         h->priv.tcl.historical_len = (ats+len) - cur;
161         h->priv.tcl.historical_bytes = cur;
162
163         return 0;
164 }
165
166
167 /* request an ATS from the PICC */
168 static int
169 tcl_request_ats(struct rfid_protocol_handle *h)
170 {
171         int ret;
172         unsigned char rats[2];
173         unsigned char fsdi;
174
175         if (h->priv.tcl.state != TCL_STATE_INITIAL)
176                 return -1;
177
178         ret = iso14443_fsd_to_fsdi(&fsdi, h->priv.tcl.fsd);
179         if (ret < 0) {
180                 DEBUGP("unable to encode FSD of %u as FSDI\n", h->priv.tcl.fsd);
181                 return ret;
182         }
183
184         rats[0] = 0xe0;
185         rats[1] = (h->priv.tcl.cid & 0x0f) | ((fsdi << 4) & 0xf0);
186
187         /* transcieve (with CRC) */
188         ret = h->l2h->l2->fn.transcieve(h->l2h, RFID_14443A_FRAME_REGULAR,
189                                         rats, 2, h->priv.tcl.ats,
190                                        &h->priv.tcl.ats_len, activation_fwt(h),
191                                        TCL_TRANSP_F_TX_CRC);
192         if (ret < 0) {
193                 DEBUGP("transcieve of rats failed\n");
194                 h->priv.tcl.state = TCL_STATE_RATS_SENT;
195                 /* FIXME: retransmit */
196                 return ret;
197         }
198         h->priv.tcl.state = TCL_STATE_ATS_RCVD;
199
200         ret = tcl_parse_ats(h, h->priv.tcl.ats, h->priv.tcl.ats_len);
201         if (ret < 0) {
202                 DEBUGP("parsing of ats failed\n");
203                 return ret;
204         }
205
206         return 0;
207 }
208
209 #define ATS_TA_DIV_2    1
210 #define ATS_TA_DIV_4    2
211 #define ATS_TA_DIV_8    4
212
213 #define PPS_DIV_8       3
214 #define PPS_DIV_4       2
215 #define PPS_DIV_2       1
216 #define PPS_DIV_1       0
217 static unsigned char d_to_di(struct rfid_protocol_handle *h, unsigned char D)
218 {
219         static char DI;
220         unsigned int speed = h->l2h->rh->reader->iso14443a.speed;
221         
222         if ((D & ATS_TA_DIV_8) && (speed & RFID_READER_SPEED_848K))
223                 DI = PPS_DIV_8;
224         else if ((D & ATS_TA_DIV_4) && (speed & RFID_READER_SPEED_424K))
225                 DI = PPS_DIV_4;
226         else if ((D & ATS_TA_DIV_2) && (speed & RFID_READER_SPEED_212K))
227                 DI = PPS_DIV_2;
228         else
229                 DI = PPS_DIV_1;
230
231         return DI;
232 }
233
234
235 /* start a PSS run (autimatically configure highest possible speed */
236 static int 
237 tcl_do_pps(struct rfid_protocol_handle *h)
238 {
239 #if 0
240         int ret;
241         unsigned char ppss[3];
242         unsigned char pps_response[1];
243         unsigned int rx_len = 1;
244         unsigned char Dr, Ds, DrI, DsI;
245
246         if (h->priv.tcl.state != TCL_STATE_ATS_RCVD)
247                 return -1;
248
249         Dr = h->priv.tcl.ta & 0x07;
250         Ds = h->priv.tcl.ta & 0x70 >> 4;
251
252         if (Dr != Ds && !(h->priv.tcl.ta & 0x80)) {
253                 /* device supports different divisors for rx and tx, but not ?!? */
254                 DEBUGP("PICC has contradictory TA, aborting PPS\n");
255                 return -1;
256         };
257
258         /* ISO 14443-4:2000(E) Section 5.3. */
259
260         ppss[0] = 0xd0 & (h->priv.tcl.cid & 0x0f);
261         ppss[1] = 0x11;
262
263         /* FIXME: deal with different speed for each direction */
264         DrI = d_to_di(h, Dr);
265         DsI = d_to_di(h, Ds);
266
267         ppss[2] = (ppss[2] & 0xf0) | (DrI | DsI << 2);
268
269         ret = h->l2h->l2->fn.transcieve(h->l2h, ppss, 3, pps_response,
270                                         &rx_len, h->priv.tcl.fwt,
271                                         TCL_TRANSP_F_TX_CRC);
272         if (ret < 0)
273                 return ret;
274
275         if (pps_response[0] != ppss[0]) {
276                 DEBUGP("PPS Response != PPSS\n");
277                 return -1;
278         }
279         
280         h->priv.tcl.state = TCL_STATE_ESTABLISHED;
281 #endif
282         return 0;
283 }
284
285
286 static int
287 tcl_build_prologue2(struct tcl_handle *th, 
288                     unsigned char *prlg, unsigned int *prlg_len, 
289                     unsigned char pcb)
290 {
291         *prlg_len = 1;
292
293         *prlg = pcb;
294
295         if (th->toggle) {
296                 /* we've sent a toggle bit last time */
297                 th->toggle = 0;
298         } else {
299                 /* we've not sent a toggle last time: send one */
300                 th->toggle = 1;
301                 *prlg |= 0x01;
302         }
303
304         if (th->flags & TCL_HANDLE_F_CID_USED) {
305                 /* ISO 14443-4:2000(E) Section 7.1.1.2 */
306                 *prlg |= TCL_PCB_CID_FOLLOWING;
307                 (*prlg_len)++;
308                 prlg[*prlg_len] = th->cid & 0x0f;
309         }
310
311         /* nad only for I-block (0xc0 == 00) */
312         if ((th->flags & TCL_HANDLE_F_NAD_USED) &&
313             ((pcb & 0xc0) == 0x00)) {
314                 /* ISO 14443-4:2000(E) Section 7.1.1.3 */
315                 /* FIXME: in case of chaining only for first frame */
316                 *prlg |= TCL_PCB_NAD_FOLLOWING;
317                 prlg[*prlg_len] = th->nad;
318                 (*prlg_len)++;
319         }
320
321         return 0;
322 }
323
324 static int
325 tcl_build_prologue_i(struct tcl_handle *th,
326                      unsigned char *prlg, unsigned int *prlg_len)
327 {
328         /* ISO 14443-4:2000(E) Section 7.1.1.1 */
329         return tcl_build_prologue2(th, prlg, prlg_len, 0x02);
330 }
331
332 static int
333 tcl_build_prologue_r(struct tcl_handle *th,
334                      unsigned char *prlg, unsigned int *prlg_len,
335                      unsigned int nak)
336 {
337         unsigned char pcb = 0xa2;
338         /* ISO 14443-4:2000(E) Section 7.1.1.1 */
339
340         if (nak)
341                 pcb |= 0x10;
342
343         return tcl_build_prologue2(th, prlg, prlg_len, pcb);
344 }
345
346 static int
347 tcl_build_prologue_s(struct tcl_handle *th,
348                      unsigned char *prlg, unsigned int *prlg_len)
349 {
350         /* ISO 14443-4:2000(E) Section 7.1.1.1 */
351
352         /* the only S-block from PCD->PICC is DESELECT,
353          * well, actually there is the S(WTX) response. */
354         return tcl_build_prologue2(th, prlg, prlg_len, 0xc2);
355 }
356
357 /* FIXME: WTXM implementation */
358
359 static int tcl_prlg_len(struct tcl_handle *th)
360 {
361         int prlg_len = 1;
362
363         if (th->flags & TCL_HANDLE_F_CID_USED)
364                 prlg_len++;
365
366         if (th->flags & TCL_HANDLE_F_NAD_USED)
367                 prlg_len++;
368
369         return prlg_len;
370 }
371
372 #define max_net_tx_framesize(x) (x->fsc - tcl_prlg_len(x))
373
374 static int
375 tcl_connect(struct rfid_protocol_handle *h)
376 {
377         int ret; 
378
379         if (h->priv.tcl.state != TCL_STATE_DESELECTED &&
380             h->priv.tcl.state != TCL_STATE_INITIAL)
381                 return -1;
382
383         switch (h->l2h->l2->id) {
384         case RFID_LAYER2_ISO14443A:
385                 /* Start Type A T=CL Activation Sequence */
386                 ret = tcl_request_ats(h);
387                 if (ret < 0)
388                         return ret;
389
390                 /* Only do PPS if any non-default divisors supported */
391                 if (h->priv.tcl.ta & 0x77) {
392                         ret = tcl_do_pps(h);
393                         if (ret < 0)
394                                 return ret;
395                 }
396                 break;
397         case RFID_LAYER2_ISO14443B:
398                 /* initialized T=CL state from Type B Activation Data */
399                 h->priv.tcl.cid = h->l2h->priv.iso14443b.cid;
400                 h->priv.tcl.fsc = h->l2h->priv.iso14443b.fsc;
401                 h->priv.tcl.fsd = h->l2h->priv.iso14443b.fsd;
402                 h->priv.tcl.fwt = h->l2h->priv.iso14443b.fwt;
403
404                 /* what about ta? sfgt? */
405
406                 if (h->l2h->priv.iso14443b.flags & ISO14443B_CID_SUPPORTED)
407                         h->priv.tcl.flags |= TCL_HANDLE_F_CID_SUPPORTED;
408                 if (h->l2h->priv.iso14443b.flags & ISO14443B_NAD_SUPPORTED)
409                         h->priv.tcl.flags |= TCL_HANDLE_F_NAD_SUPPORTED;
410
411                 switch (h->l2h->priv.iso14443b.state) {
412                         case ISO14443B_STATE_SELECTED:
413                                 h->priv.tcl.state = TCL_STATE_ATS_RCVD;
414                                 break;
415                         case ISO14443B_STATE_ATTRIB_SENT:
416                                 h->priv.tcl.state = TCL_STATE_RATS_SENT;
417                                 break;
418                 }
419
420                 /* PUPI will be presented as ATS/historical bytes */
421                 memcpy(h->priv.tcl.ats, h->l2h->uid, 4);
422                 h->priv.tcl.ats_len = 4;
423                 h->priv.tcl.historical_bytes = h->priv.tcl.ats;
424
425                 break;
426         default:
427                 DEBUGP("unsupported l2: %u\n", h->l2h->l2->id);
428                 return -1;
429                 break;
430         }
431
432         return 0;
433 }
434
435 static int
436 tcl_deselect(struct rfid_protocol_handle *h)
437 {
438         /* ISO 14443-4:2000(E) Section 8 */
439         int ret;
440         unsigned char frame[3];         /* 3 bytes prologue, no information */
441         unsigned char rx[3];
442         unsigned int rx_len = sizeof(rx);
443         unsigned int prlg_len;
444         struct tcl_handle *th = &h->priv.tcl;
445
446         if (th->state != TCL_STATE_ESTABLISHED) {
447                 /* FIXME: not sure whether deselect is possible here,
448                  * probably better send a HLTA? */
449         }
450
451         /* build DESELECT S-block */
452         ret = tcl_build_prologue_s(th, frame, &prlg_len);
453         if (ret < 0)
454                 return ret;
455
456         ret = h->l2h->l2->fn.transcieve(h->l2h, RFID_14443A_FRAME_REGULAR,
457                                         frame, prlg_len, rx,
458                                      &rx_len, deactivation_fwt(h),
459                                      TCL_TRANSP_F_TX_CRC);
460         if (ret < 0) {
461                 /* FIXME: retransmit, HLT(A|B) */
462                 return ret;
463         }
464
465         th->state = TCL_STATE_DESELECTED;
466
467         return 0;
468 }
469
470 #define is_s_block(x) ((x & 0xc0) == 0xc0)
471 #define is_r_block(x) ((x & 0xc0) == 0x80)
472 #define is_i_block(x) ((x & 0xc0) == 0x00)
473
474 static int
475 tcl_transcieve(struct rfid_protocol_handle *h,
476                 const unsigned char *tx_data, unsigned int tx_len,
477                 unsigned char *rx_data, unsigned int *rx_len,
478                 unsigned int timeout, unsigned int flags)
479 {
480         int ret;
481         unsigned char *tx_buf, *rx_buf;
482         unsigned char *_rx_data = rx_data;
483         unsigned int _rx_len;
484         unsigned int max_rx_len = *rx_len; /* maximum number of payoload that
485                                               caller has requested */
486         unsigned int prlg_len;
487         struct tcl_handle *th = &h->priv.tcl;
488
489         unsigned char *_tx;
490         unsigned int _tx_len, _timeout;
491         unsigned char wtx_resp[3];
492         unsigned char ack[10];
493         unsigned int ack_len;
494
495         if (tx_len > max_net_tx_framesize(th)) {
496                 /* slow path: we need to use chaining */
497                 return -1;
498         }
499
500         tx_buf = malloc(tcl_prlg_len(th) + tx_len);
501         if (!tx_buf) {
502                 ret = -ENOMEM;
503                 goto out;
504         }
505         rx_buf = malloc(tcl_prlg_len(th) + *rx_len);
506         if (!rx_buf) {
507                 ret = -ENOMEM;
508                 goto out_txb;
509         }
510
511         if (tcl_build_prologue_i(th, tx_buf, &prlg_len) < 0) {
512                 ret = -1;
513                 goto out_rxb;
514         }
515         memcpy(tx_buf + prlg_len, tx_data, tx_len);
516
517         /* intialize to data-to-be-transferred */
518         _tx = tx_buf;
519         _tx_len = tx_len+prlg_len;
520         _timeout = th->fwt;
521         _rx_len = *rx_len;
522         *rx_len = 0;
523
524 do_tx:
525         ret = h->l2h->l2->fn.transcieve(h->l2h, l2_to_frame(h->l2h->l2->id),
526                                         _tx, _tx_len,
527                                         rx_buf, &_rx_len, _timeout, 0);
528         DEBUGP("l2 transcieve finished\n");
529         if (ret < 0)
530                 goto out_rxb;
531
532         if ((*rx_buf & 0x01) != h->priv.tcl.toggle) {
533                 DEBUGP("response with wrong toggle bit\n");
534                 goto out_rxb;
535         }
536
537         if (is_r_block(*rx_buf)) {
538                 unsigned int txed = _tx - tx_buf;
539                 DEBUGP("R-Block\n");
540                 /* Handle ACK frame in case of chaining */
541                 if (*rx_buf & TCL_PCB_CID_FOLLOWING) {
542                         if (*(rx_buf+1) != h->priv.tcl.cid) {
543                                 DEBUGP("CID %u is not valid\n", *(rx_buf)+1);
544                                 goto out_rxb;
545                         }
546                 }
547                 /* set up parameters for next frame in chain */
548                 if (txed < tx_len) {
549                         /* move tx pointer by the amount of bytes transferred
550                          * in last frame */
551                         _tx += _tx_len;
552                         _tx_len = (tx_len - txed);
553                         if (_tx_len > max_net_tx_framesize(th)) {
554                                 /* not last frame in chain */
555                                 _tx_len = max_net_tx_framesize(th);
556                         } else {
557                                 /* last frame in chain */
558                         }
559                         goto do_tx;
560                 } else {
561                         DEBUGP("Received ACK in response to last frame in "
562                                "chain?!? Expected I-frame.\n");
563                         ret = -1;
564                         goto out_rxb;
565                 }
566         } else if (is_s_block(*rx_buf)) {
567                 unsigned char inf;
568                 unsigned int prlg_len;
569
570                 DEBUGP("S-Block\n");
571                 /* Handle Wait Time Extension */
572                 if (*rx_buf & TCL_PCB_CID_FOLLOWING) {
573                         if (_rx_len < 3) {
574                                 DEBUGP("S-Block with CID but short len\n");
575                                 ret = -1;
576                                 goto out_rxb;
577                         }
578                         if (*(rx_buf+1) != h->priv.tcl.cid) {
579                                 DEBUGP("CID %u is not valid\n", *(rx_buf)+1);
580                                 goto out_rxb;
581                         }
582                         inf = *(rx_buf+2);
583                 } else
584                         inf = *(rx_buf+1);
585
586                 if ((*rx_buf & 0x30) != 0x30) {
587                         DEBUGP("S-Block but not WTX?\n");
588                         ret = -1;
589                         goto out_rxb;
590                 }
591                 inf &= 0x3f;    /* only lower 6 bits code WTXM */
592                 if (inf == 0 || (inf >= 60 && inf <= 63)) {
593                         DEBUGP("WTXM %u is RFU!\n", inf);
594                         ret = -1;
595                         goto out_rxb;
596                 }
597                 
598                 /* Acknowledge WTXM */
599                 tcl_build_prologue_s(&h->priv.tcl, wtx_resp, &prlg_len);
600                 /* set two bits that make this block a wtx */
601                 wtx_resp[0] |= 0x30;
602                 wtx_resp[prlg_len] = inf;
603                 _tx = wtx_resp;
604                 _tx_len = prlg_len+1;
605                 _timeout = th->fwt * inf;
606
607                 /* start over with next transcieve */
608                 goto do_tx; /* FIXME: do transcieve locally since we use
609                                 totally different buffer */
610
611         } else if (is_i_block(*rx_buf)) {
612                 unsigned char *inf = rx_buf+1;
613                 unsigned int net_payload_len;
614                 /* we're actually receiving payload data */
615
616                 DEBUGP("I-Block: ");
617                 if (*rx_buf & TCL_PCB_CID_FOLLOWING) {
618                         if (*(rx_buf+1) != h->priv.tcl.cid) {
619                                 DEBUGPC("CID %u is not valid\n", *(rx_buf)+1);
620                                 goto out_rxb;
621                         }
622                         inf++;
623                 }
624                 if (*rx_buf & TCL_PCB_NAD_FOLLOWING) {
625                         inf++;
626                 }
627                 net_payload_len = _rx_len - (inf - rx_buf);
628                 DEBUGPC("%u bytes\n", net_payload_len);
629                 memcpy(_rx_data, inf, net_payload_len);
630                 /* increment the number of payload bytes that we actually received */
631                 *rx_len += net_payload_len;
632                 _rx_data += net_payload_len;
633
634                 if (*rx_buf & 0x10) {
635                         /* we're not the last frame in the chain, continue rx */
636                         DEBUGP("we're not the last frame in the chain, continue\n");
637                         ack_len = sizeof(ack);
638                         tcl_build_prologue_r(&h->priv.tcl, ack, &ack_len, 0);
639                         _tx = ack;
640                         _tx_len = ack_len;
641                         goto do_tx;
642                 }
643         }
644
645 out_rxb:
646         free(rx_buf);
647 out_txb:
648         free(tx_buf);
649 out:
650         return ret;
651 }
652
653 static struct rfid_protocol_handle *
654 tcl_init(struct rfid_layer2_handle *l2h)
655 {
656         struct rfid_protocol_handle *th;
657         unsigned int mru = l2h->rh->ah->mru;
658
659         th = malloc(sizeof(struct rfid_protocol_handle) + mru);
660         if (!th)
661                 return NULL;
662
663         /* FIXME: mru should be attribute of layer2 (in case it adds/removes
664          * some overhead */
665         memset(th, 0, sizeof(struct rfid_protocol_handle) + mru);
666
667         /* maximum received ats length equals mru of asic/reader */
668         th->priv.tcl.state = TCL_STATE_INITIAL;
669         th->priv.tcl.ats_len = mru;
670         th->priv.tcl.toggle = 1;
671
672         th->priv.tcl.fsd = iso14443_fsd_approx(mru);
673
674         return th;
675 }
676
677 static int
678 tcl_fini(struct rfid_protocol_handle *ph)
679 {
680         free(ph);
681         return 0;
682 }
683
684 struct rfid_protocol rfid_protocol_tcl = {
685         .id     = RFID_PROTOCOL_TCL,
686         .name   = "ISO 14443-4 / T=CL",
687         .fn     = {
688                 .init = &tcl_init,
689                 .open = &tcl_connect,
690                 .transcieve = &tcl_transcieve,
691                 .close = &tcl_deselect,
692                 .fini = &tcl_fini,
693         },
694 };