takashi kadono / Mbed OS Nucleo_446

Dependencies:   ssd1331

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers pn512_poll.c Source File

pn512_poll.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2014-2018, ARM Limited, All Rights Reserved
00003  * SPDX-License-Identifier: Apache-2.0
00004  *
00005  * Licensed under the Apache License, Version 2.0 (the "License"); you may
00006  * not use this file except in compliance with the License.
00007  * You may obtain a copy of the License at
00008  *
00009  * http://www.apache.org/licenses/LICENSE-2.0
00010  *
00011  * Unless required by applicable law or agreed to in writing, software
00012  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
00013  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  * See the License for the specific language governing permissions and
00015  * limitations under the License.
00016  */
00017 /**
00018  * \file pn512_poll.c
00019  * \copyright Copyright (c) ARM Ltd 2014
00020  * \author Donatien Garnier
00021  */
00022 
00023 #define __DEBUG__ 0
00024 #ifndef __MODULE__
00025 #define __MODULE__ "pn512_poll.c"
00026 #endif
00027 
00028 #include "stack/nfc_errors.h"
00029 
00030 #include "pn512.h"
00031 #include "pn512_poll.h"
00032 #include "pn512_transceive.h"
00033 #include "pn512_registers.h"
00034 #include "pn512_rf.h"
00035 #include "pn512_cmd.h"
00036 #include "pn512_internal.h"
00037 
00038 #define TIMEOUT 1000
00039 
00040 static void pn512_target_anticollision(pn512_t *pPN512, pn512_cb_t cb);
00041 static void pn512_initiator_isoa_anticollision(pn512_t *pPN512, pn512_cb_t cb);
00042 
00043 static inline bool pn512_config_initiator(pn512_t *pPN512)
00044 {
00045     return (pPN512->config.initiators.nfc_iso_dep_a | pPN512->config.initiators.nfc_iso_dep_b |
00046             pPN512->config.initiators.nfc_nfc_dep_a | pPN512->config.initiators.nfc_nfc_dep_f_212 | pPN512->config.initiators.nfc_nfc_dep_f_424 |
00047             pPN512->config.initiators.nfc_type1 | pPN512->config.initiators.nfc_type2 | pPN512->config.initiators.nfc_type3) != 0;
00048 }
00049 
00050 static inline bool pn512_config_target(pn512_t *pPN512)
00051 {
00052     return (pPN512->config.targets.nfc_iso_dep_a | pPN512->config.targets.nfc_iso_dep_b |
00053             pPN512->config.targets.nfc_nfc_dep_a | pPN512->config.targets.nfc_nfc_dep_f_212 | pPN512->config.initiators.nfc_nfc_dep_f_424 |
00054             pPN512->config.targets.nfc_type1 | pPN512->config.targets.nfc_type2 | pPN512->config.targets.nfc_type3) != 0;
00055 }
00056 
00057 void pn512_target_anticollision_complete(pn512_t *pPN512, nfc_err_t ret)
00058 {
00059 
00060     bool iso14443a = pPN512->config.targets.nfc_type2 || pPN512->config.targets.nfc_iso_dep_a || pPN512->config.targets.nfc_nfc_dep_a; //We do not support type 1 card emulation so irrelevant
00061     bool felica = pPN512->config.targets.nfc_type3 || pPN512->config.targets.nfc_nfc_dep_f_212 || pPN512->config.targets.nfc_nfc_dep_f_424;
00062 
00063     nfc_transceiver_t *pTransceiver = &pPN512->transceiver;
00064     if (ret) {
00065         NFC_WARN("Returned %d", ret);
00066         pn512_anticollision_callback(pPN512, ret);
00067         return;
00068     }
00069 
00070     //Data available in FIFO
00071     if (pPN512->readLastByteLength != 8) { //We should receive a full byte
00072         NFC_WARN("Not enough data in FIFO");
00073         pn512_anticollision_callback(pPN512, NFC_ERR_PROTOCOL);
00074         return;
00075     }
00076 
00077     //If successful, update state machine
00078     if (iso14443a && felica) {
00079         //Update current protocol accordingly
00080         uint8_t txmode = pn512_register_read(pPN512, PN512_REG_TXMODE);
00081         if ((txmode & 0x03) == 0x00) {
00082             pn512_framing_set(pPN512, nfc_framing_target_a_106);
00083 
00084             NFC_DBG("A 106");
00085             felica = false;
00086         } else if ((txmode & 0x03) == 0x02) {
00087             if ((txmode & 0x70) == 0x20) {
00088                 //424kbps
00089                 NFC_DBG("F 424");
00090                 pn512_framing_set(pPN512, nfc_framing_target_f_424);
00091             } else {
00092                 //212kbps
00093                 NFC_DBG("F 212");
00094                 pn512_framing_set(pPN512, nfc_framing_target_f_212);
00095             }
00096             iso14443a = false;
00097         } else {
00098             //Unsupported mode, exit
00099             pn512_anticollision_callback(pPN512, NFC_ERR_UNSUPPORTED);
00100             return;
00101         }
00102     }
00103 
00104     if (iso14443a) {
00105         if (ac_buffer_reader_readable(ac_buffer_builder_buffer(&pPN512->readBufBldr)) == 0) {
00106             pn512_anticollision_callback(pPN512, NFC_ERR_PROTOCOL);
00107             return;
00108         }
00109 
00110         //Halt device, so that if anticollision is restarted it's in the correct state (cleared automatically by RF reset)
00111         pn512_register_write(pPN512, PN512_REG_MIFNFC, 0x62 | 0x04);
00112 
00113         //Copy buffer to peek
00114         ac_buffer_t readBufDup;
00115         ac_buffer_dup(&readBufDup, ac_buffer_builder_buffer(&pPN512->readBufBldr));
00116 
00117         uint8_t b0 = ac_buffer_read_nu8(&readBufDup);
00118 
00119         //Get first byte
00120         //Read FIFO to see if the target was selected as NFC-DEP, ISO-DEP or proprietary (NFC Type 2)
00121         //F0 --> NFC-DEP
00122         //E0 --> ISO-DEP
00123         //Anything else --> NFC Type 2
00124 
00125         //First check if this could be NFC-DEP
00126         if (pPN512->config.targets.nfc_nfc_dep_a && (b0 == 0xF0)) {
00127             pTransceiver->active_tech.nfc_nfc_dep_a = true;
00128         } else if (pPN512->config.targets.nfc_iso_dep_a && (b0 == 0xE0)) {
00129             pTransceiver->active_tech.nfc_iso_dep_a = true;
00130         } else if (pPN512->config.targets.nfc_type2) {
00131             pTransceiver->active_tech.nfc_type2 = true;
00132         } else {
00133             //Unknown tech, return error
00134             pn512_anticollision_callback(pPN512, NFC_ERR_UNSUPPORTED);
00135             return;
00136         }
00137 
00138         //Give control to higher layer
00139         pn512_anticollision_callback(pPN512, NFC_OK);
00140         return;
00141     } else if (felica) {
00142         //First check if this could be NFC-DEP
00143         if ((pPN512->config.targets.nfc_nfc_dep_f_212 || pPN512->config.targets.nfc_nfc_dep_f_424)) {
00144             if (pPN512->framing == nfc_framing_target_f_424) {
00145                 pTransceiver->active_tech.nfc_nfc_dep_f_424 = true;
00146             } else {
00147                 pTransceiver->active_tech.nfc_nfc_dep_f_212 = true;
00148             }
00149         } else {
00150             pn512_anticollision_callback(pPN512, NFC_ERR_UNSUPPORTED);
00151             return;
00152         }
00153     }
00154 
00155     //NFC-IP 1 active mode is not supported by other devices so ignore it for now
00156     pn512_anticollision_callback(pPN512, NFC_OK);
00157 }
00158 
00159 
00160 void pn512_target_anticollision(pn512_t *pPN512, pn512_cb_t cb)
00161 {
00162     pPN512->anticollision.cb = cb;
00163 
00164     //Reset active states
00165     pPN512->transceiver.initiator_ntarget = false;
00166     pPN512->transceiver.active_tech.nfc_type1 = pPN512->transceiver.active_tech.nfc_type2 = pPN512->transceiver.active_tech.nfc_type3
00167                                                                                             = pPN512->transceiver.active_tech.nfc_iso_dep_a = pPN512->transceiver.active_tech.nfc_nfc_dep_a =
00168                                                                                                         pPN512->transceiver.active_tech.nfc_nfc_dep_f_212 = pPN512->transceiver.active_tech.nfc_nfc_dep_f_424 = 0;
00169 
00170     pn512_set_timeout((nfc_transceiver_t *)pPN512, -1); //Should only fail on RF drop
00171 
00172     pn512_transceive_hw(pPN512, pn512_transceive_mode_target_autocoll, pn512_target_anticollision_complete);
00173 }
00174 
00175 // ISO A
00176 
00177 #define ISO14443A_BUF_SIZE 8
00178 
00179 #define REQA 0x26
00180 #define SEL(n) (0x93 + (n)*2)
00181 #define NVB(bits) ( (((2*8 + (bits))>>3)<<4) | ((bits) & 0x7) )
00182 #define HALTA1 0x50
00183 #define HALTA2 0x00
00184 #define CT 0x88
00185 
00186 static void pn512_initiator_isoa_anticollision_reqa(pn512_t *pPN512);
00187 static void pn512_initiator_isoa_anticollision_atqa(pn512_t *pPN512, nfc_err_t ret);
00188 static void pn512_initiator_isoa_anticollision_cascade_1(pn512_t *pPN512);
00189 static void pn512_initiator_isoa_anticollision_cascade_2(pn512_t *pPN512, nfc_err_t ret);
00190 static void pn512_initiator_isoa_anticollision_cascade_3(pn512_t *pPN512, nfc_err_t ret);
00191 static void pn512_initiator_isoa_anticollision_cascade_4(pn512_t *pPN512, nfc_err_t ret);
00192 static void pn512_initiator_isoa_anticollision_complete(pn512_t *pPN512);
00193 
00194 void pn512_initiator_isoa_anticollision(pn512_t *pPN512, pn512_cb_t cb)
00195 {
00196     pPN512->anticollision.cb = cb;
00197 
00198     // Reset transceive mode
00199     pPN512->transceive.mode = pn512_transceive_mode_idle;
00200 
00201     pn512_initiator_isoa_anticollision_reqa(pPN512);
00202 }
00203 
00204 void pn512_initiator_isoa_anticollision_reqa(pn512_t *pPN512)
00205 {
00206     ac_buffer_builder_t *pDataOutBldr = &pPN512->readBufBldr;
00207     ac_buffer_builder_reset(pDataOutBldr);
00208 
00209     pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].nfcA.uidLength = 0;
00210 
00211     ac_buffer_builder_write_nu8(pDataOutBldr, REQA);
00212     pn512_set_last_byte_length((nfc_transceiver_t *)pPN512, 7); //Only 7 bits in this first command
00213     // FIXME PN512 Anomaly: pn512_register_write(pPN512, PN512_REG_COLL, 0x00); // Set MSB to 0, to accept collisions
00214     pn512_set_crc((nfc_transceiver_t *)pPN512, false, false);
00215     pn512_set_timeout((nfc_transceiver_t *)pPN512, 4);
00216     pn512_set_write((nfc_transceiver_t *)pPN512, ac_buffer_builder_buffer(pDataOutBldr));
00217 
00218     pn512_transceive_hw(pPN512, pn512_transceive_mode_transceive, pn512_initiator_isoa_anticollision_atqa);
00219 }
00220 
00221 void pn512_initiator_isoa_anticollision_atqa(pn512_t *pPN512, nfc_err_t ret)
00222 {
00223     // Clear collisions register
00224     // FIXME PN512 Anomaly: pn512_register_write(pPN512, PN512_REG_COLL, 0x80); // Set MSB to 1, to treat collisions as errors
00225 
00226     if (ret && (ret != NFC_ERR_COLLISION)) { // There might be collisions here
00227         NFC_WARN("Did not receive ATQA: error %d", ret);
00228         pn512_anticollision_callback(pPN512, NFC_ERR_NOPEER);
00229         return;
00230     }
00231 
00232     ac_buffer_t *pResp = pn512_get_read((nfc_transceiver_t *)pPN512);
00233 
00234     if (ac_buffer_reader_readable(pResp) != 2) {
00235         NFC_WARN("Wrong length (%u bytes)", ac_buffer_reader_readable(pResp));
00236         pn512_anticollision_callback(pPN512, NFC_ERR_PROTOCOL);
00237         return;
00238     }
00239 
00240     NFC_DBG("Got ATQA:");
00241     NFC_DBG_BLOCK(ac_buffer_dump(pResp);)
00242 
00243     // Ignore ATQA as there can be collisions
00244     ac_buffer_read_n_bytes(pResp, pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].nfcA.atqa, 2);
00245 
00246     //Start cascading
00247     pPN512->anticollision.iso_a.cascade_level = 1;
00248     pPN512->anticollision.iso_a.valid_bits = 0;
00249     pPN512->anticollision.iso_a.more_targets = false;
00250     memset(pPN512->anticollision.iso_a.cln, 0, 5);
00251 
00252     pn512_initiator_isoa_anticollision_cascade_1(pPN512);
00253 }
00254 
00255 void pn512_initiator_isoa_anticollision_cascade_1(pn512_t *pPN512)
00256 {
00257     ac_buffer_builder_t *pDataOutBldr = &pPN512->readBufBldr;
00258     ac_buffer_builder_reset(pDataOutBldr);
00259 
00260     //SEL
00261     ac_buffer_builder_write_nu8(pDataOutBldr, SEL(pPN512->anticollision.iso_a.cascade_level - 1)); //SEL: Cascade level
00262     ac_buffer_builder_write_nu8(pDataOutBldr, NVB(pPN512->anticollision.iso_a.valid_bits)); //First NVB: Bytecount = 2, Bitcount = 0, then adapt if collision detected
00263 
00264     NFC_DBG("SEL - cascade level %u,  %u valid bits - NVB %u", pPN512->anticollision.iso_a.cascade_level, pPN512->anticollision.iso_a.valid_bits, NVB(pPN512->anticollision.iso_a.valid_bits));
00265 
00266     if (pPN512->anticollision.iso_a.valid_bits > 0) {
00267         // Transmit first part of uid
00268         ac_buffer_builder_write_n_bytes(pDataOutBldr, pPN512->anticollision.iso_a.cln, (pPN512->anticollision.iso_a.valid_bits >> 3) + ((pPN512->anticollision.iso_a.valid_bits & 0x7) ? 1 : 0));
00269         pn512_set_last_byte_length((nfc_transceiver_t *)pPN512, pPN512->anticollision.iso_a.valid_bits & 0x7);
00270         pn512_set_first_byte_align((nfc_transceiver_t *)pPN512, pPN512->anticollision.iso_a.valid_bits & 0x7);
00271     }
00272 
00273     // FIXME PN512 Anomaly: pn512_register_write(pPN512, PN512_REG_COLL, 0x00); // Set MSB to 0, to accept collisions
00274     pn512_set_crc((nfc_transceiver_t *)pPN512, false, false);
00275     pn512_set_timeout((nfc_transceiver_t *)pPN512, 30);
00276     pn512_set_write((nfc_transceiver_t *)pPN512, ac_buffer_builder_buffer(pDataOutBldr));
00277 
00278 
00279     pn512_register_write(pPN512, PN512_REG_COMIRQ, 2);
00280     NFC_DBG("IRQ status %04X", ((pn512_register_read(pPN512, PN512_REG_COMIRQ))
00281                                 | ((pn512_register_read(pPN512, PN512_REG_DIVIRQ)) << 8)));
00282 
00283     pn512_transceive_hw(pPN512, pn512_transceive_mode_transceive, pn512_initiator_isoa_anticollision_cascade_2);
00284 }
00285 
00286 void pn512_initiator_isoa_anticollision_cascade_2(pn512_t *pPN512, nfc_err_t ret)
00287 {
00288     ac_buffer_t *pResp = pn512_get_read((nfc_transceiver_t *)pPN512);
00289 
00290     // Load & clear collisions register
00291     // FIXME PN512 Anomaly: pn512_register_write(pPN512, PN512_REG_COLL, 0x80); // Set MSB to 1, to treat collisions as errors
00292 
00293     if (ret && (ret != NFC_ERR_COLLISION)) { // There might be collisions here
00294         NFC_WARN("Did not receive response: error %d", ret);
00295         pn512_anticollision_callback(pPN512, ret);
00296         return;
00297     }
00298 
00299     // We should receive 5 bytes back minus all the CLn bits that we have transmitted; we ignore all bits from the first collision
00300     size_t expected_resp_bits = (5 << 3) - pPN512->anticollision.iso_a.valid_bits;
00301 
00302     // Check for collision
00303     uint8_t valid_bits = expected_resp_bits;
00304     if (ret == NFC_ERR_COLLISION) {
00305         uint8_t coll_reg = pn512_register_read(pPN512, PN512_REG_COLL);
00306 
00307         // FIXME - PN512 error
00308         //if( !(coll_reg & 0x20) ) // bit 5 is CollPosNotValidSet
00309         {
00310             valid_bits = (coll_reg & 0x1f);
00311 
00312             if (valid_bits == 0) {
00313                 valid_bits = 32;
00314             }
00315 
00316             valid_bits--;
00317 
00318             NFC_DBG("Collision detected, %u valid bits", valid_bits);
00319             if (valid_bits < expected_resp_bits) {
00320                 // Collision detected
00321                 pPN512->anticollision.iso_a.more_targets = true;
00322             } else {
00323                 valid_bits = expected_resp_bits;
00324             }
00325         }
00326     }
00327 
00328     size_t resp_sz = (valid_bits >> 3) + ((valid_bits & 0x7) ? 1 : 0);
00329     if (ac_buffer_reader_readable(pResp) < resp_sz) {
00330         (void) pn512_register_read(pPN512, PN512_REG_COLL);
00331 
00332         NFC_WARN("Wrong length (%u instead of %u - valid bits %u)", ac_buffer_reader_readable(pResp), resp_sz, valid_bits);
00333         pn512_anticollision_callback(pPN512, NFC_ERR_PROTOCOL);
00334         return;
00335     }
00336 
00337     // Read bytes
00338     uint8_t bufIn[5] = {0};
00339     ac_buffer_read_n_bytes(pResp, bufIn + (pPN512->anticollision.iso_a.valid_bits >> 3), resp_sz);
00340 
00341     // Mask out valid bits that are already known
00342     bufIn[pPN512->anticollision.iso_a.valid_bits >> 3] &= 0xff << (pPN512->anticollision.iso_a.valid_bits & 0x7);
00343 
00344     // Update number of valid bits
00345     pPN512->anticollision.iso_a.valid_bits += valid_bits;
00346 
00347     // Mask out bits past valid bits in last byte
00348     bufIn[pPN512->anticollision.iso_a.valid_bits >> 3] &= 0xff >> ((8 - pPN512->anticollision.iso_a.valid_bits) & 0x7);
00349 
00350     // Now remember bits before collision
00351     for (size_t p = 0; p < 5; p++) {
00352         pPN512->anticollision.iso_a.cln[p] |= bufIn[p];
00353     }
00354 
00355     // If we have all bits, then check BCC, go to next step
00356     if (pPN512->anticollision.iso_a.valid_bits < 5 * 8) { // Collision, add a 1 at the end of known bits to resolve collision
00357         pPN512->anticollision.iso_a.cln[pPN512->anticollision.iso_a.valid_bits >> 3] |= (1 << (pPN512->anticollision.iso_a.valid_bits & 0x7));
00358         pPN512->anticollision.iso_a.valid_bits++;
00359 
00360         // Restart first step with more valid bits
00361         pn512_initiator_isoa_anticollision_cascade_1(pPN512);
00362         return;
00363     }
00364 
00365     //Check BCC if all bits are valid
00366     if (pPN512->anticollision.iso_a.cln[4] != (pPN512->anticollision.iso_a.cln[0] ^ pPN512->anticollision.iso_a.cln[1] ^ pPN512->anticollision.iso_a.cln[2] ^ pPN512->anticollision.iso_a.cln[3])) {
00367         NFC_WARN("Wrong BCC %02X != %02X", bufIn[4], bufIn[0] ^ bufIn[1] ^ bufIn[2] ^ bufIn[3]);
00368         pn512_anticollision_callback(pPN512, NFC_ERR_COLLISION);
00369         return; //TODO handle this properly
00370     }
00371 
00372     if (pPN512->anticollision.iso_a.cln[0] == CT) {
00373         //Not the last cascade level
00374         if (pPN512->anticollision.iso_a.cascade_level == 3) { // not allowed
00375             NFC_WARN("Cascade tag present in cascade level 3");
00376             pn512_anticollision_callback(pPN512, NFC_ERR_PROTOCOL);
00377             return;
00378         }
00379         memcpy(&pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].nfcA.uid[(pPN512->anticollision.iso_a.cascade_level - 1) * 3], &pPN512->anticollision.iso_a.cln[1], 3);
00380         pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].nfcA.uidLength += 3;
00381     } else {
00382         //Last cascade level
00383         memcpy(&pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].nfcA.uid[(pPN512->anticollision.iso_a.cascade_level - 1) * 3], &pPN512->anticollision.iso_a.cln[0], 4);
00384         pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].nfcA.uidLength += 4;
00385     }
00386 
00387     ac_buffer_builder_t *pDataOutBldr = &pPN512->readBufBldr;
00388     ac_buffer_builder_reset(pDataOutBldr);
00389 
00390     //Select and get SAK
00391     ac_buffer_builder_write_nu8(pDataOutBldr, SEL(pPN512->anticollision.iso_a.cascade_level - 1));  //SEL: Cascade level
00392     ac_buffer_builder_write_nu8(pDataOutBldr, NVB(40));  //NVB: 40 valid bits = 5 bytes
00393 
00394     //Transmit last 4 transmitted UID bytes + BCC (including cascade byte if relevant)
00395     ac_buffer_builder_write_n_bytes(pDataOutBldr, pPN512->anticollision.iso_a.cln, 5);
00396 
00397     NFC_DBG("Selecting target");
00398 
00399     //This time compute & check CRC
00400     pn512_set_crc((nfc_transceiver_t *)pPN512, true, true);
00401     pn512_set_write((nfc_transceiver_t *)pPN512, ac_buffer_builder_buffer(pDataOutBldr));
00402     pn512_transceive_hw(pPN512, pn512_transceive_mode_transceive, pn512_initiator_isoa_anticollision_cascade_3);
00403 }
00404 
00405 static void pn512_initiator_isoa_anticollision_cascade_3(pn512_t *pPN512, nfc_err_t ret)
00406 {
00407     ac_buffer_t *pResp = pn512_get_read((nfc_transceiver_t *)pPN512);
00408 
00409     if (ret) {
00410         NFC_WARN("Did not receive response: error %d", ret);
00411         pn512_anticollision_callback(pPN512, ret);
00412         return;
00413     }
00414 
00415     if (ac_buffer_reader_readable(pResp) != 1) {
00416         NFC_WARN("Wrong length");
00417         pn512_anticollision_callback(pPN512, NFC_ERR_PROTOCOL);
00418         return;
00419     }
00420 
00421     pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].nfcA.sak = ac_buffer_read_nu8(pResp);
00422     NFC_DBG("Got SAK %02X", pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].nfcA.sak);
00423 
00424     //Check SAK
00425     if (pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].nfcA.sak & 0x04) {
00426         //Continue anticollision
00427         pPN512->anticollision.iso_a.cascade_level++;
00428         pPN512->anticollision.iso_a.valid_bits = 0;
00429         memset(pPN512->anticollision.iso_a.cln, 0, 5);
00430         pn512_initiator_isoa_anticollision_cascade_1(pPN512);
00431     } else {
00432         //Anticollision complete
00433 
00434         NFC_DBG("Found one target- SAK = %02X", pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].nfcA.sak);
00435 
00436         //Analyze SAK
00437         memset(&pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].type, 0, sizeof(nfc_tech_t));
00438 
00439         if (pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].nfcA.sak & 0x40) { //NFC-IP1 compliant
00440             pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].type.nfc_nfc_dep_a = true;
00441         }
00442         if ((pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].nfcA.sak & 0x20)
00443                 && pPN512->config.initiators.nfc_iso_dep_a) { //ISO-14443A-4 compliant
00444             pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].type.nfc_iso_dep_a = true;
00445         }
00446         if (!(pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].nfcA.sak & 0x60)
00447                 && pPN512->config.initiators.nfc_type2) { //Potentially NFC Type 2 (or Mifare, etc)
00448             pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].type.nfc_type2 = true;
00449         }
00450 
00451         // Unknown target
00452         if (!pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].type.nfc_iso_dep_a
00453                 && !pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].type.nfc_nfc_dep_a
00454                 && !pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].type.nfc_type2
00455            ) {
00456             pn512_anticollision_callback(pPN512, NFC_ERR_NOPEER);
00457             return;
00458         }
00459 
00460         // Valid target detected
00461         pPN512->transceiver.active_tech = pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].type;
00462         pPN512->transceiver.remote_targets_count++;
00463 
00464         if (!pPN512->config.options.bail_at_first_target
00465                 && pPN512->anticollision.iso_a.more_targets
00466                 && (pPN512->transceiver.remote_targets_count < MUNFC_MAX_REMOTE_TARGETS)) {
00467             // Halt target and continue with others
00468             ac_buffer_builder_t *pDataOutBldr = &pPN512->readBufBldr;
00469             ac_buffer_builder_reset(pDataOutBldr);
00470 
00471             //HALTA
00472             ac_buffer_builder_write_nu8(pDataOutBldr, HALTA1);
00473             ac_buffer_builder_write_nu8(pDataOutBldr, HALTA2);
00474 
00475             pn512_set_crc((nfc_transceiver_t *)pPN512, true, false);
00476             pn512_set_timeout((nfc_transceiver_t *)pPN512, 30);
00477             pn512_set_write((nfc_transceiver_t *)pPN512, ac_buffer_builder_buffer(pDataOutBldr));
00478             pn512_transceive_hw(pPN512, pn512_transceive_mode_transmit, pn512_initiator_isoa_anticollision_cascade_4);
00479             return;
00480         }
00481 
00482         // Leave it activated and finish!
00483         pn512_initiator_isoa_anticollision_complete(pPN512);
00484     }
00485 }
00486 
00487 static void pn512_initiator_isoa_anticollision_cascade_4(pn512_t *pPN512, nfc_err_t ret)
00488 {
00489     if (ret) {
00490         NFC_WARN("Could not halt device: error %d", ret);
00491         pn512_anticollision_callback(pPN512, ret);
00492         return;
00493     }
00494 
00495     // Start again
00496     pn512_initiator_isoa_anticollision_reqa(pPN512);
00497 }
00498 
00499 void pn512_initiator_isoa_anticollision_complete(pn512_t *pPN512)
00500 {
00501     pn512_anticollision_callback(pPN512, NFC_OK);
00502 }
00503 
00504 // ISO B
00505 static void pn512_initiator_isob_anticollision(pn512_t *pPN512, pn512_cb_t cb);
00506 static void pn512_initiator_isob_anticollision_reqb(pn512_t *pPN512);
00507 static void pn512_initiator_isob_anticollision_atqb(pn512_t *pPN512, nfc_err_t ret);
00508 static void pn512_initiator_isob_anticollision_next_slot(pn512_t *pPN512);
00509 static void pn512_initiator_isob_anticollision_haltb_resp(pn512_t *pPN512, nfc_err_t ret);
00510 static void pn512_initiator_isob_anticollision_complete(pn512_t *pPN512);
00511 
00512 #define REQB 0x05
00513 #define HALTB 0x50
00514 
00515 void pn512_initiator_isob_anticollision(pn512_t *pPN512, pn512_cb_t cb)
00516 {
00517     pPN512->anticollision.cb = cb;
00518     pPN512->anticollision.iso_b.slots_num_exponent = 0; // Start with one slot
00519     pPN512->anticollision.iso_b.slot_number = 0;
00520     pPN512->anticollision.iso_b.found_one = false;
00521 
00522     // Reset transceive mode
00523     pPN512->transceive.mode = pn512_transceive_mode_idle;
00524 
00525     pn512_initiator_isob_anticollision_reqb(pPN512);
00526 }
00527 
00528 void pn512_initiator_isob_anticollision_reqb(pn512_t *pPN512)
00529 {
00530     ac_buffer_builder_t *pDataOutBldr = &pPN512->readBufBldr;
00531     ac_buffer_builder_reset(pDataOutBldr);
00532 
00533     if (pPN512->anticollision.iso_b.slot_number == 0) {
00534         // Send REQB/WUPB
00535         pPN512->anticollision.iso_b.more_targets = false;
00536 
00537         ac_buffer_builder_write_nu8(pDataOutBldr, REQB);
00538         ac_buffer_builder_write_nu8(pDataOutBldr, 0x00); // AFI: All card types should respond
00539         uint8_t wup = 0;
00540         if ((pPN512->anticollision.iso_b.slots_num_exponent == 0)) { //&& (pPN512->anticollision.iso_b.slot_number == 0))
00541             wup |= 0x8; // Send Wake-Up command on first iteration
00542         }
00543         ac_buffer_builder_write_nu8(pDataOutBldr, wup | (pPN512->anticollision.iso_b.slots_num_exponent & 0x7)); // Param: number of slots
00544     } else {
00545         // Just send slot marker
00546         ac_buffer_builder_write_nu8(pDataOutBldr, REQB | ((pPN512->anticollision.iso_b.slot_number & 0xf) << 4));
00547     }
00548 
00549     pn512_set_crc((nfc_transceiver_t *)pPN512, true, true);
00550     pn512_set_timeout((nfc_transceiver_t *)pPN512, 18);
00551     pn512_set_write((nfc_transceiver_t *)pPN512, ac_buffer_builder_buffer(pDataOutBldr));
00552     pn512_transceive_hw(pPN512, pn512_transceive_mode_transceive, pn512_initiator_isob_anticollision_atqb);
00553 }
00554 
00555 void pn512_initiator_isob_anticollision_atqb(pn512_t *pPN512, nfc_err_t ret)
00556 {
00557     // Three cases:
00558     // - 1 response --> store response, halt PICC and check next slot number
00559     // - No response --> check next slot number
00560     // - Collision --> check next slot number but we will have to increment number of slots
00561     ac_buffer_t *pResp = pn512_get_read((nfc_transceiver_t *)pPN512);
00562 
00563     if (ret && (ret != NFC_ERR_COLLISION) && (ret != NFC_ERR_WRONG_COMM) && (ret != NFC_ERR_TIMEOUT)) {
00564         NFC_WARN("Did not receive ATQB: error %u", ret);
00565         pn512_anticollision_callback(pPN512, NFC_ERR_PROTOCOL);
00566         return;
00567     }
00568 
00569     // Increment slot number
00570     pPN512->anticollision.iso_b.slot_number++;
00571 
00572     if ((ret == NFC_ERR_COLLISION) || (ret == NFC_ERR_WRONG_COMM)) {
00573         pPN512->anticollision.iso_b.more_targets = true;
00574     } else if (!ret) {
00575         pPN512->anticollision.iso_b.found_one = true;
00576 
00577         // Decode ATQB
00578         if (ac_buffer_reader_readable(pResp) != 12) {
00579             NFC_WARN("Wrong length (%u bytes)", ac_buffer_reader_readable(pResp));
00580             pn512_anticollision_callback(pPN512, NFC_ERR_PROTOCOL);
00581             return;
00582         }
00583 
00584         NFC_DBG("Got ATQB:");
00585         NFC_DBG_BLOCK(ac_buffer_dump(pResp);)
00586 
00587         // Check first byte
00588         uint8_t atqb0 = ac_buffer_read_nu8(pResp);
00589         if (atqb0 != 0x50) {
00590             NFC_WARN("Wrong first byte for ATQB: %02X", atqb0);
00591             pn512_anticollision_callback(pPN512, NFC_ERR_PROTOCOL);
00592             return;
00593         }
00594 
00595         memset(&pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].type, 0, sizeof(nfc_tech_t));
00596         pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].type.nfc_iso_dep_b = true;
00597 
00598         // Save PUPI, application data & protocol info
00599         ac_buffer_read_n_bytes(pResp, pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].nfcB.pupi, 4);
00600         ac_buffer_read_n_bytes(pResp, pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].nfcB.application_data, 4);
00601         ac_buffer_read_n_bytes(pResp, pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].nfcB.protocol_info, 3);
00602 
00603         // Valid target detected
00604         pPN512->transceiver.active_tech = pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].type;
00605         pPN512->transceiver.remote_targets_count++;
00606 
00607         if (!pPN512->config.options.bail_at_first_target
00608                 && (pPN512->anticollision.iso_b.more_targets || (pPN512->anticollision.iso_b.slot_number < (1 << pPN512->anticollision.iso_b.slots_num_exponent)))
00609                 && (pPN512->transceiver.remote_targets_count < MUNFC_MAX_REMOTE_TARGETS)) {
00610             // Halt target and continue with others
00611             ac_buffer_builder_t *pDataOutBldr = &pPN512->readBufBldr;
00612             ac_buffer_builder_reset(pDataOutBldr);
00613 
00614             // Halt PICC and move on to the next slot
00615 
00616             //HALTB
00617             ac_buffer_builder_write_nu8(pDataOutBldr, HALTB);
00618             ac_buffer_builder_write_n_bytes(pDataOutBldr, pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count - 1].nfcB.pupi, 4);
00619 
00620             pn512_set_crc((nfc_transceiver_t *)pPN512, true, true);
00621             pn512_set_timeout((nfc_transceiver_t *)pPN512, 30);
00622             pn512_set_write((nfc_transceiver_t *)pPN512, ac_buffer_builder_buffer(pDataOutBldr));
00623             pn512_transceive_hw(pPN512, pn512_transceive_mode_transceive, pn512_initiator_isob_anticollision_haltb_resp);
00624             return;
00625         } else {
00626             pn512_initiator_isob_anticollision_complete(pPN512);
00627             return;
00628         }
00629     }
00630 
00631     // Move on to the next slot
00632     pn512_initiator_isob_anticollision_next_slot(pPN512);
00633 }
00634 
00635 void pn512_initiator_isob_anticollision_next_slot(pn512_t *pPN512)
00636 {
00637     if (pPN512->anticollision.iso_b.slot_number >= (1 << pPN512->anticollision.iso_b.slots_num_exponent)) {
00638         if (!pPN512->anticollision.iso_b.more_targets) {
00639             // No further collisions to resolve
00640             pn512_initiator_isob_anticollision_complete(pPN512);
00641             return;
00642         }
00643         if (pPN512->anticollision.iso_b.slots_num_exponent >= 4) {
00644             // Cannot handle more than 16 slots
00645             pn512_initiator_isob_anticollision_complete(pPN512);
00646             return;
00647         }
00648         pPN512->anticollision.iso_b.slots_num_exponent++;
00649         pPN512->anticollision.iso_b.slot_number = 0;
00650     }
00651     pn512_initiator_isob_anticollision_reqb(pPN512);
00652 }
00653 
00654 void pn512_initiator_isob_anticollision_haltb_resp(pn512_t *pPN512, nfc_err_t ret)
00655 {
00656     // Check for response
00657     if (ret) {
00658         NFC_WARN("Did not receive HALTB response: error %u", ret);
00659         pn512_anticollision_callback(pPN512, NFC_ERR_PROTOCOL);
00660         return;
00661     }
00662 
00663     ac_buffer_t *pResp = pn512_get_read((nfc_transceiver_t *)pPN512);
00664 
00665     if (ac_buffer_reader_readable(pResp) != 1) {
00666         NFC_WARN("Wrong length (%u bytes)", ac_buffer_reader_readable(pResp));
00667         pn512_anticollision_callback(pPN512, NFC_ERR_PROTOCOL);
00668         return;
00669     }
00670 
00671     NFC_DBG("Got HALTB response:");
00672     NFC_DBG_BLOCK(ac_buffer_dump(pResp);)
00673 
00674     // Check byte
00675     uint8_t haltbr = ac_buffer_read_nu8(pResp);
00676     if (haltbr != 0x00) {
00677         NFC_WARN("Wrong byte for HALTB response: %02X", haltbr);
00678         pn512_anticollision_callback(pPN512, NFC_ERR_PROTOCOL);
00679         return;
00680     }
00681 
00682     // PICC halted, move to next slot
00683     pn512_initiator_isob_anticollision_next_slot(pPN512);
00684 }
00685 
00686 void pn512_initiator_isob_anticollision_complete(pn512_t *pPN512)
00687 {
00688     if (pPN512->anticollision.iso_b.found_one) {
00689         pn512_anticollision_callback(pPN512, NFC_OK);
00690     } else {
00691         pn512_anticollision_callback(pPN512, NFC_ERR_NOPEER);
00692     }
00693 }
00694 
00695 // Felica
00696 static void pn512_initiator_felica_anticollision(pn512_t *pPN512, pn512_cb_t cb);
00697 static void pn512_initiator_felica_anticollision_reqc(pn512_t *pPN512);
00698 static void pn512_initiator_felica_anticollision_atqc(pn512_t *pPN512, nfc_err_t ret);
00699 static void pn512_initiator_felica_anticollision_complete(pn512_t *pPN512);
00700 
00701 #define REQC 0x00
00702 
00703 void pn512_initiator_felica_anticollision(pn512_t *pPN512, pn512_cb_t cb)
00704 {
00705     pPN512->anticollision.cb = cb;
00706 
00707     // Reset transceive mode
00708     pPN512->transceive.mode = pn512_transceive_mode_idle;
00709 
00710     pn512_initiator_felica_anticollision_reqc(pPN512);
00711 }
00712 
00713 void pn512_initiator_felica_anticollision_reqc(pn512_t *pPN512)
00714 {
00715     ac_buffer_builder_t *pDataOutBldr = &pPN512->readBufBldr;
00716     ac_buffer_builder_reset(pDataOutBldr);
00717 
00718     ac_buffer_builder_write_nu8(pDataOutBldr, 6); //Length
00719     ac_buffer_builder_write_nu8(pDataOutBldr, REQC);
00720     ac_buffer_builder_write_nu16(pDataOutBldr, 0xFFFF); //Any system code
00721     ac_buffer_builder_write_nu8(pDataOutBldr, 0x00); // Padding
00722     ac_buffer_builder_write_nu8(pDataOutBldr, 0x07); // 8 time slots, more would overflow the rx buffer if many cards responded
00723 
00724     pn512_set_crc((nfc_transceiver_t *)pPN512, true, true);
00725     pn512_set_timeout((nfc_transceiver_t *)pPN512, 13); //8 timeslots at 212kbps
00726     pn512_set_write((nfc_transceiver_t *)pPN512, ac_buffer_builder_buffer(pDataOutBldr));
00727 
00728     pn512_framing_rx_multiple_enable(pPN512); // Set RxMultiple bit
00729 
00730     pn512_transceive_hw(pPN512, pn512_transceive_mode_transceive, pn512_initiator_felica_anticollision_atqc);
00731 }
00732 
00733 void pn512_initiator_felica_anticollision_atqc(pn512_t *pPN512, nfc_err_t ret)
00734 {
00735     ac_buffer_t *pResp = pn512_get_read((nfc_transceiver_t *)pPN512);
00736 
00737     if (ret || (ac_buffer_reader_readable(pResp) == 0)) {
00738         NFC_WARN("Did not receive ATQC: error %d", ret);
00739         pn512_anticollision_callback(pPN512, NFC_ERR_NOPEER);
00740         return;
00741     }
00742 
00743     // We might have multiple responses
00744     NFC_DBG("Got ATQC:");
00745     NFC_DBG_BLOCK(ac_buffer_dump(pResp);)
00746 
00747     while (ac_buffer_reader_readable(pResp) > 0) {
00748         if (ac_buffer_reader_readable(pResp) != 18 + 1) { // ATQC is 18 bytes, 1 byte for errors added by PN512
00749             NFC_WARN("Wrong length (%d bytes)", ac_buffer_reader_readable(pResp));
00750             pn512_anticollision_callback(pPN512, NFC_ERR_PROTOCOL);
00751             return;
00752         }
00753 
00754         // First byte is length, check that it's correct
00755         uint8_t frame_length = ac_buffer_read_nu8(pResp);
00756         uint8_t atqc0 = ac_buffer_read_nu8(pResp);
00757         if ((frame_length != 18) || (atqc0 != 0x01)) {
00758             NFC_WARN("Wrong ATQC frame");
00759             pn512_anticollision_callback(pPN512, NFC_ERR_PROTOCOL);
00760             return;
00761         }
00762 
00763         // Read NFCID2
00764         ac_buffer_read_n_bytes(pResp, pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].nfcF.nfcid2, 8);
00765 
00766         // Discard padding bytes
00767         ac_buffer_read_n_skip(pResp, 8);
00768 
00769         // Read error register
00770         uint8_t err_reg = ac_buffer_read_nu8(pResp);
00771         if (err_reg & 0x1f) {
00772             // Error within this time slot, skip
00773             continue;
00774         }
00775 
00776         //Populate tech accordingly
00777         memset(&pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].type, 0, sizeof(nfc_tech_t));
00778         if (
00779             (pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].nfcF.nfcid2[0] == 0x01)
00780             && (pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].nfcF.nfcid2[1] == 0xFE)
00781         ) {
00782             // NFC-DEP supported
00783             pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].type.nfc_nfc_dep_f_212 = 1;
00784         } else {
00785             // Type 3 supported
00786             pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].type.nfc_type3 = 1;
00787         }
00788         pPN512->transceiver.active_tech = pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].type;
00789         pPN512->transceiver.remote_targets_count++;
00790 
00791         // Only continue if we can have more targets
00792         if (!pPN512->config.options.bail_at_first_target
00793                 && (pPN512->transceiver.remote_targets_count < MUNFC_MAX_REMOTE_TARGETS)) {
00794             continue;
00795         }
00796         break;
00797     }
00798 
00799     pn512_initiator_felica_anticollision_complete(pPN512);
00800 }
00801 
00802 void pn512_initiator_felica_anticollision_complete(pn512_t *pPN512)
00803 {
00804     pn512_anticollision_callback(pPN512, NFC_OK);
00805 }
00806 
00807 void pn512_poll_setup(pn512_t *pPN512)
00808 {
00809     bool target = pPN512->config.targets.nfc_type2
00810                   || pPN512->config.targets.nfc_type3
00811                   || pPN512->config.targets.nfc_iso_dep_a
00812                   || pPN512->config.targets.nfc_nfc_dep_a
00813                   || pPN512->config.targets.nfc_nfc_dep_f_212
00814                   || pPN512->config.targets.nfc_nfc_dep_f_424;
00815 
00816 // No need for initiator-specific configuration at this stage, but keep this just in case
00817 //  bool initiator = pPN512->config.initiators.nfc_type1
00818 //      || pPN512->config.initiators.nfc_type2
00819 //      || pPN512->config.initiators.nfc_type3
00820 //      || pPN512->config.initiators.nfc_iso_dep_a
00821 //      || pPN512->config.initiators.nfc_nfc_dep_a
00822 //      || pPN512->config.initiators.nfc_nfc_dep_f_212
00823 //      || pPN512->config.initiators.nfc_nfc_dep_f_424;
00824 
00825     if (target) {
00826         NFC_DBG("Configure anticoll/polling response");
00827         //Setup ATQA, SAK and Felica polling response
00828         pn512_fifo_clear(pPN512);
00829 
00830         ac_buffer_builder_t *pDataCfgBldr = &pPN512->readBufBldr;
00831         ac_buffer_builder_reset(pDataCfgBldr);
00832 
00833         //Write ATQA
00834         ac_buffer_builder_write_nu8(pDataCfgBldr, 0x04);
00835         ac_buffer_builder_write_nu8(pDataCfgBldr, 0x00);
00836 
00837         //Write NFCID1 (0s as it will be randomly generated) - first byte will be set to 0x08 by HW according to NFC-IP1
00838         for (int i = 0; i < 3; i++) {
00839             ac_buffer_builder_write_nu8(pDataCfgBldr, 0x00);
00840         }
00841 
00842         //Write SAK
00843         uint8_t sak = 0x00; //Default SAK (UID complete)
00844         if (pPN512->config.targets.nfc_iso_dep_a) {
00845             sak |= 0x20; //This target is ISO-14443A-4 compliant
00846         }
00847         if (pPN512->config.targets.nfc_nfc_dep_a) {
00848             sak |= 0x40; //This target is NFC-IP1 compliant
00849         }
00850         ac_buffer_builder_write_nu8(pDataCfgBldr, sak);
00851 
00852         //Write NFCID2 (xx 0xfe according to NFC-IP1 and 0s as 6 bytes will be randomly generated)
00853         if (pPN512->config.targets.nfc_nfc_dep_f_212 || pPN512->config.targets.nfc_nfc_dep_f_424) {
00854             //Byte 1 is 0x01 if supporting NFC-IP1
00855             ac_buffer_builder_write_nu8(pDataCfgBldr, 0x01);
00856         } else if (pPN512->config.targets.nfc_type3) { //NFC-IP will have priority over type 3 tag emulation
00857             //Byte 1 is 0x02 if supporting Type 3 tag platform
00858             ac_buffer_builder_write_nu8(pDataCfgBldr, 0x02);
00859         } else {
00860             ac_buffer_builder_write_nu8(pDataCfgBldr, 0x00);
00861         }
00862         ac_buffer_builder_write_nu8(pDataCfgBldr, 0xFE);
00863 
00864         for (int i = 0; i < 6; i++) {
00865             ac_buffer_builder_write_nu8(pDataCfgBldr, 0x00);
00866         }
00867 
00868         //2 PAD0 bytes (Felica spec) - this would code the manufacturer + IC code (0xFFFF for NFC-IP1 tags)
00869         ac_buffer_builder_write_nu8(pDataCfgBldr, 0xFF);
00870         ac_buffer_builder_write_nu8(pDataCfgBldr, 0xFF);
00871 
00872         //3 PAD1 bytes
00873         ac_buffer_builder_write_nu8(pDataCfgBldr, 0x00);
00874         ac_buffer_builder_write_nu8(pDataCfgBldr, 0x00);
00875         ac_buffer_builder_write_nu8(pDataCfgBldr, 0x00);
00876 
00877         if (!(pPN512->config.targets.nfc_nfc_dep_f_212 || pPN512->config.targets.nfc_nfc_dep_f_424)
00878                 && pPN512->config.targets.nfc_type3) {
00879             ac_buffer_builder_write_nu8(pDataCfgBldr, 0x01); //MRTI Check
00880             ac_buffer_builder_write_nu8(pDataCfgBldr, 0x01); //MRTI Update
00881         } else {
00882             ac_buffer_builder_write_nu8(pDataCfgBldr, 0x00);
00883             ac_buffer_builder_write_nu8(pDataCfgBldr, 0x00);
00884         }
00885 
00886         //1 PAD2 byte
00887         ac_buffer_builder_write_nu8(pDataCfgBldr, 0x00);
00888 
00889         //2 system code bytes
00890         if (!(pPN512->config.targets.nfc_nfc_dep_f_212 || pPN512->config.targets.nfc_nfc_dep_f_424)
00891                 && pPN512->config.targets.nfc_type3) {
00892             ac_buffer_builder_write_nu8(pDataCfgBldr, 0x12);
00893             ac_buffer_builder_write_nu8(pDataCfgBldr, 0xFC);
00894         } else {
00895             ac_buffer_builder_write_nu8(pDataCfgBldr, 0xFF); //Wildcard system code
00896             ac_buffer_builder_write_nu8(pDataCfgBldr, 0xFF);
00897         }
00898 
00899         //Write NFCID3
00900         ac_buffer_builder_write_nu8(pDataCfgBldr, 0x00);
00901 
00902         pn512_fifo_write(pPN512, ac_buffer_builder_buffer(pDataCfgBldr));
00903 
00904         pn512_cmd_exec(pPN512, PN512_CMD_CONFIG);
00905         pn512_cmd_wait_idle(pPN512, -1);
00906 
00907         NFC_DBG("Overwrite NFCIDs with random numbers");
00908 
00909         //Overwrite NFCIDs with random numbers
00910         pn512_cmd_exec(pPN512, PN512_CMD_RNDIDG);
00911         pn512_cmd_wait_idle(pPN512, -1);
00912     }
00913 }
00914 
00915 static void pn512_poll_iteration(pn512_t *pPN512, nfc_err_t ret);
00916 static void pn512_poll_delay_complete(uint32_t events, void *pUserData)
00917 {
00918     pn512_t *pPN512 = (pn512_t *) pUserData;
00919 
00920     if (events & EVENT_ABORTED) {
00921         pn512_poll_callback(pPN512, NFC_ERR_ABORTED);
00922         return;
00923     }
00924 
00925     pn512_poll_iteration(pPN512, NFC_OK);
00926 }
00927 
00928 static void pn512_poll_delay(pn512_t *pPN512, uint32_t timeout)
00929 {
00930     task_init(&pPN512->transceiver.task, EVENT_TIMEOUT, timeout, pn512_poll_delay_complete, pPN512);
00931     nfc_scheduler_queue_task(&pPN512->transceiver.scheduler, &pPN512->transceiver.task);
00932 }
00933 
00934 void pn512_poll_iteration(pn512_t *pPN512, nfc_err_t ret)
00935 {
00936     do {
00937         if (pPN512->poll.state == pn512_polling_state_start_listening) {
00938             NFC_DBG("pn512_polling_state_start_listening");
00939             // Start with listening
00940             if (!pn512_config_target(pPN512)) {
00941                 // Otherwise switch to next step
00942                 pPN512->poll.state = pn512_polling_state_start_polling;
00943                 continue;
00944             }
00945 
00946             pPN512->poll.state = pn512_polling_state_listen_wait_for_remote_field;
00947 
00948             // Shortcut if target is halted (means RF field is still here)
00949             if (pn512_register_read(pPN512, PN512_REG_MIFNFC) & 0x04) {
00950                 continue;
00951             }
00952 
00953             // Fix for PN512 bug that sometimes detects its own RF field
00954             //  if(pPN512->rf_on)
00955             {
00956                 //Switch RF field off
00957                 pn512_rf_field_switch_off(pPN512);
00958                 NFC_DBG("RF field switched off");
00959             }
00960 
00961             NFC_DBG("Target anticollision");
00962 
00963             bool iso14443a = pPN512->config.targets.nfc_type2 || pPN512->config.targets.nfc_iso_dep_a || pPN512->config.targets.nfc_nfc_dep_a;
00964             bool felica = pPN512->config.targets.nfc_type3 || pPN512->config.targets.nfc_nfc_dep_f_212 || pPN512->config.targets.nfc_nfc_dep_f_424;
00965 
00966             NFC_DBG("Switch in target mode and set framing: ISO A: %s; Felica: %s", iso14443a ? "Yes" : "No", felica ? "Yes" : "No");
00967 
00968             //Switch in target mode
00969             if (iso14443a && felica) {
00970                 pn512_framing_set(pPN512, nfc_framing_target_mode_detector);
00971             } else if (iso14443a) {
00972                 pn512_framing_set(pPN512, nfc_framing_target_a_106);
00973             } else if (felica) {
00974                 pn512_framing_set(pPN512, nfc_framing_target_f_212);
00975             }
00976 
00977             pn512_rf_field_wait_for_external(pPN512, pPN512->config.options.listen_for, pn512_poll_iteration);
00978             return;
00979         }
00980 
00981         if (pPN512->poll.state == pn512_polling_state_listen_wait_for_remote_field) {
00982             NFC_DBG("pn512_polling_state_listen_wait_for_remote_field");
00983 
00984             if (!pn512_config_target(pPN512)) {
00985                 // Otherwise switch to next step
00986                 pPN512->poll.state = pn512_polling_state_start_listening;
00987                 continue;
00988             }
00989 
00990             if (ret == NFC_ERR_TIMEOUT) {
00991                 // Continue polling
00992                 pPN512->poll.state = pn512_polling_state_start_polling;
00993                 continue;
00994             }
00995 
00996             if (ret) {
00997                 pn512_poll_callback(pPN512, ret);
00998                 return;
00999             }
01000 
01001             pPN512->poll.state = pn512_polling_state_listen_anticollision;
01002 
01003             pn512_target_anticollision(pPN512, pn512_poll_iteration);
01004             return;
01005         }
01006 
01007         if (pPN512->poll.state == pn512_polling_state_listen_anticollision) {
01008             NFC_DBG("pn512_polling_state_listen_anticollision");
01009 
01010             if (ret == NFC_ERR_FIELD) {
01011                 // This means that a remote field was dropped - give it another chance
01012                 pPN512->poll.state = pn512_polling_state_listen_wait_for_remote_field;
01013                 pn512_rf_field_switch_off(pPN512);
01014                 pn512_rf_field_wait_for_external(pPN512, pPN512->config.options.listen_for, pn512_poll_iteration);
01015                 return;
01016             }
01017 
01018             if (ret) {
01019                 pn512_poll_callback(pPN512, ret);
01020                 return;
01021             }
01022 
01023             // Be safe, not sure what the framing is
01024             pPN512->framing = nfc_framing_unknown;
01025 
01026             pn512_poll_callback(pPN512, NFC_OK);
01027             return;
01028         }
01029 
01030         if (pPN512->poll.state == pn512_polling_state_start_polling) {
01031             NFC_DBG("pn512_polling_state_start_polling");
01032 
01033             if (!pn512_config_initiator(pPN512)) {
01034                 // Otherwise switch to next step
01035                 pPN512->poll.state = pn512_polling_state_start_listening;
01036                 continue;
01037             }
01038 
01039             // Try to activate RF field
01040             pPN512->poll.state = pn512_polling_state_rf_collision_avoidance;
01041 
01042             pn512_rf_field_nfcip1_rf_collision_avoidance(pPN512, pn512_poll_iteration);
01043             return;
01044         }
01045 
01046         if (pPN512->poll.state == pn512_polling_state_rf_collision_avoidance) {
01047             NFC_DBG("pn512_polling_state_rf_collision_avoidance");
01048 
01049             if (ret) {
01050                 pn512_poll_callback(pPN512, ret);
01051                 return;
01052             }
01053 
01054             NFC_DBG("Own RF field is %s", pPN512->rf_on ? "on" : "off");
01055 
01056             if (!pPN512->rf_on) {
01057                 // Go back to listening, target framing is still valid so no need to reset it
01058                 pPN512->poll.state = pn512_polling_state_listen_wait_for_remote_field;
01059                 continue;
01060             }
01061 
01062             pPN512->poll.state = pn512_polling_state_polling_nfc_a_start;
01063         }
01064 
01065         if (pPN512->poll.state == pn512_polling_state_polling_nfc_a_start) {
01066             NFC_DBG("pn512_polling_state_polling_nfc_a_start");
01067 
01068             //Check if ISO A is needed
01069             bool nfc_a = pPN512->config.initiators.nfc_type2 || pPN512->config.initiators.nfc_iso_dep_a || pPN512->config.initiators.nfc_nfc_dep_a; //We do not support type 1 card emulation so irrelevant
01070             if (!nfc_a) {
01071                 // Continue with NFC B
01072                 pPN512->poll.state = pn512_polling_state_polling_nfc_b_start;
01073                 continue;
01074             }
01075 
01076             pPN512->transceiver.initiator_ntarget = true;
01077             pn512_framing_set(pPN512, nfc_framing_initiator_a_106);
01078 
01079             pPN512->poll.state = pn512_polling_state_polling_nfc_a_gt;
01080             pn512_poll_delay(pPN512, 10 + 5); // Guard time for ISO A is 5 ms
01081             return;
01082         }
01083 
01084         if (pPN512->poll.state == pn512_polling_state_polling_nfc_a_gt) {
01085             NFC_DBG("pn512_polling_state_polling_nfc_a_gt");
01086 
01087             // Start anticollision
01088             pPN512->poll.state = pn512_polling_state_polling_nfc_a_anticollision;
01089             pn512_initiator_isoa_anticollision(pPN512, pn512_poll_iteration);
01090             return;
01091         }
01092 
01093         if (pPN512->poll.state == pn512_polling_state_polling_nfc_a_anticollision) {
01094             NFC_DBG("pn512_polling_state_polling_nfc_a_anticollision");
01095 
01096             if (ret == NFC_ERR_NOPEER) {
01097                 NFC_DBG("Not found");
01098                 // Continue with NFC B
01099                 pPN512->poll.state = pn512_polling_state_polling_nfc_b_start;
01100                 continue;
01101             }
01102 
01103             if ((ret == NFC_OK) && (pPN512->config.options.bail_at_first_tech || (pPN512->transceiver.remote_targets_count == MUNFC_MAX_REMOTE_TARGETS))) {
01104                 // At least one target found, exit polling loop
01105                 pn512_poll_callback(pPN512, NFC_OK);
01106                 return;
01107             }
01108 
01109             if (ret == NFC_ERR_ABORTED) {
01110                 pn512_poll_callback(pPN512, ret);
01111                 return;
01112             }
01113 
01114             // Continue with NFC B
01115             pPN512->poll.state = pn512_polling_state_polling_nfc_b_start;
01116             continue;
01117         }
01118 
01119         if (pPN512->poll.state == pn512_polling_state_polling_nfc_b_start) {
01120             NFC_DBG("pn512_polling_state_polling_nfc_b_start");
01121 
01122             //Check if ISO B is needed
01123             bool nfc_b = pPN512->config.initiators.nfc_iso_dep_b;
01124             if (!nfc_b) {
01125                 // Continue with NFC F
01126                 pPN512->poll.state = pn512_polling_state_polling_nfc_f_start;
01127                 continue;
01128             }
01129 
01130             pPN512->transceiver.initiator_ntarget = true;
01131             pn512_framing_set(pPN512, nfc_framing_initiator_b_106);
01132 
01133             pPN512->poll.state = pn512_polling_state_polling_nfc_b_gt;
01134             pn512_poll_delay(pPN512, 10 + 5); // Guard time for ISO B is 5 ms
01135             return;
01136         }
01137 
01138         if (pPN512->poll.state == pn512_polling_state_polling_nfc_b_gt) {
01139             NFC_DBG("pn512_polling_state_polling_nfc_b_gt");
01140 
01141             // Start anticollision
01142             pPN512->poll.state = pn512_polling_state_polling_nfc_b_anticollision;
01143             pn512_initiator_isob_anticollision(pPN512, pn512_poll_iteration);
01144             return;
01145         }
01146 
01147         if (pPN512->poll.state == pn512_polling_state_polling_nfc_b_anticollision) {
01148             NFC_DBG("pn512_polling_state_polling_nfc_b_anticollision");
01149 
01150             if (ret == NFC_ERR_NOPEER) {
01151                 NFC_DBG("Not found");
01152                 // Continue with NFC F
01153                 pPN512->poll.state = pn512_polling_state_polling_nfc_f_start;
01154                 continue;
01155             }
01156 
01157             if ((ret == NFC_OK)
01158                     && (pPN512->config.options.bail_at_first_tech
01159                         || (pPN512->transceiver.remote_targets_count
01160                             == MUNFC_MAX_REMOTE_TARGETS))) {
01161                 // At least one target found, exit polling loop
01162                 pn512_poll_callback(pPN512, NFC_OK);
01163                 return;
01164             }
01165 
01166             if (ret == NFC_ERR_ABORTED) {
01167                 pn512_poll_callback(pPN512, ret);
01168                 return;
01169             }
01170 
01171             // Continue with NFC F
01172             pPN512->poll.state = pn512_polling_state_polling_nfc_f_start;
01173             continue;
01174         }
01175 
01176         if (pPN512->poll.state == pn512_polling_state_polling_nfc_f_start) {
01177             NFC_DBG("pn512_polling_state_polling_nfc_f_start");
01178 
01179             //Check if Felica is needed
01180             bool nfc_f = pPN512->config.initiators.nfc_type3 || pPN512->config.initiators.nfc_nfc_dep_f_212;
01181             if (!nfc_f) {
01182                 // Wrap up
01183                 pPN512->poll.state = pn512_polling_state_finish_polling;
01184                 continue;
01185             }
01186 
01187             pPN512->transceiver.initiator_ntarget = true;
01188             pn512_framing_set(pPN512, nfc_framing_initiator_f_212);
01189 
01190             pPN512->poll.state = pn512_polling_state_polling_nfc_f_gt;
01191             pn512_poll_delay(pPN512, 20); // Guard time for Felica is 20 ms
01192             return;
01193         }
01194 
01195         if (pPN512->poll.state == pn512_polling_state_polling_nfc_f_gt) {
01196             NFC_DBG("pn512_polling_state_polling_nfc_f_gt");
01197 
01198             // Start anticollision
01199             pPN512->poll.state = pn512_polling_state_polling_nfc_f_anticollision;
01200             pn512_initiator_felica_anticollision(pPN512, pn512_poll_iteration);
01201             return;
01202         }
01203 
01204         if (pPN512->poll.state == pn512_polling_state_polling_nfc_f_anticollision) {
01205             NFC_DBG("pn512_polling_state_polling_nfc_f_anticollision");
01206 
01207             if (ret == NFC_ERR_NOPEER) {
01208                 NFC_DBG("Not found");
01209                 // Resolve polling
01210                 pPN512->poll.state = pn512_polling_state_finish_polling;
01211                 continue;
01212             }
01213 
01214             if ((ret == NFC_OK) && (pPN512->config.options.bail_at_first_tech || (pPN512->transceiver.remote_targets_count == MUNFC_MAX_REMOTE_TARGETS))) {
01215                 // At least one target found, exit polling loop
01216                 pn512_poll_callback(pPN512, NFC_OK);
01217                 return;
01218             }
01219 
01220             if (ret == NFC_ERR_ABORTED) {
01221                 pn512_poll_callback(pPN512, ret);
01222                 return;
01223             }
01224 
01225             // Resolve polling
01226             pPN512->poll.state = pn512_polling_state_finish_polling;
01227             continue;
01228         }
01229 
01230         if (pPN512->poll.state == pn512_polling_state_finish_polling) {
01231             if (pPN512->transceiver.remote_targets_count > 0) {
01232                 pn512_poll_callback(pPN512, NFC_OK);
01233             } else {
01234                 pn512_poll_callback(pPN512, NFC_ERR_NOPEER);
01235             }
01236             return;
01237         }
01238 
01239     } while (true);
01240 }
01241 
01242 // Main polling loop function
01243 void pn512_poll_hw(pn512_t *pPN512, pn512_cb_t cb)
01244 {
01245     nfc_transceiver_t *pTransceiver = (nfc_transceiver_t *)pPN512;
01246     pPN512->poll.cb = cb;
01247 
01248     //Reset active state
01249     pTransceiver->initiator_ntarget = false;
01250     memset(&pTransceiver->active_tech, 0, sizeof(nfc_tech_t));
01251 
01252     //Reset discovered targets
01253     pTransceiver->remote_targets_count = 0;
01254 
01255     //Initialize state machine
01256     pPN512->poll.state = pn512_polling_state_start_listening;
01257 
01258     if (!pn512_config_target(pPN512) && !pn512_config_initiator(pPN512)) {
01259         pn512_poll_callback(pPN512, NFC_ERR_PARAMS);
01260         return;
01261     }
01262 
01263     //First iteration
01264     pn512_poll_iteration(pPN512, NFC_OK);
01265 }