Erase & Read implementations in NFCEEPROM

pull/7822/head
Donatien Garnier 2018-08-17 11:06:34 +01:00
parent 5a9cab2408
commit 9fcca783b9
2 changed files with 176 additions and 9 deletions

View File

@ -94,6 +94,8 @@ namespace nfc {
void handle_error(nfc_err_t ret);
void continue_write();
void continue_read();
void continue_erase();
enum class nfc_eeprom_operation_t {
nfc_eeprom_idle,
@ -106,7 +108,12 @@ namespace nfc {
nfc_eeprom_write_start_session,
nfc_eeprom_read_read_size,
nfc_eeprom_read_read_bytes,
nfc_eeprom_read_end_session
nfc_eeprom_read_end_session,
nfc_eeprom_erase_start_session,
nfc_eeprom_erase_erase_bytes,
nfc_eeprom_erase_write_size,
nfc_eeprom_erase_end_session
};
NFCEEPROMDriver* _driver;
@ -117,7 +124,9 @@ namespace nfc {
nfc_eeprom_operation_t _current_op;
buffer_t _ndef_buffer_reader;
size_t _ndef_buffer_read_sz;
uint32_t _eeprom_address;
nfc_err_t _operation_result;
};
/**

View File

@ -21,7 +21,7 @@ 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(driver), _queue(queue), _initialized(false), _current_op(nfc_eeprom_idle), _eeprom_address(0), _operation_result(NFC_ERR_UNKNOWN)
{
_driver->set_delegate(this);
}
@ -99,6 +99,27 @@ void NFCEEPROM::read_ndef_message() {
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
MBED_ASSERT(_initialized == true);
if(_current_op != nfc_eeprom_idle) {
if(_delegate != NULL) {
_delegate->on_ndef_message_erased(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 - Erase bytes (can be repeated)
// 3 - Set NDEF message size to 0
// 4 - End session
}
void NFCEEPROM::on_session_started(bool success) {
@ -121,6 +142,15 @@ void NFCEEPROM::on_session_started(bool success) {
_driver->read_size();
break;
case nfc_eeprom_erase_start_session:
if(!success) {
handle_error(NFC_ERR_CONTROLLER);
return;
}
_current_op = nfc_eeprom_erase_bytes;
continue_erase();
break;
default:
// Should not happen, state machine is broken or driver is doing something wrong
handle_error(NFC_ERR_UNKNOWN);
@ -137,7 +167,7 @@ void NFCEEPROM::on_session_ended(bool success) {
}
_current_op = nfc_eeprom_idle;
if( _delegate != NULL ) {
_driver->on_ndef_message_written(NFC_OK);
_driver->on_ndef_message_written(_operation_result);
}
break;
@ -147,11 +177,26 @@ void NFCEEPROM::on_session_ended(bool success) {
return;
}
_current_op = nfc_eeprom_idle;
// Try to parse the NDEF message
ndef_msg_decode(ndef_message());
if( _delegate != NULL ) {
_driver->on_ndef_message_read(NFC_OK);
_driver->on_ndef_message_read(_operation_result);
}
break;
case nfc_eeprom_erase_end_session:
if(!success) {
handle_error(NFC_ERR_CONTROLLER);
return;
}
_current_op = nfc_eeprom_idle;
if( _delegate != NULL ) {
_driver->on_ndef_message_erased(_operation_result);
}
break;
default:
// Should not happen, state machine is broken or driver is doing something wrong
handle_error(NFC_ERR_UNKNOWN);
@ -160,7 +205,26 @@ void NFCEEPROM::on_session_ended(bool success) {
}
void NFCEEPROM::on_bytes_read(size_t count) {
switch(_current_op) {
case nfc_eeprom_read_read_bytes:
if(count == 0) {
handle_error(NFC_ERR_CONTROLLER);
return;
}
// Discard bytes that were actually read and update address
_eeprom_address += count;
ac_buffer_builder_t* buffer_builder = ndef_msg_buffer_builder(ndef_message());
ac_buffer_builder_write_n_skip(buffer_builder, count);
// Continue reading
continue_read();
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_written(size_t count) {
@ -171,7 +235,7 @@ void NFCEEPROM::on_bytes_written(size_t count) {
return;
}
// Discard bytes that were actually read and update address
// Skip bytes that were actually written and update address
_eeprom_address += count;
ac_buffer_read_n_skip(&_ndef_buffer_reader, count);
@ -195,6 +259,18 @@ void NFCEEPROM::on_size_written(bool success) {
// End session
_current_op = nfc_eeprom_write_end_session;
_operation_result = NFC_OK;
_driver->end_session();
break;
case nfc_eeprom_erase_write_size:
if(!success) {
handle_error(NFC_ERR_CONTROLLER);
return;
}
// End session
_current_op = nfc_eeprom_erase_end_session;
_operation_result = NFC_OK;
_driver->end_session();
break;
default:
@ -205,15 +281,66 @@ void NFCEEPROM::on_size_written(bool success) {
}
void NFCEEPROM::on_size_read(bool success, size_t size) {
switch(_current_op) {
case nfc_eeprom_read_read_size:
if(!success) {
handle_error(NFC_ERR_CONTROLLER);
return;
}
// Reset NDEF message buffer builder
ac_buffer_builder_t* buffer_builder = ndef_msg_buffer_builder(ndef_message());
ac_buffer_builder_reset( buffer_builder );
// Check that we have a big enough buffer to read the message
if( size > ac_buffer_builder_writable(buffer_builder) )
{
// Not enough space, close session
_current_op = nfc_eeprom_read_end_session;
_operation_result = NFC_ERR_BUFFER_TOO_SMALL;
_driver->end_session();
return;
}
// Save size and reset address
_eeprom_address = 0;
_ndef_buffer_read_sz = size;
// Start reading bytes
_current_op = nfc_eeprom_read_read_bytes;
continue_read();
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_erased(size_t count) {
switch(_current_op) {
case nfc_eeprom_erase_erase_bytes:
if(count == 0) {
handle_error(NFC_ERR_CONTROLLER);
return;
}
// Update address
_eeprom_address += count;
// Continue erasing
continue_erase();
break;
default:
// Should not happen, state machine is broken or driver is doing something wrong
handle_error(NFC_ERR_UNKNOWN);
return;
}
}
void NFCEEPROM::on_event() {
// Just schedule a task on event queue
_queue->call(_driver, NFCEEPROMDriver::process_events);
}
void NFCEEPROM::continue_write() {
@ -223,11 +350,36 @@ void NFCEEPROM::continue_write() {
}
else {
// Now update size
_current_op = nfc_eeprom_write_set_size;
_current_op = nfc_eeprom_write_write_size;
_driver->write_size(_eeprom_address);
}
}
void NFCEEPROM::continue_erase() {
if( _eeprom_address < _driver->get_max_size() ) {
// Continue erasing
_driver->erase_bytes(_eeprom_address, _driver->get_max_size() - _eeprom_address);
}
else {
// Now update size
_current_op = nfc_eeprom_erase_write_size;
_driver->write_size(0);
}
}
void NFCEEPROM::continue_read() {
if( _eeprom_address < _ndef_buffer_read_sz ) {
// Continue reading
ac_buffer_builder_t* buffer_builder = ndef_msg_buffer_builder(ndef_message());
_driver->read_bytes(_eeprom_address, ac_buffer_builder_write_position(buffer_builder), _ndef_buffer_read_sz - _eeprom_address);
}
else {
// Done, close session
_operation_result = NFC_OK;
_driver->end_session();
}
}
void NFCEEPROM::handle_error(nfc_err_t ret) {
// Save & reset current op
nfc_eeprom_operation_t last_op = _current_op;
@ -235,7 +387,13 @@ void NFCEEPROM::handle_error(nfc_err_t ret) {
if(_delegate != NULL) {
if(last_op <= nfc_eeprom_write_end_session) {
_delegate->on_ndef_message_written(NFC_ERR_BUSY);
_delegate->on_ndef_message_written(ret);
}
else if(last_op <= nfc_eeprom_read_end_session) {
_delegate->on_ndef_message_read(ret);
}
else if(last_op <= nfc_eeprom_erase_end_session) {
_delegate->on_ndef_message_erased(ret);
}
}
}