nfc test on MQX4.1
[nfc-test.git] / iso14444.c
blobb5512c90cca009165caea69e8650bec89495d271
2 /* 14443-4 */
3 #include "common.h"
4 #include "picc.h"
5 #include "iso14444.h"
7 #include "delay.h"
8 #include "iso14443_typeA.h"
9 #include "iso14443_typeB.h"
10 #include "pcd_config.h"
12 const uint16_t fsdi_to_fsd[] = {16, 24, 32, 40, 48, 64, 96, 128, 256};
14 /* pn512 timer setting for 7.2 Frame waiting time P25 */
15 static const uint8_t fwi_table [] =
17 // (330us) FWI=0
18 0x00,0x11,
19 0x00,0x80,
20 // (661us) FWI=1
21 0x00,0x11,
22 0x01,0x00,
23 // (1322us) FWI=2
24 0x00,0x11,
25 0x02,0x00,
26 // (2643us) FWI=3
27 0x00,0x11,
28 0x04,0x00,
29 // (5286us) FWI=4
30 0x00,0x11,
31 0x08,0x00,
32 // (10.572ms) FWI=5
33 0x00,0x44,
34 0x04,0x16,
35 // (21.14ms) FWI=6
36 0x00,0x44,
37 0x08,0x2C,
38 // (42.29ms) FWI=7
39 0x00,0x44,
40 0x10,0x59,
41 // (84.58ms) FWI=8
42 0x00,0x44,
43 0x20,0xB3,
44 // (169.2ms) FWI=9
45 0x02,0xA5,
46 0x06,0x9C,
47 // (338.3ms) FWI=10
48 0x02,0xA5,
49 0x0C,0x17,
50 // (676.6ms;) FWI=11
51 0x02,0xA5,
52 0x1A,0x6E,
53 // (1353.3ms) FWI=12
54 0x02,0xA5,
55 0x34,0xDD,
56 // (2706.5ms) FWI=13
57 0x02,0xA5,
58 0x69,0xB9,
59 // (5413.0ms) FWI=14
60 0x02,0xA5,
61 0xD3,0x72,
64 const uint16_t fsdi_to_fsd_convertion[] = {16, 24, 32, 40, 48, 64, 96, 128, 256};
66 uint8_t tempIBlockBuf[253]; /* set max block size */
69 /****************************************************************/
70 // Type A RATS
71 /****************************************************************/
72 int typeA_request_ats(struct picc_device *picc)
74 int ret = 0;
75 uint8_t i;
76 uint8_t retry = 0;
77 struct pn51x_request *req = picc->request;
79 while(retry < 3) {
80 pn51x_reg_set(TxModeReg, TxCRCEn); //TXCRC enable
81 pn51x_reg_set(RxModeReg, RxCRCEn); //RXCRC enable
82 pn51x_reg_clear(Status2Reg, MFCrypto1On); // disable crypto 1 unit add.....
84 /* 14443-4 P12 Request for answer to select */
85 req->buf[0] = 0xE0;
86 req->buf[1] = picc->pcd->FSDI << 4 | picc->CID;
87 req->length = 2;
88 req->bit_frame = 0x00;
89 req->command = CMD_TRANSCEIVE;
90 req->direction = TRANSCEIVE;
91 req->time_out = 60;
93 picc_wait_for_req(req);
95 picc->ATS[0] = req->buf[0];
96 retry++;
97 ret = req->error_code;
98 if((ret) && (retry >= 2)) {
99 break;
102 if(!ret) {
103 // store ATS ,Figure 4 - Structure of the ATS (14443-4 P13)
104 if(req->actual != picc->ATS[0]) {
105 ret = -ERROR_ATSLEN;
106 goto err;
109 picc->states = PICC_ACTIVATED;
111 CLEAR_BIT(picc->flags_TCL, PCD_BLOCK_NUMBER); // reset block number
112 SET_BIT(picc->flags_TCL, CID_PRESENT); // CID supported by PICC by default
114 if(req->actual < 2) {
115 goto err;
117 else {
118 memcpy(&picc->ATS[1], &req->buf[1], req->actual - 1);
120 picc->FSCI = picc->ATS[1] & 0x0F; // T0: format byte, codes Y(1) and FSCI
121 if(picc->FSCI > 8) { /* 14443-4 P12 Table 1 - FSDI to FSD conversion */
122 picc->FSCI = 8;
125 i = 1; /* Parse the ATS 14443-4 P14 */
126 if(picc->ATS[1] & 0x10) {
127 // TA(1) present
128 i++;
129 picc->speed = picc->ATS[i];
130 if(picc->speed & 0x08) {
131 // b4 = 1 should be interpreted by the PCD as (b8 to b1) = (00000000)b (only ~106 kbit/s in both directions).
132 picc->speed = 0x00; // complaint to ISO14443-4: 2008
135 if(picc->ATS[1] & 0x20) {
136 // TB(1) present
137 i++;
138 picc->FWI = (picc->ATS[i] & 0xF0) >> 4; // Set FWT
139 if(picc->FWI > 14) {
140 // Until the RFU value 15 is assigned by ISO/IEC, a PCD receiving FWI = 15 should interpret it as FWI = 4.
141 picc->FWI = 4; // complaint to ISO14443-4: 2008
143 picc->SFGI = picc->ATS[i] & 0x0F;
144 if(picc->SFGI > 14) {
145 // Until the RFU value 15 is assigned by ISO/IEC, a PCD receiving SFGI = 15 should interpret it as SFGI = 0.
146 picc->SFGI = 0; // complaint to ISO14443-4: 2008
149 if(picc->ATS[1] & 0x40) {
150 // TC(1) present
151 i++;
152 if((picc->ATS[i] & 0x02) == 0x00) {
153 // CID do not supported by the PICC
154 CLEAR_BIT(picc->flags_TCL, CID_PRESENT);
157 break;
161 err:
162 return ret;
165 /* Start-up Frame Guard time , 14443-3 P11 (Frame format and timing) */
166 static void typeA_sfg_delay(uint8_t delay)
168 switch(delay)
170 case 1: //661us
171 Delay1us(200);
172 break;
173 case 2: //1322us
174 Delay1us(600);
175 break;
176 case 3: //2643us
177 Delay1us(1900);
178 break;
179 case 4: //5286us
180 Delay1us(4500);
181 break;
182 case 5: //10.572ms
183 Delay1us(9800);
184 break;
185 case 6: //21.14ms
186 Delay1ms(20);
187 Delay1us(400);
188 break;
189 case 7: //42.29ms
190 Delay1ms(40);
191 Delay1us(1500);
192 break;
193 case 8: //84.58ms
194 Delay1ms(80);
195 Delay1us(3800);
196 break;
197 case 9: //169.2ms
198 Delay1ms(160);
199 Delay1us(8500);
200 break;
201 case 10: // 338.3ms
202 Delay1ms(330);
203 Delay1us(7600);
204 break;
205 case 11: //676.6ms
206 Delay1ms(670);
207 Delay1us(5900);
208 break;
209 case 12: //1353.3ms
210 Delay1ms(1350);
211 Delay1us(2600);
212 break;
213 case 13: //2706.5ms
214 Delay1ms(2500);
215 Delay1ms(200);
216 Delay1us(5800);
217 break;
218 case 14: //5413.0ms
219 Delay1s(5);
220 Delay1ms(410);
221 Delay1us(2300);
222 break;
223 default: //330us
224 break;
228 void typeA_set_timeout(struct picc_device *picc, uint8_t timeout)
230 uint16_t preScaler;
231 uint16_t reloadValue;
232 uint8_t tempWTXM = picc->WTXM;
234 preScaler = MAKEWORD(fwi_table[timeout * 4], fwi_table[timeout * 4 + 1]);
235 reloadValue = MAKEWORD(fwi_table[timeout * 4 + 2], fwi_table[timeout * 4 + 3]);
237 if(picc->type == PICC_TYPEB_TCL) {
238 reloadValue += 8;
239 if(BITISSET(picc->flags_TCL, TYPEB_ATTRIB)) {
240 reloadValue += 8;
242 if(!timeout) {
243 reloadValue += 20;
246 if(BITISSET(picc->flags_TCL, WTX_REQUEST)) {
247 if(tempWTXM > 59) {
248 tempWTXM = 59;
250 if(timeout < 9) {
251 preScaler *= tempWTXM;
252 if(preScaler > 0x0FFF) {
253 preScaler = 0x0FFF;
256 else {
257 reloadValue *= tempWTXM;
259 CLEAR_BIT(picc->flags_TCL, WTX_REQUEST);
261 pn51x_reg_write(TModeReg, (uint8_t)(preScaler>>8) | 0x80);
262 pn51x_reg_write(TPrescalerReg, (uint8_t)preScaler);
263 pn51x_reg_write(TReloadVal_Hi, (uint8_t)(reloadValue>>8));
264 pn51x_reg_write(TReloadVal_Lo, (uint8_t)reloadValue);
265 pn51x_reg_write(CommIRqReg,0x01); // Clear the TimerIrq bit
268 uint8_t typeA_speed_check(struct picc_device *picc)
270 uint8_t priByte;
271 uint8_t curByte;
273 picc->pcd->current_speed = 0x80;
274 priByte = 0x00;
276 /* Divisor Receive */
277 if(picc->speed & 0x01) {
278 // DR = 2 supported, PCD to PICC, 1 etu = 64 / fc, bit rate supported is fc / 64 (~ 212 kbit/s)
279 priByte = 0x01;
281 if(picc->speed & 0x02) {
282 // DR = 4 supported, PCD to PICC, 1 etu = 32 / fc, bit rate supported is fc / 32 (~ 424 kbit/s)
283 priByte = 0x02;
285 if(picc->speed & 0x04) {
286 // DR = 8 supported, PCD to PICC, 1 etu = 16 / fc, bit rate supported is fc / 16 (~ 848 kbit/s)
287 priByte = 0x03;
290 curByte = 0x00;
292 /* Divisor Send */
293 if(picc->speed & 0x10) {
294 // DS = 2 supported, PICC to PCD, 1 etu = 64 / fc, bit rate supported is fc / 64 (~ 212 kbit/s)
295 curByte = 0x01;
297 if(picc->speed & 0x20) {
298 // DS = 4 supported, PICC to PCD, 1 etu = 32 / fc, bit rate supported is fc / 32 (~ 424 kbit/s)
299 curByte = 0x02;
301 if(picc->speed & 0x40) {
302 // DS = 8 supported, PICC to PCD, 1 etu = 16 / fc, bit rate supported is fc / 16 (~ 848 kbit/s)
303 curByte = 0x03;
306 if(picc->speed & 0x80) {
307 // Only the same D for both directions supported , if bit is set to 1
308 if(curByte > priByte) {
309 curByte = priByte;
311 else {
312 priByte = curByte;
316 if(picc->speed & 0x08) {
317 // if b4 = 1, b8 to b1 should be interpreted as (00000000)b, accroding to ISO14443-4: 2008(typeA) and ISO14443-3: 2011(typeB)
318 curByte = priByte = 0x00;
321 curByte = (curByte << 2) | priByte; /* bxx(DS 0-3) xx(DR 0-3) */
323 return curByte;
326 void typeA_high_speed_config(struct picc_device *picc, uint8_t speedParam, uint8_t typeB)
328 picc->pcd->current_speed = picc->speed & 0x80;
329 if((speedParam & 0x03) == 0x03) {
330 // DR = 8 supported, PCD to PICC, 1 etu = 16 / fc, bit rate supported is fc / 16 (~ 848 kbit/s)
331 picc->pcd->current_speed |= 0x03;
332 pcd_config_iso14443_card(CONFIGNOTHING, TYPEA_848TX | typeB); /* TX */
334 else if((speedParam & 0x03) == 0x02) {
335 // DR = 4 supported, PCD to PICC, 1 etu = 32 / fc, bit rate supported is fc / 32 (~ 424 kbit/s)
336 picc->pcd->current_speed |= 0x02;
337 pcd_config_iso14443_card(CONFIGNOTHING, TYPEA_424TX | typeB);
339 else if((speedParam & 0x03) == 0x01) {
340 // DR = 2 supported, PCD to PICC, 1 etu = 64 / fc, bit rate supported is fc / 64 (~ 212 kbit/s)
341 picc->pcd->current_speed |= 0x01;
342 pcd_config_iso14443_card(CONFIGNOTHING, TYPEA_212TX | typeB);
345 if((speedParam & 0x0c) == 0x0c) {
346 // DS = 8 supported, PICC to PCD, 1 etu = 16 / fc, bit rate supported is fc / 16 (~ 848 kbit/s)
347 picc->pcd->current_speed |= 0x18;
348 pcd_config_iso14443_card(CONFIGNOTHING, TYPEA_848RX | typeB); /* RX */
350 else if((speedParam & 0x0c) == 0x08) {
351 // DS = 4 supported, PICC to PCD, 1 etu = 32 / fc, bit rate supported is fc / 32 (~ 424 kbit/s)
352 picc->pcd->current_speed |= 0x10;
353 pcd_config_iso14443_card(CONFIGNOTHING, TYPEA_424RX | typeB);
355 else if((speedParam & 0x0c) == 0x04) {
356 // DS = 2 supported, PICC to PCD, 1 etu = 64 / fc, bit rate supported is fc / 64 (~ 212 kbit/s)
357 picc->pcd->current_speed |= 0x08;
358 pcd_config_iso14443_card(CONFIGNOTHING, TYPEA_212RX | typeB);
362 /* 14443-4 Protocol control byte field P22 */
363 void typeA_prologue_feild_load(struct picc_device *picc)
365 if((picc->pcd->PCB & 0xC0) != 0xC0) {
366 // I-block or R-block ,not S-Block
367 // block number toggle
368 if(BITISSET(picc->flags_TCL, PCD_BLOCK_NUMBER)) {
369 picc->pcd->PCB |= 0x01;
371 else {
372 picc->pcd->PCB &= 0xFE;
375 if(BITISSET(picc->flags_TCL, CID_PRESENT)) {
376 picc->pcd->PCB |= 0x08;
378 else {
379 picc->pcd->PCB &= 0xF7;
384 /****************************************************************/
385 // Type A PPS
386 /****************************************************************/
387 void typeA_pps_check_and_send(struct picc_device *picc)
389 uint8_t speedParam;
390 uint8_t RecBuf[5];
391 struct pn51x_request *req = picc->request;
393 speedParam = typeA_speed_check(picc);
394 if(speedParam) {
395 /* 14443-4 Protocol and Parameter Selection P16 */
396 req->buf[0] = 0xD0 | picc->CID;
397 req->buf[1] = 0x11;
398 req->buf[2] = speedParam;
399 typeA_sfg_delay(picc->SFGI);
400 Delay1ms(5); /* liunote why ? */
401 req->length = 3;
402 req->bit_frame = 0x00;
403 req->command = CMD_TRANSCEIVE;
404 req->direction = TRANSCEIVE;
405 req->time_out = 0;
406 typeA_set_timeout(picc, picc->FWI); /* set timeout according FWI */
407 picc_wait_for_req(req); /* Figure 19 - Frame waiting time ,14443-4 P25 */
409 if(!req->error_code) {
410 memcpy(RecBuf, req->buf, req->actual);
411 if((RecBuf[0] & 0xF0) == 0xD0) {
412 // return PPSS, PPS successful , (if successful then response the start byte of pps.)
413 typeA_high_speed_config(picc, speedParam, TYPEA_106TX);
419 int typeA_select_(struct picc_device *picc, uint8_t blockPCB)
421 uint8_t tempFWI;
422 struct pn51x_request *req = picc->request;
424 picc->pcd->PCB = blockPCB;
425 typeA_prologue_feild_load(picc);
426 tempFWI = picc->FWI;
427 tempFWI = (tempFWI > 0x06) ? 0x06 : tempFWI;
429 req->buf[0] = picc->pcd->PCB;
430 if(BITISSET(picc->flags_TCL, CID_PRESENT)) {
431 req->buf[1] = picc->CID;
432 req->length = 2;
434 else
435 req->length = 1;
437 req->bit_frame = 0x00;
438 req->command = CMD_TRANSCEIVE;
439 req->direction = TRANSCEIVE;
440 req->time_out = 0;
441 typeA_set_timeout(picc, tempFWI);
442 picc_wait_for_req(req);
444 pr_debug("%s: ret = %d\n", __func__, req->error_code);
446 return(req->error_code);
449 int typeA_deselect_request(struct picc_device *picc)
451 int ret = 0;
452 struct pn51x_request *req = picc->request;
454 if(picc->states == PICC_ACTIVATED) {
455 picc->pcd->PCB = 0xC2; // S-block, DESELECT
456 typeA_prologue_feild_load(picc);
458 req->buf[0] = picc->pcd->PCB;
459 if(BITISSET(picc->flags_TCL, CID_PRESENT)) {
460 req->buf[1] = picc->CID;
461 req->length = 2;
463 else
464 req->length = 1;
466 req->bit_frame = 0x00;
467 req->command = CMD_TRANSCEIVE;
468 req->direction = TRANSCEIVE;
469 req->time_out = 53;
471 picc_wait_for_req(req);
473 if(picc->states != PICC_POWEROFF) {
474 picc->states = PICC_IDLE;
476 if(picc->type == PICC_TYPEA_TCL) {
477 pcd_config_iso14443_card(CONFIGNOTHING, TYPEA_106TX);
478 pcd_config_iso14443_card(CONFIGNOTHING, TYPEA_106RX);
480 else if(picc->type == PICC_TYPEB_TCL) {
481 pcd_config_iso14443_card(CONFIGNOTHING,TYPEB_106TX);
482 pcd_config_iso14443_card(CONFIGNOTHING,TYPEB_106RX);
486 return(ret);
490 R-block used to convey positive or negative acknowledgements. An R-block never contains an INF field. The
491 acknowledgement relates to the last received block.
493 static int typeA_rblock_command(struct picc_device *picc, uint8_t blockPCB, uint8_t *recBuf, uint32_t *recLen)
495 int ret = 0;
496 struct pn51x_request *req = picc->request;
498 picc->pcd->PCB = blockPCB;
499 typeA_prologue_feild_load(picc);
501 req->buf[0] = picc->pcd->PCB;
502 if(BITISSET(picc->flags_TCL, CID_PRESENT)) {
503 req->buf[1] = picc->CID;
504 req->length = 2;
506 else
507 req->length = 1;
509 req->bit_frame = 0x00;
510 req->command = CMD_TRANSCEIVE;
511 req->direction = TRANSCEIVE;
512 req->time_out = 0;
513 typeA_set_timeout(picc, picc->FWI);
514 picc_wait_for_req(req);
515 memcpy(recBuf, req->buf, req->actual);
516 *recLen = req->actual;
518 return(ret);
521 static int typeA_data_send_error_check(struct picc_device *picc, uint8_t *senBuf, uint32_t senLen, uint8_t *recBuf, uint32_t *recLen)
523 uint8_t timeoutRetry = 0;
524 uint8_t frameRetry = 0;
525 uint8_t ackRetry = 0;
526 uint32_t i;
527 int ret = 0;
528 uint8_t resend;
529 uint8_t resendCount;
530 struct pn51x_request *req = picc->request;
532 resendCount = 0;
533 do {
534 /* send block according picc PCB */
535 resend = 0;
536 picc->pcd->PCB = picc->PCB;
537 typeA_sfg_delay(picc->SFGI);
538 typeA_prologue_feild_load(picc);
540 req->buf[0] = picc->pcd->PCB;
541 if(BITISSET(picc->flags_TCL, CID_PRESENT)) {
542 req->buf[1] = picc->CID;
543 memcpy(req->buf+2, senBuf, senLen);
544 req->length = 2+senLen;
546 else {
547 memcpy(req->buf + 1, senBuf, senLen);
548 req->length = 1 + senLen;
550 req->bit_frame = 0x00;
551 req->command = CMD_TRANSCEIVE;
552 req->direction = TRANSCEIVE;
553 req->time_out = 0;
554 typeA_set_timeout(picc, picc->FWI);
555 picc_wait_for_req(req);
556 memcpy(recBuf, req->buf, req->actual);
557 *recLen = req->actual;
558 ret = req->error_code;
559 while(1) {
560 //Error handling
561 if(ret == -ERROR_NOTAG) { //Time Out
562 CLEAR_BIT(picc->flags_TCL, WTX_REQ_BEFORE);
563 /* Figure 22 -Chaining ,14443-4 P28 */
564 if(BITISSET(picc->flags_TCL, PICC_CHAINING)) {
565 if(ackRetry == 2) {
566 ret = -PICC_ERRORCODE_MUTE;
567 break;
569 ret = typeA_rblock_command(picc, 0xA2, recBuf, recLen); // R-Block: ACK
570 ackRetry++;
572 else {
573 if(timeoutRetry == 2) {
574 ret = -PICC_ERRORCODE_MUTE;
575 break;
577 ret = typeA_rblock_command(picc, 0xB2, recBuf, recLen); // R-Block: NAK
578 timeoutRetry++;
581 else if(!ret) {
582 CLEAR_BIT(picc->flags_TCL, WTX_REQ_BEFORE);
583 if((recBuf[0] & 0xC0) == 0xC0) { /* S-BLOCK */
584 //S-Block received
585 if((recBuf[0] & 0x30) == 0x30) {
586 //S(WTX) received
587 if(recBuf[0] & 0x08) {
588 // CID following
589 if(BITISCLEAR(picc->flags_TCL, CID_PRESENT)) { /* if picc not support cid */
590 ret = (-SLOTERROR_TCL_BLOCK_INVALID);
591 goto err;
594 if(recBuf[0] & 0x04) { /* NAD don't support */
595 ret = (-SLOTERROR_TCL_BLOCK_INVALID);
596 goto err;
599 if(BITISSET(picc->flags_TCL, CID_PRESENT)) {
600 picc->WTXM = recBuf[2];
603 else {
604 picc->WTXM = recBuf[1];
606 if((picc->WTXM == 0) || (picc->WTXM > 59)) {
607 // WTXM must be code in the range from 1 to 59, or it will be treat as a protocol error. ISO/IEC 14443-4:2008
608 ret = (-SLOTERROR_TCL_BLOCK_INVALID);
609 goto err;
611 /* ack WTXM with S-block 14443-4 P25
612 The PCD shall acknowledge by sending an S(WTX) response containing also a 1 byte long INF field that consists
613 of two parts (see Figure 21) and contains the same WTXM as received in the request:
615 picc->pcd->PCB = 0xF2;
616 typeA_sfg_delay(picc->SFGI);
617 typeA_prologue_feild_load(picc);
619 req->buf[0] = picc->pcd->PCB;
620 if(BITISSET(picc->flags_TCL, CID_PRESENT)) {
621 req->buf[1] = picc->CID;
622 req->buf[2] = picc->WTXM;
623 req->length = 3;
625 else {
626 req->buf[1] = picc->WTXM;
627 req->length = 2;
630 req->bit_frame = 0x00;
631 req->command = CMD_TRANSCEIVE;
632 req->direction = TRANSCEIVE;
633 req->time_out = 0;
634 typeA_set_timeout(picc, picc->FWI);
635 picc_wait_for_req(req);
636 memcpy(recBuf, req->buf, req->actual);
637 *recLen = req->actual;
638 ret = req->error_code;
639 SET_BIT(picc->flags_TCL, WTX_REQUEST); // the time FWTtemp starts after the PCD has sent the S(WTX) response
640 SET_BIT(picc->flags_TCL, WTX_REQ_BEFORE);
642 else {
643 ret = (-SLOTERROR_TCL_BLOCK_INVALID);
644 goto err;
647 else if((recBuf[0] & 0xC0) == 0x80) { /* R-BLOCK b101X-X01X */
648 //R-Block received
649 if(recBuf[0] & 0x14) {
650 ret = (-SLOTERROR_TCL_BLOCK_INVALID); //PICC Never send a R(NAK) and Never used NAD
651 goto err;
653 if((recBuf[0] & 0x20) == 0x00) {
654 ret = (-SLOTERROR_TCL_BLOCK_INVALID); // R(ACK) bit 6 must set to 1
655 goto err;
657 if(recBuf[0] & 0x08) {
658 if(BITISCLEAR(picc->flags_TCL, CID_PRESENT)) { /* receiver pcd having CID, but pcc don't set */
659 ret = (-SLOTERROR_TCL_BLOCK_INVALID);
660 goto err;
664 if((picc->PCB ^ recBuf[0]) & 0x01) {/* R-block block number must equal I block block number */
666 // the block number of R-block do not equal the block number of the last I-block
667 timeoutRetry = 0;
669 if(resendCount == 2) {
670 ret = -SLOTERROR_TCL_3RETRANSMIT_FAIL;
671 goto err;
673 picc->PCB &= 0x1F; /* back to I block */
674 for(i = 0; i < senLen; i++) {
675 senBuf[i] = tempIBlockBuf[i];
678 //re-transmit last I-block
679 resend = 01;
680 resendCount++;
682 else {
683 if(BITISSET(picc->flags_TCL, PCD_CHAINING)) {
684 // PCD Chaining continue
685 TOGGLE_BIT(picc->flags_TCL, PCD_BLOCK_NUMBER);
687 else {
688 ret = (-SLOTERROR_TCL_BLOCK_INVALID);
689 goto err;
692 break;
694 else if((recBuf[0] & 0xC0) == 0x00) {
695 //I-Block received
696 if(recBuf[0] & 0x08) {
697 if(BITISCLEAR(picc->flags_TCL, CID_PRESENT)) {
698 ret = (-SLOTERROR_TCL_BLOCK_INVALID);
699 goto err;
703 if((recBuf[0] & 0x02) == 0x00) { /* must set 1 ,14443-4 P23 Figure 15 - Coding of I-block PCB */
704 ret = (-SLOTERROR_TCL_BLOCK_INVALID);
705 goto err;
708 if(recBuf[0] & 0x04) { // Not used NAD
709 ret = (-SLOTERROR_TCL_BLOCK_INVALID);
710 goto err;
713 if(BITISSET(picc->flags_TCL, PCD_CHAINING)) { /* last sent block should not be a chain block before receive a I block */
714 ret = (-SLOTERROR_TCL_BLOCK_INVALID);
715 goto err;
717 else {
718 if((picc->PCB ^ recBuf[0]) & 0x01) { //Block number error
719 ret = (-SLOTERROR_TCL_BLOCK_INVALID);
720 goto err;
723 TOGGLE_BIT(picc->flags_TCL, PCD_BLOCK_NUMBER);
725 if(recBuf[0] & 0x10) { /* will continue for chaining I block */
726 SET_BIT(picc->flags_TCL, PICC_CHAINING);
728 else {
729 CLEAR_BIT(picc->flags_TCL, PICC_CHAINING);
731 break;
734 else {
735 ret = (-SLOTERROR_TCL_BLOCK_INVALID);
736 goto err;
738 } /*end if !ret */
739 else if(ret == -ERROR_PROTOCOL) {
740 if(BITISSET(picc->flags_TCL, WTX_REQ_BEFORE)) {
741 SET_BIT(picc->flags_TCL, WTX_REQUEST);
742 CLEAR_BIT(picc->flags_TCL, WTX_REQ_BEFORE);
745 if(BITISSET(picc->flags_TCL, PICC_CHAINING)) {
746 if(ackRetry == 2) {
747 ret = -SLOTERROR_T1_3RETRY_FAIL_RESYNCH_FAIL;
748 break;
750 typeA_sfg_delay(picc->SFGI);
751 ret = typeA_rblock_command(picc, 0xA2,recBuf,recLen); /* send R-block ACK , then get recv buf to recbuf */
752 ackRetry++;
754 else {
755 if(frameRetry == 2) {
756 ret = -SLOTERROR_T1_3RETRY_FAIL_RESYNCH_FAIL;
757 break;
759 typeA_sfg_delay(picc->SFGI);
760 ret = typeA_rblock_command(picc, 0xB2,recBuf,recLen); /* send R-block NAK , then get recv buf to recbuf */
761 frameRetry++;
764 else {
765 CLEAR_BIT(picc->flags_TCL, WTX_REQ_BEFORE);
766 ret = -PICC_ERRORCODE_MUTE;
767 goto err;
770 }while(resend);
772 err:
773 return(ret);
776 int typeA_standard_apdu_handler(struct picc_device *picc, uint8_t *cmdBuf, uint32_t senLen, uint8_t *recBuf, uint32_t *recLen, uint8_t *level)
778 int ret = 0;
779 uint32_t i;
780 uint32_t tempSenLen;
781 uint32_t offset;
782 uint32_t tempRecLen;
783 uint8_t *pSenAddr;
784 uint8_t *pRecAddr;
785 uint32_t ChainLastLen = 0;
786 uint32_t LastCCIDRemainLen = 0x00;
788 pSenAddr = cmdBuf;
789 pRecAddr = recBuf;
790 tempRecLen = 0;
791 if(*level == 0x10) {
792 senLen = 0;
793 *recLen = 0;
794 for(i = 0; i < ChainLastLen; i++) { /* ChainLastLen = 0 liunote why ? */
795 recBuf[i] = tempIBlockBuf[i];
797 tempRecLen = ChainLastLen;
798 *recLen = ChainLastLen;
799 ChainLastLen = 0;
801 else if(((*level == 0x03) || (*level == 0x02)) && (LastCCIDRemainLen != 0)) {
802 i = senLen;
803 while(i--) {
804 pSenAddr[i + LastCCIDRemainLen] = pSenAddr[i];
806 for(i=0; i < LastCCIDRemainLen; i++) {
807 pSenAddr[i] = tempIBlockBuf[i];
809 senLen += LastCCIDRemainLen;
810 LastCCIDRemainLen = 0;
813 while(senLen) { /* start send */
814 CLEAR_BIT(picc->flags_TCL, PICC_CHAINING);
815 if((senLen <= picc->FSC) && ((*level == 0x02) || (*level == 0x00))) {
816 CLEAR_BIT(picc->flags_TCL, PCD_CHAINING); /* don't need chaining ,because send lenght litter than FSC */
817 picc->PCB = 0x02; // I-block, no chaining
818 if(BITISSET(picc->flags_TCL, PCD_BLOCK_NUMBER)) {
819 picc->PCB |= 0x01;
821 if(BITISSET(picc->flags_TCL, CID_PRESENT)) {
822 picc->PCB |= 0x08;
824 tempSenLen = senLen;
825 ret = typeA_data_send_error_check(picc, pSenAddr, tempSenLen, pRecAddr, &tempRecLen);
827 senLen = 0;
829 if(!ret) {
830 /* 14443-4 P21 get the Information field */
831 if(BITISSET(picc->flags_TCL, CID_PRESENT)) {
832 offset = 2;
834 else {
835 offset = 1;
837 tempRecLen -= offset;
838 for(i = 0; i < tempRecLen; i++) {
839 pRecAddr[i] = pRecAddr[i + offset];
842 if(tempRecLen == 1) { /* only 1 byte Information field , liunote ,why set as below ? */
843 pRecAddr[1] = 0x90;
844 pRecAddr[2] = 0x00;
845 *recLen = 3;
847 else {
848 *recLen = tempRecLen;
851 else {
852 CLEAR_BIT(picc->flags_TCL, PICC_CHAINING);
855 else {
856 // PCD chaining
857 SET_BIT(picc->flags_TCL, PCD_CHAINING);
858 picc->PCB = 0x12;
859 if(BITISSET(picc->flags_TCL, PCD_BLOCK_NUMBER)) {
860 picc->PCB |= 0x01;
862 if(BITISSET(picc->flags_TCL, CID_PRESENT)) {
863 picc->PCB |= 0x08;
865 ret = typeA_data_send_error_check(picc, pSenAddr, picc->FSC, pRecAddr, &tempRecLen);
866 CLEAR_BIT(picc->flags_TCL, PCD_CHAINING);
867 if(!ret) {
868 senLen -= picc->FSC;
869 pSenAddr += picc->FSC;
870 if(((*level == 0x01) || (*level == 0x03)) && (senLen < picc->FSC)) {
871 LastCCIDRemainLen = senLen; /* need send at next, while don't send ? liunote (typeA_data_send_error_check will continue chaining ) */
872 for(i = 0; i < LastCCIDRemainLen; i++) {
873 tempIBlockBuf[i] = pSenAddr[i];
875 *recLen = 0;
876 *level = 0x10;
877 senLen = 0;
878 CLEAR_BIT(picc->flags_TCL, PICC_CHAINING);
879 return(ret);
882 else {
883 senLen = 0;
884 CLEAR_BIT(picc->flags_TCL, PICC_CHAINING);
889 // PICC Chaining // only recv ?
890 while(BITISSET(picc->flags_TCL, PICC_CHAINING)) {
891 picc->PCB = 0xA2;
892 if(BITISSET(picc->flags_TCL, PCD_BLOCK_NUMBER)) {
893 picc->PCB |= 0x01;
895 if(BITISSET(picc->flags_TCL, CID_PRESENT)) {
896 picc->PCB |= 0x08;
898 pRecAddr += tempRecLen;
899 ret = typeA_data_send_error_check(picc, pSenAddr, 0, pRecAddr, &tempRecLen);
901 if(!ret) {
902 if(BITISSET(picc->flags_TCL, CID_PRESENT)) {
903 offset = 2;
905 else {
906 offset = 1;
908 tempRecLen -= offset;
909 for(i = 0; i < tempRecLen; i++) { /* only get the inf data*/
910 pRecAddr[i] = pRecAddr[i + offset];
912 *recLen += tempRecLen;
914 if(*recLen > APDURECLENTHREHOLD) {
915 if(*level == 0x10) { //Continue Chaining
916 *level = 0x03;
918 else {
919 *level = 0x01; //Chaining Beginning
921 ChainLastLen = (uint8_t)(*recLen - APDURECLENTHREHOLD);
922 for(i = 0; i < ChainLastLen; i++) {
923 tempIBlockBuf[i] = recBuf[i + APDURECLENTHREHOLD];
925 *recLen = APDURECLENTHREHOLD;
926 picc->pcd->piccPoll = FALSE;
927 picc->pcd->poll_interval = 1000; // 1000ms, start another poll
928 return(0);
931 else {
932 CLEAR_BIT(picc->flags_TCL, PICC_CHAINING);
935 if(*level == 0x10) {
936 *level = 0x02;
938 else {
939 *level = 0x00;
942 if(!ret) {
943 picc->pcd->piccPoll = FALSE;
944 picc->pcd->poll_interval = 1000; // 1000ms, start another poll
946 else {
947 picc->pcd->piccPoll = TRUE;
948 recBuf[0] = 0x63;
949 recBuf[1] = 0x00;
950 *recLen = 2;
951 CLEAR_BIT(picc->flags_TCL, PCD_CHAINING);
952 CLEAR_BIT(picc->flags_TCL, PICC_CHAINING);
955 return(ret);