takashi kadono / Mbed OS Nucleo_446

Dependencies:   ssd1331

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers NFCEEPROM.cpp Source File

NFCEEPROM.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 "NFCEEPROM.h"
00018 #include "ndef/ndef.h"
00019 
00020 using namespace mbed;
00021 using namespace mbed::nfc;
00022 
00023 NFCEEPROM::NFCEEPROM(NFCEEPROMDriver *driver, events::EventQueue *queue, const Span<uint8_t>  &ndef_buffer) : NFCTarget(ndef_buffer),
00024     _delegate(NULL), _driver(driver), _initialized(false), _current_op(nfc_eeprom_idle), _ndef_buffer_read_sz(0), _eeprom_address(0), _operation_result(NFC_ERR_UNKNOWN)
00025 {
00026     _driver->set_delegate(this);
00027     _driver->set_event_queue(queue);
00028 }
00029 
00030 nfc_err_t NFCEEPROM::initialize()
00031 {
00032     MBED_ASSERT(_initialized == false); // Initialize should only be called once
00033 
00034     // Initialize driver
00035     _driver->reset();
00036     _initialized = true;
00037     return NFC_OK;
00038 }
00039 
00040 void NFCEEPROM::set_delegate(NFCEEPROM::Delegate *delegate)
00041 {
00042     _delegate = delegate;
00043 }
00044 
00045 void NFCEEPROM::write_ndef_message()
00046 {
00047     MBED_ASSERT(_initialized == true);
00048     if (_current_op != nfc_eeprom_idle) {
00049         if (_delegate != NULL) {
00050             _delegate->on_ndef_message_written(NFC_ERR_BUSY);
00051         }
00052         return;
00053     }
00054 
00055     // First update NDEF message if required
00056     ndef_msg_encode(ndef_message());
00057 
00058     _current_op = nfc_eeprom_write_start_session;
00059 
00060     // Retrieve reader
00061     ac_buffer_dup(&_ndef_buffer_reader, ac_buffer_builder_buffer(ndef_msg_buffer_builder(ndef_message())));
00062 
00063     // Check that NDEF message is not too big
00064     if (ac_buffer_reader_readable(&_ndef_buffer_reader) > _driver->read_max_size()) {
00065         handle_error(NFC_ERR_BUFFER_TOO_SMALL);
00066         return;
00067     }
00068 
00069     // Reset EEPROM address
00070     _eeprom_address = 0;
00071 
00072     // Go through the steps!
00073     _driver->start_session();
00074 
00075     // 1 - Start session
00076     // 2 - Write bytes (can be repeated)
00077     // 3 - Set NDEF message size
00078     // 4 - End session
00079 }
00080 
00081 void NFCEEPROM::read_ndef_message()
00082 {
00083     MBED_ASSERT(_initialized == true);
00084     if (_current_op != nfc_eeprom_idle) {
00085         if (_delegate != NULL) {
00086             _delegate->on_ndef_message_written(NFC_ERR_BUSY);
00087         }
00088         return;
00089     }
00090 
00091     _current_op = nfc_eeprom_read_start_session;
00092 
00093     // Reset EEPROM address
00094     _eeprom_address = 0;
00095 
00096     // Go through the steps!
00097     _driver->start_session();
00098 
00099     // 1 - Start session
00100     // 2 - Get NDEF message size
00101     // 3 - Read bytes (can be repeated)
00102     // 4 - End session
00103 }
00104 
00105 void NFCEEPROM::erase_ndef_message()
00106 {
00107     // We don't want to take any risks, so erase the whole address space
00108     // And set the message size to 0
00109 
00110     MBED_ASSERT(_initialized == true);
00111     if (_current_op != nfc_eeprom_idle) {
00112         if (_delegate != NULL) {
00113             _delegate->on_ndef_message_erased(NFC_ERR_BUSY);
00114         }
00115         return;
00116     }
00117 
00118     _current_op = nfc_eeprom_read_start_session;
00119 
00120     // Reset EEPROM address
00121     _eeprom_address = 0;
00122 
00123     // Go through the steps!
00124     _driver->start_session();
00125 
00126     // 1 - Start session
00127     // 2 - Set addressable size to the max
00128     // 3 - Erase bytes (can be repeated)
00129     // 4 - Set addressable size to 0
00130     // 5 - End session
00131 }
00132 
00133 void NFCEEPROM::on_session_started(bool success)
00134 {
00135     switch (_current_op) {
00136         case nfc_eeprom_write_start_session:
00137             if (!success) {
00138                 handle_error(NFC_ERR_CONTROLLER); // An EEPROM is not really a controller but close enough
00139                 return;
00140             }
00141             _current_op = nfc_eeprom_write_write_bytes;
00142             continue_write();
00143             break;
00144 
00145         case nfc_eeprom_read_start_session:
00146             if (!success) {
00147                 handle_error(NFC_ERR_CONTROLLER);
00148                 return;
00149             }
00150             _current_op = nfc_eeprom_read_read_size;
00151             _driver->read_size();
00152             break;
00153 
00154         case nfc_eeprom_erase_start_session:
00155             if (!success) {
00156                 handle_error(NFC_ERR_CONTROLLER);
00157                 return;
00158             }
00159 
00160             _current_op = nfc_eeprom_erase_write_max_size;
00161             _driver->write_size(_driver->read_max_size());
00162             break;
00163 
00164         default:
00165             // Should not happen, state machine is broken or driver is doing something wrong
00166             handle_error(NFC_ERR_UNKNOWN);
00167             return;
00168     }
00169 }
00170 
00171 void NFCEEPROM::on_session_ended(bool success)
00172 {
00173     switch (_current_op) {
00174         case nfc_eeprom_write_end_session:
00175             if (!success) {
00176                 handle_error(NFC_ERR_CONTROLLER);
00177                 return;
00178             }
00179             _current_op = nfc_eeprom_idle;
00180             if (_delegate != NULL) {
00181                 _delegate->on_ndef_message_written(_operation_result);
00182             }
00183             break;
00184 
00185         case nfc_eeprom_read_end_session:
00186             if (!success) {
00187                 handle_error(NFC_ERR_CONTROLLER);
00188                 return;
00189             }
00190             _current_op = nfc_eeprom_idle;
00191 
00192             // Try to parse the NDEF message
00193             ndef_msg_decode(ndef_message());
00194 
00195             if (_delegate != NULL) {
00196                 _delegate->on_ndef_message_read(_operation_result);
00197             }
00198             break;
00199 
00200         case nfc_eeprom_erase_end_session:
00201             if (!success) {
00202                 handle_error(NFC_ERR_CONTROLLER);
00203                 return;
00204             }
00205             _current_op = nfc_eeprom_idle;
00206             if (_delegate != NULL) {
00207                 _delegate->on_ndef_message_erased(_operation_result);
00208             }
00209             break;
00210 
00211         default:
00212             // Should not happen, state machine is broken or driver is doing something wrong
00213             handle_error(NFC_ERR_UNKNOWN);
00214             return;
00215     }
00216 }
00217 
00218 void NFCEEPROM::on_bytes_read(size_t count)
00219 {
00220     switch (_current_op) {
00221         case nfc_eeprom_read_read_bytes: {
00222             if (count == 0) {
00223                 handle_error(NFC_ERR_CONTROLLER);
00224                 return;
00225             }
00226 
00227             // Discard bytes that were actually read and update address
00228             _eeprom_address += count;
00229             ac_buffer_builder_t *buffer_builder = ndef_msg_buffer_builder(ndef_message());
00230             ac_buffer_builder_write_n_skip(buffer_builder, count);
00231 
00232             // Continue reading
00233             continue_read();
00234             break;
00235         }
00236         default:
00237             // Should not happen, state machine is broken or driver is doing something wrong
00238             handle_error(NFC_ERR_UNKNOWN);
00239             return;
00240     }
00241 }
00242 
00243 void NFCEEPROM::on_bytes_written(size_t count)
00244 {
00245     switch (_current_op) {
00246         case nfc_eeprom_write_write_bytes:
00247             if (count == 0) {
00248                 handle_error(NFC_ERR_CONTROLLER);
00249                 return;
00250             }
00251 
00252             // Skip bytes that were actually written and update address
00253             _eeprom_address += count;
00254             ac_buffer_read_n_skip(&_ndef_buffer_reader, count);
00255 
00256             // Continue writing
00257             continue_write();
00258             break;
00259         default:
00260             // Should not happen, state machine is broken or driver is doing something wrong
00261             handle_error(NFC_ERR_UNKNOWN);
00262             return;
00263     }
00264 }
00265 
00266 void NFCEEPROM::on_size_written(bool success)
00267 {
00268     switch (_current_op) {
00269         case nfc_eeprom_write_write_size:
00270             if (!success) {
00271                 handle_error(NFC_ERR_CONTROLLER);
00272                 return;
00273             }
00274 
00275             // End session
00276             _current_op = nfc_eeprom_write_end_session;
00277             _operation_result = NFC_OK;
00278             _driver->end_session();
00279             break;
00280         case nfc_eeprom_erase_write_max_size:
00281             if (!success) {
00282                 handle_error(NFC_ERR_CONTROLLER);
00283                 return;
00284             }
00285 
00286             // Start erasing bytes
00287             _current_op = nfc_eeprom_erase_erase_bytes;
00288             continue_erase();
00289             break;
00290         case nfc_eeprom_erase_write_0_size:
00291             if (!success) {
00292                 handle_error(NFC_ERR_CONTROLLER);
00293                 return;
00294             }
00295 
00296             // End session
00297             _current_op = nfc_eeprom_erase_end_session;
00298             _operation_result = NFC_OK;
00299             _driver->end_session();
00300             break;
00301         default:
00302             // Should not happen, state machine is broken or driver is doing something wrong
00303             handle_error(NFC_ERR_UNKNOWN);
00304             return;
00305     }
00306 }
00307 
00308 void NFCEEPROM::on_size_read(bool success, size_t size)
00309 {
00310     switch (_current_op) {
00311         case nfc_eeprom_read_read_size: {
00312             if (!success) {
00313                 handle_error(NFC_ERR_CONTROLLER);
00314                 return;
00315             }
00316 
00317             // Reset NDEF message buffer builder
00318             ac_buffer_builder_t *buffer_builder = ndef_msg_buffer_builder(ndef_message());
00319             ac_buffer_builder_reset(buffer_builder);
00320 
00321             // Check that we have a big enough buffer to read the message
00322             if (size > ac_buffer_builder_writable(buffer_builder)) {
00323                 // Not enough space, close session
00324                 _current_op = nfc_eeprom_read_end_session;
00325                 _operation_result = NFC_ERR_BUFFER_TOO_SMALL;
00326                 _driver->end_session();
00327                 return;
00328             }
00329 
00330             // Save size and reset address
00331             _eeprom_address = 0;
00332             _ndef_buffer_read_sz = size;
00333 
00334             // Start reading bytes
00335             _current_op = nfc_eeprom_read_read_bytes;
00336             continue_read();
00337             break;
00338         }
00339         default:
00340             // Should not happen, state machine is broken or driver is doing something wrong
00341             handle_error(NFC_ERR_UNKNOWN);
00342             return;
00343     }
00344 }
00345 
00346 void NFCEEPROM::on_bytes_erased(size_t count)
00347 {
00348     switch (_current_op) {
00349         case nfc_eeprom_erase_erase_bytes:
00350             if (count == 0) {
00351                 handle_error(NFC_ERR_CONTROLLER);
00352                 return;
00353             }
00354 
00355             // Update address
00356             _eeprom_address += count;
00357 
00358             // Continue erasing
00359             continue_erase();
00360             break;
00361         default:
00362             // Should not happen, state machine is broken or driver is doing something wrong
00363             handle_error(NFC_ERR_UNKNOWN);
00364             return;
00365     }
00366 }
00367 
00368 void NFCEEPROM::continue_write()
00369 {
00370     if (ac_buffer_reader_readable(&_ndef_buffer_reader) > 0) {
00371         // Continue writing
00372         _driver->write_bytes(_eeprom_address, ac_buffer_reader_current_buffer_pointer(&_ndef_buffer_reader), ac_buffer_reader_current_buffer_length(&_ndef_buffer_reader));
00373     } else {
00374         // Now update size
00375         _current_op = nfc_eeprom_write_write_size;
00376         _driver->write_size(_eeprom_address);
00377     }
00378 }
00379 
00380 void NFCEEPROM::continue_erase()
00381 {
00382     if (_eeprom_address < _driver->read_max_size()) {
00383         // Continue erasing
00384         _driver->erase_bytes(_eeprom_address, _driver->read_max_size() - _eeprom_address);
00385     } else {
00386         // Now update size
00387         _current_op = nfc_eeprom_erase_write_0_size;
00388         _driver->write_size(0);
00389     }
00390 }
00391 
00392 void NFCEEPROM::continue_read()
00393 {
00394     if (_eeprom_address < _ndef_buffer_read_sz) {
00395         // Continue reading
00396         ac_buffer_builder_t *buffer_builder = ndef_msg_buffer_builder(ndef_message());
00397         _driver->read_bytes(_eeprom_address, ac_buffer_builder_write_position(buffer_builder), _ndef_buffer_read_sz - _eeprom_address);
00398     } else {
00399         // Done, close session
00400         _current_op = nfc_eeprom_read_end_session;
00401         _operation_result = NFC_OK;
00402         _driver->end_session();
00403     }
00404 }
00405 
00406 void NFCEEPROM::handle_error(nfc_err_t ret)
00407 {
00408     // Save & reset current op
00409     nfc_eeprom_operation_t last_op = _current_op;
00410     _current_op = nfc_eeprom_idle;
00411 
00412     if (_delegate != NULL) {
00413         if (last_op <= nfc_eeprom_write_end_session) {
00414             _delegate->on_ndef_message_written(ret);
00415         } else if (last_op <= nfc_eeprom_read_end_session) {
00416             _delegate->on_ndef_message_read(ret);
00417         } else if (last_op <= nfc_eeprom_erase_end_session) {
00418             _delegate->on_ndef_message_erased(ret);
00419         }
00420     }
00421 }
00422 
00423 NFCNDEFCapable::Delegate *NFCEEPROM::ndef_capable_delegate()
00424 {
00425     return _delegate;
00426 }