Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

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 (
00541             pPN512->anticollision.iso_b.slots_num_exponent == 0
00542             //&& (pPN512->anticollision.iso_b.slot_number == 0)
00543         ) {
00544             wup |= 0x8; // Send Wake-Up command on first iteration
00545         }
00546         ac_buffer_builder_write_nu8(pDataOutBldr, wup | (pPN512->anticollision.iso_b.slots_num_exponent & 0x7)); // Param: number of slots
00547     } else {
00548         // Just send slot marker
00549         ac_buffer_builder_write_nu8(pDataOutBldr, REQB | ((pPN512->anticollision.iso_b.slot_number & 0xf) << 4));
00550     }
00551 
00552     pn512_set_crc((nfc_transceiver_t *)pPN512, true, true);
00553     pn512_set_timeout((nfc_transceiver_t *)pPN512, 18);
00554     pn512_set_write((nfc_transceiver_t *)pPN512, ac_buffer_builder_buffer(pDataOutBldr));
00555     pn512_transceive_hw(pPN512, pn512_transceive_mode_transceive, pn512_initiator_isob_anticollision_atqb);
00556 }
00557 
00558 void pn512_initiator_isob_anticollision_atqb(pn512_t *pPN512, nfc_err_t ret)
00559 {
00560     // Three cases:
00561     // - 1 response --> store response, halt PICC and check next slot number
00562     // - No response --> check next slot number
00563     // - Collision --> check next slot number but we will have to increment number of slots
00564     ac_buffer_t *pResp = pn512_get_read((nfc_transceiver_t *)pPN512);
00565 
00566     if (ret && (ret != NFC_ERR_COLLISION) && (ret != NFC_ERR_WRONG_COMM) && (ret != NFC_ERR_TIMEOUT)) {
00567         NFC_WARN("Did not receive ATQB: error %u", ret);
00568         pn512_anticollision_callback(pPN512, NFC_ERR_PROTOCOL);
00569         return;
00570     }
00571 
00572     // Increment slot number
00573     pPN512->anticollision.iso_b.slot_number++;
00574 
00575     if ((ret == NFC_ERR_COLLISION) || (ret == NFC_ERR_WRONG_COMM)) {
00576         pPN512->anticollision.iso_b.more_targets = true;
00577     } else if (!ret) {
00578         pPN512->anticollision.iso_b.found_one = true;
00579 
00580         // Decode ATQB
00581         if (ac_buffer_reader_readable(pResp) != 12) {
00582             NFC_WARN("Wrong length (%u bytes)", ac_buffer_reader_readable(pResp));
00583             pn512_anticollision_callback(pPN512, NFC_ERR_PROTOCOL);
00584             return;
00585         }
00586 
00587         NFC_DBG("Got ATQB:");
00588         NFC_DBG_BLOCK(ac_buffer_dump(pResp);)
00589 
00590         // Check first byte
00591         uint8_t atqb0 = ac_buffer_read_nu8(pResp);
00592         if (atqb0 != 0x50) {
00593             NFC_WARN("Wrong first byte for ATQB: %02X", atqb0);
00594             pn512_anticollision_callback(pPN512, NFC_ERR_PROTOCOL);
00595             return;
00596         }
00597 
00598         memset(&pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].type, 0, sizeof(nfc_tech_t));
00599         pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].type.nfc_iso_dep_b = true;
00600 
00601         // Save PUPI, application data & protocol info
00602         ac_buffer_read_n_bytes(pResp, pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].nfcB.pupi, 4);
00603         ac_buffer_read_n_bytes(pResp, pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].nfcB.application_data, 4);
00604         ac_buffer_read_n_bytes(pResp, pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].nfcB.protocol_info, 3);
00605 
00606         // Valid target detected
00607         pPN512->transceiver.active_tech = pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].type;
00608         pPN512->transceiver.remote_targets_count++;
00609 
00610         if (!pPN512->config.options.bail_at_first_target
00611                 && (pPN512->anticollision.iso_b.more_targets || (pPN512->anticollision.iso_b.slot_number < (1 << pPN512->anticollision.iso_b.slots_num_exponent)))
00612                 && (pPN512->transceiver.remote_targets_count < MUNFC_MAX_REMOTE_TARGETS)) {
00613             // Halt target and continue with others
00614             ac_buffer_builder_t *pDataOutBldr = &pPN512->readBufBldr;
00615             ac_buffer_builder_reset(pDataOutBldr);
00616 
00617             // Halt PICC and move on to the next slot
00618 
00619             //HALTB
00620             ac_buffer_builder_write_nu8(pDataOutBldr, HALTB);
00621             ac_buffer_builder_write_n_bytes(pDataOutBldr, pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count - 1].nfcB.pupi, 4);
00622 
00623             pn512_set_crc((nfc_transceiver_t *)pPN512, true, true);
00624             pn512_set_timeout((nfc_transceiver_t *)pPN512, 30);
00625             pn512_set_write((nfc_transceiver_t *)pPN512, ac_buffer_builder_buffer(pDataOutBldr));
00626             pn512_transceive_hw(pPN512, pn512_transceive_mode_transceive, pn512_initiator_isob_anticollision_haltb_resp);
00627             return;
00628         } else {
00629             pn512_initiator_isob_anticollision_complete(pPN512);
00630             return;
00631         }
00632     }
00633 
00634     // Move on to the next slot
00635     pn512_initiator_isob_anticollision_next_slot(pPN512);
00636 }
00637 
00638 void pn512_initiator_isob_anticollision_next_slot(pn512_t *pPN512)
00639 {
00640     if (pPN512->anticollision.iso_b.slot_number >= (1 << pPN512->anticollision.iso_b.slots_num_exponent)) {
00641         if (!pPN512->anticollision.iso_b.more_targets) {
00642             // No further collisions to resolve
00643             pn512_initiator_isob_anticollision_complete(pPN512);
00644             return;
00645         }
00646         if (pPN512->anticollision.iso_b.slots_num_exponent >= 4) {
00647             // Cannot handle more than 16 slots
00648             pn512_initiator_isob_anticollision_complete(pPN512);
00649             return;
00650         }
00651         pPN512->anticollision.iso_b.slots_num_exponent++;
00652         pPN512->anticollision.iso_b.slot_number = 0;
00653     }
00654     pn512_initiator_isob_anticollision_reqb(pPN512);
00655 }
00656 
00657 void pn512_initiator_isob_anticollision_haltb_resp(pn512_t *pPN512, nfc_err_t ret)
00658 {
00659     // Check for response
00660     if (ret) {
00661         NFC_WARN("Did not receive HALTB response: error %u", ret);
00662         pn512_anticollision_callback(pPN512, NFC_ERR_PROTOCOL);
00663         return;
00664     }
00665 
00666     ac_buffer_t *pResp = pn512_get_read((nfc_transceiver_t *)pPN512);
00667 
00668     if (ac_buffer_reader_readable(pResp) != 1) {
00669         NFC_WARN("Wrong length (%u bytes)", ac_buffer_reader_readable(pResp));
00670         pn512_anticollision_callback(pPN512, NFC_ERR_PROTOCOL);
00671         return;
00672     }
00673 
00674     NFC_DBG("Got HALTB response:");
00675     NFC_DBG_BLOCK(ac_buffer_dump(pResp);)
00676 
00677     // Check byte
00678     uint8_t haltbr = ac_buffer_read_nu8(pResp);
00679     if (haltbr != 0x00) {
00680         NFC_WARN("Wrong byte for HALTB response: %02X", haltbr);
00681         pn512_anticollision_callback(pPN512, NFC_ERR_PROTOCOL);
00682         return;
00683     }
00684 
00685     // PICC halted, move to next slot
00686     pn512_initiator_isob_anticollision_next_slot(pPN512);
00687 }
00688 
00689 void pn512_initiator_isob_anticollision_complete(pn512_t *pPN512)
00690 {
00691     if (pPN512->anticollision.iso_b.found_one) {
00692         pn512_anticollision_callback(pPN512, NFC_OK);
00693     } else {
00694         pn512_anticollision_callback(pPN512, NFC_ERR_NOPEER);
00695     }
00696 }
00697 
00698 // Felica
00699 static void pn512_initiator_felica_anticollision(pn512_t *pPN512, pn512_cb_t cb);
00700 static void pn512_initiator_felica_anticollision_reqc(pn512_t *pPN512);
00701 static void pn512_initiator_felica_anticollision_atqc(pn512_t *pPN512, nfc_err_t ret);
00702 static void pn512_initiator_felica_anticollision_complete(pn512_t *pPN512);
00703 
00704 #define REQC 0x00
00705 
00706 void pn512_initiator_felica_anticollision(pn512_t *pPN512, pn512_cb_t cb)
00707 {
00708     pPN512->anticollision.cb = cb;
00709 
00710     // Reset transceive mode
00711     pPN512->transceive.mode = pn512_transceive_mode_idle;
00712 
00713     pn512_initiator_felica_anticollision_reqc(pPN512);
00714 }
00715 
00716 void pn512_initiator_felica_anticollision_reqc(pn512_t *pPN512)
00717 {
00718     ac_buffer_builder_t *pDataOutBldr = &pPN512->readBufBldr;
00719     ac_buffer_builder_reset(pDataOutBldr);
00720 
00721     ac_buffer_builder_write_nu8(pDataOutBldr, 6); //Length
00722     ac_buffer_builder_write_nu8(pDataOutBldr, REQC);
00723     ac_buffer_builder_write_nu16(pDataOutBldr, 0xFFFF); //Any system code
00724     ac_buffer_builder_write_nu8(pDataOutBldr, 0x00); // Padding
00725     ac_buffer_builder_write_nu8(pDataOutBldr, 0x07); // 8 time slots, more would overflow the rx buffer if many cards responded
00726 
00727     pn512_set_crc((nfc_transceiver_t *)pPN512, true, true);
00728     pn512_set_timeout((nfc_transceiver_t *)pPN512, 13); //8 timeslots at 212kbps
00729     pn512_set_write((nfc_transceiver_t *)pPN512, ac_buffer_builder_buffer(pDataOutBldr));
00730 
00731     pn512_framing_rx_multiple_enable(pPN512); // Set RxMultiple bit
00732 
00733     pn512_transceive_hw(pPN512, pn512_transceive_mode_transceive, pn512_initiator_felica_anticollision_atqc);
00734 }
00735 
00736 void pn512_initiator_felica_anticollision_atqc(pn512_t *pPN512, nfc_err_t ret)
00737 {
00738     ac_buffer_t *pResp = pn512_get_read((nfc_transceiver_t *)pPN512);
00739 
00740     if (ret || (ac_buffer_reader_readable(pResp) == 0)) {
00741         NFC_WARN("Did not receive ATQC: error %d", ret);
00742         pn512_anticollision_callback(pPN512, NFC_ERR_NOPEER);
00743         return;
00744     }
00745 
00746     // We might have multiple responses
00747     NFC_DBG("Got ATQC:");
00748     NFC_DBG_BLOCK(ac_buffer_dump(pResp);)
00749 
00750     while (ac_buffer_reader_readable(pResp) > 0) {
00751         if (ac_buffer_reader_readable(pResp) != 18 + 1) { // ATQC is 18 bytes, 1 byte for errors added by PN512
00752             NFC_WARN("Wrong length (%d bytes)", ac_buffer_reader_readable(pResp));
00753             pn512_anticollision_callback(pPN512, NFC_ERR_PROTOCOL);
00754             return;
00755         }
00756 
00757         // First byte is length, check that it's correct
00758         uint8_t frame_length = ac_buffer_read_nu8(pResp);
00759         uint8_t atqc0 = ac_buffer_read_nu8(pResp);
00760         if ((frame_length != 18) || (atqc0 != 0x01)) {
00761             NFC_WARN("Wrong ATQC frame");
00762             pn512_anticollision_callback(pPN512, NFC_ERR_PROTOCOL);
00763             return;
00764         }
00765 
00766         // Read NFCID2
00767         ac_buffer_read_n_bytes(pResp, pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].nfcF.nfcid2, 8);
00768 
00769         // Discard padding bytes
00770         ac_buffer_read_n_skip(pResp, 8);
00771 
00772         // Read error register
00773         uint8_t err_reg = ac_buffer_read_nu8(pResp);
00774         if (err_reg & 0x1f) {
00775             // Error within this time slot, skip
00776             continue;
00777         }
00778 
00779         //Populate tech accordingly
00780         memset(&pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].type, 0, sizeof(nfc_tech_t));
00781         if (
00782             (pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].nfcF.nfcid2[0] == 0x01)
00783             && (pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].nfcF.nfcid2[1] == 0xFE)
00784         ) {
00785             // NFC-DEP supported
00786             pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].type.nfc_nfc_dep_f_212 = 1;
00787         } else {
00788             // Type 3 supported
00789             pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].type.nfc_type3 = 1;
00790         }
00791         pPN512->transceiver.active_tech = pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].type;
00792         pPN512->transceiver.remote_targets_count++;
00793 
00794         // Only continue if we can have more targets
00795         if (!pPN512->config.options.bail_at_first_target
00796                 && (pPN512->transceiver.remote_targets_count < MUNFC_MAX_REMOTE_TARGETS)) {
00797             continue;
00798         }
00799         break;
00800     }
00801 
00802     pn512_initiator_felica_anticollision_complete(pPN512);
00803 }
00804 
00805 void pn512_initiator_felica_anticollision_complete(pn512_t *pPN512)
00806 {
00807     pn512_anticollision_callback(pPN512, NFC_OK);
00808 }
00809 
00810 void pn512_poll_setup(pn512_t *pPN512)
00811 {
00812     bool target = pPN512->config.targets.nfc_type2
00813                   || pPN512->config.targets.nfc_type3
00814                   || pPN512->config.targets.nfc_iso_dep_a
00815                   || pPN512->config.targets.nfc_nfc_dep_a
00816                   || pPN512->config.targets.nfc_nfc_dep_f_212
00817                   || pPN512->config.targets.nfc_nfc_dep_f_424;
00818 
00819 // No need for initiator-specific configuration at this stage, but keep this just in case
00820 //  bool initiator = pPN512->config.initiators.nfc_type1
00821 //      || pPN512->config.initiators.nfc_type2
00822 //      || pPN512->config.initiators.nfc_type3
00823 //      || pPN512->config.initiators.nfc_iso_dep_a
00824 //      || pPN512->config.initiators.nfc_nfc_dep_a
00825 //      || pPN512->config.initiators.nfc_nfc_dep_f_212
00826 //      || pPN512->config.initiators.nfc_nfc_dep_f_424;
00827 
00828     if (target) {
00829         NFC_DBG("Configure anticoll/polling response");
00830         //Setup ATQA, SAK and Felica polling response
00831         pn512_fifo_clear(pPN512);
00832 
00833         ac_buffer_builder_t *pDataCfgBldr = &pPN512->readBufBldr;
00834         ac_buffer_builder_reset(pDataCfgBldr);
00835 
00836         //Write ATQA
00837         ac_buffer_builder_write_nu8(pDataCfgBldr, 0x04);
00838         ac_buffer_builder_write_nu8(pDataCfgBldr, 0x00);
00839 
00840         //Write NFCID1 (0s as it will be randomly generated) - first byte will be set to 0x08 by HW according to NFC-IP1
00841         for (int i = 0; i < 3; i++) {
00842             ac_buffer_builder_write_nu8(pDataCfgBldr, 0x00);
00843         }
00844 
00845         //Write SAK
00846         uint8_t sak = 0x00; //Default SAK (UID complete)
00847         if (pPN512->config.targets.nfc_iso_dep_a) {
00848             sak |= 0x20; //This target is ISO-14443A-4 compliant
00849         }
00850         if (pPN512->config.targets.nfc_nfc_dep_a) {
00851             sak |= 0x40; //This target is NFC-IP1 compliant
00852         }
00853         ac_buffer_builder_write_nu8(pDataCfgBldr, sak);
00854 
00855         //Write NFCID2 (xx 0xfe according to NFC-IP1 and 0s as 6 bytes will be randomly generated)
00856         if (pPN512->config.targets.nfc_nfc_dep_f_212 || pPN512->config.targets.nfc_nfc_dep_f_424) {
00857             //Byte 1 is 0x01 if supporting NFC-IP1
00858             ac_buffer_builder_write_nu8(pDataCfgBldr, 0x01);
00859         } else if (pPN512->config.targets.nfc_type3) { //NFC-IP will have priority over type 3 tag emulation
00860             //Byte 1 is 0x02 if supporting Type 3 tag platform
00861             ac_buffer_builder_write_nu8(pDataCfgBldr, 0x02);
00862         } else {
00863             ac_buffer_builder_write_nu8(pDataCfgBldr, 0x00);
00864         }
00865         ac_buffer_builder_write_nu8(pDataCfgBldr, 0xFE);
00866 
00867         for (int i = 0; i < 6; i++) {
00868             ac_buffer_builder_write_nu8(pDataCfgBldr, 0x00);
00869         }
00870 
00871         //2 PAD0 bytes (Felica spec) - this would code the manufacturer + IC code (0xFFFF for NFC-IP1 tags)
00872         ac_buffer_builder_write_nu8(pDataCfgBldr, 0xFF);
00873         ac_buffer_builder_write_nu8(pDataCfgBldr, 0xFF);
00874 
00875         //3 PAD1 bytes
00876         ac_buffer_builder_write_nu8(pDataCfgBldr, 0x00);
00877         ac_buffer_builder_write_nu8(pDataCfgBldr, 0x00);
00878         ac_buffer_builder_write_nu8(pDataCfgBldr, 0x00);
00879 
00880         if (!(pPN512->config.targets.nfc_nfc_dep_f_212 || pPN512->config.targets.nfc_nfc_dep_f_424)
00881                 && pPN512->config.targets.nfc_type3) {
00882             ac_buffer_builder_write_nu8(pDataCfgBldr, 0x01); //MRTI Check
00883             ac_buffer_builder_write_nu8(pDataCfgBldr, 0x01); //MRTI Update
00884         } else {
00885             ac_buffer_builder_write_nu8(pDataCfgBldr, 0x00);
00886             ac_buffer_builder_write_nu8(pDataCfgBldr, 0x00);
00887         }
00888 
00889         //1 PAD2 byte
00890         ac_buffer_builder_write_nu8(pDataCfgBldr, 0x00);
00891 
00892         //2 system code bytes
00893         if (!(pPN512->config.targets.nfc_nfc_dep_f_212 || pPN512->config.targets.nfc_nfc_dep_f_424)
00894                 && pPN512->config.targets.nfc_type3) {
00895             ac_buffer_builder_write_nu8(pDataCfgBldr, 0x12);
00896             ac_buffer_builder_write_nu8(pDataCfgBldr, 0xFC);
00897         } else {
00898             ac_buffer_builder_write_nu8(pDataCfgBldr, 0xFF); //Wildcard system code
00899             ac_buffer_builder_write_nu8(pDataCfgBldr, 0xFF);
00900         }
00901 
00902         //Write NFCID3
00903         ac_buffer_builder_write_nu8(pDataCfgBldr, 0x00);
00904 
00905         pn512_fifo_write(pPN512, ac_buffer_builder_buffer(pDataCfgBldr));
00906 
00907         pn512_cmd_exec(pPN512, PN512_CMD_CONFIG);
00908         pn512_cmd_wait_idle(pPN512, -1);
00909 
00910         NFC_DBG("Overwrite NFCIDs with random numbers");
00911 
00912         //Overwrite NFCIDs with random numbers
00913         pn512_cmd_exec(pPN512, PN512_CMD_RNDIDG);
00914         pn512_cmd_wait_idle(pPN512, -1);
00915     }
00916 }
00917 
00918 static void pn512_poll_iteration(pn512_t *pPN512, nfc_err_t ret);
00919 static void pn512_poll_delay_complete(uint32_t events, void *pUserData)
00920 {
00921     pn512_t *pPN512 = (pn512_t *) pUserData;
00922 
00923     if (events & EVENT_ABORTED) {
00924         pn512_poll_callback(pPN512, NFC_ERR_ABORTED);
00925         return;
00926     }
00927 
00928     pn512_poll_iteration(pPN512, NFC_OK);
00929 }
00930 
00931 static void pn512_poll_delay(pn512_t *pPN512, uint32_t timeout)
00932 {
00933     task_init(&pPN512->transceiver.task, EVENT_TIMEOUT, timeout, pn512_poll_delay_complete, pPN512);
00934     nfc_scheduler_queue_task(&pPN512->transceiver.scheduler, &pPN512->transceiver.task);
00935 }
00936 
00937 void pn512_poll_iteration(pn512_t *pPN512, nfc_err_t ret)
00938 {
00939     do {
00940         if (pPN512->poll.state == pn512_polling_state_start_listening) {
00941             NFC_DBG("pn512_polling_state_start_listening");
00942             // Start with listening
00943             if (!pn512_config_target(pPN512)) {
00944                 // Otherwise switch to next step
00945                 pPN512->poll.state = pn512_polling_state_start_polling;
00946                 continue;
00947             }
00948 
00949             pPN512->poll.state = pn512_polling_state_listen_wait_for_remote_field;
00950 
00951             // Shortcut if target is halted (means RF field is still here)
00952             if (pn512_register_read(pPN512, PN512_REG_MIFNFC) & 0x04) {
00953                 continue;
00954             }
00955 
00956             // Fix for PN512 bug that sometimes detects its own RF field
00957             //  if(pPN512->rf_on)
00958             {
00959                 //Switch RF field off
00960                 pn512_rf_field_switch_off(pPN512);
00961                 NFC_DBG("RF field switched off");
00962             }
00963 
00964             NFC_DBG("Target anticollision");
00965 
00966             bool iso14443a = pPN512->config.targets.nfc_type2 || pPN512->config.targets.nfc_iso_dep_a || pPN512->config.targets.nfc_nfc_dep_a;
00967             bool felica = pPN512->config.targets.nfc_type3 || pPN512->config.targets.nfc_nfc_dep_f_212 || pPN512->config.targets.nfc_nfc_dep_f_424;
00968 
00969             NFC_DBG("Switch in target mode and set framing: ISO A: %s; Felica: %s", iso14443a ? "Yes" : "No", felica ? "Yes" : "No");
00970 
00971             //Switch in target mode
00972             if (iso14443a && felica) {
00973                 pn512_framing_set(pPN512, nfc_framing_target_mode_detector);
00974             } else if (iso14443a) {
00975                 pn512_framing_set(pPN512, nfc_framing_target_a_106);
00976             } else if (felica) {
00977                 pn512_framing_set(pPN512, nfc_framing_target_f_212);
00978             }
00979 
00980             pn512_rf_field_wait_for_external(pPN512, pPN512->config.options.listen_for, pn512_poll_iteration);
00981             return;
00982         }
00983 
00984         if (pPN512->poll.state == pn512_polling_state_listen_wait_for_remote_field) {
00985             NFC_DBG("pn512_polling_state_listen_wait_for_remote_field");
00986 
00987             if (!pn512_config_target(pPN512)) {
00988                 // Otherwise switch to next step
00989                 pPN512->poll.state = pn512_polling_state_start_listening;
00990                 continue;
00991             }
00992 
00993             if (ret == NFC_ERR_TIMEOUT) {
00994                 // Continue polling
00995                 pPN512->poll.state = pn512_polling_state_start_polling;
00996                 continue;
00997             }
00998 
00999             if (ret) {
01000                 pn512_poll_callback(pPN512, ret);
01001                 return;
01002             }
01003 
01004             pPN512->poll.state = pn512_polling_state_listen_anticollision;
01005 
01006             pn512_target_anticollision(pPN512, pn512_poll_iteration);
01007             return;
01008         }
01009 
01010         if (pPN512->poll.state == pn512_polling_state_listen_anticollision) {
01011             NFC_DBG("pn512_polling_state_listen_anticollision");
01012 
01013             if (ret == NFC_ERR_FIELD) {
01014                 // This means that a remote field was dropped - give it another chance
01015                 pPN512->poll.state = pn512_polling_state_listen_wait_for_remote_field;
01016                 pn512_rf_field_switch_off(pPN512);
01017                 pn512_rf_field_wait_for_external(pPN512, pPN512->config.options.listen_for, pn512_poll_iteration);
01018                 return;
01019             }
01020 
01021             if (ret) {
01022                 pn512_poll_callback(pPN512, ret);
01023                 return;
01024             }
01025 
01026             // Be safe, not sure what the framing is
01027             pPN512->framing = nfc_framing_unknown;
01028 
01029             pn512_poll_callback(pPN512, NFC_OK);
01030             return;
01031         }
01032 
01033         if (pPN512->poll.state == pn512_polling_state_start_polling) {
01034             NFC_DBG("pn512_polling_state_start_polling");
01035 
01036             if (!pn512_config_initiator(pPN512)) {
01037                 // Otherwise switch to next step
01038                 pPN512->poll.state = pn512_polling_state_start_listening;
01039                 continue;
01040             }
01041 
01042             // Try to activate RF field
01043             pPN512->poll.state = pn512_polling_state_rf_collision_avoidance;
01044 
01045             pn512_rf_field_nfcip1_rf_collision_avoidance(pPN512, pn512_poll_iteration);
01046             return;
01047         }
01048 
01049         if (pPN512->poll.state == pn512_polling_state_rf_collision_avoidance) {
01050             NFC_DBG("pn512_polling_state_rf_collision_avoidance");
01051 
01052             if (ret) {
01053                 pn512_poll_callback(pPN512, ret);
01054                 return;
01055             }
01056 
01057             NFC_DBG("Own RF field is %s", pPN512->rf_on ? "on" : "off");
01058 
01059             if (!pPN512->rf_on) {
01060                 // Go back to listening, target framing is still valid so no need to reset it
01061                 pPN512->poll.state = pn512_polling_state_listen_wait_for_remote_field;
01062                 continue;
01063             }
01064 
01065             pPN512->poll.state = pn512_polling_state_polling_nfc_a_start;
01066         }
01067 
01068         if (pPN512->poll.state == pn512_polling_state_polling_nfc_a_start) {
01069             NFC_DBG("pn512_polling_state_polling_nfc_a_start");
01070 
01071             //Check if ISO A is needed
01072             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
01073             if (!nfc_a) {
01074                 // Continue with NFC B
01075                 pPN512->poll.state = pn512_polling_state_polling_nfc_b_start;
01076                 continue;
01077             }
01078 
01079             pPN512->transceiver.initiator_ntarget = true;
01080             pn512_framing_set(pPN512, nfc_framing_initiator_a_106);
01081 
01082             pPN512->poll.state = pn512_polling_state_polling_nfc_a_gt;
01083             pn512_poll_delay(pPN512, 10 + 5); // Guard time for ISO A is 5 ms
01084             return;
01085         }
01086 
01087         if (pPN512->poll.state == pn512_polling_state_polling_nfc_a_gt) {
01088             NFC_DBG("pn512_polling_state_polling_nfc_a_gt");
01089 
01090             // Start anticollision
01091             pPN512->poll.state = pn512_polling_state_polling_nfc_a_anticollision;
01092             pn512_initiator_isoa_anticollision(pPN512, pn512_poll_iteration);
01093             return;
01094         }
01095 
01096         if (pPN512->poll.state == pn512_polling_state_polling_nfc_a_anticollision) {
01097             NFC_DBG("pn512_polling_state_polling_nfc_a_anticollision");
01098 
01099             if (ret == NFC_ERR_NOPEER) {
01100                 NFC_DBG("Not found");
01101                 // Continue with NFC B
01102                 pPN512->poll.state = pn512_polling_state_polling_nfc_b_start;
01103                 continue;
01104             }
01105 
01106             if ((ret == NFC_OK) && (pPN512->config.options.bail_at_first_tech || (pPN512->transceiver.remote_targets_count == MUNFC_MAX_REMOTE_TARGETS))) {
01107                 // At least one target found, exit polling loop
01108                 pn512_poll_callback(pPN512, NFC_OK);
01109                 return;
01110             }
01111 
01112             if (ret == NFC_ERR_ABORTED) {
01113                 pn512_poll_callback(pPN512, ret);
01114                 return;
01115             }
01116 
01117             // Continue with NFC B
01118             pPN512->poll.state = pn512_polling_state_polling_nfc_b_start;
01119             continue;
01120         }
01121 
01122         if (pPN512->poll.state == pn512_polling_state_polling_nfc_b_start) {
01123             NFC_DBG("pn512_polling_state_polling_nfc_b_start");
01124 
01125             //Check if ISO B is needed
01126             bool nfc_b = pPN512->config.initiators.nfc_iso_dep_b;
01127             if (!nfc_b) {
01128                 // Continue with NFC F
01129                 pPN512->poll.state = pn512_polling_state_polling_nfc_f_start;
01130                 continue;
01131             }
01132 
01133             pPN512->transceiver.initiator_ntarget = true;
01134             pn512_framing_set(pPN512, nfc_framing_initiator_b_106);
01135 
01136             pPN512->poll.state = pn512_polling_state_polling_nfc_b_gt;
01137             pn512_poll_delay(pPN512, 10 + 5); // Guard time for ISO B is 5 ms
01138             return;
01139         }
01140 
01141         if (pPN512->poll.state == pn512_polling_state_polling_nfc_b_gt) {
01142             NFC_DBG("pn512_polling_state_polling_nfc_b_gt");
01143 
01144             // Start anticollision
01145             pPN512->poll.state = pn512_polling_state_polling_nfc_b_anticollision;
01146             pn512_initiator_isob_anticollision(pPN512, pn512_poll_iteration);
01147             return;
01148         }
01149 
01150         if (pPN512->poll.state == pn512_polling_state_polling_nfc_b_anticollision) {
01151             NFC_DBG("pn512_polling_state_polling_nfc_b_anticollision");
01152 
01153             if (ret == NFC_ERR_NOPEER) {
01154                 NFC_DBG("Not found");
01155                 // Continue with NFC F
01156                 pPN512->poll.state = pn512_polling_state_polling_nfc_f_start;
01157                 continue;
01158             }
01159 
01160             if ((ret == NFC_OK)
01161                     && (pPN512->config.options.bail_at_first_tech
01162                         || (pPN512->transceiver.remote_targets_count
01163                             == MUNFC_MAX_REMOTE_TARGETS))) {
01164                 // At least one target found, exit polling loop
01165                 pn512_poll_callback(pPN512, NFC_OK);
01166                 return;
01167             }
01168 
01169             if (ret == NFC_ERR_ABORTED) {
01170                 pn512_poll_callback(pPN512, ret);
01171                 return;
01172             }
01173 
01174             // Continue with NFC F
01175             pPN512->poll.state = pn512_polling_state_polling_nfc_f_start;
01176             continue;
01177         }
01178 
01179         if (pPN512->poll.state == pn512_polling_state_polling_nfc_f_start) {
01180             NFC_DBG("pn512_polling_state_polling_nfc_f_start");
01181 
01182             //Check if Felica is needed
01183             bool nfc_f = pPN512->config.initiators.nfc_type3 || pPN512->config.initiators.nfc_nfc_dep_f_212;
01184             if (!nfc_f) {
01185                 // Wrap up
01186                 pPN512->poll.state = pn512_polling_state_finish_polling;
01187                 continue;
01188             }
01189 
01190             pPN512->transceiver.initiator_ntarget = true;
01191             pn512_framing_set(pPN512, nfc_framing_initiator_f_212);
01192 
01193             pPN512->poll.state = pn512_polling_state_polling_nfc_f_gt;
01194             pn512_poll_delay(pPN512, 20); // Guard time for Felica is 20 ms
01195             return;
01196         }
01197 
01198         if (pPN512->poll.state == pn512_polling_state_polling_nfc_f_gt) {
01199             NFC_DBG("pn512_polling_state_polling_nfc_f_gt");
01200 
01201             // Start anticollision
01202             pPN512->poll.state = pn512_polling_state_polling_nfc_f_anticollision;
01203             pn512_initiator_felica_anticollision(pPN512, pn512_poll_iteration);
01204             return;
01205         }
01206 
01207         if (pPN512->poll.state == pn512_polling_state_polling_nfc_f_anticollision) {
01208             NFC_DBG("pn512_polling_state_polling_nfc_f_anticollision");
01209 
01210             if (ret == NFC_ERR_NOPEER) {
01211                 NFC_DBG("Not found");
01212                 // Resolve polling
01213                 pPN512->poll.state = pn512_polling_state_finish_polling;
01214                 continue;
01215             }
01216 
01217             if ((ret == NFC_OK) && (pPN512->config.options.bail_at_first_tech || (pPN512->transceiver.remote_targets_count == MUNFC_MAX_REMOTE_TARGETS))) {
01218                 // At least one target found, exit polling loop
01219                 pn512_poll_callback(pPN512, NFC_OK);
01220                 return;
01221             }
01222 
01223             if (ret == NFC_ERR_ABORTED) {
01224                 pn512_poll_callback(pPN512, ret);
01225                 return;
01226             }
01227 
01228             // Resolve polling
01229             pPN512->poll.state = pn512_polling_state_finish_polling;
01230             continue;
01231         }
01232 
01233         if (pPN512->poll.state == pn512_polling_state_finish_polling) {
01234             if (pPN512->transceiver.remote_targets_count > 0) {
01235                 pn512_poll_callback(pPN512, NFC_OK);
01236             } else {
01237                 pn512_poll_callback(pPN512, NFC_ERR_NOPEER);
01238             }
01239             return;
01240         }
01241 
01242     } while (true);
01243 }
01244 
01245 // Main polling loop function
01246 void pn512_poll_hw(pn512_t *pPN512, pn512_cb_t cb)
01247 {
01248     nfc_transceiver_t *pTransceiver = (nfc_transceiver_t *)pPN512;
01249     pPN512->poll.cb = cb;
01250 
01251     //Reset active state
01252     pTransceiver->initiator_ntarget = false;
01253     memset(&pTransceiver->active_tech, 0, sizeof(nfc_tech_t));
01254 
01255     //Reset discovered targets
01256     pTransceiver->remote_targets_count = 0;
01257 
01258     //Initialize state machine
01259     pPN512->poll.state = pn512_polling_state_start_listening;
01260 
01261     if (!pn512_config_target(pPN512) && !pn512_config_initiator(pPN512)) {
01262         pn512_poll_callback(pPN512, NFC_ERR_PARAMS);
01263         return;
01264     }
01265 
01266     //First iteration
01267     pn512_poll_iteration(pPN512, NFC_OK);
01268 }