Writing implementation in NFC EEPROM

pull/7822/head
Donatien Garnier 2018-08-16 18:11:29 +01:00
parent 28fad6b320
commit 5a9cab2408
5 changed files with 298 additions and 10 deletions

View File

@ -86,8 +86,9 @@ namespace nfc {
*
* @param[in] driver a pointer to a NFCControllerDriver instance
* @param[in] queue a pointer to the events queue to use
* @param[in] ndef_buffer_sz NDEF buffer size
*/
NFCController(NFCControllerDriver* driver, events::EventQueue* queue);
NFCController(NFCControllerDriver* driver, events::EventQueue* queue, uint8_t* ndef_buffer, size_t ndef_buffer_sz);
/**
* Initialize the NFC controller
@ -166,6 +167,7 @@ namespace nfc {
Timeout _timeout;
Delegate* _delegate;
bool _discovery_running;
size_t _ndef_buffer_sz;
};
/**

View File

@ -48,10 +48,11 @@ namespace nfc {
* Construct a NFCEEPROM instance.
*
* @param[in] driver a pointer to a NFCEEPROMDriver instance
* @param[in] queue a pointer to the events queue to use
* @param[in] ndef_buffer a bytes array used to store NDEF messages
* @param[in] ndef_buffer_sz the array size in bytes
*/
NFCEEPROM(NFCEEPROMDriver* driver);
virtual ~NFCEEPROM();
NFCEEPROM(NFCEEPROMDriver* driver, events::EventQueue* queue, uint8_t* ndef_buffer, size_t ndef_buffer_sz);
/**
* The NFCEEPROM delegate. Users of the NFCEEPROM class need to implement this delegate's methods to receive events.
@ -59,6 +60,15 @@ namespace nfc {
struct Delegate : NFCTarget::Delegate {
};
/**
* Initialize the NFC EEPROM
*
* This method must be called before any other method call.
*
* @return NFC_OK, or an error.
*/
nfc_err_t initialize();
/**
* Set the delegate that will receive events generated by this EEPROM.
*
@ -67,15 +77,47 @@ namespace nfc {
void set_delegate(Delegate* delegate);
private:
// Implementation of NFCTarget
virtual void write_ndef_message();
virtual void read_ndef_message();
virtual void erase_ndef_message();
// Implementation of NFCEEPROMDriver::Delegate
virtual void on_session_started(bool success);
virtual void on_session_ended(bool success);
virtual void on_bytes_read(size_t count);
virtual void on_bytes_written(size_t count);
virtual void on_size_set(bool success);
virtual void on_size_gotten(bool success, size_t size);
virtual void on_size_written(bool success);
virtual void on_size_read(bool success, size_t size);
virtual void on_bytes_erased(size_t count);
virtual void on_event();
void handle_error(nfc_err_t ret);
void continue_write();
enum class nfc_eeprom_operation_t {
nfc_eeprom_idle,
nfc_eeprom_write_start_session,
nfc_eeprom_write_write_bytes,
nfc_eeprom_write_write_size,
nfc_eeprom_write_end_session,
nfc_eeprom_write_start_session,
nfc_eeprom_read_read_size,
nfc_eeprom_read_read_bytes,
nfc_eeprom_read_end_session
};
NFCEEPROMDriver* _driver;
events::EventQueue* _queue;
bool _initialized;
uint8_t* _ndef_buffer;
size_t _ndef_buffer_sz;
nfc_eeprom_operation_t _current_op;
buffer_t _ndef_buffer_reader;
uint32_t _eeprom_address;
};
/**

View File

@ -40,8 +40,11 @@ namespace nfc {
public:
/**
* Create a NFCTarget.
*
* @param[in] buffer a bytes array used to store NDEF messages
* @param[in] buffer_size the array size in bytes
*/
NFCTarget();
NFCTarget(uint8_t* buffer, size_t buffer_size);
virtual ~NFCTarget();
struct Delegate {

View File

@ -23,8 +23,8 @@
using namespace mbed;
using namespace mbed::nfc;
NFCController::NFCController(NFCControllerDriver* driver, events::EventQueue* queue) :
_driver(driver), _queue(queue), _transceiver(NULL), _scheduler(NULL), _delegate(NULL), _discovery_running(false)
NFCController::NFCController(NFCControllerDriver* driver, events::EventQueue* queue, size_t ndef_buffer_sz) :
_driver(driver), _queue(queue), _transceiver(NULL), _scheduler(NULL), _delegate(NULL), _discovery_running(false), _ndef_buffer_sz(ndef_buffer_sz)
{
_driver->set_delegate(this);
}
@ -135,7 +135,7 @@ void NFCController::polling_callback(nfc_err_t ret)
if( !transceiver_is_initiator_mode(_transceiver) ) {
nfc_tech_t active_tech = transceiver_get_active_techs(_transceiver);
if( active_tech.nfc_iso_dep_a || active_tech.nfc_iso_dep_b ) {
SharedPtr<Type4RemoteInitiator> type4_remote_initiator( new Type4RemoteInitiator(_transceiver) );
SharedPtr<Type4RemoteInitiator> type4_remote_initiator( new Type4RemoteInitiator(_transceiver, _ndef_buffer_sz) );
if( _delegate != NULL ) {
_delegate->on_nfc_initiator_discovered(type4_remote_initiator);
}

View File

@ -0,0 +1,241 @@
/* mbed Microcontroller Library
* Copyright (c) 2018 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "NFCEEPROM.h"
#include "ndef/ndef.h"
using namespace mbed;
using namespace mbed::nfc;
NFCEEPROM(NFCEEPROMDriver* driver, events::EventQueue* queue, uint8_t* ndef_buffer, size_t ndef_buffer_sz) : NFCTarget( ndef_buffer, ndef_buffer_sz )
_driver(driver), _queue(queue), _delegate(NULL), _initialized(false), _current_op(nfc_eeprom_idle), _eeprom_address(0)
{
_driver->set_delegate(this);
}
nfc_err_t NFCEEPROM::initialize() {
MBED_ASSERT(_initialized == false); // Initialize should only be called once
// Initialize driver
_driver->reset();
_initialized = true;
}
void NFCEEPROM::set_delegate(NFCEEPROM::Delegate* delegate) {
_delegate = delegate;
}
void NFCEEPROM::write_ndef_message() {
MBED_ASSERT(_initialized == true);
if(_current_op != nfc_eeprom_idle) {
if(_delegate != NULL) {
_delegate->on_ndef_message_written(NFC_ERR_BUSY);
}
return;
}
// First update NDEF message if required
ndef_msg_encode(ndef_message());
_current_op = nfc_eeprom_write_start_session;
// Retrieve reader
ac_buffer_dup(&_ndef_buffer_reader, ac_buffer_builder_buffer(ndef_msg_buffer_builder(ndef_message()) );
// Check that NDEF message is not too big
if( ac_buffer_reader_readable(&_ndef_buffer_reader) > _driver->get_max_size() ) {
handle_error(NFC_ERR_BUFFER_TOO_SMALL);
return;
}
// Reset EEPROM address
_eeprom_address = 0;
// Go through the steps!
_driver->start_session();
// 1 - Start session
// 2 - Write bytes (can be repeated)
// 3 - Set NDEF message size
// 4 - End session
}
void NFCEEPROM::read_ndef_message() {
MBED_ASSERT(_initialized == true);
if(_current_op != nfc_eeprom_idle) {
if(_delegate != NULL) {
_delegate->on_ndef_message_written(NFC_ERR_BUSY);
}
return;
}
_current_op = nfc_eeprom_read_start_session;
// Reset EEPROM address
_eeprom_address = 0;
// Go through the steps!
_driver->start_session();
// 1 - Start session
// 2 - Get NDEF message size
// 3 - Read bytes (can be repeated)
// 4 - End session
}
void NFCEEPROM::erase_ndef_message() {
// We don't want to take any risks, so erase the whole address space
// And set the message size to 0
}
void NFCEEPROM::on_session_started(bool success) {
switch(_current_op) {
case nfc_eeprom_write_start_session:
if(!success) {
handle_error(NFC_ERR_CONTROLLER); // An EEPROM is not really a controller but close enough
return;
}
_current_op = nfc_eeprom_write_write_bytes;
continue_write();
break;
case nfc_eeprom_read_start_session:
if(!success) {
handle_error(NFC_ERR_CONTROLLER);
return;
}
_current_op = nfc_eeprom_read_read_size;
_driver->read_size();
break;
default:
// Should not happen, state machine is broken or driver is doing something wrong
handle_error(NFC_ERR_UNKNOWN);
return;
}
}
void NFCEEPROM::on_session_ended(bool success) {
switch(_current_op) {
case nfc_eeprom_write_end_session:
if(!success) {
handle_error(NFC_ERR_CONTROLLER);
return;
}
_current_op = nfc_eeprom_idle;
if( _delegate != NULL ) {
_driver->on_ndef_message_written(NFC_OK);
}
break;
case nfc_eeprom_read_end_session:
if(!success) {
handle_error(NFC_ERR_CONTROLLER);
return;
}
_current_op = nfc_eeprom_idle;
if( _delegate != NULL ) {
_driver->on_ndef_message_read(NFC_OK);
}
break;
default:
// Should not happen, state machine is broken or driver is doing something wrong
handle_error(NFC_ERR_UNKNOWN);
return;
}
}
void NFCEEPROM::on_bytes_read(size_t count) {
}
void NFCEEPROM::on_bytes_written(size_t count) {
switch(_current_op) {
case nfc_eeprom_write_write_bytes:
if(count == 0) {
handle_error(NFC_ERR_CONTROLLER);
return;
}
// Discard bytes that were actually read and update address
_eeprom_address += count;
ac_buffer_read_n_skip(&_ndef_buffer_reader, count);
// Continue writing
continue_write();
break;
default:
// Should not happen, state machine is broken or driver is doing something wrong
handle_error(NFC_ERR_UNKNOWN);
return;
}
}
void NFCEEPROM::on_size_written(bool success) {
switch(_current_op) {
case nfc_eeprom_write_write_size:
if(!success) {
handle_error(NFC_ERR_CONTROLLER);
return;
}
// End session
_current_op = nfc_eeprom_write_end_session;
_driver->end_session();
break;
default:
// Should not happen, state machine is broken or driver is doing something wrong
handle_error(NFC_ERR_UNKNOWN);
return;
}
}
void NFCEEPROM::on_size_read(bool success, size_t size) {
}
void NFCEEPROM::on_bytes_erased(size_t count) {
}
void NFCEEPROM::on_event() {
}
void NFCEEPROM::continue_write() {
if( ac_buffer_reader_readable(&_ndef_buffer_reader) > 0 ) {
// Continue writing
_driver->write_bytes(_eeprom_address, ac_buffer_reader_current_buffer_pointer(&_ndef_buffer_reader), ac_buffer_reader_current_buffer_length(&_ndef_buffer_reader));
}
else {
// Now update size
_current_op = nfc_eeprom_write_set_size;
_driver->write_size(_eeprom_address);
}
}
void NFCEEPROM::handle_error(nfc_err_t ret) {
// Save & reset current op
nfc_eeprom_operation_t last_op = _current_op;
_current_op = nfc_eeprom_idle;
if(_delegate != NULL) {
if(last_op <= nfc_eeprom_write_end_session) {
_delegate->on_ndef_message_written(NFC_ERR_BUSY);
}
}
}