Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

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