Kenji Arai / TYBLE16_mbedlized_os5_several_examples_1st

Dependencies:   nRF51_Vdd TextLCD BME280

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers NFCController.cpp Source File

NFCController.cpp

00001 /* mbed Microcontroller Library
00002  * Copyright (c) 2018 ARM Limited
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00017 #include "NFCController.h"
00018 #include "NFCControllerDriver.h"
00019 #include "Type4RemoteInitiator.h"
00020 
00021 #include "stack/transceiver/transceiver.h"
00022 
00023 using namespace mbed;
00024 using namespace mbed::nfc;
00025 
00026 NFCController::NFCController(NFCControllerDriver *driver, events::EventQueue *queue, const Span<uint8_t>  &ndef_buffer) :
00027     _driver(driver), _queue(queue), _transceiver(NULL), _scheduler(NULL), _delegate(NULL), _discovery_running(false), _ndef_buffer(ndef_buffer)
00028 {
00029     _driver->set_delegate(this);
00030 }
00031 
00032 nfc_err_t NFCController::initialize()
00033 {
00034     MBED_ASSERT(_transceiver == NULL); // Initialize should only be called once
00035     _transceiver = _driver->initialize((nfc_scheduler_timer_t *)&_timer); // See implementation below
00036 
00037     if (_transceiver == NULL) {
00038         // Initialization error
00039         return NFC_ERR_CONTROLLER; // Controller error
00040     }
00041 
00042     // Recover scheduler
00043     _scheduler = transceiver_get_scheduler(_transceiver);
00044 
00045     // Run scheduler for the first time
00046     _queue->call(this, &NFCController::scheduler_process, false);
00047 
00048     return NFC_OK;
00049 }
00050 
00051 void NFCController::set_delegate(Delegate *delegate)
00052 {
00053     _delegate = delegate;
00054 }
00055 
00056 nfc_rf_protocols_bitmask_t NFCController::get_supported_rf_protocols() const
00057 {
00058     // nfc_rf_protocols_bitmask_t is mapped on NFC Forum types, nfc_tech_t is mapped on the underlying RF techs
00059     // We therefore need to convert these
00060 
00061     nfc_rf_protocols_bitmask_t rf_protocols = {0};
00062     nfc_tech_t initiator_tech;
00063     nfc_tech_t target_tech;
00064     _driver->get_supported_nfc_techs(&initiator_tech, &target_tech);
00065 
00066     // Note: we only support ISO-DEP tag emulation in this release,
00067     // so mask out all other protocols
00068 
00069     // rf_protocols.initiator_t1t = initiator_tech.nfc_type1;
00070     // rf_protocols.initiator_t2t = initiator_tech.nfc_type2;
00071     // rf_protocols.initiator_t3t = initiator_tech.nfc_type3;
00072     // rf_protocols.initiator_iso_dep = initiator_tech.nfc_iso_dep_a || initiator_tech.nfc_iso_dep_b;
00073     // rf_protocols.initiator_nfc_dep = initiator_tech.nfc_nfc_dep_a || initiator_tech.nfc_nfc_dep_f_212 || initiator_tech.nfc_nfc_dep_f_424;
00074 
00075     // rf_protocols.target_t1t = target_tech.nfc_type1;
00076     // rf_protocols.target_t2t = target_tech.nfc_type2;
00077     // rf_protocols.target_t3t = target_tech.nfc_type3;
00078     rf_protocols.target_iso_dep = target_tech.nfc_iso_dep_a || target_tech.nfc_iso_dep_b;
00079     // rf_protocols.target_nfc_dep = target_tech.nfc_nfc_dep_a || target_tech.nfc_nfc_dep_f_212 || target_tech.nfc_nfc_dep_f_424;
00080 
00081     return rf_protocols;
00082 }
00083 
00084 nfc_err_t NFCController::configure_rf_protocols(nfc_rf_protocols_bitmask_t rf_protocols)
00085 {
00086     if (_discovery_running) {
00087         // Cannot configure RF protocols if discovery is running
00088         return NFC_ERR_BUSY;
00089     }
00090 
00091     // Map to NFC techs
00092     nfc_tech_t initiator_tech = {0};
00093     nfc_tech_t target_tech = {0};
00094 
00095     // Note: we only support ISO-DEP tag emulation in this release,
00096     // so mask out all other protocols
00097 
00098     target_tech.nfc_iso_dep_a = target_tech.nfc_iso_dep_b =  true;
00099 
00100     // Configure polling options (no need to set bailing flags as we're only using target mode)
00101     polling_options_t options = {0};
00102     options.listen_for = -1; // Listen forever
00103 
00104     transceiver_set_protocols(_transceiver, initiator_tech, target_tech, options);
00105 
00106     return NFC_OK;
00107 }
00108 
00109 nfc_err_t NFCController::start_discovery()
00110 {
00111     if (_discovery_running) {
00112         // Cannot start discovery if it's already running
00113         return NFC_ERR_BUSY;
00114     }
00115 
00116     transceiver_poll(_transceiver, &NFCController::s_polling_callback, this /* use this as callback argument */);
00117 
00118     return NFC_OK;
00119 }
00120 
00121 nfc_err_t NFCController::cancel_discovery()
00122 {
00123     if (!_discovery_running) {
00124         return NFC_OK;
00125     }
00126 
00127     transceiver_abort(_transceiver);
00128 
00129     return NFC_OK;
00130 }
00131 
00132 nfc_transceiver_t *NFCController::transceiver() const
00133 {
00134     return _transceiver;
00135 }
00136 
00137 void NFCController::polling_callback(nfc_err_t ret)
00138 {
00139     // Polling has completed
00140     _discovery_running = false;
00141 
00142     NFC_DBG("Polling finished with result %u", ret);
00143 
00144     if (ret == NFC_OK) {
00145         // Check if a remote initiator was detected and if so, instantiate it
00146         if (!transceiver_is_initiator_mode(_transceiver)) {
00147             nfc_tech_t active_tech = transceiver_get_active_techs(_transceiver);
00148             if ((active_tech.nfc_iso_dep_a || active_tech.nfc_iso_dep_b) && (_delegate != NULL)) {
00149                 Type4RemoteInitiator *type4_remote_initiator_ptr = new (std::nothrow) Type4RemoteInitiator(this, _ndef_buffer);
00150                 if (type4_remote_initiator_ptr != NULL) {
00151                     SharedPtr<NFCRemoteInitiator> type4_remote_initiator(type4_remote_initiator_ptr);
00152                     _delegate->on_nfc_initiator_discovered(type4_remote_initiator);
00153                 }
00154             }
00155         }
00156     }
00157 
00158     if (_delegate != NULL) {
00159         Delegate::nfc_discovery_terminated_reason_t reason;
00160 
00161         // Map reason
00162         switch (ret) {
00163             case NFC_OK:
00164                 reason = Delegate::nfc_discovery_terminated_completed;
00165                 break;
00166             case NFC_ERR_ABORTED:
00167                 reason = Delegate::nfc_discovery_terminated_canceled;
00168                 break;
00169             default:
00170                 // Any other error code means there was an error during the discovery process
00171                 reason = Delegate::nfc_discovery_terminated_rf_error;
00172                 break;
00173         }
00174 
00175         _delegate->on_discovery_terminated(reason);
00176     }
00177 }
00178 
00179 void NFCController::scheduler_process(bool hw_interrupt)
00180 {
00181     _timeout.detach(); // Cancel timeout - if it triggers, it's ok as we'll have an "early" iteration which will likely be a no-op
00182 
00183     // Process stack events
00184     uint32_t timeout = nfc_scheduler_iteration(_scheduler, hw_interrupt ? EVENT_HW_INTERRUPT : EVENT_NONE);
00185 
00186     _timeout.attach(callback(this, &NFCController::on_timeout), timeout);
00187 }
00188 
00189 void NFCController::on_hw_interrupt()
00190 {
00191     // Run scheduler - this is called in interrupt context
00192     _timeout.detach(); // Cancel timeout - if it triggers anyways, it's ok
00193     _queue->call(this, &NFCController::scheduler_process, true);
00194 }
00195 
00196 void NFCController::on_timeout()
00197 {
00198     // Run scheduler - this is called in interrupt context
00199     _queue->call(this, &NFCController::scheduler_process, false);
00200 }
00201 
00202 void NFCController::s_polling_callback(nfc_transceiver_t *pTransceiver, nfc_err_t ret, void *pUserData)
00203 {
00204     NFCController *self = (NFCController *) pUserData;
00205     self->polling_callback(ret);
00206 }
00207 
00208 // Implementation nfc_scheduler_timer_t
00209 void nfc_scheduler_timer_init(nfc_scheduler_timer_t *timer)
00210 {
00211     (void)timer; // This is a no-op
00212 }
00213 
00214 void nfc_scheduler_timer_start(nfc_scheduler_timer_t *timer)
00215 {
00216     Timer *mbed_timer = (Timer *)timer;
00217     mbed_timer->start();
00218 }
00219 
00220 uint32_t nfc_scheduler_timer_get(nfc_scheduler_timer_t *timer)
00221 {
00222     Timer *mbed_timer = (Timer *)timer;
00223     return (uint32_t)mbed_timer->read_ms();
00224 }
00225 
00226 void nfc_scheduler_timer_stop(nfc_scheduler_timer_t *timer)
00227 {
00228     Timer *mbed_timer = (Timer *)timer;
00229     mbed_timer->stop();
00230 }
00231 
00232 void nfc_scheduler_timer_reset(nfc_scheduler_timer_t *timer)
00233 {
00234     Timer *mbed_timer = (Timer *)timer;
00235     mbed_timer->reset();
00236 }