diff --git a/TESTS/nfc/eeprom/main.cpp b/TESTS/nfc/eeprom/main.cpp deleted file mode 100644 index c8d40a0..0000000 --- a/TESTS/nfc/eeprom/main.cpp +++ /dev/null @@ -1,501 +0,0 @@ -/* - * Copyright (c) 2017, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * 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 "mbed.h" -#include "greentea-client/test_env.h" -#include "unity.h" -#include "utest.h" - -#include -#include "NFCEEPROMDriver.h" - -#if !MBED_CONF_NFCEEPROM -#error [NOT_SUPPORTED] NFC EEPROM not supported for this target -#else - -using namespace utest::v1; -using namespace mbed::nfc; - -/* individual steps that map to specific operations that include parameters */ -typedef enum { - START_SESSION = 0x0000, - - END_SESSION = 0x0100, - - READ_BYTES = 0x0200, - READ_2_BYTES = 0x0201, - READ_2_BYTES_OFFSET_FAIL = 0x0202, - READ_4_BYTES = 0x0203, - READ_4_BYTES_MIXED = 0x0204, - READ_4_BYTES_OFFSET = 0x0205, - READ_4_BYTES_ERASED = 0x0206, - READ_4_BYTES_FAIL = 0x0207, - - WRITE_BYTES = 0x0300, - WRITE_2_BYTES = 0x0301, - WRITE_2_BYTES_OFFSET = 0x0302, - WRITE_2_BYTES_OFFSET_FAIL = 0x0303, - WRITE_4_BYTES = 0x0304, - WRITE_4_BYTES_FAIL = 0x0305, - - ERASE_BYTES = 0x0400, - ERASE_4_BYTES = 0x0401, - - READ_SIZE = 0x0500, - READ_SIZE_2 = 0x0501, - READ_SIZE_4 = 0x0502, - - WRITE_SIZE = 0x0600, - WRITE_SIZE_2 = 0x0601, - WRITE_SIZE_4 = 0x0602, - - TERMINATE = 0xFF00 -} TestCommand_t; - -/* We group the command based on their first byte to simplify step checking. - * Individual conditions of a step are checked in the event so this doesn't - * sacrifice any correctness checking */ -const size_t TEST_COMMAND_GROUP_MASK = 0xFF00; - -/* test case sequences that index into the array of commands which comprise them */ -typedef enum { - SESSION_TEST, - WRITE_READ_TEST, - ERASE_TEST, - WRITE_READ_SIZE_TEST, - TRUNCATE_TEST, - WRITE_TRUNCATE_TEST, - WRITE_WITH_OFFSET_TEST, - WRITE_BEYOND_SIZE_TEST, - SEQUENCE_MAX -} TestSequence_t; - -static EventQueue event_queue(/* event count */ 10 * EVENTS_EVENT_SIZE); - -static const size_t MAX_STEP = 10; -static const size_t BUFFER_MAX = 10; - -/* defines the "script" the test follows, each step is checked and all - * have to execute to completion for a successful run */ -static const TestCommand_t SEQUENCES[SEQUENCE_MAX][MAX_STEP] = { - /* SESSION_TEST */ - { START_SESSION, END_SESSION, TERMINATE }, - - /* WRITE_READ_TEST */ - { - START_SESSION, WRITE_SIZE_4, READ_SIZE_4, WRITE_4_BYTES, READ_4_BYTES, - WRITE_2_BYTES, READ_4_BYTES_MIXED, END_SESSION, TERMINATE - }, - - /* ERASE_TEST */ - { - START_SESSION, WRITE_SIZE_4, READ_SIZE_4, WRITE_4_BYTES, READ_4_BYTES, - ERASE_4_BYTES, READ_4_BYTES_ERASED, END_SESSION, TERMINATE - }, - - /* WRITE_READ_SIZE_TEST */ - { - START_SESSION, WRITE_SIZE_2, READ_SIZE_2, WRITE_SIZE_4, READ_SIZE_4, - END_SESSION, TERMINATE - }, - - /* TRUNCATE_TEST */ - { - START_SESSION, WRITE_SIZE_4, READ_SIZE_4, WRITE_4_BYTES, READ_4_BYTES, - WRITE_SIZE_2, READ_SIZE_2, READ_4_BYTES_FAIL, END_SESSION, TERMINATE - }, - - /* WRITE_TRUNCATE_TEST */ - { - START_SESSION, WRITE_SIZE_2, READ_SIZE_2, WRITE_4_BYTES_FAIL, READ_4_BYTES_FAIL, - END_SESSION, TERMINATE - }, - - /* WRITE_WITH_OFFSET_TEST */ - { - START_SESSION, WRITE_SIZE_4, READ_SIZE_4, WRITE_4_BYTES, READ_4_BYTES, - WRITE_2_BYTES_OFFSET, READ_4_BYTES_OFFSET, END_SESSION, TERMINATE - }, - - /* WRITE_BEYOND_SIZE_TEST */ - { - START_SESSION, WRITE_SIZE_2, READ_SIZE_2, WRITE_2_BYTES_OFFSET_FAIL, READ_2_BYTES_OFFSET_FAIL, - WRITE_2_BYTES, READ_2_BYTES, END_SESSION, TERMINATE - } -}; - -static const uint8_t DATA_4_BYTES[] = { 0x01, 0x02, 0x03, 0x04 }; -static const uint8_t DATA_2_BYTES[] = { 0x05, 0x06 }; -static const uint8_t DATA_4_BYTES_MIXED[] = { 0x05, 0x06, 0x03, 0x04 }; -static const uint8_t DATA_4_BYTES_OFFSET[] = { 0x01, 0x02, 0x05, 0x06 }; -static const uint8_t DATA_4_BYTES_ERASED[] = { 0x00, 0x00, 0x00, 0x00 }; - -class DriverTest : public NFCEEPROMDriver::Delegate { -public: - DriverTest(NFCEEPROMDriver *_driver) - : _operation_data(NULL), - _driver(_driver), - _sequence(SEQUENCE_MAX), - _step(0), - _result_size(0), - _address(0), - _success(true) { }; - - virtual ~DriverTest() { }; - - /* Delegate events */ - - virtual void on_session_started(bool success) - { - if (success != _success) { - TEST_FAIL_MESSAGE("failed to start session"); - } - - evaluate_step(START_SESSION); - }; - - virtual void on_session_ended(bool success) - { - if (success != _success) { - TEST_FAIL_MESSAGE("failed to end session"); - } - - evaluate_step(END_SESSION); - }; - - virtual void on_bytes_read(size_t count) - { - if (count != _result_size) { - TEST_FAIL_MESSAGE("failed to read bytes"); - } - if (memcmp(_buffer, _operation_data, count) != 0) { - TEST_FAIL_MESSAGE("read bytes are different than expected"); - } - - evaluate_step(READ_BYTES); - }; - - virtual void on_bytes_written(size_t count) - { - if (count != _result_size) { - TEST_FAIL_MESSAGE("failed to write bytes"); - } - - evaluate_step(WRITE_BYTES); - }; - - virtual void on_size_written(bool success) - { - if (success != _success) { - TEST_FAIL_MESSAGE("failed to write size"); - } - - evaluate_step(WRITE_SIZE); - }; - - virtual void on_size_read(bool success, size_t size) - { - if (success != _success || size != _result_size) { - TEST_FAIL_MESSAGE("failed to read size"); - } - - evaluate_step(READ_SIZE); - }; - - virtual void on_bytes_erased(size_t count) - { - if (count != _result_size) { - TEST_FAIL_MESSAGE("failed to erase bytes"); - } - - evaluate_step(ERASE_BYTES); - } - - /* Sequence running code */ - - void run_sequence(TestSequence_t sequence) - { - _sequence = sequence; - - if (_sequence >= SEQUENCE_MAX) { - TEST_FAIL_MESSAGE("internal test failure - invalid command"); - } - - execute_next_step(); - - event_queue.dispatch_forever(); - - TEST_ASSERT_EQUAL(TERMINATE, SEQUENCES[_sequence][_step]); - } - - void execute_next_step() - { - TestCommand_t command = SEQUENCES[_sequence][_step]; - - /* setup data buffer */ - switch (command) { - case READ_2_BYTES: - case READ_2_BYTES_OFFSET_FAIL: - case WRITE_2_BYTES: - case WRITE_2_BYTES_OFFSET: - case WRITE_2_BYTES_OFFSET_FAIL: - _operation_data = DATA_2_BYTES; - break; - case READ_4_BYTES: - case READ_4_BYTES_FAIL: - case WRITE_4_BYTES: - case WRITE_4_BYTES_FAIL: - _operation_data = DATA_4_BYTES; - break; - case READ_4_BYTES_ERASED: - _operation_data = DATA_4_BYTES_ERASED; - break; - case READ_4_BYTES_MIXED: - _operation_data = DATA_4_BYTES_MIXED; - break; - case READ_4_BYTES_OFFSET: - _operation_data = DATA_4_BYTES_OFFSET; - break; - default: - _operation_data = NULL; - } - - /* setup result size */ - switch (command) { - case READ_2_BYTES: - case READ_4_BYTES_FAIL: - case WRITE_2_BYTES: - case WRITE_4_BYTES_FAIL: - case WRITE_2_BYTES_OFFSET: - case READ_SIZE_2: - _result_size = 2; - break; - case READ_4_BYTES: - case READ_4_BYTES_ERASED: - case READ_4_BYTES_MIXED: - case READ_4_BYTES_OFFSET: - case WRITE_4_BYTES: - case ERASE_4_BYTES: - case READ_SIZE_4: - _result_size = 4; - break; - default: - _result_size = 0; - } - - /* setup operation size */ - switch (command) { - case READ_2_BYTES: - case READ_2_BYTES_OFFSET_FAIL: - case WRITE_2_BYTES: - case WRITE_2_BYTES_OFFSET: - case WRITE_2_BYTES_OFFSET_FAIL: - case WRITE_SIZE_2: - _operation_size = 2; - break; - case READ_4_BYTES: - case READ_4_BYTES_ERASED: - case READ_4_BYTES_MIXED: - case READ_4_BYTES_OFFSET: - case READ_4_BYTES_FAIL: - case WRITE_4_BYTES: - case WRITE_4_BYTES_FAIL: - case ERASE_4_BYTES: - case READ_SIZE_4: - case WRITE_SIZE_4: - _operation_size = 4; - break; - default: - _operation_size = 0; - } - - /* setup offset */ - switch (command) { - case READ_2_BYTES_OFFSET_FAIL: - case WRITE_2_BYTES_OFFSET: - case WRITE_2_BYTES_OFFSET_FAIL: - _address = 2; - break; - default: - _address = 0; - } - - /* setup command success */ - switch (command) { - case READ_2_BYTES_OFFSET_FAIL: - case WRITE_2_BYTES_OFFSET_FAIL: - _success = false; - break; - default: - _success = true; - } - - /* call next command */ - switch (command & TEST_COMMAND_GROUP_MASK) { - case START_SESSION: - _driver->start_session(true); - break; - case END_SESSION: - _driver->end_session(); - break; - case READ_BYTES: - _driver->read_bytes(_address, _buffer, _operation_size); - break; - case WRITE_BYTES: - _driver->write_bytes(_address, _operation_data, _operation_size); - break; - case ERASE_BYTES: - _driver->erase_bytes(_address, _operation_size); - break; - case READ_SIZE: - _driver->read_size(); - break; - case WRITE_SIZE: - _driver->write_size(_operation_size); - break; - case TERMINATE: - event_queue.break_dispatch(); - break; - default: - TEST_FAIL_MESSAGE("internal test failure - invalid command"); - } - } - - void evaluate_step(TestCommand_t command_completed) - { - /* check last command succeeded */ - TEST_ASSERT_EQUAL(command_completed, SEQUENCES[_sequence][_step]&TEST_COMMAND_GROUP_MASK); - - _step++; - - if (_step == MAX_STEP) { - TEST_FAIL_MESSAGE("internal test failure - too many steps"); - } - - execute_next_step(); - } - -private: - uint8_t _buffer[BUFFER_MAX]; - const uint8_t *_operation_data; - - NFCEEPROMDriver *_driver; - - TestSequence_t _sequence; - size_t _step; - size_t _result_size; - size_t _operation_size; - size_t _address; - bool _success; -}; - -/* test case running code */ - -static DriverTest *driver_test; -extern NFCEEPROMDriver *greentea_nfc_EEPROM_driver_get_instance(); - -utest::v1::status_t test_setup(const Case *const source, const size_t index_of_case) -{ - NFCEEPROMDriver *driver = greentea_nfc_EEPROM_driver_get_instance(); - driver_test = new DriverTest(driver); - - driver->set_event_queue(&event_queue); - driver->set_delegate(driver_test); - driver->reset(); - - TEST_ASSERT_NOT_EQUAL(0, driver->read_max_size()); - - return greentea_case_setup_handler(source, index_of_case); -} - -void session() -{ - driver_test->run_sequence(SESSION_TEST); -} - -void write_read() -{ - driver_test->run_sequence(WRITE_READ_TEST); -} - -void erase_bytes() -{ - driver_test->run_sequence(ERASE_TEST); -} - -void write_read_size() -{ - driver_test->run_sequence(WRITE_READ_SIZE_TEST); -} - -void truncate_size() -{ - driver_test->run_sequence(TRUNCATE_TEST); -} - -void write_bytes_truncated() -{ - driver_test->run_sequence(WRITE_TRUNCATE_TEST); -} - -void write_with_offset() -{ - driver_test->run_sequence(WRITE_WITH_OFFSET_TEST); -} - -void write_beyond_size() -{ - driver_test->run_sequence(WRITE_BEYOND_SIZE_TEST); -} - -utest::v1::status_t test_tear_down(const Case *const source, const size_t passed, - const size_t failed, const failure_t reason) -{ - delete driver_test; - - return greentea_case_teardown_handler(source, passed, failed, reason); -} - -/* test setup */ - -utest::v1::status_t test_init(const size_t number_of_cases) -{ - GREENTEA_SETUP(10, "default_auto"); - return greentea_test_setup_handler(number_of_cases); -} - -// Test cases -Case cases[] = { - Case("NFCEEPROM-SESSION", test_setup, session, test_tear_down), - Case("NFCEEPROM-WRITE-READ", test_setup, write_read, test_tear_down), - Case("NFCEEPROM-ERASE-BYTES", test_setup, erase_bytes, test_tear_down), - Case("NFCEEPROM-WRITE-READ-SIZE", test_setup, write_read_size, test_tear_down), - Case("NFCEEPROM-TRUNCATE-SIZE", test_setup, truncate_size, test_tear_down), - Case("NFCEEPROM-WRITE-BYTES-TRUNCATED", test_setup, write_bytes_truncated, test_tear_down), - Case("NFCEEPROM-WRITE-WITH-OFFSET", test_setup, write_with_offset, test_tear_down), - Case("NFCEEPROM-WRITE-BEYOND-SIZE", test_setup, write_beyond_size, test_tear_down) -}; - -Specification specification(test_init, cases); - -// Entry point into the tests -int main() -{ - return !Harness::run(specification); -} - -#endif // !MBED_CONF_NFCEEPROM diff --git a/connectivity/drivers/nfc/PN512/include/nfc/controllers/PN512Driver.h b/connectivity/drivers/nfc/PN512/include/nfc/controllers/PN512Driver.h new file mode 100644 index 0000000..cd84dbc --- /dev/null +++ b/connectivity/drivers/nfc/PN512/include/nfc/controllers/PN512Driver.h @@ -0,0 +1,51 @@ +/* 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. + */ + +#ifndef MBED_PN512_DRIVER_H +#define MBED_PN512_DRIVER_H + +#include + +#include "nfc/NFCControllerDriver.h" +#include "PN512TransportDriver.h" + +#include "acore/acore/ac_buffer.h" +#include "acore/acore/ac_buffer_reader.h" +#include "acore/acore/ac_buffer_builder.h" +#include "transceiver/pn512.h" + +namespace mbed { +namespace nfc { + +class PN512Driver : public NFCControllerDriver, private PN512TransportDriver::Delegate { +public: + PN512Driver(PN512TransportDriver *transport_driver); + + virtual nfc_transceiver_t *initialize(nfc_scheduler_timer_t *scheduler_timer); + virtual void get_supported_nfc_techs(nfc_tech_t *initiator, nfc_tech_t *target) const; + +private: + // PN512TransportDriver::Delegate implementation + virtual void on_hw_interrupt(); + + PN512TransportDriver *_transport_driver; + pn512_t _pn512; +}; + +} // namespace nfc +} // namespace mbed + +#endif diff --git a/connectivity/drivers/nfc/PN512/include/nfc/controllers/PN512SPITransportDriver.h b/connectivity/drivers/nfc/PN512/include/nfc/controllers/PN512SPITransportDriver.h new file mode 100644 index 0000000..99a7ab9 --- /dev/null +++ b/connectivity/drivers/nfc/PN512/include/nfc/controllers/PN512SPITransportDriver.h @@ -0,0 +1,58 @@ +/* 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. + */ + +#ifndef MBED_PN512_SPI_TRANSPORT_DRIVER_H +#define MBED_PN512_SPI_TRANSPORT_DRIVER_H + +#include + +#include "platform/platform.h" +#include "platform/nfc_transport.h" +#include "PN512TransportDriver.h" + +#include "drivers/SPI.h" +#include "drivers/DigitalOut.h" +#include "drivers/InterruptIn.h" + +namespace mbed { +namespace nfc { + +class PN512SPITransportDriver : public PN512TransportDriver { +public: + PN512SPITransportDriver(PinName mosi, PinName miso, PinName sclk, PinName ssel, PinName irq, PinName rst); + +private: + virtual void initialize(); + virtual nfc_transport_t *get_transport(); + + void transport_write(uint8_t address, const uint8_t *outBuf, size_t outLen); + void transport_read(uint8_t address, uint8_t *inBuf, size_t inLen); + + // Callbacks from munfc + static void s_transport_write(uint8_t address, const uint8_t *outBuf, size_t outLen, void *pUser); + static void s_transport_read(uint8_t address, uint8_t *inBuf, size_t inLen, void *pUser); + + nfc_transport_t _nfc_transport; + mbed::SPI _spi; + mbed::DigitalOut _ssel; + mbed::InterruptIn _irq; + mbed::DigitalOut _rst; +}; + +} // namespace nfc +} // namespace mbed + +#endif diff --git a/connectivity/drivers/nfc/PN512/include/nfc/controllers/PN512TransportDriver.h b/connectivity/drivers/nfc/PN512/include/nfc/controllers/PN512TransportDriver.h new file mode 100644 index 0000000..cb5c437 --- /dev/null +++ b/connectivity/drivers/nfc/PN512/include/nfc/controllers/PN512TransportDriver.h @@ -0,0 +1,86 @@ +/* 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. + */ + +#ifndef MBED_PN512_TRANSPORT_DRIVER_H +#define MBED_PN512_TRANSPORT_DRIVER_H + +#include +#include "stack/platform/nfc_transport.h" + + +namespace mbed { +namespace nfc { +/** + * The PN512 supports multiple transport mechanisms (SPI, I2C, UART): this class provides a unified API across these transports + */ +class PN512TransportDriver { +public: + /** + * The PN512TransportDriver delegate + */ + struct Delegate { + /** + * Called when the PN512 asserts the interrupt line + */ + virtual void on_hw_interrupt() {} + + protected: + ~Delegate() {} + }; + + /** + * Create a PN512TransportDriver instance + */ + PN512TransportDriver(); + + /** + * PN512TransportDriver destructor. + */ + virtual ~PN512TransportDriver(); + + /** + * Initialize transport driver and perform a chip reset + */ + virtual void initialize() = 0; + + /** + * Retrieve the nfc_transport_t struct for the stack to use + * + * @return a pointer to a nfc_transport_t struct + */ + virtual nfc_transport_t *get_transport() = 0; + + /** + * Set this instance's delegate + * + * @param[in] delegate the delegate instance to use + */ + void set_delegate(Delegate *delegate); +protected: + + /** + * An implementation must call this function (can be called from interrupt context) + * when the PN512 asserts its interrupt line + */ + void hw_interrupt(); +private: + Delegate *_delegate; +}; + +} // namespace nfc +} // namespace mbed + +#endif diff --git a/connectivity/drivers/nfc/PN512/mbed_lib.json b/connectivity/drivers/nfc/PN512/mbed_lib.json new file mode 100644 index 0000000..a58b5d8 --- /dev/null +++ b/connectivity/drivers/nfc/PN512/mbed_lib.json @@ -0,0 +1,3 @@ +{ + "name": "PN512-nfc" +} diff --git a/connectivity/drivers/nfc/PN512/source/PN512Driver.cpp b/connectivity/drivers/nfc/PN512/source/PN512Driver.cpp new file mode 100644 index 0000000..315c53e --- /dev/null +++ b/connectivity/drivers/nfc/PN512/source/PN512Driver.cpp @@ -0,0 +1,68 @@ +/* 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 "PN512Driver.h" + +#include "stack/platform/nfc_debug.h" + +using namespace mbed; +using namespace mbed::nfc; + +PN512Driver::PN512Driver(PN512TransportDriver *transport_driver) : NFCControllerDriver(), _transport_driver(transport_driver) +{ + _transport_driver->set_delegate(this); +} + +nfc_transceiver_t *PN512Driver::initialize(nfc_scheduler_timer_t *scheduler_timer) +{ + // Initialize transport + _transport_driver->initialize(); + + nfc_err_t ret = pn512_init(&_pn512, _transport_driver->get_transport(), scheduler_timer); + if (ret != NFC_OK) { + NFC_ERR("PN512 init error (%d)", ret); + return NULL; + } + NFC_DBG("PN512 Initialized"); + + return pn512_get_transceiver(&_pn512); +} + +void PN512Driver::get_supported_nfc_techs(nfc_tech_t *initiator, nfc_tech_t *target) const +{ + initiator->nfc_type1 = 0; + initiator->nfc_type2 = 1; + initiator->nfc_type3 = 1; + initiator->nfc_iso_dep_a = 1; + initiator->nfc_iso_dep_b = 0; + initiator->nfc_nfc_dep_a = 1; + initiator->nfc_nfc_dep_f_212 = 1; + initiator->nfc_nfc_dep_f_424 = 1; + + target->nfc_type1 = 0; + target->nfc_type2 = 0; + target->nfc_type3 = 0; + target->nfc_iso_dep_a = 1; + target->nfc_iso_dep_b = 0; + target->nfc_nfc_dep_a = 1; + target->nfc_nfc_dep_f_212 = 1; + target->nfc_nfc_dep_f_424 = 1; +} + +void PN512Driver::on_hw_interrupt() +{ + hw_interrupt(); // Propagate interrupt signal +} diff --git a/connectivity/drivers/nfc/PN512/source/PN512SPITransportDriver.cpp b/connectivity/drivers/nfc/PN512/source/PN512SPITransportDriver.cpp new file mode 100644 index 0000000..1fb9f99 --- /dev/null +++ b/connectivity/drivers/nfc/PN512/source/PN512SPITransportDriver.cpp @@ -0,0 +1,117 @@ +/* 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 "platform/platform.h" + +#if (defined (DEVICE_SPI) && defined (DEVICE_INTERRUPTIN)) || defined(DOXYGEN_ONLY) + +#include "PN512SPITransportDriver.h" + +#include "stack/transceiver/transceiver.h" +#include "platform/mbed_wait_api.h" + +using namespace mbed; +using namespace mbed::nfc; + +PN512SPITransportDriver::PN512SPITransportDriver(PinName mosi, PinName miso, PinName sclk, PinName ssel, PinName irq, PinName rst) : + _spi(mosi, miso, sclk), + _ssel(ssel, 1), + _irq(irq, PullNone), + _rst(rst, 1) +{ + + // Use SPI mode 0 + _spi.format(8, 0); + + // The PN512 supports SPI clock frequencies up to 10MHz, so use this if we can + _spi.frequency(10000000UL); + + // Initialize NFC transport + nfc_transport_init(&_nfc_transport, &PN512SPITransportDriver::s_transport_write, &PN512SPITransportDriver::s_transport_read, this); +} + +void PN512SPITransportDriver::initialize() +{ + // Deactivate IRQ + _irq.rise(callback()); + + // Assert reset pin + // According to the datasheet, it needs to be asserted for at least 100ns + // Wait for 1us as that's the shortest time we can wait for + _rst = 0; + wait_us(1); + _rst = 1; + + // Setup IRQ pin + _irq.rise(callback(this, &PN512SPITransportDriver::hw_interrupt)); +} + +nfc_transport_t *PN512SPITransportDriver::get_transport() +{ + return &_nfc_transport; +} + +void PN512SPITransportDriver::transport_write(uint8_t address, const uint8_t *outBuf, size_t outLen) +{ + if (outLen == 0) { + return; + } + + // First byte is (address << 1) | 0x00 for a write + address = (address << 1) | 0x00; + _ssel = 0; + _spi.write(address); // First write address byte + _spi.write((const char *) outBuf, outLen, (char *) NULL, 0); // Ignore read bytes + _ssel = 1; +} + +void PN512SPITransportDriver::transport_read(uint8_t address, uint8_t *inBuf, size_t inLen) +{ + if (inLen == 0) { + return; + } + + // Address byte is (address << 1) | 0x80 for a read + // This should be repeated accross the transfer, except for the last byte which should be 0 + address = (address << 1) | 0x80; + + // Set this byte across inBuf so that it's repeated accross the transfer + // Bit cheeky, but will work + memset(inBuf, address, inLen - 1); + + // Also terminate with 0 so that it's a no-op + inBuf[inLen - 1] = 0; + + _ssel = 0; + _spi.write(address); // First write address byte + _spi.write((const char *) inBuf, inLen, (char *) inBuf, inLen); + _ssel = 1; +} + +// Callbacks from munfc +void PN512SPITransportDriver::s_transport_write(uint8_t address, const uint8_t *outBuf, size_t outLen, void *pUser) +{ + PN512SPITransportDriver *self = (PN512SPITransportDriver *)pUser; + self->transport_write(address, outBuf, outLen); +} + +void PN512SPITransportDriver::s_transport_read(uint8_t address, uint8_t *inBuf, size_t inLen, void *pUser) +{ + PN512SPITransportDriver *self = (PN512SPITransportDriver *)pUser; + self->transport_read(address, inBuf, inLen); +} + +#endif diff --git a/connectivity/drivers/nfc/PN512/source/PN512TransportDriver.cpp b/connectivity/drivers/nfc/PN512/source/PN512TransportDriver.cpp new file mode 100644 index 0000000..f065349 --- /dev/null +++ b/connectivity/drivers/nfc/PN512/source/PN512TransportDriver.cpp @@ -0,0 +1,42 @@ +/* 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 "PN512TransportDriver.h" + +using namespace mbed; +using namespace mbed::nfc; + +PN512TransportDriver::PN512TransportDriver() : _delegate(NULL) +{ + +} + +PN512TransportDriver::~PN512TransportDriver() +{ + +} + +void PN512TransportDriver::set_delegate(Delegate *delegate) +{ + _delegate = delegate; +} + +void PN512TransportDriver::hw_interrupt() +{ + if (_delegate != NULL) { + _delegate->on_hw_interrupt(); + } +} diff --git a/connectivity/drivers/nfc/PN512/source/transceiver/pn512.c b/connectivity/drivers/nfc/PN512/source/transceiver/pn512.c new file mode 100644 index 0000000..e2eb348 --- /dev/null +++ b/connectivity/drivers/nfc/PN512/source/transceiver/pn512.c @@ -0,0 +1,356 @@ +/* + * Copyright (c) 2013-2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + */ +/** + * \file pn512.c + * \copyright Copyright (c) ARM Ltd 2013 + * \author Donatien Garnier + * \details PN512 implementation of the transceiver interface + */ + +#define __DEBUG__ 4 +#ifndef __MODULE__ +#define __MODULE__ "pn512.c" +#endif +#include "stack/nfc_errors.h" + +#include "stdlib.h" + +#include "acore/ac_buffer.h" + +#include "transceiver/transceiver.h" +#include "transceiver/protocols.h" +#include "pn512_rf.h" +#include "pn512_registers.h" +#include "pn512_cmd.h" +#include "pn512_hw.h" +#include "pn512_irq.h" +#include "pn512_poll.h" +#include "pn512_transceive.h" +#include "pn512_internal.h" + +#include "pn512.h" + +#define DEFAULT_READER_TRANSCEIVE_TIMEOUT 100 +#define DEFAULT_TARGET_TRANSCEIVE_TIMEOUT -1 + + +//Prototypes +#include "pn512_internal.h" + +/** \addtogroup PN512 + * @{ + * \name Transceiver + * \details Implementation of the transceiver interface + * @{ + */ + +//PN 512 VTABLE + +static const transceiver_impl_t pn512_impl = { + .set_protocols = pn512_set_protocols, + .poll = pn512_poll, + .transceive = pn512_transceive, + .abort = pn512_abort, + .set_crc = pn512_set_crc, + .set_timeout = pn512_set_timeout, + .set_transceive_options = pn512_set_transceive_options, + .set_transceive_framing = pn512_set_transceive_framing, + .set_write = pn512_set_write, + .get_read = pn512_get_read, + .set_last_byte_length = pn512_set_last_byte_length, + .get_last_byte_length = pn512_get_last_byte_length, + .set_first_byte_align = pn512_set_first_byte_align, + .close = pn512_close, + .sleep = pn512_sleep +}; + +/** Initialize PN512 transceiver + * \param pPN512 pointer to pn512_t structure to initialize + * \param pTransport pointer to already initialized nfc_transport_t structure + * \return NFC_OK (0) on success or NFC_ERR_* error on failure + */ +nfc_err_t pn512_init(pn512_t *pPN512, nfc_transport_t *pTransport, nfc_scheduler_timer_t *pTimer) +{ + //// + //For Self-test + //// +#if NFC_PN512_SELFTEST + const uint8_t null_array[25] = {0}; +#endif + //// + uint8_t r; + + //Init transceiver + transceiver_init((nfc_transceiver_t *)pPN512, pTransport, pTimer); + + //Init buffer + ac_buffer_builder_init(&pPN512->readBufBldr, pPN512->payload, 256); + + pPN512->readFirstByteAlign = 0; + pPN512->readLastByteLength = 8; + pPN512->writeLastByteLength = 8; + + //Populate functions + pPN512->transceiver.fn = &pn512_impl; + + //Init variables + memset(&pPN512->config.initiators, 0, sizeof(nfc_tech_t)); + memset(&pPN512->config.targets, 0, sizeof(nfc_tech_t)); + pPN512->timeout = -1; + pPN512->nextFrameMode = pn512_transceive_mode_transceive; + + pn512_hw_init(pPN512); + pn512_registers_init(pPN512); //Cannot switch page now + pn512_cmd_init(pPN512); + + pn512_cmd_exec(pPN512, PN512_CMD_SOFTRST); + pn512_cmd_wait_idle(pPN512, -1); + + //pn512_registers_init(pPN512); + //Put into known state + pn512_registers_reset(pPN512); + + pPN512->transceive.mode = pn512_transceive_mode_idle; + + pn512_irq_clear(pPN512, PN512_IRQ_ALL); + pn512_fifo_clear(pPN512); + pn512_cmd_exec(pPN512, PN512_CMD_IDLE); + pn512_cmd_wait_idle(pPN512, -1); + + pn512_rf_field_switch_off(pPN512); + + //Required for polling loop + srand(4242); + +#if NFC_PN512_SELFTEST // Self test + pn512_cmd_exec(pPN512, PN512_CMD_SOFTRST); + pn512_cmd_wait_idle(pPN512, -1); + + const uint8_t null_array_buf[25] = {0}; //FIXME + ac_buffer_t null_array; + ac_buffer_init(&null_array, null_array_buf, 25); + + //Perform self test + pn512_fifo_write(pPN512, &null_array); + pn512_cmd_exec(pPN512, PN512_CMD_CONFIG); + while (pn512_cmd_get(pPN512) != PN512_CMD_IDLE); + pn512_register_write(pPN512, PN512_REG_AUTOTEST, 0x09); + + ac_buffer_init(&null_array, null_array_buf, 1); + + pn512_fifo_write(pPN512, &null_array); + pn512_cmd_exec(pPN512, PN512_CMD_CRC); + while (pn512_cmd_get(pPN512) != PN512_CMD_IDLE); + + DBGX_ENTER(); + NFC_DBG("Test result:"); + while (pn512_fifo_length(pPN512)) { + ac_buffer_builder_t read_byte; + ac_buffer_builder_init(&read_byte, null_array_buf, 1); + + pn512_fifo_read(pPN512, &read_byte); + DBGX("%02x ", null_array_buf[0]); + } + DBGX("\n"); + DBGX_LEAVE(); +#endif + + r = pn512_register_read(pPN512, PN512_REG_VERSION); + + NFC_DBG_BLOCK( + NFC_DBG("PN512 version %02x", r); + ) + + if ((r != 0x82) && (r != 0xB1) && (r != 0xB2)) { + return NFC_ERR_UNSUPPORTED; //PN512 not found + } + + return NFC_OK; +} + +/** Get pointer to nfc_transceiver_t structure + * \param pPN512 pointer to pn512_t instance + * \return pointer to initialized nfc_transceiver_t instance + */ +nfc_transceiver_t *pn512_get_transceiver(pn512_t *pPN512) +{ + return &pPN512->transceiver; +} + +void pn512_set_protocols(nfc_transceiver_t *pTransceiver, nfc_tech_t initiators, nfc_tech_t targets, polling_options_t options) +{ + pn512_t *pPN512 = (pn512_t *) pTransceiver; + //If different, reconfigure + if (memcmp(&initiators, &pPN512->config.initiators, sizeof(nfc_tech_t)) || memcmp(&targets, &pPN512->config.targets, sizeof(nfc_tech_t))) { + pPN512->config.initiators = initiators; + if (memcmp(&targets, &pPN512->config.targets, sizeof(nfc_tech_t))) { + pPN512->config.targets = targets; + pn512_poll_setup(pPN512); + } + pTransceiver->initiator_ntarget = false; + memset(&pTransceiver->active_tech, 0, sizeof(nfc_tech_t)); + } + pPN512->config.options = options; +} + +void pn512_poll(nfc_transceiver_t *pTransceiver) +{ + pn512_t *pPN512 = (pn512_t *) pTransceiver; + pPN512->nextFrameMode = pn512_transceive_mode_transceive; + pn512_poll_hw(pPN512, pn512_transceiver_callback); +} + +void pn512_set_crc(nfc_transceiver_t *pTransceiver, bool crc_out, bool crc_in) +{ + pn512_t *pPN512 = (pn512_t *) pTransceiver; + pn512_framing_crc_set(pPN512, crc_out, crc_in); +} + +void pn512_set_timeout(nfc_transceiver_t *pTransceiver, int timeout) +{ + pn512_t *pPN512 = (pn512_t *) pTransceiver; + pPN512->timeout = timeout; +} + +void pn512_set_transceive_options(nfc_transceiver_t *pTransceiver, bool transmit, bool receive, bool repoll) +{ + pn512_t *pPN512 = (pn512_t *) pTransceiver; + if (transmit && receive) { + pPN512->nextFrameMode = pn512_transceive_mode_transceive; + } else if (transmit && repoll) { + pPN512->nextFrameMode = pn512_transceive_mode_transmit_and_target_autocoll; + } else if (transmit) { + pPN512->nextFrameMode = pn512_transceive_mode_transmit; + } else if (receive) { + pPN512->nextFrameMode = pn512_transceive_mode_receive; + } else { + pPN512->nextFrameMode = pn512_transceive_mode_target_autocoll; + } +} + +void pn512_set_transceive_framing(nfc_transceiver_t *pTransceiver, nfc_framing_t framing) +{ + pn512_t *pPN512 = (pn512_t *) pTransceiver; + pn512_framing_set(pPN512, framing); + + //Switch NFC tech if NFC DEP + if (pTransceiver->active_tech.nfc_nfc_dep_a + || pTransceiver->active_tech.nfc_nfc_dep_f_212 + || pTransceiver->active_tech.nfc_nfc_dep_f_424) { + //FIXME + pTransceiver->active_tech.nfc_nfc_dep_a = 0; + pTransceiver->active_tech.nfc_nfc_dep_f_212 = 0; + pTransceiver->active_tech.nfc_nfc_dep_f_424 = 0; + switch (framing) { + case nfc_framing_target_a_106: + case nfc_framing_initiator_a_106: + pTransceiver->active_tech.nfc_nfc_dep_a = 1; + break; + case nfc_framing_target_f_212: + case nfc_framing_initiator_f_212: + pTransceiver->active_tech.nfc_nfc_dep_f_212 = 1; + break; + case nfc_framing_target_f_424: + case nfc_framing_initiator_f_424: + pTransceiver->active_tech.nfc_nfc_dep_f_424 = 1; + break; + default: + break; + } + } +} + +void pn512_set_write(nfc_transceiver_t *pTransceiver, ac_buffer_t *pWriteBuf) +{ + pn512_t *pPN512 = (pn512_t *) pTransceiver; + if (pWriteBuf == NULL) { + ac_buffer_init(&pPN512->writeBuf, NULL, 0); + return; + } + ac_buffer_dup(&pPN512->writeBuf, pWriteBuf); +} + +ac_buffer_t *pn512_get_read(nfc_transceiver_t *pTransceiver) +{ + pn512_t *pPN512 = (pn512_t *) pTransceiver; + return ac_buffer_builder_buffer(&pPN512->readBufBldr); +} + +void pn512_set_last_byte_length(nfc_transceiver_t *pTransceiver, size_t lastByteLength) +{ + pn512_t *pPN512 = (pn512_t *) pTransceiver; + if ((lastByteLength > 8) || (lastByteLength == 0)) { + lastByteLength = 8; + } + pPN512->writeLastByteLength = lastByteLength; +} + +void pn512_set_first_byte_align(nfc_transceiver_t *pTransceiver, size_t firstByteAlign) +{ + pn512_t *pPN512 = (pn512_t *) pTransceiver; + firstByteAlign &= 0x7; + pPN512->readFirstByteAlign = firstByteAlign; +} + +size_t pn512_get_last_byte_length(nfc_transceiver_t *pTransceiver) +{ + pn512_t *pPN512 = (pn512_t *) pTransceiver; + return pPN512->readLastByteLength; +} + +void pn512_transceive(nfc_transceiver_t *pTransceiver) +{ + pn512_t *pPN512 = (pn512_t *) pTransceiver; + pn512_transceive_hw(pPN512, pPN512->nextFrameMode, pn512_transceiver_callback); + pPN512->nextFrameMode = pn512_transceive_mode_transceive; +} + +void pn512_abort(nfc_transceiver_t *pTransceiver) +{ + pn512_t *pPN512 = (pn512_t *) pTransceiver; + nfc_scheduler_dequeue_task(&pTransceiver->scheduler, true, &pPN512->transceiver.task); +} + +void pn512_close(nfc_transceiver_t *pTransceiver) +{ + //pn512_t* pPN512 = (pn512_t*) pTransceiver; + (void) pTransceiver; + //TODO + return; +} + +void pn512_sleep(nfc_transceiver_t *pTransceiver, bool sleep) +{ + pn512_t *pPN512 = (pn512_t *) pTransceiver; + + if (sleep) { + pn512_register_write(pPN512, PN512_REG_COMMAND, 0x30); //Receiver off + soft power down + } else { + pn512_register_write(pPN512, PN512_REG_COMMAND, 0x00); + while (pn512_register_read(pPN512, PN512_REG_COMMAND) & 0x10); + } +} + +void pn512_transceiver_callback(pn512_t *pPN512, nfc_err_t ret) +{ + transceiver_callback(&pPN512->transceiver, ret); +} + +/** + * @} + * @} + * */ diff --git a/connectivity/drivers/nfc/PN512/source/transceiver/pn512.h b/connectivity/drivers/nfc/PN512/source/transceiver/pn512.h new file mode 100644 index 0000000..9af06b2 --- /dev/null +++ b/connectivity/drivers/nfc/PN512/source/transceiver/pn512.h @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2013-2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + */ +/** + * \file pn512.h + * \copyright Copyright (c) ARM Ltd 2013 + * \author Donatien Garnier + */ + +#ifndef PN512_H_ +#define PN512_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "stack/nfc_common.h" +#include "transceiver/transceiver.h" + +#include "pn512_types.h" +#include "pn512_callback.h" + +typedef enum __pn512_state { + pn512_state_ready, + pn512_state_target_autocoll, + pn512_state_initiator_transceive_first_frame, + pn512_state_transceive, + pn512_state_transceive_last_frame, +} pn512_state_t; + +typedef enum __pn512_transceive_mode { + pn512_transceive_mode_idle, + pn512_transceive_mode_target_autocoll, + pn512_transceive_mode_transmit, + pn512_transceive_mode_transmit_and_target_autocoll, + pn512_transceive_mode_transceive, + pn512_transceive_mode_receive, +} pn512_transceive_mode_t; + +struct __pn512 { + nfc_transceiver_t transceiver; + //Impl specific + pn512_registers_t registers; + bool rf_on; + struct { + bool out; + bool in; + } crc; + int timeout; + + struct { + nfc_tech_t initiators; + nfc_tech_t targets; + polling_options_t options; + } config; + + //Transceive options + pn512_transceive_mode_t nextFrameMode; + + nfc_framing_t framing; + uint16_t irqsEn; + uint8_t payload[256]; //Incoming buffer + + ac_buffer_builder_t readBufBldr; + ac_buffer_t writeBuf; + + uint8_t readFirstByteAlign; + uint8_t readLastByteLength; + uint8_t writeLastByteLength; + + //Task parameters + struct { + //Polling + struct { + enum { + pn512_polling_state_start_listening, + + pn512_polling_state_listen_wait_for_remote_field, + pn512_polling_state_listen_anticollision, + + pn512_polling_state_listen_no_target_found, + + pn512_polling_state_start_polling, + + pn512_polling_state_rf_collision_avoidance, // TID + n × TRFW, n is random, TID>4096/(13.56E6) ~ 302.06us, TRFW=51/(13.56E6) ~ 37.76us + pn512_polling_state_polling_nfc_a_start, + pn512_polling_state_polling_nfc_a_gt, // guard time nfc a >= 5.0 ms + pn512_polling_state_polling_nfc_a_anticollision, // polling for nfc a + pn512_polling_state_polling_nfc_b_start, + pn512_polling_state_polling_nfc_b_gt, // guard time nfc b >= 5.0 ms + pn512_polling_state_polling_nfc_b_anticollision, // polling for nfc b + pn512_polling_state_polling_nfc_f_start, + pn512_polling_state_polling_nfc_f_gt, // guard time nfc f >= 20 ms + pn512_polling_state_polling_nfc_f_anticollision, // polling for nfc f + + pn512_polling_state_finish_polling, + + } state; + + pn512_cb_t cb; + } poll; + struct { + pn512_cb_t cb; + pn512_transceive_mode_t mode; + } transceive; + struct { + pn512_cb_t cb; + } rf; + struct { + union { + // ISO A + struct { + bool more_targets; // Collision detected + uint8_t cascade_level; + uint8_t cln[5]; + uint8_t valid_bits; // valid bits within cascade level + } iso_a; + // ISO B + struct { + bool more_targets; // Collision detected + uint8_t slots_num_exponent; + uint8_t slot_number; + bool found_one; + } iso_b; + }; + pn512_cb_t cb; + } anticollision; + }; + +}; + +nfc_err_t pn512_init(pn512_t *pPN512, nfc_transport_t *pTransport, nfc_scheduler_timer_t *pTimer); + +nfc_transceiver_t *pn512_get_transceiver(pn512_t *pPN512); + +#ifdef __cplusplus +} +#endif + +#endif /* PN512_H_ */ diff --git a/connectivity/drivers/nfc/PN512/source/transceiver/pn512_callback.h b/connectivity/drivers/nfc/PN512/source/transceiver/pn512_callback.h new file mode 100644 index 0000000..2ab8c3d --- /dev/null +++ b/connectivity/drivers/nfc/PN512/source/transceiver/pn512_callback.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2015-2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + */ +/** + * \file pn512_callback.h + * \copyright Copyright (c) ARM Ltd 2015 + * \author Donatien Garnier + */ + +#ifndef PN512_CALLBACK_H_ +#define PN512_CALLBACK_H_ + +#include "stack/nfc_common.h" +#include "pn512_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void (*pn512_cb_t)(pn512_t *pPN512, nfc_err_t ret); + +#ifdef __cplusplus +} +#endif + +#endif /* PN512_CALLBACK_H_ */ diff --git a/connectivity/drivers/nfc/PN512/source/transceiver/pn512_cmd.c b/connectivity/drivers/nfc/PN512/source/transceiver/pn512_cmd.c new file mode 100644 index 0000000..34bfac1 --- /dev/null +++ b/connectivity/drivers/nfc/PN512/source/transceiver/pn512_cmd.c @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2013-2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + */ +/** + * \file pn512_cmd.c + * \copyright Copyright (c) ARM Ltd 2013 + * \author Donatien Garnier + * \details Format and execute PN512 commands + * \internal + */ + +#define __DEBUG__ 0 +#ifndef __MODULE__ +#define __MODULE__ "pn512_cmd.c" +#endif +#include "stack/nfc_errors.h" + +#include "pn512_cmd.h" + +#define PN512_FIFO_SIZE 64 + +#include "pn512.h" +#include "pn512_registers.h" +#include "pn512_irq.h" +#include "pn512_hw.h" + +/** \addtogroup PN512 + * \internal + * @{ + * \name Commands + * @{ + */ + +/** \internal Initialize underlying pn512_cmd_t structure + * \param pPN512 pointer to pn512_t structure + */ +void pn512_cmd_init(pn512_t *pPN512) +{ + (void) pPN512; +} + +//Fifo read / write +/** \internal Write bytes to FIFO + * \param pPN512 pointer to pn512_t structure + * \param pData buffer to write + */ +void pn512_fifo_write(pn512_t *pPN512, ac_buffer_t *pData) +{ + uint8_t fifo_space = pn512_fifo_space(pPN512); //Do not call this fn twice + size_t len = ac_buffer_reader_readable(pData); + len = MIN(fifo_space, len); + + pn512_register_switch_page(pPN512, PN512_REG_FIFODATA); + pn512_hw_write_buffer(pPN512, PN512_REG_FIFODATA, pData, len); +} + +/** \internal Read bytes from FIFO + * \param pPN512 pointer to pn512_t structure + * \param pData buffer in which to read + */ +void pn512_fifo_read(pn512_t *pPN512, ac_buffer_builder_t *pData) +{ + uint8_t fifo_len = pn512_fifo_length(pPN512); //Do not call this fn twice + size_t len = ac_buffer_builder_writable(pData); + len = MIN(fifo_len, len); + + pn512_register_switch_page(pPN512, PN512_REG_FIFODATA); + pn512_hw_read_buffer(pPN512, PN512_REG_FIFODATA, pData, len); +} + +/** \internal Clear FIFO + * Removes any bytes left in FIFO + * \param pPN512 pointer to pn512_t structure + */ +void pn512_fifo_clear(pn512_t *pPN512) +{ + pn512_register_write(pPN512, PN512_REG_FIFOLEVEL, 0x80); //Flush FIFO +} + +/** \internal Get space in FIFO + * \param pPN512 pointer to pn512_t structure + * \return number of bytes that can be written to FIFO + */ +size_t pn512_fifo_space(pn512_t *pPN512) +{ + return PN512_FIFO_SIZE - pn512_register_read(pPN512, PN512_REG_FIFOLEVEL); +} + +/** \internal Get FIFO length + * \param pPN512 pointer to pn512_t structure + * \return number of bytes that can be read from FIFO + */ +size_t pn512_fifo_length(pn512_t *pPN512) +{ + return pn512_register_read(pPN512, PN512_REG_FIFOLEVEL); +} + +/** \internal Execute command + * \param pPN512 pointer to pn512_t structure + * \param cmd PN512 command to execute + */ +void pn512_cmd_exec(pn512_t *pPN512, uint8_t cmd) +{ + pn512_register_write(pPN512, PN512_REG_COMMAND, cmd); +} + +/** \internal Wait for command completion + * \param pPN512 pointer to pn512_t structure + * \param timeout timeout in milliseconds or -1 for blocking mode + * \return NFC_OK on success or NFC_ERR_TIMEOUT on timeout + */ +nfc_err_t pn512_cmd_wait_idle(pn512_t *pPN512, int timeout) +{ + (void) timeout; + while (pn512_cmd_get(pPN512) != PN512_CMD_IDLE) { + + } + return NFC_OK; +} + + +/** \internal Read executed command + * \param pPN512 pointer to pn512_t structure + * \return PN512 command being executed + */ +uint8_t pn512_cmd_get(pn512_t *pPN512) +{ + return pn512_register_read(pPN512, PN512_REG_COMMAND) & PN512_CMD_REG_MASK; +} + +/** + * @} + * @} + * */ + diff --git a/connectivity/drivers/nfc/PN512/source/transceiver/pn512_cmd.h b/connectivity/drivers/nfc/PN512/source/transceiver/pn512_cmd.h new file mode 100644 index 0000000..ec1d553 --- /dev/null +++ b/connectivity/drivers/nfc/PN512/source/transceiver/pn512_cmd.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2013-2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + */ +/** + * \file pn512_cmd.h + * \copyright Copyright (c) ARM Ltd 2013 + * \author Donatien Garnier + */ + +#ifndef PN512_CMD_H_ +#define PN512_CMD_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "stack/nfc_common.h" +#include "pn512.h" + +#define PN512_CMD_IDLE 0x00 //No action, cancels current command execution +#define PN512_CMD_MEM 0x01 //Stores 25 bytes into the internal buffer +#define PN512_CMD_CONFIG 0x01 //Configures the PN512 for FeliCa, MIFARE and NFCIP-1 communication +#define PN512_CMD_RNDIDG 0x02 //Generates a 10-byte random ID number +#define PN512_CMD_CRC 0x03 //Activates the CRC coprocessor or performs a self test +#define PN512_CMD_TRANSMIT 0x04 //Transmits data from the FIFO buffer +#define PN512_CMD_NOCHANGE 0x07 //No command change +#define PN512_CMD_RECEIVE 0x08 //Activates the receiver circuits +#define PN512_CMD_TRANSCEIVE 0x0C //Transmits data from FIFO buffer to antenna and automatically activates the receiver after transmission +#define PN512_CMD_AUTOCOLL 0x0D //Handles FeliCa polling (Card Operation mode only) and MIFARE anticollision (Card Operation mode only) +#define PN512_CMD_MFAUTH 0x0E //Performs the MIFARE standard authentication as a reader +#define PN512_CMD_SOFTRST 0x0F //Resets the PN512 + +#define PN512_CMD_REG_MASK 0x0F + +void pn512_cmd_init(pn512_t *pPN512); + +//Fifo read / write + +void pn512_fifo_write(pn512_t *pPN512, ac_buffer_t *pData); +void pn512_fifo_read(pn512_t *pPN512, ac_buffer_builder_t *pData); + +//Fifo clear +void pn512_fifo_clear(pn512_t *pPN512); + +//Fifo bytes read +size_t pn512_fifo_space(pn512_t *pPN512); +size_t pn512_fifo_length(pn512_t *pPN512); + +//Execute command +void pn512_cmd_exec(pn512_t *pPN512, uint8_t cmd); + +//Wait for command completion +nfc_err_t pn512_cmd_wait_idle(pn512_t *pPN512, int timeout); + +//Read executed command +uint8_t pn512_cmd_get(pn512_t *pPN512); + + +#ifdef __cplusplus +} +#endif + +#endif /* PN512_CMD_H_ */ diff --git a/connectivity/drivers/nfc/PN512/source/transceiver/pn512_hw.c b/connectivity/drivers/nfc/PN512/source/transceiver/pn512_hw.c new file mode 100644 index 0000000..922c078 --- /dev/null +++ b/connectivity/drivers/nfc/PN512/source/transceiver/pn512_hw.c @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2013-2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + */ +/** + * \file pn512_hw.c + * \copyright Copyright (c) ARM Ltd 2013 + * \author Donatien Garnier + * \details Format and execute PN512 frames + */ + +#include "stack/nfc_errors.h" + +#include "pn512_hw.h" + +//Platform specific +#include "platform/nfc_transport.h" + + + +/** \addtogroup PN512 + * \internal + * @{ + * \name Hardware + * @{ + */ + +/** \internal Initialize underlying pn512_hw_t structure + * \param pPN512 pointer to pn512_t structure + */ +void pn512_hw_init(pn512_t *pPN512) +{ + //Nothing to init in this implementation + (void) pPN512; +} + + +/** + * @} + * @} + * */ + diff --git a/connectivity/drivers/nfc/PN512/source/transceiver/pn512_hw.h b/connectivity/drivers/nfc/PN512/source/transceiver/pn512_hw.h new file mode 100644 index 0000000..b193517 --- /dev/null +++ b/connectivity/drivers/nfc/PN512/source/transceiver/pn512_hw.h @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2013-2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + */ +/** + * \file pn512_hw.h + * \copyright Copyright (c) ARM Ltd 2013 + * \author Donatien Garnier + */ + +#ifndef PN512_HW_H_ +#define PN512_HW_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "stack/nfc_common.h" +#include "pn512.h" + +//Utility for transport: SPI address read/write +#define PN512_SPI_ADDR_R(x) ((1<<7) | ((x) << 1)) +#define PN512_SPI_ADDR_W(x) ((0<<7) | ((x) << 1)) + +void pn512_hw_init(pn512_t *pPN512); + +/** \internal Write bytes at the specified address on the underlying transport link + * \param pPN512 pointer to pn512_t structure + * \param addr address at which to write + * \param buf buffer to write + * \param len length of buffer + */ +static inline void pn512_hw_write(pn512_t *pPN512, uint8_t addr, uint8_t *buf, size_t len) +{ + nfc_transport_write(((nfc_transceiver_t *)pPN512)->pTransport, addr, buf, len); +} + +/** \internal Read bytes from the specified address on the underlying transport link + * \param pPN512 pointer to pn512_t structure + * \param addr address from which to read + * \param buf buffer to read + * \param len length of buffer + */ +static inline void pn512_hw_read(pn512_t *pPN512, uint8_t addr, uint8_t *buf, size_t len) +{ + nfc_transport_read(((nfc_transceiver_t *)pPN512)->pTransport, addr, buf, len); +} + +static inline void pn512_hw_write_buffer(pn512_t *pPN512, uint8_t addr, ac_buffer_t *pData, size_t len) +{ + while (len > 0) { + if (ac_buffer_reader_readable(pData) == 0) { + return; + } + size_t cpyLen = MIN(len, ac_buffer_reader_current_buffer_length(pData)); + nfc_transport_write(((nfc_transceiver_t *)pPN512)->pTransport, addr, ac_buffer_reader_current_buffer_pointer(pData), cpyLen); + ac_buffer_read_n_skip(pData, cpyLen); + len -= cpyLen; + } +} + +static inline void pn512_hw_read_buffer(pn512_t *pPN512, uint8_t addr, ac_buffer_builder_t *pData, size_t len) +{ + while (len > 0) { + if (ac_buffer_builder_writable(pData) == 0) { + return; + } + //Read payload + size_t cpyLen = MIN(len, ac_buffer_builder_space(pData)); + nfc_transport_read(((nfc_transceiver_t *)pPN512)->pTransport, addr, ac_buffer_builder_write_position(pData), cpyLen); + ac_buffer_builder_write_n_skip(pData, cpyLen); + len -= cpyLen; + } +} + +#ifdef __cplusplus +} +#endif + +#endif /* PN512_HW_H_ */ diff --git a/connectivity/drivers/nfc/PN512/source/transceiver/pn512_internal.h b/connectivity/drivers/nfc/PN512/source/transceiver/pn512_internal.h new file mode 100644 index 0000000..ffff027 --- /dev/null +++ b/connectivity/drivers/nfc/PN512/source/transceiver/pn512_internal.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2013-2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + */ +/** + * \file pn512_internal.h + * \copyright Copyright (c) ARM Ltd 2013 + * \author Donatien Garnier + */ + +#ifndef PN512_INTERNAL_H_ +#define PN512_INTERNAL_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "stack/nfc_common.h" +#include "transceiver/transceiver_internal.h" + +#include "pn512.h" +#include "pn512_callback.h" + +//Public +void pn512_set_protocols(nfc_transceiver_t *pTransceiver, nfc_tech_t initiators, nfc_tech_t targets, polling_options_t options); +void pn512_poll(nfc_transceiver_t *pTransceiver); +void pn512_set_crc(nfc_transceiver_t *pTransceiver, bool crc_out, bool crc_in); +void pn512_set_timeout(nfc_transceiver_t *pTransceiver, int timeout); +void pn512_set_transceive_options(nfc_transceiver_t *pTransceiver, bool transmit, bool receive, bool repoll); +void pn512_set_transceive_framing(nfc_transceiver_t *pTransceiver, nfc_framing_t framing); +void pn512_set_write(nfc_transceiver_t *pTransceiver, ac_buffer_t *pWriteBuf); +ac_buffer_t *pn512_get_read(nfc_transceiver_t *pTransceiver); +size_t pn512_get_last_byte_length(nfc_transceiver_t *pTransceiver); +void pn512_set_last_byte_length(nfc_transceiver_t *pTransceiver, size_t lastByteLength); +void pn512_set_first_byte_align(nfc_transceiver_t *pTransceiver, size_t firstByteAlign); +void pn512_abort(nfc_transceiver_t *pTransceiver); +void pn512_transceive(nfc_transceiver_t *pTransceiver); +void pn512_close(nfc_transceiver_t *pTransceiver); +void pn512_sleep(nfc_transceiver_t *pTransceiver, bool sleep); + +void pn512_transceiver_callback(pn512_t *pPN512, nfc_err_t ret); + +static inline void pn512_rf_callback(pn512_t *pPN512, nfc_err_t ret) +{ + pPN512->rf.cb(pPN512, ret); +} + +static inline void pn512_poll_callback(pn512_t *pPN512, nfc_err_t ret) +{ + pPN512->poll.cb(pPN512, ret); +} + +static inline void pn512_anticollision_callback(pn512_t *pPN512, nfc_err_t ret) +{ + pPN512->anticollision.cb(pPN512, ret); +} + +static inline void pn512_transceive_callback(pn512_t *pPN512, nfc_err_t ret) +{ + pPN512->transceive.cb(pPN512, ret); +} + + + +#ifdef __cplusplus +} +#endif + +#endif /* PN512_INTERNAL_H_ */ diff --git a/connectivity/drivers/nfc/PN512/source/transceiver/pn512_irq.c b/connectivity/drivers/nfc/PN512/source/transceiver/pn512_irq.c new file mode 100644 index 0000000..1c8c82e --- /dev/null +++ b/connectivity/drivers/nfc/PN512/source/transceiver/pn512_irq.c @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2013-2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + */ +/** + * \file pn512_irq.c + * \copyright Copyright (c) ARM Ltd 2013 + * \author Donatien Garnier + * \details Manage PN512 interrupt requests + */ + +#define __DEBUG__ 0 +#ifndef __MODULE__ +#define __MODULE__ "pn512_irq.c" +#endif +#include "stack/nfc_errors.h" + +#include "pn512_irq.h" +#include "pn512_registers.h" +#include "pn512_hw.h" +#include "pn512.h" + +/** \addtogroup PN512 + * \internal + * @{ + * \name Interrupts + * @{ + */ + + + + + + +/** + * @} + * @} + * */ diff --git a/connectivity/drivers/nfc/PN512/source/transceiver/pn512_irq.h b/connectivity/drivers/nfc/PN512/source/transceiver/pn512_irq.h new file mode 100644 index 0000000..9c56544 --- /dev/null +++ b/connectivity/drivers/nfc/PN512/source/transceiver/pn512_irq.h @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2013-2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + */ +/** + * \file pn512_irq.h + * \copyright Copyright (c) ARM Ltd 2013 + * \author Donatien Garnier + */ + +#ifndef PN512_IRQ_H_ +#define PN512_IRQ_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "stack/nfc_common.h" +#include "pn512.h" +#include "pn512_registers.h" + +#define PN512_IRQ_TX (1<<6) +#define PN512_IRQ_RX (1<<5) +#define PN512_IRQ_IDLE (1<<4) +#define PN512_IRQ_HIGH_ALERT (1<<3) +#define PN512_IRQ_LOW_ALERT (1<<2) +#define PN512_IRQ_ERR (1<<1) +#define PN512_IRQ_TIMER (1<<0) + +#define PN512_IRQ_SIGIN (1<<(4+8)) +#define PN512_IRQ_MODE (1<<(3+8)) +#define PN512_IRQ_CRC (1<<(2+8)) +#define PN512_IRQ_RF_ON (1<<(1+8)) +#define PN512_IRQ_RF_OFF (1<<(0+8)) + +#define PN512_IRQ_NONE 0x00 +#define PN512_IRQ_ALL 0x1F7F + +#define PN512_REG_COMIEN_MASK 0x7F +#define PN512_REG_COMIEN_VAL 0x00 + +#define PN512_REG_DIVIEN_MASK 0x1F +#define PN512_REG_DIVIEN_VAL 0x80 + +#define PN512_REG_COMIRQ_MASK 0x7F +#define PN512_REG_COMIRQ_CLEAR 0x00 + +#define PN512_REG_DIVIRQ_MASK 0x1F +#define PN512_REG_DIVIRQ_CLEAR 0x00 + +/** \internal Set IRQ enable registers + * \param pPN512 pointer to pn512_t structure + * \param irqs MSB is DIVIEN value, LSB is COMIEN value + */ +static inline void pn512_irq_set(pn512_t *pPN512, uint16_t irqs) //ORed +{ + pn512_register_write(pPN512, PN512_REG_COMIEN, PN512_REG_COMIEN_VAL | (PN512_REG_COMIEN_MASK & (irqs & 0xFF))); + pn512_register_write(pPN512, PN512_REG_DIVIEN, PN512_REG_DIVIEN_VAL | (PN512_REG_DIVIEN_MASK & (irqs >> 8))); + pPN512->irqsEn = irqs; +} + +/** \internal Get IRQ enable registers + * \param pPN512 pointer to pn512_t structure + * \return MSB is DIVIEN value, LSB is COMIEN value + */ +static inline uint16_t pn512_irq_enabled(pn512_t *pPN512) //ORed +{ + return pPN512->irqsEn /*(pn512_register_read(pPN512, PN512_REG_COMIEN_VAL) & PN512_REG_COMIEN_MASK) + | ((pn512_register_read(pPN512, PN512_REG_DIVIEN_VAL) & PN512_REG_DIVIEN_MASK) << 8)*/; +} + +/** \internal Get IRQ status registers (masked with enabled IRQ register) + * \param pPN512 pointer to pn512_t structure + * \return MSB is DIVIRQ value, LSB is COMIRQ value + */ +static inline uint16_t pn512_irq_get(pn512_t *pPN512) //ORed +{ + return ((pn512_register_read(pPN512, PN512_REG_COMIRQ) & PN512_REG_COMIEN_MASK) + | ((pn512_register_read(pPN512, PN512_REG_DIVIRQ) & PN512_REG_DIVIEN_MASK) << 8)) & pPN512->irqsEn; +} + +/** \internal Clear some interrupts + * \param pPN512 pointer to pn512_t structure + * \param irqs MSB is DIVIEN value, LSB is COMIEN value + */ +static inline void pn512_irq_clear(pn512_t *pPN512, uint16_t irqs) +{ + pn512_register_write(pPN512, PN512_REG_COMIRQ, PN512_REG_COMIRQ_CLEAR | (PN512_REG_COMIRQ_MASK & (irqs & 0xFF))); + pn512_register_write(pPN512, PN512_REG_DIVIRQ, PN512_REG_DIVIRQ_CLEAR | (PN512_REG_DIVIRQ_MASK & (irqs >> 8))); +} + +#ifdef __cplusplus +} +#endif + +#endif /* PN512_IRQ_H_ */ diff --git a/connectivity/drivers/nfc/PN512/source/transceiver/pn512_poll.c b/connectivity/drivers/nfc/PN512/source/transceiver/pn512_poll.c new file mode 100644 index 0000000..ad349c5 --- /dev/null +++ b/connectivity/drivers/nfc/PN512/source/transceiver/pn512_poll.c @@ -0,0 +1,1268 @@ +/* + * Copyright (c) 2014-2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + */ +/** + * \file pn512_poll.c + * \copyright Copyright (c) ARM Ltd 2014 + * \author Donatien Garnier + */ + +#define __DEBUG__ 0 +#ifndef __MODULE__ +#define __MODULE__ "pn512_poll.c" +#endif + +#include "stack/nfc_errors.h" + +#include "pn512.h" +#include "pn512_poll.h" +#include "pn512_transceive.h" +#include "pn512_registers.h" +#include "pn512_rf.h" +#include "pn512_cmd.h" +#include "pn512_internal.h" + +#define TIMEOUT 1000 + +static void pn512_target_anticollision(pn512_t *pPN512, pn512_cb_t cb); +static void pn512_initiator_isoa_anticollision(pn512_t *pPN512, pn512_cb_t cb); + +static inline bool pn512_config_initiator(pn512_t *pPN512) +{ + return (pPN512->config.initiators.nfc_iso_dep_a | pPN512->config.initiators.nfc_iso_dep_b | + pPN512->config.initiators.nfc_nfc_dep_a | pPN512->config.initiators.nfc_nfc_dep_f_212 | pPN512->config.initiators.nfc_nfc_dep_f_424 | + pPN512->config.initiators.nfc_type1 | pPN512->config.initiators.nfc_type2 | pPN512->config.initiators.nfc_type3) != 0; +} + +static inline bool pn512_config_target(pn512_t *pPN512) +{ + return (pPN512->config.targets.nfc_iso_dep_a | pPN512->config.targets.nfc_iso_dep_b | + pPN512->config.targets.nfc_nfc_dep_a | pPN512->config.targets.nfc_nfc_dep_f_212 | pPN512->config.initiators.nfc_nfc_dep_f_424 | + pPN512->config.targets.nfc_type1 | pPN512->config.targets.nfc_type2 | pPN512->config.targets.nfc_type3) != 0; +} + +void pn512_target_anticollision_complete(pn512_t *pPN512, nfc_err_t ret) +{ + + bool iso14443a = pPN512->config.targets.nfc_type2 || pPN512->config.targets.nfc_iso_dep_a || pPN512->config.targets.nfc_nfc_dep_a; //We do not support type 1 card emulation so irrelevant + bool felica = pPN512->config.targets.nfc_type3 || pPN512->config.targets.nfc_nfc_dep_f_212 || pPN512->config.targets.nfc_nfc_dep_f_424; + + nfc_transceiver_t *pTransceiver = &pPN512->transceiver; + if (ret) { + NFC_WARN("Returned %d", ret); + pn512_anticollision_callback(pPN512, ret); + return; + } + + //Data available in FIFO + if (pPN512->readLastByteLength != 8) { //We should receive a full byte + NFC_WARN("Not enough data in FIFO"); + pn512_anticollision_callback(pPN512, NFC_ERR_PROTOCOL); + return; + } + + //If successful, update state machine + if (iso14443a && felica) { + //Update current protocol accordingly + uint8_t txmode = pn512_register_read(pPN512, PN512_REG_TXMODE); + if ((txmode & 0x03) == 0x00) { + pn512_framing_set(pPN512, nfc_framing_target_a_106); + + NFC_DBG("A 106"); + felica = false; + } else if ((txmode & 0x03) == 0x02) { + if ((txmode & 0x70) == 0x20) { + //424kbps + NFC_DBG("F 424"); + pn512_framing_set(pPN512, nfc_framing_target_f_424); + } else { + //212kbps + NFC_DBG("F 212"); + pn512_framing_set(pPN512, nfc_framing_target_f_212); + } + iso14443a = false; + } else { + //Unsupported mode, exit + pn512_anticollision_callback(pPN512, NFC_ERR_UNSUPPORTED); + return; + } + } + + if (iso14443a) { + if (ac_buffer_reader_readable(ac_buffer_builder_buffer(&pPN512->readBufBldr)) == 0) { + pn512_anticollision_callback(pPN512, NFC_ERR_PROTOCOL); + return; + } + + //Halt device, so that if anticollision is restarted it's in the correct state (cleared automatically by RF reset) + pn512_register_write(pPN512, PN512_REG_MIFNFC, 0x62 | 0x04); + + //Copy buffer to peek + ac_buffer_t readBufDup; + ac_buffer_dup(&readBufDup, ac_buffer_builder_buffer(&pPN512->readBufBldr)); + + uint8_t b0 = ac_buffer_read_nu8(&readBufDup); + + //Get first byte + //Read FIFO to see if the target was selected as NFC-DEP, ISO-DEP or proprietary (NFC Type 2) + //F0 --> NFC-DEP + //E0 --> ISO-DEP + //Anything else --> NFC Type 2 + + //First check if this could be NFC-DEP + if (pPN512->config.targets.nfc_nfc_dep_a && (b0 == 0xF0)) { + pTransceiver->active_tech.nfc_nfc_dep_a = true; + } else if (pPN512->config.targets.nfc_iso_dep_a && (b0 == 0xE0)) { + pTransceiver->active_tech.nfc_iso_dep_a = true; + } else if (pPN512->config.targets.nfc_type2) { + pTransceiver->active_tech.nfc_type2 = true; + } else { + //Unknown tech, return error + pn512_anticollision_callback(pPN512, NFC_ERR_UNSUPPORTED); + return; + } + + //Give control to higher layer + pn512_anticollision_callback(pPN512, NFC_OK); + return; + } else if (felica) { + //First check if this could be NFC-DEP + if ((pPN512->config.targets.nfc_nfc_dep_f_212 || pPN512->config.targets.nfc_nfc_dep_f_424)) { + if (pPN512->framing == nfc_framing_target_f_424) { + pTransceiver->active_tech.nfc_nfc_dep_f_424 = true; + } else { + pTransceiver->active_tech.nfc_nfc_dep_f_212 = true; + } + } else { + pn512_anticollision_callback(pPN512, NFC_ERR_UNSUPPORTED); + return; + } + } + + //NFC-IP 1 active mode is not supported by other devices so ignore it for now + pn512_anticollision_callback(pPN512, NFC_OK); +} + + +void pn512_target_anticollision(pn512_t *pPN512, pn512_cb_t cb) +{ + pPN512->anticollision.cb = cb; + + //Reset active states + pPN512->transceiver.initiator_ntarget = false; + pPN512->transceiver.active_tech.nfc_type1 = pPN512->transceiver.active_tech.nfc_type2 = pPN512->transceiver.active_tech.nfc_type3 + = pPN512->transceiver.active_tech.nfc_iso_dep_a = pPN512->transceiver.active_tech.nfc_nfc_dep_a = + pPN512->transceiver.active_tech.nfc_nfc_dep_f_212 = pPN512->transceiver.active_tech.nfc_nfc_dep_f_424 = 0; + + pn512_set_timeout((nfc_transceiver_t *)pPN512, -1); //Should only fail on RF drop + + pn512_transceive_hw(pPN512, pn512_transceive_mode_target_autocoll, pn512_target_anticollision_complete); +} + +// ISO A + +#define ISO14443A_BUF_SIZE 8 + +#define REQA 0x26 +#define SEL(n) (0x93 + (n)*2) +#define NVB(bits) ( (((2*8 + (bits))>>3)<<4) | ((bits) & 0x7) ) +#define HALTA1 0x50 +#define HALTA2 0x00 +#define CT 0x88 + +static void pn512_initiator_isoa_anticollision_reqa(pn512_t *pPN512); +static void pn512_initiator_isoa_anticollision_atqa(pn512_t *pPN512, nfc_err_t ret); +static void pn512_initiator_isoa_anticollision_cascade_1(pn512_t *pPN512); +static void pn512_initiator_isoa_anticollision_cascade_2(pn512_t *pPN512, nfc_err_t ret); +static void pn512_initiator_isoa_anticollision_cascade_3(pn512_t *pPN512, nfc_err_t ret); +static void pn512_initiator_isoa_anticollision_cascade_4(pn512_t *pPN512, nfc_err_t ret); +static void pn512_initiator_isoa_anticollision_complete(pn512_t *pPN512); + +void pn512_initiator_isoa_anticollision(pn512_t *pPN512, pn512_cb_t cb) +{ + pPN512->anticollision.cb = cb; + + // Reset transceive mode + pPN512->transceive.mode = pn512_transceive_mode_idle; + + pn512_initiator_isoa_anticollision_reqa(pPN512); +} + +void pn512_initiator_isoa_anticollision_reqa(pn512_t *pPN512) +{ + ac_buffer_builder_t *pDataOutBldr = &pPN512->readBufBldr; + ac_buffer_builder_reset(pDataOutBldr); + + pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].nfcA.uidLength = 0; + + ac_buffer_builder_write_nu8(pDataOutBldr, REQA); + pn512_set_last_byte_length((nfc_transceiver_t *)pPN512, 7); //Only 7 bits in this first command + // FIXME PN512 Anomaly: pn512_register_write(pPN512, PN512_REG_COLL, 0x00); // Set MSB to 0, to accept collisions + pn512_set_crc((nfc_transceiver_t *)pPN512, false, false); + pn512_set_timeout((nfc_transceiver_t *)pPN512, 4); + pn512_set_write((nfc_transceiver_t *)pPN512, ac_buffer_builder_buffer(pDataOutBldr)); + + pn512_transceive_hw(pPN512, pn512_transceive_mode_transceive, pn512_initiator_isoa_anticollision_atqa); +} + +void pn512_initiator_isoa_anticollision_atqa(pn512_t *pPN512, nfc_err_t ret) +{ + // Clear collisions register + // FIXME PN512 Anomaly: pn512_register_write(pPN512, PN512_REG_COLL, 0x80); // Set MSB to 1, to treat collisions as errors + + if (ret && (ret != NFC_ERR_COLLISION)) { // There might be collisions here + NFC_WARN("Did not receive ATQA: error %d", ret); + pn512_anticollision_callback(pPN512, NFC_ERR_NOPEER); + return; + } + + ac_buffer_t *pResp = pn512_get_read((nfc_transceiver_t *)pPN512); + + if (ac_buffer_reader_readable(pResp) != 2) { + NFC_WARN("Wrong length (%u bytes)", ac_buffer_reader_readable(pResp)); + pn512_anticollision_callback(pPN512, NFC_ERR_PROTOCOL); + return; + } + + NFC_DBG("Got ATQA:"); + NFC_DBG_BLOCK(ac_buffer_dump(pResp);) + + // Ignore ATQA as there can be collisions + ac_buffer_read_n_bytes(pResp, pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].nfcA.atqa, 2); + + //Start cascading + pPN512->anticollision.iso_a.cascade_level = 1; + pPN512->anticollision.iso_a.valid_bits = 0; + pPN512->anticollision.iso_a.more_targets = false; + memset(pPN512->anticollision.iso_a.cln, 0, 5); + + pn512_initiator_isoa_anticollision_cascade_1(pPN512); +} + +void pn512_initiator_isoa_anticollision_cascade_1(pn512_t *pPN512) +{ + ac_buffer_builder_t *pDataOutBldr = &pPN512->readBufBldr; + ac_buffer_builder_reset(pDataOutBldr); + + //SEL + ac_buffer_builder_write_nu8(pDataOutBldr, SEL(pPN512->anticollision.iso_a.cascade_level - 1)); //SEL: Cascade level + ac_buffer_builder_write_nu8(pDataOutBldr, NVB(pPN512->anticollision.iso_a.valid_bits)); //First NVB: Bytecount = 2, Bitcount = 0, then adapt if collision detected + + NFC_DBG("SEL - cascade level %u, %u valid bits - NVB %u", pPN512->anticollision.iso_a.cascade_level, pPN512->anticollision.iso_a.valid_bits, NVB(pPN512->anticollision.iso_a.valid_bits)); + + if (pPN512->anticollision.iso_a.valid_bits > 0) { + // Transmit first part of uid + ac_buffer_builder_write_n_bytes(pDataOutBldr, pPN512->anticollision.iso_a.cln, (pPN512->anticollision.iso_a.valid_bits >> 3) + ((pPN512->anticollision.iso_a.valid_bits & 0x7) ? 1 : 0)); + pn512_set_last_byte_length((nfc_transceiver_t *)pPN512, pPN512->anticollision.iso_a.valid_bits & 0x7); + pn512_set_first_byte_align((nfc_transceiver_t *)pPN512, pPN512->anticollision.iso_a.valid_bits & 0x7); + } + + // FIXME PN512 Anomaly: pn512_register_write(pPN512, PN512_REG_COLL, 0x00); // Set MSB to 0, to accept collisions + pn512_set_crc((nfc_transceiver_t *)pPN512, false, false); + pn512_set_timeout((nfc_transceiver_t *)pPN512, 30); + pn512_set_write((nfc_transceiver_t *)pPN512, ac_buffer_builder_buffer(pDataOutBldr)); + + + pn512_register_write(pPN512, PN512_REG_COMIRQ, 2); + NFC_DBG("IRQ status %04X", ((pn512_register_read(pPN512, PN512_REG_COMIRQ)) + | ((pn512_register_read(pPN512, PN512_REG_DIVIRQ)) << 8))); + + pn512_transceive_hw(pPN512, pn512_transceive_mode_transceive, pn512_initiator_isoa_anticollision_cascade_2); +} + +void pn512_initiator_isoa_anticollision_cascade_2(pn512_t *pPN512, nfc_err_t ret) +{ + ac_buffer_t *pResp = pn512_get_read((nfc_transceiver_t *)pPN512); + + // Load & clear collisions register + // FIXME PN512 Anomaly: pn512_register_write(pPN512, PN512_REG_COLL, 0x80); // Set MSB to 1, to treat collisions as errors + + if (ret && (ret != NFC_ERR_COLLISION)) { // There might be collisions here + NFC_WARN("Did not receive response: error %d", ret); + pn512_anticollision_callback(pPN512, ret); + return; + } + + // We should receive 5 bytes back minus all the CLn bits that we have transmitted; we ignore all bits from the first collision + size_t expected_resp_bits = (5 << 3) - pPN512->anticollision.iso_a.valid_bits; + + // Check for collision + uint8_t valid_bits = expected_resp_bits; + if (ret == NFC_ERR_COLLISION) { + uint8_t coll_reg = pn512_register_read(pPN512, PN512_REG_COLL); + + // FIXME - PN512 error + //if( !(coll_reg & 0x20) ) // bit 5 is CollPosNotValidSet + { + valid_bits = (coll_reg & 0x1f); + + if (valid_bits == 0) { + valid_bits = 32; + } + + valid_bits--; + + NFC_DBG("Collision detected, %u valid bits", valid_bits); + if (valid_bits < expected_resp_bits) { + // Collision detected + pPN512->anticollision.iso_a.more_targets = true; + } else { + valid_bits = expected_resp_bits; + } + } + } + + size_t resp_sz = (valid_bits >> 3) + ((valid_bits & 0x7) ? 1 : 0); + if (ac_buffer_reader_readable(pResp) < resp_sz) { + (void) pn512_register_read(pPN512, PN512_REG_COLL); + + NFC_WARN("Wrong length (%u instead of %u - valid bits %u)", ac_buffer_reader_readable(pResp), resp_sz, valid_bits); + pn512_anticollision_callback(pPN512, NFC_ERR_PROTOCOL); + return; + } + + // Read bytes + uint8_t bufIn[5] = {0}; + ac_buffer_read_n_bytes(pResp, bufIn + (pPN512->anticollision.iso_a.valid_bits >> 3), resp_sz); + + // Mask out valid bits that are already known + bufIn[pPN512->anticollision.iso_a.valid_bits >> 3] &= 0xff << (pPN512->anticollision.iso_a.valid_bits & 0x7); + + // Update number of valid bits + pPN512->anticollision.iso_a.valid_bits += valid_bits; + + // Mask out bits past valid bits in last byte + bufIn[pPN512->anticollision.iso_a.valid_bits >> 3] &= 0xff >> ((8 - pPN512->anticollision.iso_a.valid_bits) & 0x7); + + // Now remember bits before collision + for (size_t p = 0; p < 5; p++) { + pPN512->anticollision.iso_a.cln[p] |= bufIn[p]; + } + + // If we have all bits, then check BCC, go to next step + if (pPN512->anticollision.iso_a.valid_bits < 5 * 8) { // Collision, add a 1 at the end of known bits to resolve collision + pPN512->anticollision.iso_a.cln[pPN512->anticollision.iso_a.valid_bits >> 3] |= (1 << (pPN512->anticollision.iso_a.valid_bits & 0x7)); + pPN512->anticollision.iso_a.valid_bits++; + + // Restart first step with more valid bits + pn512_initiator_isoa_anticollision_cascade_1(pPN512); + return; + } + + //Check BCC if all bits are valid + if (pPN512->anticollision.iso_a.cln[4] != (pPN512->anticollision.iso_a.cln[0] ^ pPN512->anticollision.iso_a.cln[1] ^ pPN512->anticollision.iso_a.cln[2] ^ pPN512->anticollision.iso_a.cln[3])) { + NFC_WARN("Wrong BCC %02X != %02X", bufIn[4], bufIn[0] ^ bufIn[1] ^ bufIn[2] ^ bufIn[3]); + pn512_anticollision_callback(pPN512, NFC_ERR_COLLISION); + return; //TODO handle this properly + } + + if (pPN512->anticollision.iso_a.cln[0] == CT) { + //Not the last cascade level + if (pPN512->anticollision.iso_a.cascade_level == 3) { // not allowed + NFC_WARN("Cascade tag present in cascade level 3"); + pn512_anticollision_callback(pPN512, NFC_ERR_PROTOCOL); + return; + } + memcpy(&pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].nfcA.uid[(pPN512->anticollision.iso_a.cascade_level - 1) * 3], &pPN512->anticollision.iso_a.cln[1], 3); + pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].nfcA.uidLength += 3; + } else { + //Last cascade level + memcpy(&pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].nfcA.uid[(pPN512->anticollision.iso_a.cascade_level - 1) * 3], &pPN512->anticollision.iso_a.cln[0], 4); + pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].nfcA.uidLength += 4; + } + + ac_buffer_builder_t *pDataOutBldr = &pPN512->readBufBldr; + ac_buffer_builder_reset(pDataOutBldr); + + //Select and get SAK + ac_buffer_builder_write_nu8(pDataOutBldr, SEL(pPN512->anticollision.iso_a.cascade_level - 1)); //SEL: Cascade level + ac_buffer_builder_write_nu8(pDataOutBldr, NVB(40)); //NVB: 40 valid bits = 5 bytes + + //Transmit last 4 transmitted UID bytes + BCC (including cascade byte if relevant) + ac_buffer_builder_write_n_bytes(pDataOutBldr, pPN512->anticollision.iso_a.cln, 5); + + NFC_DBG("Selecting target"); + + //This time compute & check CRC + pn512_set_crc((nfc_transceiver_t *)pPN512, true, true); + pn512_set_write((nfc_transceiver_t *)pPN512, ac_buffer_builder_buffer(pDataOutBldr)); + pn512_transceive_hw(pPN512, pn512_transceive_mode_transceive, pn512_initiator_isoa_anticollision_cascade_3); +} + +static void pn512_initiator_isoa_anticollision_cascade_3(pn512_t *pPN512, nfc_err_t ret) +{ + ac_buffer_t *pResp = pn512_get_read((nfc_transceiver_t *)pPN512); + + if (ret) { + NFC_WARN("Did not receive response: error %d", ret); + pn512_anticollision_callback(pPN512, ret); + return; + } + + if (ac_buffer_reader_readable(pResp) != 1) { + NFC_WARN("Wrong length"); + pn512_anticollision_callback(pPN512, NFC_ERR_PROTOCOL); + return; + } + + pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].nfcA.sak = ac_buffer_read_nu8(pResp); + NFC_DBG("Got SAK %02X", pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].nfcA.sak); + + //Check SAK + if (pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].nfcA.sak & 0x04) { + //Continue anticollision + pPN512->anticollision.iso_a.cascade_level++; + pPN512->anticollision.iso_a.valid_bits = 0; + memset(pPN512->anticollision.iso_a.cln, 0, 5); + pn512_initiator_isoa_anticollision_cascade_1(pPN512); + } else { + //Anticollision complete + + NFC_DBG("Found one target- SAK = %02X", pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].nfcA.sak); + + //Analyze SAK + memset(&pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].type, 0, sizeof(nfc_tech_t)); + + if (pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].nfcA.sak & 0x40) { //NFC-IP1 compliant + pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].type.nfc_nfc_dep_a = true; + } + if ((pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].nfcA.sak & 0x20) + && pPN512->config.initiators.nfc_iso_dep_a) { //ISO-14443A-4 compliant + pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].type.nfc_iso_dep_a = true; + } + if (!(pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].nfcA.sak & 0x60) + && pPN512->config.initiators.nfc_type2) { //Potentially NFC Type 2 (or Mifare, etc) + pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].type.nfc_type2 = true; + } + + // Unknown target + if (!pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].type.nfc_iso_dep_a + && !pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].type.nfc_nfc_dep_a + && !pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].type.nfc_type2 + ) { + pn512_anticollision_callback(pPN512, NFC_ERR_NOPEER); + return; + } + + // Valid target detected + pPN512->transceiver.active_tech = pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].type; + pPN512->transceiver.remote_targets_count++; + + if (!pPN512->config.options.bail_at_first_target + && pPN512->anticollision.iso_a.more_targets + && (pPN512->transceiver.remote_targets_count < MUNFC_MAX_REMOTE_TARGETS)) { + // Halt target and continue with others + ac_buffer_builder_t *pDataOutBldr = &pPN512->readBufBldr; + ac_buffer_builder_reset(pDataOutBldr); + + //HALTA + ac_buffer_builder_write_nu8(pDataOutBldr, HALTA1); + ac_buffer_builder_write_nu8(pDataOutBldr, HALTA2); + + pn512_set_crc((nfc_transceiver_t *)pPN512, true, false); + pn512_set_timeout((nfc_transceiver_t *)pPN512, 30); + pn512_set_write((nfc_transceiver_t *)pPN512, ac_buffer_builder_buffer(pDataOutBldr)); + pn512_transceive_hw(pPN512, pn512_transceive_mode_transmit, pn512_initiator_isoa_anticollision_cascade_4); + return; + } + + // Leave it activated and finish! + pn512_initiator_isoa_anticollision_complete(pPN512); + } +} + +static void pn512_initiator_isoa_anticollision_cascade_4(pn512_t *pPN512, nfc_err_t ret) +{ + if (ret) { + NFC_WARN("Could not halt device: error %d", ret); + pn512_anticollision_callback(pPN512, ret); + return; + } + + // Start again + pn512_initiator_isoa_anticollision_reqa(pPN512); +} + +void pn512_initiator_isoa_anticollision_complete(pn512_t *pPN512) +{ + pn512_anticollision_callback(pPN512, NFC_OK); +} + +// ISO B +static void pn512_initiator_isob_anticollision(pn512_t *pPN512, pn512_cb_t cb); +static void pn512_initiator_isob_anticollision_reqb(pn512_t *pPN512); +static void pn512_initiator_isob_anticollision_atqb(pn512_t *pPN512, nfc_err_t ret); +static void pn512_initiator_isob_anticollision_next_slot(pn512_t *pPN512); +static void pn512_initiator_isob_anticollision_haltb_resp(pn512_t *pPN512, nfc_err_t ret); +static void pn512_initiator_isob_anticollision_complete(pn512_t *pPN512); + +#define REQB 0x05 +#define HALTB 0x50 + +void pn512_initiator_isob_anticollision(pn512_t *pPN512, pn512_cb_t cb) +{ + pPN512->anticollision.cb = cb; + pPN512->anticollision.iso_b.slots_num_exponent = 0; // Start with one slot + pPN512->anticollision.iso_b.slot_number = 0; + pPN512->anticollision.iso_b.found_one = false; + + // Reset transceive mode + pPN512->transceive.mode = pn512_transceive_mode_idle; + + pn512_initiator_isob_anticollision_reqb(pPN512); +} + +void pn512_initiator_isob_anticollision_reqb(pn512_t *pPN512) +{ + ac_buffer_builder_t *pDataOutBldr = &pPN512->readBufBldr; + ac_buffer_builder_reset(pDataOutBldr); + + if (pPN512->anticollision.iso_b.slot_number == 0) { + // Send REQB/WUPB + pPN512->anticollision.iso_b.more_targets = false; + + ac_buffer_builder_write_nu8(pDataOutBldr, REQB); + ac_buffer_builder_write_nu8(pDataOutBldr, 0x00); // AFI: All card types should respond + uint8_t wup = 0; + if ( + pPN512->anticollision.iso_b.slots_num_exponent == 0 + //&& (pPN512->anticollision.iso_b.slot_number == 0) + ) { + wup |= 0x8; // Send Wake-Up command on first iteration + } + ac_buffer_builder_write_nu8(pDataOutBldr, wup | (pPN512->anticollision.iso_b.slots_num_exponent & 0x7)); // Param: number of slots + } else { + // Just send slot marker + ac_buffer_builder_write_nu8(pDataOutBldr, REQB | ((pPN512->anticollision.iso_b.slot_number & 0xf) << 4)); + } + + pn512_set_crc((nfc_transceiver_t *)pPN512, true, true); + pn512_set_timeout((nfc_transceiver_t *)pPN512, 18); + pn512_set_write((nfc_transceiver_t *)pPN512, ac_buffer_builder_buffer(pDataOutBldr)); + pn512_transceive_hw(pPN512, pn512_transceive_mode_transceive, pn512_initiator_isob_anticollision_atqb); +} + +void pn512_initiator_isob_anticollision_atqb(pn512_t *pPN512, nfc_err_t ret) +{ + // Three cases: + // - 1 response --> store response, halt PICC and check next slot number + // - No response --> check next slot number + // - Collision --> check next slot number but we will have to increment number of slots + ac_buffer_t *pResp = pn512_get_read((nfc_transceiver_t *)pPN512); + + if (ret && (ret != NFC_ERR_COLLISION) && (ret != NFC_ERR_WRONG_COMM) && (ret != NFC_ERR_TIMEOUT)) { + NFC_WARN("Did not receive ATQB: error %u", ret); + pn512_anticollision_callback(pPN512, NFC_ERR_PROTOCOL); + return; + } + + // Increment slot number + pPN512->anticollision.iso_b.slot_number++; + + if ((ret == NFC_ERR_COLLISION) || (ret == NFC_ERR_WRONG_COMM)) { + pPN512->anticollision.iso_b.more_targets = true; + } else if (!ret) { + pPN512->anticollision.iso_b.found_one = true; + + // Decode ATQB + if (ac_buffer_reader_readable(pResp) != 12) { + NFC_WARN("Wrong length (%u bytes)", ac_buffer_reader_readable(pResp)); + pn512_anticollision_callback(pPN512, NFC_ERR_PROTOCOL); + return; + } + + NFC_DBG("Got ATQB:"); + NFC_DBG_BLOCK(ac_buffer_dump(pResp);) + + // Check first byte + uint8_t atqb0 = ac_buffer_read_nu8(pResp); + if (atqb0 != 0x50) { + NFC_WARN("Wrong first byte for ATQB: %02X", atqb0); + pn512_anticollision_callback(pPN512, NFC_ERR_PROTOCOL); + return; + } + + memset(&pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].type, 0, sizeof(nfc_tech_t)); + pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].type.nfc_iso_dep_b = true; + + // Save PUPI, application data & protocol info + ac_buffer_read_n_bytes(pResp, pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].nfcB.pupi, 4); + ac_buffer_read_n_bytes(pResp, pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].nfcB.application_data, 4); + ac_buffer_read_n_bytes(pResp, pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].nfcB.protocol_info, 3); + + // Valid target detected + pPN512->transceiver.active_tech = pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].type; + pPN512->transceiver.remote_targets_count++; + + if (!pPN512->config.options.bail_at_first_target + && (pPN512->anticollision.iso_b.more_targets || (pPN512->anticollision.iso_b.slot_number < (1 << pPN512->anticollision.iso_b.slots_num_exponent))) + && (pPN512->transceiver.remote_targets_count < MUNFC_MAX_REMOTE_TARGETS)) { + // Halt target and continue with others + ac_buffer_builder_t *pDataOutBldr = &pPN512->readBufBldr; + ac_buffer_builder_reset(pDataOutBldr); + + // Halt PICC and move on to the next slot + + //HALTB + ac_buffer_builder_write_nu8(pDataOutBldr, HALTB); + ac_buffer_builder_write_n_bytes(pDataOutBldr, pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count - 1].nfcB.pupi, 4); + + pn512_set_crc((nfc_transceiver_t *)pPN512, true, true); + pn512_set_timeout((nfc_transceiver_t *)pPN512, 30); + pn512_set_write((nfc_transceiver_t *)pPN512, ac_buffer_builder_buffer(pDataOutBldr)); + pn512_transceive_hw(pPN512, pn512_transceive_mode_transceive, pn512_initiator_isob_anticollision_haltb_resp); + return; + } else { + pn512_initiator_isob_anticollision_complete(pPN512); + return; + } + } + + // Move on to the next slot + pn512_initiator_isob_anticollision_next_slot(pPN512); +} + +void pn512_initiator_isob_anticollision_next_slot(pn512_t *pPN512) +{ + if (pPN512->anticollision.iso_b.slot_number >= (1 << pPN512->anticollision.iso_b.slots_num_exponent)) { + if (!pPN512->anticollision.iso_b.more_targets) { + // No further collisions to resolve + pn512_initiator_isob_anticollision_complete(pPN512); + return; + } + if (pPN512->anticollision.iso_b.slots_num_exponent >= 4) { + // Cannot handle more than 16 slots + pn512_initiator_isob_anticollision_complete(pPN512); + return; + } + pPN512->anticollision.iso_b.slots_num_exponent++; + pPN512->anticollision.iso_b.slot_number = 0; + } + pn512_initiator_isob_anticollision_reqb(pPN512); +} + +void pn512_initiator_isob_anticollision_haltb_resp(pn512_t *pPN512, nfc_err_t ret) +{ + // Check for response + if (ret) { + NFC_WARN("Did not receive HALTB response: error %u", ret); + pn512_anticollision_callback(pPN512, NFC_ERR_PROTOCOL); + return; + } + + ac_buffer_t *pResp = pn512_get_read((nfc_transceiver_t *)pPN512); + + if (ac_buffer_reader_readable(pResp) != 1) { + NFC_WARN("Wrong length (%u bytes)", ac_buffer_reader_readable(pResp)); + pn512_anticollision_callback(pPN512, NFC_ERR_PROTOCOL); + return; + } + + NFC_DBG("Got HALTB response:"); + NFC_DBG_BLOCK(ac_buffer_dump(pResp);) + + // Check byte + uint8_t haltbr = ac_buffer_read_nu8(pResp); + if (haltbr != 0x00) { + NFC_WARN("Wrong byte for HALTB response: %02X", haltbr); + pn512_anticollision_callback(pPN512, NFC_ERR_PROTOCOL); + return; + } + + // PICC halted, move to next slot + pn512_initiator_isob_anticollision_next_slot(pPN512); +} + +void pn512_initiator_isob_anticollision_complete(pn512_t *pPN512) +{ + if (pPN512->anticollision.iso_b.found_one) { + pn512_anticollision_callback(pPN512, NFC_OK); + } else { + pn512_anticollision_callback(pPN512, NFC_ERR_NOPEER); + } +} + +// Felica +static void pn512_initiator_felica_anticollision(pn512_t *pPN512, pn512_cb_t cb); +static void pn512_initiator_felica_anticollision_reqc(pn512_t *pPN512); +static void pn512_initiator_felica_anticollision_atqc(pn512_t *pPN512, nfc_err_t ret); +static void pn512_initiator_felica_anticollision_complete(pn512_t *pPN512); + +#define REQC 0x00 + +void pn512_initiator_felica_anticollision(pn512_t *pPN512, pn512_cb_t cb) +{ + pPN512->anticollision.cb = cb; + + // Reset transceive mode + pPN512->transceive.mode = pn512_transceive_mode_idle; + + pn512_initiator_felica_anticollision_reqc(pPN512); +} + +void pn512_initiator_felica_anticollision_reqc(pn512_t *pPN512) +{ + ac_buffer_builder_t *pDataOutBldr = &pPN512->readBufBldr; + ac_buffer_builder_reset(pDataOutBldr); + + ac_buffer_builder_write_nu8(pDataOutBldr, 6); //Length + ac_buffer_builder_write_nu8(pDataOutBldr, REQC); + ac_buffer_builder_write_nu16(pDataOutBldr, 0xFFFF); //Any system code + ac_buffer_builder_write_nu8(pDataOutBldr, 0x00); // Padding + ac_buffer_builder_write_nu8(pDataOutBldr, 0x07); // 8 time slots, more would overflow the rx buffer if many cards responded + + pn512_set_crc((nfc_transceiver_t *)pPN512, true, true); + pn512_set_timeout((nfc_transceiver_t *)pPN512, 13); //8 timeslots at 212kbps + pn512_set_write((nfc_transceiver_t *)pPN512, ac_buffer_builder_buffer(pDataOutBldr)); + + pn512_framing_rx_multiple_enable(pPN512); // Set RxMultiple bit + + pn512_transceive_hw(pPN512, pn512_transceive_mode_transceive, pn512_initiator_felica_anticollision_atqc); +} + +void pn512_initiator_felica_anticollision_atqc(pn512_t *pPN512, nfc_err_t ret) +{ + ac_buffer_t *pResp = pn512_get_read((nfc_transceiver_t *)pPN512); + + if (ret || (ac_buffer_reader_readable(pResp) == 0)) { + NFC_WARN("Did not receive ATQC: error %d", ret); + pn512_anticollision_callback(pPN512, NFC_ERR_NOPEER); + return; + } + + // We might have multiple responses + NFC_DBG("Got ATQC:"); + NFC_DBG_BLOCK(ac_buffer_dump(pResp);) + + while (ac_buffer_reader_readable(pResp) > 0) { + if (ac_buffer_reader_readable(pResp) != 18 + 1) { // ATQC is 18 bytes, 1 byte for errors added by PN512 + NFC_WARN("Wrong length (%d bytes)", ac_buffer_reader_readable(pResp)); + pn512_anticollision_callback(pPN512, NFC_ERR_PROTOCOL); + return; + } + + // First byte is length, check that it's correct + uint8_t frame_length = ac_buffer_read_nu8(pResp); + uint8_t atqc0 = ac_buffer_read_nu8(pResp); + if ((frame_length != 18) || (atqc0 != 0x01)) { + NFC_WARN("Wrong ATQC frame"); + pn512_anticollision_callback(pPN512, NFC_ERR_PROTOCOL); + return; + } + + // Read NFCID2 + ac_buffer_read_n_bytes(pResp, pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].nfcF.nfcid2, 8); + + // Discard padding bytes + ac_buffer_read_n_skip(pResp, 8); + + // Read error register + uint8_t err_reg = ac_buffer_read_nu8(pResp); + if (err_reg & 0x1f) { + // Error within this time slot, skip + continue; + } + + //Populate tech accordingly + memset(&pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].type, 0, sizeof(nfc_tech_t)); + if ( + (pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].nfcF.nfcid2[0] == 0x01) + && (pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].nfcF.nfcid2[1] == 0xFE) + ) { + // NFC-DEP supported + pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].type.nfc_nfc_dep_f_212 = 1; + } else { + // Type 3 supported + pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].type.nfc_type3 = 1; + } + pPN512->transceiver.active_tech = pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].type; + pPN512->transceiver.remote_targets_count++; + + // Only continue if we can have more targets + if (!pPN512->config.options.bail_at_first_target + && (pPN512->transceiver.remote_targets_count < MUNFC_MAX_REMOTE_TARGETS)) { + continue; + } + break; + } + + pn512_initiator_felica_anticollision_complete(pPN512); +} + +void pn512_initiator_felica_anticollision_complete(pn512_t *pPN512) +{ + pn512_anticollision_callback(pPN512, NFC_OK); +} + +void pn512_poll_setup(pn512_t *pPN512) +{ + bool target = pPN512->config.targets.nfc_type2 + || pPN512->config.targets.nfc_type3 + || pPN512->config.targets.nfc_iso_dep_a + || pPN512->config.targets.nfc_nfc_dep_a + || pPN512->config.targets.nfc_nfc_dep_f_212 + || pPN512->config.targets.nfc_nfc_dep_f_424; + +// No need for initiator-specific configuration at this stage, but keep this just in case +// bool initiator = pPN512->config.initiators.nfc_type1 +// || pPN512->config.initiators.nfc_type2 +// || pPN512->config.initiators.nfc_type3 +// || pPN512->config.initiators.nfc_iso_dep_a +// || pPN512->config.initiators.nfc_nfc_dep_a +// || pPN512->config.initiators.nfc_nfc_dep_f_212 +// || pPN512->config.initiators.nfc_nfc_dep_f_424; + + if (target) { + NFC_DBG("Configure anticoll/polling response"); + //Setup ATQA, SAK and Felica polling response + pn512_fifo_clear(pPN512); + + ac_buffer_builder_t *pDataCfgBldr = &pPN512->readBufBldr; + ac_buffer_builder_reset(pDataCfgBldr); + + //Write ATQA + ac_buffer_builder_write_nu8(pDataCfgBldr, 0x04); + ac_buffer_builder_write_nu8(pDataCfgBldr, 0x00); + + //Write NFCID1 (0s as it will be randomly generated) - first byte will be set to 0x08 by HW according to NFC-IP1 + for (int i = 0; i < 3; i++) { + ac_buffer_builder_write_nu8(pDataCfgBldr, 0x00); + } + + //Write SAK + uint8_t sak = 0x00; //Default SAK (UID complete) + if (pPN512->config.targets.nfc_iso_dep_a) { + sak |= 0x20; //This target is ISO-14443A-4 compliant + } + if (pPN512->config.targets.nfc_nfc_dep_a) { + sak |= 0x40; //This target is NFC-IP1 compliant + } + ac_buffer_builder_write_nu8(pDataCfgBldr, sak); + + //Write NFCID2 (xx 0xfe according to NFC-IP1 and 0s as 6 bytes will be randomly generated) + if (pPN512->config.targets.nfc_nfc_dep_f_212 || pPN512->config.targets.nfc_nfc_dep_f_424) { + //Byte 1 is 0x01 if supporting NFC-IP1 + ac_buffer_builder_write_nu8(pDataCfgBldr, 0x01); + } else if (pPN512->config.targets.nfc_type3) { //NFC-IP will have priority over type 3 tag emulation + //Byte 1 is 0x02 if supporting Type 3 tag platform + ac_buffer_builder_write_nu8(pDataCfgBldr, 0x02); + } else { + ac_buffer_builder_write_nu8(pDataCfgBldr, 0x00); + } + ac_buffer_builder_write_nu8(pDataCfgBldr, 0xFE); + + for (int i = 0; i < 6; i++) { + ac_buffer_builder_write_nu8(pDataCfgBldr, 0x00); + } + + //2 PAD0 bytes (Felica spec) - this would code the manufacturer + IC code (0xFFFF for NFC-IP1 tags) + ac_buffer_builder_write_nu8(pDataCfgBldr, 0xFF); + ac_buffer_builder_write_nu8(pDataCfgBldr, 0xFF); + + //3 PAD1 bytes + ac_buffer_builder_write_nu8(pDataCfgBldr, 0x00); + ac_buffer_builder_write_nu8(pDataCfgBldr, 0x00); + ac_buffer_builder_write_nu8(pDataCfgBldr, 0x00); + + if (!(pPN512->config.targets.nfc_nfc_dep_f_212 || pPN512->config.targets.nfc_nfc_dep_f_424) + && pPN512->config.targets.nfc_type3) { + ac_buffer_builder_write_nu8(pDataCfgBldr, 0x01); //MRTI Check + ac_buffer_builder_write_nu8(pDataCfgBldr, 0x01); //MRTI Update + } else { + ac_buffer_builder_write_nu8(pDataCfgBldr, 0x00); + ac_buffer_builder_write_nu8(pDataCfgBldr, 0x00); + } + + //1 PAD2 byte + ac_buffer_builder_write_nu8(pDataCfgBldr, 0x00); + + //2 system code bytes + if (!(pPN512->config.targets.nfc_nfc_dep_f_212 || pPN512->config.targets.nfc_nfc_dep_f_424) + && pPN512->config.targets.nfc_type3) { + ac_buffer_builder_write_nu8(pDataCfgBldr, 0x12); + ac_buffer_builder_write_nu8(pDataCfgBldr, 0xFC); + } else { + ac_buffer_builder_write_nu8(pDataCfgBldr, 0xFF); //Wildcard system code + ac_buffer_builder_write_nu8(pDataCfgBldr, 0xFF); + } + + //Write NFCID3 + ac_buffer_builder_write_nu8(pDataCfgBldr, 0x00); + + pn512_fifo_write(pPN512, ac_buffer_builder_buffer(pDataCfgBldr)); + + pn512_cmd_exec(pPN512, PN512_CMD_CONFIG); + pn512_cmd_wait_idle(pPN512, -1); + + NFC_DBG("Overwrite NFCIDs with random numbers"); + + //Overwrite NFCIDs with random numbers + pn512_cmd_exec(pPN512, PN512_CMD_RNDIDG); + pn512_cmd_wait_idle(pPN512, -1); + } +} + +static void pn512_poll_iteration(pn512_t *pPN512, nfc_err_t ret); +static void pn512_poll_delay_complete(uint32_t events, void *pUserData) +{ + pn512_t *pPN512 = (pn512_t *) pUserData; + + if (events & EVENT_ABORTED) { + pn512_poll_callback(pPN512, NFC_ERR_ABORTED); + return; + } + + pn512_poll_iteration(pPN512, NFC_OK); +} + +static void pn512_poll_delay(pn512_t *pPN512, uint32_t timeout) +{ + task_init(&pPN512->transceiver.task, EVENT_TIMEOUT, timeout, pn512_poll_delay_complete, pPN512); + nfc_scheduler_queue_task(&pPN512->transceiver.scheduler, &pPN512->transceiver.task); +} + +void pn512_poll_iteration(pn512_t *pPN512, nfc_err_t ret) +{ + do { + if (pPN512->poll.state == pn512_polling_state_start_listening) { + NFC_DBG("pn512_polling_state_start_listening"); + // Start with listening + if (!pn512_config_target(pPN512)) { + // Otherwise switch to next step + pPN512->poll.state = pn512_polling_state_start_polling; + continue; + } + + pPN512->poll.state = pn512_polling_state_listen_wait_for_remote_field; + + // Shortcut if target is halted (means RF field is still here) + if (pn512_register_read(pPN512, PN512_REG_MIFNFC) & 0x04) { + continue; + } + + // Fix for PN512 bug that sometimes detects its own RF field + // if(pPN512->rf_on) + { + //Switch RF field off + pn512_rf_field_switch_off(pPN512); + NFC_DBG("RF field switched off"); + } + + NFC_DBG("Target anticollision"); + + bool iso14443a = pPN512->config.targets.nfc_type2 || pPN512->config.targets.nfc_iso_dep_a || pPN512->config.targets.nfc_nfc_dep_a; + bool felica = pPN512->config.targets.nfc_type3 || pPN512->config.targets.nfc_nfc_dep_f_212 || pPN512->config.targets.nfc_nfc_dep_f_424; + + NFC_DBG("Switch in target mode and set framing: ISO A: %s; Felica: %s", iso14443a ? "Yes" : "No", felica ? "Yes" : "No"); + + //Switch in target mode + if (iso14443a && felica) { + pn512_framing_set(pPN512, nfc_framing_target_mode_detector); + } else if (iso14443a) { + pn512_framing_set(pPN512, nfc_framing_target_a_106); + } else if (felica) { + pn512_framing_set(pPN512, nfc_framing_target_f_212); + } + + pn512_rf_field_wait_for_external(pPN512, pPN512->config.options.listen_for, pn512_poll_iteration); + return; + } + + if (pPN512->poll.state == pn512_polling_state_listen_wait_for_remote_field) { + NFC_DBG("pn512_polling_state_listen_wait_for_remote_field"); + + if (!pn512_config_target(pPN512)) { + // Otherwise switch to next step + pPN512->poll.state = pn512_polling_state_start_listening; + continue; + } + + if (ret == NFC_ERR_TIMEOUT) { + // Continue polling + pPN512->poll.state = pn512_polling_state_start_polling; + continue; + } + + if (ret) { + pn512_poll_callback(pPN512, ret); + return; + } + + pPN512->poll.state = pn512_polling_state_listen_anticollision; + + pn512_target_anticollision(pPN512, pn512_poll_iteration); + return; + } + + if (pPN512->poll.state == pn512_polling_state_listen_anticollision) { + NFC_DBG("pn512_polling_state_listen_anticollision"); + + if (ret == NFC_ERR_FIELD) { + // This means that a remote field was dropped - give it another chance + pPN512->poll.state = pn512_polling_state_listen_wait_for_remote_field; + pn512_rf_field_switch_off(pPN512); + pn512_rf_field_wait_for_external(pPN512, pPN512->config.options.listen_for, pn512_poll_iteration); + return; + } + + if (ret) { + pn512_poll_callback(pPN512, ret); + return; + } + + // Be safe, not sure what the framing is + pPN512->framing = nfc_framing_unknown; + + pn512_poll_callback(pPN512, NFC_OK); + return; + } + + if (pPN512->poll.state == pn512_polling_state_start_polling) { + NFC_DBG("pn512_polling_state_start_polling"); + + if (!pn512_config_initiator(pPN512)) { + // Otherwise switch to next step + pPN512->poll.state = pn512_polling_state_start_listening; + continue; + } + + // Try to activate RF field + pPN512->poll.state = pn512_polling_state_rf_collision_avoidance; + + pn512_rf_field_nfcip1_rf_collision_avoidance(pPN512, pn512_poll_iteration); + return; + } + + if (pPN512->poll.state == pn512_polling_state_rf_collision_avoidance) { + NFC_DBG("pn512_polling_state_rf_collision_avoidance"); + + if (ret) { + pn512_poll_callback(pPN512, ret); + return; + } + + NFC_DBG("Own RF field is %s", pPN512->rf_on ? "on" : "off"); + + if (!pPN512->rf_on) { + // Go back to listening, target framing is still valid so no need to reset it + pPN512->poll.state = pn512_polling_state_listen_wait_for_remote_field; + continue; + } + + pPN512->poll.state = pn512_polling_state_polling_nfc_a_start; + } + + if (pPN512->poll.state == pn512_polling_state_polling_nfc_a_start) { + NFC_DBG("pn512_polling_state_polling_nfc_a_start"); + + //Check if ISO A is needed + bool nfc_a = pPN512->config.initiators.nfc_type2 || pPN512->config.initiators.nfc_iso_dep_a || pPN512->config.initiators.nfc_nfc_dep_a; //We do not support type 1 card emulation so irrelevant + if (!nfc_a) { + // Continue with NFC B + pPN512->poll.state = pn512_polling_state_polling_nfc_b_start; + continue; + } + + pPN512->transceiver.initiator_ntarget = true; + pn512_framing_set(pPN512, nfc_framing_initiator_a_106); + + pPN512->poll.state = pn512_polling_state_polling_nfc_a_gt; + pn512_poll_delay(pPN512, 10 + 5); // Guard time for ISO A is 5 ms + return; + } + + if (pPN512->poll.state == pn512_polling_state_polling_nfc_a_gt) { + NFC_DBG("pn512_polling_state_polling_nfc_a_gt"); + + // Start anticollision + pPN512->poll.state = pn512_polling_state_polling_nfc_a_anticollision; + pn512_initiator_isoa_anticollision(pPN512, pn512_poll_iteration); + return; + } + + if (pPN512->poll.state == pn512_polling_state_polling_nfc_a_anticollision) { + NFC_DBG("pn512_polling_state_polling_nfc_a_anticollision"); + + if (ret == NFC_ERR_NOPEER) { + NFC_DBG("Not found"); + // Continue with NFC B + pPN512->poll.state = pn512_polling_state_polling_nfc_b_start; + continue; + } + + if ((ret == NFC_OK) && (pPN512->config.options.bail_at_first_tech || (pPN512->transceiver.remote_targets_count == MUNFC_MAX_REMOTE_TARGETS))) { + // At least one target found, exit polling loop + pn512_poll_callback(pPN512, NFC_OK); + return; + } + + if (ret == NFC_ERR_ABORTED) { + pn512_poll_callback(pPN512, ret); + return; + } + + // Continue with NFC B + pPN512->poll.state = pn512_polling_state_polling_nfc_b_start; + continue; + } + + if (pPN512->poll.state == pn512_polling_state_polling_nfc_b_start) { + NFC_DBG("pn512_polling_state_polling_nfc_b_start"); + + //Check if ISO B is needed + bool nfc_b = pPN512->config.initiators.nfc_iso_dep_b; + if (!nfc_b) { + // Continue with NFC F + pPN512->poll.state = pn512_polling_state_polling_nfc_f_start; + continue; + } + + pPN512->transceiver.initiator_ntarget = true; + pn512_framing_set(pPN512, nfc_framing_initiator_b_106); + + pPN512->poll.state = pn512_polling_state_polling_nfc_b_gt; + pn512_poll_delay(pPN512, 10 + 5); // Guard time for ISO B is 5 ms + return; + } + + if (pPN512->poll.state == pn512_polling_state_polling_nfc_b_gt) { + NFC_DBG("pn512_polling_state_polling_nfc_b_gt"); + + // Start anticollision + pPN512->poll.state = pn512_polling_state_polling_nfc_b_anticollision; + pn512_initiator_isob_anticollision(pPN512, pn512_poll_iteration); + return; + } + + if (pPN512->poll.state == pn512_polling_state_polling_nfc_b_anticollision) { + NFC_DBG("pn512_polling_state_polling_nfc_b_anticollision"); + + if (ret == NFC_ERR_NOPEER) { + NFC_DBG("Not found"); + // Continue with NFC F + pPN512->poll.state = pn512_polling_state_polling_nfc_f_start; + continue; + } + + if ((ret == NFC_OK) + && (pPN512->config.options.bail_at_first_tech + || (pPN512->transceiver.remote_targets_count + == MUNFC_MAX_REMOTE_TARGETS))) { + // At least one target found, exit polling loop + pn512_poll_callback(pPN512, NFC_OK); + return; + } + + if (ret == NFC_ERR_ABORTED) { + pn512_poll_callback(pPN512, ret); + return; + } + + // Continue with NFC F + pPN512->poll.state = pn512_polling_state_polling_nfc_f_start; + continue; + } + + if (pPN512->poll.state == pn512_polling_state_polling_nfc_f_start) { + NFC_DBG("pn512_polling_state_polling_nfc_f_start"); + + //Check if Felica is needed + bool nfc_f = pPN512->config.initiators.nfc_type3 || pPN512->config.initiators.nfc_nfc_dep_f_212; + if (!nfc_f) { + // Wrap up + pPN512->poll.state = pn512_polling_state_finish_polling; + continue; + } + + pPN512->transceiver.initiator_ntarget = true; + pn512_framing_set(pPN512, nfc_framing_initiator_f_212); + + pPN512->poll.state = pn512_polling_state_polling_nfc_f_gt; + pn512_poll_delay(pPN512, 20); // Guard time for Felica is 20 ms + return; + } + + if (pPN512->poll.state == pn512_polling_state_polling_nfc_f_gt) { + NFC_DBG("pn512_polling_state_polling_nfc_f_gt"); + + // Start anticollision + pPN512->poll.state = pn512_polling_state_polling_nfc_f_anticollision; + pn512_initiator_felica_anticollision(pPN512, pn512_poll_iteration); + return; + } + + if (pPN512->poll.state == pn512_polling_state_polling_nfc_f_anticollision) { + NFC_DBG("pn512_polling_state_polling_nfc_f_anticollision"); + + if (ret == NFC_ERR_NOPEER) { + NFC_DBG("Not found"); + // Resolve polling + pPN512->poll.state = pn512_polling_state_finish_polling; + continue; + } + + if ((ret == NFC_OK) && (pPN512->config.options.bail_at_first_tech || (pPN512->transceiver.remote_targets_count == MUNFC_MAX_REMOTE_TARGETS))) { + // At least one target found, exit polling loop + pn512_poll_callback(pPN512, NFC_OK); + return; + } + + if (ret == NFC_ERR_ABORTED) { + pn512_poll_callback(pPN512, ret); + return; + } + + // Resolve polling + pPN512->poll.state = pn512_polling_state_finish_polling; + continue; + } + + if (pPN512->poll.state == pn512_polling_state_finish_polling) { + if (pPN512->transceiver.remote_targets_count > 0) { + pn512_poll_callback(pPN512, NFC_OK); + } else { + pn512_poll_callback(pPN512, NFC_ERR_NOPEER); + } + return; + } + + } while (true); +} + +// Main polling loop function +void pn512_poll_hw(pn512_t *pPN512, pn512_cb_t cb) +{ + nfc_transceiver_t *pTransceiver = (nfc_transceiver_t *)pPN512; + pPN512->poll.cb = cb; + + //Reset active state + pTransceiver->initiator_ntarget = false; + memset(&pTransceiver->active_tech, 0, sizeof(nfc_tech_t)); + + //Reset discovered targets + pTransceiver->remote_targets_count = 0; + + //Initialize state machine + pPN512->poll.state = pn512_polling_state_start_listening; + + if (!pn512_config_target(pPN512) && !pn512_config_initiator(pPN512)) { + pn512_poll_callback(pPN512, NFC_ERR_PARAMS); + return; + } + + //First iteration + pn512_poll_iteration(pPN512, NFC_OK); +} diff --git a/connectivity/drivers/nfc/PN512/source/transceiver/pn512_poll.h b/connectivity/drivers/nfc/PN512/source/transceiver/pn512_poll.h new file mode 100644 index 0000000..a048912 --- /dev/null +++ b/connectivity/drivers/nfc/PN512/source/transceiver/pn512_poll.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2014-2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + */ +/** + * \file pn512_poll.h + * \copyright Copyright (c) ARM Ltd 2014 + * \author Donatien Garnier + */ + +#ifndef PN512_POLL_H_ +#define PN512_POLL_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "stack/nfc_common.h" + +void pn512_poll_setup(pn512_t *pPN512); +void pn512_poll_hw(pn512_t *pPN512, pn512_cb_t cb); + + +#ifdef __cplusplus +} +#endif + +#endif /* PN512_POLL_H_ */ diff --git a/connectivity/drivers/nfc/PN512/source/transceiver/pn512_registers.c b/connectivity/drivers/nfc/PN512/source/transceiver/pn512_registers.c new file mode 100644 index 0000000..a751dff --- /dev/null +++ b/connectivity/drivers/nfc/PN512/source/transceiver/pn512_registers.c @@ -0,0 +1,153 @@ + +/* + * Copyright (c) 2013-2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + */ +/** + * \file pn512_registers.c + * \copyright Copyright (c) ARM Ltd 2013 + * \author Donatien Garnier + * \details Access to PN512 registers + */ + + +#define __DEBUG__ 0 +#ifndef __MODULE__ +#define __MODULE__ "pn512_registers.c" +#endif +#include "stack/nfc_errors.h" + +#include "pn512_registers.h" +#include "pn512_hw.h" +#include "pn512.h" + +#define REGISTER_PAGE(x) ((x)>>4) +#define REGISTER_ADDR(x) ((x)&0xF) + +/** \addtogroup PN512 + * \internal + * @{ + * \name Registers + * @{ + */ + +static void pn512_register_switch_page_intl(pn512_t *pPN512, uint8_t page); + +/** \internal Initialize underlying pn512_registers_t structure + * \param pPN512 pointer to pn512_t structure + */ +void pn512_registers_init(pn512_t *pPN512) +{ + pPN512->registers.registers_page = 0; +} + +#define PN512_CFG_INIT_LEN 9 +static const uint8_t PN512_CFG_INIT_REGS[] = { + PN512_REG_DIVIEN, + PN512_REG_MODE, + PN512_REG_GSNOFF, + PN512_REG_RFCFG, + PN512_REG_CWGSP, + PN512_REG_MIFNFC, + PN512_REG_FELNFC2, + PN512_REG_RXSEL, + PN512_REG_TYPEB +}; +static const uint8_t PN512_CFG_INIT_VALS[] = { + 0x80, + 0x3F, + 0xF2, + 0x68, + 0x3F, + 0x62, + 0x80, + 0x84, + 0x00 +}; //Timer: For now max prescaler, max reload value + +/** \internal Switch to known (0) registers page, reset registers state + * \param pPN512 pointer to pn512_t structure + */ +void pn512_registers_reset(pn512_t *pPN512) +{ + pn512_register_switch_page_intl(pPN512, 0); + for (int i = 0; i < PN512_CFG_INIT_LEN; i++) { + pn512_register_write(pPN512, PN512_CFG_INIT_REGS[i], PN512_CFG_INIT_VALS[i]); + } +} + +/** \internal Write register + * \param pPN512 pointer to pn512_t structure + * \param address register address + * \param data value to write in register + */ +void pn512_register_write(pn512_t *pPN512, uint8_t address, uint8_t data) +{ + NFC_DBG("Write [%02x] << %02x", address, data); + if (REGISTER_PAGE(address) != pPN512->registers.registers_page) { + pn512_register_switch_page_intl(pPN512, REGISTER_PAGE(address)); + } + address = REGISTER_ADDR(address); + pn512_hw_write(pPN512, address, &data, 1); +} + +/** \internal Read register + * \param pPN512 pointer to pn512_t structure + * \param address register address + * \return data value read from register + */ +uint8_t pn512_register_read(pn512_t *pPN512, uint8_t address) +{ + uint8_t data; + NFC_DBG_BLOCK( + uint8_t __dbg_addr; + __dbg_addr = address; //FIXME + ) + if (REGISTER_PAGE(address) != pPN512->registers.registers_page) { + pn512_register_switch_page_intl(pPN512, REGISTER_PAGE(address)); + } + address = REGISTER_ADDR(address); + pn512_hw_read(pPN512, address, &data, 1); + NFC_DBG("Read [%02x] >> %02x", __dbg_addr, data); + return data; +} + +void pn512_register_switch_page(pn512_t *pPN512, uint8_t address) +{ + if (REGISTER_PAGE(address) != pPN512->registers.registers_page) { + pn512_register_switch_page_intl(pPN512, REGISTER_PAGE(address)); + } +} + +/** \internal Switch registers page + * \param pPN512 pointer to pn512_t structure + * \param page registers page + */ +void pn512_register_switch_page_intl(pn512_t *pPN512, uint8_t page) +{ + uint8_t pageRegValue; + pageRegValue = (1 << 7) | page; + + pn512_hw_write(pPN512, PN512_REG_PAGE, &pageRegValue, 1); + + pPN512->registers.registers_page = page; +} + + + +/** + * @} + * @} + * */ diff --git a/connectivity/drivers/nfc/PN512/source/transceiver/pn512_registers.h b/connectivity/drivers/nfc/PN512/source/transceiver/pn512_registers.h new file mode 100644 index 0000000..4d3cf49 --- /dev/null +++ b/connectivity/drivers/nfc/PN512/source/transceiver/pn512_registers.h @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2013-2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + */ +/** + * \file pn512_registers.h + * \copyright Copyright (c) ARM Ltd 2013 + * \author Donatien Garnier + */ + +#ifndef PN512_REGISTERS_H_ +#define PN512_REGISTERS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "stack/nfc_common.h" +#include "pn512.h" + +//Page 0 - Command and Status +#define PN512_REG_PAGE 0x00 //Selects the register page +#define PN512_REG_COMMAND 0x01 //Starts and stops command execution +#define PN512_REG_COMIEN 0x02 //Controls bits to enable and disable the passing of Interrupt Requests +#define PN512_REG_DIVIEN 0x03 //Controls bits to enable and disable the passing of Interrupt Requests +#define PN512_REG_COMIRQ 0x04 //Contains Interrupt Request bits +#define PN512_REG_DIVIRQ 0x05 //Contains Interrupt Request bits +#define PN512_REG_ERROR 0x06 //Error bits showing the error status of the last command executed +#define PN512_REG_STATUS1 0x07 //Contains status bits for communication +#define PN512_REG_STATUS2 0x08 //Contains status bits of the receiver and transmitter +#define PN512_REG_FIFODATA 0x09 //In- and output of 64 byte FIFO-buffer +#define PN512_REG_FIFOLEVEL 0x0A //Indicates the number of bytes stored in the FIFO +#define PN512_REG_WATERLEVEL 0x0B //Defines the level for FIFO under- and overflow warning +#define PN512_REG_CONTROL 0x0C //Contains miscellaneous Control Registers +#define PN512_REG_BITFRAMING 0x0D //Adjustments for bit oriented frames +#define PN512_REG_COLL 0x0E //Bit position of the first bit collision detected on the RF-interface + +//Page 1 - Command +//#define PN512_REG_PAGE 0x10 //Selects the register page +#define PN512_REG_MODE 0x11 //Defines general modes for transmitting and receiving +#define PN512_REG_TXMODE 0x12 //Defines the data rate and framing during transmission +#define PN512_REG_RXMODE 0x13 //Defines the data rate and framing during receiving +#define PN512_REG_TXCONTROL 0x14 //Controls the logical behavior of the antenna driver pins TX1 and TX2 +#define PN512_REG_TXAUTO 0x15 //Controls the setting of the antenna drivers +#define PN512_REG_TXSEL 0x16 //Selects the internal sources for the antenna driver +#define PN512_REG_RXSEL 0x17 //Selects internal receiver settings +#define PN512_REG_RXTHRESHOLD 0x18 //Selects thresholds for the bit decoder +#define PN512_REG_DEMOD 0x19 //Defines demodulator settings +#define PN512_REG_FELNFC1 0x1A //Defines the length of the valid range for the receive package +#define PN512_REG_FELNFC2 0x1B //Defines the length of the valid range for the receive package +#define PN512_REG_MIFNFC 0x1C //Controls the communication in ISO/IEC 14443/MIFARE and NFC target mode at 106 kbit +#define PN512_REG_MANUALRCV 0x1D //Allows manual fine tuning of the internal receiver +#define PN512_REG_TYPEB 0x1E //Configure the ISO/IEC 14443 type B +#define PN512_REG_SERIALSPEED 0x1F //Selects the speed of the serial UART interface + +//Page 2 - CFG +//#define PN512_REG_PAGE 0x20 //Selects the register page +#define PN512_REG_CRCRESULT_MSB 0x21 //Shows the actual MSB and LSB values of the CRC calculation +#define PN512_REG_CRCRESULT_LSB 0x22 //Shows the actual MSB and LSB values of the CRC calculation +#define PN512_REG_GSNOFF 0x23 //Selects the conductance of the antenna driver pins TX1 and TX2 for modulation, when the driver is switched off +#define PN512_REG_MODWIDTH 0x24 //Controls the setting of the ModWidth +#define PN512_REG_TXBITPHASE 0x25 //Adjust the TX bit phase at 106 kbit +#define PN512_REG_RFCFG 0x26 //Configures the receiver gain and RF level +#define PN512_REG_GSNON 0x27 //Selects the conductance of the antenna driver pins TX1 and TX2 for modulation when the drivers are switched on +#define PN512_REG_CWGSP 0x28 //Selects the conductance of the antenna driver pins TX1 and TX2 for modulation during times of no modulation +#define PN512_REG_MODGSP 0x29 //Selects the conductance of the antenna driver pins TX1 and TX2 for modulation during modulation +#define PN512_REG_TMODE_TPRESCALERHIGH 0x2A //Defines settings for the internal timer +#define PN512_REG_TPRESCALERLOW 0x2B //Defines settings for the internal timer +#define PN512_REG_TRELOADHIGH 0x2C //Describes the 16-bit timer reload value +#define PN512_REG_TRELOADLOW 0x2D //Describes the 16-bit timer reload value +#define PN512_REG_TCOUNTERVALHIGH 0x2E //Shows the 16-bit actual timer value +#define PN512_REG_TCOUNTERVALLOW 0x2F //Shows the 16-bit actual timer value + +//Page 3 - TestRegister +//#define PN512_REG_PAGE 0x30 //Selects the register page +#define PN512_REG_TESTSEL1 0x31 //General test signal configuration +#define PN512_REG_TESTSEL2 0x32 //General test signal configuration and PRBS control +#define PN512_REG_TESTPINEN 0x33 //Enables pin output driver on 8-bit parallel bus (Note: For serial interfaces only) +#define PN512_REG_TESTPINVALUE 0x34 //Defines the values for the 8-bit parallel bus when it is used as I/O bus +#define PN512_REG_TESTBUS 0x35 //Shows the status of the internal testbus +#define PN512_REG_AUTOTEST 0x36 //Controls the digital selftest +#define PN512_REG_VERSION 0x37 //Shows the version +#define PN512_REG_ANALOGTEST 0x38 //Controls the pins AUX1 and AUX2 +#define PN512_REG_TESTDAC1 0x39 //Defines the test value for the TestDAC1 +#define PN512_REG_TESTDAC2 0x3A //Defines the test value for the TestDAC2 +#define PN512_REG_TESTADC 0x3B //Shows the actual value of ADC I and Q + + +void pn512_registers_init(pn512_t *pPN512); +void pn512_registers_reset(pn512_t *pPN512); + +void pn512_register_write(pn512_t *pPN512, uint8_t address, uint8_t data); +uint8_t pn512_register_read(pn512_t *pPN512, uint8_t address); + +void pn512_register_switch_page(pn512_t *pPN512, uint8_t address); + +#ifdef __cplusplus +} +#endif + +#endif /* PN512_REGISTERS_H_ */ diff --git a/connectivity/drivers/nfc/PN512/source/transceiver/pn512_rf.c b/connectivity/drivers/nfc/PN512/source/transceiver/pn512_rf.c new file mode 100644 index 0000000..bbee18f --- /dev/null +++ b/connectivity/drivers/nfc/PN512/source/transceiver/pn512_rf.c @@ -0,0 +1,329 @@ +/* + * Copyright (c) 2014-2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + */ +/** + * \file pn512_rf.c + * \copyright Copyright (c) ARM Ltd 2014 + * \author Donatien Garnier + */ + +#define __DEBUG__ 0 +#ifndef __MODULE__ +#define __MODULE__ "pn512_rf.c" +#endif + +#include "stack/nfc_errors.h" + +#include "pn512_callback.h" +#include "pn512_rf.h" +#include "pn512_registers.h" +#include "pn512_timer.h" +#include "pn512_irq.h" +#include "pn512.h" +#include "pn512_internal.h" + +#include "stdlib.h" //For rand() func + +#define PN512_FRAMING_REGS 6 +static const uint8_t framing_registers[] = { PN512_REG_MODE, PN512_REG_TXMODE, PN512_REG_RXMODE, PN512_REG_MODGSP, PN512_REG_RXTHRESHOLD, PN512_REG_MODWIDTH }; +static const uint8_t framing_registers_mode_detector[] = { 0x3B, 0x80, 0x80, 0x3F, 0x55, 0x26 }; +static const uint8_t framing_registers_initiator_iso14443a_106k[] = { 0x3D, 0x80, 0x80, 0x3F, 0x55, 0x26 }; +static const uint8_t framing_registers_initiator_iso14443b_106k[] = { 0x3F, 0x83, 0x83, 0x04, 0x50, 0x26 }; +static const uint8_t framing_registers_target_iso14443a_106k[] = { 0x3D, 0x80, 0x80, 0x3F, 0x55, 0x26 }; +static const uint8_t framing_registers_felica_212k[] = { 0x3A, 0x92, 0x92, 0x12, 0x55, 0x15 }; +static const uint8_t framing_registers_felica_414k[] = { 0x3A, 0xA2, 0xA2, 0x12, 0x55, 0x0A }; + +nfc_err_t pn512_framing_set(pn512_t *pPN512, nfc_framing_t framing) +{ + if (framing == pPN512->framing) { //No need to do anything + return NFC_OK; + } + + NFC_DBG("Switching to %u", framing); + + const uint8_t *framing_registers_values; + switch (framing) { + case nfc_framing_target_mode_detector: + framing_registers_values = framing_registers_mode_detector; + break; + case nfc_framing_target_a_106: + framing_registers_values = framing_registers_target_iso14443a_106k; + break; + case nfc_framing_initiator_a_106: + framing_registers_values = framing_registers_initiator_iso14443a_106k; + break; + case nfc_framing_initiator_b_106: + framing_registers_values = framing_registers_initiator_iso14443b_106k; + break; + case nfc_framing_target_f_212: + case nfc_framing_initiator_f_212: + framing_registers_values = framing_registers_felica_212k; + break; + case nfc_framing_target_f_424: + case nfc_framing_initiator_f_424: + framing_registers_values = framing_registers_felica_414k; + break; + default: + return NFC_ERR_UNSUPPORTED; + } + + for (int i = 0; i < PN512_FRAMING_REGS; i++) { + pn512_register_write(pPN512, framing_registers[i], framing_registers_values[i]); + } + + pPN512->framing = framing; + pPN512->crc.out = true; + pPN512->crc.in = true; + + //TODO initiator: PN512_REG_MODGSP + + switch (pPN512->framing) { + case nfc_framing_initiator_a_106: + case nfc_framing_initiator_b_106: + case nfc_framing_initiator_f_212: + case nfc_framing_initiator_f_424: + pn512_register_write(pPN512, PN512_REG_CONTROL, 0x10); //Act as initiator + break; + case nfc_framing_target_mode_detector: + case nfc_framing_target_a_106: + case nfc_framing_target_f_212: + case nfc_framing_target_f_424: + pn512_register_write(pPN512, PN512_REG_CONTROL, 0x00); //Act as target + break; + default: + return NFC_ERR_UNSUPPORTED; + } +#if 1 + if ( + pPN512->framing == nfc_framing_initiator_a_106 + //|| (pPN512->framing == pn512_framing_target_iso14443a_106k) + ) { + //Enable 100% ASK Modulation + pn512_register_write(pPN512, PN512_REG_TXAUTO, pn512_register_read(pPN512, PN512_REG_TXAUTO) | 0x40); + } else { + pn512_register_write(pPN512, PN512_REG_TXAUTO, pn512_register_read(pPN512, PN512_REG_TXAUTO) & (~0x40)); + } +#endif + return NFC_OK; +} + +nfc_err_t pn512_framing_crc_set(pn512_t *pPN512, bool out, bool in) +{ + const uint8_t *framing_registers_values; + switch (pPN512->framing) { + case nfc_framing_target_mode_detector: + framing_registers_values = framing_registers_mode_detector; + break; + case nfc_framing_target_a_106: + framing_registers_values = framing_registers_target_iso14443a_106k; + break; + case nfc_framing_initiator_a_106: + framing_registers_values = framing_registers_initiator_iso14443a_106k; + break; + case nfc_framing_initiator_b_106: + framing_registers_values = framing_registers_initiator_iso14443b_106k; + break; + case nfc_framing_target_f_212: + case nfc_framing_initiator_f_212: + framing_registers_values = framing_registers_felica_212k; + break; + case nfc_framing_target_f_424: + case nfc_framing_initiator_f_424: + framing_registers_values = framing_registers_felica_414k; + break; + default: + return NFC_ERR_UNSUPPORTED; + } + + if (pPN512->crc.out != out) { + pn512_register_write(pPN512, framing_registers[1], (framing_registers_values[1] & 0x7F) | (out ? 0x80 : 0x00)); //TXMODE + pPN512->crc.out = out; + } + if (pPN512->crc.in != in) { + pn512_register_write(pPN512, framing_registers[2], (framing_registers_values[2] & 0x7F) | (in ? 0x80 : 0x00)); //RXMODE + pPN512->crc.in = in; + } + + return NFC_OK; +} + +nfc_err_t pn512_framing_rx_multiple_enable(pn512_t *pPN512) +{ + const uint8_t *framing_registers_values; + switch (pPN512->framing) { + case nfc_framing_target_mode_detector: + framing_registers_values = framing_registers_mode_detector; + break; + case nfc_framing_target_a_106: + framing_registers_values = framing_registers_target_iso14443a_106k; + break; + case nfc_framing_initiator_a_106: + framing_registers_values = framing_registers_initiator_iso14443a_106k; + break; + case nfc_framing_initiator_b_106: + framing_registers_values = framing_registers_initiator_iso14443b_106k; + break; + case nfc_framing_target_f_212: + case nfc_framing_initiator_f_212: + framing_registers_values = framing_registers_felica_212k; + break; + case nfc_framing_target_f_424: + case nfc_framing_initiator_f_424: + framing_registers_values = framing_registers_felica_414k; + break; + default: + return NFC_ERR_UNSUPPORTED; + } + + pn512_register_write(pPN512, framing_registers[2], (framing_registers_values[2] & 0x7F) | (pPN512->crc.in ? 0x80 : 0x00) | 0x04); //RXMODE + + return NFC_OK; +} + +void pn512_rf_field_switch_off(pn512_t *pPN512) +{ + pn512_register_write(pPN512, PN512_REG_TXAUTO, 0x00); + pn512_register_write(pPN512, PN512_REG_TXCONTROL, 0x80); + pPN512->rf_on = false; +} + +void pn512_rf_field_nfcip1_rf_collision_avoidance_complete(uint32_t events, void *pUserData) +{ + pn512_t *pPN512 = (pn512_t *) pUserData; + + uint16_t irq_res = pn512_irq_get(pPN512); + + (void) events; + + pn512_timer_stop(pPN512); + pn512_timer_config(pPN512, false, 0, 0xffff); //Deactivate autostart + pn512_irq_set(pPN512, PN512_IRQ_NONE); + pn512_irq_clear(pPN512, PN512_IRQ_RF_ON | PN512_IRQ_TIMER); + + if (irq_res & PN512_IRQ_RF_ON) { + NFC_DBG("External field on"); + + //Clear TXAUTO register + pn512_register_write(pPN512, PN512_REG_TXAUTO, 0x00); + + pPN512->rf_on = false; //External field on + pn512_rf_callback(pPN512, NFC_OK); + return; + } + + //Has our RF field been switched on? + if (pn512_register_read(pPN512, PN512_REG_TXAUTO) & 0x40) { //InitialRFOn bit is cleared automatically, if the RF field is switched on + NFC_ERR("InitialRFOn bit still set"); + pn512_rf_callback(pPN512, NFC_ERR_UNKNOWN); + return; + } + + pPN512->rf_on = true; //Own field on and guard time ok + + NFC_DBG("RF field enabled"); + pn512_rf_callback(pPN512, NFC_OK); +} + +void pn512_rf_field_nfcip1_rf_collision_avoidance(pn512_t *pPN512, pn512_cb_t cb) +{ + pPN512->rf.cb = cb; + pn512_irq_clear(pPN512, PN512_IRQ_RF_ON | PN512_IRQ_TIMER); + + //If our field is switched on, Wait TIRFG according to NFC-IP1 = 5ms => 67800 clock edges = (3+1)*8475 + pn512_timer_config(pPN512, true, 3, 8475); + + pn512_irq_set(pPN512, PN512_IRQ_RF_ON /* External field switched on */ + | PN512_IRQ_TIMER /* Timer reached 0 */); + + //Try to enable RF field in compliance with NFC-IP1 + pn512_register_write(pPN512, PN512_REG_TXAUTO, 0x0F); + + //Is external RF Field already on? + if (pn512_register_read(pPN512, PN512_REG_STATUS1) & 0x4) { + NFC_DBG("External field already on"); + pPN512->rf_on = false; //External field on + + //Cancel + pn512_timer_stop(pPN512); + pn512_timer_config(pPN512, false, 0, 0xffff); //Deactivate autostart + pn512_irq_clear(pPN512, PN512_IRQ_RF_ON | PN512_IRQ_TIMER); + pn512_rf_callback(pPN512, NFC_OK); + return; + } + + //Queue task to process IRQ + task_init(&pPN512->transceiver.task, EVENT_HW_INTERRUPT | EVENT_TIMEOUT, -1, pn512_rf_field_nfcip1_rf_collision_avoidance_complete, pPN512); + nfc_scheduler_queue_task(&pPN512->transceiver.scheduler, &pPN512->transceiver.task); +} + +void pn512_rf_field_wait_for_external_complete_task(uint32_t events, void *pUserData) +{ + pn512_t *pPN512 = (pn512_t *) pUserData; + + NFC_DBG("%lu events", events); + + //Wake up PN512 + pn512_register_write(pPN512, PN512_REG_COMMAND, 0x00); + while (pn512_register_read(pPN512, PN512_REG_COMMAND) & 0x10); + + pn512_irq_set(pPN512, PN512_IRQ_NONE); + pn512_irq_clear(pPN512, PN512_IRQ_RF_ON); + + if (events & EVENT_ABORTED) { + pn512_rf_callback(pPN512, NFC_ERR_ABORTED); + return; + } + + if (events & EVENT_TIMEOUT) { + NFC_DBG("Timeout"); + pn512_rf_callback(pPN512, NFC_ERR_TIMEOUT); + return; + } + + NFC_DBG("On"); + pn512_rf_callback(pPN512, NFC_OK); +} + +void pn512_rf_field_wait_for_external(pn512_t *pPN512, int timeout, pn512_cb_t cb) +{ + pPN512->rf.cb = cb; + + pn512_irq_clear(pPN512, PN512_IRQ_RF_ON); + + NFC_DBG("Wait for RF field to come up (timeout %d)", timeout); + + //Is external RF Field already on? + pn512_irq_set(pPN512, PN512_IRQ_RF_ON /* External field switched on */); + if (pn512_register_read(pPN512, PN512_REG_STATUS1) & 0x4) { + NFC_DBG("RF field already on"); + pn512_irq_set(pPN512, PN512_IRQ_NONE); + pn512_irq_clear(pPN512, PN512_IRQ_RF_ON); + + pn512_rf_callback(pPN512, NFC_OK); + return; + } + + //Send PN512 to sleep mode + pn512_register_write(pPN512, PN512_REG_COMMAND, 0x30); //Receiver off + soft power down + + //Queue task to process IRQ + task_init(&pPN512->transceiver.task, EVENT_HW_INTERRUPT | EVENT_TIMEOUT, timeout, pn512_rf_field_wait_for_external_complete_task, pPN512); + nfc_scheduler_queue_task(&pPN512->transceiver.scheduler, &pPN512->transceiver.task); +} + + + + diff --git a/connectivity/drivers/nfc/PN512/source/transceiver/pn512_rf.h b/connectivity/drivers/nfc/PN512/source/transceiver/pn512_rf.h new file mode 100644 index 0000000..34d965a --- /dev/null +++ b/connectivity/drivers/nfc/PN512/source/transceiver/pn512_rf.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2014-2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + */ +/** + * \file pn512_rf.h + * \copyright Copyright (c) ARM Ltd 2014 + * \author Donatien Garnier + */ + +#ifndef PN512_RF_H_ +#define PN512_RF_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "stack/nfc_common.h" +#include "pn512_types.h" +#include "pn512_callback.h" +#include "pn512.h" + +nfc_err_t pn512_framing_set(pn512_t *pPN512, nfc_framing_t framing); + +nfc_err_t pn512_framing_crc_set(pn512_t *pPN512, bool out, bool in); + +nfc_err_t pn512_framing_rx_multiple_enable(pn512_t *pPN512); + +#define PN512_FRAMING_IS_TARGET( framing ) ((framing) <= nfc_framing_target_f_424) + +void pn512_rf_field_switch_off(pn512_t *pPN512); + +void pn512_rf_field_nfcip1_rf_collision_avoidance(pn512_t *pPN512, pn512_cb_t cb); + +void pn512_rf_field_wait_for_external(pn512_t *pPN512, int timeout, pn512_cb_t cb); + + +#ifdef __cplusplus +} +#endif + +#endif /* PN512_RF_H_ */ diff --git a/connectivity/drivers/nfc/PN512/source/transceiver/pn512_timer.c b/connectivity/drivers/nfc/PN512/source/transceiver/pn512_timer.c new file mode 100644 index 0000000..60334a8 --- /dev/null +++ b/connectivity/drivers/nfc/PN512/source/transceiver/pn512_timer.c @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2014-2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + */ +/** + * \file pn512_timer.c + * \copyright Copyright (c) ARM Ltd 2014 + * \author Donatien Garnier + */ + +#include "stack/nfc_errors.h" + +#include "pn512_timer.h" +#include "pn512_registers.h" + +void pn512_timer_config(pn512_t *pPN512, bool autostart, uint16_t prescaler, uint16_t countdown_value) +{ + pn512_timer_stop(pPN512); //just in case... + + pn512_register_write(pPN512, PN512_REG_TRELOADLOW, countdown_value & 0xFF); + pn512_register_write(pPN512, PN512_REG_TRELOADHIGH, (countdown_value >> 8) & 0xFF); + + pn512_register_write(pPN512, PN512_REG_TPRESCALERLOW, prescaler & 0xFF); + pn512_register_write(pPN512, PN512_REG_TMODE_TPRESCALERHIGH, (autostart ? 0x80 : 0x00) | ((prescaler >> 8) & 0x0F)); +} + +void pn512_timer_start(pn512_t *pPN512) +{ + //The control register also contains the initiator bit that we must set correctly + switch (pPN512->framing) { + case nfc_framing_initiator_a_106: + case nfc_framing_initiator_f_212: + case nfc_framing_initiator_f_424: + pn512_register_write(pPN512, PN512_REG_CONTROL, 0x50); + break; + case nfc_framing_target_mode_detector: + case nfc_framing_target_a_106: + case nfc_framing_target_f_212: + case nfc_framing_target_f_424: + default: + pn512_register_write(pPN512, PN512_REG_CONTROL, 0x40); + break; + } +} + +void pn512_timer_stop(pn512_t *pPN512) +{ + //The control register also contains the initiator bit that we must set correctly + switch (pPN512->framing) { + case nfc_framing_initiator_a_106: + case nfc_framing_initiator_f_212: + case nfc_framing_initiator_f_424: + pn512_register_write(pPN512, PN512_REG_CONTROL, 0x90); + break; + case nfc_framing_target_mode_detector: + case nfc_framing_target_a_106: + case nfc_framing_target_f_212: + case nfc_framing_target_f_424: + default: + pn512_register_write(pPN512, PN512_REG_CONTROL, 0x80); + break; + } +} diff --git a/connectivity/drivers/nfc/PN512/source/transceiver/pn512_timer.h b/connectivity/drivers/nfc/PN512/source/transceiver/pn512_timer.h new file mode 100644 index 0000000..ae85edd --- /dev/null +++ b/connectivity/drivers/nfc/PN512/source/transceiver/pn512_timer.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2014-2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + */ +/** + * \file pn512_timer.h + * \copyright Copyright (c) ARM Ltd 2014 + * \author Donatien Garnier + */ + +#ifndef PN512_TIMER_H_ +#define PN512_TIMER_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "stack/nfc_common.h" +#include "pn512_types.h" + +void pn512_timer_config(pn512_t *pPN512, bool autostart, uint16_t prescaler, uint16_t countdown_value); + +void pn512_timer_start(pn512_t *pPN512); +void pn512_timer_stop(pn512_t *pPN512); + +#ifdef __cplusplus +} +#endif + +#endif /* PN512_TIMER_H_ */ diff --git a/connectivity/drivers/nfc/PN512/source/transceiver/pn512_transceive.c b/connectivity/drivers/nfc/PN512/source/transceiver/pn512_transceive.c new file mode 100644 index 0000000..304ae88 --- /dev/null +++ b/connectivity/drivers/nfc/PN512/source/transceiver/pn512_transceive.c @@ -0,0 +1,441 @@ +/* + * Copyright (c) 2014-2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + */ +/** + * \file pn512_transceive.c + * \copyright Copyright (c) ARM Ltd 2014 + * \author Donatien Garnier + */ + +#define __DEBUG__ 0 +#ifndef __MODULE__ +#define __MODULE__ "pn512_transceive.c" +#endif + +#include "stack/nfc_errors.h" + +#include "pn512.h" +#include "pn512_transceive.h" +#include "pn512_rf.h" +#include "pn512_irq.h" +#include "pn512_cmd.h" +#include "pn512_registers.h" +#include "pn512_internal.h" + + +#define TIMEOUT 1000 + +void pn512_transceive_hw_tx_iteration(pn512_t *pPN512, bool start) +{ + uint16_t irqs_en = pn512_irq_enabled(pPN512); + + if (ac_buffer_reader_readable(&pPN512->writeBuf) > 0) { + //Fill FIFO + pn512_fifo_write(pPN512, &pPN512->writeBuf); + + if (ac_buffer_reader_readable(&pPN512->writeBuf) > 0) { //Did not fit in FIFO + pn512_irq_clear(pPN512, PN512_IRQ_LOW_ALERT); + //Has low FIFO alert IRQ already been enabled? + if (!(irqs_en & PN512_IRQ_LOW_ALERT)) { + irqs_en |= PN512_IRQ_LOW_ALERT; + pn512_irq_set(pPN512, irqs_en); + } + } else { + if (irqs_en & PN512_IRQ_LOW_ALERT) { + //Buffer has been fully sent + irqs_en &= ~PN512_IRQ_LOW_ALERT; + pn512_irq_set(pPN512, irqs_en); + } + } + } + + + if (start) { + if ((pPN512->transceive.mode == pn512_transceive_mode_transmit) || (pPN512->transceive.mode == pn512_transceive_mode_transmit_and_target_autocoll)) { + //Update bitframing register + pn512_register_write(pPN512, PN512_REG_BITFRAMING, + 0x00 | ((pPN512->readFirstByteAlign & 0x7) << 4) | (pPN512->writeLastByteLength & 0x7)); + + //Use transmit command + pn512_cmd_exec(pPN512, PN512_CMD_TRANSMIT); + } else { + NFC_DBG("Bitframing %02X", 0x80 | ((pPN512->readFirstByteAlign & 0x7) << 4) | (pPN512->writeLastByteLength & 0x7)); + //Update bitframing register to start transmission + pn512_register_write(pPN512, PN512_REG_BITFRAMING, + 0x80 | ((pPN512->readFirstByteAlign & 0x7) << 4) | (pPN512->writeLastByteLength & 0x7)); + } + + //Reset last byte length, first byte align + pPN512->writeLastByteLength = 8; + pPN512->readFirstByteAlign = 0; + } + + //Queue task to process IRQ + task_init(&pPN512->transceiver.task, EVENT_HW_INTERRUPT | EVENT_TIMEOUT, TIMEOUT, pn512_transceive_hw_tx_task, pPN512); + nfc_scheduler_queue_task(&pPN512->transceiver.scheduler, &pPN512->transceiver.task); +} + +void pn512_transceive_hw_tx_task(uint32_t events, void *pUserData) +{ + pn512_t *pPN512 = (pn512_t *) pUserData; + + if (events & EVENT_ABORTED) { + //Stop command + pn512_cmd_exec(pPN512, PN512_CMD_IDLE); + pPN512->transceive.mode = pn512_transceive_mode_idle; + + NFC_ERR("Aborted TX"); + + pn512_irq_set(pPN512, PN512_IRQ_NONE); + pn512_irq_clear(pPN512, PN512_IRQ_ALL); + + pn512_transceive_callback(pPN512, NFC_ERR_ABORTED); + return; + } + + NFC_DBG("TX task"); + if (events & EVENT_TIMEOUT) { + // Check status + NFC_DBG("Status = %02X %02X", pn512_register_read(pPN512, PN512_REG_STATUS1), pn512_register_read(pPN512, PN512_REG_STATUS2)); + + //Stop command + pn512_cmd_exec(pPN512, PN512_CMD_IDLE); + pPN512->transceive.mode = pn512_transceive_mode_idle; + + NFC_ERR("Timeout on TX"); + + pn512_irq_set(pPN512, PN512_IRQ_NONE); + pn512_irq_clear(pPN512, PN512_IRQ_ALL); + + //Call callback + pn512_transceive_callback(pPN512, NFC_ERR_TIMEOUT); + return; + } + + uint16_t irqs_en = pn512_irq_enabled(pPN512); + uint16_t irqs = pn512_irq_get(pPN512); + + if (irqs & PN512_IRQ_RF_OFF) { + //Stop command + pn512_cmd_exec(pPN512, PN512_CMD_IDLE); + pPN512->transceive.mode = pn512_transceive_mode_idle; + + pn512_irq_set(pPN512, PN512_IRQ_NONE); + pn512_irq_clear(pPN512, PN512_IRQ_ALL); + NFC_WARN("RF Off"); + pn512_transceive_callback(pPN512, NFC_ERR_FIELD); + return; + } + if (irqs & PN512_IRQ_TX) { + if (irqs_en & PN512_IRQ_LOW_ALERT) { + //If the transmission has been completed without us getting a chance to fill the buffer up it means that we had a buffer underflow + NFC_ERR("Buffer underflow"); + pn512_irq_set(pPN512, PN512_IRQ_NONE); + pn512_irq_clear(pPN512, PN512_IRQ_ALL); + + pn512_transceive_callback(pPN512, NFC_ERR_UNDERFLOW); + return; + } + + //Transmission complete + pn512_irq_set(pPN512, PN512_IRQ_NONE); + pn512_irq_clear(pPN512, PN512_IRQ_TX | PN512_IRQ_LOW_ALERT); + + //Start receiving + NFC_DBG("Transmission complete"); + if (pPN512->transceive.mode != pn512_transceive_mode_transmit) { + if (pPN512->transceive.mode == pn512_transceive_mode_transmit_and_target_autocoll) { + //Make sure bitframing reg is clean + pn512_register_write(pPN512, PN512_REG_BITFRAMING, 0x00); + + pn512_cmd_exec(pPN512, PN512_CMD_IDLE); + pn512_transceive_hw_rx_start(pPN512); + + //Start autocoll + pn512_cmd_exec(pPN512, PN512_CMD_AUTOCOLL); + } else { + pn512_transceive_hw_rx_start(pPN512); + } + return; + } else { + pn512_irq_set(pPN512, PN512_IRQ_NONE); + pn512_irq_clear(pPN512, PN512_IRQ_RX | PN512_IRQ_HIGH_ALERT); + + pn512_transceive_callback(pPN512, NFC_OK); + return; + } + } + if ((irqs & PN512_IRQ_LOW_ALERT) && (ac_buffer_reader_readable(&pPN512->writeBuf) > 0)) { + //Continue to fill FIFO + pn512_irq_clear(pPN512, PN512_IRQ_LOW_ALERT); + + pn512_transceive_hw_tx_iteration(pPN512, false); + return; + } + + if (irqs & PN512_IRQ_IDLE) { + pn512_irq_clear(pPN512, PN512_IRQ_ERR); + + NFC_ERR("Modem went to idle"); + + pn512_cmd_exec(pPN512, PN512_CMD_IDLE); + pPN512->transceive.mode = pn512_transceive_mode_idle; + + pn512_irq_set(pPN512, PN512_IRQ_NONE); + pn512_irq_clear(pPN512, PN512_IRQ_ALL); + pn512_transceive_callback(pPN512, NFC_ERR_WRONG_COMM); + return; + } + + //Call back function + pn512_transceive_hw_tx_iteration(pPN512, false); +} + +void pn512_transceive_hw_rx_start(pn512_t *pPN512) +{ + uint16_t irqs_en = PN512_IRQ_RX | PN512_IRQ_HIGH_ALERT | PN512_IRQ_ERR; + if (PN512_FRAMING_IS_TARGET(pPN512->framing)) { + irqs_en |= PN512_IRQ_RF_OFF; + } + + pn512_irq_set(pPN512, irqs_en); + + //Reset buffer except if data should be appended to this -- TODO + ac_buffer_builder_reset(&pPN512->readBufBldr); + + //Queue task to process IRQ + task_init(&pPN512->transceiver.task, EVENT_HW_INTERRUPT | EVENT_TIMEOUT, + pPN512->timeout, pn512_transceive_hw_rx_task, pPN512); + nfc_scheduler_queue_task(&pPN512->transceiver.scheduler, + &pPN512->transceiver.task); +} + +void pn512_transceive_hw_rx_task(uint32_t events, void *pUserData) +{ + pn512_t *pPN512 = (pn512_t *) pUserData; + + NFC_DBG("RX task"); + if (events & EVENT_ABORTED) { + //Stop command + pn512_cmd_exec(pPN512, PN512_CMD_IDLE); + pPN512->transceive.mode = pn512_transceive_mode_idle; + + NFC_ERR("Aborted RX"); + + pn512_irq_set(pPN512, PN512_IRQ_NONE); + pn512_irq_clear(pPN512, PN512_IRQ_ALL); + + pn512_transceive_callback(pPN512, NFC_ERR_ABORTED); + return; + } + + if (events & EVENT_TIMEOUT) { + NFC_WARN("Timeout"); + //Stop command + pn512_cmd_exec(pPN512, PN512_CMD_IDLE); + pPN512->transceive.mode = pn512_transceive_mode_idle; + + pn512_irq_set(pPN512, PN512_IRQ_NONE); + pn512_irq_clear(pPN512, PN512_IRQ_ALL); + + //Call callback + pn512_transceive_callback(pPN512, NFC_ERR_TIMEOUT); + return; + } + + uint16_t irqs = pn512_irq_get(pPN512); + NFC_DBG("irqs %04x", irqs); + bool collision_detected = false; + if (irqs & PN512_IRQ_ERR) { + pn512_irq_clear(pPN512, PN512_IRQ_ERR); + + uint8_t err_reg = pn512_register_read(pPN512, PN512_REG_ERROR); + NFC_ERR("Got error - error reg is %02X", err_reg); + // if err_reg == 0, sticky error that must have been cleared automatically, continue + if (err_reg != 0) { + //If it's a collsision, flag it but still carry on with RX procedure + collision_detected = true; + + if ((err_reg == 0x08) || (err_reg == 0x0A)) { // Collision (and maybe parity) (and no other error) + irqs &= ~PN512_IRQ_ERR; + irqs |= PN512_IRQ_RX; + } else { + NFC_DBG_BLOCK( + //Empty FIFO into buffer + pn512_fifo_read(pPN512, &pPN512->readBufBldr); + + NFC_DBG("Received"); + ac_buffer_dump(ac_buffer_builder_buffer(&pPN512->readBufBldr)); + + NFC_DBG("Computed CRC = %02X %02X", pn512_register_read(pPN512, PN512_REG_CRCRESULT_MSB), pn512_register_read(pPN512, PN512_REG_CRCRESULT_LSB)); + + ) + + //Stop command + pn512_cmd_exec(pPN512, PN512_CMD_IDLE); + pPN512->transceive.mode = pn512_transceive_mode_idle; + + pn512_irq_set(pPN512, PN512_IRQ_NONE); + pn512_irq_clear(pPN512, PN512_IRQ_ALL); + + //Call callback + pn512_transceive_callback(pPN512, NFC_ERR_WRONG_COMM); + return; + } + } + } + if ((irqs & PN512_IRQ_RX) || (irqs & PN512_IRQ_HIGH_ALERT)) { + //Empty FIFO into buffer + pn512_fifo_read(pPN512, &pPN512->readBufBldr); + + if ((ac_buffer_builder_writable(&pPN512->readBufBldr) == 0) && (pn512_fifo_length(pPN512) > 0)) { + //Stop command + pn512_cmd_exec(pPN512, PN512_CMD_IDLE); + pPN512->transceive.mode = pn512_transceive_mode_idle; + + NFC_WARN("RX buffer overflow"); + + pn512_irq_set(pPN512, PN512_IRQ_NONE); + pn512_irq_clear(pPN512, PN512_IRQ_ALL); + //Call callback + pn512_transceive_callback(pPN512, NFC_ERR_BUFFER_TOO_SMALL); + return; //overflow + } + + if (irqs & PN512_IRQ_HIGH_ALERT) { + NFC_DBG("High alert"); + pn512_irq_clear(pPN512, PN512_IRQ_HIGH_ALERT); + } + + if (irqs & PN512_IRQ_RX) { + pn512_irq_clear(pPN512, PN512_IRQ_RX); + + size_t last_byte_length = pn512_register_read(pPN512, PN512_REG_CONTROL) & 0x7; + if (last_byte_length == 0) { + last_byte_length = 8; + } + pPN512->readLastByteLength = last_byte_length; + + pn512_irq_set(pPN512, PN512_IRQ_NONE); + pn512_irq_clear(pPN512, PN512_IRQ_RX | PN512_IRQ_HIGH_ALERT); + + NFC_DBG("Received:"); + NFC_DBG_BLOCK(ac_buffer_dump(ac_buffer_builder_buffer(&pPN512->readBufBldr));) + + if ((pPN512->transceive.mode == pn512_transceive_mode_target_autocoll) || (pPN512->transceive.mode == pn512_transceive_mode_transmit_and_target_autocoll)) { + //Check if target was activated + if (!(pn512_register_read(pPN512, PN512_REG_STATUS2) & 0x10)) { + pPN512->transceive.mode = pn512_transceive_mode_idle; + + pn512_irq_set(pPN512, PN512_IRQ_NONE); + pn512_irq_clear(pPN512, PN512_IRQ_ALL); + //Call callback + pn512_transceive_callback(pPN512, NFC_ERR_PROTOCOL); + return; + } + //PN512 switches to transceive automatically + pPN512->transceive.mode = pn512_transceive_mode_transceive; + } else if (pPN512->transceive.mode == pn512_transceive_mode_receive) { + pPN512->transceive.mode = pn512_transceive_mode_transceive; + //pn512_cmd_exec(pPN512, PN512_CMD_IDLE); //Useful? + } + + if (!collision_detected) { + pn512_transceive_callback(pPN512, NFC_OK); + } else { + pn512_transceive_callback(pPN512, NFC_ERR_COLLISION); + } + + return; + } + } + if (irqs & PN512_IRQ_RF_OFF) { + //Stop command + pn512_cmd_exec(pPN512, PN512_CMD_IDLE); + pPN512->transceive.mode = pn512_transceive_mode_idle; + + pn512_irq_set(pPN512, PN512_IRQ_NONE); + pn512_irq_clear(pPN512, PN512_IRQ_ALL); + + //Call callback + pn512_transceive_callback(pPN512, NFC_ERR_FIELD); + return; + } + + //Queue task to process IRQ + task_init(&pPN512->transceiver.task, EVENT_HW_INTERRUPT | EVENT_TIMEOUT, + pPN512->timeout, pn512_transceive_hw_rx_task, pPN512); + nfc_scheduler_queue_task(&pPN512->transceiver.scheduler, + &pPN512->transceiver.task); +} + +void pn512_transceive_hw(pn512_t *pPN512, pn512_transceive_mode_t mode, pn512_cb_t cb) +{ + uint16_t irqs_en; + + //Store callback + pPN512->transceive.cb = cb; + + //Clear FIFO + pn512_fifo_clear(pPN512); + + //Clear previous IRQs if present + pn512_irq_clear(pPN512, PN512_IRQ_RX | PN512_IRQ_TX | PN512_IRQ_HIGH_ALERT | PN512_IRQ_LOW_ALERT | PN512_IRQ_ERR | PN512_IRQ_IDLE | PN512_IRQ_RF_OFF); + + if (PN512_FRAMING_IS_TARGET(pPN512->framing)) { + //RF off? + if (!(pn512_register_read(pPN512, PN512_REG_STATUS1) & 0x04)) { + //Call callback + pn512_transceive_callback(pPN512, NFC_ERR_FIELD); + return; + } + } else if ((pPN512->transceive.mode != mode) && (mode == pn512_transceive_mode_transceive)) { + pn512_cmd_exec(pPN512, PN512_CMD_TRANSCEIVE); + } + + pPN512->transceive.mode = mode; + + if (mode == pn512_transceive_mode_receive) { + pn512_cmd_exec(pPN512, PN512_CMD_IDLE); + pn512_transceive_hw_rx_start(pPN512); + pn512_cmd_exec(pPN512, PN512_CMD_TRANSCEIVE); + } else if (mode == pn512_transceive_mode_target_autocoll) { + //Make sure bitframing reg is clean + pn512_register_write(pPN512, PN512_REG_BITFRAMING, 0x00); + + pn512_transceive_hw_rx_start(pPN512); + + //Start autocoll + pn512_cmd_exec(pPN512, PN512_CMD_AUTOCOLL); + return; + } else { + NFC_DBG("Sending:"); + NFC_DBG_BLOCK(ac_buffer_dump(&pPN512->writeBuf);) + + //Transmit a frame to remote target/initiator + irqs_en = PN512_IRQ_TX | PN512_IRQ_IDLE; + if (PN512_FRAMING_IS_TARGET(pPN512->framing)) { + irqs_en |= PN512_IRQ_RF_OFF; + } + + pn512_irq_set(pPN512, irqs_en); + + pn512_transceive_hw_tx_iteration(pPN512, true); + } +} + + + diff --git a/connectivity/drivers/nfc/PN512/source/transceiver/pn512_transceive.h b/connectivity/drivers/nfc/PN512/source/transceiver/pn512_transceive.h new file mode 100644 index 0000000..1c3f224 --- /dev/null +++ b/connectivity/drivers/nfc/PN512/source/transceiver/pn512_transceive.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2014-2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + */ +/** + * \file pn512_transceive.h + * \copyright Copyright (c) ARM Ltd 2014 + * \author Donatien Garnier + */ + +#ifndef PN512_TRANSCEIVE_H_ +#define PN512_TRANSCEIVE_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "stack/nfc_common.h" +#include "pn512.h" + +void pn512_transceive_hw(pn512_t *pPN512, pn512_transceive_mode_t mode, pn512_cb_t cb); + +void pn512_transceive_hw_tx_task(uint32_t events, void *pUserData); +void pn512_transceive_hw_tx_iteration(pn512_t *pPN512, bool start); + +void pn512_transceive_hw_rx_start(pn512_t *pPN512); +void pn512_transceive_hw_rx_task(uint32_t events, void *pUserData); + + +#ifdef __cplusplus +} +#endif + +#endif /* PN512_TRANSCEIVE_H_ */ diff --git a/connectivity/drivers/nfc/PN512/source/transceiver/pn512_types.h b/connectivity/drivers/nfc/PN512/source/transceiver/pn512_types.h new file mode 100644 index 0000000..efefefd --- /dev/null +++ b/connectivity/drivers/nfc/PN512/source/transceiver/pn512_types.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2015-2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + */ +/** + * \file pn512_types.h + * \copyright Copyright (c) ARM Ltd 2015 + * \author Donatien Garnier + */ + +#ifndef TRANSCEIVER_PN512_PN512_TYPES_H_ +#define TRANSCEIVER_PN512_PN512_TYPES_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "stack/nfc_common.h" + +typedef struct __pn512 pn512_t; + +typedef struct __pn512_registers { + int8_t registers_page; +} pn512_registers_t; + + + +#ifdef __cplusplus +} +#endif + +#endif /* TRANSCEIVER_PN512_PN512_TYPES_H_ */ diff --git a/connectivity/nfc/include/nfc/NFC.h b/connectivity/nfc/include/nfc/NFC.h new file mode 100644 index 0000000..38cfe23 --- /dev/null +++ b/connectivity/nfc/include/nfc/NFC.h @@ -0,0 +1,31 @@ +/* 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. + */ + +#ifndef MBED_NFC_H +#define MBED_NFC_H + +// Convenience header + +// NFC Controller +#include "NFCController.h" + +// NFC EEPROM +#include "NFCEEPROM.h" + +// Type 4 Remote Initiator +#include "Type4RemoteInitiator.h" + +#endif diff --git a/connectivity/nfc/include/nfc/NFCController.h b/connectivity/nfc/include/nfc/NFCController.h new file mode 100644 index 0000000..df55292 --- /dev/null +++ b/connectivity/nfc/include/nfc/NFCController.h @@ -0,0 +1,184 @@ +/* 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. + */ + +#ifndef MBED_NFC_CONTROLLER_H +#define MBED_NFC_CONTROLLER_H + +#include +#include "events/EventQueue.h" +#include "platform/SharedPtr.h" +#include "drivers/Timer.h" +#include "drivers/Timeout.h" + +#include "NFCDefinitions.h" +#include "NFCControllerDriver.h" + +#include "platform/Span.h" + +namespace mbed { +namespace nfc { + +/** @addtogroup nfc + * @{ + */ + +class NFCRemoteInitiator; +class NFCRemoteTarget; +class NFCControllerDriver; + +/** + * This class represents a NFC Controller. + * + * A controller can be in one of three different states: + * * Idle/sleep state + * * Discovery state: The controller tries to discover a remote endpoint (initiator or target) + * * Connected state: The controller exchanges data with an endpoint (initiator or target) + * + * A NFCController instance needs to be initialized with a NFCControllerDriver instance which abstracts the specific controller being used. + * A delegate needs to be set by the user to receive discovery events. + */ +class NFCController : private NFCControllerDriver::Delegate { +public: + + /** + * The NFCController delegate. Users of the NFCController class need to implement this delegate's methods to receive events. + */ + struct Delegate { + /** + * A enumeration of causes for the discovery process terminating. + */ + enum nfc_discovery_terminated_reason_t { + nfc_discovery_terminated_completed = 0, ///< Process completed, at least one endpoint was discovered + nfc_discovery_terminated_canceled, ///< Process was canceled by the user + nfc_discovery_terminated_rf_error ///< An unexpected error was encountered during an exchange on the air interface + }; + + /** + * The discovery process terminated. + * @param[in] reason the cause for the termination + */ + virtual void on_discovery_terminated(nfc_discovery_terminated_reason_t reason) {} + + /** + * A remote initiator was discovered (the local controller is in target mode). + * @param[in] nfc_initiator the NFCRemoteInitiator instance + */ + virtual void on_nfc_initiator_discovered(const SharedPtr &nfc_initiator) {} + + /** + * A remote target was discovered (the local controller is in initiator mode). + * @param[in] nfc_target the NFCRemoteTarget instance + */ + virtual void on_nfc_target_discovered(const SharedPtr &nfc_target) {} + + protected: + ~Delegate() { } + }; + + /** + * Construct a NFCController instance. + * + * @param[in] driver a pointer to a NFCControllerDriver instance + * @param[in] queue a pointer to the events queue to use + * @param[in] ndef_buffer a bytes array used to store NDEF messages + */ + NFCController(NFCControllerDriver *driver, events::EventQueue *queue, const Span &ndef_buffer); + + /** + * Initialize the NFC controller + * + * 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 controller. + * + * @param[in] delegate the delegate instance to use + */ + void set_delegate(Delegate *delegate); + + /** + * Get the list of RF protocols supported by this controller. + * + * @return a bitmask of RF protocols supported by the controller + */ + nfc_rf_protocols_bitmask_t get_supported_rf_protocols() const; + + /** + * Set the list of RF protocols to look for during discovery. + * + * @param[in] rf_protocols the relevant bitmask + * @return NFC_OK on success, or + * NFC_ERR_UNSUPPORTED if a protocol is not supported by the controller, + * NFC_ERR_BUSY if the discovery process is already running + */ + nfc_err_t configure_rf_protocols(nfc_rf_protocols_bitmask_t rf_protocols); + + /** + * Start the discovery process using the protocols configured previously. + * + * If remote endpoints are connected when this is called, they will be disconnected. + * + * @return NFC_OK on success, or + * NFC_ERR_BUSY if the discovery process is already running + */ + nfc_err_t start_discovery(); + + /** + * Cancel/stop a running discovery process. + * + * @return NFC_OK + */ + nfc_err_t cancel_discovery(); + +private: + // These two classes need to be friends to access the following transceiver() method + friend class NFCRemoteEndpoint; + friend class Type4RemoteInitiator; + nfc_transceiver_t *transceiver() const; + + void polling_callback(nfc_err_t ret); + + // NFC Stack scheduler + void scheduler_process(bool hw_interrupt); + + // Callbacks from NFC stack + static void s_polling_callback(nfc_transceiver_t *pTransceiver, nfc_err_t ret, void *pUserData); + + // Implementation of NFCControllerDriver::Delegate + virtual void on_hw_interrupt(); + + // Triggers when scheduler must be run again + void on_timeout(); + + NFCControllerDriver *_driver; + events::EventQueue *_queue; + nfc_transceiver_t *_transceiver; + nfc_scheduler_t *_scheduler; + Timer _timer; + Timeout _timeout; + Delegate *_delegate; + bool _discovery_running; + Span _ndef_buffer; +}; +/** @}*/ +} // namespace nfc +} // namespace mbed + +#endif diff --git a/connectivity/nfc/include/nfc/NFCControllerDriver.h b/connectivity/nfc/include/nfc/NFCControllerDriver.h new file mode 100644 index 0000000..db78cfb --- /dev/null +++ b/connectivity/nfc/include/nfc/NFCControllerDriver.h @@ -0,0 +1,104 @@ +/* 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. + */ + +#ifndef MBED_NFC_CONTROLLER_DRIVER_H +#define MBED_NFC_CONTROLLER_DRIVER_H + +#include +#include "events/EventQueue.h" + +#include "stack/nfc_errors.h" +#include "stack/transceiver/transceiver.h" +#include "stack/platform/nfc_scheduler.h" + +namespace mbed { +namespace nfc { + +/** + * @addtogroup nfc + * @{ + */ + +/** + * The abstraction for a NFC controller driver. + * Implementers need to derive from this class and implement its methods. + */ +class NFCControllerDriver { +public: + /** + * Instantiate a NFCControllerDriver + */ + NFCControllerDriver(); + + /** + * NFCControllerDriver destructor + */ + virtual ~NFCControllerDriver(); + + /** + * The NFCControllerDriver delegate + */ + struct Delegate { + /** + * Called when the controller asserts the interrupt line + */ + virtual void on_hw_interrupt() {} + + protected: + ~Delegate() {} + }; + + /** + * Initialize the driver and retrieve the interface to the controller. + * + * @param[in] scheduler_timer a timer to initialize the controller's scheduler instance with + * @return an initialized MicroNFC nfc_transceiver_t instance + */ + virtual nfc_transceiver_t *initialize(nfc_scheduler_timer_t *scheduler_timer) = 0; + + /** + * Retrieve list of technologies supported by the controller + * @param[out] initiator bitmask of technologies supported when the controller is in initiator mode + * @param[out] target bitmask of technologies supported when the controller is in target mode + */ + virtual void get_supported_nfc_techs(nfc_tech_t *initiator, nfc_tech_t *target) const = 0; + + /** + * Set this instance's delegate + * + * @param[in] delegate the delegate instance to use + */ + void set_delegate(Delegate *delegate); + +protected: + /** + * An implementation must call this function (can be called from interrupt context) + * when the controller asserts its interrupt line + */ + void hw_interrupt(); + +private: + Delegate *_delegate; +}; + +/** + * @} + */ + +} // namespace nfc +} // namespace mbed + +#endif diff --git a/connectivity/nfc/include/nfc/NFCDefinitions.h b/connectivity/nfc/include/nfc/NFCDefinitions.h new file mode 100644 index 0000000..0c1d3ce --- /dev/null +++ b/connectivity/nfc/include/nfc/NFCDefinitions.h @@ -0,0 +1,57 @@ +/* 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. + */ + +#ifndef MBED_NFC_DEFINITIONS_H +#define MBED_NFC_DEFINITIONS_H + +#include +#include + +#include "stack/nfc_errors.h" + +#include "acore/ac_buffer.h" + +namespace mbed { +namespace nfc { +struct nfc_rf_protocols_bitmask_t { + bool initiator_t1t : 1; + bool initiator_t2t : 1; + bool initiator_t3t : 1; + bool initiator_iso_dep : 1; + bool initiator_nfc_dep : 1; + bool initiator_t5t : 1; + + bool target_t1t : 1; + bool target_t2t : 1; + bool target_t3t : 1; + bool target_iso_dep : 1; + bool target_nfc_dep : 1; + bool target_t5t : 1; +}; + +enum nfc_tag_type_t { + nfc_tag_type_1, + nfc_tag_type_2, + nfc_tag_type_3, + nfc_tag_type_4a, + nfc_tag_type_4b, + nfc_tag_type_5 +}; + +} // namespace nfc +} // namespace mbed + +#endif diff --git a/connectivity/nfc/include/nfc/NFCEEPROM.h b/connectivity/nfc/include/nfc/NFCEEPROM.h new file mode 100644 index 0000000..ed0deb3 --- /dev/null +++ b/connectivity/nfc/include/nfc/NFCEEPROM.h @@ -0,0 +1,159 @@ +/* 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. + */ + +#ifndef MBED_NFC_EEPROM_H +#define MBED_NFC_EEPROM_H + +#include +#include "events/EventQueue.h" + +#include "NFCDefinitions.h" +#include "NFCTarget.h" +#include "NFCEEPROMDriver.h" + +namespace mbed { +namespace nfc { + +/** @addtogroup nfc + * @{ + */ + +/** + * The NFC EEPROM class represents a NFC target device connected using a wired + * link (I2C, SPI, etc). + * + * These EEPROMs essentially provide addressable memory that can be accessed + * using either a wired or NFC interface. + * + * In NFC mode these most often conform to one of the NFC tag types defined + * by the NFC Forum, therefore encoding NDEF data in these EEPROMs will + * ensure that it is understandable by a NFC reader. + */ +class NFCEEPROM : public NFCTarget, public NFCEEPROMDriver::Delegate { +public: + /** + * 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 + */ + NFCEEPROM(NFCEEPROMDriver *driver, events::EventQueue *queue, const Span &ndef_buffer); + + /** + * The NFCEEPROM delegate. Users of the NFCEEPROM class need to implement this delegate's methods to receive events. + */ + struct Delegate : NFCTarget::Delegate { + /** + * The NDEF message erasing request completed. + * + * @param[in] result NFC_OK or an error code on failure + */ + virtual void on_ndef_message_erased(nfc_err_t result) {} + + /** + * The NDEF message writing request completed. + * + * @param[in] result NFC_OK or an error code on failure + */ + virtual void on_ndef_message_written(nfc_err_t result) {} + + /** + * The NDEF message reading request completed. + * + * @param[in] result NFC_OK or an error code on failure + */ + virtual void on_ndef_message_read(nfc_err_t result) {} + + protected: + ~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. + * + * @param[in] delegate the delegate instance to use + */ + void set_delegate(Delegate *delegate); + + // Implementation of NFCTarget + virtual void write_ndef_message(); + virtual void read_ndef_message(); + virtual void erase_ndef_message(); + +private: + // 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_written(bool success); + virtual void on_size_read(bool success, size_t size); + virtual void on_bytes_erased(size_t count); + + void handle_error(nfc_err_t ret); + void continue_write(); + void continue_read(); + void continue_erase(); + + // NFCNDEFCapable implementation + virtual NFCNDEFCapable::Delegate *ndef_capable_delegate(); + + enum nfc_eeprom_operation_t { + nfc_eeprom_idle, + + nfc_eeprom_write_start_session, + nfc_eeprom_write_write_size, + nfc_eeprom_write_write_bytes, + nfc_eeprom_write_end_session, + + nfc_eeprom_read_start_session, + nfc_eeprom_read_read_size, + nfc_eeprom_read_read_bytes, + nfc_eeprom_read_end_session, + + nfc_eeprom_erase_start_session, + nfc_eeprom_erase_write_max_size, + nfc_eeprom_erase_erase_bytes, + nfc_eeprom_erase_write_0_size, + nfc_eeprom_erase_end_session + }; + + Delegate *_delegate; + NFCEEPROMDriver *_driver; + events::EventQueue *_event_queue; + bool _initialized; + + nfc_eeprom_operation_t _current_op; + ac_buffer_t _ndef_buffer_reader; + size_t _ndef_buffer_read_sz; + uint32_t _eeprom_address; + nfc_err_t _operation_result; +}; +/** @}*/ +} // namespace nfc +} // namespace mbed + +#endif diff --git a/connectivity/nfc/include/nfc/NFCEEPROMDriver.h b/connectivity/nfc/include/nfc/NFCEEPROMDriver.h new file mode 100644 index 0000000..f190e54 --- /dev/null +++ b/connectivity/nfc/include/nfc/NFCEEPROMDriver.h @@ -0,0 +1,203 @@ +/* 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. + */ + +#ifndef MBED_NFC_EEPROM_DRIVER_H +#define MBED_NFC_EEPROM_DRIVER_H + +#include + +#include "events/EventQueue.h" + +namespace mbed { +namespace nfc { + +/** + * @addtogroup nfc + * @{ + */ + +/** + * The abstraction for a NFC EEPROM driver. + * Implementers need to derive from this class and implement its methods. + */ +class NFCEEPROMDriver { +public: + /** + * Construct a NFCEEPROM driver instance. + */ + NFCEEPROMDriver(); + + /** + * NFCEEPROM driver destructor. + */ + virtual ~NFCEEPROMDriver(); + + /** + * The NFCEEPROMDriver delegate. + * Methods in this class are called by the driver on completion of long-running operations. + */ + struct Delegate { + /** + * Completion of session start operation. + * + * @param[in] success whether this operation succeeded + */ + virtual void on_session_started(bool success) = 0; + + /** + * Completion of session end operation. + * + * @param[in] success whether this operation succeeded + */ + virtual void on_session_ended(bool success) = 0; + + /** + * Completion of read operation. + * + * @param[in] count number of bytes actually read + */ + virtual void on_bytes_read(size_t count) = 0; + + /** + * Completion of write operation. + * + * @param[in] count number of bytes actually written + */ + virtual void on_bytes_written(size_t count) = 0; + + /** + * Completion of size retrieval operation. + * + * @param[in] success whether this operation succeeded + * @param[out] size the current addressable memory size + */ + virtual void on_size_read(bool success, size_t size) = 0; + + /** + * Completion of size setting operation. + * + * @param[in] success whether this operation succeeded + */ + virtual void on_size_written(bool success) = 0; + + /** + * Completion of erasing operation. + * + * @param[in] count number of bytes actually erased + */ + virtual void on_bytes_erased(size_t count) = 0; + + protected: + ~Delegate() {} + }; + + /** + * Set the delegate that will receive events generated by this EEPROM. + * + * @param[in] delegate the delegate instance to use + */ + void set_delegate(Delegate *delegate); + + /** + * Set the event queue that will be used to schedule event handling + * + * @param[in] queue the queue instance to use + */ + void set_event_queue(events::EventQueue *queue); + + /** + * Reset and initialize the EEPROM. + * This method should complete synchronously. + */ + virtual void reset() = 0; + + /** + * Get the maximum memory size addressable by the EEPROM. + */ + virtual size_t read_max_size() = 0; + + /** + * Start a session of operations (reads, writes, erases, size gets/sets). + * This method is called prior to any memory access to allow the underlying implementation + * to disable the RF interface or abort the transaction if it's being used. + * This method should complete asynchronously by calling has_started_session(). + */ + virtual void start_session(bool force = true) = 0; // This could lock the chip's RF interface + + /** + * End a session. + * This method should complete asynchronously by calling has_ended_session(). + */ + virtual void end_session() = 0; + + /** + * Read bytes from memory. + * @param[in] address the virtual address (starting from 0) from which to start the read. + * @param[out] bytes a buffer in which the read bytes will be stored. + * This buffer should remain valid till the callback is called. + * @param[in] count the number of bytes to read. + * This method should complete asynchronously by calling has_read_bytes(). + */ + virtual void read_bytes(uint32_t address, uint8_t *bytes, size_t count) = 0; + + /** + * Write bytes to memory. + * @param[in] address the virtual address (starting from 0) from which to start the write. + * @param[in] bytes a buffer from to copy. + * This buffer should remain valid till the callback is called. + * @param[in] count the number of bytes to write. + * This method should complete asynchronously by calling has_written_bytes(). + */ + virtual void write_bytes(uint32_t address, const uint8_t *bytes, size_t count) = 0; + + /** + * Retrieve the size of the addressable memory. + * This method should complete asynchronously by calling has_gotten_size(). + */ + virtual void read_size() = 0; + + /** + * Set the size of the addressable memory. + * @param[in] count the number of addressable bytes. + * This method should complete asynchronously by calling has_set_size(). + */ + virtual void write_size(size_t count) = 0; + + /** + * Erase bytes from memory. + * @param[in] address the virtual address (starting from 0) from which to start erasing. + * @param[in] size the number of bytes to erase. + * This method should complete asynchronously by calling has_erased_bytes(). + */ + virtual void erase_bytes(uint32_t address, size_t size) = 0; + +protected: + Delegate *delegate(); + events::EventQueue *event_queue(); + +private: + Delegate *_delegate; + events::EventQueue *_event_queue; +}; + +/** + * @} + */ + +} // namespace nfc +} // namespace mbed + +#endif diff --git a/connectivity/nfc/include/nfc/NFCNDEFCapable.h b/connectivity/nfc/include/nfc/NFCNDEFCapable.h new file mode 100644 index 0000000..46f718d --- /dev/null +++ b/connectivity/nfc/include/nfc/NFCNDEFCapable.h @@ -0,0 +1,130 @@ +/* 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. + */ + +#ifndef MBED_NFC_NDEF_CAPABLE_H +#define MBED_NFC_NDEF_CAPABLE_H + +#include + +#include "platform/Span.h" + +#include "NFCDefinitions.h" + +#include "stack/ndef/ndef.h" +#include "acore/acore/ac_buffer.h" +#include "acore/acore/ac_buffer_reader.h" +#include "acore/acore/ac_buffer_builder.h" + +namespace mbed { +namespace nfc { + +/** + * @addtogroup nfc + * @{ + */ + +/** + * The base class for all endpoints that can support NDEF content. + */ +class NFCNDEFCapable { +public: + /** + * Construct a NFCNDEFCapable instance. + * @param[in] buffer a bytes array used to store NDEF messages + */ + NFCNDEFCapable(const Span &buffer); + + /** + * Check if this instance actually supports NDEF content. + * + * @return whether NDEF content is supported + */ + virtual bool is_ndef_supported() const + { + return false; + } + + struct Delegate { + /** + * Parse a NDEF message. + * + * @param[in] buffer a buffer containing the message to parse + */ + virtual void parse_ndef_message(const Span &buffer) { } + + /** + * Build a NDEF message. + * + * @param[in] buffer a mutable buffer in which the message should be stored + * + * @return the number of bytes actually used + */ + virtual size_t build_ndef_message(const Span &buffer) + { + return 0; + } + + protected: + ~Delegate() {} + }; + +protected: + /** + * Parse a NDEF message. + * + * @param[in] buffer a buffer containing a NDEF message + */ + void parse_ndef_message(const ac_buffer_t &buffer); + + /** + * Build NDEF message. + * + * @param[in,out] buffer_builder a buffer builder in which to create the NDEF message. + * The backing buffer is guaranteed to be continuous. + */ + void build_ndef_message(ac_buffer_builder_t &buffer_builder); + + /** + * Retrieve underlying NDEF message instance + * @return pointer to NDEF message instance + */ + ndef_msg_t *ndef_message(); + +private: + /** + * Get the delegate that will receive events generated by this class. + * + * @return the delegate instance to use + */ + virtual Delegate *ndef_capable_delegate(); + + // Callbacks from NDEF stack + static nfc_err_t s_ndef_encode(ndef_msg_t *pTag, ac_buffer_builder_t *pBufferBldr, void *pUserData); + static nfc_err_t s_ndef_decode(ndef_msg_t *pTag, ac_buffer_t *pBuffer, void *pUserData); + nfc_err_t ndef_encode(ac_buffer_builder_t *pBufferBldr); + nfc_err_t ndef_decode(ac_buffer_t *pBuffer); + + ndef_msg_t _ndef_message; +}; + +/** + * @} + */ + +} // namespace nfc +} // namespace mbed + +#endif diff --git a/connectivity/nfc/include/nfc/NFCRemoteEndpoint.h b/connectivity/nfc/include/nfc/NFCRemoteEndpoint.h new file mode 100644 index 0000000..7d2916c --- /dev/null +++ b/connectivity/nfc/include/nfc/NFCRemoteEndpoint.h @@ -0,0 +1,135 @@ +/* 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. + */ + +#ifndef MBED_NFC_REMOTE_ENDPOINT_H +#define MBED_NFC_REMOTE_ENDPOINT_H + +#include + +#include "NFCDefinitions.h" + +namespace mbed { +namespace nfc { + +/** + * @addtogroup nfc + * @{ + */ + +class NFCController; + +/** + * This is the base class for all remote endpoints (initiators and targets) + * addressable over the air interface. + */ +class NFCRemoteEndpoint { +public: + /** + * Create a NFCRemoteEndpointinstance + * @param[in] controller the NFCController instance that detected this endpoint + */ + NFCRemoteEndpoint(NFCController *controller); + + /** + * Destructor + */ + virtual ~NFCRemoteEndpoint(); + + /** + * The NFCRemoteEndpoint base delegate. + */ + struct Delegate { + /** + * This method is called when the endpoint is connected + */ + virtual void on_connected() {} + + /** + * This method is called when the endpoint is lost (air interface link disconnnected) + */ + virtual void on_disconnected() {} + + protected: + ~Delegate() {} + }; + + /** + * Connect the remote endpoint + * + * @return NFC_OK or an error code + */ + virtual nfc_err_t connect() = 0; + + /** + * Disconnect the remote endpoint + * + * @return NFC_OK or an error code + */ + virtual nfc_err_t disconnect() = 0; + + /** + * Check if the endpoint is connected. + * @return whether the endpoint is connected + */ + virtual bool is_connected() const = 0; + + /** + * Check if the endpoint is disconnected/lost. + * @return whether the endpoint has been disconnected + */ + virtual bool is_disconnected() const = 0; + + /** + * Get the list of RF protocols supported and activated over the air interface. + * @return a bitmask of activated protocols + */ + virtual nfc_rf_protocols_bitmask_t rf_protocols() = 0; + +protected: + /** + * Mark endpoint as connected + */ + virtual void connected() = 0; + + /** + * Mark endpoint as disconnected + */ + virtual void disconnected() = 0; + + /** + * Retrieve NFCController instance + * @return a pointer to the NFController instance that created this endpoint. + */ + NFCController *nfc_controller(); + + /** + * Retrieve NFCController instance + * @return a pointer to the NFController instance that created this endpoint. + */ + const NFCController *nfc_controller() const; + +private: + NFCController *_controller; +}; + +/** + * @} + */ + +} // namespace nfc +} // namespace mbed + +#endif diff --git a/connectivity/nfc/include/nfc/NFCRemoteInitiator.h b/connectivity/nfc/include/nfc/NFCRemoteInitiator.h new file mode 100644 index 0000000..b8cde88 --- /dev/null +++ b/connectivity/nfc/include/nfc/NFCRemoteInitiator.h @@ -0,0 +1,108 @@ +/* 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. + */ + +#ifndef MBED_NFC_REMOTE_INITIATOR_H +#define MBED_NFC_REMOTE_INITIATOR_H + +#include + +#include "NFCDefinitions.h" +#include "NFCRemoteEndpoint.h" +#include "NFCNDEFCapable.h" +#include "stack/tech/iso7816/iso7816_app.h" + +#include "platform/Span.h" + +namespace mbed { +namespace nfc { + +/** + * @addtogroup nfc + * @{ + */ + +class NFCController; + +/** + * This class represents a remote NFC initiator (the local controller being in target mode). + * + * An initiator can be a NFC reader, a NFC-enabled phone or other NFC device capable of generating a RF field. + */ +class NFCRemoteInitiator : public NFCRemoteEndpoint, public NFCNDEFCapable { +public: + /** + * Create a NFCRemoteInitiator. + * @param[in] controller the NFCController instance that detected this endpoint + * @param[in] buffer a bytes array used to store NDEF messages + */ + NFCRemoteInitiator(NFCController *controller, const Span &buffer); + virtual ~NFCRemoteInitiator(); + + /** + * The NFCRemoteInitiator delegate. Users of the NFCRemoteInitiator class need to implement this delegate's methods to receive events. + */ + struct Delegate : NFCRemoteEndpoint::Delegate, NFCNDEFCapable::Delegate { + protected: + ~Delegate() {} + }; + + /** + * Set the delegate that will receive events generated by the initiator. + * + * @param[in] delegate the delegate instance to use + */ + void set_delegate(Delegate *delegate); + + /** + * Retrieve the NFC tag type exposed by the controller to communicate with the initiator. + * + * @return the relevant NFC tag type + */ + virtual nfc_tag_type_t nfc_tag_type() const = 0; + + /** + * Retrieve whether ISO7816 applications are supported by the underlying technology. + * + * @return whether ISO7816 applications are supported + */ + virtual bool is_iso7816_supported() const = 0; + + /** + * Register an ISO7816 application to be used by the initiator. + * + * @param[in] application a pointer to an nfc_tech_iso7816_app_t instance as defined by the MuNFC stack + */ + virtual void add_iso7816_application(nfc_tech_iso7816_app_t *application) = 0; + +protected: + virtual void connected(); + virtual void disconnected(); + +private: + // NFCNDEFCapable implementation + virtual NFCNDEFCapable::Delegate *ndef_capable_delegate(); + + Delegate *_delegate; +}; + +/** + * @} + */ + +} // namespace nfc +} // namespace mbed + +#endif diff --git a/connectivity/nfc/include/nfc/NFCTarget.h b/connectivity/nfc/include/nfc/NFCTarget.h new file mode 100644 index 0000000..b80d835 --- /dev/null +++ b/connectivity/nfc/include/nfc/NFCTarget.h @@ -0,0 +1,109 @@ +/* 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. + */ + +#ifndef MBED_NFC_TARGET_H +#define MBED_NFC_TARGET_H + +#include + +#include "NFCDefinitions.h" +#include "NFCNDEFCapable.h" + +#include "platform/Span.h" + +namespace mbed { +namespace nfc { + +/** + * @addtogroup nfc + * @{ + */ + +/** + * This class represents a NFC target (either a remote target when the local controller in in initiator mode, or a target connected through a wired connection). + * + * A target can be a NFC tag/card, a NFC-enabled phone or other NFC device capable of modulating a RF field. + */ +class NFCTarget : public NFCNDEFCapable { +public: + /** + * Create a NFCTarget. + * + * @param[in] buffer a bytes array used to store NDEF messages + */ + NFCTarget(const Span &buffer); + + /** + * NFCTarget destructor + */ + virtual ~NFCTarget(); + + struct Delegate : NFCNDEFCapable::Delegate { + /** + * The NDEF message erasing request completed. + * + * @param[in] result NFC_OK or an error code on failure + */ + virtual void on_ndef_message_erased(nfc_err_t result) {} + + /** + * The NDEF message writing request completed. + * + * @param[in] result NFC_OK or an error code on failure + */ + virtual void on_ndef_message_written(nfc_err_t result) {} + + /** + * The NDEF message reading request completed. + * + * @param[in] result NFC_OK or an error code on failure + */ + virtual void on_ndef_message_read(nfc_err_t result) {} + + protected: + ~Delegate() {} + }; + + /** + * Write a NDEF message to the target. + * + * on_ndef_message_written() will be called on completion. + */ + virtual void write_ndef_message() = 0; + + /** + * Read a NDEF message from the target. + * + * on_ndef_message_read() will be called on completion. + */ + virtual void read_ndef_message() = 0; + + /** + * Erase the NDEF message in the target. + * + * on_ndef_message_erased() will be called on completion. + */ + virtual void erase_ndef_message() = 0; +}; + +/** + * @} + */ + +} // namespace nfc +} // namespace mbed + +#endif diff --git a/connectivity/nfc/include/nfc/Type4RemoteInitiator.h b/connectivity/nfc/include/nfc/Type4RemoteInitiator.h new file mode 100644 index 0000000..af71c7f --- /dev/null +++ b/connectivity/nfc/include/nfc/Type4RemoteInitiator.h @@ -0,0 +1,91 @@ +/* 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. + */ + +#ifndef MBED_TYPE4_REMOTE_INITIATOR_H +#define MBED_TYPE4_REMOTE_INITIATOR_H + +#include +#include + +#include "NFCNDEFCapable.h" +#include "NFCRemoteInitiator.h" + +#include "acore/acore/ac_buffer.h" +#include "acore/acore/ac_buffer_reader.h" +#include "acore/acore/ac_buffer_builder.h" +#include "stack/tech/type4/type4_target.h" + +#include "platform/Span.h" + +namespace mbed { +namespace nfc { + +/** + * @addtogroup nfc + * @{ + */ + +/** + * This class is an implementation of the Type 4 tag application. + */ +class Type4RemoteInitiator : public NFCRemoteInitiator { +public: + /** + * Create a Type4RemoteInitiator. + * + * @param[in] controller pointer to the NFCController instance that created this object + * @param[in] buffer a bytes array used to store NDEF messages + */ + Type4RemoteInitiator(NFCController *controller, const Span &buffer); + + /** + * Type4RemoteInitiator destructor. + */ + virtual ~Type4RemoteInitiator(); + + // NFCRemoteEndpoint implementation + virtual nfc_err_t connect(); + virtual nfc_err_t disconnect(); + virtual bool is_connected() const; + virtual bool is_disconnected() const; + virtual nfc_rf_protocols_bitmask_t rf_protocols(); + + // NFCRemoteInitiator implementation + virtual nfc_tag_type_t nfc_tag_type() const; + virtual bool is_iso7816_supported() const; + virtual void add_iso7816_application(nfc_tech_iso7816_app_t *application); + + // NFCNDEFCapable implementation + virtual bool is_ndef_supported() const; + + // Callbacks from NFC stack + void disconnected_callback(); + static void s_disconnected_callback(nfc_tech_iso7816_t *pIso7816, void *pUserData); + + bool _is_connected; + bool _is_disconnected; + nfc_tech_iso7816_t _iso7816; + nfc_tech_type4_target_t _type4; +}; + +/** + * @} + */ + +} // namespace nfc +} // namespace mbed + +#endif diff --git a/connectivity/nfc/include/nfc/ndef/MessageBuilder.h b/connectivity/nfc/include/nfc/ndef/MessageBuilder.h new file mode 100644 index 0000000..1b4e38e --- /dev/null +++ b/connectivity/nfc/include/nfc/ndef/MessageBuilder.h @@ -0,0 +1,196 @@ +/* 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. + */ + +#ifndef NFC_NDEF_MESSAGEBUILDER_H_ +#define NFC_NDEF_MESSAGEBUILDER_H_ + +#include + +#include "platform/Span.h" + +#include "nfc/ndef/Record.h" + +namespace mbed { +namespace nfc { +namespace ndef { + +/** @addtogroup nfc + * @{ + */ + +/** + * Construct a NDEF Message. + */ +class MessageBuilder { + +public: + /** + * Build a record payload. + */ + struct PayloadBuilder { + /** + * Return the size of the payload built by this object. + * + * @return The size of the payload. + */ + virtual size_t size() const = 0; + + /** + * Build the payload in a buffer that has the required size. + * + * @param buffer The buffer used to construct the payload. + */ + virtual void build(const Span &buffer) const = 0; + + protected: + /** + * Non virtual destructor. + */ + ~PayloadBuilder() { } + }; + + /** + * Create a new MessageBuilder that can be used to construct valid NDEF + * messages. + * + * @param buffer The data buffer that will contain the NDEF message. + */ + MessageBuilder(const Span &buffer); + + /** + * Append a new record to the message being built. + * + * @param type The type of the record to insert. + * @param payload The payload of the record (optional). + * @param is_last_record true if the record to insert is the last record of + * the payload or false otherwise. + * + * @return true if the record has been successfully inserted or false + * otherwise. + * + * @note insertion can fail if the message is already complete or if the + * size remaining in the message buffer is not large enough to makes the + * record inserted fit. + */ + bool append_record( + const RecordType &type, + const RecordPayload &payload = RecordPayload(), + bool is_last_record = false + ); + + /** + * Append a new record to the message being built. + * + * @param type The type of the record to insert. + * @param builder The builder of the payload. + * @param is_last_record true if the record to insert is the last record of + * the payload or false otherwise. + * + * @return true if the record has been successfully inserted or false + * otherwise. + * + * @note insertion can fail if the message is already complete or if the + * size remaining in the message buffer is not large enough to makes the + * record inserted fit. + */ + bool append_record( + const RecordType &type, + const PayloadBuilder &builder, + bool is_last_record = false + ); + + /** + * Append a new record to the message being built. + * + * @param record The record to insert. + * @param builder The builder that will construct the payload. + * + * @return true if the record has been successfully inserted or false otherwise. + * + * @note insertion can fail if the message is already complete or if the + * size remaining in the message buffer is not large enough to makes the + * record inserted fit. + */ + bool append_record( + const Record &record, + const PayloadBuilder *builder = NULL + ); + + /** + * Compute the size of a record. + * + * @param record The record used to compute the size. + * @param builder The payload builder if any. + * + * @return The size of the payload for the record in input. + */ + static size_t compute_record_size( + const Record &record, + const PayloadBuilder *builder = NULL + ); + + /** + * Reset the builder state. + */ + void reset(); + + /** + * Reset the builder state and assign a new buffer to it. + */ + void reset(const Span &buffer); + + /** + * Return true if the message stored is complete and false otherwise. + * + * @return true if the message is complete or false. + */ + bool is_message_complete() const; + + /** + * Return the buffer storing the data if the message is complete or an empty + * buffer if the message is not complete. + * + * @return The message built. + */ + Span get_message() const; + +private: + // append fields + void append_header(const Record &record, const PayloadBuilder *); + void append_type_length(const Record &record); + void append_payload_length(const Record &, const PayloadBuilder *); + void append_id_length(const Record &); + void append_type(const Record &); + void append_id(const Record &); + void append_payload(const Record &, const PayloadBuilder *); + + // helpers + static bool is_short_payload(const Record &record, const PayloadBuilder *); + static size_t get_payload_size(const Record &, const PayloadBuilder *); + + // builder state. + Span _message_buffer; + size_t _position; + bool _message_started; + bool _message_ended; + bool _in_chunk; +}; +/** @}*/ +} // namespace ndef +} // namespace nfc +} // namespace mbed + +#endif /* NFC_NDEF_MESSAGEBUILDER_H_ */ diff --git a/connectivity/nfc/include/nfc/ndef/MessageParser.h b/connectivity/nfc/include/nfc/ndef/MessageParser.h new file mode 100644 index 0000000..a0ac939 --- /dev/null +++ b/connectivity/nfc/include/nfc/ndef/MessageParser.h @@ -0,0 +1,171 @@ +/* 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. + */ + +#ifndef NFC_NDEF_MESSAGEPARSER_H_ +#define NFC_NDEF_MESSAGEPARSER_H_ + +#include +#include "platform/Span.h" + +namespace mbed { +namespace nfc { +namespace ndef { + +/** @addtogroup nfc + * @{ + */ + +// Forward declaration +class Record; + +/** + * Event driven NDEF Message parser + */ +class MessageParser { +public: + /** + * Error that can be reported by the parsing operation. + */ + enum error_t { + /** + * The message doesn't start with a message start tag. + */ + INVALID_MESSAGE_START, + + /** + * There is not enough data left to pursue parsing of the message. + */ + INSUFICIENT_DATA, + + /** + * The type name of a record is invalid. + */ + INVALID_TYPE_NAME_FORMAT, + + /** + * An empty record is malformed. + */ + INVALID_EMPTY_RECORD, + + /** + * Record of unknown type embed a type length different than 0. + */ + INVALID_UNKNOWN_TYPE_LENGTH, + + /** + * Record of unchanged type contains a type. + */ + INVALID_UNCHANGED_TYPE, + + /** + * Chunk record encountered. + */ + CHUNK_RECORD_NOT_SUPPORTED, + + /** + * Message is not properly closed. + */ + MISSING_MESSAGE_END, + + /** + * Type is missing in a record expecting a type (well known type, media + * type, absolute uri or external type). + */ + MISSING_TYPE_VALUE + }; + + /** + * Report parsing event to the application. + */ + struct Delegate { + /** + * Invoked when parsing as started. + */ + virtual void on_parsing_started() { } + + /** + * Invoked when a record has been parsed. + * + * @param record The record obtained from parsing. + */ + virtual void on_record_parsed(const Record &record) { } + + /** + * Invoked when parsing is over. + */ + virtual void on_parsing_terminated() { } + + /** + * Invoked when an error is present in the message. + * @param error The error present in the message. + */ + virtual void on_parsing_error(error_t error) { } + + protected: + /** + * Protected non virtual destructor. + * Delegate is not meant to be destroyed in a polymorphic manner. + */ + ~Delegate() { } + }; + + /** + * Construct a message parser. + */ + MessageParser(); + + /** + * Set the handler that processes parsing events. + * @param delegate The parsing event handler. + */ + void set_delegate(Delegate *delegate); + + /** + * Parse an NDEF Message. + * + * Records and errors are reported to the handler registered with + * set_event_handler. + * + * @param data_buffer The data buffer that contains the NDEF message. + */ + void parse(const Span &data_buffer); + +private: + struct parsing_state_t; + + // parser + bool parse_record(parsing_state_t &it); + + static uint8_t compute_lengths_size(uint8_t header); + static uint8_t extract_type_length(parsing_state_t &s); + static uint32_t extract_payload_length(parsing_state_t &s, uint8_t header); + static uint8_t extract_id_length(parsing_state_t &s, uint8_t header); + + // reporting + void report_parsing_started(); + void report_record_parsed(const Record &record); + void report_parsing_terminated(); + void report_parsing_error(error_t error, parsing_state_t &parsing_state); + + Delegate *_delegate; +}; +/** @}*/ +} // namespace ndef +} // namespace nfc +} // namespace mbed + + +#endif /* NFC_NDEF_MESSAGEPARSER_H_ */ diff --git a/connectivity/nfc/include/nfc/ndef/Record.h b/connectivity/nfc/include/nfc/ndef/Record.h new file mode 100644 index 0000000..7c6fcd2 --- /dev/null +++ b/connectivity/nfc/include/nfc/ndef/Record.h @@ -0,0 +1,216 @@ +/* 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. + */ + +#ifndef NFC_NDEF_RECORD_H_ +#define NFC_NDEF_RECORD_H_ + +#include + +#include "platform/Span.h" + +namespace mbed { +namespace nfc { +namespace ndef { + +/** + * @addtogroup nfc + * @{ + */ + + +/** + * Set of constants of a record header + */ +struct Header { + static const uint8_t message_begin_bit = (1 << 7); + static const uint8_t message_end_bit = (1 << 6); + static const uint8_t chunk_flag_bit = (1 << 5); + static const uint8_t short_record_bit = (1 << 4); + static const uint8_t id_length_bit = (1 << 3); + static const uint8_t tnf_bits = (1 << 0) | (1 << 1) | (1 << 2); +}; + +/** + * Encode a record type. + * + * A RecordType is composed of a type name format flag and an optional type + * value. + */ +struct RecordType { + /** + * Type name format of a record. + */ + enum tnf_t { + /** + * empty type; value must be empty. + */ + empty = 0x00, //!< empty + + /** + * Type defined by the NFC forum; value must be defined. + */ + well_known_type = 0x01,//!< well_known_type + + /** + * Mime type; value must be defined. + */ + media_type = 0x02, //!< media_type + + /** + * Absolute URI; value must be defined. + */ + absolute_uri = 0x03, //!< absolute_uri + + /** + * Type defined by vendors; value must be defined. + */ + external_type = 0x04, //!< external_type + + /** + * Unknown type; value must be empty. + */ + unknown = 0x05, //!< unknown + + /** + * Use for middle and terminating chunk record. + * value must be empty. + */ + unchanged = 0x06 //!< unchanged + }; + + /** + * Construct an unknown type. + */ + RecordType() : tnf(unknown), value() { } + + /** + * Construct a type with no value. + * + * @note Valid tnf are: empty, unknown and unchanged. + * + * @param tnf The type name format of the type. + */ + RecordType(tnf_t tnf) : + tnf(tnf), value() + { } + + /** + * Construct a RecordType from a type name format and its associated value. + * + * @param tnf The type name format of the record type. + * @param value The value associated with the tnf. + */ + RecordType(tnf_t tnf, const Span &value) : + tnf(tnf), value(value) + { } + + /** + * Type name format of the record type. + */ + tnf_t tnf; + + /** + * Value associated with the record type. It can be empty. + */ + Span value; +}; + +/** + * Definition of a Record payload. + * + * @note A payload can be empty. + */ +typedef Span RecordPayload; + +/** + * Definition of a Record IR. + * + * @note ID's are optional and therefore it can be empty. + */ +typedef Span RecordID; + +/** + * Represent a record. + */ +struct Record { + /** + * Construct an empty record. + */ + Record() : type(), payload(), id(), chunk(false), last_record(false) { } + + /** + * Construct a record from its type, payload and id. + * + * The flags chunk and last_record can be added to indicate if the record + * is aprt of a chunk or the last one in a message. + * + * @param type The type of the record. + * @param payload The payload of the record. + * @param id The id associated with the record. + * @param chunk If true then this record is a chunk of a bigger record. + * @param last_record If true then this record is the last of the message + * containing it. + */ + Record( + RecordType type, + const RecordPayload &payload, + const RecordID &id, + bool chunk, + bool last_record + ) : + type(type), + payload(payload), + id(id), + chunk(chunk), + last_record(last_record) + { } + + /** + * Type of the record. + */ + RecordType type; + + /** + * Value of the payload. + */ + RecordPayload payload; + + /** + * ID of the record. + */ + RecordID id; + + /** + * If true, this record is a chunked record. + */ + bool chunk: 1; + + /** + * If true, this record is the last one of the payload containing it. + */ + bool last_record: 1; +}; + + +/** + * @} + */ + +} // namespace ndef +} // namespace nfc +} // namespace mbed + +#endif /* NFC_NDEF_RECORD_H_ */ diff --git a/connectivity/nfc/include/nfc/ndef/RecordParser.h b/connectivity/nfc/include/nfc/ndef/RecordParser.h new file mode 100644 index 0000000..4c09078 --- /dev/null +++ b/connectivity/nfc/include/nfc/ndef/RecordParser.h @@ -0,0 +1,172 @@ +/* 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. + */ + +#ifndef NFC_NDEF_RECORDPARSER_H_ +#define NFC_NDEF_RECORDPARSER_H_ + +#include + +#include "nfc/ndef/Record.h" + +namespace mbed { +namespace nfc { +namespace ndef { + +/** + * @addtogroup nfc + * @{ + */ + +/** + * Parse a record. + */ +struct RecordParser { + /** + * Construct a record parser. + */ + RecordParser() : _next_parser(NULL) { } + + /** + * Parse the record in input. + * @param record The NDEF record to parse. + * @return true if decoding has succeeded and false otherwise. + */ + virtual bool parse(const Record &record) = 0; + +protected: + /** + * Protected non virtual destructor. + * RecordParser subclasses are not meant to be destroyed as RecordParser's. + */ + ~RecordParser() { } + +private: + friend class RecordParserChain; + RecordParser *_next_parser; +}; + + +/** + * GenericRecordParser. + * + * @tparam ParserImplementation the implementation type of the parser. + * It must provides A decoding function named do_parse that accept a const + * reference to a record and a reference to the type parsed and return a boolean + * status that indicates the result of the parsing operation. + * + * @tparam ParsingResult Type produced by the parsing operation when successful. + */ +template +struct GenericRecordParser : public RecordParser { + + /** + * Handle that receives parsed values. + */ + struct Delegate { + /** + * Called when a record has been parsed and converted into a value_type. + * + * @param object_parsed The record in its parsed form. + * @param id The RecordId associated with the object parsed. + */ + virtual void on_record_parsed(const ParsingResult &object_parsed, const RecordID &id) = 0; + + protected: + ~Delegate() { } + }; + + /** + * Construct a record parser. + */ + GenericRecordParser() : _delegate(NULL) { } + + /** + * @see RecordParser::parse + */ + virtual bool parse(const Record &record) + { + ParsingResult parsed_value; + if (static_cast(this)->do_parse(record, parsed_value)) { + if (_delegate) { + _delegate->on_record_parsed(parsed_value, record.id); + } + return true; + } + return false; + } + + /** + * Set the delegate that processes record parser. + * + * @param delegate The delegate to set. + */ + void set_delegate(Delegate *delegate) + { + _delegate = delegate; + } + +protected: + /** + * Protected non virtual destructor. + */ + ~GenericRecordParser() { } + +private: + Delegate *_delegate; +}; + + +/** + * Record parser chain. + */ +struct RecordParserChain { + /** + * Construct a parser chain. + */ + RecordParserChain() : _parsers(NULL) { } + + /** + * Destroy a parser chain. + */ + ~RecordParserChain() { } + + /** + * Parse a record. + * @param record The record to parse. + * @return true if the record has been parsed and false otherwise. + */ + bool parse(const Record &record); + + /** + * Add a parser at the end of the parser list. + * @param parser The parser to add. + */ + void set_next_parser(RecordParser *parser); + +private: + RecordParser *_parsers; +}; + +/** + * @} + */ + +} // namespace ndef +} // namespace nfc +} // namespace mbed + + +#endif /* NFC_NDEF_RECORDPARSER_H_ */ diff --git a/connectivity/nfc/include/nfc/ndef/common/Mime.h b/connectivity/nfc/include/nfc/ndef/common/Mime.h new file mode 100644 index 0000000..ebf66e3 --- /dev/null +++ b/connectivity/nfc/include/nfc/ndef/common/Mime.h @@ -0,0 +1,155 @@ +/* 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. + */ + +#ifndef NFC_COMMON_MIME_H_ +#define NFC_COMMON_MIME_H_ + +#include + +#include "platform/Span.h" + +#include "nfc/ndef/RecordParser.h" +#include "nfc/ndef/MessageBuilder.h" + +namespace mbed { +namespace nfc { +namespace ndef { +namespace common { + +/** + * @addtogroup nfc + * @{ + */ + +/** + * Represent a mime object. + */ +class Mime { +public: + /** + * Construct an empty Mime object. + */ + Mime(); + + /** + * Construct a mime object from its type and content + * + * @param mime_type The mime type of the object. + * @param content The content of the object. + * + * @note To remove the NULL terminator of the C-string of the mime_type + * parameter, you can use the utility function span_from_cstr. + */ + Mime( + const Span &mime_type, + const Span &content + ); + + /** + * Copy construct a Mime object. + * @param other The Mime object copied. + */ + Mime(const Mime &other); + + /** + * Destroy a Mime object. + */ + ~Mime(); + + /** + * Copy assign a Mime object. + * + * @param other The Mime object to copy. + * + * @return a reference to this object + */ + Mime &operator=(const Mime &other); + + /** + * Set all attributes of a mime object. + * + * @param mime_type Type of the mime object. + * @param content Content of the mime object. + * + * @note To remove the NULL terminator of the C-string of the mime_type + * parameter, you can use the utility function span_from_cstr. + */ + void set_mime( + const Span &mime_type, + const Span &content + ); + + /** + * Return the mime type. + * @return The mime type. + */ + Span get_mime_type() const; + + /** + * Return the content of the mime object. + * @return the content of the mime object. + */ + Span get_mime_content() const; + + /** + * Append into a message builder + */ + bool append_as_record( + MessageBuilder &message_builder, + bool is_last_record = false + ) const; + + /** + * Compute the size of this Mime object in a ndef record. + * + * @return The size of the ndef record required to store this object. + */ + size_t get_record_size() const; + +private: + friend class MimeParser; + + void move_data( + uint8_t *mime_record, + size_t mime_type_size, + size_t mime_content_size + ); + + size_t mime_size() const; + + uint8_t *_mime; + size_t _type_size; + size_t _content_size; +}; + +/** + * Parse a Mime payload. + */ +class MimeParser : public GenericRecordParser { +public: + bool do_parse(const Record &record, Mime &mime); +}; + +/** + * @} + */ + +} // namespace common +} // namespace ndef +} // namespace nfc +} // namespace mbed + +#endif /* NFC_COMMON_MIME_H_ */ diff --git a/connectivity/nfc/include/nfc/ndef/common/SimpleMessageParser.h b/connectivity/nfc/include/nfc/ndef/common/SimpleMessageParser.h new file mode 100644 index 0000000..2f7bbbc --- /dev/null +++ b/connectivity/nfc/include/nfc/ndef/common/SimpleMessageParser.h @@ -0,0 +1,170 @@ +/* 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. + */ + +#ifndef NFC_COMMON_SIMPLEMESSAGEPARSER_H_ +#define NFC_COMMON_SIMPLEMESSAGEPARSER_H_ + +#include "platform/Span.h" + +#include "nfc/ndef/MessageParser.h" +#include "nfc/ndef/RecordParser.h" +#include "nfc/ndef/common/URI.h" +#include "nfc/ndef/common/Text.h" +#include "nfc/ndef/common/Mime.h" + +namespace mbed { +namespace nfc { +namespace ndef { +namespace common { + +/** @addtogroup nfc + * @{ + */ + +/** + * Basic message parser that aggregates URIParser, TextParser and MimeParser. + * + * Custom parsers can be added at runtime as well. + */ +class SimpleMessageParser : + MessageParser::Delegate, + URIParser::Delegate, + TextParser::Delegate, + MimeParser::Delegate { +public: + /** + * Delegate invoked when the parser raise an event. + */ + struct Delegate { + /** + * Invoked when an error is present in the message. + * @param error The error present in the message. + */ + virtual void on_parsing_error(MessageParser::error_t error) { } + + /** + * Invoked when parsing as started. + */ + virtual void on_parsing_started() { } + + /** + * Invoked when a text element has been parsed. + * + * @param text The text parsed. + * @param id The RecordId of the text object. + */ + virtual void on_text_parsed(const Text &text, const RecordID &id) { } + + /** + * Invoked when a text element has been parsed. + * + * @param uri The uri parsed. + * @param id The RecordId of the uri object. + */ + virtual void on_uri_parsed(const URI &uri, const RecordID &id) { } + + /** + * Invoked when a mime element has been parsed. + * + * @param mime The mime object parsed. + * @param id The RecordId of the mime object. + */ + virtual void on_mime_parsed(const Mime &mime, const RecordID &id) { } + + /** + * Invoked when an unknown record has been parsed. + * @param record The record freshly parsed. + */ + virtual void on_unknown_record_parsed(const Record &record) { } + + /** + * Invoked when parsing is over. + */ + virtual void on_parsing_terminated() { } + + protected: + ~Delegate() { } + }; + + /** + * Construct a new CommonMessageParser. + */ + SimpleMessageParser(); + + /** + * Set the handler that processes parsing events. + * @param delegate The parsing event handler. + */ + void set_delegate(Delegate *delegate); + + /** + * Parse an NDEF Message. + * + * Records and errors are reported to the handler registered with + * set_event_handler. + * + * @param data_buffer The data buffer that contains the NDEF message. + */ + void parse(const Span &data_buffer); + + /** + * Insert a new parser in the parser chain. + * @param parser The parser to add in the parsing chain. + */ + void add_record_parser(RecordParser *parser); + +private: + //////////////////////////////////////////////////////////////////////////// + /// Implementation of MessageParser::EventHandler + + virtual void on_parsing_error(MessageParser::error_t error); + + virtual void on_parsing_started(); + + virtual void on_record_parsed(const Record &record); + + virtual void on_parsing_terminated(); + + //////////////////////////////////////////////////////////////////////////// + /// Implementation of URIParser::EventHandler + + virtual void on_record_parsed(const URI &uri, const RecordID &id); + + //////////////////////////////////////////////////////////////////////////// + /// Implementation of TextParser::EventHandler + + virtual void on_record_parsed(const Text &text, const RecordID &id); + + //////////////////////////////////////////////////////////////////////////// + /// Implementation of MimeParser::EventHandler + + virtual void on_record_parsed(const Mime &mime, const RecordID &id); + + MessageParser _message_parser; + RecordParserChain _record_parser_chain; + URIParser _uri_parser; + TextParser _text_parser; + MimeParser _mime_parser; + Delegate *_delegate; +}; +/** @}*/ +} // namespace common +} // namespace ndef +} // namespace nfc +} // namespace mbed + +#endif /* NFC_COMMON_SIMPLEMESSAGEPARSER_H_ */ + diff --git a/connectivity/nfc/include/nfc/ndef/common/Text.h b/connectivity/nfc/include/nfc/ndef/common/Text.h new file mode 100644 index 0000000..e9d62d9 --- /dev/null +++ b/connectivity/nfc/include/nfc/ndef/common/Text.h @@ -0,0 +1,165 @@ +/* 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. + */ + +#ifndef NFC_COMMON_TEXT_H_ +#define NFC_COMMON_TEXT_H_ + +#include + +#include "platform/Span.h" + +#include "nfc/ndef/RecordParser.h" +#include "nfc/ndef/MessageBuilder.h" + +namespace mbed { +namespace nfc { +namespace ndef { +namespace common { + +/** + * @addtogroup nfc + * @{ + */ + +/** + * Represent the well known type text. + */ +class Text { +public: + /** + * Encoding of the text. + */ + enum encoding_t { + UTF8 = 0,//!< UTF8 + UTF16 = 1//!< UTF16 + }; + + /** + * Construct an empty text element. + */ + Text(); + + /** + * Construct a text element from a data buffer and an encoding. + * + * @param text_encoding The encoding of the text. + * @param language_code The string of the language code. + * @param text The text buffer. + * + * @note To remove the NULL terminator of the C-string of the language_code + * and text parameters, you can use the utility function span_from_cstr. + */ + Text( + encoding_t text_encoding, + const Span &language_code, + const Span &text + ); + + /** + * Copy construct a text element. + * @param to_copy + */ + Text(const Text &to_copy); + + /** + * Destroy a text element. + */ + ~Text(); + + /** + * Copy assignment of another text element. + * @param to_copy The Text instance to copy + * @return a reference to this object. + */ + Text &operator=(const Text &to_copy); + + /** + * Copy a text from an external buffer. + * + * @param text_encoding The encoding of the text. + * @param language_code The language code of the text. + * @param text The text to copy. + * + * @note To remove the NULL terminator of the C-string of the language_code + * and text parameters, you can use the utility function span_from_cstr. + */ + void set_text( + encoding_t text_encoding, + const Span &language_code, + const Span &text + ); + + /** + * Get the encoding of the text. + * @return The encoding of the text. + */ + encoding_t get_encoding() const; + + /** + * Return the language code. + * @return The language code. + */ + Span get_language_code() const; + + /** + * Return the text contained in this object. + * @return The text contained in this object. + */ + Span get_text() const; + + /** + * Append into a message builder + */ + bool append_as_record( + MessageBuilder &message_builder, + bool is_last_record = false + ) const; + + /** + * Compute the size of this object in a ndef record. + * + * @return The size of the ndef record required to store this object. + */ + size_t get_record_size() const; + +private: + friend class TextParser; + + void move_data(uint8_t *text, size_t size); + + uint8_t *_text_record; + size_t _text_record_size; +}; + +/** + * Parse a Text. + */ +class TextParser : public GenericRecordParser { +public: + virtual bool do_parse(const Record &record, Text &text); +}; + +/** + * @} + */ + +} // namespace common +} // namespace ndef +} // namespace nfc +} // namespace mbed + + +#endif /* NFC_COMMON_TEXT_H_ */ diff --git a/connectivity/nfc/include/nfc/ndef/common/URI.h b/connectivity/nfc/include/nfc/ndef/common/URI.h new file mode 100644 index 0000000..683cdaa --- /dev/null +++ b/connectivity/nfc/include/nfc/ndef/common/URI.h @@ -0,0 +1,206 @@ +/* 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. + */ + +#ifndef NFC_COMMON_URI_H_ +#define NFC_COMMON_URI_H_ + +#include +#include + +#include "platform/Span.h" + +#include "nfc/ndef/RecordParser.h" +#include "nfc/ndef/MessageBuilder.h" + +namespace mbed { +namespace nfc { +namespace ndef { +namespace common { + +/** + * @addtogroup nfc + * @{ + */ + +/** + * Model the well known type URI. + */ +class URI { +public: + /** + * Identifier codes + */ + enum uri_identifier_code_t { + NA = 0x00, /// Not applicable + HTTP_WWW = 0x01, /// http://www. + HTTPS_WWW = 0x02, /// https://www. + HTTP = 0x03, /// http:// + HTTPS = 0x04, /// https:// + TEL = 0x05, /// tel: + MAILTO = 0x06, /// mailto: + FTP_ANONYMOUS = 0x07, /// ftp://anonymous:anonymous@ + FTP_FTP = 0x08, /// ftp://ftp. + FTPS = 0x09, /// ftps:// + SFTP = 0x0A, /// sftp:// + SMB = 0x0B, /// smb:// + NFS = 0x0C, /// nfs:// + FTP = 0x0D, /// ftp:// + DAV = 0x0E, /// dav:// + NEWS = 0x0F, /// news: + TELNET = 0x10, /// telnet:// + IMAP = 0x11, /// imap: + RSTP = 0x12, /// rstp:// + URN = 0x13, /// urn: + POP = 0x14, /// pop: + SIP = 0x15, /// sip: + SIPS = 0x16, /// sips: + TFTP = 0x17, /// tftp: + BTSPP = 0x18, /// btspp:// + BTL2CAP = 0x19, /// btl2cap:// + BTGOEP = 0x1A, /// btgoep:// + TCPOBEX = 0x1B, /// tcpobex:// + IRDAOBEX = 0x1C, /// irdaobex:// + FILE = 0x1D, /// file:// + URN_EPC_ID = 0x1E, /// urn:epc:id: + URN_EPC_TAG = 0x1F, /// urn:epc:tag: + URN_EPC_PAT = 0x20, /// urn:epc:pat: + URN_EPC_RAW = 0x21, /// urn:epc:raw: + URN_EPC = 0x22, /// urn:epc: + URN_NFC = 0x23, /// urn:nfc: + }; + + /** + * Construct an empty URI object. + */ + URI(); + + /** + * Construct a URI from an id and a uri field. + * + * @param id The code of the URI prefix. + * @param uri_field The URI itself. + * + * @note To remove the NULL terminator of the C-string of the uri_field + * parameter, you can use the utility function span_from_cstr. + */ + URI(uri_identifier_code_t id, const Span &uri_field); + + /** + * Construct a URI from another URI. + * @param to_copy The uri copied. + */ + URI(const URI &to_copy); + + /** + * Destroy a URI object. + */ + ~URI(); + + /** + * Replace the content by the one of an existing URI. + * @param to_copy The URI to copy. + * @return a reference to this object + */ + URI &operator=(const URI &to_copy); + + /** + * Replace the value of the URI. + * + * @param id The ID of the URI + * @param uri_field A buffer containing the value of the URI field. + * + * @note To remove the NULL terminator of the C-string of the uri_field + * parameter, you can use the utility function span_from_cstr. + */ + void set_uri( + uri_identifier_code_t id, + const Span &uri_field + ); + + /** + * Return the id of the uri. + * @return The id of the uri. + */ + uri_identifier_code_t get_id() const; + + /** + * Return the current value of the uri field. + * @return The value of the uri field. + */ + Span get_uri_field() const; + + /** + * Append into a message builder + */ + bool append_as_record( + MessageBuilder &message_builder, + bool is_last_record = false + ) const; + + /** + * Compute the size of this object in a ndef record. + * + * @return The size of the ndef record required to store this object. + */ + size_t get_record_size() const; + + /** + * Equal operator between two URIs + * @param lhs The URI on the left hand side + * @param rhs The URI on the right hand side + * @return true if lhs equals rhs or false. + */ + friend bool operator==(const URI &lhs, const URI &rhs) + { + if (lhs._uri_size != rhs._uri_size) { + return false; + } + + return memcmp(lhs._uri, rhs._uri, lhs._uri_size) == 0; + } + + friend bool operator!=(const URI &lhs, const URI &rhs) + { + return !(lhs == rhs); + } + +private: + friend class URIParser; + + void move_data(uint8_t *text, size_t size); + + uint8_t *_uri; + size_t _uri_size; +}; + +/** + * Parser of a URI. + */ +class URIParser : public GenericRecordParser { +public: + bool do_parse(const Record &record, URI &uri); +}; + +/** + * @} + */ + +} // namespace common +} // namespace ndef +} // namespace nfc +} // namespace mbed + +#endif /* NFC_COMMON_URI_H_ */ diff --git a/connectivity/nfc/include/nfc/ndef/common/util.h b/connectivity/nfc/include/nfc/ndef/common/util.h new file mode 100644 index 0000000..1be5577 --- /dev/null +++ b/connectivity/nfc/include/nfc/ndef/common/util.h @@ -0,0 +1,69 @@ +/* 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. + */ + +#ifndef FEATURES_NFC_SOURCE_NFC_COMMON_UTIL_H_ +#define FEATURES_NFC_SOURCE_NFC_COMMON_UTIL_H_ + +#include "platform/Span.h" + +namespace mbed { +namespace nfc { +namespace ndef { +namespace common { + +/** + * @addtogroup nfc + * @{ + */ + +/** + * Convert a C-string into a Span. + * + * @note The NULL charactere is not present in the resulting object. + * + * @param cstr The cstr to convert into a Span. + * + * @return A Span that views cstr but doesn't include the NULL terminator + * character. + */ +template +Span < const uint8_t, N - 1 > span_from_cstr(const char (&cstr)[N]) +{ + return Span < const uint8_t, N - 1 > ((const uint8_t *)cstr, N - 1); +} + +/** + * Convert a C-string into a Span. + * + * @note The NULL charactere is not present in the resulting object. + * + * @param cstr The cstr to convert into a Span. + * + * @return A Span that views cstr but doesn't include the NULL terminator + * character. + */ +Span span_from_cstr(const char *cstr); + +/** + * @} + */ + +} // namespace common +} // namespace ndef +} // namespace nfc +} // namespace mbed + +#endif /* FEATURES_NFC_SOURCE_NFC_COMMON_UTIL_H_ */ diff --git a/connectivity/nfc/libraries/acore/acore/ac_buffer.h b/connectivity/nfc/libraries/acore/acore/ac_buffer.h new file mode 100644 index 0000000..68b84f6 --- /dev/null +++ b/connectivity/nfc/libraries/acore/acore/ac_buffer.h @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2017, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + */ +/** + * \file ac_buffer.h + * \copyright Copyright (c) ARM Ltd 2013 + * \author Donatien Garnier + */ + +/** \addtogroup ACore + * @{ + * \name Buffer + * @{ + */ + +#ifndef ACORE_BUFFER_H_ +#define ACORE_BUFFER_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "stdint.h" +#include "stddef.h" +#include "stdbool.h" + +typedef struct __ac_buffer { + const uint8_t *data; + size_t size; + struct __ac_buffer *pNext; +} ac_buffer_t; + +/** Initialize ac_buffer using underlying byte array, set ac_buffer's length to 0 (empty) + * \param pBuf pointer to ac_buffer_t structure to initialize + * \param data byte array to use + * \param size size of byte array + */ +void ac_buffer_init(ac_buffer_t *pBuf, const uint8_t *data, size_t size); + +/** Copy pBufIn to pBuf + * \param pBuf pointer to ac_buffer_t structure to initialize + * \param pBufIn the source buffer + */ +void ac_buffer_dup(ac_buffer_t *pBuf, const ac_buffer_t *pBufIn); + +/** Get buffer's underlying byte array + * \param pBuf pointer to ac_buffer_t structure + * \return underlying array + */ +static inline const uint8_t *ac_buffer_data(const ac_buffer_t *pBuf) +{ + return pBuf->data; +} + +/** Get buffer's size + * \param pBuf pointer to ac_buffer_t structure + * \return buffer's size + */ +static inline size_t ac_buffer_size(const ac_buffer_t *pBuf) +{ + return pBuf->size; +} + +/** Get next buffer in chain + * \param pBuf pointer to ac_buffer_t structure + * \return pointer to next buffer + */ +static inline ac_buffer_t *ac_buffer_next(const ac_buffer_t *pBuf) +{ + return pBuf->pNext; +} + +/** Set next buffer in chain + * \param pBuf pointer to ac_buffer_t structure + * \param pNextBuf pointer to next buffer (or NULL to break chain) + */ +static inline void ac_buffer_set_next(ac_buffer_t *pBuf, ac_buffer_t *pNextBuf) +{ + pBuf->pNext = (ac_buffer_t *) pNextBuf; +} + +/** Append buffer to end of chain + * \param pBuf pointer to ac_buffer_t structure + * \param pAppBuf pointer to buffer to append to chain + */ +void ac_buffer_append(ac_buffer_t *pBuf, ac_buffer_t *pAppBuf); + +/** Truncate pBuf to length bytes and save the remaining bytes in pEndBuf + * \param pBuf The buffer to split (will be set to invalid state) + * \param pStartBuf A new buffer at the head of the split + * \param pEndBuf A new buffer at the tail of the split + * \param length How long pStartBuf should be (if longer than pBuf, then pStartBuf will be pBuf) + */ +void ac_buffer_split(ac_buffer_t *pStartBuf, ac_buffer_t *pEndBuf, ac_buffer_t *pBuf, size_t length); + +//Debug +void ac_buffer_dump(ac_buffer_t *pBuf); + +#ifdef __cplusplus +} +#endif + +#endif /* ACORE_BUFFER_H_ */ + +/** + * @} + * @} + * */ diff --git a/connectivity/nfc/libraries/acore/acore/ac_buffer_builder.h b/connectivity/nfc/libraries/acore/acore/ac_buffer_builder.h new file mode 100644 index 0000000..946b178 --- /dev/null +++ b/connectivity/nfc/libraries/acore/acore/ac_buffer_builder.h @@ -0,0 +1,370 @@ +/* + * Copyright (c) 2017, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + */ +/** + * \file ac_buffer_builder.h + * \copyright Copyright (c) ARM Ltd 2017 + * \author Donatien Garnier + */ + +/** \addtogroup ACore + * @{ + * \name Buffer Builder + * @{ + */ + +#ifndef ACORE_BUFFER_BUILDER_H_ +#define ACORE_BUFFER_BUILDER_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "stdint.h" +#include "stddef.h" +#include "stdbool.h" + +#include "acore/ac_buffer.h" + +typedef struct __ac_buffer_builder { + ac_buffer_t ac_buffer; + uint8_t *data; + size_t size; +} ac_buffer_builder_t; + +/** Write data to big endian ac_buffer (on a LE architecture, byte order will be swapped) + * \param pBuilder ac_buffer builder to use + * \param buf pointer to data + * \param size the data size + */ +void ac_buffer_builder_write_be(ac_buffer_builder_t *pBuilder, const uint8_t *buf, size_t size); + +/** Write data to little endian ac_buffer (on a LE architecture, byte order will be preserved) + * \param pBuilder ac_buffer builder to use + * \param buf pointer to data + * \param size the data size + */ +void ac_buffer_builder_write_le(ac_buffer_builder_t *pBuilder, const uint8_t *buf, size_t size); + +/** Write data to big endian ac_buffer at specific position (on a LE architecture, byte order will be swapped) + * \param pBuilder ac_buffer builder to use + * \param pos position in ac_buffer to write from + * \param buf pointer to data + * \param size the data size + */ +void ac_buffer_builder_write_be_at(ac_buffer_builder_t *pBuilder, size_t pos, const uint8_t *buf, size_t size); + +/** Write data to little endian ac_buffer at specific position (on a LE architecture, byte order will be preserved) + * \param pBuilder ac_buffer builder to use + * \param pos position in ac_buffer to write from + * \param buf pointer to data + * \param size the data size + */ +void ac_buffer_builder_write_le_at(ac_buffer_builder_t *pBuilder, size_t pos, const uint8_t *buf, size_t size); + +/** Initialize ac_buffer builder + * \param pBuilder ac_buffer builder to init + * \param data pointer to byte array to use + * \param size of byte array + */ +void ac_buffer_builder_init(ac_buffer_builder_t *pBuilder, uint8_t *data, size_t size); + +/** Initialize ac_buffer builder from underlying ac_buffer + * \param pBuilder ac_buffer builder to init + */ +void ac_buffer_builder_from_buffer(ac_buffer_builder_t *pBuilder); + +/** Reset ac_buffer builder + * \param pBuilder ac_buffer builder to reset + */ +void ac_buffer_builder_reset(ac_buffer_builder_t *pBuilder); + +/** Set ac_buffer builder's ac_buffer to full size + * \param pBuilder ac_buffer builder to set to full size + */ +void ac_buffer_builder_set_full(ac_buffer_builder_t *pBuilder); + +/** Get ac_buffer builder's length + * \param pBuilder ac_buffer builder to get length of + * \return number of valid bytes in ac_buffer + */ +static inline size_t ac_buffer_builder_length(ac_buffer_builder_t *pBuilder) +{ + return ac_buffer_size(&pBuilder->ac_buffer); +} + +/** Set ac_buffer builder's length + * \param pBuilder ac_buffer builder to set length of + * \param length number of valid bytes in ac_buffer + */ +static inline void ac_buffer_builder_set_length(ac_buffer_builder_t *pBuilder, size_t length) +{ + if (ac_buffer_data(&pBuilder->ac_buffer) + length > pBuilder->data + pBuilder->size) { + return; + } + pBuilder->ac_buffer.size = length; +} + +/** Get ac_buffer builder's pointer to write position + * \param pBuilder ac_buffer builder + * \return pointer to write position + */ +static inline uint8_t *ac_buffer_builder_write_position(ac_buffer_builder_t *pBuilder) +{ + return (uint8_t *)ac_buffer_data(&pBuilder->ac_buffer) + ac_buffer_size(&pBuilder->ac_buffer); +} + +/** Get ac_buffer builder's write offset + * \param pBuilder ac_buffer builder + * \return write offset + */ +static inline size_t ac_buffer_builder_write_offset(ac_buffer_builder_t *pBuilder) +{ + return ac_buffer_data(&pBuilder->ac_buffer) + ac_buffer_size(&pBuilder->ac_buffer) - pBuilder->data; +} + +/** Set ac_buffer builder's write offset + * \param pBuilder ac_buffer builder + * \param off new write offset + */ +static inline void ac_buffer_builder_set_write_offset(ac_buffer_builder_t *pBuilder, size_t off) +{ + if (off > pBuilder->size) { + return; + } + if (pBuilder->data + off > pBuilder->ac_buffer.data) { + pBuilder->ac_buffer.size = off - (pBuilder->ac_buffer.data - pBuilder->data); + } else { + pBuilder->ac_buffer.size = 0; + } +} + +/** Get ac_buffer builder's read offset + * \param pBuilder ac_buffer builder + * \return read offset + */ +static inline size_t ac_buffer_builder_read_offset(ac_buffer_builder_t *pBuilder) +{ + return ac_buffer_data(&pBuilder->ac_buffer) - pBuilder->data; +} + +/** Set ac_buffer builder's read offset + * \param pBuilder ac_buffer builder + * \param off new read offset + */ +static inline void ac_buffer_builder_set_read_offset(ac_buffer_builder_t *pBuilder, size_t off) +{ + if (off > pBuilder->size) { + return; + } + if (pBuilder->data + off < pBuilder->ac_buffer.data + pBuilder->ac_buffer.size) { + pBuilder->ac_buffer.size = pBuilder->ac_buffer.data - (pBuilder->data + off); + } else { + pBuilder->ac_buffer.size = 0; + } + pBuilder->ac_buffer.data = pBuilder->data + off; +} + +/** Get ac_buffer builder's underlying ac_buffer + * \param pBuilder ac_buffer builder + * \return ac_buffer + */ +static inline ac_buffer_t *ac_buffer_builder_buffer(ac_buffer_builder_t *pBuilder) +{ + return &pBuilder->ac_buffer; +} + +/** Get space in ac_buffer builder + * \param pBuilder ac_buffer builder + * \return number of free bytes in ac_buffer builder + */ +static inline size_t ac_buffer_builder_space(ac_buffer_builder_t *pBuilder) +{ + return pBuilder->size - (ac_buffer_data(&pBuilder->ac_buffer) - pBuilder->data + ac_buffer_size(&pBuilder->ac_buffer)); +} + +/** Is ac_buffer builder empty + * \param pBuilder ac_buffer builder + * \return true if ac_buffer builder is empty + */ +static inline bool ac_buffer_builder_empty(ac_buffer_builder_t *pBuilder) +{ + return (ac_buffer_builder_length(pBuilder) == 0); +} + +/** Is ac_buffer builder full + * \param pBuilder ac_buffer builder + * \return true if ac_buffer builder is full + */ +static inline bool ac_buffer_full(ac_buffer_builder_t *pBuilder) +{ + return (ac_buffer_builder_space(pBuilder) == 0); +} + +/** Write 8-bit value in ac_buffer builder + * \param pBuilder ac_buffer builder + * \param hu8 8-bit value to write + */ +static inline void ac_buffer_builder_write_nu8(ac_buffer_builder_t *pBuilder, uint8_t hu8) +{ + ac_buffer_builder_write_be(pBuilder, &hu8, 1); +} + +/** Write 16-bit value in ac_buffer builder + * \param pBuilder ac_buffer builder + * \param hu16 16-bit value to write in big-endian format + */ +static inline void ac_buffer_builder_write_nu16(ac_buffer_builder_t *pBuilder, uint16_t hu16) +{ + ac_buffer_builder_write_be(pBuilder, (uint8_t *)&hu16, 2); +} + +/** Write 24-bit value in ac_buffer builder + * \param pBuilder ac_buffer builder + * \param hu24 24-bit value to write in big-endian format + */ +static inline void ac_buffer_builder_write_nu24(ac_buffer_builder_t *pBuilder, uint32_t hu24) +{ + ac_buffer_builder_write_be(pBuilder, (uint8_t *)&hu24, 3); +} + +/** Write 32-bit value in ac_buffer builder + * \param pBuilder ac_buffer builder + * \param hu32 32-bit value to write in big-endian format + */ +static inline void ac_buffer_builder_write_nu32(ac_buffer_builder_t *pBuilder, uint32_t hu32) +{ + ac_buffer_builder_write_be(pBuilder, (uint8_t *)&hu32, 4); +} + +/** Write 64-bit value in ac_buffer builder + * \param pBuilder ac_buffer builder + * \param hu64 64-bit value to write in big-endian format + */ +static inline void ac_buffer_builder_write_nu64(ac_buffer_builder_t *pBuilder, uint64_t hu64) +{ + ac_buffer_builder_write_be(pBuilder, (uint8_t *)&hu64, 8); +} + +/** Write n-bytes value in ac_buffer builder + * \param pBuilder ac_buffer builder + * \param data data to write + * \param size data length + */ +static inline void ac_buffer_builder_write_n_bytes(ac_buffer_builder_t *pBuilder, const uint8_t *data, size_t size) +{ + ac_buffer_builder_write_le(pBuilder, data, size); +} + +/** Write 8-bit value in ac_buffer builder at specified position + * \param pBuilder ac_buffer builder + * \param off offset at which to write + * \param hu8 8-bit value to write + */ +static inline void ac_buffer_builder_write_nu8_at(ac_buffer_builder_t *pBuilder, size_t off, uint8_t hu8) +{ + ac_buffer_builder_write_be_at(pBuilder, off, &hu8, 1); +} + +/** Write 16-bit value in ac_buffer builder at specified position + * \param pBuilder ac_buffer builder + * \param off offset at which to write + * \param hu16 16-bit value to write + */ +static inline void ac_buffer_builder_write_nu16_at(ac_buffer_builder_t *pBuilder, size_t off, uint16_t hu16) +{ + ac_buffer_builder_write_be_at(pBuilder, off, (uint8_t *)&hu16, 2); +} + +/** Write 24-bit value in ac_buffer builder at specified position + * \param pBuilder ac_buffer builder + * \param off offset at which to write + * \param hu24 24-bit value to write + */ +static inline void ac_buffer_builder_write_nu24_at(ac_buffer_builder_t *pBuilder, size_t off, uint32_t hu24) +{ + ac_buffer_builder_write_be_at(pBuilder, off, (uint8_t *)&hu24, 3); +} + +/** Write 32-bit value in ac_buffer builder at specified position + * \param pBuilder ac_buffer builder + * \param off offset at which to write + * \param hu32 32-bit value to write + */ +static inline void ac_buffer_builder_write_nu32_at(ac_buffer_builder_t *pBuilder, size_t off, uint32_t hu32) +{ + ac_buffer_builder_write_be_at(pBuilder, off, (uint8_t *)&hu32, 4); +} + +/** Write 64-bit value in ac_buffer builder at specified position + * \param pBuilder ac_buffer builder + * \param off offset at which to write + * \param hu64 64-bit value to write + */ +static inline void ac_buffer_builder_write_nu64_at(ac_buffer_builder_t *pBuilder, size_t off, uint64_t hu64) +{ + ac_buffer_builder_write_be_at(pBuilder, off, (uint8_t *)&hu64, 8); +} + +/** Write n-bytes value in ac_buffer builder at specified position + * \param pBuilder ac_buffer builder + * \param off offset at which to write + * \param data data to write + * \param size data length + */ +static inline void ac_buffer_builder_write_n_bytes_at(ac_buffer_builder_t *pBuilder, size_t off, const uint8_t *data, size_t size) +{ + ac_buffer_builder_write_be_at(pBuilder, off, data, size); +} + +/** Skip n-bytes in ac_buffer builder + * \param pBuilder ac_buffer builder + * \param size number of bytes to skip + */ +void ac_buffer_builder_write_n_skip(ac_buffer_builder_t *pBuilder, size_t size); + +/** Copy n bytes from buffer to builder + * \param pBuilderOut ac_buffer builder + * \param pBufIn the input buffer + * \param size number of bytes to copy + */ +void ac_buffer_builder_copy_n_bytes(ac_buffer_builder_t *pBuilderOut, ac_buffer_t *pBufIn, size_t size); + +/** Compact builder + * Will move underlying buffer's byte to start of allocated buffer + * \param pBuilder ac_buffer builder + */ +void ac_buffer_builder_compact(ac_buffer_builder_t *pBuilder); + +/** Get number of writable bytes in ac_buffer builder + * \param pBuilder ac_buffer builder + * \return number of free bytes in ac_buffer builder + */ +static inline size_t ac_buffer_builder_writable(ac_buffer_builder_t *pBuilder) +{ + return ac_buffer_builder_space(pBuilder); +} + +#ifdef __cplusplus +} +#endif + +#endif /* ACORE_BUFFER_BUILDER_H_ */ + +/** + * @} + * @} + * */ diff --git a/connectivity/nfc/libraries/acore/acore/ac_buffer_reader.h b/connectivity/nfc/libraries/acore/acore/ac_buffer_reader.h new file mode 100644 index 0000000..0030908 --- /dev/null +++ b/connectivity/nfc/libraries/acore/acore/ac_buffer_reader.h @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2017, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + */ +/** + * \file ac_buffer_reader.h + * \copyright Copyright (c) ARM Ltd 2015 + * \author Donatien Garnier + */ + +/** \addtogroup ACore + * @{ + * \name Buffer Reader + * @{ + */ + +#ifndef ACORE_BUFFER_READER_H_ +#define ACORE_BUFFER_READER_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "stdint.h" +#include "stddef.h" +#include "stdbool.h" + +#include "acore/ac_buffer.h" + +/** Read n-bytes in big-endian format from buffer reader and advance read posiion + * \param pBuf the buffer to read from + * \param buf the array to write to + * \param size the number of bytes to read + */ +void ac_buffer_read_be(ac_buffer_t *pBuf, uint8_t *buf, size_t size); + +/** Read n-bytes in little-endian format from buffer reader and advance read posiion + * \param pBuf the buffer to read from + * \param buf the array to write to + * \param size the number of bytes to read + */ +void ac_buffer_read_le(ac_buffer_t *pBuf, uint8_t *buf, size_t size); + +/** Read 8-bit value from buffer reader and advance read posiion + * \param pBuf the buffer to read from + * \return 8-bit value read + */ +static inline uint8_t ac_buffer_read_nu8(ac_buffer_t *pBuf) +{ + uint8_t hu8; + ac_buffer_read_be(pBuf, &hu8, 1); + return hu8; +} + +/** Read BE 16-bit value from buffer reader and advance read posiion + * \param pBuf the buffer to read from + * \return 16-bit value read + */ +static inline uint16_t ac_buffer_read_nu16(ac_buffer_t *pBuf) +{ + uint16_t hu16; + ac_buffer_read_be(pBuf, (uint8_t *)&hu16, 2); + return hu16; +} + +/** Read BE 24-bit value from buffer reader and advance read posiion + * \param pBuf the buffer to read from + * \return 24-bit value read + */ +static inline uint32_t ac_buffer_read_nu24(ac_buffer_t *pBuf) +{ + uint32_t hu24; + ac_buffer_read_be(pBuf, (uint8_t *)&hu24, 3); + return hu24; +} + +/** Read BE 32-bit value from buffer reader and advance read posiion + * \param pBuf the buffer to read from + * \return 32-bit value read + */ +static inline uint32_t ac_buffer_read_nu32(ac_buffer_t *pBuf) +{ + uint32_t hu32; + ac_buffer_read_be(pBuf, (uint8_t *)&hu32, 4); + return hu32; +} + +/** Read BE 64-bit value from buffer reader and advance read posiion + * \param pBuf the buffer to read from + * \return 64-bit value read + */ +static inline uint64_t ac_buffer_read_nu64(ac_buffer_t *pBuf) +{ + uint64_t hu64; + ac_buffer_read_be(pBuf, (uint8_t *)&hu64, 8); + return hu64; +} + +/** Read n bytes from buffer reader and advance read posiion + * \param pBuf the buffer to read from + * \param data the array to write bytes to + * \param size the number of bytes to read + */ +static inline void ac_buffer_read_n_bytes(ac_buffer_t *pBuf, uint8_t *data, size_t size) +{ + ac_buffer_read_le(pBuf, data, size); +} + +/** Skip n bytes from buffer reader and advance read posiion + * \param pBuf the buffer to read from + * \param size the number of bytes to skip + */ +void ac_buffer_read_n_skip(ac_buffer_t *pBuf, size_t size); + +/** Get number of bytes readable from buffer + * \param pBuf the buffer to read from + * \return The number of bytes which can be read + */ +size_t ac_buffer_reader_readable(const ac_buffer_t *pBuf); + +/** Get a pointer to the current position within this buffer's current backing array + * \param pBuf the buffer to read from + * \return A pointer to the current position within the current backing array + */ +const uint8_t *ac_buffer_reader_current_buffer_pointer(ac_buffer_t *pBuf); + +/** Get the number of bytes readable within the current backing array + * \param pBuf the buffer to read from + * \return The number of bytes readable within the current backing array + */ +size_t ac_buffer_reader_current_buffer_length(ac_buffer_t *pBuf); + +/** Compare buffer with array (does not advance read position) + * \param pBuf the buffer to compare from + * \param bytes the array to compare with + * \param length the array length + * \return Whether the buffer is AT LEAST as long as the array AND the buffer and array have the same content + */ +bool ac_buffer_reader_cmp_bytes(const ac_buffer_t *pBuf, const uint8_t *bytes, size_t length); + +/** Compare buffer with array (does not advance read position) + * \param pBuf1 the buffer to compare from + * \param pBuf2 the buffer to compare with + * \return Whether the buffers have the same length and content + */ +bool ac_buffer_reader_cmp(const ac_buffer_t *pBuf1, const ac_buffer_t *pBuf2); + +#ifdef __cplusplus +} +#endif + +#endif /* CORE_ac_buffer_READER_H_ */ + +/** + * @} + * @} + * */ diff --git a/connectivity/nfc/libraries/acore/acore/ac_debug.h b/connectivity/nfc/libraries/acore/acore/ac_debug.h new file mode 100644 index 0000000..2348514 --- /dev/null +++ b/connectivity/nfc/libraries/acore/acore/ac_debug.h @@ -0,0 +1,41 @@ +/** + * \file ac_debug.h + * \copyright Copyright (c) ARM Ltd 2018 + * \author Donatien Garnier + */ +/* + * Copyright (c) 2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + */ + +#ifndef ACORE_DEBUG_H_ +#define ACORE_DEBUG_H_ + +// Macro that can be defined to lock stdio in multithreaded environments +#if !defined(ACORE_STDIO_LOCK) +#define ACORE_STDIO_LOCK() +#endif + +#if !defined(ACORE_STDIO_UNLOCK) +#define ACORE_STDIO_UNLOCK() +#endif + +// Macro that can be defined to define an alternative printf impl for debugging +#if !defined(ACORE_STDIO_PRINT) +#include "stdio.h" +#define ACORE_STDIO_PRINT(...) printf(__VA_ARGS__) +#endif + +#endif diff --git a/connectivity/nfc/libraries/acore/acore/ac_macros.h b/connectivity/nfc/libraries/acore/acore/ac_macros.h new file mode 100644 index 0000000..cf56295 --- /dev/null +++ b/connectivity/nfc/libraries/acore/acore/ac_macros.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2017, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + */ + +#ifndef ACORE_MACROS_H_ +#define ACORE_MACROS_H_ + +//Macros +#ifndef MAX +#define MAX(a,b) (((a)>(b))?(a):(b)) +#define MIN(a,b) (((a)<(b))?(a):(b)) +#endif + +#endif + diff --git a/connectivity/nfc/libraries/acore/acore/ac_stream.h b/connectivity/nfc/libraries/acore/acore/ac_stream.h new file mode 100644 index 0000000..1347d20 --- /dev/null +++ b/connectivity/nfc/libraries/acore/acore/ac_stream.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2017, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + */ +/** + * \file ac_stream.h + * \copyright Copyright (c) ARM Ltd 2015 + * \author Donatien Garnier + */ + +#ifndef ACORE_STREAM_H_ +#define ACORE_STREAM_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +struct __ac_istream; +struct __ac_ostream; + +typedef struct __ac_istream ac_istream_t; +typedef struct __ac_ostream ac_ostream_t; + +#include "stddef.h" +#include "stdbool.h" +#include "stdint.h" + +#include "acore/ac_buffer.h" + +typedef void (*ac_istream_fn)(ac_buffer_t *pDataIn, bool *pClose, size_t maxLength, void *pUserParam); +typedef void (*ac_ostream_fn)(ac_buffer_t *pDataOut, bool closed, void *pUserParam); + +//Input stream -- pulled by consumer +struct __ac_istream { + ac_istream_fn fn; + void *pUserParam; +}; + +//Output stream -- pushed by supplier +struct __ac_ostream { + ac_ostream_fn fn; + void *pUserParam; +}; + +//Called by supplier +void ac_istream_init(ac_istream_t *pac_istream, ac_istream_fn fn, void *pUserParam); +//Called by consumer +void ac_istream_pull(ac_istream_t *pac_istream, ac_buffer_t *pDataIn, bool *pClose, size_t maxLength); + +//Called by consumer +void ac_ostream_init(ac_ostream_t *pac_ostream, ac_ostream_fn fn, void *pUserParam); +//Called by supplier +void ac_ostream_push(ac_ostream_t *pac_ostream, ac_buffer_t *pDataOut, bool closed); + +#ifdef __cplusplus +} +#endif + +#endif /* ACORE_STREAM_H_ */ diff --git a/connectivity/nfc/libraries/acore/source/ac_buffer.c b/connectivity/nfc/libraries/acore/source/ac_buffer.c new file mode 100644 index 0000000..c3b91ff --- /dev/null +++ b/connectivity/nfc/libraries/acore/source/ac_buffer.c @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2017, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + */ +/** + * \file buffer.c + * \copyright Copyright (c) ARM Ltd 2013 + * \author Donatien Garnier + * \desc Module to ease ac_buffers' management + */ + +#include "string.h" + +#include "acore/ac_buffer.h" +#include "acore/ac_buffer_reader.h" +#include "acore/ac_macros.h" + +#include "acore/ac_debug.h" + +void ac_buffer_init(ac_buffer_t *pBuf, const uint8_t *data, size_t size) +{ + pBuf->data = data; + pBuf->size = size; + + pBuf->pNext = NULL; +} + +void ac_buffer_dup(ac_buffer_t *pBuf, const ac_buffer_t *pBufIn) +{ + if (pBuf != pBufIn) { + memcpy(pBuf, pBufIn, sizeof(ac_buffer_t)); + } +} + +void ac_buffer_append(ac_buffer_t *pBuf, ac_buffer_t *pAppBuf) +{ + while (pBuf->pNext != NULL) { + pBuf = pBuf->pNext; + } + pBuf->pNext = pAppBuf; +} + +void ac_buffer_split(ac_buffer_t *pStartBuf, ac_buffer_t *pEndBuf, ac_buffer_t *pBuf, size_t length) +{ + ac_buffer_dup(pStartBuf, pBuf); + ac_buffer_dup(pEndBuf, pBuf); + + ac_buffer_read_n_skip(pEndBuf, length); + + while (length > ac_buffer_size(pStartBuf)) { + length -= pStartBuf->size; + pStartBuf = pStartBuf->pNext; + } + + pStartBuf->size = length; + pStartBuf->pNext = NULL; +} + +/** Dump a ac_buffer's content to stdout (useful for debugging) + * \param pBuf pointer to ac_buffer_t structure + */ +void ac_buffer_dump(ac_buffer_t *pBuf) +{ +#if !defined(NDEBUG) + ACORE_STDIO_LOCK(); + while (pBuf != NULL) { + size_t r = ac_buffer_size(pBuf); + size_t i = 0; + size_t j = 0; + while (i < r) { + for (j = i; j < MIN(i + 16, r); j++) { + ACORE_STDIO_PRINT("%02x ", ac_buffer_data(pBuf)[j]); + } + ACORE_STDIO_PRINT("\r\n"); + i = j; + } + pBuf = ac_buffer_next(pBuf); + if (pBuf != NULL) { + ACORE_STDIO_PRINT("->\r\n"); + } + } + ACORE_STDIO_UNLOCK(); +#else + (void)pBuf; +#endif +} diff --git a/connectivity/nfc/libraries/acore/source/ac_buffer_builder.c b/connectivity/nfc/libraries/acore/source/ac_buffer_builder.c new file mode 100644 index 0000000..8e15488 --- /dev/null +++ b/connectivity/nfc/libraries/acore/source/ac_buffer_builder.c @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2017, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + */ +/** + * \file buffer_builder.c + * \copyright Copyright (c) ARM Ltd 2015 + * \author Donatien Garnier + */ + +#include "acore/ac_buffer_builder.h" +#include "acore/ac_buffer_reader.h" +#include "acore/ac_macros.h" + +#include "string.h" + +#define VOID +#define ENSURE_WRITE_LENGTH(pBuilder, n) do{ if( ac_buffer_builder_space(pBuilder) < n ) { return; } }while(0); + +void ac_buffer_builder_init(ac_buffer_builder_t *pBuilder, uint8_t *data, size_t size) +{ + pBuilder->data = data; + pBuilder->size = size; + ac_buffer_init(&pBuilder->ac_buffer, data, 0); +} + +void ac_buffer_builder_from_buffer(ac_buffer_builder_t *pBuilder) +{ + pBuilder->data = (uint8_t *)pBuilder->ac_buffer.data; + pBuilder->size = pBuilder->ac_buffer.size; + pBuilder->ac_buffer.size = 0; +} + +void ac_buffer_builder_reset(ac_buffer_builder_t *pBuilder) +{ + ac_buffer_init(&pBuilder->ac_buffer, pBuilder->data, 0); +} + +void ac_buffer_builder_set_full(ac_buffer_builder_t *pBuilder) +{ + ac_buffer_init(&pBuilder->ac_buffer, pBuilder->data, pBuilder->size); +} + +void ac_buffer_builder_write_be(ac_buffer_builder_t *pBuilder, const uint8_t *buf, size_t size) +{ + ENSURE_WRITE_LENGTH(pBuilder, size); + buf += size; + while (size > 0) { + buf--; + *ac_buffer_builder_write_position(pBuilder) = *buf; + pBuilder->ac_buffer.size++; + size--; + } +} + +void ac_buffer_builder_write_le(ac_buffer_builder_t *pBuilder, const uint8_t *buf, size_t size) +{ + ENSURE_WRITE_LENGTH(pBuilder, size); + memcpy(ac_buffer_builder_write_position(pBuilder), buf, size); + pBuilder->ac_buffer.size += size; +} + +void ac_buffer_builder_write_be_at(ac_buffer_builder_t *pBuilder, size_t pos, const uint8_t *buf, size_t size) +{ + size_t currentPos = pBuilder->ac_buffer.size; + pBuilder->ac_buffer.size = pos; + ac_buffer_builder_write_be(pBuilder, buf, size); + pBuilder->ac_buffer.size = currentPos; +} + +void ac_buffer_builder_write_le_at(ac_buffer_builder_t *pBuilder, size_t pos, const uint8_t *buf, size_t size) +{ + size_t currentPos = pBuilder->ac_buffer.size; + pBuilder->ac_buffer.size = pos; + ac_buffer_builder_write_le(pBuilder, buf, size); + pBuilder->ac_buffer.size = currentPos; +} + +void ac_buffer_builder_write_n_skip(ac_buffer_builder_t *pBuilder, size_t size) +{ + ENSURE_WRITE_LENGTH(pBuilder, size); + pBuilder->ac_buffer.size += size; +} + +void ac_buffer_builder_copy_n_bytes(ac_buffer_builder_t *pBuilderOut, ac_buffer_t *pBufIn, size_t size) +{ + ENSURE_WRITE_LENGTH(pBuilderOut, size); + if (ac_buffer_reader_readable(pBufIn) < size) { + return; + } + while (size > 0) { + size_t cpy = ac_buffer_reader_current_buffer_length(pBufIn); + cpy = MIN(cpy, size); + ac_buffer_builder_write_n_bytes(pBuilderOut, ac_buffer_reader_current_buffer_pointer(pBufIn), cpy); + ac_buffer_read_n_skip(pBufIn, cpy); + size -= cpy; + } +} + +void ac_buffer_builder_compact(ac_buffer_builder_t *pBuilder) +{ + memmove(pBuilder->data, ac_buffer_data(&pBuilder->ac_buffer), ac_buffer_size(&pBuilder->ac_buffer)); + pBuilder->ac_buffer.data = pBuilder->data; +} diff --git a/connectivity/nfc/libraries/acore/source/ac_buffer_reader.c b/connectivity/nfc/libraries/acore/source/ac_buffer_reader.c new file mode 100644 index 0000000..44d0303 --- /dev/null +++ b/connectivity/nfc/libraries/acore/source/ac_buffer_reader.c @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2017, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + */ +/** + * \file buffer_reader.c + * \copyright Copyright (c) ARM Ltd 2015 + * \author Donatien Garnier + */ + +#include "acore/ac_buffer_reader.h" +#include "acore/ac_macros.h" + +#include "string.h" + +#define VOID +#define ENSURE_READ_LENGTH(pBuf, n) do{ if( ac_buffer_reader_readable(pBuf) < n ) { return; } }while(0); + +static inline void update_buf(ac_buffer_t *pBuf) +{ + while (ac_buffer_size(pBuf) == 0) { + if (ac_buffer_next(pBuf) != NULL) { + ac_buffer_t *pNext = ac_buffer_next(pBuf); + ac_buffer_init(pBuf, ac_buffer_data(pNext), ac_buffer_size(pNext)); + pBuf->pNext = ac_buffer_next(pNext); + } else if (pBuf->data != NULL) { + ac_buffer_init(pBuf, NULL, 0); + } else { + return; + } + } +} + +void ac_buffer_read_be(ac_buffer_t *pBuf, uint8_t *buf, size_t size) +{ + ENSURE_READ_LENGTH(pBuf, size); + buf += size; + while (size > 0) { + buf--; + *buf = *ac_buffer_data(pBuf); + pBuf->data++; + pBuf->size--; + update_buf(pBuf); + size--; + } +} + +void ac_buffer_read_le(ac_buffer_t *pBuf, uint8_t *buf, size_t size) +{ + ENSURE_READ_LENGTH(pBuf, size); + while (size > 0) { + size_t cpy = ac_buffer_size(pBuf); + cpy = MIN(cpy, size); + memcpy(buf, ac_buffer_data(pBuf), cpy); + pBuf->data += cpy; + pBuf->size -= cpy; + update_buf(pBuf); + size -= cpy; + buf += cpy; + } +} + +void ac_buffer_read_n_skip(ac_buffer_t *pBuf, size_t size) +{ + ENSURE_READ_LENGTH(pBuf, size); + while (size > 0) { + size_t cpy = ac_buffer_size(pBuf); + cpy = MIN(cpy, size); + pBuf->data += cpy; + pBuf->size -= cpy; + update_buf(pBuf); + size -= cpy; + } +} + +size_t ac_buffer_reader_readable(const ac_buffer_t *pBuf) +{ + size_t r = 0; + while (pBuf != NULL) { + r += ac_buffer_size(pBuf); + pBuf = ac_buffer_next(pBuf); + } + return r; +} + +const uint8_t *ac_buffer_reader_current_buffer_pointer(ac_buffer_t *pBuf) +{ + update_buf(pBuf); + return ac_buffer_data(pBuf); +} + +size_t ac_buffer_reader_current_buffer_length(ac_buffer_t *pBuf) +{ + update_buf(pBuf); + return ac_buffer_size(pBuf); +} + +bool ac_buffer_reader_cmp_bytes(const ac_buffer_t *pBuf, const uint8_t *bytes, size_t length) +{ + ac_buffer_t reader; + + if (length > ac_buffer_reader_readable(pBuf)) { + return false; + } + + ac_buffer_dup(&reader, pBuf); + + while (length > 0) { + size_t sz = ac_buffer_reader_current_buffer_length(&reader); + if (sz > length) { + sz = length; + } + int c = memcmp(ac_buffer_reader_current_buffer_pointer(&reader), bytes, sz); + if (c) { + return false; + } + length -= sz; + bytes += sz; + ac_buffer_read_n_skip(&reader, sz); + } + + return true; +} + +bool ac_buffer_reader_cmp(const ac_buffer_t *pBuf1, const ac_buffer_t *pBuf2) +{ + ac_buffer_t reader1; + ac_buffer_t reader2; + + if (ac_buffer_reader_readable(pBuf1) != ac_buffer_reader_readable(pBuf2)) { + return false; + } + + ac_buffer_dup(&reader1, pBuf1); + ac_buffer_dup(&reader2, pBuf2); + + size_t length = ac_buffer_reader_readable(pBuf1); + while (length > 0) { + size_t sz1 = ac_buffer_reader_current_buffer_length(&reader1); + size_t sz2 = ac_buffer_reader_current_buffer_length(&reader2); + + size_t sz = MIN(sz1, sz2); + + int c = memcmp(ac_buffer_reader_current_buffer_pointer(&reader1), ac_buffer_reader_current_buffer_pointer(&reader2), sz); + if (c) { + return false; + } + length -= sz; + ac_buffer_read_n_skip(&reader1, sz); + ac_buffer_read_n_skip(&reader2, sz); + } + + return true; +} diff --git a/connectivity/nfc/libraries/acore/source/ac_stream.c b/connectivity/nfc/libraries/acore/source/ac_stream.c new file mode 100644 index 0000000..6954f25 --- /dev/null +++ b/connectivity/nfc/libraries/acore/source/ac_stream.c @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2017, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + */ +/** + * \file stream.c + * \copyright Copyright (c) ARM Ltd 2015 + * \author Donatien Garnier + */ + +#include "acore/ac_stream.h" +#include "acore/ac_macros.h" + +//Called by supplier +void ac_istream_init(ac_istream_t *pac_istream, ac_istream_fn fn, void *pUserParam) +{ + pac_istream->fn = fn; + pac_istream->pUserParam = pUserParam; +} + +//Called by consumer +void ac_istream_pull(ac_istream_t *pac_istream, ac_buffer_t *pDataIn, bool *pClose, size_t maxLength) +{ + pac_istream->fn(pDataIn, pClose, maxLength, pac_istream->pUserParam); +} + +//Called by consumer +void ac_ostream_init(ac_ostream_t *pac_ostream, ac_ostream_fn fn, void *pUserParam) +{ + pac_ostream->fn = fn; + pac_ostream->pUserParam = pUserParam; +} + +//Called by supplier +void ac_ostream_push(ac_ostream_t *pac_ostream, ac_buffer_t *pDataOut, bool closed) +{ + pac_ostream->fn(pDataOut, closed, pac_ostream->pUserParam); +} diff --git a/connectivity/nfc/libraries/stack/ndef/ndef.c b/connectivity/nfc/libraries/stack/ndef/ndef.c new file mode 100644 index 0000000..50fb192 --- /dev/null +++ b/connectivity/nfc/libraries/stack/ndef/ndef.c @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2013-2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + */ +/** + * \file ndef.c + * \copyright Copyright (c) ARM Ltd 2013 + * \author Donatien Garnier + * \details NDEF tag abstraction + */ + + +#include "ndef.h" + +/** \addtogroup NDEF + * @{ + * \name Generic NDEF Tag + * @{ + */ + +/** Initialize NDEF tag abstraction + * \param pNdefTag pointer to ndef_tag_t structure to initialize + * \param encode function that will be called to generate the NDEF message before sending it to the other party + * \param decode function that will be called to parse the NDEF message after receiving it from the other party + * \param buffer underlying buffer to use (it should be big enough so that any NDEF message you might need could be stored inside) + * \param buffer_size size of the underlying buffer + * \param pImpl pointer to actual implementation + */ +void ndef_msg_init(ndef_msg_t *pNdef, ndef_encode_fn_t encode, ndef_decode_fn_t decode, uint8_t *data, size_t size, void *pUserData) +{ + pNdef->encode = encode; + pNdef->decode = decode; + ac_buffer_builder_init(&pNdef->bufferBldr, data, size); + pNdef->pUserData = pUserData; +} + +/** Get NDEF tag implementation + * \param pNdefTag pointer to ndef_tag_t structure + * \return implementation + */ +/* +void* ndef_tag_impl(ndef_tag_t* pNdefTag) +{ + return pNdefTag->pImpl; +} +*/ + +/** + * @} + * @} + * */ diff --git a/connectivity/nfc/libraries/stack/ndef/ndef.h b/connectivity/nfc/libraries/stack/ndef/ndef.h new file mode 100644 index 0000000..6ff4eb9 --- /dev/null +++ b/connectivity/nfc/libraries/stack/ndef/ndef.h @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2013-2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + */ +/** + * \file ndef.h + * \copyright Copyright (c) ARM Ltd 2013 + * \author Donatien Garnier + */ + +/** \addtogroup NDEF + * @{ + * \name Generic NDEF Tag + * @{ + */ + +#ifndef NDEF_H_ +#define NDEF_H_ + +#include "stack/nfc_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +//Generic interface for NDEF messages +typedef struct __ndef_msg ndef_msg_t; + +/** Function called to generate the tag's content on read (target mode) + * \param pTag pointer to ndef_tag_t instance + * \param type pMem buffer in which to store the generated content + */ +typedef nfc_err_t (*ndef_encode_fn_t)(ndef_msg_t *pTag, ac_buffer_builder_t *pBufferBldr, void *pUserData); + +/** Function called to decode the tag's content on write (target mode) or read (reader mode) + * \param pTag pointer to ndef_tag_t instance + * \param type pMem buffer containing the tag's content + */ +typedef nfc_err_t (*ndef_decode_fn_t)(ndef_msg_t *pTag, ac_buffer_t *pBuffer, void *pUserData); + +struct __ndef_msg { + ndef_encode_fn_t encode; + ndef_decode_fn_t decode; + ac_buffer_builder_t bufferBldr; + void *pUserData; +}; + +void ndef_msg_init(ndef_msg_t *pNdef, ndef_encode_fn_t encode, ndef_decode_fn_t decode, uint8_t *data, size_t size, void *pUserData); + +static inline nfc_err_t ndef_msg_encode(ndef_msg_t *pNdef) +{ + if (pNdef->encode == NULL) { + return NFC_OK; + } + return pNdef->encode(pNdef, &pNdef->bufferBldr, pNdef->pUserData); +} + +static inline nfc_err_t ndef_msg_decode(ndef_msg_t *pNdef) +{ + if (pNdef->decode == NULL) { + return NFC_OK; + } + return pNdef->decode(pNdef, ac_buffer_builder_buffer(&pNdef->bufferBldr), pNdef->pUserData); +} + +static inline ac_buffer_builder_t *ndef_msg_buffer_builder(ndef_msg_t *pNdef) +{ + return &pNdef->bufferBldr; +} + +//void* ndef_tag_impl(ndef_tag_t* pNdefTag); + +#ifdef __cplusplus +} +#endif + +#endif /* NDEF_H_ */ + +/** + * @} + * @} + * */ + diff --git a/connectivity/nfc/libraries/stack/nfc_common.h b/connectivity/nfc/libraries/stack/nfc_common.h new file mode 100644 index 0000000..e481188 --- /dev/null +++ b/connectivity/nfc/libraries/stack/nfc_common.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + */ +/** + * \file nfc_common.h + * \copyright Copyright (c) ARM Ltd 2018 + * \author Donatien Garnier + * \details Common includes for NFC Stack + */ + +#ifndef NFC_COMMON_H_ +#define NFC_COMMON_H_ + +#include "stddef.h" +#include "stdint.h" +#include "string.h" +#include "stdbool.h" + +#include "nfc_errors.h" + +#include "platform/nfc_debug.h" + +#include "acore/ac_macros.h" +#include "acore/ac_buffer.h" +#include "acore/ac_buffer_reader.h" +#include "acore/ac_buffer_builder.h" +#include "acore/ac_stream.h" + +#endif /* NFC_COMMON_H_ */ + +/** + * @} + * @} + * */ diff --git a/connectivity/nfc/libraries/stack/nfc_errors.h b/connectivity/nfc/libraries/stack/nfc_errors.h new file mode 100644 index 0000000..f8870cb --- /dev/null +++ b/connectivity/nfc/libraries/stack/nfc_errors.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2013-2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + */ +/** + * \file nfc_errors.h + * \copyright Copyright (c) ARM Ltd 2013 + * \author Donatien Garnier + * \details NFC Error codes + */ + +/** \addtogroup Core + * @{ + * \name Error codes + * @{ + */ + +#ifndef NFC_ERRORS_H_ +#define NFC_ERRORS_H_ + +#define NFC_OK 0 ///< No error + +#define NFC_ERR_UNKNOWN 1 ///< Unknown error +#define NFC_ERR_LENGTH 2 ///< Length of parameter is wrong +#define NFC_ERR_NOT_FOUND 3 ///< Could not find item +#define NFC_ERR_UNSUPPORTED 4 ///< This action is not supported +#define NFC_ERR_PARAMS 5 ///< These parameters are not correct +#define NFC_ERR_BUFFER_TOO_SMALL 6 ///< The buffer is too small to store all data (buffer overflow) +#define NFC_ERR_TIMEOUT 7 ///< Timeout +#define NFC_ERR_CRC 8 ///< Checksum does not match +#define NFC_ERR_NOPEER 9 ///< No target/initiator in vicinity +#define NFC_ERR_PARITY 10 ///< Parity error +#define NFC_ERR_FIELD 11 ///< No RF field detected (or RF field lost) +#define NFC_ERR_COLLISION 12 ///< Collision detected +#define NFC_ERR_WRONG_COMM 13 ///< Communication error +#define NFC_ERR_PROTOCOL 14 ///< Protocol is not conformant +#define NFC_ERR_BUSY 15 ///< Resource is busy +#define NFC_ERR_CONTROLLER 16 ///< Controller failure +#define NFC_ERR_HALTED 17 ///< Target has been halted +#define NFC_ERR_MAC 18 ///< MAC does not match +#define NFC_ERR_UNDERFLOW 19 ///< Could not send data in time +#define NFC_ERR_DISCONNECTED 20 ///< Link has disconnected +#define NFC_ERR_ABORTED 21 ///< Command was aborted + +/** Type for NFC errors + */ +typedef int nfc_err_t; + +#endif /* NFC_ERRORS_H_ */ + +/** + * @} + * @} + * */ diff --git a/connectivity/nfc/libraries/stack/platform/nfc_debug.h b/connectivity/nfc/libraries/stack/platform/nfc_debug.h new file mode 100644 index 0000000..0d6cd71 --- /dev/null +++ b/connectivity/nfc/libraries/stack/platform/nfc_debug.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + */ + +#ifndef MBED_NFC_DEBUG_H +#define MBED_NFC_DEBUG_H + +#if NFC_DEBUG && !defined(NDEBUG) && __DEBUG__ +#ifdef __MODULE__ +#define __NFC_MODULE__ __MODULE__ +#else +#define __NFC_MODULE__ __FILE__ +#endif + +#include "stdio.h" +#include "stdarg.h" +static inline void nfc_dbg_print(const char *type, const char *module, unsigned int line, const char *fmt, ...) +{ +#if !defined(NDEBUG) + printf("NFC [%s] %s:%u ", type, module, line); + va_list args; + va_start(args, fmt); + vprintf(fmt, args); + va_end(args); + printf("\r\n"); +#endif +} + +#if !defined(NFC_DBG) +#define NFC_DBG(...) nfc_dbg_print("DBG", __NFC_MODULE__, __LINE__, __VA_ARGS__) +#endif + +#if !defined(NFC_WARN) +#define NFC_WARN(...) nfc_dbg_print("WARN", __NFC_MODULE__, __LINE__, __VA_ARGS__) +#endif + +#if !defined(NFC_ERR) +#define NFC_ERR(...) nfc_dbg_print("ERR", __NFC_MODULE__, __LINE__, __VA_ARGS__) +#endif + +#define NFC_DBG_BLOCK(x) x + +#else + +#if !defined(NFC_DBG) +#define NFC_DBG(...) +#endif + +#if !defined(NFC_WARN) +#define NFC_WARN(...) +#endif + +#if !defined(NFC_ERR) +#define NFC_ERR(...) +#endif + +#define NFC_DBG_BLOCK(x) + +#endif + +#endif diff --git a/connectivity/nfc/libraries/stack/platform/nfc_scheduler.c b/connectivity/nfc/libraries/stack/platform/nfc_scheduler.c new file mode 100644 index 0000000..8ba8cce --- /dev/null +++ b/connectivity/nfc/libraries/stack/platform/nfc_scheduler.c @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2015-2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + */ +/** + * \file nfc_scheduler.c + * \copyright Copyright (c) ARM Ltd 2015 + * \author Donatien Garnier + */ + +#include +#include +#include + +#define __DEBUG__ 0 +#ifndef __MODULE__ +#define __MODULE__ "nfc_scheduler.c" +#endif + +#include "platform/nfc_scheduler.h" + +void nfc_scheduler_init(nfc_scheduler_t *pScheduler, nfc_scheduler_timer_t *pTimer) +{ + pScheduler->pNext = NULL; + pScheduler->pTimer = pTimer; + + //Start timer + nfc_scheduler_timer_start(pTimer); +} + +#define MAX_TIMEOUT UINT32_MAX + +uint32_t nfc_scheduler_iteration(nfc_scheduler_t *pScheduler, uint32_t events) +{ + while (true) { + nfc_task_t *pPrioTask = NULL; + nfc_task_t *pPrioTaskPrevious = NULL; + uint32_t prioTaskEvent = 0; + int64_t timeout; + nfc_task_t *pPreviousTask = NULL; + nfc_task_t *pTask = pScheduler->pNext; + + if (pTask == NULL) { + NFC_DBG("Empty queue, %lu ms elapsed", nfc_scheduler_timer_get(pScheduler->pTimer)); + //Empty queue, return + return MAX_TIMEOUT; + } + + //Get timer value + uint32_t timeElapsed = nfc_scheduler_timer_get(pScheduler->pTimer); + NFC_DBG("%lu ms elapsed", timeElapsed); + nfc_scheduler_timer_reset(pScheduler->pTimer); + + do { + //Apply timeouts + if (pTask->events & EVENT_TIMEOUT) { + pTask->timeout -= timeElapsed; + } + pPreviousTask = pTask; + pTask = pTask->pNext; + } while (pTask != NULL); + + pTask = pScheduler->pNext; + pPreviousTask = NULL; + timeout = MAX_TIMEOUT; + do { + //Check which task should be woken up first + if ((events & EVENT_HW_INTERRUPT) && (pTask->events & EVENT_HW_INTERRUPT)) { + //Hardware interrupts have prio + pPrioTask = pTask; + pPrioTaskPrevious = pPreviousTask; + timeout = 0; + events &= ~EVENT_HW_INTERRUPT; //Only one task gets triggered per event + prioTaskEvent = EVENT_HW_INTERRUPT; + break; + } else if ((pTask->events & EVENT_TIMEOUT) && (pTask->timeout < timeout)) { + pPrioTask = pTask; + pPrioTaskPrevious = pPreviousTask; + timeout = pTask->timeout; + prioTaskEvent = EVENT_TIMEOUT; + } + pPreviousTask = pTask; + pTask = pTask->pNext; + } while (pTask != NULL); + + if (pPrioTask == NULL) { + //No task to wake up, exit + NFC_DBG("No task to wake up"); + return MAX_TIMEOUT; + } + + if (timeout > 0) { + //No task to wake up yet + if (timeout > MAX_TIMEOUT) { + NFC_DBG("No task to wake up"); + return MAX_TIMEOUT; + } else { + NFC_DBG("No task to wake up, wait %lu ms", timeout); + return timeout; + } + } + + //Dequeue task + if (pPrioTaskPrevious == NULL) { + pScheduler->pNext = pPrioTask->pNext; + } else { + pPrioTaskPrevious->pNext = pPrioTask->pNext; + } + pPrioTask->pNext = NULL; + + //Execute task + NFC_DBG("Calling task %p - events %02X", pPrioTask, prioTaskEvent); + pPrioTask->fn(prioTaskEvent, pPrioTask->pUserData); + events &= ~EVENT_HW_INTERRUPT; //Only one task gets triggered per event + } + return MAX_TIMEOUT; +} + +void nfc_scheduler_queue_task(nfc_scheduler_t *pScheduler, nfc_task_t *pTask) +{ + pTask->timeout = pTask->timeoutInitial + nfc_scheduler_timer_get(pScheduler->pTimer); + NFC_DBG("Queuing task %p: events %1X, timeout %lu ms", pTask, pTask->events, pTask->timeout); + //Find last task + nfc_task_t *pPrevTask = pScheduler->pNext; + pTask->pNext = NULL; + if (pPrevTask == NULL) { + pScheduler->pNext = pTask; + return; + } + while (pPrevTask->pNext != NULL) { + pPrevTask = pPrevTask->pNext; + } + pPrevTask->pNext = pTask; +} + +void nfc_scheduler_dequeue_task(nfc_scheduler_t *pScheduler, bool abort, nfc_task_t *pTask) +{ + NFC_DBG("Dequeuing task %p", pTask); + //Find task + nfc_task_t *pPrevTask = pScheduler->pNext; + if (pPrevTask == NULL) { + pTask->pNext = NULL; + return; + } + if (pPrevTask == pTask) { + if (abort) { + pTask->fn(EVENT_ABORTED, pTask->pUserData); + } + pScheduler->pNext = pTask->pNext; + pTask->pNext = NULL; + return; + } + while (pPrevTask->pNext != NULL) { + if (pPrevTask->pNext == pTask) { + if (abort) { + pTask->fn(EVENT_ABORTED, pTask->pUserData); + } + pPrevTask->pNext = pTask->pNext; + pTask->pNext = NULL; + return; + } + pPrevTask = pPrevTask->pNext; + } + pTask->pNext = NULL; +} + +void task_init(nfc_task_t *pTask, uint32_t events, uint32_t timeout, nfc_task_fn fn, void *pUserData) +{ + pTask->events = events; + pTask->timeoutInitial = timeout; + pTask->fn = fn; + pTask->pUserData = pUserData; + pTask->pNext = NULL; +} diff --git a/connectivity/nfc/libraries/stack/platform/nfc_scheduler.h b/connectivity/nfc/libraries/stack/platform/nfc_scheduler.h new file mode 100644 index 0000000..6e1fb2d --- /dev/null +++ b/connectivity/nfc/libraries/stack/platform/nfc_scheduler.h @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2014-2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + */ +/** + * \file nfc_scheduler.h + * \copyright Copyright (c) ARM Ltd 2014 + * \author Donatien Garnier + */ +/** \addtogroup Core + * @{ + * \name Scheduler + * @{ + */ + +#ifndef NFC_SCHEDULER_H_ +#define NFC_SCHEDULER_H_ + +#include "stack/nfc_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define EVENT_NONE 0 +#define EVENT_TIMEOUT 1 +#define EVENT_ABORTED 2 +#define EVENT_HW_INTERRUPT 4 + +struct __nfc_timer; +typedef struct __nfc_timer nfc_scheduler_timer_t; + +struct __nfc_task; +typedef struct __nfc_task nfc_task_t; + +typedef struct __scheduler { + nfc_task_t *pNext; + nfc_scheduler_timer_t *pTimer; +} nfc_scheduler_t; + +typedef void (*nfc_task_fn)(uint32_t events, void *pUserData); + +struct __nfc_task { + uint32_t events; + int64_t timeout; //millisecs + int64_t timeoutInitial; + + nfc_task_fn fn; + void *pUserData; + + nfc_task_t *pNext; +}; + +void nfc_scheduler_timer_init(nfc_scheduler_timer_t *timer); + +void nfc_scheduler_timer_start(nfc_scheduler_timer_t *timer); + +uint32_t nfc_scheduler_timer_get(nfc_scheduler_timer_t *timer); + +void nfc_scheduler_timer_stop(nfc_scheduler_timer_t *timer); + +void nfc_scheduler_timer_reset(nfc_scheduler_timer_t *timer); + +/** Init scheduler + * \param pScheduler scheduler instance to init + * \param pTimer timer instance + */ +void nfc_scheduler_init(nfc_scheduler_t *pScheduler, nfc_scheduler_timer_t *pTimer); + +/** Iterate through all tasks + * \param pScheduler scheduler instance + * \param events mask of events (except EVENT_TIMEOUT) that have been raised since this function last returned (0 on first call) + * \return time after which this function must be called again if no other event arises + */ +uint32_t nfc_scheduler_iteration(nfc_scheduler_t *pScheduler, uint32_t events); + +/** Queue a task to execute + * \param pScheduler scheduler instance + * \param pTask task to queue + * + */ +void nfc_scheduler_queue_task(nfc_scheduler_t *pScheduler, nfc_task_t *pTask); + +/** Remove a task to execute + * \param pScheduler scheduler instance + * \param pTask task to remove + * \param abort abort task if queued + */ +void nfc_scheduler_dequeue_task(nfc_scheduler_t *pScheduler, bool abort, nfc_task_t *pTask); + +/** Initialize task with the following parameters + * \param pTask task to initialize + * \param events events on which to call task + * \param timeout if relevant + * \param fn function to be called + * \param pUserData data that will be passed to function + */ +void task_init(nfc_task_t *pTask, uint32_t events, uint32_t timeout, nfc_task_fn fn, void *pUserData); + +#ifdef __cplusplus +} +#endif + +#endif /* NFC_SCHEDULER_H_ */ + +/** + * @} + * @} + * */ + diff --git a/connectivity/nfc/libraries/stack/platform/nfc_transport.c b/connectivity/nfc/libraries/stack/platform/nfc_transport.c new file mode 100644 index 0000000..5dcbf80 --- /dev/null +++ b/connectivity/nfc/libraries/stack/platform/nfc_transport.c @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2013-2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + */ +/** + * \file nfc_transport.c + * \copyright Copyright (c) ARM Ltd 2013-2018 + * \author Donatien Garnier + * \details Transport layer + */ + +/** \addtogroup Implementation + * @{ + * \name Transport + * @{ + */ + +#include "stack/nfc_errors.h" +#include "nfc_transport.h" + +/** Initialize transport with a specific implementation + * \param pTransport pointer to a nfc_transport_t structure to initialize + * \param write transport write function + * \param read transport read function + * \param pUser parameter that will be passed to any of the above functions + */ +void nfc_transport_init(nfc_transport_t *pTransport, nfc_transport_write_fn_t write, nfc_transport_read_fn_t read, void *pUser) +{ + pTransport->write = write; + pTransport->read = read; + pTransport->pUser = pUser; +} + + + + +/** + * @} + * @} + * */ + diff --git a/connectivity/nfc/libraries/stack/platform/nfc_transport.h b/connectivity/nfc/libraries/stack/platform/nfc_transport.h new file mode 100644 index 0000000..5e25283 --- /dev/null +++ b/connectivity/nfc/libraries/stack/platform/nfc_transport.h @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2013-2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + */ +/** + * \file nfc_transport.h + * \copyright Copyright (c) ARM Ltd 2013-2018 + * \author Donatien Garnier + */ + +/** \addtogroup Implementation + * @{ + * \name Transport + * @{ + */ + +#ifndef NFC_TRANSPORT_H_ +#define NFC_TRANSPORT_H_ + +#include "stack/nfc_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** Function called to write a register's value + * \param address address of the register to write to + * \param outBuf buffer to write + * \param outLen buffer's length + * \param pUser parameter passed to the nfc_transport_init function + */ +typedef void (*nfc_transport_write_fn_t)(uint8_t address, const uint8_t *outBuf, size_t outLen, void *pUser); + +/** Function called to read a register's value + * \param address address to read packet from + * \param outBuf buffer to read + * \param outLen buffer's length + * \param pUser parameter passed to the nfc_transport_init function + */ +typedef void (*nfc_transport_read_fn_t)(uint8_t address, uint8_t *inBuf, size_t inLen, void *pUser); + +typedef struct __transport { + nfc_transport_write_fn_t write; + nfc_transport_read_fn_t read; + void *pUser; +} nfc_transport_t; + +void nfc_transport_init(nfc_transport_t *pTransport, nfc_transport_write_fn_t write, nfc_transport_read_fn_t read, void *pUser); + +static inline void nfc_transport_write(nfc_transport_t *pTransport, uint8_t address, const uint8_t *outBuf, size_t outLen) +{ + pTransport->write(address, outBuf, outLen, pTransport->pUser); +} + +static inline void nfc_transport_read(nfc_transport_t *pTransport, uint8_t address, uint8_t *inBuf, size_t inLen) +{ + pTransport->read(address, inBuf, inLen, pTransport->pUser); +} + +#ifdef __cplusplus +} +#endif + +#endif /* NFC_TRANSPORT_H_ */ + + +/** + * @} + * @} + * */ + diff --git a/connectivity/nfc/libraries/stack/tech/iso7816/iso7816.c b/connectivity/nfc/libraries/stack/tech/iso7816/iso7816.c new file mode 100644 index 0000000..fec02ae --- /dev/null +++ b/connectivity/nfc/libraries/stack/tech/iso7816/iso7816.c @@ -0,0 +1,343 @@ +/* + * Copyright (c) 2015-2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + */ +/** + * \file iso7816.c + * \copyright Copyright (c) ARM Ltd 2015 + * \author Donatien Garnier + */ + +#define __DEBUG__ 0 +#ifndef __MODULE__ +#define __MODULE__ "iso7816.c" +#endif + +#include "stack/nfc_errors.h" + +#include "iso7816.h" +#include "iso7816_app.h" +#include "iso7816_defs.h" +#include "tech/isodep/isodep_target.h" +#include "platform/nfc_debug.h" + +static void iso7816_disconnected(nfc_tech_iso7816_t *pIso7816, bool deselected); + +static nfc_err_t iso7816_parse(nfc_tech_iso7816_t *pIso7816); + +static void iso7816_receive(nfc_tech_iso7816_t *pIso7816); +static nfc_err_t iso7816_transmit(nfc_tech_iso7816_t *pIso7816); + +static bool iso7816_mf_command(nfc_tech_iso7816_t *pIso7816); + +static void iso_dep_received_cb(nfc_tech_isodep_t *pIsodep, nfc_err_t ret, void *pUserData); +static void iso_dep_transmitted_cb(nfc_tech_isodep_t *pIsodep, nfc_err_t ret, void *pUserData); +static void iso_dep_disconnected_cb(nfc_tech_isodep_t *pIsodep, bool deselected, void *pUserData); + +static void iso_dep_stream_transmit_cb(ac_buffer_t *ppDataIn, bool *pClose, size_t maxLength, void *pUserParam); +static void iso_dep_stream_receive_cb(ac_buffer_t *pDataOut, bool closed, void *pUserParam); + +void nfc_tech_iso7816_init(nfc_tech_iso7816_t *pIso7816, nfc_transceiver_t *pTransceiver, nfc_tech_iso7816_disconnected_cb disconnectedCb, void *pUserData) +{ + ac_buffer_init(&pIso7816->hist, NULL, 0); + nfc_tech_isodep_target_init(&pIso7816->isoDepTarget, pTransceiver, &pIso7816->hist, iso_dep_disconnected_cb, pIso7816); + pIso7816->pAppList = NULL; + pIso7816->pSelectedApp = NULL; + pIso7816->disconnectedCb = disconnectedCb; + + ac_istream_init(&pIso7816->inputStream, iso_dep_stream_transmit_cb, pIso7816); + ac_ostream_init(&pIso7816->outputStream, iso_dep_stream_receive_cb, pIso7816); + + ac_buffer_builder_init(&pIso7816->txBldr, pIso7816->txBuf, 2); //Just enough to fit sw + + ac_buffer_builder_init(&pIso7816->rxBldr, pIso7816->rxBuf, ISO7816_RX_BUFFER_SIZE); + + pIso7816->pUserData = pUserData; +} + +void nfc_tech_iso7816_connect(nfc_tech_iso7816_t *pIso7816) +{ + pIso7816->disconnected = false; + pIso7816->responseReady = true; + + iso7816_receive(pIso7816); + nfc_tech_isodep_target_connect(&pIso7816->isoDepTarget); +} + +void nfc_tech_iso7816_disconnect(nfc_tech_iso7816_t *pIso7816) +{ + nfc_tech_isodep_target_disconnect(&pIso7816->isoDepTarget); +} + +void nfc_tech_iso7816_add_app(nfc_tech_iso7816_t *pIso7816, nfc_tech_iso7816_app_t *pIso7816App) +{ + nfc_tech_iso7816_app_t **ppPrevApp = &pIso7816->pAppList; + while (*ppPrevApp != NULL) { + ppPrevApp = &((*ppPrevApp)->pNext); + } + *ppPrevApp = pIso7816App; + pIso7816App->pNext = NULL; +} + +nfc_err_t nfc_tech_iso7816_reply(nfc_tech_iso7816_t *pIso7816) +{ + nfc_err_t ret; + + //Serialize APDU and send + ac_buffer_builder_reset(&pIso7816->txBldr); + ac_buffer_builder_write_nu16(&pIso7816->txBldr, pIso7816->rApdu.sw); + + ac_buffer_append(&pIso7816->rApdu.dataOut, ac_buffer_builder_buffer(&pIso7816->txBldr)); + + NFC_DBG("R-ADPU: (LE):%02X SW:%04X", ac_buffer_reader_readable(&pIso7816->rApdu.dataOut), pIso7816->rApdu.sw); + NFC_DBG_BLOCK(ac_buffer_dump(&pIso7816->rApdu.dataOut);) + + ret = iso7816_transmit(pIso7816); + if (ret) { + return ret; + } + + return NFC_OK; +} + +void iso7816_disconnected(nfc_tech_iso7816_t *pIso7816, bool deselected) +{ + pIso7816->disconnected = true; + if (pIso7816->pSelectedApp != NULL) { + //Deselect previous app + pIso7816->pSelectedApp->deselected(pIso7816->pSelectedApp, pIso7816->pSelectedApp->pUserData); + pIso7816->pSelectedApp = NULL; + } + if (!deselected) { + pIso7816->disconnectedCb(pIso7816, pIso7816->pUserData); + } +} + +nfc_err_t iso7816_parse(nfc_tech_iso7816_t *pIso7816) +{ + //Reset R-APDU + ac_buffer_init(&pIso7816->rApdu.dataOut, NULL, 0); + pIso7816->rApdu.sw = ISO7816_SW_OK; + + NFC_DBG_BLOCK(ac_buffer_dump(ac_buffer_builder_buffer(&pIso7816->rxBldr));) + + if (ac_buffer_reader_readable(ac_buffer_builder_buffer(&pIso7816->rxBldr)) < 4) { + NFC_ERR("C-APDU is too small"); + pIso7816->rApdu.sw = ISO7816_SW_INVALID_CLASS; + nfc_tech_iso7816_reply(pIso7816); + return NFC_ERR_PROTOCOL; + } + + pIso7816->cApdu.cla = ac_buffer_read_nu8(ac_buffer_builder_buffer(&pIso7816->rxBldr)); + pIso7816->cApdu.ins = ac_buffer_read_nu8(ac_buffer_builder_buffer(&pIso7816->rxBldr)); + pIso7816->cApdu.p1 = ac_buffer_read_nu8(ac_buffer_builder_buffer(&pIso7816->rxBldr)); + pIso7816->cApdu.p2 = ac_buffer_read_nu8(ac_buffer_builder_buffer(&pIso7816->rxBldr)); + ac_buffer_init(&pIso7816->cApdu.dataIn, NULL, 0); + pIso7816->cApdu.maxRespLength = 0; + + if (ac_buffer_reader_readable(ac_buffer_builder_buffer(&pIso7816->rxBldr)) > 1) { + size_t lc = ac_buffer_read_nu8(ac_buffer_builder_buffer(&pIso7816->rxBldr)); + if (ac_buffer_reader_readable(ac_buffer_builder_buffer(&pIso7816->rxBldr)) >= lc) { + ac_buffer_split(&pIso7816->cApdu.dataIn, ac_buffer_builder_buffer(&pIso7816->rxBldr), ac_buffer_builder_buffer(&pIso7816->rxBldr), lc); + } else { + pIso7816->rApdu.sw = ISO7816_SW_WRONG_LENGTH; + nfc_tech_iso7816_reply(pIso7816); + return NFC_ERR_LENGTH; //Not a valid frame + } + } + + if (ac_buffer_reader_readable(ac_buffer_builder_buffer(&pIso7816->rxBldr)) >= 1) { + pIso7816->cApdu.maxRespLength = ac_buffer_read_nu8(ac_buffer_builder_buffer(&pIso7816->rxBldr)); + } + + NFC_DBG("C-APDU: CLA:%02X INS:%02X P1:%02X P2:%02X LC:%02X LE:%02X", pIso7816->cApdu.cla, pIso7816->cApdu.ins, pIso7816->cApdu.p1, pIso7816->cApdu.p2, + ac_buffer_reader_readable(&pIso7816->cApdu.dataIn), pIso7816->cApdu.maxRespLength); + + if (ac_buffer_reader_readable(ac_buffer_builder_buffer(&pIso7816->rxBldr)) > 0) { + pIso7816->rApdu.sw = ISO7816_SW_WRONG_LENGTH; + nfc_tech_iso7816_reply(pIso7816); + return NFC_ERR_LENGTH; //Not a valid frame + } + + //See if can select an app + if (iso7816_mf_command(pIso7816)) { + nfc_tech_iso7816_reply(pIso7816); + return NFC_OK; + } + + //Pass command to selected app + if (pIso7816->pSelectedApp == NULL) { + pIso7816->rApdu.sw = ISO7816_SW_NOT_FOUND; + nfc_tech_iso7816_reply(pIso7816); + return NFC_ERR_NOT_FOUND; //Not a valid frame + } + + pIso7816->pSelectedApp->apdu(pIso7816->pSelectedApp, pIso7816->pSelectedApp->pUserData); + + return NFC_OK; +} + +void iso7816_receive(nfc_tech_iso7816_t *pIso7816) +{ + ac_buffer_builder_reset(&pIso7816->rxBldr); + nfc_tech_isodep_target_receive(&pIso7816->isoDepTarget, &pIso7816->outputStream, iso_dep_received_cb, pIso7816); +} + +nfc_err_t iso7816_transmit(nfc_tech_iso7816_t *pIso7816) +{ + return nfc_tech_isodep_target_transmit(&pIso7816->isoDepTarget, &pIso7816->inputStream, iso_dep_transmitted_cb, pIso7816); +} + +/** Handle ISO7816-4 command + * \param pTarget pointer to target instance + * \param CLA ISO7816-4 class byte + * \param INS ISO7816-4 instruction byte + * \param P1 ISO7816-4 P1 byte + * \param P2 ISO7816-4 P2 byte + * \param pDataIn ISO7816-4 command payload + * \param pDataOut ISO7816-4 response payload + * \param SW status word + * \return true if command was handled, false if it should be passed to the selected application + */ +bool iso7816_mf_command(nfc_tech_iso7816_t *pIso7816) +{ + nfc_tech_iso7816_app_t *pApp; + if (pIso7816->cApdu.cla != 0x00) { + return false; + } + switch (pIso7816->cApdu.ins) { + case ISO7816_INS_SELECT: + switch (pIso7816->cApdu.p1) { + case 0x04: //Selection by DF name + pApp = pIso7816->pAppList; + while (pApp != NULL) { + if (ac_buffer_reader_readable(&pIso7816->cApdu.dataIn) <= pApp->aidSize) { + if (ac_buffer_reader_cmp_bytes(&pIso7816->cApdu.dataIn, pApp->aid, ac_buffer_reader_readable(&pIso7816->cApdu.dataIn))) { + if (pIso7816->pSelectedApp != NULL) { + //Deselect previous app + pIso7816->pSelectedApp->deselected(pIso7816->pSelectedApp, pIso7816->pSelectedApp->pUserData); + } + pIso7816->pSelectedApp = pApp; + pIso7816->pSelectedApp->selected(pIso7816->pSelectedApp, pIso7816->pSelectedApp->pUserData); + pIso7816->rApdu.sw = ISO7816_SW_OK; + return true; + } + } + pApp = pApp->pNext; + } + pIso7816->rApdu.sw = ISO7816_SW_NOT_FOUND; + return true; + default: + if (pIso7816->pSelectedApp == NULL) { + pIso7816->rApdu.sw = ISO7816_SW_NOT_FOUND; + return true; + } else { + return false; + } + } + break; + default: + if (pIso7816->pSelectedApp == NULL) { + pIso7816->rApdu.sw = ISO7816_SW_INVALID_INS; + return true; + } else { + return false; + } + break; + } +} + +void iso_dep_received_cb(nfc_tech_isodep_t *pIsodep, nfc_err_t ret, void *pUserData) +{ + nfc_tech_iso7816_t *pIso7816 = (nfc_tech_iso7816_t *) pUserData; + + (void) pIsodep; + + if (ret) { + NFC_WARN("Got error %d", ret); + return; + } + + //Parse received APDU + ret = iso7816_parse(pIso7816); + if (ret) { + NFC_WARN("Got error %d", ret); + return; + } +} + +void iso_dep_transmitted_cb(nfc_tech_isodep_t *pIsodep, nfc_err_t ret, void *pUserData) +{ + nfc_tech_iso7816_t *pIso7816 = (nfc_tech_iso7816_t *) pUserData; + + (void) pIsodep; + + if (ret) { + NFC_WARN("Got error %d", ret); + return; + } + + //Advertise that we have space in our buffer? + + //Switch to receive mode! + iso7816_receive(pIso7816); +} + +void iso_dep_disconnected_cb(nfc_tech_isodep_t *pIsodep, bool deselected, void *pUserData) +{ + nfc_tech_iso7816_t *pIso7816 = (nfc_tech_iso7816_t *) pUserData; + + (void) pIsodep; + + NFC_DBG("ISO DEP %s", deselected ? "deselected" : "disconnected"); + iso7816_disconnected(pIso7816, deselected); + + if (deselected) { + // Re-connect immediately + nfc_tech_iso7816_connect(pIso7816); + } +} + +void iso_dep_stream_transmit_cb(ac_buffer_t *pDataIn, bool *pClose, size_t maxLength, void *pUserParam) +{ + nfc_tech_iso7816_t *pIso7816 = (nfc_tech_iso7816_t *) pUserParam; + + //Only close if buffer fits in this frame + if (maxLength >= ac_buffer_reader_readable(&pIso7816->rApdu.dataOut)) + //if( ac_buffer_total_length(&pLlcp->tx) <= maxLength ) + { + maxLength = ac_buffer_reader_readable(&pIso7816->rApdu.dataOut); + *pClose = true; + } else { + *pClose = false; + } + + ac_buffer_split(pDataIn, &pIso7816->rApdu.dataOut, &pIso7816->rApdu.dataOut, maxLength); +} + +void iso_dep_stream_receive_cb(ac_buffer_t *pDataOut, bool closed, void *pUserParam) +{ + nfc_tech_iso7816_t *pIso7816 = (nfc_tech_iso7816_t *) pUserParam; + + (void) closed; + + if (ac_buffer_reader_readable(pDataOut) > ac_buffer_builder_writable(&pIso7816->rxBldr)) { + NFC_ERR("Frame will not fit (%u > %u)", ac_buffer_reader_readable(pDataOut), ac_buffer_builder_writable(&pIso7816->rxBldr)); + } + + //Feed rx buffer + ac_buffer_builder_copy_n_bytes(&pIso7816->rxBldr, pDataOut, ac_buffer_reader_readable(pDataOut)); +} + diff --git a/connectivity/nfc/libraries/stack/tech/iso7816/iso7816.h b/connectivity/nfc/libraries/stack/tech/iso7816/iso7816.h new file mode 100644 index 0000000..ea223f4 --- /dev/null +++ b/connectivity/nfc/libraries/stack/tech/iso7816/iso7816.h @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2014-2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + */ +/** + * \file iso7816.h + * \copyright Copyright (c) ARM Ltd 2014 + * \author Donatien Garnier + */ + +#ifndef ISO7816_H_ +#define ISO7816_H_ + +#include "stack/nfc_common.h" + +#include "transceiver/protocols.h" +#include "tech/isodep/isodep_target.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct nfc_tech_iso7816_c_apdu { + uint8_t cla; + uint8_t ins; + uint8_t p1; + uint8_t p2; + ac_buffer_t dataIn; + size_t maxRespLength; +}; + +struct nfc_tech_iso7816_r_apdu { + ac_buffer_t dataOut; + uint16_t sw; +}; + +#define ISO7816_RX_BUFFER_SIZE 256 + +typedef struct nfc_tech_iso7816_c_apdu nfc_tech_iso7816_c_apdu_t; +typedef struct nfc_tech_iso7816_r_apdu nfc_tech_iso7816_r_apdu_t; + +typedef struct nfc_tech_iso7816 nfc_tech_iso7816_t; + +typedef void (*nfc_tech_iso7816_disconnected_cb)(nfc_tech_iso7816_t *pIso7816, void *pUserData); + +struct nfc_tech_iso7816_app; +typedef struct nfc_tech_iso7816_app nfc_tech_iso7816_app_t; + +struct nfc_tech_iso7816 { + nfc_tech_isodep_target_t isoDepTarget; + + nfc_tech_iso7816_app_t *pAppList; + nfc_tech_iso7816_app_t *pSelectedApp; + + bool disconnected; + + nfc_tech_iso7816_c_apdu_t cApdu; + nfc_tech_iso7816_r_apdu_t rApdu; + + bool responseReady; + + nfc_tech_iso7816_disconnected_cb disconnectedCb; + void *pUserData; + + ac_buffer_t hist; //Historical bytes + + ac_istream_t inputStream; + ac_ostream_t outputStream; + + //PDU buffer (tx) + uint8_t txBuf[2]; + ac_buffer_builder_t txBldr; + + //Receive buffer + uint8_t rxBuf[ISO7816_RX_BUFFER_SIZE]; + ac_buffer_builder_t rxBldr; +}; + +void nfc_tech_iso7816_init(nfc_tech_iso7816_t *pIso7816, nfc_transceiver_t *pTransceiver, nfc_tech_iso7816_disconnected_cb disconnectedCb, void *pUserData); +void nfc_tech_iso7816_add_app(nfc_tech_iso7816_t *pIso7816, nfc_tech_iso7816_app_t *pIso7816App); +void nfc_tech_iso7816_connect(nfc_tech_iso7816_t *pIso7816); +void nfc_tech_iso7816_disconnect(nfc_tech_iso7816_t *pIso7816); +nfc_err_t nfc_tech_iso7816_reply(nfc_tech_iso7816_t *pIso7816); + +inline static nfc_tech_iso7816_c_apdu_t *nfc_tech_iso7816_c_apdu(nfc_tech_iso7816_t *pIso7816) +{ + return &pIso7816->cApdu; +} + +inline static nfc_tech_iso7816_r_apdu_t *nfc_tech_iso7816_r_apdu(nfc_tech_iso7816_t *pIso7816) +{ + return &pIso7816->rApdu; +} + +#ifdef __cplusplus +} +#endif + +#endif /* ISO7816_H_ */ diff --git a/connectivity/nfc/libraries/stack/tech/iso7816/iso7816_app.c b/connectivity/nfc/libraries/stack/tech/iso7816/iso7816_app.c new file mode 100644 index 0000000..63ee17a --- /dev/null +++ b/connectivity/nfc/libraries/stack/tech/iso7816/iso7816_app.c @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2013-2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + */ +/** + * \file iso7816_app.c + * \copyright Copyright (c) ARM Ltd 2015-2018 + * \author Donatien Garnier + */ + +#include "iso7816_app.h" + +void nfc_tech_iso7816_app_init(nfc_tech_iso7816_app_t *pIso7816App, + nfc_tech_iso7816_t *pIso7816, + const uint8_t *aid, size_t aidSize, + nfc_tech_iso7816_app_cb selected, + nfc_tech_iso7816_app_cb deselected, + nfc_tech_iso7816_app_cb apdu, + void *pUserData + ) +{ + pIso7816App->pIso7816 = pIso7816; + pIso7816App->aid = aid; + pIso7816App->aidSize = aidSize; + pIso7816App->selected = selected; + pIso7816App->deselected = deselected; + pIso7816App->apdu = apdu; + pIso7816App->pUserData = pUserData; + pIso7816App->pNext = NULL; +} diff --git a/connectivity/nfc/libraries/stack/tech/iso7816/iso7816_app.h b/connectivity/nfc/libraries/stack/tech/iso7816/iso7816_app.h new file mode 100644 index 0000000..25c403e --- /dev/null +++ b/connectivity/nfc/libraries/stack/tech/iso7816/iso7816_app.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2015-2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + */ +/** + * \file iso7816_app.h + * \copyright Copyright (c) ARM Ltd 2015 + * \author Donatien Garnier + */ +#ifndef TECH_ISO7816_ISO7816_APP_H_ +#define TECH_ISO7816_ISO7816_APP_H_ + +#include "stack/nfc_common.h" +#include "iso7816.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct nfc_tech_iso7816; +struct nfc_tech_iso7816_app; + +typedef void (*nfc_tech_iso7816_app_cb)(nfc_tech_iso7816_app_t *pIso7816App, void *pUserData); + +struct nfc_tech_iso7816_app { + nfc_tech_iso7816_t *pIso7816; + + const uint8_t *aid; + size_t aidSize; + + nfc_tech_iso7816_app_cb selected; + nfc_tech_iso7816_app_cb deselected; + nfc_tech_iso7816_app_cb apdu; + + void *pUserData; + + nfc_tech_iso7816_app_t *pNext; +}; + +void nfc_tech_iso7816_app_init(nfc_tech_iso7816_app_t *pIso7816App, nfc_tech_iso7816_t *pIso7816, const uint8_t *aid, size_t aidSize, + nfc_tech_iso7816_app_cb selected, + nfc_tech_iso7816_app_cb deselected, + nfc_tech_iso7816_app_cb apdu, + void *pUserData + ); + +inline static nfc_err_t nfc_tech_iso7816_app_reply(nfc_tech_iso7816_app_t *pIso7816App) +{ + return nfc_tech_iso7816_reply(pIso7816App->pIso7816); +} + +inline static nfc_tech_iso7816_c_apdu_t *nfc_tech_iso7816_app_c_apdu(nfc_tech_iso7816_app_t *pIso7816App) +{ + return nfc_tech_iso7816_c_apdu(pIso7816App->pIso7816); +} + +inline static nfc_tech_iso7816_r_apdu_t *nfc_tech_iso7816_app_r_apdu(nfc_tech_iso7816_app_t *pIso7816App) +{ + return nfc_tech_iso7816_r_apdu(pIso7816App->pIso7816); +} + +#ifdef __cplusplus +} +#endif + +#endif /* TECH_ISO7816_ISO7816_APP_H_ */ diff --git a/connectivity/nfc/libraries/stack/tech/iso7816/iso7816_defs.h b/connectivity/nfc/libraries/stack/tech/iso7816/iso7816_defs.h new file mode 100644 index 0000000..7f7e42c --- /dev/null +++ b/connectivity/nfc/libraries/stack/tech/iso7816/iso7816_defs.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2013-2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + */ +/** + * \file iso7816_defs.h + * \copyright Copyright (c) ARM Ltd 2013 + * \author Donatien Garnier + */ + +#ifndef ISO7816_DEFS_H_ +#define ISO7816_DEFS_H_ + +#define ISO7816_INS_SELECT 0xA4 +#define ISO7816_INS_READ_BINARY 0xB0 +#define ISO7816_INS_UPDATE_BINARY 0xD6 +#define ISO7816_INS_ENVELOPE 0xC2 + + +#define ISO7816_SW_OK 0x9000 +#define ISO7816_SW_INVALID_CLASS 0x6E00 +#define ISO7816_SW_INVALID_INS 0x6D00 +#define ISO7816_SW_NOT_FOUND 0x6A82 +#define ISO7816_SW_WRONG_LENGTH 0x6700 + +#define ISO7816_PUT_SW(buf, sw) do{ *(buf)=(sw>>8) & 0xFF; *(buf+1)=(sw>>0) & 0xFF; } while(0); + + + +#endif /* ISO7816_DEFS_H_ */ diff --git a/connectivity/nfc/libraries/stack/tech/isodep/isodep.h b/connectivity/nfc/libraries/stack/tech/isodep/isodep.h new file mode 100644 index 0000000..7ef3c72 --- /dev/null +++ b/connectivity/nfc/libraries/stack/tech/isodep/isodep.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2015-2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + */ +/** + * \file isodep.h + * \copyright Copyright (c) ARM Ltd 2014 + * \author Donatien Garnier + */ + +#ifndef ISODEP_H_ +#define ISODEP_H_ + +#include "stack/nfc_common.h" +#include "transceiver/transceiver.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct nfc_tech_isodep; +typedef struct nfc_tech_isodep nfc_tech_isodep_t; + +typedef void (*nfc_tech_isodep_cb_t)(nfc_tech_isodep_t *pIsodep, nfc_err_t ret, void *pUserData); +typedef void (*nfc_tech_isodep_disconnected_cb)(nfc_tech_isodep_t *pIsodep, bool deselected, void *pUserData); + +#ifdef __cplusplus +} +#endif + +#endif /* ISODEP_H_ */ diff --git a/connectivity/nfc/libraries/stack/tech/isodep/isodep_target.c b/connectivity/nfc/libraries/stack/tech/isodep/isodep_target.c new file mode 100644 index 0000000..9791422 --- /dev/null +++ b/connectivity/nfc/libraries/stack/tech/isodep/isodep_target.c @@ -0,0 +1,685 @@ +/* + * Copyright (c) 2015-2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + */ +/** + * \file isodep_target.c + * \copyright Copyright (c) ARM Ltd 2015 + * \author Donatien Garnier + */ + +#define __DEBUG__ 0 +#ifndef __MODULE__ +#define __MODULE__ "isodep_target.c" +#endif + +#include "isodep_target.h" + +#include "stack/nfc_errors.h" +#include "transceiver/transceiver.h" + +//Private defines +#define RATS 0xE0 +#define FSDI_TO_FSD(x) (((x)<5)?(((x)<<3) + 16):((x)<8)?(((x)<<5)-96):256) +#define FSC_TO_FSCI(x) (((x)<=48)?(((x)-16)>>3):((x)<=128)?(((x)+96)>>5):8) //returns the closest lower or equal value +#define DID(x) ((x) & 0x0F) +#define FSDI(x) (((x) >> 4) & 0x0F) + +#define FSCI_TO_FSC(x) FSDI_TO_FSD(x) +#define FSD_TO_FSDI(x) FSC_TO_FSCI(x) + +//#define DI_TO_D(x) (1 << (x)) +#define DI_TO_BITRATE(x) ((RF_BITRATE)((x) + RF_BITRATE_106K)) + + +#define GET_FRAME_TYPE(pcb) ((((pcb) & 0xF0) == 0xD0)?PPS_FRAME:(((pcb) & 0xC0) == (0x00 << 6))?I_FRAME:((((pcb) & 0xC0) == (0x2 << 6))?R_FRAME:S_FRAME)) + +#define I_BLOCK_PCB 0 +#define R_BLOCK_PCB 2 +#define S_BLOCK_PCB 3 + +#define PCB_TYPE(pcb) (((pcb)>>6)&0x03) + +#define BUILD_I_BLOCK_PCB(chaining, cid, nad, block_toggle) ( (0x0 << 6) | (((chaining)?1:0) << 4) \ + | (((cid)?1:0) << 3) | (((nad)?1:0) << 2) | (1 << 1) | (((block_toggle)?1:0)) ) +#define BUILD_S_BLOCK_PCB(cid, wtx_n_deselect) ( (0x3 << 6) | (((wtx_n_deselect)?0x3:0) << 4) \ + | (((cid)?1:0) << 3) | (1 << 1) ) +#define BUILD_R_BLOCK_PCB(cid, block_toggle, nak) ( (0x2 << 6) | (1 <<5) | (((nak)?1:0) << 4) \ + | (((cid)?1:0) << 3) | (1 << 1) | (((block_toggle)?1:0)) ) + +#define PCB_IS_CID(pcb) (((pcb) & (1 << 3))?true:false) +#define PCB_BLOCK_TOGGLE(pcb) (((pcb) & 1)?true:false) +#define PCB_CHAINING(pcb) (((pcb) & 0x10)?true:false) +#define PCB_NACK(pcb) (((pcb) & 0x10)?true:false) +#define PCB_WTX(pcb) (((pcb)&0x30)==0x30) + +#define WTXM_DEFAULT 10 + +//Parameters +#define FSC 256 //Maximum frame size the PICC (us) can receive -- TODO should be a parameter at some point -- linked to PN512 buffer +#define SFGI 2 //Guard time ~ 1.2ms +//#define FWI 6 //Max time before answer is ~ 19.3ms +#define FWI 14 //Max time before answer is ~ 19.3ms + +typedef enum __dep_type dep_type_t; +enum __dep_type { + dep_type_information, + dep_type_response, + dep_type_supervisory, +}; + +//Local functions +static void dep_init(nfc_tech_isodep_target_t *pIsodepTarget); +static bool dep_ready(nfc_tech_isodep_target_t *pIsodepTarget); + +static void dep_req_information(nfc_tech_isodep_target_t *pIsodepTarget, ac_buffer_t *pReq, bool moreInformation, uint8_t blockNumber); +static void dep_req_response(nfc_tech_isodep_target_t *pIsodepTarget, bool ack, uint8_t blockNumber); +static void dep_req_supervisory(nfc_tech_isodep_target_t *pIsodepTarget, bool wtxNDeselect, uint8_t wtxm); + +static dep_type_t dep_res_type(nfc_tech_isodep_target_t *pIsodepTarget); +static void dep_res_information(nfc_tech_isodep_target_t *pIsodepTarget, size_t maxLength, ac_buffer_t **ppRes, bool *pMoreInformation, uint8_t *pBlockNumber); +static void dep_res_response(nfc_tech_isodep_target_t *pIsodepTarget, bool *pAck, uint8_t *pBlockNumber); +static void dep_res_supervisory(nfc_tech_isodep_target_t *pIsodepTarget, bool *pWtxNDeselect, uint8_t *pWtxm); + +static void dep_disconnected(nfc_tech_isodep_target_t *pIsodepTarget, bool deselected); + +static void command_init(nfc_tech_isodep_target_t *pIsodepTarget); + +static nfc_err_t command_ats_req(nfc_tech_isodep_target_t *pIsodepTarget); +static nfc_err_t command_dep_req(nfc_tech_isodep_target_t *pIsodepTarget); + +static nfc_err_t command_ats_res(nfc_tech_isodep_target_t *pIsodepTarget); +static nfc_err_t command_dep_res(nfc_tech_isodep_target_t *pIsodepTarget); + +static void command_reply(nfc_tech_isodep_target_t *pIsodepTarget, bool depWait); +static void command_transceiver_cb(nfc_transceiver_t *pTransceiver, nfc_err_t ret, void *pUserData); + +//High-level Target functions +void nfc_tech_isodep_target_init(nfc_tech_isodep_target_t *pIsodepTarget, nfc_transceiver_t *pTransceiver, + ac_buffer_t *pHist, nfc_tech_isodep_disconnected_cb disconnectedCb, void *pUserData) +{ + pIsodepTarget->pTransceiver = pTransceiver; + + pIsodepTarget->pHist = pHist; + + pIsodepTarget->disconnectedCb = disconnectedCb; + pIsodepTarget->pUserData = pUserData; + + dep_init(pIsodepTarget); + command_init(pIsodepTarget); +} + +nfc_err_t nfc_tech_isodep_target_connect(nfc_tech_isodep_target_t *pIsodepTarget) +{ + NFC_DBG("Connecting"); + pIsodepTarget->commands.state = ISO_DEP_TARGET_COMMANDS_CONNECTING; + + transceiver_set_crc(pIsodepTarget->pTransceiver, true, true); + command_transceiver_cb(pIsodepTarget->pTransceiver, NFC_OK, pIsodepTarget); + + return NFC_OK; +} + +void nfc_tech_isodep_target_disconnect(nfc_tech_isodep_target_t *pIsodepTarget) +{ + // This should not be called within a callback + + transceiver_abort(pIsodepTarget->pTransceiver); + + dep_disconnected(pIsodepTarget, false); +} + +nfc_err_t nfc_tech_isodep_target_transmit(nfc_tech_isodep_target_t *pIsodepTarget, ac_istream_t *pStream, nfc_tech_isodep_cb_t cb, void *pUserData) +{ + if (pIsodepTarget->dep.pReqStream != NULL) { + return NFC_ERR_BUSY; + } + + pIsodepTarget->dep.pResStream = pStream; + pIsodepTarget->dep.resCb = cb; + pIsodepTarget->dep.pResUserData = pUserData; + + //Do we need to start transceiving? + if (pIsodepTarget->commands.state == ISO_DEP_TARGET_COMMANDS_DEP_REQ_RECVD) { + command_reply(pIsodepTarget, false); //Force reply + } + + return NFC_OK; +} + +nfc_err_t nfc_tech_isodep_target_receive(nfc_tech_isodep_target_t *pIsodepTarget, ac_ostream_t *pStream, nfc_tech_isodep_cb_t cb, void *pUserData) +{ + if (pIsodepTarget->dep.pResStream != NULL) { + return NFC_ERR_BUSY; + } + + pIsodepTarget->dep.pReqStream = pStream; + pIsodepTarget->dep.reqCb = cb; + pIsodepTarget->dep.pReqUserData = pUserData; + + return NFC_OK; +} + +//DEP Layer +void dep_init(nfc_tech_isodep_target_t *pIsodepTarget) +{ + //ac_buffer_init(&pIsodepTarget->dep.res, NULL, 0); + pIsodepTarget->dep.pReqStream = NULL; + pIsodepTarget->dep.pResStream = NULL; + + pIsodepTarget->dep.reqCb = NULL; + pIsodepTarget->dep.pReqUserData = NULL; + + pIsodepTarget->dep.resCb = NULL; + pIsodepTarget->dep.pResUserData = NULL; + + pIsodepTarget->dep.blockNumber = 1; //Rule C + + //pIsodepTarget->dep.pduState = ISO_DEP_TARGET_DEP_PDU_IDLE; + pIsodepTarget->dep.chaining = false; + pIsodepTarget->dep.frameState = ISO_DEP_TARGET_DEP_FRAME_IDLE; +} + +bool dep_ready(nfc_tech_isodep_target_t *pIsodepTarget) +{ + //Anything to send back? + if (pIsodepTarget->dep.frameState != ISO_DEP_TARGET_DEP_FRAME_INFORMATION_RECEIVED) { + return true; + } + + if ((pIsodepTarget->dep.pResStream != NULL)) { + return true; + } else { + return false; + } +} + +void dep_req_information(nfc_tech_isodep_target_t *pIsodepTarget, ac_buffer_t *pReq, bool moreInformation, uint8_t blockNumber) +{ + (void) blockNumber; + + pIsodepTarget->dep.blockNumber++; + pIsodepTarget->dep.blockNumber %= 2; + + // Note: callbacks can call nfc_tech_isodep_target_transmit() - however we must make sure that we wait AFTER this routine has been processed to actually transmit + // To do so, reset state to ATS_RES_SENT state + pIsodepTarget->commands.state = ISO_DEP_TARGET_COMMANDS_ATS_RES_SENT; + + if (!pIsodepTarget->dep.chaining + && (pIsodepTarget->dep.pResStream != NULL)) { + //Sent the full frame + pIsodepTarget->dep.pResStream = NULL; + pIsodepTarget->dep.resCb((nfc_tech_isodep_t *)pIsodepTarget, NFC_OK, pIsodepTarget->dep.pResUserData); + } + if (pIsodepTarget->dep.pReqStream != NULL) { + // Pull more + ac_ostream_push(pIsodepTarget->dep.pReqStream, pReq, !moreInformation); + if (!moreInformation) { + //Got the full frame + pIsodepTarget->dep.pReqStream = NULL; + pIsodepTarget->dep.reqCb((nfc_tech_isodep_t *)pIsodepTarget, NFC_OK, pIsodepTarget->dep.pReqUserData); + } + } + + // Update state + pIsodepTarget->dep.frameState = ISO_DEP_TARGET_DEP_FRAME_INFORMATION_RECEIVED; + pIsodepTarget->dep.chaining = moreInformation; +} + +void dep_req_response(nfc_tech_isodep_target_t *pIsodepTarget, bool ack, uint8_t blockNumber) +{ + if (blockNumber != pIsodepTarget->dep.blockNumber) { + //Should be NACK + pIsodepTarget->dep.frameState = ISO_DEP_TARGET_DEP_FRAME_NACK_DIFF_BLOCK_NUMBER_RECEIVED; + } else { + if (ack) { + pIsodepTarget->dep.frameState = ISO_DEP_TARGET_DEP_FRAME_ACK_RECEIVED; + } else { + pIsodepTarget->dep.frameState = ISO_DEP_TARGET_DEP_FRAME_NACK_RECEIVED; + } + } +} + +void dep_req_supervisory(nfc_tech_isodep_target_t *pIsodepTarget, bool wtxNDeselect, uint8_t wtxm) +{ + (void) wtxm; + + if (wtxNDeselect) { + if ((pIsodepTarget->dep.frameState != ISO_DEP_TARGET_DEP_FRAME_WTX_SENT)) { + NFC_WARN("Unexpected WTX frame"); + } + pIsodepTarget->dep.frameState = ISO_DEP_TARGET_DEP_FRAME_WTX_RECEIVED; + } else { + pIsodepTarget->dep.frameState = ISO_DEP_TARGET_DEP_FRAME_DESELECT_RECEIVED; + } +} + +dep_type_t dep_res_type(nfc_tech_isodep_target_t *pIsodepTarget) +{ + dep_type_t depType; + switch (pIsodepTarget->dep.frameState) { + case ISO_DEP_TARGET_DEP_FRAME_DESELECT_RECEIVED: + depType = dep_type_supervisory; //Deselect + break; + case ISO_DEP_TARGET_DEP_FRAME_INFORMATION_RECEIVED: + case ISO_DEP_TARGET_DEP_FRAME_WTX_RECEIVED: + if (pIsodepTarget->dep.chaining) { //Need to ack? + depType = dep_type_response; + } else if (pIsodepTarget->dep.pResStream != NULL) { //Anything to send back? + depType = dep_type_information; + } else { + depType = dep_type_supervisory; //WTX + } + break; + case ISO_DEP_TARGET_DEP_FRAME_ACK_RECEIVED: + if ((pIsodepTarget->dep.pResStream != NULL) && (pIsodepTarget->dep.chaining)) { + depType = dep_type_information; + } else { + depType = dep_type_supervisory; //WTX + } + break; + case ISO_DEP_TARGET_DEP_FRAME_NACK_DIFF_BLOCK_NUMBER_RECEIVED: + depType = dep_type_response; //Should send ACK + break; + case ISO_DEP_TARGET_DEP_FRAME_NACK_RECEIVED: + depType = dep_type_information; + break; + default: + depType = dep_type_supervisory; //ATN + break; + } + return depType; +} + +void dep_res_information(nfc_tech_isodep_target_t *pIsodepTarget, size_t maxLength, ac_buffer_t **ppRes, bool *pMoreInformation, uint8_t *pBlockNumber) +{ + *pBlockNumber = pIsodepTarget->dep.blockNumber; + if (pIsodepTarget->dep.frameState != ISO_DEP_TARGET_DEP_FRAME_NACK_RECEIVED) { + if (pIsodepTarget->dep.pResStream != NULL) { + bool lastFrame = true; + ac_istream_pull(pIsodepTarget->dep.pResStream, &pIsodepTarget->dep.res, &lastFrame, maxLength); + pIsodepTarget->dep.chaining = !lastFrame; + } + } else { + //Retransmit previous frame (leave it as it is) + } + *ppRes = &pIsodepTarget->dep.res; + *pMoreInformation = pIsodepTarget->dep.chaining; + pIsodepTarget->dep.frameState = ISO_DEP_TARGET_DEP_FRAME_INFORMATION_SENT; +} + +void dep_res_response(nfc_tech_isodep_target_t *pIsodepTarget, bool *pAck, uint8_t *pBlockNumber) +{ + //Continue chaining or send ACK + *pAck = true; + *pBlockNumber = pIsodepTarget->dep.blockNumber; + pIsodepTarget->dep.frameState = ISO_DEP_TARGET_DEP_FRAME_ACK_SENT; +} + +void dep_res_supervisory(nfc_tech_isodep_target_t *pIsodepTarget, bool *pWtxNDeselect, uint8_t *pWtxm) +{ + if (pIsodepTarget->dep.frameState == ISO_DEP_TARGET_DEP_FRAME_DESELECT_RECEIVED) { + *pWtxNDeselect = false; + pIsodepTarget->dep.frameState = ISO_DEP_TARGET_DEP_FRAME_DESELECT_SENT; + } else { + *pWtxNDeselect = true; + *pWtxm = WTXM_DEFAULT; + pIsodepTarget->dep.frameState = ISO_DEP_TARGET_DEP_FRAME_WTX_SENT; + } +} + +void dep_disconnected(nfc_tech_isodep_target_t *pIsodepTarget, bool deselected) +{ + //Call callbacks if needed + if (pIsodepTarget->dep.pReqStream != NULL) { + pIsodepTarget->dep.reqCb((nfc_tech_isodep_t *)pIsodepTarget, NFC_ERR_DISCONNECTED, pIsodepTarget->dep.pReqUserData); + pIsodepTarget->dep.pReqStream = NULL; + } + if (pIsodepTarget->dep.pReqStream != NULL) { + pIsodepTarget->dep.resCb((nfc_tech_isodep_t *)pIsodepTarget, NFC_ERR_DISCONNECTED, pIsodepTarget->dep.pResUserData); + pIsodepTarget->dep.pResStream = NULL; + } + if (pIsodepTarget->commands.state != ISO_DEP_TARGET_COMMANDS_DISCONNECTED) { + pIsodepTarget->commands.state = ISO_DEP_TARGET_COMMANDS_DISCONNECTED; + pIsodepTarget->disconnectedCb((nfc_tech_isodep_t *)pIsodepTarget, deselected, pIsodepTarget->pUserData); + } +} + +//Commands Layer +void command_init(nfc_tech_isodep_target_t *pIsodepTarget) +{ + ac_buffer_builder_init(&pIsodepTarget->commands.respBldr, pIsodepTarget->commands.respBuf, sizeof(pIsodepTarget->commands.respBuf)); + pIsodepTarget->commands.pReq = NULL; + // Update if/when we support DIDs + //pIsodepTarget->commands.did = 0; + //pIsodepTarget->commands.didUsed = false; + pIsodepTarget->commands.state = ISO_DEP_TARGET_COMMANDS_DISCONNECTED; + pIsodepTarget->commands.inPayloadSize = 0; +} + +nfc_err_t command_ats_req(nfc_tech_isodep_target_t *pIsodepTarget) +{ + //Check we are in a correct state -- this should be the first command received + if (pIsodepTarget->commands.state != ISO_DEP_TARGET_COMMANDS_CONNECTING) { + return NFC_ERR_PROTOCOL; + } + + if (ac_buffer_reader_readable(pIsodepTarget->commands.pReq) < 2) { + NFC_ERR("Payload too short"); + return NFC_ERR_PROTOCOL; + } + + ac_buffer_read_n_skip(pIsodepTarget->commands.pReq, 1); + + uint8_t b = ac_buffer_read_nu8(pIsodepTarget->commands.pReq); + + //Save DID -- not supported for now + //pIsodepTarget->commands.did = DID(b); + + uint8_t fsdi = FSDI(b); + pIsodepTarget->commands.inPayloadSize = FSDI_TO_FSD(fsdi); + + pIsodepTarget->commands.state = ISO_DEP_TARGET_COMMANDS_ATS_REQ_RECVD; + + return NFC_OK; +} + +nfc_err_t command_dep_req(nfc_tech_isodep_target_t *pIsodepTarget) +{ + if (pIsodepTarget->commands.state < ISO_DEP_TARGET_COMMANDS_ATS_RES_SENT) { + return NFC_ERR_PROTOCOL; + } + + if (ac_buffer_reader_readable(pIsodepTarget->commands.pReq) < 1) { + NFC_ERR("Payload too short"); + return NFC_ERR_PROTOCOL; + } + + uint8_t pcb = ac_buffer_read_nu8(pIsodepTarget->commands.pReq); + + // Udpate if/when we support DIDs + /* + if( pfb & PFB_DID ) + { + uint8_t did = ac_buffer_read_nu8(pIsodepTarget->commands.pReq); + if( pIsodepTarget->commands.did != did ) + { + //Not for us + return NFC_ERR_PROTOCOL; + } + pIsodepTarget->commands.didUsed = true; + } + else + { + pIsodepTarget->commands.didUsed = false; + } + + if( pfb & PFB_NAD ) + { + ac_buffer_read_nu8(pIsodepTarget->commands.pReq); //Skip NAD + } + */ + + uint8_t wtxm = 0; + switch (PCB_TYPE(pcb)) { + case I_BLOCK_PCB: + dep_req_information(pIsodepTarget, pIsodepTarget->commands.pReq, PCB_CHAINING(pcb), PCB_BLOCK_TOGGLE(pcb)); + break; + case R_BLOCK_PCB: + dep_req_response(pIsodepTarget, !PCB_NACK(pcb), PCB_BLOCK_TOGGLE(pcb)); + break; + case S_BLOCK_PCB: + if (PCB_WTX(pcb)) { + if (ac_buffer_reader_readable(pIsodepTarget->commands.pReq) < 1) { + NFC_ERR("Payload too short"); + return NFC_ERR_PROTOCOL; + } + wtxm = ac_buffer_read_nu8(pIsodepTarget->commands.pReq); + } + dep_req_supervisory(pIsodepTarget, PCB_WTX(pcb), wtxm); + break; + default: + NFC_ERR("PCB is invalid"); + return NFC_ERR_PROTOCOL; + } + + pIsodepTarget->commands.state = ISO_DEP_TARGET_COMMANDS_DEP_REQ_RECVD; + + return NFC_OK; +} + +nfc_err_t command_ats_res(nfc_tech_isodep_target_t *pIsodepTarget) +{ + //Send ATS back + if (ac_buffer_builder_writable(&pIsodepTarget->commands.respBldr) < 5) { + return NFC_ERR_BUFFER_TOO_SMALL; + } + + ac_buffer_builder_write_nu8(&pIsodepTarget->commands.respBldr, (5 + ac_buffer_size(pIsodepTarget->pHist)) & 0xFF); + + //T0 + ac_buffer_builder_write_nu8(&pIsodepTarget->commands.respBldr, (0x7 << 4) | FSC_TO_FSCI(FSC)); //TA(1), TB(1) and TC(1) are transmitted + + //TA(1) + //For now only 106kbps supported + ac_buffer_builder_write_nu8(&pIsodepTarget->commands.respBldr, (1 << 7) | (0x0 << 4) | 0x0); + + //TODO when supporting other bitrates + //ac_buffer_builder_write_nu8(&pIsodepTarget->commands.respBldr, (0 << 7) | (0x3 << 4) | 0x3); //106, 212, 414 kbps bitrates + + //TB(1) + ac_buffer_builder_write_nu8(&pIsodepTarget->commands.respBldr, (FWI << 4) | SFGI); //Specify guard-time and time between frames + + //TC(1) + ac_buffer_builder_write_nu8(&pIsodepTarget->commands.respBldr, (0 << 1) | 0); //DID not supported, NAD not supported + + ac_buffer_set_next(ac_buffer_builder_buffer(&pIsodepTarget->commands.respBldr), pIsodepTarget->pHist); //Queue general bytes + + pIsodepTarget->commands.state = ISO_DEP_TARGET_COMMANDS_ATS_RES_SENT; + + //TODO PPS + + return NFC_OK; +} + +nfc_err_t command_dep_res(nfc_tech_isodep_target_t *pIsodepTarget) +{ + uint8_t pcb = 0; + + // If/when supporting DIDs + /* + if( pIsodepTarget->commands.didUsed ) + { + pcb |= PFB_DID; + }*/ + + ac_buffer_t *pDepBuf = NULL; + bool moreInformation = false; + bool ack = false; + bool wtxNDeselect = false; + uint8_t wtxm = 0; + uint8_t blockNumber = 0; + + size_t maxLength = pIsodepTarget->commands.inPayloadSize - 1; + + switch (dep_res_type(pIsodepTarget)) { + case dep_type_information: + dep_res_information(pIsodepTarget, maxLength, &pDepBuf, &moreInformation, &blockNumber); + pcb = BUILD_I_BLOCK_PCB(moreInformation, false, false, blockNumber); + break; + case dep_type_response: + dep_res_response(pIsodepTarget, &ack, &blockNumber); + pcb = BUILD_R_BLOCK_PCB(0, blockNumber, !ack); + break; + case dep_type_supervisory: + dep_res_supervisory(pIsodepTarget, &wtxNDeselect, &wtxm); + pcb = BUILD_S_BLOCK_PCB(0, wtxNDeselect); + break; + } + + ac_buffer_builder_write_nu8(&pIsodepTarget->commands.respBldr, pcb); + /* + if( pIsodepTarget->commands.didUsed ) + { + ac_buffer_builder_write_nu8(&pIsodepTarget->commands.respBldr, pIsodepTarget->commands.did); + } + */ + if (pDepBuf != NULL) { + ac_buffer_set_next(ac_buffer_builder_buffer(&pIsodepTarget->commands.respBldr), pDepBuf); + } else if (wtxNDeselect) { + ac_buffer_builder_write_nu8(&pIsodepTarget->commands.respBldr, wtxm); + } + + pIsodepTarget->commands.state = ISO_DEP_TARGET_COMMANDS_DEP_RES_SENT; + + return NFC_OK; +} + +void command_reply(nfc_tech_isodep_target_t *pIsodepTarget, bool depWait) +{ + nfc_err_t ret; + + //Check whether we want to reply or wait for the higher layer to send us something + if ((pIsodepTarget->commands.state == ISO_DEP_TARGET_COMMANDS_DEP_REQ_RECVD) && depWait && !dep_ready(pIsodepTarget)) { + return; + } + + //Reply + ac_buffer_builder_reset(&pIsodepTarget->commands.respBldr); + + switch (pIsodepTarget->commands.state) { + case ISO_DEP_TARGET_COMMANDS_ATS_REQ_RECVD: + ret = command_ats_res(pIsodepTarget); + break; + case ISO_DEP_TARGET_COMMANDS_DEP_REQ_RECVD: + ret = command_dep_res(pIsodepTarget); + break; + default: + NFC_ERR("Unknown state %d", pIsodepTarget->commands.state); + //Go back to receive mode + nfc_transceiver_transceive(pIsodepTarget->pTransceiver, command_transceiver_cb, pIsodepTarget); + return; + } + + if (ret) { + NFC_ERR("Error %d", ret); + //Go back to receive mode + nfc_transceiver_transceive(pIsodepTarget->pTransceiver, command_transceiver_cb, pIsodepTarget); + return; + } + + NFC_DBG("Transceive"); + + if (pIsodepTarget->dep.frameState == ISO_DEP_TARGET_DEP_FRAME_DESELECT_SENT) { + transceiver_set_transceive_options(pIsodepTarget->pTransceiver, true, false, true); + } else { + transceiver_set_transceive_options(pIsodepTarget->pTransceiver, true, true, false); + } + + NFC_DBG_BLOCK(ac_buffer_dump(ac_buffer_builder_buffer(&pIsodepTarget->commands.respBldr));) + + //Send next frame + transceiver_set_write(pIsodepTarget->pTransceiver, ac_buffer_builder_buffer(&pIsodepTarget->commands.respBldr)); + nfc_transceiver_transceive(pIsodepTarget->pTransceiver, command_transceiver_cb, pIsodepTarget); + + NFC_DBG("Processed"); +} + +void command_transceiver_cb(nfc_transceiver_t *pTransceiver, nfc_err_t ret, void *pUserData) +{ + nfc_tech_isodep_target_t *pIsodepTarget = (nfc_tech_isodep_target_t *) pUserData; + + if (ret == NFC_ERR_ABORTED) { + // Just return + return; + } + + if (pIsodepTarget->dep.frameState == ISO_DEP_TARGET_DEP_FRAME_DESELECT_SENT) { + NFC_DBG("Deselect sent and re-polled: %u", ret); + //We are now disconnected (deselected) + //Reset status + dep_init(pIsodepTarget); + command_init(pIsodepTarget); + + transceiver_set_crc(pIsodepTarget->pTransceiver, true, true); + pIsodepTarget->commands.state = ISO_DEP_TARGET_COMMANDS_CONNECTING; + + //Call so that we can reinit higher layer + dep_disconnected(pIsodepTarget, true); //This will call us again + return; + } + + //Prepare default empty reply + transceiver_set_write(pTransceiver, NULL); + transceiver_set_transceive_options(pTransceiver, false, true, false); + + if (ret == NFC_ERR_FIELD) { + NFC_WARN("Lost initiator"); + dep_disconnected(pIsodepTarget, false); + return; + } else if (ret) { + //We should ignore this error and wait for another frame + NFC_WARN("Got invalid frame (error %d)", ret); + + nfc_transceiver_transceive(pTransceiver, command_transceiver_cb, pIsodepTarget); + return; + } + + NFC_DBG("Reading data from initiator"); + ac_buffer_t *pDataInitiator = transceiver_get_read(pTransceiver); //In buffer + + NFC_DBG_BLOCK(ac_buffer_dump(pDataInitiator);) + + //Framing is handled by transceiver + if ((ac_buffer_reader_readable(pDataInitiator) < 1)) { + NFC_ERR("Empty initiator message"); + + //Go back to receive mode + nfc_transceiver_transceive(pTransceiver, command_transceiver_cb, pIsodepTarget); + return; + } + + pIsodepTarget->commands.pReq = pDataInitiator; + + //Duplicate to peek on req + ac_buffer_t dataInitiatorDup; + ac_buffer_dup(&dataInitiatorDup, pDataInitiator); + uint8_t req = ac_buffer_read_nu8(&dataInitiatorDup); + + switch (req) { + case RATS: + ret = command_ats_req(pIsodepTarget); + break; + default: + ret = command_dep_req(pIsodepTarget); + break; + } + + if (ret) { + NFC_ERR("Error %d", ret); + + //Go back to receive mode + nfc_transceiver_transceive(pTransceiver, command_transceiver_cb, pIsodepTarget); + return; + } + + NFC_DBG("Reply"); + + //Reply + command_reply(pIsodepTarget, true); //Make sure we send a WTX frame if we cannot respond straight away +} + + + diff --git a/connectivity/nfc/libraries/stack/tech/isodep/isodep_target.h b/connectivity/nfc/libraries/stack/tech/isodep/isodep_target.h new file mode 100644 index 0000000..a4e6d5c --- /dev/null +++ b/connectivity/nfc/libraries/stack/tech/isodep/isodep_target.h @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2015-2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + */ +/** + * \file isodep_target.h + * \copyright Copyright (c) ARM Ltd 2015 + * \author Donatien Garnier + */ + +#ifndef ISODEP_TARGET_H_ +#define ISODEP_TARGET_H_ + +#include "stack/nfc_common.h" +#include "transceiver/transceiver.h" +#include "isodep.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct nfc_tech_isodep_target; +typedef struct nfc_tech_isodep_target nfc_tech_isodep_target_t; +struct nfc_tech_isodep_target { + nfc_transceiver_t *pTransceiver; + + struct { + ac_ostream_t *pReqStream; + ac_istream_t *pResStream; + + nfc_tech_isodep_cb_t reqCb; + void *pReqUserData; + + nfc_tech_isodep_cb_t resCb; + void *pResUserData; + + ac_buffer_t res; + bool chaining; + + uint8_t blockNumber; + + enum { + ISO_DEP_TARGET_DEP_FRAME_IDLE, + ISO_DEP_TARGET_DEP_FRAME_WTX_RECEIVED, + ISO_DEP_TARGET_DEP_FRAME_WTX_SENT, + ISO_DEP_TARGET_DEP_FRAME_INFORMATION_RECEIVED, + ISO_DEP_TARGET_DEP_FRAME_INFORMATION_SENT, + ISO_DEP_TARGET_DEP_FRAME_NACK_RECEIVED, + ISO_DEP_TARGET_DEP_FRAME_NACK_DIFF_BLOCK_NUMBER_RECEIVED, + ISO_DEP_TARGET_DEP_FRAME_NACK_SENT, + ISO_DEP_TARGET_DEP_FRAME_ACK_RECEIVED, + ISO_DEP_TARGET_DEP_FRAME_ACK_SENT, + ISO_DEP_TARGET_DEP_FRAME_DESELECT_RECEIVED, + ISO_DEP_TARGET_DEP_FRAME_DESELECT_SENT, + } frameState; + } dep; + struct { + enum { + ISO_DEP_TARGET_COMMANDS_DISCONNECTED, + + ISO_DEP_TARGET_COMMANDS_CONNECTING, + + ISO_DEP_TARGET_COMMANDS_ATS_REQ_RECVD, + ISO_DEP_TARGET_COMMANDS_ATS_RES_SENT, + + ISO_DEP_TARGET_COMMANDS_DEP_REQ_RECVD, + ISO_DEP_TARGET_COMMANDS_DEP_RES_SENT, + } state; + + size_t inPayloadSize; + + ac_buffer_builder_t respBldr; + uint8_t respBuf[32]; + + ac_buffer_t *pReq; + } commands; + + ac_buffer_t *pHist; + + nfc_tech_isodep_disconnected_cb disconnectedCb; + void *pUserData; +}; + +//High-level Target functions +void nfc_tech_isodep_target_init(nfc_tech_isodep_target_t *pIsodepTarget, nfc_transceiver_t *pTransceiver, + ac_buffer_t *pHist, nfc_tech_isodep_disconnected_cb disconnectedCb, void *pUserData); + +nfc_err_t nfc_tech_isodep_target_connect(nfc_tech_isodep_target_t *pIsodepTarget); +void nfc_tech_isodep_target_disconnect(nfc_tech_isodep_target_t *pIsodepTarget); + +nfc_err_t nfc_tech_isodep_target_transmit(nfc_tech_isodep_target_t *pIsodepTarget, ac_istream_t *pStream, nfc_tech_isodep_cb_t cb, void *pUserData); +nfc_err_t nfc_tech_isodep_target_receive(nfc_tech_isodep_target_t *pIsodepTarget, ac_ostream_t *pStream, nfc_tech_isodep_cb_t cb, void *pUserData); + + +#ifdef __cplusplus +} +#endif + +#endif /* ISODEP_TARGET_H_ */ diff --git a/connectivity/nfc/libraries/stack/tech/type4/type4_target.c b/connectivity/nfc/libraries/stack/tech/type4/type4_target.c new file mode 100644 index 0000000..63fd23e --- /dev/null +++ b/connectivity/nfc/libraries/stack/tech/type4/type4_target.c @@ -0,0 +1,286 @@ +/* + * Copyright (c) 2015-2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + */ +/** + * \file type4_target.c + * \copyright Copyright (c) ARM Ltd 2015 + * \author Donatien Garnier + */ + +#define __DEBUG__ 0 +#ifndef __MODULE__ +#define __MODULE__ "type4_target.c" +#endif + +#include "stack/nfc_errors.h" + +#include "type4_target.h" +#include "tech/iso7816/iso7816_defs.h" + +#define TYPE4_NDEF_VERSION 2 + +#if TYPE4_NDEF_VERSION == 2 +static const uint8_t aid[] = { 0xD2, 0x76, 0x00, 0x00, 0x85, 0x01, 0x01 }; +#else +static const uint8_t aid[] = { 0xD2, 0x76, 0x00, 0x00, 0x85, 0x01, 0x00 }; +#endif +#define CC_FILE 0xE103 //Must not be changed +#define NDEF_FILE 0xA443 +#define DEFAULT_FILE 0x0000 + +static void app_selected(nfc_tech_iso7816_app_t *pIso7816App, void *pUserData); +static void app_deselected(nfc_tech_iso7816_app_t *pIso7816App, void *pUserData); +static void app_apdu(nfc_tech_iso7816_app_t *pIso7816App, void *pUserData); + +static nfc_err_t data_read(nfc_tech_type4_target_t *pType4Target, ac_buffer_t *pBuf, uint16_t file, size_t off, size_t len); +static nfc_err_t data_write(nfc_tech_type4_target_t *pType4Target, ac_buffer_t *pBuf, uint16_t file, size_t off); + +void nfc_tech_type4_target_init(nfc_tech_type4_target_t *pType4Target, nfc_tech_iso7816_t *pIso7816, ndef_msg_t *pNdef) +{ + ac_buffer_builder_init(&pType4Target->ccFileBldr, pType4Target->ccFileBuf, /*sizeof(pType4Target->ccFileBuf)*/15); + + ac_buffer_builder_init(&pType4Target->ndefFileBldr, pType4Target->ndefFileBuf, /*sizeof(pType4Target->ndefFileBuf)*/2); + + pType4Target->selFile = DEFAULT_FILE; + pType4Target->pNdef = pNdef; + pType4Target->written = false; + + nfc_tech_iso7816_app_init(&pType4Target->app, pIso7816, aid, sizeof(aid), app_selected, app_deselected, app_apdu, pType4Target); + + nfc_tech_iso7816_add_app(pIso7816, &pType4Target->app); +} + +void app_selected(nfc_tech_iso7816_app_t *pIso7816App, void *pUserData) +{ + nfc_tech_type4_target_t *pType4Target = (nfc_tech_type4_target_t *) pUserData; + NFC_DBG("Selected"); + + (void) pIso7816App; + + ac_buffer_builder_reset(ndef_msg_buffer_builder(pType4Target->pNdef)); + + //Populate CC file + ac_buffer_builder_reset(&pType4Target->ccFileBldr); + ac_buffer_builder_write_nu16(&pType4Target->ccFileBldr, 15); //CC file is 15 bytes long +#if TYPE4_NDEF_VERSION == 2 + ac_buffer_builder_write_nu8(&pType4Target->ccFileBldr, 0x20); //NFC Forum Tag Type 4 V2.0 compliant +#else + ac_buffer_builder_write_nu8(&pType4Target->ccFileBldr, 0x10); //NFC Forum Tag Type 4 V1.0 compliant +#endif + ac_buffer_builder_write_nu16(&pType4Target->ccFileBldr, 256 /* Max frame size */ - 2 /* SW */ - 3 /* ISO-DEP PFB + DID + NAD */); //Max data size that can be read from the tag + ac_buffer_builder_write_nu16(&pType4Target->ccFileBldr, 256 /* Max frame size */ - 6 /* CLA INS P1 P2 LC LE */ - 3 /* ISO-DEP PFB + DID + NAD */); //Max data size that can be written to the tag + ac_buffer_builder_write_nu8(&pType4Target->ccFileBldr, 0x04); //NDEF File Control TLV - Type + ac_buffer_builder_write_nu8(&pType4Target->ccFileBldr, 6); //NDEF File Control TLV - Length + ac_buffer_builder_write_nu16(&pType4Target->ccFileBldr, NDEF_FILE); //NDEF file id + ac_buffer_builder_write_nu16(&pType4Target->ccFileBldr, 2 /* length header */ + ac_buffer_builder_writable(ndef_msg_buffer_builder(pType4Target->pNdef))); //Max size of NDEF data + ac_buffer_builder_write_nu8(&pType4Target->ccFileBldr, 0x00); //Open read access + ac_buffer_builder_write_nu8(&pType4Target->ccFileBldr, 0x00); //Open write access + + //Encode NDEF file + ndef_msg_encode(pType4Target->pNdef); + + //Populate NDEF file + ac_buffer_builder_init(&pType4Target->ndefFileBldr, pType4Target->ndefFileBuf, /*sizeof(pType4Target->ndefFileBuf)*/2); + + ac_buffer_builder_write_nu16(&pType4Target->ndefFileBldr, ac_buffer_reader_readable(ac_buffer_builder_buffer(ndef_msg_buffer_builder(pType4Target->pNdef)))); + + //Pad NDEF file with 0s + while (ac_buffer_builder_writable(ndef_msg_buffer_builder(pType4Target->pNdef)) > 0) { + ac_buffer_builder_write_nu8(ndef_msg_buffer_builder(pType4Target->pNdef), 0); + } + + //No file selected + pType4Target->selFile = DEFAULT_FILE; + + pType4Target->written = false; +} + +void app_deselected(nfc_tech_iso7816_app_t *pIso7816App, void *pUserData) +{ + nfc_tech_type4_target_t *pType4Target = (nfc_tech_type4_target_t *) pUserData; + + (void) pIso7816App; + + //Reset buffers + ac_buffer_builder_reset(&pType4Target->ccFileBldr); + ac_buffer_builder_set_full(&pType4Target->ndefFileBldr); //To read length + ac_buffer_builder_reset(ndef_msg_buffer_builder(pType4Target->pNdef)); + + NFC_DBG("Deselected"); + + if (pType4Target->written) { + NFC_DBG("New content has been written"); + //Try to parse NDEF + //Set buffer length based on file header + size_t length = ac_buffer_read_nu16(ac_buffer_builder_buffer(&pType4Target->ndefFileBldr)); + NFC_DBG("Length is %lu", length); + if (length < ac_buffer_builder_writable(ndef_msg_buffer_builder(pType4Target->pNdef))) { + ac_buffer_builder_set_write_offset(ndef_msg_buffer_builder(pType4Target->pNdef), length); + ndef_msg_decode(pType4Target->pNdef); + } else { + NFC_ERR("Invalid length"); + } + } +} + +void app_apdu(nfc_tech_iso7816_app_t *pIso7816App, void *pUserData) +{ + nfc_tech_type4_target_t *pType4Target = (nfc_tech_type4_target_t *) pUserData; + + //Reset buffers + ac_buffer_builder_set_full(&pType4Target->ccFileBldr); + ac_buffer_builder_set_full(&pType4Target->ndefFileBldr); + ac_buffer_builder_set_full(ndef_msg_buffer_builder(pType4Target->pNdef)); //Set offset to 0, size to max + + ac_buffer_set_next(ac_buffer_builder_buffer(&pType4Target->ndefFileBldr), ac_buffer_builder_buffer(ndef_msg_buffer_builder(pType4Target->pNdef))); + + //Recover PDU + nfc_tech_iso7816_c_apdu_t *pCApdu = nfc_tech_iso7816_app_c_apdu(pIso7816App); + nfc_tech_iso7816_r_apdu_t *pRApdu = nfc_tech_iso7816_app_r_apdu(pIso7816App); + + nfc_err_t ret; + switch (pCApdu->ins) { + case ISO7816_INS_SELECT: + switch (pCApdu->p1) { + case 0x00: //Selection by ID + case 0x02: //Selection by child ID + if (ac_buffer_reader_readable(&pCApdu->dataIn) != 2) { + pRApdu->sw = ISO7816_SW_NOT_FOUND; + break; + } + + uint16_t file = ac_buffer_read_nu16(&pCApdu->dataIn); + if (file == NDEF_FILE) { + pType4Target->selFile = NDEF_FILE; + NFC_DBG("NDEF File selected"); + pRApdu->sw = ISO7816_SW_OK; + } else if (file == CC_FILE) { + pType4Target->selFile = CC_FILE; + NFC_DBG("CC File selected"); + pRApdu->sw = ISO7816_SW_OK; + } else { + //file = DEFAULT_FILE; + NFC_DBG("Could not select file %04X", file); + pRApdu->sw = ISO7816_SW_NOT_FOUND; + } + break; + default: + pRApdu->sw = ISO7816_SW_NOT_FOUND; + break; + } + break; + case 0xB0: //Read binary + NFC_DBG("Trying to read %d bytes at offset %d from file %04x", pCApdu->maxRespLength, (pCApdu->p1 << 8) | pCApdu->p2, pType4Target->selFile); + ret = data_read(pType4Target, &pRApdu->dataOut, pType4Target->selFile, (pCApdu->p1 << 8) | pCApdu->p2, pCApdu->maxRespLength); + if (ret == NFC_OK) { + NFC_DBG("Read %d bytes", ac_buffer_reader_readable(&pRApdu->dataOut)); + NFC_DBG_BLOCK(ac_buffer_dump(&pRApdu->dataOut);) + pRApdu->sw = ISO7816_SW_OK; + } else { + NFC_DBG("Failed with ret code %d", ret); + pRApdu->sw = ISO7816_SW_WRONG_LENGTH; + } + break; + case 0xD6: //Update binary + NFC_DBG("Trying to write %d bytes at offset %d to file %04x", ac_buffer_reader_readable(&pCApdu->dataIn), (pCApdu->p1 << 8) | pCApdu->p2, pType4Target->selFile); + ret = data_write(pType4Target, &pCApdu->dataIn, pType4Target->selFile, (pCApdu->p1 << 8) | pCApdu->p2); + if (ret == NFC_OK) { + NFC_DBG("OK"); + pRApdu->sw = ISO7816_SW_OK; + pType4Target->written = true; + } else { + NFC_DBG("Failed with ret code %d", ret); + pRApdu->sw = ISO7816_SW_WRONG_LENGTH; + } + break; + default: + pRApdu->sw = ISO7816_SW_INVALID_INS; + break; + } + + //Send reply + nfc_tech_iso7816_app_reply(pIso7816App); +} + +nfc_err_t data_read(nfc_tech_type4_target_t *pType4Target, ac_buffer_t *pBuf, uint16_t file, size_t off, size_t len) +{ + ac_buffer_t *pFile; + switch (file) { + case CC_FILE: + pFile = ac_buffer_builder_buffer(&pType4Target->ccFileBldr); + break; + case NDEF_FILE: + pFile = ac_buffer_builder_buffer(&pType4Target->ndefFileBldr); + break; + default: + return NFC_ERR_NOT_FOUND; + } + + if (off > ac_buffer_reader_readable(pFile)) { + return NFC_ERR_LENGTH; + } + + ac_buffer_read_n_skip(pFile, off); + + if (len > ac_buffer_reader_readable(pFile)) { + len = ac_buffer_reader_readable(pFile); + } + + ac_buffer_split(pBuf, pFile, pFile, len); + + return NFC_OK; +} + +nfc_err_t data_write(nfc_tech_type4_target_t *pType4Target, ac_buffer_t *pBuf, uint16_t file, size_t off) +{ + ac_buffer_t *pFile; + switch (file) { + case NDEF_FILE: + pFile = ac_buffer_builder_buffer(&pType4Target->ndefFileBldr); + break; + case CC_FILE: //Cannot write to CC file! + default: + return NFC_ERR_NOT_FOUND; + } + + size_t len = ac_buffer_reader_readable(pBuf); + + if (off > ac_buffer_reader_readable(pFile)) { + return NFC_ERR_LENGTH; + } + + ac_buffer_read_n_skip(pFile, off); + + if (len > ac_buffer_reader_readable(pFile)) { + len = ac_buffer_reader_readable(pFile); + } + + while (len > 0) { + size_t cpy; + ac_buffer_builder_t builder; + ac_buffer_dup(ac_buffer_builder_buffer(&builder), pFile); + ac_buffer_builder_from_buffer(&builder); + cpy = ac_buffer_builder_writable(&builder); + cpy = MIN(cpy, len); + ac_buffer_builder_copy_n_bytes(&builder, pBuf, cpy); + pFile = ac_buffer_next(pFile); + len -= cpy; + } + + return NFC_OK; +} + + diff --git a/connectivity/nfc/libraries/stack/tech/type4/type4_target.h b/connectivity/nfc/libraries/stack/tech/type4/type4_target.h new file mode 100644 index 0000000..a090edd --- /dev/null +++ b/connectivity/nfc/libraries/stack/tech/type4/type4_target.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2015-2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + */ +/** + * \file type4_target.h + * \copyright Copyright (c) ARM Ltd 2015 + * \author Donatien Garnier + */ + +#ifndef TECH_TYPE4_TYPE4_TARGET_H_ +#define TECH_TYPE4_TYPE4_TARGET_H_ + +#include "stack/nfc_common.h" + +#include "tech/iso7816/iso7816.h" +#include "tech/iso7816/iso7816_app.h" +#include "ndef/ndef.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct nfc_tech_type4_target nfc_tech_type4_target_t; + +typedef void (*nfc_tech_type4_cb)(nfc_tech_type4_target_t *pType4Target, nfc_err_t ret, void *pUserData); + +struct nfc_tech_type4_target { + nfc_tech_iso7816_app_t app; + + ndef_msg_t *pNdef; + + uint8_t ccFileBuf[15]; + ac_buffer_builder_t ccFileBldr; + + uint8_t ndefFileBuf[2]; + ac_buffer_builder_t ndefFileBldr; + + uint16_t selFile; + + bool written; +}; + +void nfc_tech_type4_target_init(nfc_tech_type4_target_t *pType4Target, nfc_tech_iso7816_t *pIso7816, ndef_msg_t *pNdef); + +#ifdef __cplusplus +} +#endif + +#endif /* TECH_TYPE4_TYPE4_TARGET_H_ */ diff --git a/connectivity/nfc/libraries/stack/transceiver/protocols.h b/connectivity/nfc/libraries/stack/transceiver/protocols.h new file mode 100644 index 0000000..6b62f6a --- /dev/null +++ b/connectivity/nfc/libraries/stack/transceiver/protocols.h @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2013-2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + */ +/** + * \file protocols.h + * \copyright Copyright (c) ARM Ltd 2013 + * \author Donatien Garnier + * \details List of RF protocols + */ + +/** \addtogroup Transceiver + * @{ + * \name Protocols and RF configuration + * @{ + */ + +#ifndef PROTOCOLS_H_ +#define PROTOCOLS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "stack/nfc_common.h" + +typedef enum __RF_PROTOCOL { + __RF_PROTOCOL_UNKNOWN = 0, + //Reader + RF_PROTOCOL_ISO_14443_A_READER, + RF_PROTOCOL_ISO_14443_B_READER, + RF_PROTOCOL_INNOVATRON_READER, + RF_PROTOCOL_ISO_15693_READER, + RF_PROTOCOL_FELICA_READER, + //... add other protocols here + RF_PROTOCOL_ISO_14443_A_TARGET, + RF_PROTOCOL_ISO_14443_B_TARGET, + RF_PROTOCOL_INNOVATRON_TARGET, + RF_PROTOCOL_ISO_15693_TARGET, + RF_PROTOCOL_FELICA_TARGET, + RF_PROTOCOL_ISO_DEP_TARGET, //ISO 14443-4 transport protocol + RF_PROTOCOL_NFC_DEP_TARGET, //NFC-IP 1 transport protocol + //... add other protocols here + +} RF_PROTOCOL; + +#define RF_PROTOCOL_IS_TARGET(x) ((x)>=RF_PROTOCOL_ISO_14443_A_TARGET) +#define RF_PROTOCOL_IS_READER(x) (!RF_PROTOCOL_IS_TARGET(x)) + +typedef uint32_t RF_OPTION; +//These options can be ORed +#define RF_OPTION_NONE 0x00 +#define RF_OPTION_COMPUTE_CRC 0x01 +#define RF_OPTION_COMPUTE_PARITY 0x02 +#define RF_OPTION_CHECK_CRC 0x04 +#define RF_OPTION_CHECK_PARITY 0x08 +#define RF_OPTION_CLOSE 0x10 //Last frame + +typedef enum __RF_BITRATE { + RF_BITRATE_106K = 0x00, + RF_BITRATE_212K = 0x01, + RF_BITRATE_424K = 0x02, + RF_BITRATE_848K = 0x03, + +} RF_BITRATE; + +#ifdef __cplusplus +} +#endif + +#endif /* PROTOCOLS_H_ */ + +/** + * @} + * @} + * */ + diff --git a/connectivity/nfc/libraries/stack/transceiver/transceiver.c b/connectivity/nfc/libraries/stack/transceiver/transceiver.c new file mode 100644 index 0000000..42d835a --- /dev/null +++ b/connectivity/nfc/libraries/stack/transceiver/transceiver.c @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2013-2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + */ +/** + * \file transceiver.c + * \copyright Copyright (c) ARM Ltd 2013 + * \author Donatien Garnier + * \details Transceiver + */ + +/** \addtogroup Transceiver + * @{ + * \name Initialization + * @{ + */ + +#include "transceiver.h" + +/** Initialize nfc_transceiver_t structure + * \param pTransceiver pointer to nfc_transceiver_t structure to initialize + * \param pTransport pointer to already initialized nfc_transport_t structure + * \param pImpl pointer to the structure implementing the transceiver interface (eg pn512_t or pn532_t) + */ +void transceiver_init(nfc_transceiver_t *pTransceiver, nfc_transport_t *pTransport, nfc_scheduler_timer_t *pTimer) +{ + pTransceiver->pTransport = pTransport; + nfc_scheduler_init(&pTransceiver->scheduler, pTimer); +} + + +/** + * @} + * @} + * */ diff --git a/connectivity/nfc/libraries/stack/transceiver/transceiver.h b/connectivity/nfc/libraries/stack/transceiver/transceiver.h new file mode 100644 index 0000000..864aeff --- /dev/null +++ b/connectivity/nfc/libraries/stack/transceiver/transceiver.h @@ -0,0 +1,272 @@ +/* + * Copyright (c) 2013-2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + */ +/** + * \file transceiver.h + * \copyright Copyright (c) ARM Ltd 2013 + * \author Donatien Garnier + */ + +#ifndef TRANSCEIVER_H_ +#define TRANSCEIVER_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "stack/nfc_common.h" + +typedef struct __nfc_tech nfc_tech_t; +typedef struct __transceiver nfc_transceiver_t; +typedef struct __transceiver_impl transceiver_impl_t; + +#include "protocols.h" +#include "platform/nfc_transport.h" +#include "platform/nfc_scheduler.h" + +enum __nfc_framing { + nfc_framing_unknown, + + nfc_framing_target_mode_detector, //Framing is unknown and will be detected by the hardware + nfc_framing_target_a_106, + nfc_framing_target_b_106, + nfc_framing_target_f_212, + nfc_framing_target_f_424, + + nfc_framing_initiator_a_106, + nfc_framing_initiator_b_106, + nfc_framing_initiator_f_212, + nfc_framing_initiator_f_424, +}; +typedef enum __nfc_framing nfc_framing_t; + +struct __nfc_tech { + unsigned int nfc_type1 : 1; + unsigned int nfc_type2 : 1; + unsigned int nfc_type3 : 1; + unsigned int nfc_iso_dep_a : 1; + unsigned int nfc_iso_dep_b : 1; + unsigned int nfc_nfc_dep_a : 1; + unsigned int nfc_nfc_dep_f_212 : 1; + unsigned int nfc_nfc_dep_f_424 : 1; +}; + +typedef struct __polling_options polling_options_t; +struct __polling_options { + unsigned int bail_at_first_target : 1; + unsigned int bail_at_first_tech : 1; + int32_t listen_for; +}; + +typedef void (*transceiver_cb_t)(nfc_transceiver_t *pTransceiver, nfc_err_t ret, void *pUserData); +typedef void (*set_protocols_fn_t)(nfc_transceiver_t *pTransceiver, nfc_tech_t initiators, nfc_tech_t targets, polling_options_t options); +typedef void (*poll_fn_t)(nfc_transceiver_t *pTransceiver); +typedef void (*set_crc_fn_t)(nfc_transceiver_t *pTransceiver, bool crcOut, bool crcIn); +typedef void (*set_timeout_fn_t)(nfc_transceiver_t *pTransceiver, int timeout); +typedef void (*set_transceive_options_fn_t)(nfc_transceiver_t *pTransceiver, bool transmit, bool receive, bool repoll); +typedef void (*set_transceive_framing_fn_t)(nfc_transceiver_t *pTransceiver, nfc_framing_t framing); +typedef void (*set_write_fn_t)(nfc_transceiver_t *pTransceiver, ac_buffer_t *pWriteBuf); //Set write buffer +typedef ac_buffer_t *(*get_read_fn_t)(nfc_transceiver_t *pTransceiver); //Get read buffer +typedef size_t (*get_last_byte_length_fn_t)(nfc_transceiver_t *pTransceiver); +typedef void (*set_last_byte_length_fn_t)(nfc_transceiver_t *pTransceiver, size_t lastByteLength); +typedef size_t (*get_first_byte_align_fn_t)(nfc_transceiver_t *pTransceiver); +typedef void (*set_first_byte_align_fn_t)(nfc_transceiver_t *pTransceiver, size_t firstByteAlign); +typedef void (*transceive_fn_t)(nfc_transceiver_t *pTransceiver); +typedef void (*abort_fn_t)(nfc_transceiver_t *pTransceiver); +typedef void (*close_fn_t)(nfc_transceiver_t *pTransceiver); +typedef void (*sleep_fn_t)(nfc_transceiver_t *pTransceiver, bool sleep); + +struct __transceiver_impl { + set_protocols_fn_t set_protocols; + poll_fn_t poll; + set_crc_fn_t set_crc; + set_timeout_fn_t set_timeout; + set_transceive_options_fn_t set_transceive_options; + set_transceive_framing_fn_t set_transceive_framing; + set_write_fn_t set_write; + get_read_fn_t get_read; + set_last_byte_length_fn_t set_last_byte_length; + get_last_byte_length_fn_t get_last_byte_length; + set_first_byte_align_fn_t set_first_byte_align; + transceive_fn_t transceive; + abort_fn_t abort; + close_fn_t close; + sleep_fn_t sleep; +}; + +typedef struct __nfc_a_info nfc_a_info_t; +struct __nfc_a_info { + uint8_t uid[10]; + size_t uidLength; + uint8_t sak; + uint8_t atqa[2]; +}; + +typedef struct __nfc_b_info nfc_b_info_t; +struct __nfc_b_info { + uint8_t pupi[4]; + uint8_t application_data[4]; + uint8_t protocol_info[3]; +}; + +typedef struct __nfc_f_info nfc_f_info_t; +struct __nfc_f_info { + uint8_t nfcid2[8]; +}; + +typedef struct __nfc_info nfc_info_t; + +struct __nfc_info { + nfc_tech_t type; + union { + nfc_a_info_t nfcA; + nfc_b_info_t nfcB; + nfc_f_info_t nfcF; + }; +}; + +#define MUNFC_MAX_REMOTE_TARGETS 4 +struct __transceiver { + const transceiver_impl_t *fn; //vtable + + bool initiator_ntarget; + nfc_info_t remote_targets[MUNFC_MAX_REMOTE_TARGETS]; + size_t remote_targets_count; + + nfc_tech_t active_tech; + + transceiver_cb_t cb; //Callback to upper layer + void *pUserData; + nfc_task_t task; //Task for deferred execution + + nfc_transport_t *pTransport; + nfc_scheduler_t scheduler; +}; + +void transceiver_init(nfc_transceiver_t *pTransceiver, nfc_transport_t *pTransport, nfc_scheduler_timer_t *pTimer); + +static inline void transceiver_set_protocols(nfc_transceiver_t *pTransceiver, nfc_tech_t initiators, nfc_tech_t targets, polling_options_t options) +{ + pTransceiver->fn->set_protocols(pTransceiver, initiators, targets, options); +} + +static inline void transceiver_poll(nfc_transceiver_t *pTransceiver, transceiver_cb_t cb, void *pUserData) +{ + pTransceiver->cb = cb; + pTransceiver->pUserData = pUserData; + pTransceiver->fn->poll(pTransceiver); +} + +static inline void transceiver_set_crc(nfc_transceiver_t *pTransceiver, bool crcOut, bool crcIn) +{ + pTransceiver->fn->set_crc(pTransceiver, crcOut, crcIn); +} + +static inline void transceiver_set_timeout(nfc_transceiver_t *pTransceiver, int timeout) +{ + pTransceiver->fn->set_timeout(pTransceiver, timeout); +} + +static inline void transceiver_set_transceive_options(nfc_transceiver_t *pTransceiver, bool transmit, bool receive, bool repoll) +{ + pTransceiver->fn->set_transceive_options(pTransceiver, transmit, receive, repoll); +} + +static inline void transceiver_set_transceive_framing(nfc_transceiver_t *pTransceiver, nfc_framing_t framing) +{ + pTransceiver->fn->set_transceive_framing(pTransceiver, framing); +} + +static inline void transceiver_set_write(nfc_transceiver_t *pTransceiver, ac_buffer_t *pWriteBuf) +{ + pTransceiver->fn->set_write(pTransceiver, pWriteBuf); +} + +static inline ac_buffer_t *transceiver_get_read(nfc_transceiver_t *pTransceiver) +{ + return pTransceiver->fn->get_read(pTransceiver); +} + +static inline size_t transceiver_get_last_byte_length(nfc_transceiver_t *pTransceiver) +{ + return pTransceiver->fn->get_last_byte_length(pTransceiver); +} + +static inline void transceiver_set_last_byte_length(nfc_transceiver_t *pTransceiver, size_t lastByteLength) +{ + pTransceiver->fn->set_last_byte_length(pTransceiver, lastByteLength); +} + +static inline void transceiver_set_first_byte_align(nfc_transceiver_t *pTransceiver, size_t firstByteAlign) +{ + pTransceiver->fn->set_first_byte_align(pTransceiver, firstByteAlign); +} + +static inline void nfc_transceiver_transceive(nfc_transceiver_t *pTransceiver, transceiver_cb_t cb, void *pUserData) +{ + pTransceiver->cb = cb; + pTransceiver->pUserData = pUserData; + pTransceiver->fn->transceive(pTransceiver); +} + +static inline void transceiver_abort(nfc_transceiver_t *pTransceiver) +{ + pTransceiver->fn->abort(pTransceiver); +} + +static inline void transceiver_close(nfc_transceiver_t *pTransceiver) +{ + pTransceiver->fn->close(pTransceiver); +} + +static inline bool transceiver_is_initiator_mode(nfc_transceiver_t *pTransceiver) +{ + return pTransceiver->initiator_ntarget; +} + +static inline nfc_tech_t transceiver_get_active_techs(nfc_transceiver_t *pTransceiver) +{ + return pTransceiver->active_tech; +} + +static inline nfc_scheduler_t *transceiver_get_scheduler(nfc_transceiver_t *pTransceiver) +{ + return &pTransceiver->scheduler; +} + +static inline const nfc_info_t *transceiver_get_remote_target_info(nfc_transceiver_t *pTransceiver, size_t number) +{ + if (number > pTransceiver->remote_targets_count) { + return NULL; + } + return &pTransceiver->remote_targets[number]; +} + +static inline size_t transceiver_get_remote_targets_count(nfc_transceiver_t *pTransceiver) +{ + return pTransceiver->remote_targets_count; +} + +static inline void transceiver_sleep(nfc_transceiver_t *pTransceiver, bool sleep) +{ + pTransceiver->fn->sleep(pTransceiver, sleep); +} + +#ifdef __cplusplus +} +#endif + +#endif /* TRANSCEIVER_H_ */ diff --git a/connectivity/nfc/libraries/stack/transceiver/transceiver_internal.h b/connectivity/nfc/libraries/stack/transceiver/transceiver_internal.h new file mode 100644 index 0000000..c689d11 --- /dev/null +++ b/connectivity/nfc/libraries/stack/transceiver/transceiver_internal.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2015-2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + */ +/** + * \file transceiver_internal.h + * \copyright Copyright (c) ARM Ltd 2015 + * \author Donatien Garnier + */ + +#ifndef TRANSCEIVER_INTERNAL_H_ +#define TRANSCEIVER_INTERNAL_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "stack/nfc_common.h" +#include "transceiver.h" + +static inline void transceiver_callback(nfc_transceiver_t *pTransceiver, nfc_err_t ret) +{ + pTransceiver->cb(pTransceiver, ret, pTransceiver->pUserData); +} + +#ifdef __cplusplus +} +#endif + +#endif /* TRANSCEIVER_INTERNAL_H_ */ diff --git a/connectivity/nfc/mbed_lib.json b/connectivity/nfc/mbed_lib.json new file mode 100644 index 0000000..dd3c37b --- /dev/null +++ b/connectivity/nfc/mbed_lib.json @@ -0,0 +1,3 @@ +{ + "name": "nfc" +} diff --git a/connectivity/nfc/source/NFCController.cpp b/connectivity/nfc/source/NFCController.cpp new file mode 100644 index 0000000..8101558 --- /dev/null +++ b/connectivity/nfc/source/NFCController.cpp @@ -0,0 +1,240 @@ +/* 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 "NFCController.h" +#include "NFCControllerDriver.h" +#include "Type4RemoteInitiator.h" + +#include "stack/transceiver/transceiver.h" + +using std::milli; +using namespace std::chrono; +using namespace mbed; +using namespace mbed::nfc; + +NFCController::NFCController(NFCControllerDriver *driver, events::EventQueue *queue, const Span &ndef_buffer) : + _driver(driver), _queue(queue), _transceiver(NULL), _scheduler(NULL), _delegate(NULL), _discovery_running(false), _ndef_buffer(ndef_buffer) +{ + _driver->set_delegate(this); +} + +nfc_err_t NFCController::initialize() +{ + MBED_ASSERT(_transceiver == NULL); // Initialize should only be called once + _transceiver = _driver->initialize((nfc_scheduler_timer_t *)&_timer); // See implementation below + + if (_transceiver == NULL) { + // Initialization error + return NFC_ERR_CONTROLLER; // Controller error + } + + // Recover scheduler + _scheduler = transceiver_get_scheduler(_transceiver); + + // Run scheduler for the first time + _queue->call(this, &NFCController::scheduler_process, false); + + return NFC_OK; +} + +void NFCController::set_delegate(Delegate *delegate) +{ + _delegate = delegate; +} + +nfc_rf_protocols_bitmask_t NFCController::get_supported_rf_protocols() const +{ + // nfc_rf_protocols_bitmask_t is mapped on NFC Forum types, nfc_tech_t is mapped on the underlying RF techs + // We therefore need to convert these + + nfc_rf_protocols_bitmask_t rf_protocols = {0}; + nfc_tech_t initiator_tech; + nfc_tech_t target_tech; + _driver->get_supported_nfc_techs(&initiator_tech, &target_tech); + + // Note: we only support ISO-DEP tag emulation in this release, + // so mask out all other protocols + + // rf_protocols.initiator_t1t = initiator_tech.nfc_type1; + // rf_protocols.initiator_t2t = initiator_tech.nfc_type2; + // rf_protocols.initiator_t3t = initiator_tech.nfc_type3; + // rf_protocols.initiator_iso_dep = initiator_tech.nfc_iso_dep_a || initiator_tech.nfc_iso_dep_b; + // 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; + + // rf_protocols.target_t1t = target_tech.nfc_type1; + // rf_protocols.target_t2t = target_tech.nfc_type2; + // rf_protocols.target_t3t = target_tech.nfc_type3; + rf_protocols.target_iso_dep = target_tech.nfc_iso_dep_a || target_tech.nfc_iso_dep_b; + // 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; + + return rf_protocols; +} + +nfc_err_t NFCController::configure_rf_protocols(nfc_rf_protocols_bitmask_t rf_protocols) +{ + if (_discovery_running) { + // Cannot configure RF protocols if discovery is running + return NFC_ERR_BUSY; + } + + // Map to NFC techs + nfc_tech_t initiator_tech = {0}; + nfc_tech_t target_tech = {0}; + + // Note: we only support ISO-DEP tag emulation in this release, + // so mask out all other protocols + + target_tech.nfc_iso_dep_a = target_tech.nfc_iso_dep_b = true; + + // Configure polling options (no need to set bailing flags as we're only using target mode) + polling_options_t options = {0}; + options.listen_for = -1; // Listen forever + + transceiver_set_protocols(_transceiver, initiator_tech, target_tech, options); + + return NFC_OK; +} + +nfc_err_t NFCController::start_discovery() +{ + if (_discovery_running) { + // Cannot start discovery if it's already running + return NFC_ERR_BUSY; + } + + transceiver_poll(_transceiver, &NFCController::s_polling_callback, this /* use this as callback argument */); + + return NFC_OK; +} + +nfc_err_t NFCController::cancel_discovery() +{ + if (!_discovery_running) { + return NFC_OK; + } + + transceiver_abort(_transceiver); + + return NFC_OK; +} + +nfc_transceiver_t *NFCController::transceiver() const +{ + return _transceiver; +} + +void NFCController::polling_callback(nfc_err_t ret) +{ + // Polling has completed + _discovery_running = false; + + NFC_DBG("Polling finished with result %u", ret); + + if (ret == NFC_OK) { + // Check if a remote initiator was detected and if so, instantiate it + 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) && (_delegate != NULL)) { + Type4RemoteInitiator *type4_remote_initiator_ptr = new (std::nothrow) Type4RemoteInitiator(this, _ndef_buffer); + if (type4_remote_initiator_ptr != NULL) { + SharedPtr type4_remote_initiator(type4_remote_initiator_ptr); + _delegate->on_nfc_initiator_discovered(type4_remote_initiator); + } + } + } + } + + if (_delegate != NULL) { + Delegate::nfc_discovery_terminated_reason_t reason; + + // Map reason + switch (ret) { + case NFC_OK: + reason = Delegate::nfc_discovery_terminated_completed; + break; + case NFC_ERR_ABORTED: + reason = Delegate::nfc_discovery_terminated_canceled; + break; + default: + // Any other error code means there was an error during the discovery process + reason = Delegate::nfc_discovery_terminated_rf_error; + break; + } + + _delegate->on_discovery_terminated(reason); + } +} + +void NFCController::scheduler_process(bool hw_interrupt) +{ + _timeout.detach(); // Cancel timeout - if it triggers, it's ok as we'll have an "early" iteration which will likely be a no-op + + // Process stack events + duration timeout{nfc_scheduler_iteration(_scheduler, hw_interrupt ? EVENT_HW_INTERRUPT : EVENT_NONE)}; + + _timeout.attach(callback(this, &NFCController::on_timeout), timeout); +} + +void NFCController::on_hw_interrupt() +{ + // Run scheduler - this is called in interrupt context + _timeout.detach(); // Cancel timeout - if it triggers anyways, it's ok + _queue->call(this, &NFCController::scheduler_process, true); +} + +void NFCController::on_timeout() +{ + // Run scheduler - this is called in interrupt context + _queue->call(this, &NFCController::scheduler_process, false); +} + +void NFCController::s_polling_callback(nfc_transceiver_t *pTransceiver, nfc_err_t ret, void *pUserData) +{ + NFCController *self = (NFCController *) pUserData; + self->polling_callback(ret); +} + +// Implementation nfc_scheduler_timer_t +void nfc_scheduler_timer_init(nfc_scheduler_timer_t *timer) +{ + (void)timer; // This is a no-op +} + +void nfc_scheduler_timer_start(nfc_scheduler_timer_t *timer) +{ + Timer *mbed_timer = (Timer *)timer; + mbed_timer->start(); +} + +uint32_t nfc_scheduler_timer_get(nfc_scheduler_timer_t *timer) +{ + Timer *mbed_timer = (Timer *)timer; + return (uint32_t)std::chrono::duration_cast( + mbed_timer->elapsed_time() + ).count(); +} + +void nfc_scheduler_timer_stop(nfc_scheduler_timer_t *timer) +{ + Timer *mbed_timer = (Timer *)timer; + mbed_timer->stop(); +} + +void nfc_scheduler_timer_reset(nfc_scheduler_timer_t *timer) +{ + Timer *mbed_timer = (Timer *)timer; + mbed_timer->reset(); +} diff --git a/connectivity/nfc/source/NFCControllerDriver.cpp b/connectivity/nfc/source/NFCControllerDriver.cpp new file mode 100644 index 0000000..bc9810a --- /dev/null +++ b/connectivity/nfc/source/NFCControllerDriver.cpp @@ -0,0 +1,42 @@ +/* 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 "NFCControllerDriver.h" + +using namespace mbed; +using namespace mbed::nfc; + +NFCControllerDriver::NFCControllerDriver() : _delegate(NULL) +{ + +} + +NFCControllerDriver::~NFCControllerDriver() +{ + +} + +void NFCControllerDriver::set_delegate(Delegate *delegate) +{ + _delegate = delegate; +} + +void NFCControllerDriver::hw_interrupt() +{ + if (_delegate != NULL) { + _delegate->on_hw_interrupt(); + } +} diff --git a/connectivity/nfc/source/NFCEEPROM.cpp b/connectivity/nfc/source/NFCEEPROM.cpp new file mode 100644 index 0000000..e3dd759 --- /dev/null +++ b/connectivity/nfc/source/NFCEEPROM.cpp @@ -0,0 +1,426 @@ +/* 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::NFCEEPROM(NFCEEPROMDriver *driver, events::EventQueue *queue, const Span &ndef_buffer) + : + NFCTarget(ndef_buffer), _delegate(NULL), _driver(driver), _event_queue(queue), _initialized(false), + _current_op(nfc_eeprom_idle), _ndef_buffer_reader { nullptr, 0, nullptr }, _ndef_buffer_read_sz(0), + _eeprom_address(0), _operation_result(NFC_ERR_UNKNOWN) +{ + _driver->set_delegate(this); + _driver->set_event_queue(queue); +} + +nfc_err_t NFCEEPROM::initialize() +{ + MBED_ASSERT(_initialized == false); // Initialize should only be called once + + // Initialize driver + _driver->reset(); + _initialized = true; + return NFC_OK; +} + +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->read_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 + + 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_erase_start_session; + + // Reset EEPROM address + _eeprom_address = 0; + + // Go through the steps! + _driver->start_session(); + + // 1 - Start session + // 2 - Set addressable size to the max + // 3 - Erase bytes (can be repeated) + // 4 - Set addressable size to 0 + // 5 - End session +} + +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_size; + _driver->write_size(ac_buffer_reader_readable(&_ndef_buffer_reader)); + 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; + + case nfc_eeprom_erase_start_session: + if (!success) { + handle_error(NFC_ERR_CONTROLLER); + return; + } + + _current_op = nfc_eeprom_erase_write_max_size; + _driver->write_size(_driver->read_max_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) { + _delegate->on_ndef_message_written(_operation_result); + } + break; + + case nfc_eeprom_read_end_session: + if (!success) { + handle_error(NFC_ERR_CONTROLLER); + return; + } + _current_op = nfc_eeprom_idle; + + // Try to parse the NDEF message + ndef_msg_decode(ndef_message()); + + if (_delegate != NULL) { + _delegate->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) { + _delegate->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); + return; + } +} + +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 + _event_queue->call(this, &NFCEEPROM::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) +{ + switch (_current_op) { + case nfc_eeprom_write_write_bytes: + if (count == 0) { + handle_error(NFC_ERR_CONTROLLER); + return; + } + + // Skip bytes that were actually written and update address + _eeprom_address += count; + ac_buffer_read_n_skip(&_ndef_buffer_reader, count); + + // Continue writing + _event_queue->call(this, &NFCEEPROM::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; + } + + _current_op = nfc_eeprom_write_write_bytes; + continue_write(); + break; + case nfc_eeprom_erase_write_max_size: + if (!success) { + handle_error(NFC_ERR_CONTROLLER); + return; + } + + // Start erasing bytes + _current_op = nfc_eeprom_erase_erase_bytes; + continue_erase(); + break; + case nfc_eeprom_erase_write_0_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: + // 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) +{ + 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; + _event_queue->call(this, &NFCEEPROM::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 + _event_queue->call(this, &NFCEEPROM::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::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 { + // we are done + _current_op = nfc_eeprom_write_end_session; + _operation_result = NFC_OK; + _driver->end_session(); + } +} + +void NFCEEPROM::continue_erase() +{ + if (_eeprom_address < _driver->read_max_size()) { + // Continue erasing + _driver->erase_bytes(_eeprom_address, _driver->read_max_size() - _eeprom_address); + } else { + // Now update size + _current_op = nfc_eeprom_erase_write_0_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 + _current_op = nfc_eeprom_read_end_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; + _current_op = nfc_eeprom_idle; + + if (_delegate != NULL) { + if (last_op <= nfc_eeprom_write_end_session) { + _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); + } + } +} + +NFCNDEFCapable::Delegate *NFCEEPROM::ndef_capable_delegate() +{ + return _delegate; +} diff --git a/connectivity/nfc/source/NFCEEPROMDriver.cpp b/connectivity/nfc/source/NFCEEPROMDriver.cpp new file mode 100644 index 0000000..8305580 --- /dev/null +++ b/connectivity/nfc/source/NFCEEPROMDriver.cpp @@ -0,0 +1,50 @@ +/* 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 "NFCEEPROMDriver.h" + +using namespace mbed; +using namespace mbed::nfc; + +NFCEEPROMDriver::NFCEEPROMDriver() : _delegate(NULL), _event_queue(NULL) +{ + +} + +NFCEEPROMDriver::~NFCEEPROMDriver() +{ + +} + +void NFCEEPROMDriver::set_delegate(Delegate *delegate) +{ + _delegate = delegate; +} + +void NFCEEPROMDriver::set_event_queue(events::EventQueue *queue) +{ + _event_queue = queue; +} + +NFCEEPROMDriver::Delegate *NFCEEPROMDriver::delegate() +{ + return _delegate; +} + +events::EventQueue *NFCEEPROMDriver::event_queue() +{ + return _event_queue; +} diff --git a/connectivity/nfc/source/NFCNDEFCapable.cpp b/connectivity/nfc/source/NFCNDEFCapable.cpp new file mode 100644 index 0000000..279820a --- /dev/null +++ b/connectivity/nfc/source/NFCNDEFCapable.cpp @@ -0,0 +1,85 @@ +/* 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 "NFCNDEFCapable.h" + +#include "acore/ac_buffer.h" +#include "acore/ac_buffer_reader.h" +#include "acore/ac_buffer_builder.h" + +#include "ndef/ndef.h" + +using namespace mbed; +using namespace mbed::nfc; + +NFCNDEFCapable::NFCNDEFCapable(const Span &buffer) +{ + ndef_msg_init(&_ndef_message, s_ndef_encode, s_ndef_decode, buffer.data(), buffer.size(), this); +} + +void NFCNDEFCapable::parse_ndef_message(const ac_buffer_t &buffer) +{ + ac_buffer_t reader; + ac_buffer_dup(&reader, &buffer); + + Delegate *delegate = ndef_capable_delegate(); + if (delegate != NULL) { + delegate->parse_ndef_message(make_const_Span(ac_buffer_reader_current_buffer_pointer(&reader), ac_buffer_reader_current_buffer_length(&reader))); + } +} + +void NFCNDEFCapable::build_ndef_message(ac_buffer_builder_t &buffer_builder) +{ + Delegate *delegate = ndef_capable_delegate(); + if (delegate != NULL) { + size_t count = delegate->build_ndef_message(make_Span(ac_buffer_builder_write_position(&buffer_builder), ac_buffer_builder_writable(&buffer_builder))); + ac_buffer_builder_write_n_skip(&buffer_builder, count); + } +} + +nfc_err_t NFCNDEFCapable::s_ndef_encode(ndef_msg_t *pTag, ac_buffer_builder_t *pBufferBldr, void *pUserData) +{ + NFCNDEFCapable *self = (NFCNDEFCapable *)pUserData; + return self->ndef_encode(pBufferBldr); +} + +nfc_err_t NFCNDEFCapable::s_ndef_decode(ndef_msg_t *pTag, ac_buffer_t *pBuffer, void *pUserData) +{ + NFCNDEFCapable *self = (NFCNDEFCapable *)pUserData; + return self->ndef_decode(pBuffer); +} + +nfc_err_t NFCNDEFCapable::ndef_encode(ac_buffer_builder_t *pBufferBldr) +{ + build_ndef_message(*pBufferBldr); + return NFC_OK; +} + +nfc_err_t NFCNDEFCapable::ndef_decode(ac_buffer_t *pBuffer) +{ + parse_ndef_message(*pBuffer); + return NFC_OK; +} + +ndef_msg_t *NFCNDEFCapable::ndef_message() +{ + return &_ndef_message; +} + +NFCNDEFCapable::Delegate *NFCNDEFCapable::ndef_capable_delegate() +{ + return NULL; +} diff --git a/connectivity/nfc/source/NFCRemoteEndpoint.cpp b/connectivity/nfc/source/NFCRemoteEndpoint.cpp new file mode 100644 index 0000000..f1c2a95 --- /dev/null +++ b/connectivity/nfc/source/NFCRemoteEndpoint.cpp @@ -0,0 +1,60 @@ +/* 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 "NFCRemoteEndpoint.h" +#include "NFCController.h" + +#include "acore/ac_buffer.h" +#include "acore/ac_buffer_reader.h" +#include "acore/ac_buffer_builder.h" + +#include "stack/transceiver/transceiver.h" + +using namespace mbed; +using namespace mbed::nfc; + +NFCRemoteEndpoint::NFCRemoteEndpoint(NFCController *controller) : _controller(controller) +{ + +} + +NFCRemoteEndpoint::~NFCRemoteEndpoint() +{ + +} + +nfc_rf_protocols_bitmask_t NFCRemoteEndpoint::rf_protocols() +{ + nfc_rf_protocols_bitmask_t rf_protocols = {0}; + nfc_tech_t active_tech = transceiver_get_active_techs(_controller->transceiver()); + if (!transceiver_is_initiator_mode(_controller->transceiver())) { + // Note: We only support ISO-DEP for now + rf_protocols.target_iso_dep = active_tech.nfc_iso_dep_a || active_tech.nfc_iso_dep_b; + } + + return rf_protocols; +} + +NFCController *NFCRemoteEndpoint::nfc_controller() +{ + return _controller; +} + +const NFCController *NFCRemoteEndpoint::nfc_controller() const +{ + return _controller; +} + diff --git a/connectivity/nfc/source/NFCRemoteInitiator.cpp b/connectivity/nfc/source/NFCRemoteInitiator.cpp new file mode 100644 index 0000000..4863ca8 --- /dev/null +++ b/connectivity/nfc/source/NFCRemoteInitiator.cpp @@ -0,0 +1,55 @@ +/* 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 "NFCRemoteInitiator.h" + +using namespace mbed; +using namespace mbed::nfc; + +NFCRemoteInitiator::NFCRemoteInitiator(NFCController *controller, const Span &buffer) : + NFCRemoteEndpoint(controller), NFCNDEFCapable(buffer), _delegate(NULL) +{ + +} + +NFCRemoteInitiator::~NFCRemoteInitiator() +{ + +} + +void NFCRemoteInitiator::set_delegate(Delegate *delegate) +{ + _delegate = delegate; +} + +void NFCRemoteInitiator::connected() +{ + if (_delegate != NULL) { + _delegate->on_connected(); + } +} + +void NFCRemoteInitiator::disconnected() +{ + if (_delegate != NULL) { + _delegate->on_disconnected(); + } +} + +NFCNDEFCapable::Delegate *NFCRemoteInitiator::ndef_capable_delegate() +{ + return _delegate; +} diff --git a/connectivity/nfc/source/NFCTarget.cpp b/connectivity/nfc/source/NFCTarget.cpp new file mode 100644 index 0000000..f54213d --- /dev/null +++ b/connectivity/nfc/source/NFCTarget.cpp @@ -0,0 +1,31 @@ +/* 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 "NFCTarget.h" + +using namespace mbed; +using namespace mbed::nfc; + +NFCTarget::NFCTarget(const Span &buffer) : + NFCNDEFCapable(buffer) +{ + +} + +NFCTarget::~NFCTarget() +{ + +} diff --git a/connectivity/nfc/source/Type4RemoteInitiator.cpp b/connectivity/nfc/source/Type4RemoteInitiator.cpp new file mode 100644 index 0000000..aa03b29 --- /dev/null +++ b/connectivity/nfc/source/Type4RemoteInitiator.cpp @@ -0,0 +1,140 @@ +/* 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 "Type4RemoteInitiator.h" +#include "NFCController.h" + +#include "acore/ac_buffer.h" +#include "acore/ac_buffer_reader.h" +#include "acore/ac_buffer_builder.h" + +#include "stack/transceiver/transceiver.h" +#include "stack/tech/iso7816/iso7816.h" +#include "stack/tech/iso7816/iso7816_app.h" +#include "stack/tech/type4/type4_target.h" + +using namespace mbed; +using namespace mbed::nfc; + +Type4RemoteInitiator::Type4RemoteInitiator(NFCController *controller, const Span &buffer) : + NFCRemoteInitiator(controller, buffer), + _is_connected(false), _is_disconnected(false) +{ + // Init ISO7816 + nfc_tech_iso7816_init(&_iso7816, nfc_controller()->transceiver(), &Type4RemoteInitiator::s_disconnected_callback, this); + + // Init Type 4 app + nfc_tech_type4_target_init(&_type4, &_iso7816, ndef_message()); +} + +Type4RemoteInitiator::~Type4RemoteInitiator() +{ + +} + +nfc_err_t Type4RemoteInitiator::connect() +{ + if (_is_connected) { + return NFC_ERR_BUSY; + } + + if (_is_disconnected) { + return NFC_ERR_DISCONNECTED; + } + + // Connect ISO7816 stack + nfc_tech_iso7816_connect(&_iso7816); + + // Call callback as it's a synchronous API + connected(); + + return NFC_OK; +} + +nfc_err_t Type4RemoteInitiator::disconnect() +{ + if (!_is_connected) { + return NFC_OK; + } + + if (_is_disconnected) { + return NFC_OK; + } + + // Disconnect ISO7816 stack + nfc_tech_iso7816_disconnect(&_iso7816); + + return NFC_OK; +} + +bool Type4RemoteInitiator::is_connected() const +{ + return _is_connected; +} + +bool Type4RemoteInitiator::is_disconnected() const +{ + return _is_disconnected; +} + +nfc_rf_protocols_bitmask_t Type4RemoteInitiator::rf_protocols() +{ + nfc_rf_protocols_bitmask_t rf_protocols = {0}; + nfc_tech_t active_tech = transceiver_get_active_techs(nfc_controller()->transceiver()); + if (!transceiver_is_initiator_mode(nfc_controller()->transceiver())) { + // We only support ISO-DEP + rf_protocols.target_iso_dep = active_tech.nfc_iso_dep_a || active_tech.nfc_iso_dep_b; + } + + return rf_protocols; +} + +nfc_tag_type_t Type4RemoteInitiator::nfc_tag_type() const +{ + nfc_tech_t active_tech = transceiver_get_active_techs(nfc_controller()->transceiver()); + if (active_tech.nfc_iso_dep_a) { + return nfc_tag_type_4a; + } else { // if(active_tech.nfc_iso_dep_b) + return nfc_tag_type_4b; + } +} + +bool Type4RemoteInitiator::is_iso7816_supported() const +{ + return true; +} + +void Type4RemoteInitiator::add_iso7816_application(nfc_tech_iso7816_app_t *application) +{ + nfc_tech_iso7816_add_app(&_iso7816, application); +} + +bool Type4RemoteInitiator::is_ndef_supported() const +{ + return true; +} + +void Type4RemoteInitiator::disconnected_callback() +{ + // Call disconnected callback + disconnected(); +} + +void Type4RemoteInitiator::s_disconnected_callback(nfc_tech_iso7816_t *pIso7816, void *pUserData) +{ + Type4RemoteInitiator *self = (Type4RemoteInitiator *) pUserData; + self->disconnected_callback(); +} diff --git a/connectivity/nfc/source/ndef/MessageBuilder.cpp b/connectivity/nfc/source/ndef/MessageBuilder.cpp new file mode 100644 index 0000000..d9aec05 --- /dev/null +++ b/connectivity/nfc/source/ndef/MessageBuilder.cpp @@ -0,0 +1,322 @@ +/* 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 + +#include "nfc/ndef/MessageBuilder.h" + +namespace mbed { +namespace nfc { +namespace ndef { + +MessageBuilder::MessageBuilder(const Span &buffer) : + _message_buffer(buffer), + _position(0), + _message_started(false), + _message_ended(false), + _in_chunk(false) +{ } + +bool MessageBuilder::append_record( + const RecordType &type, + const RecordPayload &payload, + bool is_last_record +) +{ + Record record( + type, + payload, + /* id */ RecordID(), + /* chunk */ false, + is_last_record + ); + + return append_record(record); +} + +bool MessageBuilder::append_record( + const RecordType &type, + const PayloadBuilder &builder, + bool is_last_record +) +{ + Record record( + type, + RecordPayload(), + RecordID(), + /* chunk */ false, + is_last_record + ); + + return append_record(record, &builder); +} + + +bool MessageBuilder::append_record(const Record &record, const PayloadBuilder *builder) +{ + if (_message_ended) { + return false; + } + + if (record.type.value.size() > 255) { + return false; + } + + if (record.id.size() > 255) { + return false; + } + + if (!record.id.empty() && _in_chunk) { + if (record.chunk) { + // middle chunk + return false; + } else if (record.type.tnf == RecordType::unchanged) { + // terminating chunk + return false; + } + } + + if (_in_chunk && record.type.tnf != RecordType::unchanged) { + return false; + } + + if (!_in_chunk && record.chunk && record.type.tnf == RecordType::unchanged) { + return false; + } + + if (record.type.tnf == RecordType::empty) { + if (!record.type.value.empty()) { + return false; + } + + if (!record.id.empty()) { + return false; + } + + if (get_payload_size(record, builder)) { + return false; + } + } + + if (record.type.tnf == RecordType::well_known_type || + record.type.tnf == RecordType::media_type || + record.type.tnf == RecordType::absolute_uri || + record.type.tnf == RecordType::external_type + ) { + if (record.type.value.empty()) { + return false; + } + } + + if (record.type.tnf == RecordType::unknown && !record.type.value.empty()) { + return false; + } + + size_t record_size = compute_record_size(record, builder); + if (record_size > (_message_buffer.size() - _position)) { + return false; + } + + append_header(record, builder); + append_type_length(record); + append_payload_length(record, builder); + append_id_length(record); + append_type(record); + append_id(record); + append_payload(record, builder); + + if (record.chunk) { + _in_chunk = true; + } else if (record.type.tnf == RecordType::unchanged) { + // last chunk reached + _in_chunk = false; + } + + return true; +} + +void MessageBuilder::reset() +{ + _position = 0; + _message_started = false; + _message_ended = false; + _in_chunk = false; +} + +void MessageBuilder::reset(const Span &buffer) +{ + _message_buffer = buffer; + _position = 0; + _message_started = false; + _message_ended = false; + _in_chunk = false; +} + +bool MessageBuilder::is_message_complete() const +{ + return _message_ended; +} + +Span MessageBuilder::get_message() const +{ + if (is_message_complete()) { + return _message_buffer.first(_position); + } else { + return Span(); + } +} + +size_t MessageBuilder::compute_record_size(const Record &record, const PayloadBuilder *builder) +{ + size_t record_size = 0; + record_size = 1; /* header */ + record_size += 1; /* type length */ + record_size += is_short_payload(record, builder) ? 1 : 4; + + if (!record.id.empty()) { + record_size += 1; + } + + record_size += record.type.value.size(); + record_size += record.id.size(); + record_size += get_payload_size(record, builder); + + return record_size; +} + +void MessageBuilder::append_header(const Record &record, const PayloadBuilder *builder) +{ + uint8_t header = 0; + if (!_message_started) { + header |= Header::message_begin_bit; + _message_started = true; + } + + if (record.last_record) { + header |= Header::message_end_bit; + _message_ended = true; + } + + if (record.chunk) { + header |= Header::chunk_flag_bit; + } + + if (is_short_payload(record, builder)) { + header |= Header::short_record_bit; + } + + if (record.id.size()) { + header |= Header::id_length_bit; + } + + header |= record.type.tnf; + _message_buffer[_position++] = header; +} + +void MessageBuilder::append_type_length(const Record &record) +{ + _message_buffer[_position++] = record.type.value.size(); +} + +void MessageBuilder::append_payload_length(const Record &record, const PayloadBuilder *builder) +{ + size_t size = get_payload_size(record, builder); + + if (is_short_payload(record, builder)) { + _message_buffer[_position++] = size; + } else { + _message_buffer[_position++] = (size >> 24) & 0xFF; + _message_buffer[_position++] = (size >> 16) & 0xFF; + _message_buffer[_position++] = (size >> 8) & 0xFF; + _message_buffer[_position++] = size & 0xFF; + } +} + +void MessageBuilder::append_id_length(const Record &record) +{ + if (record.id.empty()) { + return; + } + + _message_buffer[_position++] = record.id.size(); +} + +void MessageBuilder::append_type(const Record &record) +{ + if (record.type.value.empty()) { + return; + } + + memcpy( + _message_buffer.data() + _position, + record.type.value.data(), + record.type.value.size() + ); + _position += record.type.value.size(); +} + +void MessageBuilder::append_id(const Record &record) +{ + if (record.id.empty()) { + return; + } + + memcpy( + _message_buffer.data() + _position, + record.id.data(), + record.id.size() + ); + _position += record.id.size(); +} + +void MessageBuilder::append_payload(const Record &record, const PayloadBuilder *builder) +{ + size_t size = get_payload_size(record, builder); + if (!size) { + return; + } + + if (builder) { + builder->build(_message_buffer.subspan(_position, size)); + } else { + memcpy( + _message_buffer.data() + _position, + record.payload.data(), + size + ); + } + + _position += size; +} + +bool MessageBuilder::is_short_payload(const Record &record, const PayloadBuilder *builder) +{ + if (get_payload_size(record, builder) <= 255) { + return true; + } else { + return false; + } +} + +size_t MessageBuilder::get_payload_size(const Record &record, const PayloadBuilder *builder) +{ + return builder ? builder->size() : record.payload.size(); +} + +} // namespace ndef +} // namespace nfc +} // namespace mbed + diff --git a/connectivity/nfc/source/ndef/MessageParser.cpp b/connectivity/nfc/source/ndef/MessageParser.cpp new file mode 100644 index 0000000..619d45d --- /dev/null +++ b/connectivity/nfc/source/ndef/MessageParser.cpp @@ -0,0 +1,314 @@ +/* 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 + +#include "nfc/ndef/MessageParser.h" +#include "nfc/ndef/Record.h" + +namespace { +struct buffer_iterator_t { + buffer_iterator_t(const mbed::Span &buffer) : + buffer(buffer), + position(0) + { } + + uint8_t operator*() + { + return buffer[position]; + } + + buffer_iterator_t &operator++() + { + ++position; + return *this; + } + + buffer_iterator_t operator++(int) + { + buffer_iterator_t previous = *this; + ++*this; + return previous; + } + + buffer_iterator_t &operator+=(size_t increment) + { + position += increment; + return *this; + } + + operator bool() const + { + return (position >= buffer.size()) ? false : true; + } + + size_t remaining_size() const + { + return buffer.size() - position; + } + + void read_le(uint8_t *dest, size_t size) + { + memcpy(dest, buffer.data() + position, size); + position += size; + } + + void read_be(uint8_t *dest, size_t size) + { + // TODO: Needs proper network to host function + std::reverse_copy( + buffer.data() + position, + buffer.data() + position + size, + dest + ); + position += size; + } + + mbed::Span get_underlying_buffer() const + { + return buffer.last(buffer.size() - position); + } + +private: + mbed::Span buffer; + mbed::Span::index_type position; +}; + +} // end of anonymous namespace + +namespace mbed { +namespace nfc { +namespace ndef { + +struct MessageParser::parsing_state_t { + parsing_state_t(const Span &data_buffer) : + it(data_buffer), + first_record_parsed(false), + last_record_parsed(false), + error(false) + { } + + buffer_iterator_t it; + bool first_record_parsed: 1; + bool last_record_parsed: 1; + bool error: 1; +}; + +MessageParser::MessageParser() : + _delegate(NULL) +{ } + +void MessageParser::set_delegate(Delegate *delegate) +{ + _delegate = delegate; +} + +void MessageParser::parse(const Span &data_buffer) +{ + parsing_state_t parsing_state(data_buffer); + report_parsing_started(); + while (parsing_state.it && parse_record(parsing_state)); + if (!parsing_state.error && !parsing_state.last_record_parsed) { + report_parsing_error(MISSING_MESSAGE_END, parsing_state); + } + report_parsing_terminated(); +} + +bool MessageParser::parse_record(parsing_state_t &s) +{ + if (s.error || s.last_record_parsed) { + return false; + } + + // ensure that the header can be extracted + if (s.it.remaining_size() < 1) { + report_parsing_error(INSUFICIENT_DATA, s); + return false; + } + + uint8_t header = *s.it++; + + // NOTE: report an error until the chunk parsing design is sorted out + if (header & Header::chunk_flag_bit) { + report_parsing_error(CHUNK_RECORD_NOT_SUPPORTED, s); + return false; + } + + // handle first record cases + if (s.first_record_parsed == false) { + if (header & Header::message_begin_bit) { + s.first_record_parsed = true; + } else { + report_parsing_error(INVALID_MESSAGE_START, s); + return false; + } + } else if (header & Header::message_begin_bit) { + report_parsing_error(INVALID_MESSAGE_START, s); + return false; + } + + // handle last record + if (header & Header::message_end_bit) { + s.last_record_parsed = true; + } + + // ensure their is enough space to contain the type length, payload + // length and id length + uint8_t lengths_size = compute_lengths_size(header); + if (s.it.remaining_size() < lengths_size) { + report_parsing_error(INSUFICIENT_DATA, s); + return false; + } + + // extract the various length from the message + uint8_t type_length = extract_type_length(s); + uint32_t payload_length = extract_payload_length(s, header); + uint8_t id_length = extract_id_length(s, header); + + // there should be enough bytes left in the buffer + if (s.it.remaining_size() < (type_length + id_length + payload_length)) { + report_parsing_error(INSUFICIENT_DATA, s); + return false; + } + + // validate the Type Name Format of the header + switch (header & Header::tnf_bits) { + case RecordType::empty: + if (type_length || payload_length || id_length) { + report_parsing_error(INVALID_EMPTY_RECORD, s); + return false; + } + break; + case RecordType::well_known_type: + case RecordType::media_type: + case RecordType::absolute_uri: + case RecordType::external_type: + if (!type_length) { + report_parsing_error(MISSING_TYPE_VALUE, s); + return false; + } + break; + case RecordType::unknown: + if (type_length) { + report_parsing_error(INVALID_UNKNOWN_TYPE_LENGTH, s); + return false; + } + break; + case RecordType::unchanged: + // shouldn't be handled outside of chunk handling + report_parsing_error(INVALID_UNCHANGED_TYPE, s); + return false; + default: + report_parsing_error(INVALID_TYPE_NAME_FORMAT, s); + return false; + } + + // build the record + Record record; + + // flags + record.last_record = header & Header::message_end_bit; + + // type + record.type.tnf = static_cast(header & Header::tnf_bits); + if (type_length) { + record.type.value = s.it.get_underlying_buffer().first(type_length); + s.it += type_length; + } + + // id + if (id_length) { + record.id = s.it.get_underlying_buffer().first(id_length); + s.it += id_length; + } + + // payload + if (payload_length) { + record.payload = s.it.get_underlying_buffer().first(payload_length); + s.it += payload_length; + } + + s.it += payload_length; + + report_record_parsed(record); + + return true; +} + +uint8_t MessageParser::compute_lengths_size(uint8_t header) +{ + return 1 /* type_length size */ + + ((header & Header::short_record_bit) ? 1 : 4) /* payload length */ + + ((header & Header::id_length_bit) ? 1 : 0); +} + +uint8_t MessageParser::extract_type_length(parsing_state_t &s) +{ + return *s.it++; +} + +uint32_t MessageParser::extract_payload_length(parsing_state_t &s, uint8_t header) +{ + uint32_t payload_length = 0; + if (header & Header::short_record_bit) { + payload_length = *s.it++; + } else { + s.it.read_be( + reinterpret_cast(&payload_length), + sizeof(payload_length) + ); + } + return payload_length; +} + +uint8_t MessageParser::extract_id_length(parsing_state_t &s, uint8_t header) +{ + return (header & Header::id_length_bit) ? *s.it++ : 0; +} + +void MessageParser::report_parsing_started() +{ + if (_delegate) { + _delegate->on_parsing_started(); + } +} + +void MessageParser::report_record_parsed(const Record &record) +{ + if (_delegate) { + _delegate->on_record_parsed(record); + } +} + +void MessageParser::report_parsing_terminated() +{ + if (_delegate) { + _delegate->on_parsing_terminated(); + } +} + +void MessageParser::report_parsing_error(error_t error, parsing_state_t &parsing_state) +{ + parsing_state.error = true; + if (_delegate) { + _delegate->on_parsing_error(error); + } +} + +} // namespace ndef +} // namespace nfc +} // namespace mbed + diff --git a/connectivity/nfc/source/ndef/RecordParser.cpp b/connectivity/nfc/source/ndef/RecordParser.cpp new file mode 100644 index 0000000..a3ae07c --- /dev/null +++ b/connectivity/nfc/source/ndef/RecordParser.cpp @@ -0,0 +1,50 @@ +/* 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 "nfc/ndef/RecordParser.h" + +namespace mbed { +namespace nfc { +namespace ndef { + +bool RecordParserChain::parse(const Record &record) +{ + RecordParser *current_parser = _parsers; + while (current_parser) { + if (current_parser->parse(record)) { + return true; + } + current_parser = current_parser->_next_parser; + } + return false; +} + +void RecordParserChain::set_next_parser(RecordParser *parser) +{ + if (!_parsers) { + _parsers = parser; + } else { + RecordParser *current_parser = _parsers; + while (current_parser->_next_parser) { + current_parser = current_parser->_next_parser; + } + current_parser->_next_parser = parser; + } +} + +} // namespace ndef +} // namespace nfc +} // namespace mbed diff --git a/connectivity/nfc/source/ndef/common/Mime.cpp b/connectivity/nfc/source/ndef/common/Mime.cpp new file mode 100644 index 0000000..7818cd3 --- /dev/null +++ b/connectivity/nfc/source/ndef/common/Mime.cpp @@ -0,0 +1,174 @@ +/* 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 + +#include "nfc/ndef/common/Mime.h" + +namespace mbed { +namespace nfc { +namespace ndef { +namespace common { + +Mime::Mime() : + _mime(NULL), + _type_size(0), + _content_size(0) +{ } + +Mime::Mime( + const Span &mime_type, + const Span &content +) : _mime(new uint8_t[mime_type.size() + content.size()]), + _type_size(mime_type.size()), + _content_size(content.size()) +{ + memcpy(_mime, mime_type.data(), mime_type.size()); + memcpy(_mime + mime_type.size(), content.data(), content.size()); +} + +Mime::Mime(const Mime &to_copy) : + _mime(new uint8_t[to_copy.mime_size()]), + _type_size(to_copy._type_size), + _content_size(to_copy._content_size) +{ + memcpy(_mime, to_copy._mime, to_copy.mime_size()); +} + +Mime::~Mime() +{ + delete[] _mime; +} + +Mime &Mime::operator=(const Mime &to_copy) +{ + if (this == &to_copy) { + return * this; + } + + delete[] _mime; + + _mime = new uint8_t[to_copy.mime_size()]; + memcpy(_mime, to_copy._mime, to_copy.mime_size()); + _type_size = to_copy._type_size; + _content_size = to_copy._content_size; + + return *this; +} + +void Mime::set_mime( + const Span &mime_type, + const Span &content +) +{ + delete[] _mime; + + _mime = new uint8_t[mime_type.size() + content.size()]; + memcpy(_mime, mime_type.data(), mime_type.size()); + memcpy(_mime + mime_type.size(), content.data(), content.size()); + _type_size = mime_type.size(); + _content_size = content.size(); +} + +Span Mime::get_mime_type() const +{ + return make_const_Span(_mime, _type_size); +} + +Span Mime::get_mime_content() const +{ + return make_const_Span(_mime + _type_size, _content_size); +} + +bool Mime::append_as_record( + MessageBuilder &message_builder, + bool is_last_record +) const +{ + return message_builder.append_record( + RecordType( + RecordType::media_type, + get_mime_type() + ), + get_mime_content(), + is_last_record + ); +} + +size_t Mime::get_record_size() const +{ + return MessageBuilder::compute_record_size( + Record( + RecordType( + RecordType::media_type, + get_mime_type() + ), + get_mime_content(), + RecordID(), + /* chunk */ false, + /* last record */ false + ) + ); +} + +void Mime::move_data( + uint8_t *mime_record, + size_t mime_type_size, + size_t mime_content_size +) +{ + delete[] _mime; + _mime = mime_record; + _type_size = mime_type_size; + _content_size = mime_content_size; +} + +size_t Mime::mime_size() const +{ + return _type_size + _content_size; +} + +bool MimeParser::do_parse(const Record &record, Mime &mime) +{ + if (record.type.tnf != RecordType::media_type) { + return false; + } + + // A type and a payload should be present + if (record.type.value.empty() || record.payload.empty()) { + return false; + } + + // create the buffer + size_t type_size = record.type.value.size(); + size_t content_size = record.payload.size(); + uint8_t *mime_buffer = new uint8_t[type_size + content_size]; + + // copy type + memcpy(mime_buffer, record.type.value.data(), type_size); + + // copy content + memcpy(mime_buffer + type_size, record.payload.data(), content_size); + + mime.move_data(mime_buffer, type_size, content_size); + + return true; +} + +} // namespace common +} // namespace ndef +} // namespace nfc +} // namespace mbed diff --git a/connectivity/nfc/source/ndef/common/SimpleMessageParser.cpp b/connectivity/nfc/source/ndef/common/SimpleMessageParser.cpp new file mode 100644 index 0000000..5f0db5a --- /dev/null +++ b/connectivity/nfc/source/ndef/common/SimpleMessageParser.cpp @@ -0,0 +1,124 @@ +/* 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 "nfc/ndef/common/SimpleMessageParser.h" + +namespace mbed { +namespace nfc { +namespace ndef { +namespace common { + +SimpleMessageParser::SimpleMessageParser() : + _message_parser(), + _record_parser_chain(), + _uri_parser(), + _text_parser(), + _mime_parser(), + _delegate(NULL) +{ + // setup the parser chain + _record_parser_chain.set_next_parser(&_uri_parser); + _record_parser_chain.set_next_parser(&_text_parser); + _record_parser_chain.set_next_parser(&_mime_parser); + + // wire event handling + _message_parser.set_delegate(this); + _uri_parser.set_delegate(this); + _text_parser.set_delegate(this); + _mime_parser.set_delegate(this); +} + +void SimpleMessageParser::set_delegate(Delegate *delegate) +{ + _delegate = delegate; +} + +void SimpleMessageParser::parse(const Span &data_buffer) +{ + _message_parser.parse(data_buffer); +} + +void SimpleMessageParser::add_record_parser(RecordParser *parser) +{ + _record_parser_chain.set_next_parser(parser); +} + +void SimpleMessageParser::on_parsing_error(MessageParser::error_t error) +{ + if (_delegate) { + _delegate->on_parsing_error(error); + } +} + +void SimpleMessageParser::on_parsing_started() +{ + if (_delegate) { + _delegate->on_parsing_started(); + } +} + +void SimpleMessageParser::on_record_parsed(const Record &record) +{ + bool parsed = _record_parser_chain.parse(record); + + if (!parsed && _delegate) { + _delegate->on_unknown_record_parsed(record); + } +} + +void SimpleMessageParser::on_parsing_terminated() +{ + if (_delegate) { + _delegate->on_parsing_terminated(); + } +} + +void SimpleMessageParser::on_record_parsed( + const URI &uri, + const RecordID &id +) +{ + if (_delegate) { + _delegate->on_uri_parsed(uri, id); + } +} + +void SimpleMessageParser::on_record_parsed( + const Text &text, + const RecordID &id +) +{ + if (_delegate) { + _delegate->on_text_parsed(text, id); + } +} + +void SimpleMessageParser::on_record_parsed( + const Mime &mime, + const RecordID &id +) +{ + if (_delegate) { + _delegate->on_mime_parsed(mime, id); + } +} + +} // namespace common +} // namespace ndef +} // namespace nfc +} // namespace mbed + + diff --git a/connectivity/nfc/source/ndef/common/Text.cpp b/connectivity/nfc/source/ndef/common/Text.cpp new file mode 100644 index 0000000..6ea37be --- /dev/null +++ b/connectivity/nfc/source/ndef/common/Text.cpp @@ -0,0 +1,208 @@ +/* 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 + +#include "nfc/ndef/common/Text.h" + +namespace { +static const uint8_t utf16_encoding_bit = (1 << 7); +static const uint8_t language_code_size_mask = 0x3F; +static const uint8_t header_index = 0; +static const uint8_t language_code_index = 1; +static const uint8_t header_size = 1; +static const uint8_t text_record_type_value[] = { 'T' }; +} + +namespace mbed { +namespace nfc { +namespace ndef { +namespace common { + +Text::Text() : + _text_record(NULL), + _text_record_size(0) +{ } + +Text::Text(const Text &other) : + _text_record(other._text_record ? new uint8_t[other._text_record_size] : NULL), + _text_record_size(other._text_record_size) +{ + if (_text_record) { + memcpy(_text_record, other._text_record, _text_record_size); + } +} + +Text::Text( + encoding_t text_encoding, + const Span &language_code, + const Span &text +) : _text_record(NULL), + _text_record_size(0) +{ + set_text(text_encoding, language_code, text); +} + +Text::~Text() +{ + delete[] _text_record; +} + +Text &Text::operator=(const Text &other) +{ + if (this == &other) { + return *this; + } + + _text_record_size = other._text_record_size; + + delete[] _text_record; + if (!other._text_record) { + _text_record = NULL; + } else { + _text_record = new uint8_t[_text_record_size]; + memcpy(_text_record, other._text_record, _text_record_size); + } + + return *this; +} + +void Text::set_text( + encoding_t text_encoding, + const Span &language_code, + const Span &text +) +{ + delete[] _text_record; + + _text_record_size = header_size + language_code.size() + text.size(); + _text_record = new uint8_t[_text_record_size]; + + // build the header + _text_record[header_index] = 0; + if (text_encoding == UTF16) { + _text_record[header_index] |= utf16_encoding_bit; + } + _text_record[header_index] |= language_code.size(); + + // language code + memcpy(_text_record + language_code_index, language_code.data(), language_code.size()); + + // actual text + memcpy(_text_record + language_code_index + language_code.size(), text.data(), text.size()); +} + +Text::encoding_t Text::get_encoding() const +{ + return (_text_record[header_index] & utf16_encoding_bit) ? UTF16 : UTF8; +} + +Span Text::get_language_code() const +{ + return make_const_Span( + _text_record + language_code_index, + _text_record[header_index] & language_code_size_mask + ); +} + +Span Text::get_text() const +{ + if (!_text_record) { + return Span(); + } + + size_t language_code_size = get_language_code().size(); + + return make_const_Span( + _text_record + header_size + language_code_size, + _text_record_size - header_size - language_code_size + ); +} + +void Text::move_data(uint8_t *text, size_t size) +{ + delete[] _text_record; + _text_record = text; + _text_record_size = size; +} + +bool Text::append_as_record( + MessageBuilder &message_builder, + bool is_last_record +) const +{ + if (!_text_record) { + return false; + } + + // Build the record type + RecordType type( + RecordType::well_known_type, + text_record_type_value + ); + + // build the record payload + RecordPayload payload(_text_record, _text_record_size); + return message_builder.append_record(type, payload, is_last_record); +} + +size_t Text::get_record_size() const +{ + if (!_text_record) { + return 0; + } + + return MessageBuilder::compute_record_size( + Record( + RecordType( + RecordType::well_known_type, + text_record_type_value + ), + RecordPayload(_text_record, _text_record_size), + RecordID(), + /* chunk */ false, + /* last record */ false + ) + ); +} + +bool TextParser::do_parse(const Record &record, Text &text) +{ + if (record.type.tnf != RecordType::well_known_type) { + return false; + } + + // the record type value should be equal to `T` + if (record.type.value != make_const_Span(text_record_type_value) || + record.payload.empty() + ) { + return false; + } + + // create the buffer + size_t text_record_size = record.payload.size(); + uint8_t *text_record = new uint8_t[text_record_size]; + memcpy(text_record, record.payload.data(), text_record_size); + + text.move_data(text_record, text_record_size); + + return true; +} + +} // namespace common +} // namespace ndef +} // namespace nfc +} // namespace mbed diff --git a/connectivity/nfc/source/ndef/common/URI.cpp b/connectivity/nfc/source/ndef/common/URI.cpp new file mode 100644 index 0000000..4761251 --- /dev/null +++ b/connectivity/nfc/source/ndef/common/URI.cpp @@ -0,0 +1,191 @@ +/* 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 + +#include "nfc/ndef/common/URI.h" + +namespace { +static const uint8_t uri_id_code_size = 1; +static const uint8_t uri_id_index = 0; +static const uint8_t uri_field_index = 1; +static const uint8_t uri_record_type_value[] = { 'U' } ; +} + +namespace mbed { +namespace nfc { +namespace ndef { +namespace common { + +URI::URI() : + _uri(NULL), + _uri_size(0) +{ +} + +URI::URI(uri_identifier_code_t id, const Span &uri_field) : + _uri(uri_field.size() ? new uint8_t[uri_id_code_size + uri_field.size()] : NULL), + _uri_size(uri_id_code_size + uri_field.size()) +{ + if (_uri) { + _uri[uri_id_index] = id; + memcpy(_uri + uri_field_index, uri_field.data(), uri_field.size()); + } +} + +URI::URI(const URI &other) : + _uri(other._uri ? new uint8_t[other._uri_size] : NULL), + _uri_size(other._uri_size) +{ + if (_uri) { + memcpy(_uri, other._uri, other._uri_size); + } +} + +URI::~URI() +{ + delete[] _uri; +} + +URI &URI::operator=(const URI &other) +{ + delete[] _uri; + + if (!other._uri) { + _uri = NULL; + _uri_size = 0; + } else { + _uri = new uint8_t[other._uri_size]; + _uri_size = other._uri_size; + memcpy(_uri, other._uri, other._uri_size); + } + + return *this; +} + +void URI::set_uri( + uri_identifier_code_t id, + const Span &uri_field +) +{ + delete[] _uri; + + if (uri_field.empty()) { + _uri = NULL; + _uri_size = 0; + return; + } + + _uri = new uint8_t[uri_id_code_size + uri_field.size()]; + _uri_size = uri_id_code_size + uri_field.size(); + _uri[uri_id_index] = id; + memcpy(_uri + uri_field_index, uri_field.data(), uri_field.size()); +} + +URI::uri_identifier_code_t URI::get_id() const +{ + if (!_uri) { + return NA; + } + + return static_cast(_uri[uri_id_index]); +} + +Span URI::get_uri_field() const +{ + if (!_uri) { + return Span(); + } + return make_const_Span( + _uri + uri_field_index, + _uri_size - uri_id_code_size + ); +} + +bool URI::append_as_record(MessageBuilder &message_builder, bool is_last_record) const +{ + if (!_uri) { + return false; + } + + // Build the record type + RecordType type( + RecordType::well_known_type, + uri_record_type_value + ); + + // build the record payload + RecordPayload payload(_uri, _uri_size); + + return message_builder.append_record(type, payload, is_last_record); +} + +size_t URI::get_record_size() const +{ + if (!_uri) { + return 0; + } + + return MessageBuilder::compute_record_size( + Record( + RecordType( + RecordType::well_known_type, + uri_record_type_value + ), + RecordPayload(_uri, _uri_size), + RecordID(), + /* chunk */ false, + /* last record */ false + ) + ); +} + +void URI::move_data(uint8_t *new_uri, size_t new_uri_size) +{ + delete[] _uri; + _uri = new_uri; + _uri_size = new_uri_size; +} + +bool URIParser::do_parse(const Record &record, URI &uri) +{ + if (record.type.tnf != RecordType::well_known_type) { + return false; + } + + // the record type value should be equal to `U` + if (record.type.value != make_const_Span(uri_record_type_value) || + record.payload.empty() + ) { + return false; + } + + // create the buffer + size_t uri_record_size = record.payload.size(); + uint8_t *uri_record = new uint8_t[uri_record_size]; + memcpy(uri_record, record.payload.data(), uri_record_size); + + uri.move_data(uri_record, uri_record_size); + + return true; +} + +} // namespace common +} // namespace ndef +} // namespace nfc +} // namespace mbed + + diff --git a/connectivity/nfc/source/ndef/common/util.cpp b/connectivity/nfc/source/ndef/common/util.cpp new file mode 100644 index 0000000..27a2b40 --- /dev/null +++ b/connectivity/nfc/source/ndef/common/util.cpp @@ -0,0 +1,39 @@ +/* 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 + +#include "nfc/ndef/common/util.h" + +namespace mbed { +namespace nfc { +namespace ndef { +namespace common { + +Span span_from_cstr(const char *cstr) +{ + return Span((const uint8_t *)cstr, strlen(cstr)); +} + +/** + * @} + */ + +} // namespace common +} // namespace ndef +} // namespace nfc +} // namespace mbed + diff --git a/connectivity/nfc/tests/TESTS/nfc/eeprom/main.cpp b/connectivity/nfc/tests/TESTS/nfc/eeprom/main.cpp new file mode 100644 index 0000000..c8d40a0 --- /dev/null +++ b/connectivity/nfc/tests/TESTS/nfc/eeprom/main.cpp @@ -0,0 +1,501 @@ +/* + * Copyright (c) 2017, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * 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 "mbed.h" +#include "greentea-client/test_env.h" +#include "unity.h" +#include "utest.h" + +#include +#include "NFCEEPROMDriver.h" + +#if !MBED_CONF_NFCEEPROM +#error [NOT_SUPPORTED] NFC EEPROM not supported for this target +#else + +using namespace utest::v1; +using namespace mbed::nfc; + +/* individual steps that map to specific operations that include parameters */ +typedef enum { + START_SESSION = 0x0000, + + END_SESSION = 0x0100, + + READ_BYTES = 0x0200, + READ_2_BYTES = 0x0201, + READ_2_BYTES_OFFSET_FAIL = 0x0202, + READ_4_BYTES = 0x0203, + READ_4_BYTES_MIXED = 0x0204, + READ_4_BYTES_OFFSET = 0x0205, + READ_4_BYTES_ERASED = 0x0206, + READ_4_BYTES_FAIL = 0x0207, + + WRITE_BYTES = 0x0300, + WRITE_2_BYTES = 0x0301, + WRITE_2_BYTES_OFFSET = 0x0302, + WRITE_2_BYTES_OFFSET_FAIL = 0x0303, + WRITE_4_BYTES = 0x0304, + WRITE_4_BYTES_FAIL = 0x0305, + + ERASE_BYTES = 0x0400, + ERASE_4_BYTES = 0x0401, + + READ_SIZE = 0x0500, + READ_SIZE_2 = 0x0501, + READ_SIZE_4 = 0x0502, + + WRITE_SIZE = 0x0600, + WRITE_SIZE_2 = 0x0601, + WRITE_SIZE_4 = 0x0602, + + TERMINATE = 0xFF00 +} TestCommand_t; + +/* We group the command based on their first byte to simplify step checking. + * Individual conditions of a step are checked in the event so this doesn't + * sacrifice any correctness checking */ +const size_t TEST_COMMAND_GROUP_MASK = 0xFF00; + +/* test case sequences that index into the array of commands which comprise them */ +typedef enum { + SESSION_TEST, + WRITE_READ_TEST, + ERASE_TEST, + WRITE_READ_SIZE_TEST, + TRUNCATE_TEST, + WRITE_TRUNCATE_TEST, + WRITE_WITH_OFFSET_TEST, + WRITE_BEYOND_SIZE_TEST, + SEQUENCE_MAX +} TestSequence_t; + +static EventQueue event_queue(/* event count */ 10 * EVENTS_EVENT_SIZE); + +static const size_t MAX_STEP = 10; +static const size_t BUFFER_MAX = 10; + +/* defines the "script" the test follows, each step is checked and all + * have to execute to completion for a successful run */ +static const TestCommand_t SEQUENCES[SEQUENCE_MAX][MAX_STEP] = { + /* SESSION_TEST */ + { START_SESSION, END_SESSION, TERMINATE }, + + /* WRITE_READ_TEST */ + { + START_SESSION, WRITE_SIZE_4, READ_SIZE_4, WRITE_4_BYTES, READ_4_BYTES, + WRITE_2_BYTES, READ_4_BYTES_MIXED, END_SESSION, TERMINATE + }, + + /* ERASE_TEST */ + { + START_SESSION, WRITE_SIZE_4, READ_SIZE_4, WRITE_4_BYTES, READ_4_BYTES, + ERASE_4_BYTES, READ_4_BYTES_ERASED, END_SESSION, TERMINATE + }, + + /* WRITE_READ_SIZE_TEST */ + { + START_SESSION, WRITE_SIZE_2, READ_SIZE_2, WRITE_SIZE_4, READ_SIZE_4, + END_SESSION, TERMINATE + }, + + /* TRUNCATE_TEST */ + { + START_SESSION, WRITE_SIZE_4, READ_SIZE_4, WRITE_4_BYTES, READ_4_BYTES, + WRITE_SIZE_2, READ_SIZE_2, READ_4_BYTES_FAIL, END_SESSION, TERMINATE + }, + + /* WRITE_TRUNCATE_TEST */ + { + START_SESSION, WRITE_SIZE_2, READ_SIZE_2, WRITE_4_BYTES_FAIL, READ_4_BYTES_FAIL, + END_SESSION, TERMINATE + }, + + /* WRITE_WITH_OFFSET_TEST */ + { + START_SESSION, WRITE_SIZE_4, READ_SIZE_4, WRITE_4_BYTES, READ_4_BYTES, + WRITE_2_BYTES_OFFSET, READ_4_BYTES_OFFSET, END_SESSION, TERMINATE + }, + + /* WRITE_BEYOND_SIZE_TEST */ + { + START_SESSION, WRITE_SIZE_2, READ_SIZE_2, WRITE_2_BYTES_OFFSET_FAIL, READ_2_BYTES_OFFSET_FAIL, + WRITE_2_BYTES, READ_2_BYTES, END_SESSION, TERMINATE + } +}; + +static const uint8_t DATA_4_BYTES[] = { 0x01, 0x02, 0x03, 0x04 }; +static const uint8_t DATA_2_BYTES[] = { 0x05, 0x06 }; +static const uint8_t DATA_4_BYTES_MIXED[] = { 0x05, 0x06, 0x03, 0x04 }; +static const uint8_t DATA_4_BYTES_OFFSET[] = { 0x01, 0x02, 0x05, 0x06 }; +static const uint8_t DATA_4_BYTES_ERASED[] = { 0x00, 0x00, 0x00, 0x00 }; + +class DriverTest : public NFCEEPROMDriver::Delegate { +public: + DriverTest(NFCEEPROMDriver *_driver) + : _operation_data(NULL), + _driver(_driver), + _sequence(SEQUENCE_MAX), + _step(0), + _result_size(0), + _address(0), + _success(true) { }; + + virtual ~DriverTest() { }; + + /* Delegate events */ + + virtual void on_session_started(bool success) + { + if (success != _success) { + TEST_FAIL_MESSAGE("failed to start session"); + } + + evaluate_step(START_SESSION); + }; + + virtual void on_session_ended(bool success) + { + if (success != _success) { + TEST_FAIL_MESSAGE("failed to end session"); + } + + evaluate_step(END_SESSION); + }; + + virtual void on_bytes_read(size_t count) + { + if (count != _result_size) { + TEST_FAIL_MESSAGE("failed to read bytes"); + } + if (memcmp(_buffer, _operation_data, count) != 0) { + TEST_FAIL_MESSAGE("read bytes are different than expected"); + } + + evaluate_step(READ_BYTES); + }; + + virtual void on_bytes_written(size_t count) + { + if (count != _result_size) { + TEST_FAIL_MESSAGE("failed to write bytes"); + } + + evaluate_step(WRITE_BYTES); + }; + + virtual void on_size_written(bool success) + { + if (success != _success) { + TEST_FAIL_MESSAGE("failed to write size"); + } + + evaluate_step(WRITE_SIZE); + }; + + virtual void on_size_read(bool success, size_t size) + { + if (success != _success || size != _result_size) { + TEST_FAIL_MESSAGE("failed to read size"); + } + + evaluate_step(READ_SIZE); + }; + + virtual void on_bytes_erased(size_t count) + { + if (count != _result_size) { + TEST_FAIL_MESSAGE("failed to erase bytes"); + } + + evaluate_step(ERASE_BYTES); + } + + /* Sequence running code */ + + void run_sequence(TestSequence_t sequence) + { + _sequence = sequence; + + if (_sequence >= SEQUENCE_MAX) { + TEST_FAIL_MESSAGE("internal test failure - invalid command"); + } + + execute_next_step(); + + event_queue.dispatch_forever(); + + TEST_ASSERT_EQUAL(TERMINATE, SEQUENCES[_sequence][_step]); + } + + void execute_next_step() + { + TestCommand_t command = SEQUENCES[_sequence][_step]; + + /* setup data buffer */ + switch (command) { + case READ_2_BYTES: + case READ_2_BYTES_OFFSET_FAIL: + case WRITE_2_BYTES: + case WRITE_2_BYTES_OFFSET: + case WRITE_2_BYTES_OFFSET_FAIL: + _operation_data = DATA_2_BYTES; + break; + case READ_4_BYTES: + case READ_4_BYTES_FAIL: + case WRITE_4_BYTES: + case WRITE_4_BYTES_FAIL: + _operation_data = DATA_4_BYTES; + break; + case READ_4_BYTES_ERASED: + _operation_data = DATA_4_BYTES_ERASED; + break; + case READ_4_BYTES_MIXED: + _operation_data = DATA_4_BYTES_MIXED; + break; + case READ_4_BYTES_OFFSET: + _operation_data = DATA_4_BYTES_OFFSET; + break; + default: + _operation_data = NULL; + } + + /* setup result size */ + switch (command) { + case READ_2_BYTES: + case READ_4_BYTES_FAIL: + case WRITE_2_BYTES: + case WRITE_4_BYTES_FAIL: + case WRITE_2_BYTES_OFFSET: + case READ_SIZE_2: + _result_size = 2; + break; + case READ_4_BYTES: + case READ_4_BYTES_ERASED: + case READ_4_BYTES_MIXED: + case READ_4_BYTES_OFFSET: + case WRITE_4_BYTES: + case ERASE_4_BYTES: + case READ_SIZE_4: + _result_size = 4; + break; + default: + _result_size = 0; + } + + /* setup operation size */ + switch (command) { + case READ_2_BYTES: + case READ_2_BYTES_OFFSET_FAIL: + case WRITE_2_BYTES: + case WRITE_2_BYTES_OFFSET: + case WRITE_2_BYTES_OFFSET_FAIL: + case WRITE_SIZE_2: + _operation_size = 2; + break; + case READ_4_BYTES: + case READ_4_BYTES_ERASED: + case READ_4_BYTES_MIXED: + case READ_4_BYTES_OFFSET: + case READ_4_BYTES_FAIL: + case WRITE_4_BYTES: + case WRITE_4_BYTES_FAIL: + case ERASE_4_BYTES: + case READ_SIZE_4: + case WRITE_SIZE_4: + _operation_size = 4; + break; + default: + _operation_size = 0; + } + + /* setup offset */ + switch (command) { + case READ_2_BYTES_OFFSET_FAIL: + case WRITE_2_BYTES_OFFSET: + case WRITE_2_BYTES_OFFSET_FAIL: + _address = 2; + break; + default: + _address = 0; + } + + /* setup command success */ + switch (command) { + case READ_2_BYTES_OFFSET_FAIL: + case WRITE_2_BYTES_OFFSET_FAIL: + _success = false; + break; + default: + _success = true; + } + + /* call next command */ + switch (command & TEST_COMMAND_GROUP_MASK) { + case START_SESSION: + _driver->start_session(true); + break; + case END_SESSION: + _driver->end_session(); + break; + case READ_BYTES: + _driver->read_bytes(_address, _buffer, _operation_size); + break; + case WRITE_BYTES: + _driver->write_bytes(_address, _operation_data, _operation_size); + break; + case ERASE_BYTES: + _driver->erase_bytes(_address, _operation_size); + break; + case READ_SIZE: + _driver->read_size(); + break; + case WRITE_SIZE: + _driver->write_size(_operation_size); + break; + case TERMINATE: + event_queue.break_dispatch(); + break; + default: + TEST_FAIL_MESSAGE("internal test failure - invalid command"); + } + } + + void evaluate_step(TestCommand_t command_completed) + { + /* check last command succeeded */ + TEST_ASSERT_EQUAL(command_completed, SEQUENCES[_sequence][_step]&TEST_COMMAND_GROUP_MASK); + + _step++; + + if (_step == MAX_STEP) { + TEST_FAIL_MESSAGE("internal test failure - too many steps"); + } + + execute_next_step(); + } + +private: + uint8_t _buffer[BUFFER_MAX]; + const uint8_t *_operation_data; + + NFCEEPROMDriver *_driver; + + TestSequence_t _sequence; + size_t _step; + size_t _result_size; + size_t _operation_size; + size_t _address; + bool _success; +}; + +/* test case running code */ + +static DriverTest *driver_test; +extern NFCEEPROMDriver *greentea_nfc_EEPROM_driver_get_instance(); + +utest::v1::status_t test_setup(const Case *const source, const size_t index_of_case) +{ + NFCEEPROMDriver *driver = greentea_nfc_EEPROM_driver_get_instance(); + driver_test = new DriverTest(driver); + + driver->set_event_queue(&event_queue); + driver->set_delegate(driver_test); + driver->reset(); + + TEST_ASSERT_NOT_EQUAL(0, driver->read_max_size()); + + return greentea_case_setup_handler(source, index_of_case); +} + +void session() +{ + driver_test->run_sequence(SESSION_TEST); +} + +void write_read() +{ + driver_test->run_sequence(WRITE_READ_TEST); +} + +void erase_bytes() +{ + driver_test->run_sequence(ERASE_TEST); +} + +void write_read_size() +{ + driver_test->run_sequence(WRITE_READ_SIZE_TEST); +} + +void truncate_size() +{ + driver_test->run_sequence(TRUNCATE_TEST); +} + +void write_bytes_truncated() +{ + driver_test->run_sequence(WRITE_TRUNCATE_TEST); +} + +void write_with_offset() +{ + driver_test->run_sequence(WRITE_WITH_OFFSET_TEST); +} + +void write_beyond_size() +{ + driver_test->run_sequence(WRITE_BEYOND_SIZE_TEST); +} + +utest::v1::status_t test_tear_down(const Case *const source, const size_t passed, + const size_t failed, const failure_t reason) +{ + delete driver_test; + + return greentea_case_teardown_handler(source, passed, failed, reason); +} + +/* test setup */ + +utest::v1::status_t test_init(const size_t number_of_cases) +{ + GREENTEA_SETUP(10, "default_auto"); + return greentea_test_setup_handler(number_of_cases); +} + +// Test cases +Case cases[] = { + Case("NFCEEPROM-SESSION", test_setup, session, test_tear_down), + Case("NFCEEPROM-WRITE-READ", test_setup, write_read, test_tear_down), + Case("NFCEEPROM-ERASE-BYTES", test_setup, erase_bytes, test_tear_down), + Case("NFCEEPROM-WRITE-READ-SIZE", test_setup, write_read_size, test_tear_down), + Case("NFCEEPROM-TRUNCATE-SIZE", test_setup, truncate_size, test_tear_down), + Case("NFCEEPROM-WRITE-BYTES-TRUNCATED", test_setup, write_bytes_truncated, test_tear_down), + Case("NFCEEPROM-WRITE-WITH-OFFSET", test_setup, write_with_offset, test_tear_down), + Case("NFCEEPROM-WRITE-BEYOND-SIZE", test_setup, write_beyond_size, test_tear_down) +}; + +Specification specification(test_init, cases); + +// Entry point into the tests +int main() +{ + return !Harness::run(specification); +} + +#endif // !MBED_CONF_NFCEEPROM diff --git a/features/nfc/acore/acore/ac_buffer.h b/features/nfc/acore/acore/ac_buffer.h deleted file mode 100644 index 68b84f6..0000000 --- a/features/nfc/acore/acore/ac_buffer.h +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (c) 2017, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * 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. - */ -/** - * \file ac_buffer.h - * \copyright Copyright (c) ARM Ltd 2013 - * \author Donatien Garnier - */ - -/** \addtogroup ACore - * @{ - * \name Buffer - * @{ - */ - -#ifndef ACORE_BUFFER_H_ -#define ACORE_BUFFER_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "stdint.h" -#include "stddef.h" -#include "stdbool.h" - -typedef struct __ac_buffer { - const uint8_t *data; - size_t size; - struct __ac_buffer *pNext; -} ac_buffer_t; - -/** Initialize ac_buffer using underlying byte array, set ac_buffer's length to 0 (empty) - * \param pBuf pointer to ac_buffer_t structure to initialize - * \param data byte array to use - * \param size size of byte array - */ -void ac_buffer_init(ac_buffer_t *pBuf, const uint8_t *data, size_t size); - -/** Copy pBufIn to pBuf - * \param pBuf pointer to ac_buffer_t structure to initialize - * \param pBufIn the source buffer - */ -void ac_buffer_dup(ac_buffer_t *pBuf, const ac_buffer_t *pBufIn); - -/** Get buffer's underlying byte array - * \param pBuf pointer to ac_buffer_t structure - * \return underlying array - */ -static inline const uint8_t *ac_buffer_data(const ac_buffer_t *pBuf) -{ - return pBuf->data; -} - -/** Get buffer's size - * \param pBuf pointer to ac_buffer_t structure - * \return buffer's size - */ -static inline size_t ac_buffer_size(const ac_buffer_t *pBuf) -{ - return pBuf->size; -} - -/** Get next buffer in chain - * \param pBuf pointer to ac_buffer_t structure - * \return pointer to next buffer - */ -static inline ac_buffer_t *ac_buffer_next(const ac_buffer_t *pBuf) -{ - return pBuf->pNext; -} - -/** Set next buffer in chain - * \param pBuf pointer to ac_buffer_t structure - * \param pNextBuf pointer to next buffer (or NULL to break chain) - */ -static inline void ac_buffer_set_next(ac_buffer_t *pBuf, ac_buffer_t *pNextBuf) -{ - pBuf->pNext = (ac_buffer_t *) pNextBuf; -} - -/** Append buffer to end of chain - * \param pBuf pointer to ac_buffer_t structure - * \param pAppBuf pointer to buffer to append to chain - */ -void ac_buffer_append(ac_buffer_t *pBuf, ac_buffer_t *pAppBuf); - -/** Truncate pBuf to length bytes and save the remaining bytes in pEndBuf - * \param pBuf The buffer to split (will be set to invalid state) - * \param pStartBuf A new buffer at the head of the split - * \param pEndBuf A new buffer at the tail of the split - * \param length How long pStartBuf should be (if longer than pBuf, then pStartBuf will be pBuf) - */ -void ac_buffer_split(ac_buffer_t *pStartBuf, ac_buffer_t *pEndBuf, ac_buffer_t *pBuf, size_t length); - -//Debug -void ac_buffer_dump(ac_buffer_t *pBuf); - -#ifdef __cplusplus -} -#endif - -#endif /* ACORE_BUFFER_H_ */ - -/** - * @} - * @} - * */ diff --git a/features/nfc/acore/acore/ac_buffer_builder.h b/features/nfc/acore/acore/ac_buffer_builder.h deleted file mode 100644 index 946b178..0000000 --- a/features/nfc/acore/acore/ac_buffer_builder.h +++ /dev/null @@ -1,370 +0,0 @@ -/* - * Copyright (c) 2017, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * 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. - */ -/** - * \file ac_buffer_builder.h - * \copyright Copyright (c) ARM Ltd 2017 - * \author Donatien Garnier - */ - -/** \addtogroup ACore - * @{ - * \name Buffer Builder - * @{ - */ - -#ifndef ACORE_BUFFER_BUILDER_H_ -#define ACORE_BUFFER_BUILDER_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "stdint.h" -#include "stddef.h" -#include "stdbool.h" - -#include "acore/ac_buffer.h" - -typedef struct __ac_buffer_builder { - ac_buffer_t ac_buffer; - uint8_t *data; - size_t size; -} ac_buffer_builder_t; - -/** Write data to big endian ac_buffer (on a LE architecture, byte order will be swapped) - * \param pBuilder ac_buffer builder to use - * \param buf pointer to data - * \param size the data size - */ -void ac_buffer_builder_write_be(ac_buffer_builder_t *pBuilder, const uint8_t *buf, size_t size); - -/** Write data to little endian ac_buffer (on a LE architecture, byte order will be preserved) - * \param pBuilder ac_buffer builder to use - * \param buf pointer to data - * \param size the data size - */ -void ac_buffer_builder_write_le(ac_buffer_builder_t *pBuilder, const uint8_t *buf, size_t size); - -/** Write data to big endian ac_buffer at specific position (on a LE architecture, byte order will be swapped) - * \param pBuilder ac_buffer builder to use - * \param pos position in ac_buffer to write from - * \param buf pointer to data - * \param size the data size - */ -void ac_buffer_builder_write_be_at(ac_buffer_builder_t *pBuilder, size_t pos, const uint8_t *buf, size_t size); - -/** Write data to little endian ac_buffer at specific position (on a LE architecture, byte order will be preserved) - * \param pBuilder ac_buffer builder to use - * \param pos position in ac_buffer to write from - * \param buf pointer to data - * \param size the data size - */ -void ac_buffer_builder_write_le_at(ac_buffer_builder_t *pBuilder, size_t pos, const uint8_t *buf, size_t size); - -/** Initialize ac_buffer builder - * \param pBuilder ac_buffer builder to init - * \param data pointer to byte array to use - * \param size of byte array - */ -void ac_buffer_builder_init(ac_buffer_builder_t *pBuilder, uint8_t *data, size_t size); - -/** Initialize ac_buffer builder from underlying ac_buffer - * \param pBuilder ac_buffer builder to init - */ -void ac_buffer_builder_from_buffer(ac_buffer_builder_t *pBuilder); - -/** Reset ac_buffer builder - * \param pBuilder ac_buffer builder to reset - */ -void ac_buffer_builder_reset(ac_buffer_builder_t *pBuilder); - -/** Set ac_buffer builder's ac_buffer to full size - * \param pBuilder ac_buffer builder to set to full size - */ -void ac_buffer_builder_set_full(ac_buffer_builder_t *pBuilder); - -/** Get ac_buffer builder's length - * \param pBuilder ac_buffer builder to get length of - * \return number of valid bytes in ac_buffer - */ -static inline size_t ac_buffer_builder_length(ac_buffer_builder_t *pBuilder) -{ - return ac_buffer_size(&pBuilder->ac_buffer); -} - -/** Set ac_buffer builder's length - * \param pBuilder ac_buffer builder to set length of - * \param length number of valid bytes in ac_buffer - */ -static inline void ac_buffer_builder_set_length(ac_buffer_builder_t *pBuilder, size_t length) -{ - if (ac_buffer_data(&pBuilder->ac_buffer) + length > pBuilder->data + pBuilder->size) { - return; - } - pBuilder->ac_buffer.size = length; -} - -/** Get ac_buffer builder's pointer to write position - * \param pBuilder ac_buffer builder - * \return pointer to write position - */ -static inline uint8_t *ac_buffer_builder_write_position(ac_buffer_builder_t *pBuilder) -{ - return (uint8_t *)ac_buffer_data(&pBuilder->ac_buffer) + ac_buffer_size(&pBuilder->ac_buffer); -} - -/** Get ac_buffer builder's write offset - * \param pBuilder ac_buffer builder - * \return write offset - */ -static inline size_t ac_buffer_builder_write_offset(ac_buffer_builder_t *pBuilder) -{ - return ac_buffer_data(&pBuilder->ac_buffer) + ac_buffer_size(&pBuilder->ac_buffer) - pBuilder->data; -} - -/** Set ac_buffer builder's write offset - * \param pBuilder ac_buffer builder - * \param off new write offset - */ -static inline void ac_buffer_builder_set_write_offset(ac_buffer_builder_t *pBuilder, size_t off) -{ - if (off > pBuilder->size) { - return; - } - if (pBuilder->data + off > pBuilder->ac_buffer.data) { - pBuilder->ac_buffer.size = off - (pBuilder->ac_buffer.data - pBuilder->data); - } else { - pBuilder->ac_buffer.size = 0; - } -} - -/** Get ac_buffer builder's read offset - * \param pBuilder ac_buffer builder - * \return read offset - */ -static inline size_t ac_buffer_builder_read_offset(ac_buffer_builder_t *pBuilder) -{ - return ac_buffer_data(&pBuilder->ac_buffer) - pBuilder->data; -} - -/** Set ac_buffer builder's read offset - * \param pBuilder ac_buffer builder - * \param off new read offset - */ -static inline void ac_buffer_builder_set_read_offset(ac_buffer_builder_t *pBuilder, size_t off) -{ - if (off > pBuilder->size) { - return; - } - if (pBuilder->data + off < pBuilder->ac_buffer.data + pBuilder->ac_buffer.size) { - pBuilder->ac_buffer.size = pBuilder->ac_buffer.data - (pBuilder->data + off); - } else { - pBuilder->ac_buffer.size = 0; - } - pBuilder->ac_buffer.data = pBuilder->data + off; -} - -/** Get ac_buffer builder's underlying ac_buffer - * \param pBuilder ac_buffer builder - * \return ac_buffer - */ -static inline ac_buffer_t *ac_buffer_builder_buffer(ac_buffer_builder_t *pBuilder) -{ - return &pBuilder->ac_buffer; -} - -/** Get space in ac_buffer builder - * \param pBuilder ac_buffer builder - * \return number of free bytes in ac_buffer builder - */ -static inline size_t ac_buffer_builder_space(ac_buffer_builder_t *pBuilder) -{ - return pBuilder->size - (ac_buffer_data(&pBuilder->ac_buffer) - pBuilder->data + ac_buffer_size(&pBuilder->ac_buffer)); -} - -/** Is ac_buffer builder empty - * \param pBuilder ac_buffer builder - * \return true if ac_buffer builder is empty - */ -static inline bool ac_buffer_builder_empty(ac_buffer_builder_t *pBuilder) -{ - return (ac_buffer_builder_length(pBuilder) == 0); -} - -/** Is ac_buffer builder full - * \param pBuilder ac_buffer builder - * \return true if ac_buffer builder is full - */ -static inline bool ac_buffer_full(ac_buffer_builder_t *pBuilder) -{ - return (ac_buffer_builder_space(pBuilder) == 0); -} - -/** Write 8-bit value in ac_buffer builder - * \param pBuilder ac_buffer builder - * \param hu8 8-bit value to write - */ -static inline void ac_buffer_builder_write_nu8(ac_buffer_builder_t *pBuilder, uint8_t hu8) -{ - ac_buffer_builder_write_be(pBuilder, &hu8, 1); -} - -/** Write 16-bit value in ac_buffer builder - * \param pBuilder ac_buffer builder - * \param hu16 16-bit value to write in big-endian format - */ -static inline void ac_buffer_builder_write_nu16(ac_buffer_builder_t *pBuilder, uint16_t hu16) -{ - ac_buffer_builder_write_be(pBuilder, (uint8_t *)&hu16, 2); -} - -/** Write 24-bit value in ac_buffer builder - * \param pBuilder ac_buffer builder - * \param hu24 24-bit value to write in big-endian format - */ -static inline void ac_buffer_builder_write_nu24(ac_buffer_builder_t *pBuilder, uint32_t hu24) -{ - ac_buffer_builder_write_be(pBuilder, (uint8_t *)&hu24, 3); -} - -/** Write 32-bit value in ac_buffer builder - * \param pBuilder ac_buffer builder - * \param hu32 32-bit value to write in big-endian format - */ -static inline void ac_buffer_builder_write_nu32(ac_buffer_builder_t *pBuilder, uint32_t hu32) -{ - ac_buffer_builder_write_be(pBuilder, (uint8_t *)&hu32, 4); -} - -/** Write 64-bit value in ac_buffer builder - * \param pBuilder ac_buffer builder - * \param hu64 64-bit value to write in big-endian format - */ -static inline void ac_buffer_builder_write_nu64(ac_buffer_builder_t *pBuilder, uint64_t hu64) -{ - ac_buffer_builder_write_be(pBuilder, (uint8_t *)&hu64, 8); -} - -/** Write n-bytes value in ac_buffer builder - * \param pBuilder ac_buffer builder - * \param data data to write - * \param size data length - */ -static inline void ac_buffer_builder_write_n_bytes(ac_buffer_builder_t *pBuilder, const uint8_t *data, size_t size) -{ - ac_buffer_builder_write_le(pBuilder, data, size); -} - -/** Write 8-bit value in ac_buffer builder at specified position - * \param pBuilder ac_buffer builder - * \param off offset at which to write - * \param hu8 8-bit value to write - */ -static inline void ac_buffer_builder_write_nu8_at(ac_buffer_builder_t *pBuilder, size_t off, uint8_t hu8) -{ - ac_buffer_builder_write_be_at(pBuilder, off, &hu8, 1); -} - -/** Write 16-bit value in ac_buffer builder at specified position - * \param pBuilder ac_buffer builder - * \param off offset at which to write - * \param hu16 16-bit value to write - */ -static inline void ac_buffer_builder_write_nu16_at(ac_buffer_builder_t *pBuilder, size_t off, uint16_t hu16) -{ - ac_buffer_builder_write_be_at(pBuilder, off, (uint8_t *)&hu16, 2); -} - -/** Write 24-bit value in ac_buffer builder at specified position - * \param pBuilder ac_buffer builder - * \param off offset at which to write - * \param hu24 24-bit value to write - */ -static inline void ac_buffer_builder_write_nu24_at(ac_buffer_builder_t *pBuilder, size_t off, uint32_t hu24) -{ - ac_buffer_builder_write_be_at(pBuilder, off, (uint8_t *)&hu24, 3); -} - -/** Write 32-bit value in ac_buffer builder at specified position - * \param pBuilder ac_buffer builder - * \param off offset at which to write - * \param hu32 32-bit value to write - */ -static inline void ac_buffer_builder_write_nu32_at(ac_buffer_builder_t *pBuilder, size_t off, uint32_t hu32) -{ - ac_buffer_builder_write_be_at(pBuilder, off, (uint8_t *)&hu32, 4); -} - -/** Write 64-bit value in ac_buffer builder at specified position - * \param pBuilder ac_buffer builder - * \param off offset at which to write - * \param hu64 64-bit value to write - */ -static inline void ac_buffer_builder_write_nu64_at(ac_buffer_builder_t *pBuilder, size_t off, uint64_t hu64) -{ - ac_buffer_builder_write_be_at(pBuilder, off, (uint8_t *)&hu64, 8); -} - -/** Write n-bytes value in ac_buffer builder at specified position - * \param pBuilder ac_buffer builder - * \param off offset at which to write - * \param data data to write - * \param size data length - */ -static inline void ac_buffer_builder_write_n_bytes_at(ac_buffer_builder_t *pBuilder, size_t off, const uint8_t *data, size_t size) -{ - ac_buffer_builder_write_be_at(pBuilder, off, data, size); -} - -/** Skip n-bytes in ac_buffer builder - * \param pBuilder ac_buffer builder - * \param size number of bytes to skip - */ -void ac_buffer_builder_write_n_skip(ac_buffer_builder_t *pBuilder, size_t size); - -/** Copy n bytes from buffer to builder - * \param pBuilderOut ac_buffer builder - * \param pBufIn the input buffer - * \param size number of bytes to copy - */ -void ac_buffer_builder_copy_n_bytes(ac_buffer_builder_t *pBuilderOut, ac_buffer_t *pBufIn, size_t size); - -/** Compact builder - * Will move underlying buffer's byte to start of allocated buffer - * \param pBuilder ac_buffer builder - */ -void ac_buffer_builder_compact(ac_buffer_builder_t *pBuilder); - -/** Get number of writable bytes in ac_buffer builder - * \param pBuilder ac_buffer builder - * \return number of free bytes in ac_buffer builder - */ -static inline size_t ac_buffer_builder_writable(ac_buffer_builder_t *pBuilder) -{ - return ac_buffer_builder_space(pBuilder); -} - -#ifdef __cplusplus -} -#endif - -#endif /* ACORE_BUFFER_BUILDER_H_ */ - -/** - * @} - * @} - * */ diff --git a/features/nfc/acore/acore/ac_buffer_reader.h b/features/nfc/acore/acore/ac_buffer_reader.h deleted file mode 100644 index 0030908..0000000 --- a/features/nfc/acore/acore/ac_buffer_reader.h +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Copyright (c) 2017, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * 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. - */ -/** - * \file ac_buffer_reader.h - * \copyright Copyright (c) ARM Ltd 2015 - * \author Donatien Garnier - */ - -/** \addtogroup ACore - * @{ - * \name Buffer Reader - * @{ - */ - -#ifndef ACORE_BUFFER_READER_H_ -#define ACORE_BUFFER_READER_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "stdint.h" -#include "stddef.h" -#include "stdbool.h" - -#include "acore/ac_buffer.h" - -/** Read n-bytes in big-endian format from buffer reader and advance read posiion - * \param pBuf the buffer to read from - * \param buf the array to write to - * \param size the number of bytes to read - */ -void ac_buffer_read_be(ac_buffer_t *pBuf, uint8_t *buf, size_t size); - -/** Read n-bytes in little-endian format from buffer reader and advance read posiion - * \param pBuf the buffer to read from - * \param buf the array to write to - * \param size the number of bytes to read - */ -void ac_buffer_read_le(ac_buffer_t *pBuf, uint8_t *buf, size_t size); - -/** Read 8-bit value from buffer reader and advance read posiion - * \param pBuf the buffer to read from - * \return 8-bit value read - */ -static inline uint8_t ac_buffer_read_nu8(ac_buffer_t *pBuf) -{ - uint8_t hu8; - ac_buffer_read_be(pBuf, &hu8, 1); - return hu8; -} - -/** Read BE 16-bit value from buffer reader and advance read posiion - * \param pBuf the buffer to read from - * \return 16-bit value read - */ -static inline uint16_t ac_buffer_read_nu16(ac_buffer_t *pBuf) -{ - uint16_t hu16; - ac_buffer_read_be(pBuf, (uint8_t *)&hu16, 2); - return hu16; -} - -/** Read BE 24-bit value from buffer reader and advance read posiion - * \param pBuf the buffer to read from - * \return 24-bit value read - */ -static inline uint32_t ac_buffer_read_nu24(ac_buffer_t *pBuf) -{ - uint32_t hu24; - ac_buffer_read_be(pBuf, (uint8_t *)&hu24, 3); - return hu24; -} - -/** Read BE 32-bit value from buffer reader and advance read posiion - * \param pBuf the buffer to read from - * \return 32-bit value read - */ -static inline uint32_t ac_buffer_read_nu32(ac_buffer_t *pBuf) -{ - uint32_t hu32; - ac_buffer_read_be(pBuf, (uint8_t *)&hu32, 4); - return hu32; -} - -/** Read BE 64-bit value from buffer reader and advance read posiion - * \param pBuf the buffer to read from - * \return 64-bit value read - */ -static inline uint64_t ac_buffer_read_nu64(ac_buffer_t *pBuf) -{ - uint64_t hu64; - ac_buffer_read_be(pBuf, (uint8_t *)&hu64, 8); - return hu64; -} - -/** Read n bytes from buffer reader and advance read posiion - * \param pBuf the buffer to read from - * \param data the array to write bytes to - * \param size the number of bytes to read - */ -static inline void ac_buffer_read_n_bytes(ac_buffer_t *pBuf, uint8_t *data, size_t size) -{ - ac_buffer_read_le(pBuf, data, size); -} - -/** Skip n bytes from buffer reader and advance read posiion - * \param pBuf the buffer to read from - * \param size the number of bytes to skip - */ -void ac_buffer_read_n_skip(ac_buffer_t *pBuf, size_t size); - -/** Get number of bytes readable from buffer - * \param pBuf the buffer to read from - * \return The number of bytes which can be read - */ -size_t ac_buffer_reader_readable(const ac_buffer_t *pBuf); - -/** Get a pointer to the current position within this buffer's current backing array - * \param pBuf the buffer to read from - * \return A pointer to the current position within the current backing array - */ -const uint8_t *ac_buffer_reader_current_buffer_pointer(ac_buffer_t *pBuf); - -/** Get the number of bytes readable within the current backing array - * \param pBuf the buffer to read from - * \return The number of bytes readable within the current backing array - */ -size_t ac_buffer_reader_current_buffer_length(ac_buffer_t *pBuf); - -/** Compare buffer with array (does not advance read position) - * \param pBuf the buffer to compare from - * \param bytes the array to compare with - * \param length the array length - * \return Whether the buffer is AT LEAST as long as the array AND the buffer and array have the same content - */ -bool ac_buffer_reader_cmp_bytes(const ac_buffer_t *pBuf, const uint8_t *bytes, size_t length); - -/** Compare buffer with array (does not advance read position) - * \param pBuf1 the buffer to compare from - * \param pBuf2 the buffer to compare with - * \return Whether the buffers have the same length and content - */ -bool ac_buffer_reader_cmp(const ac_buffer_t *pBuf1, const ac_buffer_t *pBuf2); - -#ifdef __cplusplus -} -#endif - -#endif /* CORE_ac_buffer_READER_H_ */ - -/** - * @} - * @} - * */ diff --git a/features/nfc/acore/acore/ac_debug.h b/features/nfc/acore/acore/ac_debug.h deleted file mode 100644 index 2348514..0000000 --- a/features/nfc/acore/acore/ac_debug.h +++ /dev/null @@ -1,41 +0,0 @@ -/** - * \file ac_debug.h - * \copyright Copyright (c) ARM Ltd 2018 - * \author Donatien Garnier - */ -/* - * Copyright (c) 2018, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * 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. - */ - -#ifndef ACORE_DEBUG_H_ -#define ACORE_DEBUG_H_ - -// Macro that can be defined to lock stdio in multithreaded environments -#if !defined(ACORE_STDIO_LOCK) -#define ACORE_STDIO_LOCK() -#endif - -#if !defined(ACORE_STDIO_UNLOCK) -#define ACORE_STDIO_UNLOCK() -#endif - -// Macro that can be defined to define an alternative printf impl for debugging -#if !defined(ACORE_STDIO_PRINT) -#include "stdio.h" -#define ACORE_STDIO_PRINT(...) printf(__VA_ARGS__) -#endif - -#endif diff --git a/features/nfc/acore/acore/ac_macros.h b/features/nfc/acore/acore/ac_macros.h deleted file mode 100644 index cf56295..0000000 --- a/features/nfc/acore/acore/ac_macros.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2017, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * 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. - */ - -#ifndef ACORE_MACROS_H_ -#define ACORE_MACROS_H_ - -//Macros -#ifndef MAX -#define MAX(a,b) (((a)>(b))?(a):(b)) -#define MIN(a,b) (((a)<(b))?(a):(b)) -#endif - -#endif - diff --git a/features/nfc/acore/acore/ac_stream.h b/features/nfc/acore/acore/ac_stream.h deleted file mode 100644 index 1347d20..0000000 --- a/features/nfc/acore/acore/ac_stream.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2017, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * 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. - */ -/** - * \file ac_stream.h - * \copyright Copyright (c) ARM Ltd 2015 - * \author Donatien Garnier - */ - -#ifndef ACORE_STREAM_H_ -#define ACORE_STREAM_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -struct __ac_istream; -struct __ac_ostream; - -typedef struct __ac_istream ac_istream_t; -typedef struct __ac_ostream ac_ostream_t; - -#include "stddef.h" -#include "stdbool.h" -#include "stdint.h" - -#include "acore/ac_buffer.h" - -typedef void (*ac_istream_fn)(ac_buffer_t *pDataIn, bool *pClose, size_t maxLength, void *pUserParam); -typedef void (*ac_ostream_fn)(ac_buffer_t *pDataOut, bool closed, void *pUserParam); - -//Input stream -- pulled by consumer -struct __ac_istream { - ac_istream_fn fn; - void *pUserParam; -}; - -//Output stream -- pushed by supplier -struct __ac_ostream { - ac_ostream_fn fn; - void *pUserParam; -}; - -//Called by supplier -void ac_istream_init(ac_istream_t *pac_istream, ac_istream_fn fn, void *pUserParam); -//Called by consumer -void ac_istream_pull(ac_istream_t *pac_istream, ac_buffer_t *pDataIn, bool *pClose, size_t maxLength); - -//Called by consumer -void ac_ostream_init(ac_ostream_t *pac_ostream, ac_ostream_fn fn, void *pUserParam); -//Called by supplier -void ac_ostream_push(ac_ostream_t *pac_ostream, ac_buffer_t *pDataOut, bool closed); - -#ifdef __cplusplus -} -#endif - -#endif /* ACORE_STREAM_H_ */ diff --git a/features/nfc/acore/source/ac_buffer.c b/features/nfc/acore/source/ac_buffer.c deleted file mode 100644 index c3b91ff..0000000 --- a/features/nfc/acore/source/ac_buffer.c +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (c) 2017, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * 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. - */ -/** - * \file buffer.c - * \copyright Copyright (c) ARM Ltd 2013 - * \author Donatien Garnier - * \desc Module to ease ac_buffers' management - */ - -#include "string.h" - -#include "acore/ac_buffer.h" -#include "acore/ac_buffer_reader.h" -#include "acore/ac_macros.h" - -#include "acore/ac_debug.h" - -void ac_buffer_init(ac_buffer_t *pBuf, const uint8_t *data, size_t size) -{ - pBuf->data = data; - pBuf->size = size; - - pBuf->pNext = NULL; -} - -void ac_buffer_dup(ac_buffer_t *pBuf, const ac_buffer_t *pBufIn) -{ - if (pBuf != pBufIn) { - memcpy(pBuf, pBufIn, sizeof(ac_buffer_t)); - } -} - -void ac_buffer_append(ac_buffer_t *pBuf, ac_buffer_t *pAppBuf) -{ - while (pBuf->pNext != NULL) { - pBuf = pBuf->pNext; - } - pBuf->pNext = pAppBuf; -} - -void ac_buffer_split(ac_buffer_t *pStartBuf, ac_buffer_t *pEndBuf, ac_buffer_t *pBuf, size_t length) -{ - ac_buffer_dup(pStartBuf, pBuf); - ac_buffer_dup(pEndBuf, pBuf); - - ac_buffer_read_n_skip(pEndBuf, length); - - while (length > ac_buffer_size(pStartBuf)) { - length -= pStartBuf->size; - pStartBuf = pStartBuf->pNext; - } - - pStartBuf->size = length; - pStartBuf->pNext = NULL; -} - -/** Dump a ac_buffer's content to stdout (useful for debugging) - * \param pBuf pointer to ac_buffer_t structure - */ -void ac_buffer_dump(ac_buffer_t *pBuf) -{ -#if !defined(NDEBUG) - ACORE_STDIO_LOCK(); - while (pBuf != NULL) { - size_t r = ac_buffer_size(pBuf); - size_t i = 0; - size_t j = 0; - while (i < r) { - for (j = i; j < MIN(i + 16, r); j++) { - ACORE_STDIO_PRINT("%02x ", ac_buffer_data(pBuf)[j]); - } - ACORE_STDIO_PRINT("\r\n"); - i = j; - } - pBuf = ac_buffer_next(pBuf); - if (pBuf != NULL) { - ACORE_STDIO_PRINT("->\r\n"); - } - } - ACORE_STDIO_UNLOCK(); -#else - (void)pBuf; -#endif -} diff --git a/features/nfc/acore/source/ac_buffer_builder.c b/features/nfc/acore/source/ac_buffer_builder.c deleted file mode 100644 index 8e15488..0000000 --- a/features/nfc/acore/source/ac_buffer_builder.c +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright (c) 2017, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * 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. - */ -/** - * \file buffer_builder.c - * \copyright Copyright (c) ARM Ltd 2015 - * \author Donatien Garnier - */ - -#include "acore/ac_buffer_builder.h" -#include "acore/ac_buffer_reader.h" -#include "acore/ac_macros.h" - -#include "string.h" - -#define VOID -#define ENSURE_WRITE_LENGTH(pBuilder, n) do{ if( ac_buffer_builder_space(pBuilder) < n ) { return; } }while(0); - -void ac_buffer_builder_init(ac_buffer_builder_t *pBuilder, uint8_t *data, size_t size) -{ - pBuilder->data = data; - pBuilder->size = size; - ac_buffer_init(&pBuilder->ac_buffer, data, 0); -} - -void ac_buffer_builder_from_buffer(ac_buffer_builder_t *pBuilder) -{ - pBuilder->data = (uint8_t *)pBuilder->ac_buffer.data; - pBuilder->size = pBuilder->ac_buffer.size; - pBuilder->ac_buffer.size = 0; -} - -void ac_buffer_builder_reset(ac_buffer_builder_t *pBuilder) -{ - ac_buffer_init(&pBuilder->ac_buffer, pBuilder->data, 0); -} - -void ac_buffer_builder_set_full(ac_buffer_builder_t *pBuilder) -{ - ac_buffer_init(&pBuilder->ac_buffer, pBuilder->data, pBuilder->size); -} - -void ac_buffer_builder_write_be(ac_buffer_builder_t *pBuilder, const uint8_t *buf, size_t size) -{ - ENSURE_WRITE_LENGTH(pBuilder, size); - buf += size; - while (size > 0) { - buf--; - *ac_buffer_builder_write_position(pBuilder) = *buf; - pBuilder->ac_buffer.size++; - size--; - } -} - -void ac_buffer_builder_write_le(ac_buffer_builder_t *pBuilder, const uint8_t *buf, size_t size) -{ - ENSURE_WRITE_LENGTH(pBuilder, size); - memcpy(ac_buffer_builder_write_position(pBuilder), buf, size); - pBuilder->ac_buffer.size += size; -} - -void ac_buffer_builder_write_be_at(ac_buffer_builder_t *pBuilder, size_t pos, const uint8_t *buf, size_t size) -{ - size_t currentPos = pBuilder->ac_buffer.size; - pBuilder->ac_buffer.size = pos; - ac_buffer_builder_write_be(pBuilder, buf, size); - pBuilder->ac_buffer.size = currentPos; -} - -void ac_buffer_builder_write_le_at(ac_buffer_builder_t *pBuilder, size_t pos, const uint8_t *buf, size_t size) -{ - size_t currentPos = pBuilder->ac_buffer.size; - pBuilder->ac_buffer.size = pos; - ac_buffer_builder_write_le(pBuilder, buf, size); - pBuilder->ac_buffer.size = currentPos; -} - -void ac_buffer_builder_write_n_skip(ac_buffer_builder_t *pBuilder, size_t size) -{ - ENSURE_WRITE_LENGTH(pBuilder, size); - pBuilder->ac_buffer.size += size; -} - -void ac_buffer_builder_copy_n_bytes(ac_buffer_builder_t *pBuilderOut, ac_buffer_t *pBufIn, size_t size) -{ - ENSURE_WRITE_LENGTH(pBuilderOut, size); - if (ac_buffer_reader_readable(pBufIn) < size) { - return; - } - while (size > 0) { - size_t cpy = ac_buffer_reader_current_buffer_length(pBufIn); - cpy = MIN(cpy, size); - ac_buffer_builder_write_n_bytes(pBuilderOut, ac_buffer_reader_current_buffer_pointer(pBufIn), cpy); - ac_buffer_read_n_skip(pBufIn, cpy); - size -= cpy; - } -} - -void ac_buffer_builder_compact(ac_buffer_builder_t *pBuilder) -{ - memmove(pBuilder->data, ac_buffer_data(&pBuilder->ac_buffer), ac_buffer_size(&pBuilder->ac_buffer)); - pBuilder->ac_buffer.data = pBuilder->data; -} diff --git a/features/nfc/acore/source/ac_buffer_reader.c b/features/nfc/acore/source/ac_buffer_reader.c deleted file mode 100644 index 44d0303..0000000 --- a/features/nfc/acore/source/ac_buffer_reader.c +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright (c) 2017, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * 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. - */ -/** - * \file buffer_reader.c - * \copyright Copyright (c) ARM Ltd 2015 - * \author Donatien Garnier - */ - -#include "acore/ac_buffer_reader.h" -#include "acore/ac_macros.h" - -#include "string.h" - -#define VOID -#define ENSURE_READ_LENGTH(pBuf, n) do{ if( ac_buffer_reader_readable(pBuf) < n ) { return; } }while(0); - -static inline void update_buf(ac_buffer_t *pBuf) -{ - while (ac_buffer_size(pBuf) == 0) { - if (ac_buffer_next(pBuf) != NULL) { - ac_buffer_t *pNext = ac_buffer_next(pBuf); - ac_buffer_init(pBuf, ac_buffer_data(pNext), ac_buffer_size(pNext)); - pBuf->pNext = ac_buffer_next(pNext); - } else if (pBuf->data != NULL) { - ac_buffer_init(pBuf, NULL, 0); - } else { - return; - } - } -} - -void ac_buffer_read_be(ac_buffer_t *pBuf, uint8_t *buf, size_t size) -{ - ENSURE_READ_LENGTH(pBuf, size); - buf += size; - while (size > 0) { - buf--; - *buf = *ac_buffer_data(pBuf); - pBuf->data++; - pBuf->size--; - update_buf(pBuf); - size--; - } -} - -void ac_buffer_read_le(ac_buffer_t *pBuf, uint8_t *buf, size_t size) -{ - ENSURE_READ_LENGTH(pBuf, size); - while (size > 0) { - size_t cpy = ac_buffer_size(pBuf); - cpy = MIN(cpy, size); - memcpy(buf, ac_buffer_data(pBuf), cpy); - pBuf->data += cpy; - pBuf->size -= cpy; - update_buf(pBuf); - size -= cpy; - buf += cpy; - } -} - -void ac_buffer_read_n_skip(ac_buffer_t *pBuf, size_t size) -{ - ENSURE_READ_LENGTH(pBuf, size); - while (size > 0) { - size_t cpy = ac_buffer_size(pBuf); - cpy = MIN(cpy, size); - pBuf->data += cpy; - pBuf->size -= cpy; - update_buf(pBuf); - size -= cpy; - } -} - -size_t ac_buffer_reader_readable(const ac_buffer_t *pBuf) -{ - size_t r = 0; - while (pBuf != NULL) { - r += ac_buffer_size(pBuf); - pBuf = ac_buffer_next(pBuf); - } - return r; -} - -const uint8_t *ac_buffer_reader_current_buffer_pointer(ac_buffer_t *pBuf) -{ - update_buf(pBuf); - return ac_buffer_data(pBuf); -} - -size_t ac_buffer_reader_current_buffer_length(ac_buffer_t *pBuf) -{ - update_buf(pBuf); - return ac_buffer_size(pBuf); -} - -bool ac_buffer_reader_cmp_bytes(const ac_buffer_t *pBuf, const uint8_t *bytes, size_t length) -{ - ac_buffer_t reader; - - if (length > ac_buffer_reader_readable(pBuf)) { - return false; - } - - ac_buffer_dup(&reader, pBuf); - - while (length > 0) { - size_t sz = ac_buffer_reader_current_buffer_length(&reader); - if (sz > length) { - sz = length; - } - int c = memcmp(ac_buffer_reader_current_buffer_pointer(&reader), bytes, sz); - if (c) { - return false; - } - length -= sz; - bytes += sz; - ac_buffer_read_n_skip(&reader, sz); - } - - return true; -} - -bool ac_buffer_reader_cmp(const ac_buffer_t *pBuf1, const ac_buffer_t *pBuf2) -{ - ac_buffer_t reader1; - ac_buffer_t reader2; - - if (ac_buffer_reader_readable(pBuf1) != ac_buffer_reader_readable(pBuf2)) { - return false; - } - - ac_buffer_dup(&reader1, pBuf1); - ac_buffer_dup(&reader2, pBuf2); - - size_t length = ac_buffer_reader_readable(pBuf1); - while (length > 0) { - size_t sz1 = ac_buffer_reader_current_buffer_length(&reader1); - size_t sz2 = ac_buffer_reader_current_buffer_length(&reader2); - - size_t sz = MIN(sz1, sz2); - - int c = memcmp(ac_buffer_reader_current_buffer_pointer(&reader1), ac_buffer_reader_current_buffer_pointer(&reader2), sz); - if (c) { - return false; - } - length -= sz; - ac_buffer_read_n_skip(&reader1, sz); - ac_buffer_read_n_skip(&reader2, sz); - } - - return true; -} diff --git a/features/nfc/acore/source/ac_stream.c b/features/nfc/acore/source/ac_stream.c deleted file mode 100644 index 6954f25..0000000 --- a/features/nfc/acore/source/ac_stream.c +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2017, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * 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. - */ -/** - * \file stream.c - * \copyright Copyright (c) ARM Ltd 2015 - * \author Donatien Garnier - */ - -#include "acore/ac_stream.h" -#include "acore/ac_macros.h" - -//Called by supplier -void ac_istream_init(ac_istream_t *pac_istream, ac_istream_fn fn, void *pUserParam) -{ - pac_istream->fn = fn; - pac_istream->pUserParam = pUserParam; -} - -//Called by consumer -void ac_istream_pull(ac_istream_t *pac_istream, ac_buffer_t *pDataIn, bool *pClose, size_t maxLength) -{ - pac_istream->fn(pDataIn, pClose, maxLength, pac_istream->pUserParam); -} - -//Called by consumer -void ac_ostream_init(ac_ostream_t *pac_ostream, ac_ostream_fn fn, void *pUserParam) -{ - pac_ostream->fn = fn; - pac_ostream->pUserParam = pUserParam; -} - -//Called by supplier -void ac_ostream_push(ac_ostream_t *pac_ostream, ac_buffer_t *pDataOut, bool closed) -{ - pac_ostream->fn(pDataOut, closed, pac_ostream->pUserParam); -} diff --git a/features/nfc/controllers/PN512Driver.h b/features/nfc/controllers/PN512Driver.h deleted file mode 100644 index 91a6778..0000000 --- a/features/nfc/controllers/PN512Driver.h +++ /dev/null @@ -1,51 +0,0 @@ -/* 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. - */ - -#ifndef MBED_PN512_DRIVER_H -#define MBED_PN512_DRIVER_H - -#include - -#include "nfc/NFCControllerDriver.h" -#include "PN512TransportDriver.h" - -#include "nfc/acore/acore/ac_buffer.h" -#include "nfc/acore/acore/ac_buffer_reader.h" -#include "nfc/acore/acore/ac_buffer_builder.h" -#include "nfc/stack/transceiver/pn512/pn512.h" - -namespace mbed { -namespace nfc { - -class PN512Driver : public NFCControllerDriver, private PN512TransportDriver::Delegate { -public: - PN512Driver(PN512TransportDriver *transport_driver); - - virtual nfc_transceiver_t *initialize(nfc_scheduler_timer_t *scheduler_timer); - virtual void get_supported_nfc_techs(nfc_tech_t *initiator, nfc_tech_t *target) const; - -private: - // PN512TransportDriver::Delegate implementation - virtual void on_hw_interrupt(); - - PN512TransportDriver *_transport_driver; - pn512_t _pn512; -}; - -} // namespace nfc -} // namespace mbed - -#endif diff --git a/features/nfc/controllers/PN512SPITransportDriver.h b/features/nfc/controllers/PN512SPITransportDriver.h deleted file mode 100644 index 99a7ab9..0000000 --- a/features/nfc/controllers/PN512SPITransportDriver.h +++ /dev/null @@ -1,58 +0,0 @@ -/* 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. - */ - -#ifndef MBED_PN512_SPI_TRANSPORT_DRIVER_H -#define MBED_PN512_SPI_TRANSPORT_DRIVER_H - -#include - -#include "platform/platform.h" -#include "platform/nfc_transport.h" -#include "PN512TransportDriver.h" - -#include "drivers/SPI.h" -#include "drivers/DigitalOut.h" -#include "drivers/InterruptIn.h" - -namespace mbed { -namespace nfc { - -class PN512SPITransportDriver : public PN512TransportDriver { -public: - PN512SPITransportDriver(PinName mosi, PinName miso, PinName sclk, PinName ssel, PinName irq, PinName rst); - -private: - virtual void initialize(); - virtual nfc_transport_t *get_transport(); - - void transport_write(uint8_t address, const uint8_t *outBuf, size_t outLen); - void transport_read(uint8_t address, uint8_t *inBuf, size_t inLen); - - // Callbacks from munfc - static void s_transport_write(uint8_t address, const uint8_t *outBuf, size_t outLen, void *pUser); - static void s_transport_read(uint8_t address, uint8_t *inBuf, size_t inLen, void *pUser); - - nfc_transport_t _nfc_transport; - mbed::SPI _spi; - mbed::DigitalOut _ssel; - mbed::InterruptIn _irq; - mbed::DigitalOut _rst; -}; - -} // namespace nfc -} // namespace mbed - -#endif diff --git a/features/nfc/controllers/PN512TransportDriver.h b/features/nfc/controllers/PN512TransportDriver.h deleted file mode 100644 index cb5c437..0000000 --- a/features/nfc/controllers/PN512TransportDriver.h +++ /dev/null @@ -1,86 +0,0 @@ -/* 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. - */ - -#ifndef MBED_PN512_TRANSPORT_DRIVER_H -#define MBED_PN512_TRANSPORT_DRIVER_H - -#include -#include "stack/platform/nfc_transport.h" - - -namespace mbed { -namespace nfc { -/** - * The PN512 supports multiple transport mechanisms (SPI, I2C, UART): this class provides a unified API across these transports - */ -class PN512TransportDriver { -public: - /** - * The PN512TransportDriver delegate - */ - struct Delegate { - /** - * Called when the PN512 asserts the interrupt line - */ - virtual void on_hw_interrupt() {} - - protected: - ~Delegate() {} - }; - - /** - * Create a PN512TransportDriver instance - */ - PN512TransportDriver(); - - /** - * PN512TransportDriver destructor. - */ - virtual ~PN512TransportDriver(); - - /** - * Initialize transport driver and perform a chip reset - */ - virtual void initialize() = 0; - - /** - * Retrieve the nfc_transport_t struct for the stack to use - * - * @return a pointer to a nfc_transport_t struct - */ - virtual nfc_transport_t *get_transport() = 0; - - /** - * Set this instance's delegate - * - * @param[in] delegate the delegate instance to use - */ - void set_delegate(Delegate *delegate); -protected: - - /** - * An implementation must call this function (can be called from interrupt context) - * when the PN512 asserts its interrupt line - */ - void hw_interrupt(); -private: - Delegate *_delegate; -}; - -} // namespace nfc -} // namespace mbed - -#endif diff --git a/features/nfc/mbed_lib.json b/features/nfc/mbed_lib.json deleted file mode 100644 index dd3c37b..0000000 --- a/features/nfc/mbed_lib.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "name": "nfc" -} diff --git a/features/nfc/nfc/NFC.h b/features/nfc/nfc/NFC.h deleted file mode 100644 index 38cfe23..0000000 --- a/features/nfc/nfc/NFC.h +++ /dev/null @@ -1,31 +0,0 @@ -/* 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. - */ - -#ifndef MBED_NFC_H -#define MBED_NFC_H - -// Convenience header - -// NFC Controller -#include "NFCController.h" - -// NFC EEPROM -#include "NFCEEPROM.h" - -// Type 4 Remote Initiator -#include "Type4RemoteInitiator.h" - -#endif diff --git a/features/nfc/nfc/NFCController.h b/features/nfc/nfc/NFCController.h deleted file mode 100644 index df55292..0000000 --- a/features/nfc/nfc/NFCController.h +++ /dev/null @@ -1,184 +0,0 @@ -/* 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. - */ - -#ifndef MBED_NFC_CONTROLLER_H -#define MBED_NFC_CONTROLLER_H - -#include -#include "events/EventQueue.h" -#include "platform/SharedPtr.h" -#include "drivers/Timer.h" -#include "drivers/Timeout.h" - -#include "NFCDefinitions.h" -#include "NFCControllerDriver.h" - -#include "platform/Span.h" - -namespace mbed { -namespace nfc { - -/** @addtogroup nfc - * @{ - */ - -class NFCRemoteInitiator; -class NFCRemoteTarget; -class NFCControllerDriver; - -/** - * This class represents a NFC Controller. - * - * A controller can be in one of three different states: - * * Idle/sleep state - * * Discovery state: The controller tries to discover a remote endpoint (initiator or target) - * * Connected state: The controller exchanges data with an endpoint (initiator or target) - * - * A NFCController instance needs to be initialized with a NFCControllerDriver instance which abstracts the specific controller being used. - * A delegate needs to be set by the user to receive discovery events. - */ -class NFCController : private NFCControllerDriver::Delegate { -public: - - /** - * The NFCController delegate. Users of the NFCController class need to implement this delegate's methods to receive events. - */ - struct Delegate { - /** - * A enumeration of causes for the discovery process terminating. - */ - enum nfc_discovery_terminated_reason_t { - nfc_discovery_terminated_completed = 0, ///< Process completed, at least one endpoint was discovered - nfc_discovery_terminated_canceled, ///< Process was canceled by the user - nfc_discovery_terminated_rf_error ///< An unexpected error was encountered during an exchange on the air interface - }; - - /** - * The discovery process terminated. - * @param[in] reason the cause for the termination - */ - virtual void on_discovery_terminated(nfc_discovery_terminated_reason_t reason) {} - - /** - * A remote initiator was discovered (the local controller is in target mode). - * @param[in] nfc_initiator the NFCRemoteInitiator instance - */ - virtual void on_nfc_initiator_discovered(const SharedPtr &nfc_initiator) {} - - /** - * A remote target was discovered (the local controller is in initiator mode). - * @param[in] nfc_target the NFCRemoteTarget instance - */ - virtual void on_nfc_target_discovered(const SharedPtr &nfc_target) {} - - protected: - ~Delegate() { } - }; - - /** - * Construct a NFCController instance. - * - * @param[in] driver a pointer to a NFCControllerDriver instance - * @param[in] queue a pointer to the events queue to use - * @param[in] ndef_buffer a bytes array used to store NDEF messages - */ - NFCController(NFCControllerDriver *driver, events::EventQueue *queue, const Span &ndef_buffer); - - /** - * Initialize the NFC controller - * - * 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 controller. - * - * @param[in] delegate the delegate instance to use - */ - void set_delegate(Delegate *delegate); - - /** - * Get the list of RF protocols supported by this controller. - * - * @return a bitmask of RF protocols supported by the controller - */ - nfc_rf_protocols_bitmask_t get_supported_rf_protocols() const; - - /** - * Set the list of RF protocols to look for during discovery. - * - * @param[in] rf_protocols the relevant bitmask - * @return NFC_OK on success, or - * NFC_ERR_UNSUPPORTED if a protocol is not supported by the controller, - * NFC_ERR_BUSY if the discovery process is already running - */ - nfc_err_t configure_rf_protocols(nfc_rf_protocols_bitmask_t rf_protocols); - - /** - * Start the discovery process using the protocols configured previously. - * - * If remote endpoints are connected when this is called, they will be disconnected. - * - * @return NFC_OK on success, or - * NFC_ERR_BUSY if the discovery process is already running - */ - nfc_err_t start_discovery(); - - /** - * Cancel/stop a running discovery process. - * - * @return NFC_OK - */ - nfc_err_t cancel_discovery(); - -private: - // These two classes need to be friends to access the following transceiver() method - friend class NFCRemoteEndpoint; - friend class Type4RemoteInitiator; - nfc_transceiver_t *transceiver() const; - - void polling_callback(nfc_err_t ret); - - // NFC Stack scheduler - void scheduler_process(bool hw_interrupt); - - // Callbacks from NFC stack - static void s_polling_callback(nfc_transceiver_t *pTransceiver, nfc_err_t ret, void *pUserData); - - // Implementation of NFCControllerDriver::Delegate - virtual void on_hw_interrupt(); - - // Triggers when scheduler must be run again - void on_timeout(); - - NFCControllerDriver *_driver; - events::EventQueue *_queue; - nfc_transceiver_t *_transceiver; - nfc_scheduler_t *_scheduler; - Timer _timer; - Timeout _timeout; - Delegate *_delegate; - bool _discovery_running; - Span _ndef_buffer; -}; -/** @}*/ -} // namespace nfc -} // namespace mbed - -#endif diff --git a/features/nfc/nfc/NFCControllerDriver.h b/features/nfc/nfc/NFCControllerDriver.h deleted file mode 100644 index db78cfb..0000000 --- a/features/nfc/nfc/NFCControllerDriver.h +++ /dev/null @@ -1,104 +0,0 @@ -/* 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. - */ - -#ifndef MBED_NFC_CONTROLLER_DRIVER_H -#define MBED_NFC_CONTROLLER_DRIVER_H - -#include -#include "events/EventQueue.h" - -#include "stack/nfc_errors.h" -#include "stack/transceiver/transceiver.h" -#include "stack/platform/nfc_scheduler.h" - -namespace mbed { -namespace nfc { - -/** - * @addtogroup nfc - * @{ - */ - -/** - * The abstraction for a NFC controller driver. - * Implementers need to derive from this class and implement its methods. - */ -class NFCControllerDriver { -public: - /** - * Instantiate a NFCControllerDriver - */ - NFCControllerDriver(); - - /** - * NFCControllerDriver destructor - */ - virtual ~NFCControllerDriver(); - - /** - * The NFCControllerDriver delegate - */ - struct Delegate { - /** - * Called when the controller asserts the interrupt line - */ - virtual void on_hw_interrupt() {} - - protected: - ~Delegate() {} - }; - - /** - * Initialize the driver and retrieve the interface to the controller. - * - * @param[in] scheduler_timer a timer to initialize the controller's scheduler instance with - * @return an initialized MicroNFC nfc_transceiver_t instance - */ - virtual nfc_transceiver_t *initialize(nfc_scheduler_timer_t *scheduler_timer) = 0; - - /** - * Retrieve list of technologies supported by the controller - * @param[out] initiator bitmask of technologies supported when the controller is in initiator mode - * @param[out] target bitmask of technologies supported when the controller is in target mode - */ - virtual void get_supported_nfc_techs(nfc_tech_t *initiator, nfc_tech_t *target) const = 0; - - /** - * Set this instance's delegate - * - * @param[in] delegate the delegate instance to use - */ - void set_delegate(Delegate *delegate); - -protected: - /** - * An implementation must call this function (can be called from interrupt context) - * when the controller asserts its interrupt line - */ - void hw_interrupt(); - -private: - Delegate *_delegate; -}; - -/** - * @} - */ - -} // namespace nfc -} // namespace mbed - -#endif diff --git a/features/nfc/nfc/NFCDefinitions.h b/features/nfc/nfc/NFCDefinitions.h deleted file mode 100644 index 0c1d3ce..0000000 --- a/features/nfc/nfc/NFCDefinitions.h +++ /dev/null @@ -1,57 +0,0 @@ -/* 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. - */ - -#ifndef MBED_NFC_DEFINITIONS_H -#define MBED_NFC_DEFINITIONS_H - -#include -#include - -#include "stack/nfc_errors.h" - -#include "acore/ac_buffer.h" - -namespace mbed { -namespace nfc { -struct nfc_rf_protocols_bitmask_t { - bool initiator_t1t : 1; - bool initiator_t2t : 1; - bool initiator_t3t : 1; - bool initiator_iso_dep : 1; - bool initiator_nfc_dep : 1; - bool initiator_t5t : 1; - - bool target_t1t : 1; - bool target_t2t : 1; - bool target_t3t : 1; - bool target_iso_dep : 1; - bool target_nfc_dep : 1; - bool target_t5t : 1; -}; - -enum nfc_tag_type_t { - nfc_tag_type_1, - nfc_tag_type_2, - nfc_tag_type_3, - nfc_tag_type_4a, - nfc_tag_type_4b, - nfc_tag_type_5 -}; - -} // namespace nfc -} // namespace mbed - -#endif diff --git a/features/nfc/nfc/NFCEEPROM.h b/features/nfc/nfc/NFCEEPROM.h deleted file mode 100644 index ed0deb3..0000000 --- a/features/nfc/nfc/NFCEEPROM.h +++ /dev/null @@ -1,159 +0,0 @@ -/* 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. - */ - -#ifndef MBED_NFC_EEPROM_H -#define MBED_NFC_EEPROM_H - -#include -#include "events/EventQueue.h" - -#include "NFCDefinitions.h" -#include "NFCTarget.h" -#include "NFCEEPROMDriver.h" - -namespace mbed { -namespace nfc { - -/** @addtogroup nfc - * @{ - */ - -/** - * The NFC EEPROM class represents a NFC target device connected using a wired - * link (I2C, SPI, etc). - * - * These EEPROMs essentially provide addressable memory that can be accessed - * using either a wired or NFC interface. - * - * In NFC mode these most often conform to one of the NFC tag types defined - * by the NFC Forum, therefore encoding NDEF data in these EEPROMs will - * ensure that it is understandable by a NFC reader. - */ -class NFCEEPROM : public NFCTarget, public NFCEEPROMDriver::Delegate { -public: - /** - * 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 - */ - NFCEEPROM(NFCEEPROMDriver *driver, events::EventQueue *queue, const Span &ndef_buffer); - - /** - * The NFCEEPROM delegate. Users of the NFCEEPROM class need to implement this delegate's methods to receive events. - */ - struct Delegate : NFCTarget::Delegate { - /** - * The NDEF message erasing request completed. - * - * @param[in] result NFC_OK or an error code on failure - */ - virtual void on_ndef_message_erased(nfc_err_t result) {} - - /** - * The NDEF message writing request completed. - * - * @param[in] result NFC_OK or an error code on failure - */ - virtual void on_ndef_message_written(nfc_err_t result) {} - - /** - * The NDEF message reading request completed. - * - * @param[in] result NFC_OK or an error code on failure - */ - virtual void on_ndef_message_read(nfc_err_t result) {} - - protected: - ~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. - * - * @param[in] delegate the delegate instance to use - */ - void set_delegate(Delegate *delegate); - - // Implementation of NFCTarget - virtual void write_ndef_message(); - virtual void read_ndef_message(); - virtual void erase_ndef_message(); - -private: - // 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_written(bool success); - virtual void on_size_read(bool success, size_t size); - virtual void on_bytes_erased(size_t count); - - void handle_error(nfc_err_t ret); - void continue_write(); - void continue_read(); - void continue_erase(); - - // NFCNDEFCapable implementation - virtual NFCNDEFCapable::Delegate *ndef_capable_delegate(); - - enum nfc_eeprom_operation_t { - nfc_eeprom_idle, - - nfc_eeprom_write_start_session, - nfc_eeprom_write_write_size, - nfc_eeprom_write_write_bytes, - nfc_eeprom_write_end_session, - - nfc_eeprom_read_start_session, - nfc_eeprom_read_read_size, - nfc_eeprom_read_read_bytes, - nfc_eeprom_read_end_session, - - nfc_eeprom_erase_start_session, - nfc_eeprom_erase_write_max_size, - nfc_eeprom_erase_erase_bytes, - nfc_eeprom_erase_write_0_size, - nfc_eeprom_erase_end_session - }; - - Delegate *_delegate; - NFCEEPROMDriver *_driver; - events::EventQueue *_event_queue; - bool _initialized; - - nfc_eeprom_operation_t _current_op; - ac_buffer_t _ndef_buffer_reader; - size_t _ndef_buffer_read_sz; - uint32_t _eeprom_address; - nfc_err_t _operation_result; -}; -/** @}*/ -} // namespace nfc -} // namespace mbed - -#endif diff --git a/features/nfc/nfc/NFCEEPROMDriver.h b/features/nfc/nfc/NFCEEPROMDriver.h deleted file mode 100644 index f190e54..0000000 --- a/features/nfc/nfc/NFCEEPROMDriver.h +++ /dev/null @@ -1,203 +0,0 @@ -/* 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. - */ - -#ifndef MBED_NFC_EEPROM_DRIVER_H -#define MBED_NFC_EEPROM_DRIVER_H - -#include - -#include "events/EventQueue.h" - -namespace mbed { -namespace nfc { - -/** - * @addtogroup nfc - * @{ - */ - -/** - * The abstraction for a NFC EEPROM driver. - * Implementers need to derive from this class and implement its methods. - */ -class NFCEEPROMDriver { -public: - /** - * Construct a NFCEEPROM driver instance. - */ - NFCEEPROMDriver(); - - /** - * NFCEEPROM driver destructor. - */ - virtual ~NFCEEPROMDriver(); - - /** - * The NFCEEPROMDriver delegate. - * Methods in this class are called by the driver on completion of long-running operations. - */ - struct Delegate { - /** - * Completion of session start operation. - * - * @param[in] success whether this operation succeeded - */ - virtual void on_session_started(bool success) = 0; - - /** - * Completion of session end operation. - * - * @param[in] success whether this operation succeeded - */ - virtual void on_session_ended(bool success) = 0; - - /** - * Completion of read operation. - * - * @param[in] count number of bytes actually read - */ - virtual void on_bytes_read(size_t count) = 0; - - /** - * Completion of write operation. - * - * @param[in] count number of bytes actually written - */ - virtual void on_bytes_written(size_t count) = 0; - - /** - * Completion of size retrieval operation. - * - * @param[in] success whether this operation succeeded - * @param[out] size the current addressable memory size - */ - virtual void on_size_read(bool success, size_t size) = 0; - - /** - * Completion of size setting operation. - * - * @param[in] success whether this operation succeeded - */ - virtual void on_size_written(bool success) = 0; - - /** - * Completion of erasing operation. - * - * @param[in] count number of bytes actually erased - */ - virtual void on_bytes_erased(size_t count) = 0; - - protected: - ~Delegate() {} - }; - - /** - * Set the delegate that will receive events generated by this EEPROM. - * - * @param[in] delegate the delegate instance to use - */ - void set_delegate(Delegate *delegate); - - /** - * Set the event queue that will be used to schedule event handling - * - * @param[in] queue the queue instance to use - */ - void set_event_queue(events::EventQueue *queue); - - /** - * Reset and initialize the EEPROM. - * This method should complete synchronously. - */ - virtual void reset() = 0; - - /** - * Get the maximum memory size addressable by the EEPROM. - */ - virtual size_t read_max_size() = 0; - - /** - * Start a session of operations (reads, writes, erases, size gets/sets). - * This method is called prior to any memory access to allow the underlying implementation - * to disable the RF interface or abort the transaction if it's being used. - * This method should complete asynchronously by calling has_started_session(). - */ - virtual void start_session(bool force = true) = 0; // This could lock the chip's RF interface - - /** - * End a session. - * This method should complete asynchronously by calling has_ended_session(). - */ - virtual void end_session() = 0; - - /** - * Read bytes from memory. - * @param[in] address the virtual address (starting from 0) from which to start the read. - * @param[out] bytes a buffer in which the read bytes will be stored. - * This buffer should remain valid till the callback is called. - * @param[in] count the number of bytes to read. - * This method should complete asynchronously by calling has_read_bytes(). - */ - virtual void read_bytes(uint32_t address, uint8_t *bytes, size_t count) = 0; - - /** - * Write bytes to memory. - * @param[in] address the virtual address (starting from 0) from which to start the write. - * @param[in] bytes a buffer from to copy. - * This buffer should remain valid till the callback is called. - * @param[in] count the number of bytes to write. - * This method should complete asynchronously by calling has_written_bytes(). - */ - virtual void write_bytes(uint32_t address, const uint8_t *bytes, size_t count) = 0; - - /** - * Retrieve the size of the addressable memory. - * This method should complete asynchronously by calling has_gotten_size(). - */ - virtual void read_size() = 0; - - /** - * Set the size of the addressable memory. - * @param[in] count the number of addressable bytes. - * This method should complete asynchronously by calling has_set_size(). - */ - virtual void write_size(size_t count) = 0; - - /** - * Erase bytes from memory. - * @param[in] address the virtual address (starting from 0) from which to start erasing. - * @param[in] size the number of bytes to erase. - * This method should complete asynchronously by calling has_erased_bytes(). - */ - virtual void erase_bytes(uint32_t address, size_t size) = 0; - -protected: - Delegate *delegate(); - events::EventQueue *event_queue(); - -private: - Delegate *_delegate; - events::EventQueue *_event_queue; -}; - -/** - * @} - */ - -} // namespace nfc -} // namespace mbed - -#endif diff --git a/features/nfc/nfc/NFCNDEFCapable.h b/features/nfc/nfc/NFCNDEFCapable.h deleted file mode 100644 index 66b3cd5..0000000 --- a/features/nfc/nfc/NFCNDEFCapable.h +++ /dev/null @@ -1,130 +0,0 @@ -/* 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. - */ - -#ifndef MBED_NFC_NDEF_CAPABLE_H -#define MBED_NFC_NDEF_CAPABLE_H - -#include - -#include "platform/Span.h" - -#include "NFCDefinitions.h" - -#include "nfc/stack/ndef/ndef.h" -#include "nfc/acore/acore/ac_buffer.h" -#include "nfc/acore/acore/ac_buffer_reader.h" -#include "nfc/acore/acore/ac_buffer_builder.h" - -namespace mbed { -namespace nfc { - -/** - * @addtogroup nfc - * @{ - */ - -/** - * The base class for all endpoints that can support NDEF content. - */ -class NFCNDEFCapable { -public: - /** - * Construct a NFCNDEFCapable instance. - * @param[in] buffer a bytes array used to store NDEF messages - */ - NFCNDEFCapable(const Span &buffer); - - /** - * Check if this instance actually supports NDEF content. - * - * @return whether NDEF content is supported - */ - virtual bool is_ndef_supported() const - { - return false; - } - - struct Delegate { - /** - * Parse a NDEF message. - * - * @param[in] buffer a buffer containing the message to parse - */ - virtual void parse_ndef_message(const Span &buffer) { } - - /** - * Build a NDEF message. - * - * @param[in] buffer a mutable buffer in which the message should be stored - * - * @return the number of bytes actually used - */ - virtual size_t build_ndef_message(const Span &buffer) - { - return 0; - } - - protected: - ~Delegate() {} - }; - -protected: - /** - * Parse a NDEF message. - * - * @param[in] buffer a buffer containing a NDEF message - */ - void parse_ndef_message(const ac_buffer_t &buffer); - - /** - * Build NDEF message. - * - * @param[in,out] buffer_builder a buffer builder in which to create the NDEF message. - * The backing buffer is guaranteed to be continuous. - */ - void build_ndef_message(ac_buffer_builder_t &buffer_builder); - - /** - * Retrieve underlying NDEF message instance - * @return pointer to NDEF message instance - */ - ndef_msg_t *ndef_message(); - -private: - /** - * Get the delegate that will receive events generated by this class. - * - * @return the delegate instance to use - */ - virtual Delegate *ndef_capable_delegate(); - - // Callbacks from NDEF stack - static nfc_err_t s_ndef_encode(ndef_msg_t *pTag, ac_buffer_builder_t *pBufferBldr, void *pUserData); - static nfc_err_t s_ndef_decode(ndef_msg_t *pTag, ac_buffer_t *pBuffer, void *pUserData); - nfc_err_t ndef_encode(ac_buffer_builder_t *pBufferBldr); - nfc_err_t ndef_decode(ac_buffer_t *pBuffer); - - ndef_msg_t _ndef_message; -}; - -/** - * @} - */ - -} // namespace nfc -} // namespace mbed - -#endif diff --git a/features/nfc/nfc/NFCRemoteEndpoint.h b/features/nfc/nfc/NFCRemoteEndpoint.h deleted file mode 100644 index 7d2916c..0000000 --- a/features/nfc/nfc/NFCRemoteEndpoint.h +++ /dev/null @@ -1,135 +0,0 @@ -/* 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. - */ - -#ifndef MBED_NFC_REMOTE_ENDPOINT_H -#define MBED_NFC_REMOTE_ENDPOINT_H - -#include - -#include "NFCDefinitions.h" - -namespace mbed { -namespace nfc { - -/** - * @addtogroup nfc - * @{ - */ - -class NFCController; - -/** - * This is the base class for all remote endpoints (initiators and targets) - * addressable over the air interface. - */ -class NFCRemoteEndpoint { -public: - /** - * Create a NFCRemoteEndpointinstance - * @param[in] controller the NFCController instance that detected this endpoint - */ - NFCRemoteEndpoint(NFCController *controller); - - /** - * Destructor - */ - virtual ~NFCRemoteEndpoint(); - - /** - * The NFCRemoteEndpoint base delegate. - */ - struct Delegate { - /** - * This method is called when the endpoint is connected - */ - virtual void on_connected() {} - - /** - * This method is called when the endpoint is lost (air interface link disconnnected) - */ - virtual void on_disconnected() {} - - protected: - ~Delegate() {} - }; - - /** - * Connect the remote endpoint - * - * @return NFC_OK or an error code - */ - virtual nfc_err_t connect() = 0; - - /** - * Disconnect the remote endpoint - * - * @return NFC_OK or an error code - */ - virtual nfc_err_t disconnect() = 0; - - /** - * Check if the endpoint is connected. - * @return whether the endpoint is connected - */ - virtual bool is_connected() const = 0; - - /** - * Check if the endpoint is disconnected/lost. - * @return whether the endpoint has been disconnected - */ - virtual bool is_disconnected() const = 0; - - /** - * Get the list of RF protocols supported and activated over the air interface. - * @return a bitmask of activated protocols - */ - virtual nfc_rf_protocols_bitmask_t rf_protocols() = 0; - -protected: - /** - * Mark endpoint as connected - */ - virtual void connected() = 0; - - /** - * Mark endpoint as disconnected - */ - virtual void disconnected() = 0; - - /** - * Retrieve NFCController instance - * @return a pointer to the NFController instance that created this endpoint. - */ - NFCController *nfc_controller(); - - /** - * Retrieve NFCController instance - * @return a pointer to the NFController instance that created this endpoint. - */ - const NFCController *nfc_controller() const; - -private: - NFCController *_controller; -}; - -/** - * @} - */ - -} // namespace nfc -} // namespace mbed - -#endif diff --git a/features/nfc/nfc/NFCRemoteInitiator.h b/features/nfc/nfc/NFCRemoteInitiator.h deleted file mode 100644 index b8cde88..0000000 --- a/features/nfc/nfc/NFCRemoteInitiator.h +++ /dev/null @@ -1,108 +0,0 @@ -/* 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. - */ - -#ifndef MBED_NFC_REMOTE_INITIATOR_H -#define MBED_NFC_REMOTE_INITIATOR_H - -#include - -#include "NFCDefinitions.h" -#include "NFCRemoteEndpoint.h" -#include "NFCNDEFCapable.h" -#include "stack/tech/iso7816/iso7816_app.h" - -#include "platform/Span.h" - -namespace mbed { -namespace nfc { - -/** - * @addtogroup nfc - * @{ - */ - -class NFCController; - -/** - * This class represents a remote NFC initiator (the local controller being in target mode). - * - * An initiator can be a NFC reader, a NFC-enabled phone or other NFC device capable of generating a RF field. - */ -class NFCRemoteInitiator : public NFCRemoteEndpoint, public NFCNDEFCapable { -public: - /** - * Create a NFCRemoteInitiator. - * @param[in] controller the NFCController instance that detected this endpoint - * @param[in] buffer a bytes array used to store NDEF messages - */ - NFCRemoteInitiator(NFCController *controller, const Span &buffer); - virtual ~NFCRemoteInitiator(); - - /** - * The NFCRemoteInitiator delegate. Users of the NFCRemoteInitiator class need to implement this delegate's methods to receive events. - */ - struct Delegate : NFCRemoteEndpoint::Delegate, NFCNDEFCapable::Delegate { - protected: - ~Delegate() {} - }; - - /** - * Set the delegate that will receive events generated by the initiator. - * - * @param[in] delegate the delegate instance to use - */ - void set_delegate(Delegate *delegate); - - /** - * Retrieve the NFC tag type exposed by the controller to communicate with the initiator. - * - * @return the relevant NFC tag type - */ - virtual nfc_tag_type_t nfc_tag_type() const = 0; - - /** - * Retrieve whether ISO7816 applications are supported by the underlying technology. - * - * @return whether ISO7816 applications are supported - */ - virtual bool is_iso7816_supported() const = 0; - - /** - * Register an ISO7816 application to be used by the initiator. - * - * @param[in] application a pointer to an nfc_tech_iso7816_app_t instance as defined by the MuNFC stack - */ - virtual void add_iso7816_application(nfc_tech_iso7816_app_t *application) = 0; - -protected: - virtual void connected(); - virtual void disconnected(); - -private: - // NFCNDEFCapable implementation - virtual NFCNDEFCapable::Delegate *ndef_capable_delegate(); - - Delegate *_delegate; -}; - -/** - * @} - */ - -} // namespace nfc -} // namespace mbed - -#endif diff --git a/features/nfc/nfc/NFCTarget.h b/features/nfc/nfc/NFCTarget.h deleted file mode 100644 index b80d835..0000000 --- a/features/nfc/nfc/NFCTarget.h +++ /dev/null @@ -1,109 +0,0 @@ -/* 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. - */ - -#ifndef MBED_NFC_TARGET_H -#define MBED_NFC_TARGET_H - -#include - -#include "NFCDefinitions.h" -#include "NFCNDEFCapable.h" - -#include "platform/Span.h" - -namespace mbed { -namespace nfc { - -/** - * @addtogroup nfc - * @{ - */ - -/** - * This class represents a NFC target (either a remote target when the local controller in in initiator mode, or a target connected through a wired connection). - * - * A target can be a NFC tag/card, a NFC-enabled phone or other NFC device capable of modulating a RF field. - */ -class NFCTarget : public NFCNDEFCapable { -public: - /** - * Create a NFCTarget. - * - * @param[in] buffer a bytes array used to store NDEF messages - */ - NFCTarget(const Span &buffer); - - /** - * NFCTarget destructor - */ - virtual ~NFCTarget(); - - struct Delegate : NFCNDEFCapable::Delegate { - /** - * The NDEF message erasing request completed. - * - * @param[in] result NFC_OK or an error code on failure - */ - virtual void on_ndef_message_erased(nfc_err_t result) {} - - /** - * The NDEF message writing request completed. - * - * @param[in] result NFC_OK or an error code on failure - */ - virtual void on_ndef_message_written(nfc_err_t result) {} - - /** - * The NDEF message reading request completed. - * - * @param[in] result NFC_OK or an error code on failure - */ - virtual void on_ndef_message_read(nfc_err_t result) {} - - protected: - ~Delegate() {} - }; - - /** - * Write a NDEF message to the target. - * - * on_ndef_message_written() will be called on completion. - */ - virtual void write_ndef_message() = 0; - - /** - * Read a NDEF message from the target. - * - * on_ndef_message_read() will be called on completion. - */ - virtual void read_ndef_message() = 0; - - /** - * Erase the NDEF message in the target. - * - * on_ndef_message_erased() will be called on completion. - */ - virtual void erase_ndef_message() = 0; -}; - -/** - * @} - */ - -} // namespace nfc -} // namespace mbed - -#endif diff --git a/features/nfc/nfc/Type4RemoteInitiator.h b/features/nfc/nfc/Type4RemoteInitiator.h deleted file mode 100644 index 5e7ef45..0000000 --- a/features/nfc/nfc/Type4RemoteInitiator.h +++ /dev/null @@ -1,91 +0,0 @@ -/* 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. - */ - -#ifndef MBED_TYPE4_REMOTE_INITIATOR_H -#define MBED_TYPE4_REMOTE_INITIATOR_H - -#include -#include - -#include "NFCNDEFCapable.h" -#include "NFCRemoteInitiator.h" - -#include "nfc/acore/acore/ac_buffer.h" -#include "nfc/acore/acore/ac_buffer_reader.h" -#include "nfc/acore/acore/ac_buffer_builder.h" -#include "nfc/stack/tech/type4/type4_target.h" - -#include "platform/Span.h" - -namespace mbed { -namespace nfc { - -/** - * @addtogroup nfc - * @{ - */ - -/** - * This class is an implementation of the Type 4 tag application. - */ -class Type4RemoteInitiator : public NFCRemoteInitiator { -public: - /** - * Create a Type4RemoteInitiator. - * - * @param[in] controller pointer to the NFCController instance that created this object - * @param[in] buffer a bytes array used to store NDEF messages - */ - Type4RemoteInitiator(NFCController *controller, const Span &buffer); - - /** - * Type4RemoteInitiator destructor. - */ - virtual ~Type4RemoteInitiator(); - - // NFCRemoteEndpoint implementation - virtual nfc_err_t connect(); - virtual nfc_err_t disconnect(); - virtual bool is_connected() const; - virtual bool is_disconnected() const; - virtual nfc_rf_protocols_bitmask_t rf_protocols(); - - // NFCRemoteInitiator implementation - virtual nfc_tag_type_t nfc_tag_type() const; - virtual bool is_iso7816_supported() const; - virtual void add_iso7816_application(nfc_tech_iso7816_app_t *application); - - // NFCNDEFCapable implementation - virtual bool is_ndef_supported() const; - - // Callbacks from NFC stack - void disconnected_callback(); - static void s_disconnected_callback(nfc_tech_iso7816_t *pIso7816, void *pUserData); - - bool _is_connected; - bool _is_disconnected; - nfc_tech_iso7816_t _iso7816; - nfc_tech_type4_target_t _type4; -}; - -/** - * @} - */ - -} // namespace nfc -} // namespace mbed - -#endif diff --git a/features/nfc/nfc/ndef/MessageBuilder.h b/features/nfc/nfc/ndef/MessageBuilder.h deleted file mode 100644 index 1b4e38e..0000000 --- a/features/nfc/nfc/ndef/MessageBuilder.h +++ /dev/null @@ -1,196 +0,0 @@ -/* 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. - */ - -#ifndef NFC_NDEF_MESSAGEBUILDER_H_ -#define NFC_NDEF_MESSAGEBUILDER_H_ - -#include - -#include "platform/Span.h" - -#include "nfc/ndef/Record.h" - -namespace mbed { -namespace nfc { -namespace ndef { - -/** @addtogroup nfc - * @{ - */ - -/** - * Construct a NDEF Message. - */ -class MessageBuilder { - -public: - /** - * Build a record payload. - */ - struct PayloadBuilder { - /** - * Return the size of the payload built by this object. - * - * @return The size of the payload. - */ - virtual size_t size() const = 0; - - /** - * Build the payload in a buffer that has the required size. - * - * @param buffer The buffer used to construct the payload. - */ - virtual void build(const Span &buffer) const = 0; - - protected: - /** - * Non virtual destructor. - */ - ~PayloadBuilder() { } - }; - - /** - * Create a new MessageBuilder that can be used to construct valid NDEF - * messages. - * - * @param buffer The data buffer that will contain the NDEF message. - */ - MessageBuilder(const Span &buffer); - - /** - * Append a new record to the message being built. - * - * @param type The type of the record to insert. - * @param payload The payload of the record (optional). - * @param is_last_record true if the record to insert is the last record of - * the payload or false otherwise. - * - * @return true if the record has been successfully inserted or false - * otherwise. - * - * @note insertion can fail if the message is already complete or if the - * size remaining in the message buffer is not large enough to makes the - * record inserted fit. - */ - bool append_record( - const RecordType &type, - const RecordPayload &payload = RecordPayload(), - bool is_last_record = false - ); - - /** - * Append a new record to the message being built. - * - * @param type The type of the record to insert. - * @param builder The builder of the payload. - * @param is_last_record true if the record to insert is the last record of - * the payload or false otherwise. - * - * @return true if the record has been successfully inserted or false - * otherwise. - * - * @note insertion can fail if the message is already complete or if the - * size remaining in the message buffer is not large enough to makes the - * record inserted fit. - */ - bool append_record( - const RecordType &type, - const PayloadBuilder &builder, - bool is_last_record = false - ); - - /** - * Append a new record to the message being built. - * - * @param record The record to insert. - * @param builder The builder that will construct the payload. - * - * @return true if the record has been successfully inserted or false otherwise. - * - * @note insertion can fail if the message is already complete or if the - * size remaining in the message buffer is not large enough to makes the - * record inserted fit. - */ - bool append_record( - const Record &record, - const PayloadBuilder *builder = NULL - ); - - /** - * Compute the size of a record. - * - * @param record The record used to compute the size. - * @param builder The payload builder if any. - * - * @return The size of the payload for the record in input. - */ - static size_t compute_record_size( - const Record &record, - const PayloadBuilder *builder = NULL - ); - - /** - * Reset the builder state. - */ - void reset(); - - /** - * Reset the builder state and assign a new buffer to it. - */ - void reset(const Span &buffer); - - /** - * Return true if the message stored is complete and false otherwise. - * - * @return true if the message is complete or false. - */ - bool is_message_complete() const; - - /** - * Return the buffer storing the data if the message is complete or an empty - * buffer if the message is not complete. - * - * @return The message built. - */ - Span get_message() const; - -private: - // append fields - void append_header(const Record &record, const PayloadBuilder *); - void append_type_length(const Record &record); - void append_payload_length(const Record &, const PayloadBuilder *); - void append_id_length(const Record &); - void append_type(const Record &); - void append_id(const Record &); - void append_payload(const Record &, const PayloadBuilder *); - - // helpers - static bool is_short_payload(const Record &record, const PayloadBuilder *); - static size_t get_payload_size(const Record &, const PayloadBuilder *); - - // builder state. - Span _message_buffer; - size_t _position; - bool _message_started; - bool _message_ended; - bool _in_chunk; -}; -/** @}*/ -} // namespace ndef -} // namespace nfc -} // namespace mbed - -#endif /* NFC_NDEF_MESSAGEBUILDER_H_ */ diff --git a/features/nfc/nfc/ndef/MessageParser.h b/features/nfc/nfc/ndef/MessageParser.h deleted file mode 100644 index a0ac939..0000000 --- a/features/nfc/nfc/ndef/MessageParser.h +++ /dev/null @@ -1,171 +0,0 @@ -/* 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. - */ - -#ifndef NFC_NDEF_MESSAGEPARSER_H_ -#define NFC_NDEF_MESSAGEPARSER_H_ - -#include -#include "platform/Span.h" - -namespace mbed { -namespace nfc { -namespace ndef { - -/** @addtogroup nfc - * @{ - */ - -// Forward declaration -class Record; - -/** - * Event driven NDEF Message parser - */ -class MessageParser { -public: - /** - * Error that can be reported by the parsing operation. - */ - enum error_t { - /** - * The message doesn't start with a message start tag. - */ - INVALID_MESSAGE_START, - - /** - * There is not enough data left to pursue parsing of the message. - */ - INSUFICIENT_DATA, - - /** - * The type name of a record is invalid. - */ - INVALID_TYPE_NAME_FORMAT, - - /** - * An empty record is malformed. - */ - INVALID_EMPTY_RECORD, - - /** - * Record of unknown type embed a type length different than 0. - */ - INVALID_UNKNOWN_TYPE_LENGTH, - - /** - * Record of unchanged type contains a type. - */ - INVALID_UNCHANGED_TYPE, - - /** - * Chunk record encountered. - */ - CHUNK_RECORD_NOT_SUPPORTED, - - /** - * Message is not properly closed. - */ - MISSING_MESSAGE_END, - - /** - * Type is missing in a record expecting a type (well known type, media - * type, absolute uri or external type). - */ - MISSING_TYPE_VALUE - }; - - /** - * Report parsing event to the application. - */ - struct Delegate { - /** - * Invoked when parsing as started. - */ - virtual void on_parsing_started() { } - - /** - * Invoked when a record has been parsed. - * - * @param record The record obtained from parsing. - */ - virtual void on_record_parsed(const Record &record) { } - - /** - * Invoked when parsing is over. - */ - virtual void on_parsing_terminated() { } - - /** - * Invoked when an error is present in the message. - * @param error The error present in the message. - */ - virtual void on_parsing_error(error_t error) { } - - protected: - /** - * Protected non virtual destructor. - * Delegate is not meant to be destroyed in a polymorphic manner. - */ - ~Delegate() { } - }; - - /** - * Construct a message parser. - */ - MessageParser(); - - /** - * Set the handler that processes parsing events. - * @param delegate The parsing event handler. - */ - void set_delegate(Delegate *delegate); - - /** - * Parse an NDEF Message. - * - * Records and errors are reported to the handler registered with - * set_event_handler. - * - * @param data_buffer The data buffer that contains the NDEF message. - */ - void parse(const Span &data_buffer); - -private: - struct parsing_state_t; - - // parser - bool parse_record(parsing_state_t &it); - - static uint8_t compute_lengths_size(uint8_t header); - static uint8_t extract_type_length(parsing_state_t &s); - static uint32_t extract_payload_length(parsing_state_t &s, uint8_t header); - static uint8_t extract_id_length(parsing_state_t &s, uint8_t header); - - // reporting - void report_parsing_started(); - void report_record_parsed(const Record &record); - void report_parsing_terminated(); - void report_parsing_error(error_t error, parsing_state_t &parsing_state); - - Delegate *_delegate; -}; -/** @}*/ -} // namespace ndef -} // namespace nfc -} // namespace mbed - - -#endif /* NFC_NDEF_MESSAGEPARSER_H_ */ diff --git a/features/nfc/nfc/ndef/Record.h b/features/nfc/nfc/ndef/Record.h deleted file mode 100644 index 7c6fcd2..0000000 --- a/features/nfc/nfc/ndef/Record.h +++ /dev/null @@ -1,216 +0,0 @@ -/* 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. - */ - -#ifndef NFC_NDEF_RECORD_H_ -#define NFC_NDEF_RECORD_H_ - -#include - -#include "platform/Span.h" - -namespace mbed { -namespace nfc { -namespace ndef { - -/** - * @addtogroup nfc - * @{ - */ - - -/** - * Set of constants of a record header - */ -struct Header { - static const uint8_t message_begin_bit = (1 << 7); - static const uint8_t message_end_bit = (1 << 6); - static const uint8_t chunk_flag_bit = (1 << 5); - static const uint8_t short_record_bit = (1 << 4); - static const uint8_t id_length_bit = (1 << 3); - static const uint8_t tnf_bits = (1 << 0) | (1 << 1) | (1 << 2); -}; - -/** - * Encode a record type. - * - * A RecordType is composed of a type name format flag and an optional type - * value. - */ -struct RecordType { - /** - * Type name format of a record. - */ - enum tnf_t { - /** - * empty type; value must be empty. - */ - empty = 0x00, //!< empty - - /** - * Type defined by the NFC forum; value must be defined. - */ - well_known_type = 0x01,//!< well_known_type - - /** - * Mime type; value must be defined. - */ - media_type = 0x02, //!< media_type - - /** - * Absolute URI; value must be defined. - */ - absolute_uri = 0x03, //!< absolute_uri - - /** - * Type defined by vendors; value must be defined. - */ - external_type = 0x04, //!< external_type - - /** - * Unknown type; value must be empty. - */ - unknown = 0x05, //!< unknown - - /** - * Use for middle and terminating chunk record. - * value must be empty. - */ - unchanged = 0x06 //!< unchanged - }; - - /** - * Construct an unknown type. - */ - RecordType() : tnf(unknown), value() { } - - /** - * Construct a type with no value. - * - * @note Valid tnf are: empty, unknown and unchanged. - * - * @param tnf The type name format of the type. - */ - RecordType(tnf_t tnf) : - tnf(tnf), value() - { } - - /** - * Construct a RecordType from a type name format and its associated value. - * - * @param tnf The type name format of the record type. - * @param value The value associated with the tnf. - */ - RecordType(tnf_t tnf, const Span &value) : - tnf(tnf), value(value) - { } - - /** - * Type name format of the record type. - */ - tnf_t tnf; - - /** - * Value associated with the record type. It can be empty. - */ - Span value; -}; - -/** - * Definition of a Record payload. - * - * @note A payload can be empty. - */ -typedef Span RecordPayload; - -/** - * Definition of a Record IR. - * - * @note ID's are optional and therefore it can be empty. - */ -typedef Span RecordID; - -/** - * Represent a record. - */ -struct Record { - /** - * Construct an empty record. - */ - Record() : type(), payload(), id(), chunk(false), last_record(false) { } - - /** - * Construct a record from its type, payload and id. - * - * The flags chunk and last_record can be added to indicate if the record - * is aprt of a chunk or the last one in a message. - * - * @param type The type of the record. - * @param payload The payload of the record. - * @param id The id associated with the record. - * @param chunk If true then this record is a chunk of a bigger record. - * @param last_record If true then this record is the last of the message - * containing it. - */ - Record( - RecordType type, - const RecordPayload &payload, - const RecordID &id, - bool chunk, - bool last_record - ) : - type(type), - payload(payload), - id(id), - chunk(chunk), - last_record(last_record) - { } - - /** - * Type of the record. - */ - RecordType type; - - /** - * Value of the payload. - */ - RecordPayload payload; - - /** - * ID of the record. - */ - RecordID id; - - /** - * If true, this record is a chunked record. - */ - bool chunk: 1; - - /** - * If true, this record is the last one of the payload containing it. - */ - bool last_record: 1; -}; - - -/** - * @} - */ - -} // namespace ndef -} // namespace nfc -} // namespace mbed - -#endif /* NFC_NDEF_RECORD_H_ */ diff --git a/features/nfc/nfc/ndef/RecordParser.h b/features/nfc/nfc/ndef/RecordParser.h deleted file mode 100644 index 4c09078..0000000 --- a/features/nfc/nfc/ndef/RecordParser.h +++ /dev/null @@ -1,172 +0,0 @@ -/* 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. - */ - -#ifndef NFC_NDEF_RECORDPARSER_H_ -#define NFC_NDEF_RECORDPARSER_H_ - -#include - -#include "nfc/ndef/Record.h" - -namespace mbed { -namespace nfc { -namespace ndef { - -/** - * @addtogroup nfc - * @{ - */ - -/** - * Parse a record. - */ -struct RecordParser { - /** - * Construct a record parser. - */ - RecordParser() : _next_parser(NULL) { } - - /** - * Parse the record in input. - * @param record The NDEF record to parse. - * @return true if decoding has succeeded and false otherwise. - */ - virtual bool parse(const Record &record) = 0; - -protected: - /** - * Protected non virtual destructor. - * RecordParser subclasses are not meant to be destroyed as RecordParser's. - */ - ~RecordParser() { } - -private: - friend class RecordParserChain; - RecordParser *_next_parser; -}; - - -/** - * GenericRecordParser. - * - * @tparam ParserImplementation the implementation type of the parser. - * It must provides A decoding function named do_parse that accept a const - * reference to a record and a reference to the type parsed and return a boolean - * status that indicates the result of the parsing operation. - * - * @tparam ParsingResult Type produced by the parsing operation when successful. - */ -template -struct GenericRecordParser : public RecordParser { - - /** - * Handle that receives parsed values. - */ - struct Delegate { - /** - * Called when a record has been parsed and converted into a value_type. - * - * @param object_parsed The record in its parsed form. - * @param id The RecordId associated with the object parsed. - */ - virtual void on_record_parsed(const ParsingResult &object_parsed, const RecordID &id) = 0; - - protected: - ~Delegate() { } - }; - - /** - * Construct a record parser. - */ - GenericRecordParser() : _delegate(NULL) { } - - /** - * @see RecordParser::parse - */ - virtual bool parse(const Record &record) - { - ParsingResult parsed_value; - if (static_cast(this)->do_parse(record, parsed_value)) { - if (_delegate) { - _delegate->on_record_parsed(parsed_value, record.id); - } - return true; - } - return false; - } - - /** - * Set the delegate that processes record parser. - * - * @param delegate The delegate to set. - */ - void set_delegate(Delegate *delegate) - { - _delegate = delegate; - } - -protected: - /** - * Protected non virtual destructor. - */ - ~GenericRecordParser() { } - -private: - Delegate *_delegate; -}; - - -/** - * Record parser chain. - */ -struct RecordParserChain { - /** - * Construct a parser chain. - */ - RecordParserChain() : _parsers(NULL) { } - - /** - * Destroy a parser chain. - */ - ~RecordParserChain() { } - - /** - * Parse a record. - * @param record The record to parse. - * @return true if the record has been parsed and false otherwise. - */ - bool parse(const Record &record); - - /** - * Add a parser at the end of the parser list. - * @param parser The parser to add. - */ - void set_next_parser(RecordParser *parser); - -private: - RecordParser *_parsers; -}; - -/** - * @} - */ - -} // namespace ndef -} // namespace nfc -} // namespace mbed - - -#endif /* NFC_NDEF_RECORDPARSER_H_ */ diff --git a/features/nfc/nfc/ndef/common/Mime.h b/features/nfc/nfc/ndef/common/Mime.h deleted file mode 100644 index ebf66e3..0000000 --- a/features/nfc/nfc/ndef/common/Mime.h +++ /dev/null @@ -1,155 +0,0 @@ -/* 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. - */ - -#ifndef NFC_COMMON_MIME_H_ -#define NFC_COMMON_MIME_H_ - -#include - -#include "platform/Span.h" - -#include "nfc/ndef/RecordParser.h" -#include "nfc/ndef/MessageBuilder.h" - -namespace mbed { -namespace nfc { -namespace ndef { -namespace common { - -/** - * @addtogroup nfc - * @{ - */ - -/** - * Represent a mime object. - */ -class Mime { -public: - /** - * Construct an empty Mime object. - */ - Mime(); - - /** - * Construct a mime object from its type and content - * - * @param mime_type The mime type of the object. - * @param content The content of the object. - * - * @note To remove the NULL terminator of the C-string of the mime_type - * parameter, you can use the utility function span_from_cstr. - */ - Mime( - const Span &mime_type, - const Span &content - ); - - /** - * Copy construct a Mime object. - * @param other The Mime object copied. - */ - Mime(const Mime &other); - - /** - * Destroy a Mime object. - */ - ~Mime(); - - /** - * Copy assign a Mime object. - * - * @param other The Mime object to copy. - * - * @return a reference to this object - */ - Mime &operator=(const Mime &other); - - /** - * Set all attributes of a mime object. - * - * @param mime_type Type of the mime object. - * @param content Content of the mime object. - * - * @note To remove the NULL terminator of the C-string of the mime_type - * parameter, you can use the utility function span_from_cstr. - */ - void set_mime( - const Span &mime_type, - const Span &content - ); - - /** - * Return the mime type. - * @return The mime type. - */ - Span get_mime_type() const; - - /** - * Return the content of the mime object. - * @return the content of the mime object. - */ - Span get_mime_content() const; - - /** - * Append into a message builder - */ - bool append_as_record( - MessageBuilder &message_builder, - bool is_last_record = false - ) const; - - /** - * Compute the size of this Mime object in a ndef record. - * - * @return The size of the ndef record required to store this object. - */ - size_t get_record_size() const; - -private: - friend class MimeParser; - - void move_data( - uint8_t *mime_record, - size_t mime_type_size, - size_t mime_content_size - ); - - size_t mime_size() const; - - uint8_t *_mime; - size_t _type_size; - size_t _content_size; -}; - -/** - * Parse a Mime payload. - */ -class MimeParser : public GenericRecordParser { -public: - bool do_parse(const Record &record, Mime &mime); -}; - -/** - * @} - */ - -} // namespace common -} // namespace ndef -} // namespace nfc -} // namespace mbed - -#endif /* NFC_COMMON_MIME_H_ */ diff --git a/features/nfc/nfc/ndef/common/SimpleMessageParser.h b/features/nfc/nfc/ndef/common/SimpleMessageParser.h deleted file mode 100644 index 2f7bbbc..0000000 --- a/features/nfc/nfc/ndef/common/SimpleMessageParser.h +++ /dev/null @@ -1,170 +0,0 @@ -/* 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. - */ - -#ifndef NFC_COMMON_SIMPLEMESSAGEPARSER_H_ -#define NFC_COMMON_SIMPLEMESSAGEPARSER_H_ - -#include "platform/Span.h" - -#include "nfc/ndef/MessageParser.h" -#include "nfc/ndef/RecordParser.h" -#include "nfc/ndef/common/URI.h" -#include "nfc/ndef/common/Text.h" -#include "nfc/ndef/common/Mime.h" - -namespace mbed { -namespace nfc { -namespace ndef { -namespace common { - -/** @addtogroup nfc - * @{ - */ - -/** - * Basic message parser that aggregates URIParser, TextParser and MimeParser. - * - * Custom parsers can be added at runtime as well. - */ -class SimpleMessageParser : - MessageParser::Delegate, - URIParser::Delegate, - TextParser::Delegate, - MimeParser::Delegate { -public: - /** - * Delegate invoked when the parser raise an event. - */ - struct Delegate { - /** - * Invoked when an error is present in the message. - * @param error The error present in the message. - */ - virtual void on_parsing_error(MessageParser::error_t error) { } - - /** - * Invoked when parsing as started. - */ - virtual void on_parsing_started() { } - - /** - * Invoked when a text element has been parsed. - * - * @param text The text parsed. - * @param id The RecordId of the text object. - */ - virtual void on_text_parsed(const Text &text, const RecordID &id) { } - - /** - * Invoked when a text element has been parsed. - * - * @param uri The uri parsed. - * @param id The RecordId of the uri object. - */ - virtual void on_uri_parsed(const URI &uri, const RecordID &id) { } - - /** - * Invoked when a mime element has been parsed. - * - * @param mime The mime object parsed. - * @param id The RecordId of the mime object. - */ - virtual void on_mime_parsed(const Mime &mime, const RecordID &id) { } - - /** - * Invoked when an unknown record has been parsed. - * @param record The record freshly parsed. - */ - virtual void on_unknown_record_parsed(const Record &record) { } - - /** - * Invoked when parsing is over. - */ - virtual void on_parsing_terminated() { } - - protected: - ~Delegate() { } - }; - - /** - * Construct a new CommonMessageParser. - */ - SimpleMessageParser(); - - /** - * Set the handler that processes parsing events. - * @param delegate The parsing event handler. - */ - void set_delegate(Delegate *delegate); - - /** - * Parse an NDEF Message. - * - * Records and errors are reported to the handler registered with - * set_event_handler. - * - * @param data_buffer The data buffer that contains the NDEF message. - */ - void parse(const Span &data_buffer); - - /** - * Insert a new parser in the parser chain. - * @param parser The parser to add in the parsing chain. - */ - void add_record_parser(RecordParser *parser); - -private: - //////////////////////////////////////////////////////////////////////////// - /// Implementation of MessageParser::EventHandler - - virtual void on_parsing_error(MessageParser::error_t error); - - virtual void on_parsing_started(); - - virtual void on_record_parsed(const Record &record); - - virtual void on_parsing_terminated(); - - //////////////////////////////////////////////////////////////////////////// - /// Implementation of URIParser::EventHandler - - virtual void on_record_parsed(const URI &uri, const RecordID &id); - - //////////////////////////////////////////////////////////////////////////// - /// Implementation of TextParser::EventHandler - - virtual void on_record_parsed(const Text &text, const RecordID &id); - - //////////////////////////////////////////////////////////////////////////// - /// Implementation of MimeParser::EventHandler - - virtual void on_record_parsed(const Mime &mime, const RecordID &id); - - MessageParser _message_parser; - RecordParserChain _record_parser_chain; - URIParser _uri_parser; - TextParser _text_parser; - MimeParser _mime_parser; - Delegate *_delegate; -}; -/** @}*/ -} // namespace common -} // namespace ndef -} // namespace nfc -} // namespace mbed - -#endif /* NFC_COMMON_SIMPLEMESSAGEPARSER_H_ */ - diff --git a/features/nfc/nfc/ndef/common/Text.h b/features/nfc/nfc/ndef/common/Text.h deleted file mode 100644 index e9d62d9..0000000 --- a/features/nfc/nfc/ndef/common/Text.h +++ /dev/null @@ -1,165 +0,0 @@ -/* 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. - */ - -#ifndef NFC_COMMON_TEXT_H_ -#define NFC_COMMON_TEXT_H_ - -#include - -#include "platform/Span.h" - -#include "nfc/ndef/RecordParser.h" -#include "nfc/ndef/MessageBuilder.h" - -namespace mbed { -namespace nfc { -namespace ndef { -namespace common { - -/** - * @addtogroup nfc - * @{ - */ - -/** - * Represent the well known type text. - */ -class Text { -public: - /** - * Encoding of the text. - */ - enum encoding_t { - UTF8 = 0,//!< UTF8 - UTF16 = 1//!< UTF16 - }; - - /** - * Construct an empty text element. - */ - Text(); - - /** - * Construct a text element from a data buffer and an encoding. - * - * @param text_encoding The encoding of the text. - * @param language_code The string of the language code. - * @param text The text buffer. - * - * @note To remove the NULL terminator of the C-string of the language_code - * and text parameters, you can use the utility function span_from_cstr. - */ - Text( - encoding_t text_encoding, - const Span &language_code, - const Span &text - ); - - /** - * Copy construct a text element. - * @param to_copy - */ - Text(const Text &to_copy); - - /** - * Destroy a text element. - */ - ~Text(); - - /** - * Copy assignment of another text element. - * @param to_copy The Text instance to copy - * @return a reference to this object. - */ - Text &operator=(const Text &to_copy); - - /** - * Copy a text from an external buffer. - * - * @param text_encoding The encoding of the text. - * @param language_code The language code of the text. - * @param text The text to copy. - * - * @note To remove the NULL terminator of the C-string of the language_code - * and text parameters, you can use the utility function span_from_cstr. - */ - void set_text( - encoding_t text_encoding, - const Span &language_code, - const Span &text - ); - - /** - * Get the encoding of the text. - * @return The encoding of the text. - */ - encoding_t get_encoding() const; - - /** - * Return the language code. - * @return The language code. - */ - Span get_language_code() const; - - /** - * Return the text contained in this object. - * @return The text contained in this object. - */ - Span get_text() const; - - /** - * Append into a message builder - */ - bool append_as_record( - MessageBuilder &message_builder, - bool is_last_record = false - ) const; - - /** - * Compute the size of this object in a ndef record. - * - * @return The size of the ndef record required to store this object. - */ - size_t get_record_size() const; - -private: - friend class TextParser; - - void move_data(uint8_t *text, size_t size); - - uint8_t *_text_record; - size_t _text_record_size; -}; - -/** - * Parse a Text. - */ -class TextParser : public GenericRecordParser { -public: - virtual bool do_parse(const Record &record, Text &text); -}; - -/** - * @} - */ - -} // namespace common -} // namespace ndef -} // namespace nfc -} // namespace mbed - - -#endif /* NFC_COMMON_TEXT_H_ */ diff --git a/features/nfc/nfc/ndef/common/URI.h b/features/nfc/nfc/ndef/common/URI.h deleted file mode 100644 index 683cdaa..0000000 --- a/features/nfc/nfc/ndef/common/URI.h +++ /dev/null @@ -1,206 +0,0 @@ -/* 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. - */ - -#ifndef NFC_COMMON_URI_H_ -#define NFC_COMMON_URI_H_ - -#include -#include - -#include "platform/Span.h" - -#include "nfc/ndef/RecordParser.h" -#include "nfc/ndef/MessageBuilder.h" - -namespace mbed { -namespace nfc { -namespace ndef { -namespace common { - -/** - * @addtogroup nfc - * @{ - */ - -/** - * Model the well known type URI. - */ -class URI { -public: - /** - * Identifier codes - */ - enum uri_identifier_code_t { - NA = 0x00, /// Not applicable - HTTP_WWW = 0x01, /// http://www. - HTTPS_WWW = 0x02, /// https://www. - HTTP = 0x03, /// http:// - HTTPS = 0x04, /// https:// - TEL = 0x05, /// tel: - MAILTO = 0x06, /// mailto: - FTP_ANONYMOUS = 0x07, /// ftp://anonymous:anonymous@ - FTP_FTP = 0x08, /// ftp://ftp. - FTPS = 0x09, /// ftps:// - SFTP = 0x0A, /// sftp:// - SMB = 0x0B, /// smb:// - NFS = 0x0C, /// nfs:// - FTP = 0x0D, /// ftp:// - DAV = 0x0E, /// dav:// - NEWS = 0x0F, /// news: - TELNET = 0x10, /// telnet:// - IMAP = 0x11, /// imap: - RSTP = 0x12, /// rstp:// - URN = 0x13, /// urn: - POP = 0x14, /// pop: - SIP = 0x15, /// sip: - SIPS = 0x16, /// sips: - TFTP = 0x17, /// tftp: - BTSPP = 0x18, /// btspp:// - BTL2CAP = 0x19, /// btl2cap:// - BTGOEP = 0x1A, /// btgoep:// - TCPOBEX = 0x1B, /// tcpobex:// - IRDAOBEX = 0x1C, /// irdaobex:// - FILE = 0x1D, /// file:// - URN_EPC_ID = 0x1E, /// urn:epc:id: - URN_EPC_TAG = 0x1F, /// urn:epc:tag: - URN_EPC_PAT = 0x20, /// urn:epc:pat: - URN_EPC_RAW = 0x21, /// urn:epc:raw: - URN_EPC = 0x22, /// urn:epc: - URN_NFC = 0x23, /// urn:nfc: - }; - - /** - * Construct an empty URI object. - */ - URI(); - - /** - * Construct a URI from an id and a uri field. - * - * @param id The code of the URI prefix. - * @param uri_field The URI itself. - * - * @note To remove the NULL terminator of the C-string of the uri_field - * parameter, you can use the utility function span_from_cstr. - */ - URI(uri_identifier_code_t id, const Span &uri_field); - - /** - * Construct a URI from another URI. - * @param to_copy The uri copied. - */ - URI(const URI &to_copy); - - /** - * Destroy a URI object. - */ - ~URI(); - - /** - * Replace the content by the one of an existing URI. - * @param to_copy The URI to copy. - * @return a reference to this object - */ - URI &operator=(const URI &to_copy); - - /** - * Replace the value of the URI. - * - * @param id The ID of the URI - * @param uri_field A buffer containing the value of the URI field. - * - * @note To remove the NULL terminator of the C-string of the uri_field - * parameter, you can use the utility function span_from_cstr. - */ - void set_uri( - uri_identifier_code_t id, - const Span &uri_field - ); - - /** - * Return the id of the uri. - * @return The id of the uri. - */ - uri_identifier_code_t get_id() const; - - /** - * Return the current value of the uri field. - * @return The value of the uri field. - */ - Span get_uri_field() const; - - /** - * Append into a message builder - */ - bool append_as_record( - MessageBuilder &message_builder, - bool is_last_record = false - ) const; - - /** - * Compute the size of this object in a ndef record. - * - * @return The size of the ndef record required to store this object. - */ - size_t get_record_size() const; - - /** - * Equal operator between two URIs - * @param lhs The URI on the left hand side - * @param rhs The URI on the right hand side - * @return true if lhs equals rhs or false. - */ - friend bool operator==(const URI &lhs, const URI &rhs) - { - if (lhs._uri_size != rhs._uri_size) { - return false; - } - - return memcmp(lhs._uri, rhs._uri, lhs._uri_size) == 0; - } - - friend bool operator!=(const URI &lhs, const URI &rhs) - { - return !(lhs == rhs); - } - -private: - friend class URIParser; - - void move_data(uint8_t *text, size_t size); - - uint8_t *_uri; - size_t _uri_size; -}; - -/** - * Parser of a URI. - */ -class URIParser : public GenericRecordParser { -public: - bool do_parse(const Record &record, URI &uri); -}; - -/** - * @} - */ - -} // namespace common -} // namespace ndef -} // namespace nfc -} // namespace mbed - -#endif /* NFC_COMMON_URI_H_ */ diff --git a/features/nfc/nfc/ndef/common/util.h b/features/nfc/nfc/ndef/common/util.h deleted file mode 100644 index 1be5577..0000000 --- a/features/nfc/nfc/ndef/common/util.h +++ /dev/null @@ -1,69 +0,0 @@ -/* 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. - */ - -#ifndef FEATURES_NFC_SOURCE_NFC_COMMON_UTIL_H_ -#define FEATURES_NFC_SOURCE_NFC_COMMON_UTIL_H_ - -#include "platform/Span.h" - -namespace mbed { -namespace nfc { -namespace ndef { -namespace common { - -/** - * @addtogroup nfc - * @{ - */ - -/** - * Convert a C-string into a Span. - * - * @note The NULL charactere is not present in the resulting object. - * - * @param cstr The cstr to convert into a Span. - * - * @return A Span that views cstr but doesn't include the NULL terminator - * character. - */ -template -Span < const uint8_t, N - 1 > span_from_cstr(const char (&cstr)[N]) -{ - return Span < const uint8_t, N - 1 > ((const uint8_t *)cstr, N - 1); -} - -/** - * Convert a C-string into a Span. - * - * @note The NULL charactere is not present in the resulting object. - * - * @param cstr The cstr to convert into a Span. - * - * @return A Span that views cstr but doesn't include the NULL terminator - * character. - */ -Span span_from_cstr(const char *cstr); - -/** - * @} - */ - -} // namespace common -} // namespace ndef -} // namespace nfc -} // namespace mbed - -#endif /* FEATURES_NFC_SOURCE_NFC_COMMON_UTIL_H_ */ diff --git a/features/nfc/source/controllers/PN512Driver.cpp b/features/nfc/source/controllers/PN512Driver.cpp deleted file mode 100644 index 9f42460..0000000 --- a/features/nfc/source/controllers/PN512Driver.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/* 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 "PN512Driver.h" - -#include "nfc/stack/platform/nfc_debug.h" - -using namespace mbed; -using namespace mbed::nfc; - -PN512Driver::PN512Driver(PN512TransportDriver *transport_driver) : NFCControllerDriver(), _transport_driver(transport_driver) -{ - _transport_driver->set_delegate(this); -} - -nfc_transceiver_t *PN512Driver::initialize(nfc_scheduler_timer_t *scheduler_timer) -{ - // Initialize transport - _transport_driver->initialize(); - - nfc_err_t ret = pn512_init(&_pn512, _transport_driver->get_transport(), scheduler_timer); - if (ret != NFC_OK) { - NFC_ERR("PN512 init error (%d)", ret); - return NULL; - } - NFC_DBG("PN512 Initialized"); - - return pn512_get_transceiver(&_pn512); -} - -void PN512Driver::get_supported_nfc_techs(nfc_tech_t *initiator, nfc_tech_t *target) const -{ - initiator->nfc_type1 = 0; - initiator->nfc_type2 = 1; - initiator->nfc_type3 = 1; - initiator->nfc_iso_dep_a = 1; - initiator->nfc_iso_dep_b = 0; - initiator->nfc_nfc_dep_a = 1; - initiator->nfc_nfc_dep_f_212 = 1; - initiator->nfc_nfc_dep_f_424 = 1; - - target->nfc_type1 = 0; - target->nfc_type2 = 0; - target->nfc_type3 = 0; - target->nfc_iso_dep_a = 1; - target->nfc_iso_dep_b = 0; - target->nfc_nfc_dep_a = 1; - target->nfc_nfc_dep_f_212 = 1; - target->nfc_nfc_dep_f_424 = 1; -} - -void PN512Driver::on_hw_interrupt() -{ - hw_interrupt(); // Propagate interrupt signal -} diff --git a/features/nfc/source/controllers/PN512SPITransportDriver.cpp b/features/nfc/source/controllers/PN512SPITransportDriver.cpp deleted file mode 100644 index 1fb9f99..0000000 --- a/features/nfc/source/controllers/PN512SPITransportDriver.cpp +++ /dev/null @@ -1,117 +0,0 @@ -/* 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 "platform/platform.h" - -#if (defined (DEVICE_SPI) && defined (DEVICE_INTERRUPTIN)) || defined(DOXYGEN_ONLY) - -#include "PN512SPITransportDriver.h" - -#include "stack/transceiver/transceiver.h" -#include "platform/mbed_wait_api.h" - -using namespace mbed; -using namespace mbed::nfc; - -PN512SPITransportDriver::PN512SPITransportDriver(PinName mosi, PinName miso, PinName sclk, PinName ssel, PinName irq, PinName rst) : - _spi(mosi, miso, sclk), - _ssel(ssel, 1), - _irq(irq, PullNone), - _rst(rst, 1) -{ - - // Use SPI mode 0 - _spi.format(8, 0); - - // The PN512 supports SPI clock frequencies up to 10MHz, so use this if we can - _spi.frequency(10000000UL); - - // Initialize NFC transport - nfc_transport_init(&_nfc_transport, &PN512SPITransportDriver::s_transport_write, &PN512SPITransportDriver::s_transport_read, this); -} - -void PN512SPITransportDriver::initialize() -{ - // Deactivate IRQ - _irq.rise(callback()); - - // Assert reset pin - // According to the datasheet, it needs to be asserted for at least 100ns - // Wait for 1us as that's the shortest time we can wait for - _rst = 0; - wait_us(1); - _rst = 1; - - // Setup IRQ pin - _irq.rise(callback(this, &PN512SPITransportDriver::hw_interrupt)); -} - -nfc_transport_t *PN512SPITransportDriver::get_transport() -{ - return &_nfc_transport; -} - -void PN512SPITransportDriver::transport_write(uint8_t address, const uint8_t *outBuf, size_t outLen) -{ - if (outLen == 0) { - return; - } - - // First byte is (address << 1) | 0x00 for a write - address = (address << 1) | 0x00; - _ssel = 0; - _spi.write(address); // First write address byte - _spi.write((const char *) outBuf, outLen, (char *) NULL, 0); // Ignore read bytes - _ssel = 1; -} - -void PN512SPITransportDriver::transport_read(uint8_t address, uint8_t *inBuf, size_t inLen) -{ - if (inLen == 0) { - return; - } - - // Address byte is (address << 1) | 0x80 for a read - // This should be repeated accross the transfer, except for the last byte which should be 0 - address = (address << 1) | 0x80; - - // Set this byte across inBuf so that it's repeated accross the transfer - // Bit cheeky, but will work - memset(inBuf, address, inLen - 1); - - // Also terminate with 0 so that it's a no-op - inBuf[inLen - 1] = 0; - - _ssel = 0; - _spi.write(address); // First write address byte - _spi.write((const char *) inBuf, inLen, (char *) inBuf, inLen); - _ssel = 1; -} - -// Callbacks from munfc -void PN512SPITransportDriver::s_transport_write(uint8_t address, const uint8_t *outBuf, size_t outLen, void *pUser) -{ - PN512SPITransportDriver *self = (PN512SPITransportDriver *)pUser; - self->transport_write(address, outBuf, outLen); -} - -void PN512SPITransportDriver::s_transport_read(uint8_t address, uint8_t *inBuf, size_t inLen, void *pUser) -{ - PN512SPITransportDriver *self = (PN512SPITransportDriver *)pUser; - self->transport_read(address, inBuf, inLen); -} - -#endif diff --git a/features/nfc/source/controllers/PN512TransportDriver.cpp b/features/nfc/source/controllers/PN512TransportDriver.cpp deleted file mode 100644 index f065349..0000000 --- a/features/nfc/source/controllers/PN512TransportDriver.cpp +++ /dev/null @@ -1,42 +0,0 @@ -/* 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 "PN512TransportDriver.h" - -using namespace mbed; -using namespace mbed::nfc; - -PN512TransportDriver::PN512TransportDriver() : _delegate(NULL) -{ - -} - -PN512TransportDriver::~PN512TransportDriver() -{ - -} - -void PN512TransportDriver::set_delegate(Delegate *delegate) -{ - _delegate = delegate; -} - -void PN512TransportDriver::hw_interrupt() -{ - if (_delegate != NULL) { - _delegate->on_hw_interrupt(); - } -} diff --git a/features/nfc/source/nfc/NFCController.cpp b/features/nfc/source/nfc/NFCController.cpp deleted file mode 100644 index 8101558..0000000 --- a/features/nfc/source/nfc/NFCController.cpp +++ /dev/null @@ -1,240 +0,0 @@ -/* 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 "NFCController.h" -#include "NFCControllerDriver.h" -#include "Type4RemoteInitiator.h" - -#include "stack/transceiver/transceiver.h" - -using std::milli; -using namespace std::chrono; -using namespace mbed; -using namespace mbed::nfc; - -NFCController::NFCController(NFCControllerDriver *driver, events::EventQueue *queue, const Span &ndef_buffer) : - _driver(driver), _queue(queue), _transceiver(NULL), _scheduler(NULL), _delegate(NULL), _discovery_running(false), _ndef_buffer(ndef_buffer) -{ - _driver->set_delegate(this); -} - -nfc_err_t NFCController::initialize() -{ - MBED_ASSERT(_transceiver == NULL); // Initialize should only be called once - _transceiver = _driver->initialize((nfc_scheduler_timer_t *)&_timer); // See implementation below - - if (_transceiver == NULL) { - // Initialization error - return NFC_ERR_CONTROLLER; // Controller error - } - - // Recover scheduler - _scheduler = transceiver_get_scheduler(_transceiver); - - // Run scheduler for the first time - _queue->call(this, &NFCController::scheduler_process, false); - - return NFC_OK; -} - -void NFCController::set_delegate(Delegate *delegate) -{ - _delegate = delegate; -} - -nfc_rf_protocols_bitmask_t NFCController::get_supported_rf_protocols() const -{ - // nfc_rf_protocols_bitmask_t is mapped on NFC Forum types, nfc_tech_t is mapped on the underlying RF techs - // We therefore need to convert these - - nfc_rf_protocols_bitmask_t rf_protocols = {0}; - nfc_tech_t initiator_tech; - nfc_tech_t target_tech; - _driver->get_supported_nfc_techs(&initiator_tech, &target_tech); - - // Note: we only support ISO-DEP tag emulation in this release, - // so mask out all other protocols - - // rf_protocols.initiator_t1t = initiator_tech.nfc_type1; - // rf_protocols.initiator_t2t = initiator_tech.nfc_type2; - // rf_protocols.initiator_t3t = initiator_tech.nfc_type3; - // rf_protocols.initiator_iso_dep = initiator_tech.nfc_iso_dep_a || initiator_tech.nfc_iso_dep_b; - // 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; - - // rf_protocols.target_t1t = target_tech.nfc_type1; - // rf_protocols.target_t2t = target_tech.nfc_type2; - // rf_protocols.target_t3t = target_tech.nfc_type3; - rf_protocols.target_iso_dep = target_tech.nfc_iso_dep_a || target_tech.nfc_iso_dep_b; - // 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; - - return rf_protocols; -} - -nfc_err_t NFCController::configure_rf_protocols(nfc_rf_protocols_bitmask_t rf_protocols) -{ - if (_discovery_running) { - // Cannot configure RF protocols if discovery is running - return NFC_ERR_BUSY; - } - - // Map to NFC techs - nfc_tech_t initiator_tech = {0}; - nfc_tech_t target_tech = {0}; - - // Note: we only support ISO-DEP tag emulation in this release, - // so mask out all other protocols - - target_tech.nfc_iso_dep_a = target_tech.nfc_iso_dep_b = true; - - // Configure polling options (no need to set bailing flags as we're only using target mode) - polling_options_t options = {0}; - options.listen_for = -1; // Listen forever - - transceiver_set_protocols(_transceiver, initiator_tech, target_tech, options); - - return NFC_OK; -} - -nfc_err_t NFCController::start_discovery() -{ - if (_discovery_running) { - // Cannot start discovery if it's already running - return NFC_ERR_BUSY; - } - - transceiver_poll(_transceiver, &NFCController::s_polling_callback, this /* use this as callback argument */); - - return NFC_OK; -} - -nfc_err_t NFCController::cancel_discovery() -{ - if (!_discovery_running) { - return NFC_OK; - } - - transceiver_abort(_transceiver); - - return NFC_OK; -} - -nfc_transceiver_t *NFCController::transceiver() const -{ - return _transceiver; -} - -void NFCController::polling_callback(nfc_err_t ret) -{ - // Polling has completed - _discovery_running = false; - - NFC_DBG("Polling finished with result %u", ret); - - if (ret == NFC_OK) { - // Check if a remote initiator was detected and if so, instantiate it - 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) && (_delegate != NULL)) { - Type4RemoteInitiator *type4_remote_initiator_ptr = new (std::nothrow) Type4RemoteInitiator(this, _ndef_buffer); - if (type4_remote_initiator_ptr != NULL) { - SharedPtr type4_remote_initiator(type4_remote_initiator_ptr); - _delegate->on_nfc_initiator_discovered(type4_remote_initiator); - } - } - } - } - - if (_delegate != NULL) { - Delegate::nfc_discovery_terminated_reason_t reason; - - // Map reason - switch (ret) { - case NFC_OK: - reason = Delegate::nfc_discovery_terminated_completed; - break; - case NFC_ERR_ABORTED: - reason = Delegate::nfc_discovery_terminated_canceled; - break; - default: - // Any other error code means there was an error during the discovery process - reason = Delegate::nfc_discovery_terminated_rf_error; - break; - } - - _delegate->on_discovery_terminated(reason); - } -} - -void NFCController::scheduler_process(bool hw_interrupt) -{ - _timeout.detach(); // Cancel timeout - if it triggers, it's ok as we'll have an "early" iteration which will likely be a no-op - - // Process stack events - duration timeout{nfc_scheduler_iteration(_scheduler, hw_interrupt ? EVENT_HW_INTERRUPT : EVENT_NONE)}; - - _timeout.attach(callback(this, &NFCController::on_timeout), timeout); -} - -void NFCController::on_hw_interrupt() -{ - // Run scheduler - this is called in interrupt context - _timeout.detach(); // Cancel timeout - if it triggers anyways, it's ok - _queue->call(this, &NFCController::scheduler_process, true); -} - -void NFCController::on_timeout() -{ - // Run scheduler - this is called in interrupt context - _queue->call(this, &NFCController::scheduler_process, false); -} - -void NFCController::s_polling_callback(nfc_transceiver_t *pTransceiver, nfc_err_t ret, void *pUserData) -{ - NFCController *self = (NFCController *) pUserData; - self->polling_callback(ret); -} - -// Implementation nfc_scheduler_timer_t -void nfc_scheduler_timer_init(nfc_scheduler_timer_t *timer) -{ - (void)timer; // This is a no-op -} - -void nfc_scheduler_timer_start(nfc_scheduler_timer_t *timer) -{ - Timer *mbed_timer = (Timer *)timer; - mbed_timer->start(); -} - -uint32_t nfc_scheduler_timer_get(nfc_scheduler_timer_t *timer) -{ - Timer *mbed_timer = (Timer *)timer; - return (uint32_t)std::chrono::duration_cast( - mbed_timer->elapsed_time() - ).count(); -} - -void nfc_scheduler_timer_stop(nfc_scheduler_timer_t *timer) -{ - Timer *mbed_timer = (Timer *)timer; - mbed_timer->stop(); -} - -void nfc_scheduler_timer_reset(nfc_scheduler_timer_t *timer) -{ - Timer *mbed_timer = (Timer *)timer; - mbed_timer->reset(); -} diff --git a/features/nfc/source/nfc/NFCControllerDriver.cpp b/features/nfc/source/nfc/NFCControllerDriver.cpp deleted file mode 100644 index bc9810a..0000000 --- a/features/nfc/source/nfc/NFCControllerDriver.cpp +++ /dev/null @@ -1,42 +0,0 @@ -/* 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 "NFCControllerDriver.h" - -using namespace mbed; -using namespace mbed::nfc; - -NFCControllerDriver::NFCControllerDriver() : _delegate(NULL) -{ - -} - -NFCControllerDriver::~NFCControllerDriver() -{ - -} - -void NFCControllerDriver::set_delegate(Delegate *delegate) -{ - _delegate = delegate; -} - -void NFCControllerDriver::hw_interrupt() -{ - if (_delegate != NULL) { - _delegate->on_hw_interrupt(); - } -} diff --git a/features/nfc/source/nfc/NFCEEPROM.cpp b/features/nfc/source/nfc/NFCEEPROM.cpp deleted file mode 100644 index e3dd759..0000000 --- a/features/nfc/source/nfc/NFCEEPROM.cpp +++ /dev/null @@ -1,426 +0,0 @@ -/* 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::NFCEEPROM(NFCEEPROMDriver *driver, events::EventQueue *queue, const Span &ndef_buffer) - : - NFCTarget(ndef_buffer), _delegate(NULL), _driver(driver), _event_queue(queue), _initialized(false), - _current_op(nfc_eeprom_idle), _ndef_buffer_reader { nullptr, 0, nullptr }, _ndef_buffer_read_sz(0), - _eeprom_address(0), _operation_result(NFC_ERR_UNKNOWN) -{ - _driver->set_delegate(this); - _driver->set_event_queue(queue); -} - -nfc_err_t NFCEEPROM::initialize() -{ - MBED_ASSERT(_initialized == false); // Initialize should only be called once - - // Initialize driver - _driver->reset(); - _initialized = true; - return NFC_OK; -} - -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->read_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 - - 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_erase_start_session; - - // Reset EEPROM address - _eeprom_address = 0; - - // Go through the steps! - _driver->start_session(); - - // 1 - Start session - // 2 - Set addressable size to the max - // 3 - Erase bytes (can be repeated) - // 4 - Set addressable size to 0 - // 5 - End session -} - -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_size; - _driver->write_size(ac_buffer_reader_readable(&_ndef_buffer_reader)); - 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; - - case nfc_eeprom_erase_start_session: - if (!success) { - handle_error(NFC_ERR_CONTROLLER); - return; - } - - _current_op = nfc_eeprom_erase_write_max_size; - _driver->write_size(_driver->read_max_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) { - _delegate->on_ndef_message_written(_operation_result); - } - break; - - case nfc_eeprom_read_end_session: - if (!success) { - handle_error(NFC_ERR_CONTROLLER); - return; - } - _current_op = nfc_eeprom_idle; - - // Try to parse the NDEF message - ndef_msg_decode(ndef_message()); - - if (_delegate != NULL) { - _delegate->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) { - _delegate->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); - return; - } -} - -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 - _event_queue->call(this, &NFCEEPROM::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) -{ - switch (_current_op) { - case nfc_eeprom_write_write_bytes: - if (count == 0) { - handle_error(NFC_ERR_CONTROLLER); - return; - } - - // Skip bytes that were actually written and update address - _eeprom_address += count; - ac_buffer_read_n_skip(&_ndef_buffer_reader, count); - - // Continue writing - _event_queue->call(this, &NFCEEPROM::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; - } - - _current_op = nfc_eeprom_write_write_bytes; - continue_write(); - break; - case nfc_eeprom_erase_write_max_size: - if (!success) { - handle_error(NFC_ERR_CONTROLLER); - return; - } - - // Start erasing bytes - _current_op = nfc_eeprom_erase_erase_bytes; - continue_erase(); - break; - case nfc_eeprom_erase_write_0_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: - // 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) -{ - 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; - _event_queue->call(this, &NFCEEPROM::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 - _event_queue->call(this, &NFCEEPROM::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::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 { - // we are done - _current_op = nfc_eeprom_write_end_session; - _operation_result = NFC_OK; - _driver->end_session(); - } -} - -void NFCEEPROM::continue_erase() -{ - if (_eeprom_address < _driver->read_max_size()) { - // Continue erasing - _driver->erase_bytes(_eeprom_address, _driver->read_max_size() - _eeprom_address); - } else { - // Now update size - _current_op = nfc_eeprom_erase_write_0_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 - _current_op = nfc_eeprom_read_end_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; - _current_op = nfc_eeprom_idle; - - if (_delegate != NULL) { - if (last_op <= nfc_eeprom_write_end_session) { - _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); - } - } -} - -NFCNDEFCapable::Delegate *NFCEEPROM::ndef_capable_delegate() -{ - return _delegate; -} diff --git a/features/nfc/source/nfc/NFCEEPROMDriver.cpp b/features/nfc/source/nfc/NFCEEPROMDriver.cpp deleted file mode 100644 index 8305580..0000000 --- a/features/nfc/source/nfc/NFCEEPROMDriver.cpp +++ /dev/null @@ -1,50 +0,0 @@ -/* 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 "NFCEEPROMDriver.h" - -using namespace mbed; -using namespace mbed::nfc; - -NFCEEPROMDriver::NFCEEPROMDriver() : _delegate(NULL), _event_queue(NULL) -{ - -} - -NFCEEPROMDriver::~NFCEEPROMDriver() -{ - -} - -void NFCEEPROMDriver::set_delegate(Delegate *delegate) -{ - _delegate = delegate; -} - -void NFCEEPROMDriver::set_event_queue(events::EventQueue *queue) -{ - _event_queue = queue; -} - -NFCEEPROMDriver::Delegate *NFCEEPROMDriver::delegate() -{ - return _delegate; -} - -events::EventQueue *NFCEEPROMDriver::event_queue() -{ - return _event_queue; -} diff --git a/features/nfc/source/nfc/NFCNDEFCapable.cpp b/features/nfc/source/nfc/NFCNDEFCapable.cpp deleted file mode 100644 index 279820a..0000000 --- a/features/nfc/source/nfc/NFCNDEFCapable.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/* 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 "NFCNDEFCapable.h" - -#include "acore/ac_buffer.h" -#include "acore/ac_buffer_reader.h" -#include "acore/ac_buffer_builder.h" - -#include "ndef/ndef.h" - -using namespace mbed; -using namespace mbed::nfc; - -NFCNDEFCapable::NFCNDEFCapable(const Span &buffer) -{ - ndef_msg_init(&_ndef_message, s_ndef_encode, s_ndef_decode, buffer.data(), buffer.size(), this); -} - -void NFCNDEFCapable::parse_ndef_message(const ac_buffer_t &buffer) -{ - ac_buffer_t reader; - ac_buffer_dup(&reader, &buffer); - - Delegate *delegate = ndef_capable_delegate(); - if (delegate != NULL) { - delegate->parse_ndef_message(make_const_Span(ac_buffer_reader_current_buffer_pointer(&reader), ac_buffer_reader_current_buffer_length(&reader))); - } -} - -void NFCNDEFCapable::build_ndef_message(ac_buffer_builder_t &buffer_builder) -{ - Delegate *delegate = ndef_capable_delegate(); - if (delegate != NULL) { - size_t count = delegate->build_ndef_message(make_Span(ac_buffer_builder_write_position(&buffer_builder), ac_buffer_builder_writable(&buffer_builder))); - ac_buffer_builder_write_n_skip(&buffer_builder, count); - } -} - -nfc_err_t NFCNDEFCapable::s_ndef_encode(ndef_msg_t *pTag, ac_buffer_builder_t *pBufferBldr, void *pUserData) -{ - NFCNDEFCapable *self = (NFCNDEFCapable *)pUserData; - return self->ndef_encode(pBufferBldr); -} - -nfc_err_t NFCNDEFCapable::s_ndef_decode(ndef_msg_t *pTag, ac_buffer_t *pBuffer, void *pUserData) -{ - NFCNDEFCapable *self = (NFCNDEFCapable *)pUserData; - return self->ndef_decode(pBuffer); -} - -nfc_err_t NFCNDEFCapable::ndef_encode(ac_buffer_builder_t *pBufferBldr) -{ - build_ndef_message(*pBufferBldr); - return NFC_OK; -} - -nfc_err_t NFCNDEFCapable::ndef_decode(ac_buffer_t *pBuffer) -{ - parse_ndef_message(*pBuffer); - return NFC_OK; -} - -ndef_msg_t *NFCNDEFCapable::ndef_message() -{ - return &_ndef_message; -} - -NFCNDEFCapable::Delegate *NFCNDEFCapable::ndef_capable_delegate() -{ - return NULL; -} diff --git a/features/nfc/source/nfc/NFCRemoteEndpoint.cpp b/features/nfc/source/nfc/NFCRemoteEndpoint.cpp deleted file mode 100644 index f1c2a95..0000000 --- a/features/nfc/source/nfc/NFCRemoteEndpoint.cpp +++ /dev/null @@ -1,60 +0,0 @@ -/* 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 "NFCRemoteEndpoint.h" -#include "NFCController.h" - -#include "acore/ac_buffer.h" -#include "acore/ac_buffer_reader.h" -#include "acore/ac_buffer_builder.h" - -#include "stack/transceiver/transceiver.h" - -using namespace mbed; -using namespace mbed::nfc; - -NFCRemoteEndpoint::NFCRemoteEndpoint(NFCController *controller) : _controller(controller) -{ - -} - -NFCRemoteEndpoint::~NFCRemoteEndpoint() -{ - -} - -nfc_rf_protocols_bitmask_t NFCRemoteEndpoint::rf_protocols() -{ - nfc_rf_protocols_bitmask_t rf_protocols = {0}; - nfc_tech_t active_tech = transceiver_get_active_techs(_controller->transceiver()); - if (!transceiver_is_initiator_mode(_controller->transceiver())) { - // Note: We only support ISO-DEP for now - rf_protocols.target_iso_dep = active_tech.nfc_iso_dep_a || active_tech.nfc_iso_dep_b; - } - - return rf_protocols; -} - -NFCController *NFCRemoteEndpoint::nfc_controller() -{ - return _controller; -} - -const NFCController *NFCRemoteEndpoint::nfc_controller() const -{ - return _controller; -} - diff --git a/features/nfc/source/nfc/NFCRemoteInitiator.cpp b/features/nfc/source/nfc/NFCRemoteInitiator.cpp deleted file mode 100644 index 4863ca8..0000000 --- a/features/nfc/source/nfc/NFCRemoteInitiator.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/* 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 "NFCRemoteInitiator.h" - -using namespace mbed; -using namespace mbed::nfc; - -NFCRemoteInitiator::NFCRemoteInitiator(NFCController *controller, const Span &buffer) : - NFCRemoteEndpoint(controller), NFCNDEFCapable(buffer), _delegate(NULL) -{ - -} - -NFCRemoteInitiator::~NFCRemoteInitiator() -{ - -} - -void NFCRemoteInitiator::set_delegate(Delegate *delegate) -{ - _delegate = delegate; -} - -void NFCRemoteInitiator::connected() -{ - if (_delegate != NULL) { - _delegate->on_connected(); - } -} - -void NFCRemoteInitiator::disconnected() -{ - if (_delegate != NULL) { - _delegate->on_disconnected(); - } -} - -NFCNDEFCapable::Delegate *NFCRemoteInitiator::ndef_capable_delegate() -{ - return _delegate; -} diff --git a/features/nfc/source/nfc/NFCTarget.cpp b/features/nfc/source/nfc/NFCTarget.cpp deleted file mode 100644 index f54213d..0000000 --- a/features/nfc/source/nfc/NFCTarget.cpp +++ /dev/null @@ -1,31 +0,0 @@ -/* 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 "NFCTarget.h" - -using namespace mbed; -using namespace mbed::nfc; - -NFCTarget::NFCTarget(const Span &buffer) : - NFCNDEFCapable(buffer) -{ - -} - -NFCTarget::~NFCTarget() -{ - -} diff --git a/features/nfc/source/nfc/Type4RemoteInitiator.cpp b/features/nfc/source/nfc/Type4RemoteInitiator.cpp deleted file mode 100644 index aa03b29..0000000 --- a/features/nfc/source/nfc/Type4RemoteInitiator.cpp +++ /dev/null @@ -1,140 +0,0 @@ -/* 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 "Type4RemoteInitiator.h" -#include "NFCController.h" - -#include "acore/ac_buffer.h" -#include "acore/ac_buffer_reader.h" -#include "acore/ac_buffer_builder.h" - -#include "stack/transceiver/transceiver.h" -#include "stack/tech/iso7816/iso7816.h" -#include "stack/tech/iso7816/iso7816_app.h" -#include "stack/tech/type4/type4_target.h" - -using namespace mbed; -using namespace mbed::nfc; - -Type4RemoteInitiator::Type4RemoteInitiator(NFCController *controller, const Span &buffer) : - NFCRemoteInitiator(controller, buffer), - _is_connected(false), _is_disconnected(false) -{ - // Init ISO7816 - nfc_tech_iso7816_init(&_iso7816, nfc_controller()->transceiver(), &Type4RemoteInitiator::s_disconnected_callback, this); - - // Init Type 4 app - nfc_tech_type4_target_init(&_type4, &_iso7816, ndef_message()); -} - -Type4RemoteInitiator::~Type4RemoteInitiator() -{ - -} - -nfc_err_t Type4RemoteInitiator::connect() -{ - if (_is_connected) { - return NFC_ERR_BUSY; - } - - if (_is_disconnected) { - return NFC_ERR_DISCONNECTED; - } - - // Connect ISO7816 stack - nfc_tech_iso7816_connect(&_iso7816); - - // Call callback as it's a synchronous API - connected(); - - return NFC_OK; -} - -nfc_err_t Type4RemoteInitiator::disconnect() -{ - if (!_is_connected) { - return NFC_OK; - } - - if (_is_disconnected) { - return NFC_OK; - } - - // Disconnect ISO7816 stack - nfc_tech_iso7816_disconnect(&_iso7816); - - return NFC_OK; -} - -bool Type4RemoteInitiator::is_connected() const -{ - return _is_connected; -} - -bool Type4RemoteInitiator::is_disconnected() const -{ - return _is_disconnected; -} - -nfc_rf_protocols_bitmask_t Type4RemoteInitiator::rf_protocols() -{ - nfc_rf_protocols_bitmask_t rf_protocols = {0}; - nfc_tech_t active_tech = transceiver_get_active_techs(nfc_controller()->transceiver()); - if (!transceiver_is_initiator_mode(nfc_controller()->transceiver())) { - // We only support ISO-DEP - rf_protocols.target_iso_dep = active_tech.nfc_iso_dep_a || active_tech.nfc_iso_dep_b; - } - - return rf_protocols; -} - -nfc_tag_type_t Type4RemoteInitiator::nfc_tag_type() const -{ - nfc_tech_t active_tech = transceiver_get_active_techs(nfc_controller()->transceiver()); - if (active_tech.nfc_iso_dep_a) { - return nfc_tag_type_4a; - } else { // if(active_tech.nfc_iso_dep_b) - return nfc_tag_type_4b; - } -} - -bool Type4RemoteInitiator::is_iso7816_supported() const -{ - return true; -} - -void Type4RemoteInitiator::add_iso7816_application(nfc_tech_iso7816_app_t *application) -{ - nfc_tech_iso7816_add_app(&_iso7816, application); -} - -bool Type4RemoteInitiator::is_ndef_supported() const -{ - return true; -} - -void Type4RemoteInitiator::disconnected_callback() -{ - // Call disconnected callback - disconnected(); -} - -void Type4RemoteInitiator::s_disconnected_callback(nfc_tech_iso7816_t *pIso7816, void *pUserData) -{ - Type4RemoteInitiator *self = (Type4RemoteInitiator *) pUserData; - self->disconnected_callback(); -} diff --git a/features/nfc/source/nfc/ndef/MessageBuilder.cpp b/features/nfc/source/nfc/ndef/MessageBuilder.cpp deleted file mode 100644 index d9aec05..0000000 --- a/features/nfc/source/nfc/ndef/MessageBuilder.cpp +++ /dev/null @@ -1,322 +0,0 @@ -/* 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 - -#include "nfc/ndef/MessageBuilder.h" - -namespace mbed { -namespace nfc { -namespace ndef { - -MessageBuilder::MessageBuilder(const Span &buffer) : - _message_buffer(buffer), - _position(0), - _message_started(false), - _message_ended(false), - _in_chunk(false) -{ } - -bool MessageBuilder::append_record( - const RecordType &type, - const RecordPayload &payload, - bool is_last_record -) -{ - Record record( - type, - payload, - /* id */ RecordID(), - /* chunk */ false, - is_last_record - ); - - return append_record(record); -} - -bool MessageBuilder::append_record( - const RecordType &type, - const PayloadBuilder &builder, - bool is_last_record -) -{ - Record record( - type, - RecordPayload(), - RecordID(), - /* chunk */ false, - is_last_record - ); - - return append_record(record, &builder); -} - - -bool MessageBuilder::append_record(const Record &record, const PayloadBuilder *builder) -{ - if (_message_ended) { - return false; - } - - if (record.type.value.size() > 255) { - return false; - } - - if (record.id.size() > 255) { - return false; - } - - if (!record.id.empty() && _in_chunk) { - if (record.chunk) { - // middle chunk - return false; - } else if (record.type.tnf == RecordType::unchanged) { - // terminating chunk - return false; - } - } - - if (_in_chunk && record.type.tnf != RecordType::unchanged) { - return false; - } - - if (!_in_chunk && record.chunk && record.type.tnf == RecordType::unchanged) { - return false; - } - - if (record.type.tnf == RecordType::empty) { - if (!record.type.value.empty()) { - return false; - } - - if (!record.id.empty()) { - return false; - } - - if (get_payload_size(record, builder)) { - return false; - } - } - - if (record.type.tnf == RecordType::well_known_type || - record.type.tnf == RecordType::media_type || - record.type.tnf == RecordType::absolute_uri || - record.type.tnf == RecordType::external_type - ) { - if (record.type.value.empty()) { - return false; - } - } - - if (record.type.tnf == RecordType::unknown && !record.type.value.empty()) { - return false; - } - - size_t record_size = compute_record_size(record, builder); - if (record_size > (_message_buffer.size() - _position)) { - return false; - } - - append_header(record, builder); - append_type_length(record); - append_payload_length(record, builder); - append_id_length(record); - append_type(record); - append_id(record); - append_payload(record, builder); - - if (record.chunk) { - _in_chunk = true; - } else if (record.type.tnf == RecordType::unchanged) { - // last chunk reached - _in_chunk = false; - } - - return true; -} - -void MessageBuilder::reset() -{ - _position = 0; - _message_started = false; - _message_ended = false; - _in_chunk = false; -} - -void MessageBuilder::reset(const Span &buffer) -{ - _message_buffer = buffer; - _position = 0; - _message_started = false; - _message_ended = false; - _in_chunk = false; -} - -bool MessageBuilder::is_message_complete() const -{ - return _message_ended; -} - -Span MessageBuilder::get_message() const -{ - if (is_message_complete()) { - return _message_buffer.first(_position); - } else { - return Span(); - } -} - -size_t MessageBuilder::compute_record_size(const Record &record, const PayloadBuilder *builder) -{ - size_t record_size = 0; - record_size = 1; /* header */ - record_size += 1; /* type length */ - record_size += is_short_payload(record, builder) ? 1 : 4; - - if (!record.id.empty()) { - record_size += 1; - } - - record_size += record.type.value.size(); - record_size += record.id.size(); - record_size += get_payload_size(record, builder); - - return record_size; -} - -void MessageBuilder::append_header(const Record &record, const PayloadBuilder *builder) -{ - uint8_t header = 0; - if (!_message_started) { - header |= Header::message_begin_bit; - _message_started = true; - } - - if (record.last_record) { - header |= Header::message_end_bit; - _message_ended = true; - } - - if (record.chunk) { - header |= Header::chunk_flag_bit; - } - - if (is_short_payload(record, builder)) { - header |= Header::short_record_bit; - } - - if (record.id.size()) { - header |= Header::id_length_bit; - } - - header |= record.type.tnf; - _message_buffer[_position++] = header; -} - -void MessageBuilder::append_type_length(const Record &record) -{ - _message_buffer[_position++] = record.type.value.size(); -} - -void MessageBuilder::append_payload_length(const Record &record, const PayloadBuilder *builder) -{ - size_t size = get_payload_size(record, builder); - - if (is_short_payload(record, builder)) { - _message_buffer[_position++] = size; - } else { - _message_buffer[_position++] = (size >> 24) & 0xFF; - _message_buffer[_position++] = (size >> 16) & 0xFF; - _message_buffer[_position++] = (size >> 8) & 0xFF; - _message_buffer[_position++] = size & 0xFF; - } -} - -void MessageBuilder::append_id_length(const Record &record) -{ - if (record.id.empty()) { - return; - } - - _message_buffer[_position++] = record.id.size(); -} - -void MessageBuilder::append_type(const Record &record) -{ - if (record.type.value.empty()) { - return; - } - - memcpy( - _message_buffer.data() + _position, - record.type.value.data(), - record.type.value.size() - ); - _position += record.type.value.size(); -} - -void MessageBuilder::append_id(const Record &record) -{ - if (record.id.empty()) { - return; - } - - memcpy( - _message_buffer.data() + _position, - record.id.data(), - record.id.size() - ); - _position += record.id.size(); -} - -void MessageBuilder::append_payload(const Record &record, const PayloadBuilder *builder) -{ - size_t size = get_payload_size(record, builder); - if (!size) { - return; - } - - if (builder) { - builder->build(_message_buffer.subspan(_position, size)); - } else { - memcpy( - _message_buffer.data() + _position, - record.payload.data(), - size - ); - } - - _position += size; -} - -bool MessageBuilder::is_short_payload(const Record &record, const PayloadBuilder *builder) -{ - if (get_payload_size(record, builder) <= 255) { - return true; - } else { - return false; - } -} - -size_t MessageBuilder::get_payload_size(const Record &record, const PayloadBuilder *builder) -{ - return builder ? builder->size() : record.payload.size(); -} - -} // namespace ndef -} // namespace nfc -} // namespace mbed - diff --git a/features/nfc/source/nfc/ndef/MessageParser.cpp b/features/nfc/source/nfc/ndef/MessageParser.cpp deleted file mode 100644 index 619d45d..0000000 --- a/features/nfc/source/nfc/ndef/MessageParser.cpp +++ /dev/null @@ -1,314 +0,0 @@ -/* 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 - -#include "nfc/ndef/MessageParser.h" -#include "nfc/ndef/Record.h" - -namespace { -struct buffer_iterator_t { - buffer_iterator_t(const mbed::Span &buffer) : - buffer(buffer), - position(0) - { } - - uint8_t operator*() - { - return buffer[position]; - } - - buffer_iterator_t &operator++() - { - ++position; - return *this; - } - - buffer_iterator_t operator++(int) - { - buffer_iterator_t previous = *this; - ++*this; - return previous; - } - - buffer_iterator_t &operator+=(size_t increment) - { - position += increment; - return *this; - } - - operator bool() const - { - return (position >= buffer.size()) ? false : true; - } - - size_t remaining_size() const - { - return buffer.size() - position; - } - - void read_le(uint8_t *dest, size_t size) - { - memcpy(dest, buffer.data() + position, size); - position += size; - } - - void read_be(uint8_t *dest, size_t size) - { - // TODO: Needs proper network to host function - std::reverse_copy( - buffer.data() + position, - buffer.data() + position + size, - dest - ); - position += size; - } - - mbed::Span get_underlying_buffer() const - { - return buffer.last(buffer.size() - position); - } - -private: - mbed::Span buffer; - mbed::Span::index_type position; -}; - -} // end of anonymous namespace - -namespace mbed { -namespace nfc { -namespace ndef { - -struct MessageParser::parsing_state_t { - parsing_state_t(const Span &data_buffer) : - it(data_buffer), - first_record_parsed(false), - last_record_parsed(false), - error(false) - { } - - buffer_iterator_t it; - bool first_record_parsed: 1; - bool last_record_parsed: 1; - bool error: 1; -}; - -MessageParser::MessageParser() : - _delegate(NULL) -{ } - -void MessageParser::set_delegate(Delegate *delegate) -{ - _delegate = delegate; -} - -void MessageParser::parse(const Span &data_buffer) -{ - parsing_state_t parsing_state(data_buffer); - report_parsing_started(); - while (parsing_state.it && parse_record(parsing_state)); - if (!parsing_state.error && !parsing_state.last_record_parsed) { - report_parsing_error(MISSING_MESSAGE_END, parsing_state); - } - report_parsing_terminated(); -} - -bool MessageParser::parse_record(parsing_state_t &s) -{ - if (s.error || s.last_record_parsed) { - return false; - } - - // ensure that the header can be extracted - if (s.it.remaining_size() < 1) { - report_parsing_error(INSUFICIENT_DATA, s); - return false; - } - - uint8_t header = *s.it++; - - // NOTE: report an error until the chunk parsing design is sorted out - if (header & Header::chunk_flag_bit) { - report_parsing_error(CHUNK_RECORD_NOT_SUPPORTED, s); - return false; - } - - // handle first record cases - if (s.first_record_parsed == false) { - if (header & Header::message_begin_bit) { - s.first_record_parsed = true; - } else { - report_parsing_error(INVALID_MESSAGE_START, s); - return false; - } - } else if (header & Header::message_begin_bit) { - report_parsing_error(INVALID_MESSAGE_START, s); - return false; - } - - // handle last record - if (header & Header::message_end_bit) { - s.last_record_parsed = true; - } - - // ensure their is enough space to contain the type length, payload - // length and id length - uint8_t lengths_size = compute_lengths_size(header); - if (s.it.remaining_size() < lengths_size) { - report_parsing_error(INSUFICIENT_DATA, s); - return false; - } - - // extract the various length from the message - uint8_t type_length = extract_type_length(s); - uint32_t payload_length = extract_payload_length(s, header); - uint8_t id_length = extract_id_length(s, header); - - // there should be enough bytes left in the buffer - if (s.it.remaining_size() < (type_length + id_length + payload_length)) { - report_parsing_error(INSUFICIENT_DATA, s); - return false; - } - - // validate the Type Name Format of the header - switch (header & Header::tnf_bits) { - case RecordType::empty: - if (type_length || payload_length || id_length) { - report_parsing_error(INVALID_EMPTY_RECORD, s); - return false; - } - break; - case RecordType::well_known_type: - case RecordType::media_type: - case RecordType::absolute_uri: - case RecordType::external_type: - if (!type_length) { - report_parsing_error(MISSING_TYPE_VALUE, s); - return false; - } - break; - case RecordType::unknown: - if (type_length) { - report_parsing_error(INVALID_UNKNOWN_TYPE_LENGTH, s); - return false; - } - break; - case RecordType::unchanged: - // shouldn't be handled outside of chunk handling - report_parsing_error(INVALID_UNCHANGED_TYPE, s); - return false; - default: - report_parsing_error(INVALID_TYPE_NAME_FORMAT, s); - return false; - } - - // build the record - Record record; - - // flags - record.last_record = header & Header::message_end_bit; - - // type - record.type.tnf = static_cast(header & Header::tnf_bits); - if (type_length) { - record.type.value = s.it.get_underlying_buffer().first(type_length); - s.it += type_length; - } - - // id - if (id_length) { - record.id = s.it.get_underlying_buffer().first(id_length); - s.it += id_length; - } - - // payload - if (payload_length) { - record.payload = s.it.get_underlying_buffer().first(payload_length); - s.it += payload_length; - } - - s.it += payload_length; - - report_record_parsed(record); - - return true; -} - -uint8_t MessageParser::compute_lengths_size(uint8_t header) -{ - return 1 /* type_length size */ + - ((header & Header::short_record_bit) ? 1 : 4) /* payload length */ + - ((header & Header::id_length_bit) ? 1 : 0); -} - -uint8_t MessageParser::extract_type_length(parsing_state_t &s) -{ - return *s.it++; -} - -uint32_t MessageParser::extract_payload_length(parsing_state_t &s, uint8_t header) -{ - uint32_t payload_length = 0; - if (header & Header::short_record_bit) { - payload_length = *s.it++; - } else { - s.it.read_be( - reinterpret_cast(&payload_length), - sizeof(payload_length) - ); - } - return payload_length; -} - -uint8_t MessageParser::extract_id_length(parsing_state_t &s, uint8_t header) -{ - return (header & Header::id_length_bit) ? *s.it++ : 0; -} - -void MessageParser::report_parsing_started() -{ - if (_delegate) { - _delegate->on_parsing_started(); - } -} - -void MessageParser::report_record_parsed(const Record &record) -{ - if (_delegate) { - _delegate->on_record_parsed(record); - } -} - -void MessageParser::report_parsing_terminated() -{ - if (_delegate) { - _delegate->on_parsing_terminated(); - } -} - -void MessageParser::report_parsing_error(error_t error, parsing_state_t &parsing_state) -{ - parsing_state.error = true; - if (_delegate) { - _delegate->on_parsing_error(error); - } -} - -} // namespace ndef -} // namespace nfc -} // namespace mbed - diff --git a/features/nfc/source/nfc/ndef/RecordParser.cpp b/features/nfc/source/nfc/ndef/RecordParser.cpp deleted file mode 100644 index a3ae07c..0000000 --- a/features/nfc/source/nfc/ndef/RecordParser.cpp +++ /dev/null @@ -1,50 +0,0 @@ -/* 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 "nfc/ndef/RecordParser.h" - -namespace mbed { -namespace nfc { -namespace ndef { - -bool RecordParserChain::parse(const Record &record) -{ - RecordParser *current_parser = _parsers; - while (current_parser) { - if (current_parser->parse(record)) { - return true; - } - current_parser = current_parser->_next_parser; - } - return false; -} - -void RecordParserChain::set_next_parser(RecordParser *parser) -{ - if (!_parsers) { - _parsers = parser; - } else { - RecordParser *current_parser = _parsers; - while (current_parser->_next_parser) { - current_parser = current_parser->_next_parser; - } - current_parser->_next_parser = parser; - } -} - -} // namespace ndef -} // namespace nfc -} // namespace mbed diff --git a/features/nfc/source/nfc/ndef/common/Mime.cpp b/features/nfc/source/nfc/ndef/common/Mime.cpp deleted file mode 100644 index 7818cd3..0000000 --- a/features/nfc/source/nfc/ndef/common/Mime.cpp +++ /dev/null @@ -1,174 +0,0 @@ -/* 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 - -#include "nfc/ndef/common/Mime.h" - -namespace mbed { -namespace nfc { -namespace ndef { -namespace common { - -Mime::Mime() : - _mime(NULL), - _type_size(0), - _content_size(0) -{ } - -Mime::Mime( - const Span &mime_type, - const Span &content -) : _mime(new uint8_t[mime_type.size() + content.size()]), - _type_size(mime_type.size()), - _content_size(content.size()) -{ - memcpy(_mime, mime_type.data(), mime_type.size()); - memcpy(_mime + mime_type.size(), content.data(), content.size()); -} - -Mime::Mime(const Mime &to_copy) : - _mime(new uint8_t[to_copy.mime_size()]), - _type_size(to_copy._type_size), - _content_size(to_copy._content_size) -{ - memcpy(_mime, to_copy._mime, to_copy.mime_size()); -} - -Mime::~Mime() -{ - delete[] _mime; -} - -Mime &Mime::operator=(const Mime &to_copy) -{ - if (this == &to_copy) { - return * this; - } - - delete[] _mime; - - _mime = new uint8_t[to_copy.mime_size()]; - memcpy(_mime, to_copy._mime, to_copy.mime_size()); - _type_size = to_copy._type_size; - _content_size = to_copy._content_size; - - return *this; -} - -void Mime::set_mime( - const Span &mime_type, - const Span &content -) -{ - delete[] _mime; - - _mime = new uint8_t[mime_type.size() + content.size()]; - memcpy(_mime, mime_type.data(), mime_type.size()); - memcpy(_mime + mime_type.size(), content.data(), content.size()); - _type_size = mime_type.size(); - _content_size = content.size(); -} - -Span Mime::get_mime_type() const -{ - return make_const_Span(_mime, _type_size); -} - -Span Mime::get_mime_content() const -{ - return make_const_Span(_mime + _type_size, _content_size); -} - -bool Mime::append_as_record( - MessageBuilder &message_builder, - bool is_last_record -) const -{ - return message_builder.append_record( - RecordType( - RecordType::media_type, - get_mime_type() - ), - get_mime_content(), - is_last_record - ); -} - -size_t Mime::get_record_size() const -{ - return MessageBuilder::compute_record_size( - Record( - RecordType( - RecordType::media_type, - get_mime_type() - ), - get_mime_content(), - RecordID(), - /* chunk */ false, - /* last record */ false - ) - ); -} - -void Mime::move_data( - uint8_t *mime_record, - size_t mime_type_size, - size_t mime_content_size -) -{ - delete[] _mime; - _mime = mime_record; - _type_size = mime_type_size; - _content_size = mime_content_size; -} - -size_t Mime::mime_size() const -{ - return _type_size + _content_size; -} - -bool MimeParser::do_parse(const Record &record, Mime &mime) -{ - if (record.type.tnf != RecordType::media_type) { - return false; - } - - // A type and a payload should be present - if (record.type.value.empty() || record.payload.empty()) { - return false; - } - - // create the buffer - size_t type_size = record.type.value.size(); - size_t content_size = record.payload.size(); - uint8_t *mime_buffer = new uint8_t[type_size + content_size]; - - // copy type - memcpy(mime_buffer, record.type.value.data(), type_size); - - // copy content - memcpy(mime_buffer + type_size, record.payload.data(), content_size); - - mime.move_data(mime_buffer, type_size, content_size); - - return true; -} - -} // namespace common -} // namespace ndef -} // namespace nfc -} // namespace mbed diff --git a/features/nfc/source/nfc/ndef/common/SimpleMessageParser.cpp b/features/nfc/source/nfc/ndef/common/SimpleMessageParser.cpp deleted file mode 100644 index 5f0db5a..0000000 --- a/features/nfc/source/nfc/ndef/common/SimpleMessageParser.cpp +++ /dev/null @@ -1,124 +0,0 @@ -/* 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 "nfc/ndef/common/SimpleMessageParser.h" - -namespace mbed { -namespace nfc { -namespace ndef { -namespace common { - -SimpleMessageParser::SimpleMessageParser() : - _message_parser(), - _record_parser_chain(), - _uri_parser(), - _text_parser(), - _mime_parser(), - _delegate(NULL) -{ - // setup the parser chain - _record_parser_chain.set_next_parser(&_uri_parser); - _record_parser_chain.set_next_parser(&_text_parser); - _record_parser_chain.set_next_parser(&_mime_parser); - - // wire event handling - _message_parser.set_delegate(this); - _uri_parser.set_delegate(this); - _text_parser.set_delegate(this); - _mime_parser.set_delegate(this); -} - -void SimpleMessageParser::set_delegate(Delegate *delegate) -{ - _delegate = delegate; -} - -void SimpleMessageParser::parse(const Span &data_buffer) -{ - _message_parser.parse(data_buffer); -} - -void SimpleMessageParser::add_record_parser(RecordParser *parser) -{ - _record_parser_chain.set_next_parser(parser); -} - -void SimpleMessageParser::on_parsing_error(MessageParser::error_t error) -{ - if (_delegate) { - _delegate->on_parsing_error(error); - } -} - -void SimpleMessageParser::on_parsing_started() -{ - if (_delegate) { - _delegate->on_parsing_started(); - } -} - -void SimpleMessageParser::on_record_parsed(const Record &record) -{ - bool parsed = _record_parser_chain.parse(record); - - if (!parsed && _delegate) { - _delegate->on_unknown_record_parsed(record); - } -} - -void SimpleMessageParser::on_parsing_terminated() -{ - if (_delegate) { - _delegate->on_parsing_terminated(); - } -} - -void SimpleMessageParser::on_record_parsed( - const URI &uri, - const RecordID &id -) -{ - if (_delegate) { - _delegate->on_uri_parsed(uri, id); - } -} - -void SimpleMessageParser::on_record_parsed( - const Text &text, - const RecordID &id -) -{ - if (_delegate) { - _delegate->on_text_parsed(text, id); - } -} - -void SimpleMessageParser::on_record_parsed( - const Mime &mime, - const RecordID &id -) -{ - if (_delegate) { - _delegate->on_mime_parsed(mime, id); - } -} - -} // namespace common -} // namespace ndef -} // namespace nfc -} // namespace mbed - - diff --git a/features/nfc/source/nfc/ndef/common/Text.cpp b/features/nfc/source/nfc/ndef/common/Text.cpp deleted file mode 100644 index 6ea37be..0000000 --- a/features/nfc/source/nfc/ndef/common/Text.cpp +++ /dev/null @@ -1,208 +0,0 @@ -/* 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 - -#include "nfc/ndef/common/Text.h" - -namespace { -static const uint8_t utf16_encoding_bit = (1 << 7); -static const uint8_t language_code_size_mask = 0x3F; -static const uint8_t header_index = 0; -static const uint8_t language_code_index = 1; -static const uint8_t header_size = 1; -static const uint8_t text_record_type_value[] = { 'T' }; -} - -namespace mbed { -namespace nfc { -namespace ndef { -namespace common { - -Text::Text() : - _text_record(NULL), - _text_record_size(0) -{ } - -Text::Text(const Text &other) : - _text_record(other._text_record ? new uint8_t[other._text_record_size] : NULL), - _text_record_size(other._text_record_size) -{ - if (_text_record) { - memcpy(_text_record, other._text_record, _text_record_size); - } -} - -Text::Text( - encoding_t text_encoding, - const Span &language_code, - const Span &text -) : _text_record(NULL), - _text_record_size(0) -{ - set_text(text_encoding, language_code, text); -} - -Text::~Text() -{ - delete[] _text_record; -} - -Text &Text::operator=(const Text &other) -{ - if (this == &other) { - return *this; - } - - _text_record_size = other._text_record_size; - - delete[] _text_record; - if (!other._text_record) { - _text_record = NULL; - } else { - _text_record = new uint8_t[_text_record_size]; - memcpy(_text_record, other._text_record, _text_record_size); - } - - return *this; -} - -void Text::set_text( - encoding_t text_encoding, - const Span &language_code, - const Span &text -) -{ - delete[] _text_record; - - _text_record_size = header_size + language_code.size() + text.size(); - _text_record = new uint8_t[_text_record_size]; - - // build the header - _text_record[header_index] = 0; - if (text_encoding == UTF16) { - _text_record[header_index] |= utf16_encoding_bit; - } - _text_record[header_index] |= language_code.size(); - - // language code - memcpy(_text_record + language_code_index, language_code.data(), language_code.size()); - - // actual text - memcpy(_text_record + language_code_index + language_code.size(), text.data(), text.size()); -} - -Text::encoding_t Text::get_encoding() const -{ - return (_text_record[header_index] & utf16_encoding_bit) ? UTF16 : UTF8; -} - -Span Text::get_language_code() const -{ - return make_const_Span( - _text_record + language_code_index, - _text_record[header_index] & language_code_size_mask - ); -} - -Span Text::get_text() const -{ - if (!_text_record) { - return Span(); - } - - size_t language_code_size = get_language_code().size(); - - return make_const_Span( - _text_record + header_size + language_code_size, - _text_record_size - header_size - language_code_size - ); -} - -void Text::move_data(uint8_t *text, size_t size) -{ - delete[] _text_record; - _text_record = text; - _text_record_size = size; -} - -bool Text::append_as_record( - MessageBuilder &message_builder, - bool is_last_record -) const -{ - if (!_text_record) { - return false; - } - - // Build the record type - RecordType type( - RecordType::well_known_type, - text_record_type_value - ); - - // build the record payload - RecordPayload payload(_text_record, _text_record_size); - return message_builder.append_record(type, payload, is_last_record); -} - -size_t Text::get_record_size() const -{ - if (!_text_record) { - return 0; - } - - return MessageBuilder::compute_record_size( - Record( - RecordType( - RecordType::well_known_type, - text_record_type_value - ), - RecordPayload(_text_record, _text_record_size), - RecordID(), - /* chunk */ false, - /* last record */ false - ) - ); -} - -bool TextParser::do_parse(const Record &record, Text &text) -{ - if (record.type.tnf != RecordType::well_known_type) { - return false; - } - - // the record type value should be equal to `T` - if (record.type.value != make_const_Span(text_record_type_value) || - record.payload.empty() - ) { - return false; - } - - // create the buffer - size_t text_record_size = record.payload.size(); - uint8_t *text_record = new uint8_t[text_record_size]; - memcpy(text_record, record.payload.data(), text_record_size); - - text.move_data(text_record, text_record_size); - - return true; -} - -} // namespace common -} // namespace ndef -} // namespace nfc -} // namespace mbed diff --git a/features/nfc/source/nfc/ndef/common/URI.cpp b/features/nfc/source/nfc/ndef/common/URI.cpp deleted file mode 100644 index 4761251..0000000 --- a/features/nfc/source/nfc/ndef/common/URI.cpp +++ /dev/null @@ -1,191 +0,0 @@ -/* 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 - -#include "nfc/ndef/common/URI.h" - -namespace { -static const uint8_t uri_id_code_size = 1; -static const uint8_t uri_id_index = 0; -static const uint8_t uri_field_index = 1; -static const uint8_t uri_record_type_value[] = { 'U' } ; -} - -namespace mbed { -namespace nfc { -namespace ndef { -namespace common { - -URI::URI() : - _uri(NULL), - _uri_size(0) -{ -} - -URI::URI(uri_identifier_code_t id, const Span &uri_field) : - _uri(uri_field.size() ? new uint8_t[uri_id_code_size + uri_field.size()] : NULL), - _uri_size(uri_id_code_size + uri_field.size()) -{ - if (_uri) { - _uri[uri_id_index] = id; - memcpy(_uri + uri_field_index, uri_field.data(), uri_field.size()); - } -} - -URI::URI(const URI &other) : - _uri(other._uri ? new uint8_t[other._uri_size] : NULL), - _uri_size(other._uri_size) -{ - if (_uri) { - memcpy(_uri, other._uri, other._uri_size); - } -} - -URI::~URI() -{ - delete[] _uri; -} - -URI &URI::operator=(const URI &other) -{ - delete[] _uri; - - if (!other._uri) { - _uri = NULL; - _uri_size = 0; - } else { - _uri = new uint8_t[other._uri_size]; - _uri_size = other._uri_size; - memcpy(_uri, other._uri, other._uri_size); - } - - return *this; -} - -void URI::set_uri( - uri_identifier_code_t id, - const Span &uri_field -) -{ - delete[] _uri; - - if (uri_field.empty()) { - _uri = NULL; - _uri_size = 0; - return; - } - - _uri = new uint8_t[uri_id_code_size + uri_field.size()]; - _uri_size = uri_id_code_size + uri_field.size(); - _uri[uri_id_index] = id; - memcpy(_uri + uri_field_index, uri_field.data(), uri_field.size()); -} - -URI::uri_identifier_code_t URI::get_id() const -{ - if (!_uri) { - return NA; - } - - return static_cast(_uri[uri_id_index]); -} - -Span URI::get_uri_field() const -{ - if (!_uri) { - return Span(); - } - return make_const_Span( - _uri + uri_field_index, - _uri_size - uri_id_code_size - ); -} - -bool URI::append_as_record(MessageBuilder &message_builder, bool is_last_record) const -{ - if (!_uri) { - return false; - } - - // Build the record type - RecordType type( - RecordType::well_known_type, - uri_record_type_value - ); - - // build the record payload - RecordPayload payload(_uri, _uri_size); - - return message_builder.append_record(type, payload, is_last_record); -} - -size_t URI::get_record_size() const -{ - if (!_uri) { - return 0; - } - - return MessageBuilder::compute_record_size( - Record( - RecordType( - RecordType::well_known_type, - uri_record_type_value - ), - RecordPayload(_uri, _uri_size), - RecordID(), - /* chunk */ false, - /* last record */ false - ) - ); -} - -void URI::move_data(uint8_t *new_uri, size_t new_uri_size) -{ - delete[] _uri; - _uri = new_uri; - _uri_size = new_uri_size; -} - -bool URIParser::do_parse(const Record &record, URI &uri) -{ - if (record.type.tnf != RecordType::well_known_type) { - return false; - } - - // the record type value should be equal to `U` - if (record.type.value != make_const_Span(uri_record_type_value) || - record.payload.empty() - ) { - return false; - } - - // create the buffer - size_t uri_record_size = record.payload.size(); - uint8_t *uri_record = new uint8_t[uri_record_size]; - memcpy(uri_record, record.payload.data(), uri_record_size); - - uri.move_data(uri_record, uri_record_size); - - return true; -} - -} // namespace common -} // namespace ndef -} // namespace nfc -} // namespace mbed - - diff --git a/features/nfc/source/nfc/ndef/common/util.cpp b/features/nfc/source/nfc/ndef/common/util.cpp deleted file mode 100644 index 27a2b40..0000000 --- a/features/nfc/source/nfc/ndef/common/util.cpp +++ /dev/null @@ -1,39 +0,0 @@ -/* 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 - -#include "nfc/ndef/common/util.h" - -namespace mbed { -namespace nfc { -namespace ndef { -namespace common { - -Span span_from_cstr(const char *cstr) -{ - return Span((const uint8_t *)cstr, strlen(cstr)); -} - -/** - * @} - */ - -} // namespace common -} // namespace ndef -} // namespace nfc -} // namespace mbed - diff --git a/features/nfc/stack/ndef/ndef.c b/features/nfc/stack/ndef/ndef.c deleted file mode 100644 index 50fb192..0000000 --- a/features/nfc/stack/ndef/ndef.c +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2013-2018, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * 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. - */ -/** - * \file ndef.c - * \copyright Copyright (c) ARM Ltd 2013 - * \author Donatien Garnier - * \details NDEF tag abstraction - */ - - -#include "ndef.h" - -/** \addtogroup NDEF - * @{ - * \name Generic NDEF Tag - * @{ - */ - -/** Initialize NDEF tag abstraction - * \param pNdefTag pointer to ndef_tag_t structure to initialize - * \param encode function that will be called to generate the NDEF message before sending it to the other party - * \param decode function that will be called to parse the NDEF message after receiving it from the other party - * \param buffer underlying buffer to use (it should be big enough so that any NDEF message you might need could be stored inside) - * \param buffer_size size of the underlying buffer - * \param pImpl pointer to actual implementation - */ -void ndef_msg_init(ndef_msg_t *pNdef, ndef_encode_fn_t encode, ndef_decode_fn_t decode, uint8_t *data, size_t size, void *pUserData) -{ - pNdef->encode = encode; - pNdef->decode = decode; - ac_buffer_builder_init(&pNdef->bufferBldr, data, size); - pNdef->pUserData = pUserData; -} - -/** Get NDEF tag implementation - * \param pNdefTag pointer to ndef_tag_t structure - * \return implementation - */ -/* -void* ndef_tag_impl(ndef_tag_t* pNdefTag) -{ - return pNdefTag->pImpl; -} -*/ - -/** - * @} - * @} - * */ diff --git a/features/nfc/stack/ndef/ndef.h b/features/nfc/stack/ndef/ndef.h deleted file mode 100644 index 6ff4eb9..0000000 --- a/features/nfc/stack/ndef/ndef.h +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (c) 2013-2018, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * 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. - */ -/** - * \file ndef.h - * \copyright Copyright (c) ARM Ltd 2013 - * \author Donatien Garnier - */ - -/** \addtogroup NDEF - * @{ - * \name Generic NDEF Tag - * @{ - */ - -#ifndef NDEF_H_ -#define NDEF_H_ - -#include "stack/nfc_common.h" - -#ifdef __cplusplus -extern "C" { -#endif - -//Generic interface for NDEF messages -typedef struct __ndef_msg ndef_msg_t; - -/** Function called to generate the tag's content on read (target mode) - * \param pTag pointer to ndef_tag_t instance - * \param type pMem buffer in which to store the generated content - */ -typedef nfc_err_t (*ndef_encode_fn_t)(ndef_msg_t *pTag, ac_buffer_builder_t *pBufferBldr, void *pUserData); - -/** Function called to decode the tag's content on write (target mode) or read (reader mode) - * \param pTag pointer to ndef_tag_t instance - * \param type pMem buffer containing the tag's content - */ -typedef nfc_err_t (*ndef_decode_fn_t)(ndef_msg_t *pTag, ac_buffer_t *pBuffer, void *pUserData); - -struct __ndef_msg { - ndef_encode_fn_t encode; - ndef_decode_fn_t decode; - ac_buffer_builder_t bufferBldr; - void *pUserData; -}; - -void ndef_msg_init(ndef_msg_t *pNdef, ndef_encode_fn_t encode, ndef_decode_fn_t decode, uint8_t *data, size_t size, void *pUserData); - -static inline nfc_err_t ndef_msg_encode(ndef_msg_t *pNdef) -{ - if (pNdef->encode == NULL) { - return NFC_OK; - } - return pNdef->encode(pNdef, &pNdef->bufferBldr, pNdef->pUserData); -} - -static inline nfc_err_t ndef_msg_decode(ndef_msg_t *pNdef) -{ - if (pNdef->decode == NULL) { - return NFC_OK; - } - return pNdef->decode(pNdef, ac_buffer_builder_buffer(&pNdef->bufferBldr), pNdef->pUserData); -} - -static inline ac_buffer_builder_t *ndef_msg_buffer_builder(ndef_msg_t *pNdef) -{ - return &pNdef->bufferBldr; -} - -//void* ndef_tag_impl(ndef_tag_t* pNdefTag); - -#ifdef __cplusplus -} -#endif - -#endif /* NDEF_H_ */ - -/** - * @} - * @} - * */ - diff --git a/features/nfc/stack/nfc_common.h b/features/nfc/stack/nfc_common.h deleted file mode 100644 index e481188..0000000 --- a/features/nfc/stack/nfc_common.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2018, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * 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. - */ -/** - * \file nfc_common.h - * \copyright Copyright (c) ARM Ltd 2018 - * \author Donatien Garnier - * \details Common includes for NFC Stack - */ - -#ifndef NFC_COMMON_H_ -#define NFC_COMMON_H_ - -#include "stddef.h" -#include "stdint.h" -#include "string.h" -#include "stdbool.h" - -#include "nfc_errors.h" - -#include "platform/nfc_debug.h" - -#include "acore/ac_macros.h" -#include "acore/ac_buffer.h" -#include "acore/ac_buffer_reader.h" -#include "acore/ac_buffer_builder.h" -#include "acore/ac_stream.h" - -#endif /* NFC_COMMON_H_ */ - -/** - * @} - * @} - * */ diff --git a/features/nfc/stack/nfc_errors.h b/features/nfc/stack/nfc_errors.h deleted file mode 100644 index f8870cb..0000000 --- a/features/nfc/stack/nfc_errors.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2013-2018, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * 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. - */ -/** - * \file nfc_errors.h - * \copyright Copyright (c) ARM Ltd 2013 - * \author Donatien Garnier - * \details NFC Error codes - */ - -/** \addtogroup Core - * @{ - * \name Error codes - * @{ - */ - -#ifndef NFC_ERRORS_H_ -#define NFC_ERRORS_H_ - -#define NFC_OK 0 ///< No error - -#define NFC_ERR_UNKNOWN 1 ///< Unknown error -#define NFC_ERR_LENGTH 2 ///< Length of parameter is wrong -#define NFC_ERR_NOT_FOUND 3 ///< Could not find item -#define NFC_ERR_UNSUPPORTED 4 ///< This action is not supported -#define NFC_ERR_PARAMS 5 ///< These parameters are not correct -#define NFC_ERR_BUFFER_TOO_SMALL 6 ///< The buffer is too small to store all data (buffer overflow) -#define NFC_ERR_TIMEOUT 7 ///< Timeout -#define NFC_ERR_CRC 8 ///< Checksum does not match -#define NFC_ERR_NOPEER 9 ///< No target/initiator in vicinity -#define NFC_ERR_PARITY 10 ///< Parity error -#define NFC_ERR_FIELD 11 ///< No RF field detected (or RF field lost) -#define NFC_ERR_COLLISION 12 ///< Collision detected -#define NFC_ERR_WRONG_COMM 13 ///< Communication error -#define NFC_ERR_PROTOCOL 14 ///< Protocol is not conformant -#define NFC_ERR_BUSY 15 ///< Resource is busy -#define NFC_ERR_CONTROLLER 16 ///< Controller failure -#define NFC_ERR_HALTED 17 ///< Target has been halted -#define NFC_ERR_MAC 18 ///< MAC does not match -#define NFC_ERR_UNDERFLOW 19 ///< Could not send data in time -#define NFC_ERR_DISCONNECTED 20 ///< Link has disconnected -#define NFC_ERR_ABORTED 21 ///< Command was aborted - -/** Type for NFC errors - */ -typedef int nfc_err_t; - -#endif /* NFC_ERRORS_H_ */ - -/** - * @} - * @} - * */ diff --git a/features/nfc/stack/platform/nfc_debug.h b/features/nfc/stack/platform/nfc_debug.h deleted file mode 100644 index 0d6cd71..0000000 --- a/features/nfc/stack/platform/nfc_debug.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2018, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * 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. - */ - -#ifndef MBED_NFC_DEBUG_H -#define MBED_NFC_DEBUG_H - -#if NFC_DEBUG && !defined(NDEBUG) && __DEBUG__ -#ifdef __MODULE__ -#define __NFC_MODULE__ __MODULE__ -#else -#define __NFC_MODULE__ __FILE__ -#endif - -#include "stdio.h" -#include "stdarg.h" -static inline void nfc_dbg_print(const char *type, const char *module, unsigned int line, const char *fmt, ...) -{ -#if !defined(NDEBUG) - printf("NFC [%s] %s:%u ", type, module, line); - va_list args; - va_start(args, fmt); - vprintf(fmt, args); - va_end(args); - printf("\r\n"); -#endif -} - -#if !defined(NFC_DBG) -#define NFC_DBG(...) nfc_dbg_print("DBG", __NFC_MODULE__, __LINE__, __VA_ARGS__) -#endif - -#if !defined(NFC_WARN) -#define NFC_WARN(...) nfc_dbg_print("WARN", __NFC_MODULE__, __LINE__, __VA_ARGS__) -#endif - -#if !defined(NFC_ERR) -#define NFC_ERR(...) nfc_dbg_print("ERR", __NFC_MODULE__, __LINE__, __VA_ARGS__) -#endif - -#define NFC_DBG_BLOCK(x) x - -#else - -#if !defined(NFC_DBG) -#define NFC_DBG(...) -#endif - -#if !defined(NFC_WARN) -#define NFC_WARN(...) -#endif - -#if !defined(NFC_ERR) -#define NFC_ERR(...) -#endif - -#define NFC_DBG_BLOCK(x) - -#endif - -#endif diff --git a/features/nfc/stack/platform/nfc_scheduler.c b/features/nfc/stack/platform/nfc_scheduler.c deleted file mode 100644 index 8ba8cce..0000000 --- a/features/nfc/stack/platform/nfc_scheduler.c +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright (c) 2015-2018, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * 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. - */ -/** - * \file nfc_scheduler.c - * \copyright Copyright (c) ARM Ltd 2015 - * \author Donatien Garnier - */ - -#include -#include -#include - -#define __DEBUG__ 0 -#ifndef __MODULE__ -#define __MODULE__ "nfc_scheduler.c" -#endif - -#include "platform/nfc_scheduler.h" - -void nfc_scheduler_init(nfc_scheduler_t *pScheduler, nfc_scheduler_timer_t *pTimer) -{ - pScheduler->pNext = NULL; - pScheduler->pTimer = pTimer; - - //Start timer - nfc_scheduler_timer_start(pTimer); -} - -#define MAX_TIMEOUT UINT32_MAX - -uint32_t nfc_scheduler_iteration(nfc_scheduler_t *pScheduler, uint32_t events) -{ - while (true) { - nfc_task_t *pPrioTask = NULL; - nfc_task_t *pPrioTaskPrevious = NULL; - uint32_t prioTaskEvent = 0; - int64_t timeout; - nfc_task_t *pPreviousTask = NULL; - nfc_task_t *pTask = pScheduler->pNext; - - if (pTask == NULL) { - NFC_DBG("Empty queue, %lu ms elapsed", nfc_scheduler_timer_get(pScheduler->pTimer)); - //Empty queue, return - return MAX_TIMEOUT; - } - - //Get timer value - uint32_t timeElapsed = nfc_scheduler_timer_get(pScheduler->pTimer); - NFC_DBG("%lu ms elapsed", timeElapsed); - nfc_scheduler_timer_reset(pScheduler->pTimer); - - do { - //Apply timeouts - if (pTask->events & EVENT_TIMEOUT) { - pTask->timeout -= timeElapsed; - } - pPreviousTask = pTask; - pTask = pTask->pNext; - } while (pTask != NULL); - - pTask = pScheduler->pNext; - pPreviousTask = NULL; - timeout = MAX_TIMEOUT; - do { - //Check which task should be woken up first - if ((events & EVENT_HW_INTERRUPT) && (pTask->events & EVENT_HW_INTERRUPT)) { - //Hardware interrupts have prio - pPrioTask = pTask; - pPrioTaskPrevious = pPreviousTask; - timeout = 0; - events &= ~EVENT_HW_INTERRUPT; //Only one task gets triggered per event - prioTaskEvent = EVENT_HW_INTERRUPT; - break; - } else if ((pTask->events & EVENT_TIMEOUT) && (pTask->timeout < timeout)) { - pPrioTask = pTask; - pPrioTaskPrevious = pPreviousTask; - timeout = pTask->timeout; - prioTaskEvent = EVENT_TIMEOUT; - } - pPreviousTask = pTask; - pTask = pTask->pNext; - } while (pTask != NULL); - - if (pPrioTask == NULL) { - //No task to wake up, exit - NFC_DBG("No task to wake up"); - return MAX_TIMEOUT; - } - - if (timeout > 0) { - //No task to wake up yet - if (timeout > MAX_TIMEOUT) { - NFC_DBG("No task to wake up"); - return MAX_TIMEOUT; - } else { - NFC_DBG("No task to wake up, wait %lu ms", timeout); - return timeout; - } - } - - //Dequeue task - if (pPrioTaskPrevious == NULL) { - pScheduler->pNext = pPrioTask->pNext; - } else { - pPrioTaskPrevious->pNext = pPrioTask->pNext; - } - pPrioTask->pNext = NULL; - - //Execute task - NFC_DBG("Calling task %p - events %02X", pPrioTask, prioTaskEvent); - pPrioTask->fn(prioTaskEvent, pPrioTask->pUserData); - events &= ~EVENT_HW_INTERRUPT; //Only one task gets triggered per event - } - return MAX_TIMEOUT; -} - -void nfc_scheduler_queue_task(nfc_scheduler_t *pScheduler, nfc_task_t *pTask) -{ - pTask->timeout = pTask->timeoutInitial + nfc_scheduler_timer_get(pScheduler->pTimer); - NFC_DBG("Queuing task %p: events %1X, timeout %lu ms", pTask, pTask->events, pTask->timeout); - //Find last task - nfc_task_t *pPrevTask = pScheduler->pNext; - pTask->pNext = NULL; - if (pPrevTask == NULL) { - pScheduler->pNext = pTask; - return; - } - while (pPrevTask->pNext != NULL) { - pPrevTask = pPrevTask->pNext; - } - pPrevTask->pNext = pTask; -} - -void nfc_scheduler_dequeue_task(nfc_scheduler_t *pScheduler, bool abort, nfc_task_t *pTask) -{ - NFC_DBG("Dequeuing task %p", pTask); - //Find task - nfc_task_t *pPrevTask = pScheduler->pNext; - if (pPrevTask == NULL) { - pTask->pNext = NULL; - return; - } - if (pPrevTask == pTask) { - if (abort) { - pTask->fn(EVENT_ABORTED, pTask->pUserData); - } - pScheduler->pNext = pTask->pNext; - pTask->pNext = NULL; - return; - } - while (pPrevTask->pNext != NULL) { - if (pPrevTask->pNext == pTask) { - if (abort) { - pTask->fn(EVENT_ABORTED, pTask->pUserData); - } - pPrevTask->pNext = pTask->pNext; - pTask->pNext = NULL; - return; - } - pPrevTask = pPrevTask->pNext; - } - pTask->pNext = NULL; -} - -void task_init(nfc_task_t *pTask, uint32_t events, uint32_t timeout, nfc_task_fn fn, void *pUserData) -{ - pTask->events = events; - pTask->timeoutInitial = timeout; - pTask->fn = fn; - pTask->pUserData = pUserData; - pTask->pNext = NULL; -} diff --git a/features/nfc/stack/platform/nfc_scheduler.h b/features/nfc/stack/platform/nfc_scheduler.h deleted file mode 100644 index 6e1fb2d..0000000 --- a/features/nfc/stack/platform/nfc_scheduler.h +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (c) 2014-2018, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * 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. - */ -/** - * \file nfc_scheduler.h - * \copyright Copyright (c) ARM Ltd 2014 - * \author Donatien Garnier - */ -/** \addtogroup Core - * @{ - * \name Scheduler - * @{ - */ - -#ifndef NFC_SCHEDULER_H_ -#define NFC_SCHEDULER_H_ - -#include "stack/nfc_common.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define EVENT_NONE 0 -#define EVENT_TIMEOUT 1 -#define EVENT_ABORTED 2 -#define EVENT_HW_INTERRUPT 4 - -struct __nfc_timer; -typedef struct __nfc_timer nfc_scheduler_timer_t; - -struct __nfc_task; -typedef struct __nfc_task nfc_task_t; - -typedef struct __scheduler { - nfc_task_t *pNext; - nfc_scheduler_timer_t *pTimer; -} nfc_scheduler_t; - -typedef void (*nfc_task_fn)(uint32_t events, void *pUserData); - -struct __nfc_task { - uint32_t events; - int64_t timeout; //millisecs - int64_t timeoutInitial; - - nfc_task_fn fn; - void *pUserData; - - nfc_task_t *pNext; -}; - -void nfc_scheduler_timer_init(nfc_scheduler_timer_t *timer); - -void nfc_scheduler_timer_start(nfc_scheduler_timer_t *timer); - -uint32_t nfc_scheduler_timer_get(nfc_scheduler_timer_t *timer); - -void nfc_scheduler_timer_stop(nfc_scheduler_timer_t *timer); - -void nfc_scheduler_timer_reset(nfc_scheduler_timer_t *timer); - -/** Init scheduler - * \param pScheduler scheduler instance to init - * \param pTimer timer instance - */ -void nfc_scheduler_init(nfc_scheduler_t *pScheduler, nfc_scheduler_timer_t *pTimer); - -/** Iterate through all tasks - * \param pScheduler scheduler instance - * \param events mask of events (except EVENT_TIMEOUT) that have been raised since this function last returned (0 on first call) - * \return time after which this function must be called again if no other event arises - */ -uint32_t nfc_scheduler_iteration(nfc_scheduler_t *pScheduler, uint32_t events); - -/** Queue a task to execute - * \param pScheduler scheduler instance - * \param pTask task to queue - * - */ -void nfc_scheduler_queue_task(nfc_scheduler_t *pScheduler, nfc_task_t *pTask); - -/** Remove a task to execute - * \param pScheduler scheduler instance - * \param pTask task to remove - * \param abort abort task if queued - */ -void nfc_scheduler_dequeue_task(nfc_scheduler_t *pScheduler, bool abort, nfc_task_t *pTask); - -/** Initialize task with the following parameters - * \param pTask task to initialize - * \param events events on which to call task - * \param timeout if relevant - * \param fn function to be called - * \param pUserData data that will be passed to function - */ -void task_init(nfc_task_t *pTask, uint32_t events, uint32_t timeout, nfc_task_fn fn, void *pUserData); - -#ifdef __cplusplus -} -#endif - -#endif /* NFC_SCHEDULER_H_ */ - -/** - * @} - * @} - * */ - diff --git a/features/nfc/stack/platform/nfc_transport.c b/features/nfc/stack/platform/nfc_transport.c deleted file mode 100644 index 5dcbf80..0000000 --- a/features/nfc/stack/platform/nfc_transport.c +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2013-2018, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * 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. - */ -/** - * \file nfc_transport.c - * \copyright Copyright (c) ARM Ltd 2013-2018 - * \author Donatien Garnier - * \details Transport layer - */ - -/** \addtogroup Implementation - * @{ - * \name Transport - * @{ - */ - -#include "stack/nfc_errors.h" -#include "nfc_transport.h" - -/** Initialize transport with a specific implementation - * \param pTransport pointer to a nfc_transport_t structure to initialize - * \param write transport write function - * \param read transport read function - * \param pUser parameter that will be passed to any of the above functions - */ -void nfc_transport_init(nfc_transport_t *pTransport, nfc_transport_write_fn_t write, nfc_transport_read_fn_t read, void *pUser) -{ - pTransport->write = write; - pTransport->read = read; - pTransport->pUser = pUser; -} - - - - -/** - * @} - * @} - * */ - diff --git a/features/nfc/stack/platform/nfc_transport.h b/features/nfc/stack/platform/nfc_transport.h deleted file mode 100644 index 5e25283..0000000 --- a/features/nfc/stack/platform/nfc_transport.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (c) 2013-2018, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * 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. - */ -/** - * \file nfc_transport.h - * \copyright Copyright (c) ARM Ltd 2013-2018 - * \author Donatien Garnier - */ - -/** \addtogroup Implementation - * @{ - * \name Transport - * @{ - */ - -#ifndef NFC_TRANSPORT_H_ -#define NFC_TRANSPORT_H_ - -#include "stack/nfc_common.h" - -#ifdef __cplusplus -extern "C" { -#endif - - -/** Function called to write a register's value - * \param address address of the register to write to - * \param outBuf buffer to write - * \param outLen buffer's length - * \param pUser parameter passed to the nfc_transport_init function - */ -typedef void (*nfc_transport_write_fn_t)(uint8_t address, const uint8_t *outBuf, size_t outLen, void *pUser); - -/** Function called to read a register's value - * \param address address to read packet from - * \param outBuf buffer to read - * \param outLen buffer's length - * \param pUser parameter passed to the nfc_transport_init function - */ -typedef void (*nfc_transport_read_fn_t)(uint8_t address, uint8_t *inBuf, size_t inLen, void *pUser); - -typedef struct __transport { - nfc_transport_write_fn_t write; - nfc_transport_read_fn_t read; - void *pUser; -} nfc_transport_t; - -void nfc_transport_init(nfc_transport_t *pTransport, nfc_transport_write_fn_t write, nfc_transport_read_fn_t read, void *pUser); - -static inline void nfc_transport_write(nfc_transport_t *pTransport, uint8_t address, const uint8_t *outBuf, size_t outLen) -{ - pTransport->write(address, outBuf, outLen, pTransport->pUser); -} - -static inline void nfc_transport_read(nfc_transport_t *pTransport, uint8_t address, uint8_t *inBuf, size_t inLen) -{ - pTransport->read(address, inBuf, inLen, pTransport->pUser); -} - -#ifdef __cplusplus -} -#endif - -#endif /* NFC_TRANSPORT_H_ */ - - -/** - * @} - * @} - * */ - diff --git a/features/nfc/stack/tech/iso7816/iso7816.c b/features/nfc/stack/tech/iso7816/iso7816.c deleted file mode 100644 index fec02ae..0000000 --- a/features/nfc/stack/tech/iso7816/iso7816.c +++ /dev/null @@ -1,343 +0,0 @@ -/* - * Copyright (c) 2015-2018, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * 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. - */ -/** - * \file iso7816.c - * \copyright Copyright (c) ARM Ltd 2015 - * \author Donatien Garnier - */ - -#define __DEBUG__ 0 -#ifndef __MODULE__ -#define __MODULE__ "iso7816.c" -#endif - -#include "stack/nfc_errors.h" - -#include "iso7816.h" -#include "iso7816_app.h" -#include "iso7816_defs.h" -#include "tech/isodep/isodep_target.h" -#include "platform/nfc_debug.h" - -static void iso7816_disconnected(nfc_tech_iso7816_t *pIso7816, bool deselected); - -static nfc_err_t iso7816_parse(nfc_tech_iso7816_t *pIso7816); - -static void iso7816_receive(nfc_tech_iso7816_t *pIso7816); -static nfc_err_t iso7816_transmit(nfc_tech_iso7816_t *pIso7816); - -static bool iso7816_mf_command(nfc_tech_iso7816_t *pIso7816); - -static void iso_dep_received_cb(nfc_tech_isodep_t *pIsodep, nfc_err_t ret, void *pUserData); -static void iso_dep_transmitted_cb(nfc_tech_isodep_t *pIsodep, nfc_err_t ret, void *pUserData); -static void iso_dep_disconnected_cb(nfc_tech_isodep_t *pIsodep, bool deselected, void *pUserData); - -static void iso_dep_stream_transmit_cb(ac_buffer_t *ppDataIn, bool *pClose, size_t maxLength, void *pUserParam); -static void iso_dep_stream_receive_cb(ac_buffer_t *pDataOut, bool closed, void *pUserParam); - -void nfc_tech_iso7816_init(nfc_tech_iso7816_t *pIso7816, nfc_transceiver_t *pTransceiver, nfc_tech_iso7816_disconnected_cb disconnectedCb, void *pUserData) -{ - ac_buffer_init(&pIso7816->hist, NULL, 0); - nfc_tech_isodep_target_init(&pIso7816->isoDepTarget, pTransceiver, &pIso7816->hist, iso_dep_disconnected_cb, pIso7816); - pIso7816->pAppList = NULL; - pIso7816->pSelectedApp = NULL; - pIso7816->disconnectedCb = disconnectedCb; - - ac_istream_init(&pIso7816->inputStream, iso_dep_stream_transmit_cb, pIso7816); - ac_ostream_init(&pIso7816->outputStream, iso_dep_stream_receive_cb, pIso7816); - - ac_buffer_builder_init(&pIso7816->txBldr, pIso7816->txBuf, 2); //Just enough to fit sw - - ac_buffer_builder_init(&pIso7816->rxBldr, pIso7816->rxBuf, ISO7816_RX_BUFFER_SIZE); - - pIso7816->pUserData = pUserData; -} - -void nfc_tech_iso7816_connect(nfc_tech_iso7816_t *pIso7816) -{ - pIso7816->disconnected = false; - pIso7816->responseReady = true; - - iso7816_receive(pIso7816); - nfc_tech_isodep_target_connect(&pIso7816->isoDepTarget); -} - -void nfc_tech_iso7816_disconnect(nfc_tech_iso7816_t *pIso7816) -{ - nfc_tech_isodep_target_disconnect(&pIso7816->isoDepTarget); -} - -void nfc_tech_iso7816_add_app(nfc_tech_iso7816_t *pIso7816, nfc_tech_iso7816_app_t *pIso7816App) -{ - nfc_tech_iso7816_app_t **ppPrevApp = &pIso7816->pAppList; - while (*ppPrevApp != NULL) { - ppPrevApp = &((*ppPrevApp)->pNext); - } - *ppPrevApp = pIso7816App; - pIso7816App->pNext = NULL; -} - -nfc_err_t nfc_tech_iso7816_reply(nfc_tech_iso7816_t *pIso7816) -{ - nfc_err_t ret; - - //Serialize APDU and send - ac_buffer_builder_reset(&pIso7816->txBldr); - ac_buffer_builder_write_nu16(&pIso7816->txBldr, pIso7816->rApdu.sw); - - ac_buffer_append(&pIso7816->rApdu.dataOut, ac_buffer_builder_buffer(&pIso7816->txBldr)); - - NFC_DBG("R-ADPU: (LE):%02X SW:%04X", ac_buffer_reader_readable(&pIso7816->rApdu.dataOut), pIso7816->rApdu.sw); - NFC_DBG_BLOCK(ac_buffer_dump(&pIso7816->rApdu.dataOut);) - - ret = iso7816_transmit(pIso7816); - if (ret) { - return ret; - } - - return NFC_OK; -} - -void iso7816_disconnected(nfc_tech_iso7816_t *pIso7816, bool deselected) -{ - pIso7816->disconnected = true; - if (pIso7816->pSelectedApp != NULL) { - //Deselect previous app - pIso7816->pSelectedApp->deselected(pIso7816->pSelectedApp, pIso7816->pSelectedApp->pUserData); - pIso7816->pSelectedApp = NULL; - } - if (!deselected) { - pIso7816->disconnectedCb(pIso7816, pIso7816->pUserData); - } -} - -nfc_err_t iso7816_parse(nfc_tech_iso7816_t *pIso7816) -{ - //Reset R-APDU - ac_buffer_init(&pIso7816->rApdu.dataOut, NULL, 0); - pIso7816->rApdu.sw = ISO7816_SW_OK; - - NFC_DBG_BLOCK(ac_buffer_dump(ac_buffer_builder_buffer(&pIso7816->rxBldr));) - - if (ac_buffer_reader_readable(ac_buffer_builder_buffer(&pIso7816->rxBldr)) < 4) { - NFC_ERR("C-APDU is too small"); - pIso7816->rApdu.sw = ISO7816_SW_INVALID_CLASS; - nfc_tech_iso7816_reply(pIso7816); - return NFC_ERR_PROTOCOL; - } - - pIso7816->cApdu.cla = ac_buffer_read_nu8(ac_buffer_builder_buffer(&pIso7816->rxBldr)); - pIso7816->cApdu.ins = ac_buffer_read_nu8(ac_buffer_builder_buffer(&pIso7816->rxBldr)); - pIso7816->cApdu.p1 = ac_buffer_read_nu8(ac_buffer_builder_buffer(&pIso7816->rxBldr)); - pIso7816->cApdu.p2 = ac_buffer_read_nu8(ac_buffer_builder_buffer(&pIso7816->rxBldr)); - ac_buffer_init(&pIso7816->cApdu.dataIn, NULL, 0); - pIso7816->cApdu.maxRespLength = 0; - - if (ac_buffer_reader_readable(ac_buffer_builder_buffer(&pIso7816->rxBldr)) > 1) { - size_t lc = ac_buffer_read_nu8(ac_buffer_builder_buffer(&pIso7816->rxBldr)); - if (ac_buffer_reader_readable(ac_buffer_builder_buffer(&pIso7816->rxBldr)) >= lc) { - ac_buffer_split(&pIso7816->cApdu.dataIn, ac_buffer_builder_buffer(&pIso7816->rxBldr), ac_buffer_builder_buffer(&pIso7816->rxBldr), lc); - } else { - pIso7816->rApdu.sw = ISO7816_SW_WRONG_LENGTH; - nfc_tech_iso7816_reply(pIso7816); - return NFC_ERR_LENGTH; //Not a valid frame - } - } - - if (ac_buffer_reader_readable(ac_buffer_builder_buffer(&pIso7816->rxBldr)) >= 1) { - pIso7816->cApdu.maxRespLength = ac_buffer_read_nu8(ac_buffer_builder_buffer(&pIso7816->rxBldr)); - } - - NFC_DBG("C-APDU: CLA:%02X INS:%02X P1:%02X P2:%02X LC:%02X LE:%02X", pIso7816->cApdu.cla, pIso7816->cApdu.ins, pIso7816->cApdu.p1, pIso7816->cApdu.p2, - ac_buffer_reader_readable(&pIso7816->cApdu.dataIn), pIso7816->cApdu.maxRespLength); - - if (ac_buffer_reader_readable(ac_buffer_builder_buffer(&pIso7816->rxBldr)) > 0) { - pIso7816->rApdu.sw = ISO7816_SW_WRONG_LENGTH; - nfc_tech_iso7816_reply(pIso7816); - return NFC_ERR_LENGTH; //Not a valid frame - } - - //See if can select an app - if (iso7816_mf_command(pIso7816)) { - nfc_tech_iso7816_reply(pIso7816); - return NFC_OK; - } - - //Pass command to selected app - if (pIso7816->pSelectedApp == NULL) { - pIso7816->rApdu.sw = ISO7816_SW_NOT_FOUND; - nfc_tech_iso7816_reply(pIso7816); - return NFC_ERR_NOT_FOUND; //Not a valid frame - } - - pIso7816->pSelectedApp->apdu(pIso7816->pSelectedApp, pIso7816->pSelectedApp->pUserData); - - return NFC_OK; -} - -void iso7816_receive(nfc_tech_iso7816_t *pIso7816) -{ - ac_buffer_builder_reset(&pIso7816->rxBldr); - nfc_tech_isodep_target_receive(&pIso7816->isoDepTarget, &pIso7816->outputStream, iso_dep_received_cb, pIso7816); -} - -nfc_err_t iso7816_transmit(nfc_tech_iso7816_t *pIso7816) -{ - return nfc_tech_isodep_target_transmit(&pIso7816->isoDepTarget, &pIso7816->inputStream, iso_dep_transmitted_cb, pIso7816); -} - -/** Handle ISO7816-4 command - * \param pTarget pointer to target instance - * \param CLA ISO7816-4 class byte - * \param INS ISO7816-4 instruction byte - * \param P1 ISO7816-4 P1 byte - * \param P2 ISO7816-4 P2 byte - * \param pDataIn ISO7816-4 command payload - * \param pDataOut ISO7816-4 response payload - * \param SW status word - * \return true if command was handled, false if it should be passed to the selected application - */ -bool iso7816_mf_command(nfc_tech_iso7816_t *pIso7816) -{ - nfc_tech_iso7816_app_t *pApp; - if (pIso7816->cApdu.cla != 0x00) { - return false; - } - switch (pIso7816->cApdu.ins) { - case ISO7816_INS_SELECT: - switch (pIso7816->cApdu.p1) { - case 0x04: //Selection by DF name - pApp = pIso7816->pAppList; - while (pApp != NULL) { - if (ac_buffer_reader_readable(&pIso7816->cApdu.dataIn) <= pApp->aidSize) { - if (ac_buffer_reader_cmp_bytes(&pIso7816->cApdu.dataIn, pApp->aid, ac_buffer_reader_readable(&pIso7816->cApdu.dataIn))) { - if (pIso7816->pSelectedApp != NULL) { - //Deselect previous app - pIso7816->pSelectedApp->deselected(pIso7816->pSelectedApp, pIso7816->pSelectedApp->pUserData); - } - pIso7816->pSelectedApp = pApp; - pIso7816->pSelectedApp->selected(pIso7816->pSelectedApp, pIso7816->pSelectedApp->pUserData); - pIso7816->rApdu.sw = ISO7816_SW_OK; - return true; - } - } - pApp = pApp->pNext; - } - pIso7816->rApdu.sw = ISO7816_SW_NOT_FOUND; - return true; - default: - if (pIso7816->pSelectedApp == NULL) { - pIso7816->rApdu.sw = ISO7816_SW_NOT_FOUND; - return true; - } else { - return false; - } - } - break; - default: - if (pIso7816->pSelectedApp == NULL) { - pIso7816->rApdu.sw = ISO7816_SW_INVALID_INS; - return true; - } else { - return false; - } - break; - } -} - -void iso_dep_received_cb(nfc_tech_isodep_t *pIsodep, nfc_err_t ret, void *pUserData) -{ - nfc_tech_iso7816_t *pIso7816 = (nfc_tech_iso7816_t *) pUserData; - - (void) pIsodep; - - if (ret) { - NFC_WARN("Got error %d", ret); - return; - } - - //Parse received APDU - ret = iso7816_parse(pIso7816); - if (ret) { - NFC_WARN("Got error %d", ret); - return; - } -} - -void iso_dep_transmitted_cb(nfc_tech_isodep_t *pIsodep, nfc_err_t ret, void *pUserData) -{ - nfc_tech_iso7816_t *pIso7816 = (nfc_tech_iso7816_t *) pUserData; - - (void) pIsodep; - - if (ret) { - NFC_WARN("Got error %d", ret); - return; - } - - //Advertise that we have space in our buffer? - - //Switch to receive mode! - iso7816_receive(pIso7816); -} - -void iso_dep_disconnected_cb(nfc_tech_isodep_t *pIsodep, bool deselected, void *pUserData) -{ - nfc_tech_iso7816_t *pIso7816 = (nfc_tech_iso7816_t *) pUserData; - - (void) pIsodep; - - NFC_DBG("ISO DEP %s", deselected ? "deselected" : "disconnected"); - iso7816_disconnected(pIso7816, deselected); - - if (deselected) { - // Re-connect immediately - nfc_tech_iso7816_connect(pIso7816); - } -} - -void iso_dep_stream_transmit_cb(ac_buffer_t *pDataIn, bool *pClose, size_t maxLength, void *pUserParam) -{ - nfc_tech_iso7816_t *pIso7816 = (nfc_tech_iso7816_t *) pUserParam; - - //Only close if buffer fits in this frame - if (maxLength >= ac_buffer_reader_readable(&pIso7816->rApdu.dataOut)) - //if( ac_buffer_total_length(&pLlcp->tx) <= maxLength ) - { - maxLength = ac_buffer_reader_readable(&pIso7816->rApdu.dataOut); - *pClose = true; - } else { - *pClose = false; - } - - ac_buffer_split(pDataIn, &pIso7816->rApdu.dataOut, &pIso7816->rApdu.dataOut, maxLength); -} - -void iso_dep_stream_receive_cb(ac_buffer_t *pDataOut, bool closed, void *pUserParam) -{ - nfc_tech_iso7816_t *pIso7816 = (nfc_tech_iso7816_t *) pUserParam; - - (void) closed; - - if (ac_buffer_reader_readable(pDataOut) > ac_buffer_builder_writable(&pIso7816->rxBldr)) { - NFC_ERR("Frame will not fit (%u > %u)", ac_buffer_reader_readable(pDataOut), ac_buffer_builder_writable(&pIso7816->rxBldr)); - } - - //Feed rx buffer - ac_buffer_builder_copy_n_bytes(&pIso7816->rxBldr, pDataOut, ac_buffer_reader_readable(pDataOut)); -} - diff --git a/features/nfc/stack/tech/iso7816/iso7816.h b/features/nfc/stack/tech/iso7816/iso7816.h deleted file mode 100644 index ea223f4..0000000 --- a/features/nfc/stack/tech/iso7816/iso7816.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (c) 2014-2018, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * 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. - */ -/** - * \file iso7816.h - * \copyright Copyright (c) ARM Ltd 2014 - * \author Donatien Garnier - */ - -#ifndef ISO7816_H_ -#define ISO7816_H_ - -#include "stack/nfc_common.h" - -#include "transceiver/protocols.h" -#include "tech/isodep/isodep_target.h" - -#ifdef __cplusplus -extern "C" { -#endif - -struct nfc_tech_iso7816_c_apdu { - uint8_t cla; - uint8_t ins; - uint8_t p1; - uint8_t p2; - ac_buffer_t dataIn; - size_t maxRespLength; -}; - -struct nfc_tech_iso7816_r_apdu { - ac_buffer_t dataOut; - uint16_t sw; -}; - -#define ISO7816_RX_BUFFER_SIZE 256 - -typedef struct nfc_tech_iso7816_c_apdu nfc_tech_iso7816_c_apdu_t; -typedef struct nfc_tech_iso7816_r_apdu nfc_tech_iso7816_r_apdu_t; - -typedef struct nfc_tech_iso7816 nfc_tech_iso7816_t; - -typedef void (*nfc_tech_iso7816_disconnected_cb)(nfc_tech_iso7816_t *pIso7816, void *pUserData); - -struct nfc_tech_iso7816_app; -typedef struct nfc_tech_iso7816_app nfc_tech_iso7816_app_t; - -struct nfc_tech_iso7816 { - nfc_tech_isodep_target_t isoDepTarget; - - nfc_tech_iso7816_app_t *pAppList; - nfc_tech_iso7816_app_t *pSelectedApp; - - bool disconnected; - - nfc_tech_iso7816_c_apdu_t cApdu; - nfc_tech_iso7816_r_apdu_t rApdu; - - bool responseReady; - - nfc_tech_iso7816_disconnected_cb disconnectedCb; - void *pUserData; - - ac_buffer_t hist; //Historical bytes - - ac_istream_t inputStream; - ac_ostream_t outputStream; - - //PDU buffer (tx) - uint8_t txBuf[2]; - ac_buffer_builder_t txBldr; - - //Receive buffer - uint8_t rxBuf[ISO7816_RX_BUFFER_SIZE]; - ac_buffer_builder_t rxBldr; -}; - -void nfc_tech_iso7816_init(nfc_tech_iso7816_t *pIso7816, nfc_transceiver_t *pTransceiver, nfc_tech_iso7816_disconnected_cb disconnectedCb, void *pUserData); -void nfc_tech_iso7816_add_app(nfc_tech_iso7816_t *pIso7816, nfc_tech_iso7816_app_t *pIso7816App); -void nfc_tech_iso7816_connect(nfc_tech_iso7816_t *pIso7816); -void nfc_tech_iso7816_disconnect(nfc_tech_iso7816_t *pIso7816); -nfc_err_t nfc_tech_iso7816_reply(nfc_tech_iso7816_t *pIso7816); - -inline static nfc_tech_iso7816_c_apdu_t *nfc_tech_iso7816_c_apdu(nfc_tech_iso7816_t *pIso7816) -{ - return &pIso7816->cApdu; -} - -inline static nfc_tech_iso7816_r_apdu_t *nfc_tech_iso7816_r_apdu(nfc_tech_iso7816_t *pIso7816) -{ - return &pIso7816->rApdu; -} - -#ifdef __cplusplus -} -#endif - -#endif /* ISO7816_H_ */ diff --git a/features/nfc/stack/tech/iso7816/iso7816_app.c b/features/nfc/stack/tech/iso7816/iso7816_app.c deleted file mode 100644 index 63ee17a..0000000 --- a/features/nfc/stack/tech/iso7816/iso7816_app.c +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2013-2018, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * 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. - */ -/** - * \file iso7816_app.c - * \copyright Copyright (c) ARM Ltd 2015-2018 - * \author Donatien Garnier - */ - -#include "iso7816_app.h" - -void nfc_tech_iso7816_app_init(nfc_tech_iso7816_app_t *pIso7816App, - nfc_tech_iso7816_t *pIso7816, - const uint8_t *aid, size_t aidSize, - nfc_tech_iso7816_app_cb selected, - nfc_tech_iso7816_app_cb deselected, - nfc_tech_iso7816_app_cb apdu, - void *pUserData - ) -{ - pIso7816App->pIso7816 = pIso7816; - pIso7816App->aid = aid; - pIso7816App->aidSize = aidSize; - pIso7816App->selected = selected; - pIso7816App->deselected = deselected; - pIso7816App->apdu = apdu; - pIso7816App->pUserData = pUserData; - pIso7816App->pNext = NULL; -} diff --git a/features/nfc/stack/tech/iso7816/iso7816_app.h b/features/nfc/stack/tech/iso7816/iso7816_app.h deleted file mode 100644 index 25c403e..0000000 --- a/features/nfc/stack/tech/iso7816/iso7816_app.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) 2015-2018, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * 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. - */ -/** - * \file iso7816_app.h - * \copyright Copyright (c) ARM Ltd 2015 - * \author Donatien Garnier - */ -#ifndef TECH_ISO7816_ISO7816_APP_H_ -#define TECH_ISO7816_ISO7816_APP_H_ - -#include "stack/nfc_common.h" -#include "iso7816.h" - -#ifdef __cplusplus -extern "C" { -#endif - -struct nfc_tech_iso7816; -struct nfc_tech_iso7816_app; - -typedef void (*nfc_tech_iso7816_app_cb)(nfc_tech_iso7816_app_t *pIso7816App, void *pUserData); - -struct nfc_tech_iso7816_app { - nfc_tech_iso7816_t *pIso7816; - - const uint8_t *aid; - size_t aidSize; - - nfc_tech_iso7816_app_cb selected; - nfc_tech_iso7816_app_cb deselected; - nfc_tech_iso7816_app_cb apdu; - - void *pUserData; - - nfc_tech_iso7816_app_t *pNext; -}; - -void nfc_tech_iso7816_app_init(nfc_tech_iso7816_app_t *pIso7816App, nfc_tech_iso7816_t *pIso7816, const uint8_t *aid, size_t aidSize, - nfc_tech_iso7816_app_cb selected, - nfc_tech_iso7816_app_cb deselected, - nfc_tech_iso7816_app_cb apdu, - void *pUserData - ); - -inline static nfc_err_t nfc_tech_iso7816_app_reply(nfc_tech_iso7816_app_t *pIso7816App) -{ - return nfc_tech_iso7816_reply(pIso7816App->pIso7816); -} - -inline static nfc_tech_iso7816_c_apdu_t *nfc_tech_iso7816_app_c_apdu(nfc_tech_iso7816_app_t *pIso7816App) -{ - return nfc_tech_iso7816_c_apdu(pIso7816App->pIso7816); -} - -inline static nfc_tech_iso7816_r_apdu_t *nfc_tech_iso7816_app_r_apdu(nfc_tech_iso7816_app_t *pIso7816App) -{ - return nfc_tech_iso7816_r_apdu(pIso7816App->pIso7816); -} - -#ifdef __cplusplus -} -#endif - -#endif /* TECH_ISO7816_ISO7816_APP_H_ */ diff --git a/features/nfc/stack/tech/iso7816/iso7816_defs.h b/features/nfc/stack/tech/iso7816/iso7816_defs.h deleted file mode 100644 index 7f7e42c..0000000 --- a/features/nfc/stack/tech/iso7816/iso7816_defs.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2013-2018, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * 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. - */ -/** - * \file iso7816_defs.h - * \copyright Copyright (c) ARM Ltd 2013 - * \author Donatien Garnier - */ - -#ifndef ISO7816_DEFS_H_ -#define ISO7816_DEFS_H_ - -#define ISO7816_INS_SELECT 0xA4 -#define ISO7816_INS_READ_BINARY 0xB0 -#define ISO7816_INS_UPDATE_BINARY 0xD6 -#define ISO7816_INS_ENVELOPE 0xC2 - - -#define ISO7816_SW_OK 0x9000 -#define ISO7816_SW_INVALID_CLASS 0x6E00 -#define ISO7816_SW_INVALID_INS 0x6D00 -#define ISO7816_SW_NOT_FOUND 0x6A82 -#define ISO7816_SW_WRONG_LENGTH 0x6700 - -#define ISO7816_PUT_SW(buf, sw) do{ *(buf)=(sw>>8) & 0xFF; *(buf+1)=(sw>>0) & 0xFF; } while(0); - - - -#endif /* ISO7816_DEFS_H_ */ diff --git a/features/nfc/stack/tech/isodep/isodep.h b/features/nfc/stack/tech/isodep/isodep.h deleted file mode 100644 index 7ef3c72..0000000 --- a/features/nfc/stack/tech/isodep/isodep.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2015-2018, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * 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. - */ -/** - * \file isodep.h - * \copyright Copyright (c) ARM Ltd 2014 - * \author Donatien Garnier - */ - -#ifndef ISODEP_H_ -#define ISODEP_H_ - -#include "stack/nfc_common.h" -#include "transceiver/transceiver.h" - -#ifdef __cplusplus -extern "C" { -#endif - -struct nfc_tech_isodep; -typedef struct nfc_tech_isodep nfc_tech_isodep_t; - -typedef void (*nfc_tech_isodep_cb_t)(nfc_tech_isodep_t *pIsodep, nfc_err_t ret, void *pUserData); -typedef void (*nfc_tech_isodep_disconnected_cb)(nfc_tech_isodep_t *pIsodep, bool deselected, void *pUserData); - -#ifdef __cplusplus -} -#endif - -#endif /* ISODEP_H_ */ diff --git a/features/nfc/stack/tech/isodep/isodep_target.c b/features/nfc/stack/tech/isodep/isodep_target.c deleted file mode 100644 index 9791422..0000000 --- a/features/nfc/stack/tech/isodep/isodep_target.c +++ /dev/null @@ -1,685 +0,0 @@ -/* - * Copyright (c) 2015-2018, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * 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. - */ -/** - * \file isodep_target.c - * \copyright Copyright (c) ARM Ltd 2015 - * \author Donatien Garnier - */ - -#define __DEBUG__ 0 -#ifndef __MODULE__ -#define __MODULE__ "isodep_target.c" -#endif - -#include "isodep_target.h" - -#include "stack/nfc_errors.h" -#include "transceiver/transceiver.h" - -//Private defines -#define RATS 0xE0 -#define FSDI_TO_FSD(x) (((x)<5)?(((x)<<3) + 16):((x)<8)?(((x)<<5)-96):256) -#define FSC_TO_FSCI(x) (((x)<=48)?(((x)-16)>>3):((x)<=128)?(((x)+96)>>5):8) //returns the closest lower or equal value -#define DID(x) ((x) & 0x0F) -#define FSDI(x) (((x) >> 4) & 0x0F) - -#define FSCI_TO_FSC(x) FSDI_TO_FSD(x) -#define FSD_TO_FSDI(x) FSC_TO_FSCI(x) - -//#define DI_TO_D(x) (1 << (x)) -#define DI_TO_BITRATE(x) ((RF_BITRATE)((x) + RF_BITRATE_106K)) - - -#define GET_FRAME_TYPE(pcb) ((((pcb) & 0xF0) == 0xD0)?PPS_FRAME:(((pcb) & 0xC0) == (0x00 << 6))?I_FRAME:((((pcb) & 0xC0) == (0x2 << 6))?R_FRAME:S_FRAME)) - -#define I_BLOCK_PCB 0 -#define R_BLOCK_PCB 2 -#define S_BLOCK_PCB 3 - -#define PCB_TYPE(pcb) (((pcb)>>6)&0x03) - -#define BUILD_I_BLOCK_PCB(chaining, cid, nad, block_toggle) ( (0x0 << 6) | (((chaining)?1:0) << 4) \ - | (((cid)?1:0) << 3) | (((nad)?1:0) << 2) | (1 << 1) | (((block_toggle)?1:0)) ) -#define BUILD_S_BLOCK_PCB(cid, wtx_n_deselect) ( (0x3 << 6) | (((wtx_n_deselect)?0x3:0) << 4) \ - | (((cid)?1:0) << 3) | (1 << 1) ) -#define BUILD_R_BLOCK_PCB(cid, block_toggle, nak) ( (0x2 << 6) | (1 <<5) | (((nak)?1:0) << 4) \ - | (((cid)?1:0) << 3) | (1 << 1) | (((block_toggle)?1:0)) ) - -#define PCB_IS_CID(pcb) (((pcb) & (1 << 3))?true:false) -#define PCB_BLOCK_TOGGLE(pcb) (((pcb) & 1)?true:false) -#define PCB_CHAINING(pcb) (((pcb) & 0x10)?true:false) -#define PCB_NACK(pcb) (((pcb) & 0x10)?true:false) -#define PCB_WTX(pcb) (((pcb)&0x30)==0x30) - -#define WTXM_DEFAULT 10 - -//Parameters -#define FSC 256 //Maximum frame size the PICC (us) can receive -- TODO should be a parameter at some point -- linked to PN512 buffer -#define SFGI 2 //Guard time ~ 1.2ms -//#define FWI 6 //Max time before answer is ~ 19.3ms -#define FWI 14 //Max time before answer is ~ 19.3ms - -typedef enum __dep_type dep_type_t; -enum __dep_type { - dep_type_information, - dep_type_response, - dep_type_supervisory, -}; - -//Local functions -static void dep_init(nfc_tech_isodep_target_t *pIsodepTarget); -static bool dep_ready(nfc_tech_isodep_target_t *pIsodepTarget); - -static void dep_req_information(nfc_tech_isodep_target_t *pIsodepTarget, ac_buffer_t *pReq, bool moreInformation, uint8_t blockNumber); -static void dep_req_response(nfc_tech_isodep_target_t *pIsodepTarget, bool ack, uint8_t blockNumber); -static void dep_req_supervisory(nfc_tech_isodep_target_t *pIsodepTarget, bool wtxNDeselect, uint8_t wtxm); - -static dep_type_t dep_res_type(nfc_tech_isodep_target_t *pIsodepTarget); -static void dep_res_information(nfc_tech_isodep_target_t *pIsodepTarget, size_t maxLength, ac_buffer_t **ppRes, bool *pMoreInformation, uint8_t *pBlockNumber); -static void dep_res_response(nfc_tech_isodep_target_t *pIsodepTarget, bool *pAck, uint8_t *pBlockNumber); -static void dep_res_supervisory(nfc_tech_isodep_target_t *pIsodepTarget, bool *pWtxNDeselect, uint8_t *pWtxm); - -static void dep_disconnected(nfc_tech_isodep_target_t *pIsodepTarget, bool deselected); - -static void command_init(nfc_tech_isodep_target_t *pIsodepTarget); - -static nfc_err_t command_ats_req(nfc_tech_isodep_target_t *pIsodepTarget); -static nfc_err_t command_dep_req(nfc_tech_isodep_target_t *pIsodepTarget); - -static nfc_err_t command_ats_res(nfc_tech_isodep_target_t *pIsodepTarget); -static nfc_err_t command_dep_res(nfc_tech_isodep_target_t *pIsodepTarget); - -static void command_reply(nfc_tech_isodep_target_t *pIsodepTarget, bool depWait); -static void command_transceiver_cb(nfc_transceiver_t *pTransceiver, nfc_err_t ret, void *pUserData); - -//High-level Target functions -void nfc_tech_isodep_target_init(nfc_tech_isodep_target_t *pIsodepTarget, nfc_transceiver_t *pTransceiver, - ac_buffer_t *pHist, nfc_tech_isodep_disconnected_cb disconnectedCb, void *pUserData) -{ - pIsodepTarget->pTransceiver = pTransceiver; - - pIsodepTarget->pHist = pHist; - - pIsodepTarget->disconnectedCb = disconnectedCb; - pIsodepTarget->pUserData = pUserData; - - dep_init(pIsodepTarget); - command_init(pIsodepTarget); -} - -nfc_err_t nfc_tech_isodep_target_connect(nfc_tech_isodep_target_t *pIsodepTarget) -{ - NFC_DBG("Connecting"); - pIsodepTarget->commands.state = ISO_DEP_TARGET_COMMANDS_CONNECTING; - - transceiver_set_crc(pIsodepTarget->pTransceiver, true, true); - command_transceiver_cb(pIsodepTarget->pTransceiver, NFC_OK, pIsodepTarget); - - return NFC_OK; -} - -void nfc_tech_isodep_target_disconnect(nfc_tech_isodep_target_t *pIsodepTarget) -{ - // This should not be called within a callback - - transceiver_abort(pIsodepTarget->pTransceiver); - - dep_disconnected(pIsodepTarget, false); -} - -nfc_err_t nfc_tech_isodep_target_transmit(nfc_tech_isodep_target_t *pIsodepTarget, ac_istream_t *pStream, nfc_tech_isodep_cb_t cb, void *pUserData) -{ - if (pIsodepTarget->dep.pReqStream != NULL) { - return NFC_ERR_BUSY; - } - - pIsodepTarget->dep.pResStream = pStream; - pIsodepTarget->dep.resCb = cb; - pIsodepTarget->dep.pResUserData = pUserData; - - //Do we need to start transceiving? - if (pIsodepTarget->commands.state == ISO_DEP_TARGET_COMMANDS_DEP_REQ_RECVD) { - command_reply(pIsodepTarget, false); //Force reply - } - - return NFC_OK; -} - -nfc_err_t nfc_tech_isodep_target_receive(nfc_tech_isodep_target_t *pIsodepTarget, ac_ostream_t *pStream, nfc_tech_isodep_cb_t cb, void *pUserData) -{ - if (pIsodepTarget->dep.pResStream != NULL) { - return NFC_ERR_BUSY; - } - - pIsodepTarget->dep.pReqStream = pStream; - pIsodepTarget->dep.reqCb = cb; - pIsodepTarget->dep.pReqUserData = pUserData; - - return NFC_OK; -} - -//DEP Layer -void dep_init(nfc_tech_isodep_target_t *pIsodepTarget) -{ - //ac_buffer_init(&pIsodepTarget->dep.res, NULL, 0); - pIsodepTarget->dep.pReqStream = NULL; - pIsodepTarget->dep.pResStream = NULL; - - pIsodepTarget->dep.reqCb = NULL; - pIsodepTarget->dep.pReqUserData = NULL; - - pIsodepTarget->dep.resCb = NULL; - pIsodepTarget->dep.pResUserData = NULL; - - pIsodepTarget->dep.blockNumber = 1; //Rule C - - //pIsodepTarget->dep.pduState = ISO_DEP_TARGET_DEP_PDU_IDLE; - pIsodepTarget->dep.chaining = false; - pIsodepTarget->dep.frameState = ISO_DEP_TARGET_DEP_FRAME_IDLE; -} - -bool dep_ready(nfc_tech_isodep_target_t *pIsodepTarget) -{ - //Anything to send back? - if (pIsodepTarget->dep.frameState != ISO_DEP_TARGET_DEP_FRAME_INFORMATION_RECEIVED) { - return true; - } - - if ((pIsodepTarget->dep.pResStream != NULL)) { - return true; - } else { - return false; - } -} - -void dep_req_information(nfc_tech_isodep_target_t *pIsodepTarget, ac_buffer_t *pReq, bool moreInformation, uint8_t blockNumber) -{ - (void) blockNumber; - - pIsodepTarget->dep.blockNumber++; - pIsodepTarget->dep.blockNumber %= 2; - - // Note: callbacks can call nfc_tech_isodep_target_transmit() - however we must make sure that we wait AFTER this routine has been processed to actually transmit - // To do so, reset state to ATS_RES_SENT state - pIsodepTarget->commands.state = ISO_DEP_TARGET_COMMANDS_ATS_RES_SENT; - - if (!pIsodepTarget->dep.chaining - && (pIsodepTarget->dep.pResStream != NULL)) { - //Sent the full frame - pIsodepTarget->dep.pResStream = NULL; - pIsodepTarget->dep.resCb((nfc_tech_isodep_t *)pIsodepTarget, NFC_OK, pIsodepTarget->dep.pResUserData); - } - if (pIsodepTarget->dep.pReqStream != NULL) { - // Pull more - ac_ostream_push(pIsodepTarget->dep.pReqStream, pReq, !moreInformation); - if (!moreInformation) { - //Got the full frame - pIsodepTarget->dep.pReqStream = NULL; - pIsodepTarget->dep.reqCb((nfc_tech_isodep_t *)pIsodepTarget, NFC_OK, pIsodepTarget->dep.pReqUserData); - } - } - - // Update state - pIsodepTarget->dep.frameState = ISO_DEP_TARGET_DEP_FRAME_INFORMATION_RECEIVED; - pIsodepTarget->dep.chaining = moreInformation; -} - -void dep_req_response(nfc_tech_isodep_target_t *pIsodepTarget, bool ack, uint8_t blockNumber) -{ - if (blockNumber != pIsodepTarget->dep.blockNumber) { - //Should be NACK - pIsodepTarget->dep.frameState = ISO_DEP_TARGET_DEP_FRAME_NACK_DIFF_BLOCK_NUMBER_RECEIVED; - } else { - if (ack) { - pIsodepTarget->dep.frameState = ISO_DEP_TARGET_DEP_FRAME_ACK_RECEIVED; - } else { - pIsodepTarget->dep.frameState = ISO_DEP_TARGET_DEP_FRAME_NACK_RECEIVED; - } - } -} - -void dep_req_supervisory(nfc_tech_isodep_target_t *pIsodepTarget, bool wtxNDeselect, uint8_t wtxm) -{ - (void) wtxm; - - if (wtxNDeselect) { - if ((pIsodepTarget->dep.frameState != ISO_DEP_TARGET_DEP_FRAME_WTX_SENT)) { - NFC_WARN("Unexpected WTX frame"); - } - pIsodepTarget->dep.frameState = ISO_DEP_TARGET_DEP_FRAME_WTX_RECEIVED; - } else { - pIsodepTarget->dep.frameState = ISO_DEP_TARGET_DEP_FRAME_DESELECT_RECEIVED; - } -} - -dep_type_t dep_res_type(nfc_tech_isodep_target_t *pIsodepTarget) -{ - dep_type_t depType; - switch (pIsodepTarget->dep.frameState) { - case ISO_DEP_TARGET_DEP_FRAME_DESELECT_RECEIVED: - depType = dep_type_supervisory; //Deselect - break; - case ISO_DEP_TARGET_DEP_FRAME_INFORMATION_RECEIVED: - case ISO_DEP_TARGET_DEP_FRAME_WTX_RECEIVED: - if (pIsodepTarget->dep.chaining) { //Need to ack? - depType = dep_type_response; - } else if (pIsodepTarget->dep.pResStream != NULL) { //Anything to send back? - depType = dep_type_information; - } else { - depType = dep_type_supervisory; //WTX - } - break; - case ISO_DEP_TARGET_DEP_FRAME_ACK_RECEIVED: - if ((pIsodepTarget->dep.pResStream != NULL) && (pIsodepTarget->dep.chaining)) { - depType = dep_type_information; - } else { - depType = dep_type_supervisory; //WTX - } - break; - case ISO_DEP_TARGET_DEP_FRAME_NACK_DIFF_BLOCK_NUMBER_RECEIVED: - depType = dep_type_response; //Should send ACK - break; - case ISO_DEP_TARGET_DEP_FRAME_NACK_RECEIVED: - depType = dep_type_information; - break; - default: - depType = dep_type_supervisory; //ATN - break; - } - return depType; -} - -void dep_res_information(nfc_tech_isodep_target_t *pIsodepTarget, size_t maxLength, ac_buffer_t **ppRes, bool *pMoreInformation, uint8_t *pBlockNumber) -{ - *pBlockNumber = pIsodepTarget->dep.blockNumber; - if (pIsodepTarget->dep.frameState != ISO_DEP_TARGET_DEP_FRAME_NACK_RECEIVED) { - if (pIsodepTarget->dep.pResStream != NULL) { - bool lastFrame = true; - ac_istream_pull(pIsodepTarget->dep.pResStream, &pIsodepTarget->dep.res, &lastFrame, maxLength); - pIsodepTarget->dep.chaining = !lastFrame; - } - } else { - //Retransmit previous frame (leave it as it is) - } - *ppRes = &pIsodepTarget->dep.res; - *pMoreInformation = pIsodepTarget->dep.chaining; - pIsodepTarget->dep.frameState = ISO_DEP_TARGET_DEP_FRAME_INFORMATION_SENT; -} - -void dep_res_response(nfc_tech_isodep_target_t *pIsodepTarget, bool *pAck, uint8_t *pBlockNumber) -{ - //Continue chaining or send ACK - *pAck = true; - *pBlockNumber = pIsodepTarget->dep.blockNumber; - pIsodepTarget->dep.frameState = ISO_DEP_TARGET_DEP_FRAME_ACK_SENT; -} - -void dep_res_supervisory(nfc_tech_isodep_target_t *pIsodepTarget, bool *pWtxNDeselect, uint8_t *pWtxm) -{ - if (pIsodepTarget->dep.frameState == ISO_DEP_TARGET_DEP_FRAME_DESELECT_RECEIVED) { - *pWtxNDeselect = false; - pIsodepTarget->dep.frameState = ISO_DEP_TARGET_DEP_FRAME_DESELECT_SENT; - } else { - *pWtxNDeselect = true; - *pWtxm = WTXM_DEFAULT; - pIsodepTarget->dep.frameState = ISO_DEP_TARGET_DEP_FRAME_WTX_SENT; - } -} - -void dep_disconnected(nfc_tech_isodep_target_t *pIsodepTarget, bool deselected) -{ - //Call callbacks if needed - if (pIsodepTarget->dep.pReqStream != NULL) { - pIsodepTarget->dep.reqCb((nfc_tech_isodep_t *)pIsodepTarget, NFC_ERR_DISCONNECTED, pIsodepTarget->dep.pReqUserData); - pIsodepTarget->dep.pReqStream = NULL; - } - if (pIsodepTarget->dep.pReqStream != NULL) { - pIsodepTarget->dep.resCb((nfc_tech_isodep_t *)pIsodepTarget, NFC_ERR_DISCONNECTED, pIsodepTarget->dep.pResUserData); - pIsodepTarget->dep.pResStream = NULL; - } - if (pIsodepTarget->commands.state != ISO_DEP_TARGET_COMMANDS_DISCONNECTED) { - pIsodepTarget->commands.state = ISO_DEP_TARGET_COMMANDS_DISCONNECTED; - pIsodepTarget->disconnectedCb((nfc_tech_isodep_t *)pIsodepTarget, deselected, pIsodepTarget->pUserData); - } -} - -//Commands Layer -void command_init(nfc_tech_isodep_target_t *pIsodepTarget) -{ - ac_buffer_builder_init(&pIsodepTarget->commands.respBldr, pIsodepTarget->commands.respBuf, sizeof(pIsodepTarget->commands.respBuf)); - pIsodepTarget->commands.pReq = NULL; - // Update if/when we support DIDs - //pIsodepTarget->commands.did = 0; - //pIsodepTarget->commands.didUsed = false; - pIsodepTarget->commands.state = ISO_DEP_TARGET_COMMANDS_DISCONNECTED; - pIsodepTarget->commands.inPayloadSize = 0; -} - -nfc_err_t command_ats_req(nfc_tech_isodep_target_t *pIsodepTarget) -{ - //Check we are in a correct state -- this should be the first command received - if (pIsodepTarget->commands.state != ISO_DEP_TARGET_COMMANDS_CONNECTING) { - return NFC_ERR_PROTOCOL; - } - - if (ac_buffer_reader_readable(pIsodepTarget->commands.pReq) < 2) { - NFC_ERR("Payload too short"); - return NFC_ERR_PROTOCOL; - } - - ac_buffer_read_n_skip(pIsodepTarget->commands.pReq, 1); - - uint8_t b = ac_buffer_read_nu8(pIsodepTarget->commands.pReq); - - //Save DID -- not supported for now - //pIsodepTarget->commands.did = DID(b); - - uint8_t fsdi = FSDI(b); - pIsodepTarget->commands.inPayloadSize = FSDI_TO_FSD(fsdi); - - pIsodepTarget->commands.state = ISO_DEP_TARGET_COMMANDS_ATS_REQ_RECVD; - - return NFC_OK; -} - -nfc_err_t command_dep_req(nfc_tech_isodep_target_t *pIsodepTarget) -{ - if (pIsodepTarget->commands.state < ISO_DEP_TARGET_COMMANDS_ATS_RES_SENT) { - return NFC_ERR_PROTOCOL; - } - - if (ac_buffer_reader_readable(pIsodepTarget->commands.pReq) < 1) { - NFC_ERR("Payload too short"); - return NFC_ERR_PROTOCOL; - } - - uint8_t pcb = ac_buffer_read_nu8(pIsodepTarget->commands.pReq); - - // Udpate if/when we support DIDs - /* - if( pfb & PFB_DID ) - { - uint8_t did = ac_buffer_read_nu8(pIsodepTarget->commands.pReq); - if( pIsodepTarget->commands.did != did ) - { - //Not for us - return NFC_ERR_PROTOCOL; - } - pIsodepTarget->commands.didUsed = true; - } - else - { - pIsodepTarget->commands.didUsed = false; - } - - if( pfb & PFB_NAD ) - { - ac_buffer_read_nu8(pIsodepTarget->commands.pReq); //Skip NAD - } - */ - - uint8_t wtxm = 0; - switch (PCB_TYPE(pcb)) { - case I_BLOCK_PCB: - dep_req_information(pIsodepTarget, pIsodepTarget->commands.pReq, PCB_CHAINING(pcb), PCB_BLOCK_TOGGLE(pcb)); - break; - case R_BLOCK_PCB: - dep_req_response(pIsodepTarget, !PCB_NACK(pcb), PCB_BLOCK_TOGGLE(pcb)); - break; - case S_BLOCK_PCB: - if (PCB_WTX(pcb)) { - if (ac_buffer_reader_readable(pIsodepTarget->commands.pReq) < 1) { - NFC_ERR("Payload too short"); - return NFC_ERR_PROTOCOL; - } - wtxm = ac_buffer_read_nu8(pIsodepTarget->commands.pReq); - } - dep_req_supervisory(pIsodepTarget, PCB_WTX(pcb), wtxm); - break; - default: - NFC_ERR("PCB is invalid"); - return NFC_ERR_PROTOCOL; - } - - pIsodepTarget->commands.state = ISO_DEP_TARGET_COMMANDS_DEP_REQ_RECVD; - - return NFC_OK; -} - -nfc_err_t command_ats_res(nfc_tech_isodep_target_t *pIsodepTarget) -{ - //Send ATS back - if (ac_buffer_builder_writable(&pIsodepTarget->commands.respBldr) < 5) { - return NFC_ERR_BUFFER_TOO_SMALL; - } - - ac_buffer_builder_write_nu8(&pIsodepTarget->commands.respBldr, (5 + ac_buffer_size(pIsodepTarget->pHist)) & 0xFF); - - //T0 - ac_buffer_builder_write_nu8(&pIsodepTarget->commands.respBldr, (0x7 << 4) | FSC_TO_FSCI(FSC)); //TA(1), TB(1) and TC(1) are transmitted - - //TA(1) - //For now only 106kbps supported - ac_buffer_builder_write_nu8(&pIsodepTarget->commands.respBldr, (1 << 7) | (0x0 << 4) | 0x0); - - //TODO when supporting other bitrates - //ac_buffer_builder_write_nu8(&pIsodepTarget->commands.respBldr, (0 << 7) | (0x3 << 4) | 0x3); //106, 212, 414 kbps bitrates - - //TB(1) - ac_buffer_builder_write_nu8(&pIsodepTarget->commands.respBldr, (FWI << 4) | SFGI); //Specify guard-time and time between frames - - //TC(1) - ac_buffer_builder_write_nu8(&pIsodepTarget->commands.respBldr, (0 << 1) | 0); //DID not supported, NAD not supported - - ac_buffer_set_next(ac_buffer_builder_buffer(&pIsodepTarget->commands.respBldr), pIsodepTarget->pHist); //Queue general bytes - - pIsodepTarget->commands.state = ISO_DEP_TARGET_COMMANDS_ATS_RES_SENT; - - //TODO PPS - - return NFC_OK; -} - -nfc_err_t command_dep_res(nfc_tech_isodep_target_t *pIsodepTarget) -{ - uint8_t pcb = 0; - - // If/when supporting DIDs - /* - if( pIsodepTarget->commands.didUsed ) - { - pcb |= PFB_DID; - }*/ - - ac_buffer_t *pDepBuf = NULL; - bool moreInformation = false; - bool ack = false; - bool wtxNDeselect = false; - uint8_t wtxm = 0; - uint8_t blockNumber = 0; - - size_t maxLength = pIsodepTarget->commands.inPayloadSize - 1; - - switch (dep_res_type(pIsodepTarget)) { - case dep_type_information: - dep_res_information(pIsodepTarget, maxLength, &pDepBuf, &moreInformation, &blockNumber); - pcb = BUILD_I_BLOCK_PCB(moreInformation, false, false, blockNumber); - break; - case dep_type_response: - dep_res_response(pIsodepTarget, &ack, &blockNumber); - pcb = BUILD_R_BLOCK_PCB(0, blockNumber, !ack); - break; - case dep_type_supervisory: - dep_res_supervisory(pIsodepTarget, &wtxNDeselect, &wtxm); - pcb = BUILD_S_BLOCK_PCB(0, wtxNDeselect); - break; - } - - ac_buffer_builder_write_nu8(&pIsodepTarget->commands.respBldr, pcb); - /* - if( pIsodepTarget->commands.didUsed ) - { - ac_buffer_builder_write_nu8(&pIsodepTarget->commands.respBldr, pIsodepTarget->commands.did); - } - */ - if (pDepBuf != NULL) { - ac_buffer_set_next(ac_buffer_builder_buffer(&pIsodepTarget->commands.respBldr), pDepBuf); - } else if (wtxNDeselect) { - ac_buffer_builder_write_nu8(&pIsodepTarget->commands.respBldr, wtxm); - } - - pIsodepTarget->commands.state = ISO_DEP_TARGET_COMMANDS_DEP_RES_SENT; - - return NFC_OK; -} - -void command_reply(nfc_tech_isodep_target_t *pIsodepTarget, bool depWait) -{ - nfc_err_t ret; - - //Check whether we want to reply or wait for the higher layer to send us something - if ((pIsodepTarget->commands.state == ISO_DEP_TARGET_COMMANDS_DEP_REQ_RECVD) && depWait && !dep_ready(pIsodepTarget)) { - return; - } - - //Reply - ac_buffer_builder_reset(&pIsodepTarget->commands.respBldr); - - switch (pIsodepTarget->commands.state) { - case ISO_DEP_TARGET_COMMANDS_ATS_REQ_RECVD: - ret = command_ats_res(pIsodepTarget); - break; - case ISO_DEP_TARGET_COMMANDS_DEP_REQ_RECVD: - ret = command_dep_res(pIsodepTarget); - break; - default: - NFC_ERR("Unknown state %d", pIsodepTarget->commands.state); - //Go back to receive mode - nfc_transceiver_transceive(pIsodepTarget->pTransceiver, command_transceiver_cb, pIsodepTarget); - return; - } - - if (ret) { - NFC_ERR("Error %d", ret); - //Go back to receive mode - nfc_transceiver_transceive(pIsodepTarget->pTransceiver, command_transceiver_cb, pIsodepTarget); - return; - } - - NFC_DBG("Transceive"); - - if (pIsodepTarget->dep.frameState == ISO_DEP_TARGET_DEP_FRAME_DESELECT_SENT) { - transceiver_set_transceive_options(pIsodepTarget->pTransceiver, true, false, true); - } else { - transceiver_set_transceive_options(pIsodepTarget->pTransceiver, true, true, false); - } - - NFC_DBG_BLOCK(ac_buffer_dump(ac_buffer_builder_buffer(&pIsodepTarget->commands.respBldr));) - - //Send next frame - transceiver_set_write(pIsodepTarget->pTransceiver, ac_buffer_builder_buffer(&pIsodepTarget->commands.respBldr)); - nfc_transceiver_transceive(pIsodepTarget->pTransceiver, command_transceiver_cb, pIsodepTarget); - - NFC_DBG("Processed"); -} - -void command_transceiver_cb(nfc_transceiver_t *pTransceiver, nfc_err_t ret, void *pUserData) -{ - nfc_tech_isodep_target_t *pIsodepTarget = (nfc_tech_isodep_target_t *) pUserData; - - if (ret == NFC_ERR_ABORTED) { - // Just return - return; - } - - if (pIsodepTarget->dep.frameState == ISO_DEP_TARGET_DEP_FRAME_DESELECT_SENT) { - NFC_DBG("Deselect sent and re-polled: %u", ret); - //We are now disconnected (deselected) - //Reset status - dep_init(pIsodepTarget); - command_init(pIsodepTarget); - - transceiver_set_crc(pIsodepTarget->pTransceiver, true, true); - pIsodepTarget->commands.state = ISO_DEP_TARGET_COMMANDS_CONNECTING; - - //Call so that we can reinit higher layer - dep_disconnected(pIsodepTarget, true); //This will call us again - return; - } - - //Prepare default empty reply - transceiver_set_write(pTransceiver, NULL); - transceiver_set_transceive_options(pTransceiver, false, true, false); - - if (ret == NFC_ERR_FIELD) { - NFC_WARN("Lost initiator"); - dep_disconnected(pIsodepTarget, false); - return; - } else if (ret) { - //We should ignore this error and wait for another frame - NFC_WARN("Got invalid frame (error %d)", ret); - - nfc_transceiver_transceive(pTransceiver, command_transceiver_cb, pIsodepTarget); - return; - } - - NFC_DBG("Reading data from initiator"); - ac_buffer_t *pDataInitiator = transceiver_get_read(pTransceiver); //In buffer - - NFC_DBG_BLOCK(ac_buffer_dump(pDataInitiator);) - - //Framing is handled by transceiver - if ((ac_buffer_reader_readable(pDataInitiator) < 1)) { - NFC_ERR("Empty initiator message"); - - //Go back to receive mode - nfc_transceiver_transceive(pTransceiver, command_transceiver_cb, pIsodepTarget); - return; - } - - pIsodepTarget->commands.pReq = pDataInitiator; - - //Duplicate to peek on req - ac_buffer_t dataInitiatorDup; - ac_buffer_dup(&dataInitiatorDup, pDataInitiator); - uint8_t req = ac_buffer_read_nu8(&dataInitiatorDup); - - switch (req) { - case RATS: - ret = command_ats_req(pIsodepTarget); - break; - default: - ret = command_dep_req(pIsodepTarget); - break; - } - - if (ret) { - NFC_ERR("Error %d", ret); - - //Go back to receive mode - nfc_transceiver_transceive(pTransceiver, command_transceiver_cb, pIsodepTarget); - return; - } - - NFC_DBG("Reply"); - - //Reply - command_reply(pIsodepTarget, true); //Make sure we send a WTX frame if we cannot respond straight away -} - - - diff --git a/features/nfc/stack/tech/isodep/isodep_target.h b/features/nfc/stack/tech/isodep/isodep_target.h deleted file mode 100644 index a4e6d5c..0000000 --- a/features/nfc/stack/tech/isodep/isodep_target.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (c) 2015-2018, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * 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. - */ -/** - * \file isodep_target.h - * \copyright Copyright (c) ARM Ltd 2015 - * \author Donatien Garnier - */ - -#ifndef ISODEP_TARGET_H_ -#define ISODEP_TARGET_H_ - -#include "stack/nfc_common.h" -#include "transceiver/transceiver.h" -#include "isodep.h" - -#ifdef __cplusplus -extern "C" { -#endif - -struct nfc_tech_isodep_target; -typedef struct nfc_tech_isodep_target nfc_tech_isodep_target_t; -struct nfc_tech_isodep_target { - nfc_transceiver_t *pTransceiver; - - struct { - ac_ostream_t *pReqStream; - ac_istream_t *pResStream; - - nfc_tech_isodep_cb_t reqCb; - void *pReqUserData; - - nfc_tech_isodep_cb_t resCb; - void *pResUserData; - - ac_buffer_t res; - bool chaining; - - uint8_t blockNumber; - - enum { - ISO_DEP_TARGET_DEP_FRAME_IDLE, - ISO_DEP_TARGET_DEP_FRAME_WTX_RECEIVED, - ISO_DEP_TARGET_DEP_FRAME_WTX_SENT, - ISO_DEP_TARGET_DEP_FRAME_INFORMATION_RECEIVED, - ISO_DEP_TARGET_DEP_FRAME_INFORMATION_SENT, - ISO_DEP_TARGET_DEP_FRAME_NACK_RECEIVED, - ISO_DEP_TARGET_DEP_FRAME_NACK_DIFF_BLOCK_NUMBER_RECEIVED, - ISO_DEP_TARGET_DEP_FRAME_NACK_SENT, - ISO_DEP_TARGET_DEP_FRAME_ACK_RECEIVED, - ISO_DEP_TARGET_DEP_FRAME_ACK_SENT, - ISO_DEP_TARGET_DEP_FRAME_DESELECT_RECEIVED, - ISO_DEP_TARGET_DEP_FRAME_DESELECT_SENT, - } frameState; - } dep; - struct { - enum { - ISO_DEP_TARGET_COMMANDS_DISCONNECTED, - - ISO_DEP_TARGET_COMMANDS_CONNECTING, - - ISO_DEP_TARGET_COMMANDS_ATS_REQ_RECVD, - ISO_DEP_TARGET_COMMANDS_ATS_RES_SENT, - - ISO_DEP_TARGET_COMMANDS_DEP_REQ_RECVD, - ISO_DEP_TARGET_COMMANDS_DEP_RES_SENT, - } state; - - size_t inPayloadSize; - - ac_buffer_builder_t respBldr; - uint8_t respBuf[32]; - - ac_buffer_t *pReq; - } commands; - - ac_buffer_t *pHist; - - nfc_tech_isodep_disconnected_cb disconnectedCb; - void *pUserData; -}; - -//High-level Target functions -void nfc_tech_isodep_target_init(nfc_tech_isodep_target_t *pIsodepTarget, nfc_transceiver_t *pTransceiver, - ac_buffer_t *pHist, nfc_tech_isodep_disconnected_cb disconnectedCb, void *pUserData); - -nfc_err_t nfc_tech_isodep_target_connect(nfc_tech_isodep_target_t *pIsodepTarget); -void nfc_tech_isodep_target_disconnect(nfc_tech_isodep_target_t *pIsodepTarget); - -nfc_err_t nfc_tech_isodep_target_transmit(nfc_tech_isodep_target_t *pIsodepTarget, ac_istream_t *pStream, nfc_tech_isodep_cb_t cb, void *pUserData); -nfc_err_t nfc_tech_isodep_target_receive(nfc_tech_isodep_target_t *pIsodepTarget, ac_ostream_t *pStream, nfc_tech_isodep_cb_t cb, void *pUserData); - - -#ifdef __cplusplus -} -#endif - -#endif /* ISODEP_TARGET_H_ */ diff --git a/features/nfc/stack/tech/type4/type4_target.c b/features/nfc/stack/tech/type4/type4_target.c deleted file mode 100644 index 63fd23e..0000000 --- a/features/nfc/stack/tech/type4/type4_target.c +++ /dev/null @@ -1,286 +0,0 @@ -/* - * Copyright (c) 2015-2018, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * 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. - */ -/** - * \file type4_target.c - * \copyright Copyright (c) ARM Ltd 2015 - * \author Donatien Garnier - */ - -#define __DEBUG__ 0 -#ifndef __MODULE__ -#define __MODULE__ "type4_target.c" -#endif - -#include "stack/nfc_errors.h" - -#include "type4_target.h" -#include "tech/iso7816/iso7816_defs.h" - -#define TYPE4_NDEF_VERSION 2 - -#if TYPE4_NDEF_VERSION == 2 -static const uint8_t aid[] = { 0xD2, 0x76, 0x00, 0x00, 0x85, 0x01, 0x01 }; -#else -static const uint8_t aid[] = { 0xD2, 0x76, 0x00, 0x00, 0x85, 0x01, 0x00 }; -#endif -#define CC_FILE 0xE103 //Must not be changed -#define NDEF_FILE 0xA443 -#define DEFAULT_FILE 0x0000 - -static void app_selected(nfc_tech_iso7816_app_t *pIso7816App, void *pUserData); -static void app_deselected(nfc_tech_iso7816_app_t *pIso7816App, void *pUserData); -static void app_apdu(nfc_tech_iso7816_app_t *pIso7816App, void *pUserData); - -static nfc_err_t data_read(nfc_tech_type4_target_t *pType4Target, ac_buffer_t *pBuf, uint16_t file, size_t off, size_t len); -static nfc_err_t data_write(nfc_tech_type4_target_t *pType4Target, ac_buffer_t *pBuf, uint16_t file, size_t off); - -void nfc_tech_type4_target_init(nfc_tech_type4_target_t *pType4Target, nfc_tech_iso7816_t *pIso7816, ndef_msg_t *pNdef) -{ - ac_buffer_builder_init(&pType4Target->ccFileBldr, pType4Target->ccFileBuf, /*sizeof(pType4Target->ccFileBuf)*/15); - - ac_buffer_builder_init(&pType4Target->ndefFileBldr, pType4Target->ndefFileBuf, /*sizeof(pType4Target->ndefFileBuf)*/2); - - pType4Target->selFile = DEFAULT_FILE; - pType4Target->pNdef = pNdef; - pType4Target->written = false; - - nfc_tech_iso7816_app_init(&pType4Target->app, pIso7816, aid, sizeof(aid), app_selected, app_deselected, app_apdu, pType4Target); - - nfc_tech_iso7816_add_app(pIso7816, &pType4Target->app); -} - -void app_selected(nfc_tech_iso7816_app_t *pIso7816App, void *pUserData) -{ - nfc_tech_type4_target_t *pType4Target = (nfc_tech_type4_target_t *) pUserData; - NFC_DBG("Selected"); - - (void) pIso7816App; - - ac_buffer_builder_reset(ndef_msg_buffer_builder(pType4Target->pNdef)); - - //Populate CC file - ac_buffer_builder_reset(&pType4Target->ccFileBldr); - ac_buffer_builder_write_nu16(&pType4Target->ccFileBldr, 15); //CC file is 15 bytes long -#if TYPE4_NDEF_VERSION == 2 - ac_buffer_builder_write_nu8(&pType4Target->ccFileBldr, 0x20); //NFC Forum Tag Type 4 V2.0 compliant -#else - ac_buffer_builder_write_nu8(&pType4Target->ccFileBldr, 0x10); //NFC Forum Tag Type 4 V1.0 compliant -#endif - ac_buffer_builder_write_nu16(&pType4Target->ccFileBldr, 256 /* Max frame size */ - 2 /* SW */ - 3 /* ISO-DEP PFB + DID + NAD */); //Max data size that can be read from the tag - ac_buffer_builder_write_nu16(&pType4Target->ccFileBldr, 256 /* Max frame size */ - 6 /* CLA INS P1 P2 LC LE */ - 3 /* ISO-DEP PFB + DID + NAD */); //Max data size that can be written to the tag - ac_buffer_builder_write_nu8(&pType4Target->ccFileBldr, 0x04); //NDEF File Control TLV - Type - ac_buffer_builder_write_nu8(&pType4Target->ccFileBldr, 6); //NDEF File Control TLV - Length - ac_buffer_builder_write_nu16(&pType4Target->ccFileBldr, NDEF_FILE); //NDEF file id - ac_buffer_builder_write_nu16(&pType4Target->ccFileBldr, 2 /* length header */ + ac_buffer_builder_writable(ndef_msg_buffer_builder(pType4Target->pNdef))); //Max size of NDEF data - ac_buffer_builder_write_nu8(&pType4Target->ccFileBldr, 0x00); //Open read access - ac_buffer_builder_write_nu8(&pType4Target->ccFileBldr, 0x00); //Open write access - - //Encode NDEF file - ndef_msg_encode(pType4Target->pNdef); - - //Populate NDEF file - ac_buffer_builder_init(&pType4Target->ndefFileBldr, pType4Target->ndefFileBuf, /*sizeof(pType4Target->ndefFileBuf)*/2); - - ac_buffer_builder_write_nu16(&pType4Target->ndefFileBldr, ac_buffer_reader_readable(ac_buffer_builder_buffer(ndef_msg_buffer_builder(pType4Target->pNdef)))); - - //Pad NDEF file with 0s - while (ac_buffer_builder_writable(ndef_msg_buffer_builder(pType4Target->pNdef)) > 0) { - ac_buffer_builder_write_nu8(ndef_msg_buffer_builder(pType4Target->pNdef), 0); - } - - //No file selected - pType4Target->selFile = DEFAULT_FILE; - - pType4Target->written = false; -} - -void app_deselected(nfc_tech_iso7816_app_t *pIso7816App, void *pUserData) -{ - nfc_tech_type4_target_t *pType4Target = (nfc_tech_type4_target_t *) pUserData; - - (void) pIso7816App; - - //Reset buffers - ac_buffer_builder_reset(&pType4Target->ccFileBldr); - ac_buffer_builder_set_full(&pType4Target->ndefFileBldr); //To read length - ac_buffer_builder_reset(ndef_msg_buffer_builder(pType4Target->pNdef)); - - NFC_DBG("Deselected"); - - if (pType4Target->written) { - NFC_DBG("New content has been written"); - //Try to parse NDEF - //Set buffer length based on file header - size_t length = ac_buffer_read_nu16(ac_buffer_builder_buffer(&pType4Target->ndefFileBldr)); - NFC_DBG("Length is %lu", length); - if (length < ac_buffer_builder_writable(ndef_msg_buffer_builder(pType4Target->pNdef))) { - ac_buffer_builder_set_write_offset(ndef_msg_buffer_builder(pType4Target->pNdef), length); - ndef_msg_decode(pType4Target->pNdef); - } else { - NFC_ERR("Invalid length"); - } - } -} - -void app_apdu(nfc_tech_iso7816_app_t *pIso7816App, void *pUserData) -{ - nfc_tech_type4_target_t *pType4Target = (nfc_tech_type4_target_t *) pUserData; - - //Reset buffers - ac_buffer_builder_set_full(&pType4Target->ccFileBldr); - ac_buffer_builder_set_full(&pType4Target->ndefFileBldr); - ac_buffer_builder_set_full(ndef_msg_buffer_builder(pType4Target->pNdef)); //Set offset to 0, size to max - - ac_buffer_set_next(ac_buffer_builder_buffer(&pType4Target->ndefFileBldr), ac_buffer_builder_buffer(ndef_msg_buffer_builder(pType4Target->pNdef))); - - //Recover PDU - nfc_tech_iso7816_c_apdu_t *pCApdu = nfc_tech_iso7816_app_c_apdu(pIso7816App); - nfc_tech_iso7816_r_apdu_t *pRApdu = nfc_tech_iso7816_app_r_apdu(pIso7816App); - - nfc_err_t ret; - switch (pCApdu->ins) { - case ISO7816_INS_SELECT: - switch (pCApdu->p1) { - case 0x00: //Selection by ID - case 0x02: //Selection by child ID - if (ac_buffer_reader_readable(&pCApdu->dataIn) != 2) { - pRApdu->sw = ISO7816_SW_NOT_FOUND; - break; - } - - uint16_t file = ac_buffer_read_nu16(&pCApdu->dataIn); - if (file == NDEF_FILE) { - pType4Target->selFile = NDEF_FILE; - NFC_DBG("NDEF File selected"); - pRApdu->sw = ISO7816_SW_OK; - } else if (file == CC_FILE) { - pType4Target->selFile = CC_FILE; - NFC_DBG("CC File selected"); - pRApdu->sw = ISO7816_SW_OK; - } else { - //file = DEFAULT_FILE; - NFC_DBG("Could not select file %04X", file); - pRApdu->sw = ISO7816_SW_NOT_FOUND; - } - break; - default: - pRApdu->sw = ISO7816_SW_NOT_FOUND; - break; - } - break; - case 0xB0: //Read binary - NFC_DBG("Trying to read %d bytes at offset %d from file %04x", pCApdu->maxRespLength, (pCApdu->p1 << 8) | pCApdu->p2, pType4Target->selFile); - ret = data_read(pType4Target, &pRApdu->dataOut, pType4Target->selFile, (pCApdu->p1 << 8) | pCApdu->p2, pCApdu->maxRespLength); - if (ret == NFC_OK) { - NFC_DBG("Read %d bytes", ac_buffer_reader_readable(&pRApdu->dataOut)); - NFC_DBG_BLOCK(ac_buffer_dump(&pRApdu->dataOut);) - pRApdu->sw = ISO7816_SW_OK; - } else { - NFC_DBG("Failed with ret code %d", ret); - pRApdu->sw = ISO7816_SW_WRONG_LENGTH; - } - break; - case 0xD6: //Update binary - NFC_DBG("Trying to write %d bytes at offset %d to file %04x", ac_buffer_reader_readable(&pCApdu->dataIn), (pCApdu->p1 << 8) | pCApdu->p2, pType4Target->selFile); - ret = data_write(pType4Target, &pCApdu->dataIn, pType4Target->selFile, (pCApdu->p1 << 8) | pCApdu->p2); - if (ret == NFC_OK) { - NFC_DBG("OK"); - pRApdu->sw = ISO7816_SW_OK; - pType4Target->written = true; - } else { - NFC_DBG("Failed with ret code %d", ret); - pRApdu->sw = ISO7816_SW_WRONG_LENGTH; - } - break; - default: - pRApdu->sw = ISO7816_SW_INVALID_INS; - break; - } - - //Send reply - nfc_tech_iso7816_app_reply(pIso7816App); -} - -nfc_err_t data_read(nfc_tech_type4_target_t *pType4Target, ac_buffer_t *pBuf, uint16_t file, size_t off, size_t len) -{ - ac_buffer_t *pFile; - switch (file) { - case CC_FILE: - pFile = ac_buffer_builder_buffer(&pType4Target->ccFileBldr); - break; - case NDEF_FILE: - pFile = ac_buffer_builder_buffer(&pType4Target->ndefFileBldr); - break; - default: - return NFC_ERR_NOT_FOUND; - } - - if (off > ac_buffer_reader_readable(pFile)) { - return NFC_ERR_LENGTH; - } - - ac_buffer_read_n_skip(pFile, off); - - if (len > ac_buffer_reader_readable(pFile)) { - len = ac_buffer_reader_readable(pFile); - } - - ac_buffer_split(pBuf, pFile, pFile, len); - - return NFC_OK; -} - -nfc_err_t data_write(nfc_tech_type4_target_t *pType4Target, ac_buffer_t *pBuf, uint16_t file, size_t off) -{ - ac_buffer_t *pFile; - switch (file) { - case NDEF_FILE: - pFile = ac_buffer_builder_buffer(&pType4Target->ndefFileBldr); - break; - case CC_FILE: //Cannot write to CC file! - default: - return NFC_ERR_NOT_FOUND; - } - - size_t len = ac_buffer_reader_readable(pBuf); - - if (off > ac_buffer_reader_readable(pFile)) { - return NFC_ERR_LENGTH; - } - - ac_buffer_read_n_skip(pFile, off); - - if (len > ac_buffer_reader_readable(pFile)) { - len = ac_buffer_reader_readable(pFile); - } - - while (len > 0) { - size_t cpy; - ac_buffer_builder_t builder; - ac_buffer_dup(ac_buffer_builder_buffer(&builder), pFile); - ac_buffer_builder_from_buffer(&builder); - cpy = ac_buffer_builder_writable(&builder); - cpy = MIN(cpy, len); - ac_buffer_builder_copy_n_bytes(&builder, pBuf, cpy); - pFile = ac_buffer_next(pFile); - len -= cpy; - } - - return NFC_OK; -} - - diff --git a/features/nfc/stack/tech/type4/type4_target.h b/features/nfc/stack/tech/type4/type4_target.h deleted file mode 100644 index a090edd..0000000 --- a/features/nfc/stack/tech/type4/type4_target.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2015-2018, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * 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. - */ -/** - * \file type4_target.h - * \copyright Copyright (c) ARM Ltd 2015 - * \author Donatien Garnier - */ - -#ifndef TECH_TYPE4_TYPE4_TARGET_H_ -#define TECH_TYPE4_TYPE4_TARGET_H_ - -#include "stack/nfc_common.h" - -#include "tech/iso7816/iso7816.h" -#include "tech/iso7816/iso7816_app.h" -#include "ndef/ndef.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct nfc_tech_type4_target nfc_tech_type4_target_t; - -typedef void (*nfc_tech_type4_cb)(nfc_tech_type4_target_t *pType4Target, nfc_err_t ret, void *pUserData); - -struct nfc_tech_type4_target { - nfc_tech_iso7816_app_t app; - - ndef_msg_t *pNdef; - - uint8_t ccFileBuf[15]; - ac_buffer_builder_t ccFileBldr; - - uint8_t ndefFileBuf[2]; - ac_buffer_builder_t ndefFileBldr; - - uint16_t selFile; - - bool written; -}; - -void nfc_tech_type4_target_init(nfc_tech_type4_target_t *pType4Target, nfc_tech_iso7816_t *pIso7816, ndef_msg_t *pNdef); - -#ifdef __cplusplus -} -#endif - -#endif /* TECH_TYPE4_TYPE4_TARGET_H_ */ diff --git a/features/nfc/stack/transceiver/pn512/pn512.c b/features/nfc/stack/transceiver/pn512/pn512.c deleted file mode 100644 index e2eb348..0000000 --- a/features/nfc/stack/transceiver/pn512/pn512.c +++ /dev/null @@ -1,356 +0,0 @@ -/* - * Copyright (c) 2013-2018, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * 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. - */ -/** - * \file pn512.c - * \copyright Copyright (c) ARM Ltd 2013 - * \author Donatien Garnier - * \details PN512 implementation of the transceiver interface - */ - -#define __DEBUG__ 4 -#ifndef __MODULE__ -#define __MODULE__ "pn512.c" -#endif -#include "stack/nfc_errors.h" - -#include "stdlib.h" - -#include "acore/ac_buffer.h" - -#include "transceiver/transceiver.h" -#include "transceiver/protocols.h" -#include "pn512_rf.h" -#include "pn512_registers.h" -#include "pn512_cmd.h" -#include "pn512_hw.h" -#include "pn512_irq.h" -#include "pn512_poll.h" -#include "pn512_transceive.h" -#include "pn512_internal.h" - -#include "pn512.h" - -#define DEFAULT_READER_TRANSCEIVE_TIMEOUT 100 -#define DEFAULT_TARGET_TRANSCEIVE_TIMEOUT -1 - - -//Prototypes -#include "pn512_internal.h" - -/** \addtogroup PN512 - * @{ - * \name Transceiver - * \details Implementation of the transceiver interface - * @{ - */ - -//PN 512 VTABLE - -static const transceiver_impl_t pn512_impl = { - .set_protocols = pn512_set_protocols, - .poll = pn512_poll, - .transceive = pn512_transceive, - .abort = pn512_abort, - .set_crc = pn512_set_crc, - .set_timeout = pn512_set_timeout, - .set_transceive_options = pn512_set_transceive_options, - .set_transceive_framing = pn512_set_transceive_framing, - .set_write = pn512_set_write, - .get_read = pn512_get_read, - .set_last_byte_length = pn512_set_last_byte_length, - .get_last_byte_length = pn512_get_last_byte_length, - .set_first_byte_align = pn512_set_first_byte_align, - .close = pn512_close, - .sleep = pn512_sleep -}; - -/** Initialize PN512 transceiver - * \param pPN512 pointer to pn512_t structure to initialize - * \param pTransport pointer to already initialized nfc_transport_t structure - * \return NFC_OK (0) on success or NFC_ERR_* error on failure - */ -nfc_err_t pn512_init(pn512_t *pPN512, nfc_transport_t *pTransport, nfc_scheduler_timer_t *pTimer) -{ - //// - //For Self-test - //// -#if NFC_PN512_SELFTEST - const uint8_t null_array[25] = {0}; -#endif - //// - uint8_t r; - - //Init transceiver - transceiver_init((nfc_transceiver_t *)pPN512, pTransport, pTimer); - - //Init buffer - ac_buffer_builder_init(&pPN512->readBufBldr, pPN512->payload, 256); - - pPN512->readFirstByteAlign = 0; - pPN512->readLastByteLength = 8; - pPN512->writeLastByteLength = 8; - - //Populate functions - pPN512->transceiver.fn = &pn512_impl; - - //Init variables - memset(&pPN512->config.initiators, 0, sizeof(nfc_tech_t)); - memset(&pPN512->config.targets, 0, sizeof(nfc_tech_t)); - pPN512->timeout = -1; - pPN512->nextFrameMode = pn512_transceive_mode_transceive; - - pn512_hw_init(pPN512); - pn512_registers_init(pPN512); //Cannot switch page now - pn512_cmd_init(pPN512); - - pn512_cmd_exec(pPN512, PN512_CMD_SOFTRST); - pn512_cmd_wait_idle(pPN512, -1); - - //pn512_registers_init(pPN512); - //Put into known state - pn512_registers_reset(pPN512); - - pPN512->transceive.mode = pn512_transceive_mode_idle; - - pn512_irq_clear(pPN512, PN512_IRQ_ALL); - pn512_fifo_clear(pPN512); - pn512_cmd_exec(pPN512, PN512_CMD_IDLE); - pn512_cmd_wait_idle(pPN512, -1); - - pn512_rf_field_switch_off(pPN512); - - //Required for polling loop - srand(4242); - -#if NFC_PN512_SELFTEST // Self test - pn512_cmd_exec(pPN512, PN512_CMD_SOFTRST); - pn512_cmd_wait_idle(pPN512, -1); - - const uint8_t null_array_buf[25] = {0}; //FIXME - ac_buffer_t null_array; - ac_buffer_init(&null_array, null_array_buf, 25); - - //Perform self test - pn512_fifo_write(pPN512, &null_array); - pn512_cmd_exec(pPN512, PN512_CMD_CONFIG); - while (pn512_cmd_get(pPN512) != PN512_CMD_IDLE); - pn512_register_write(pPN512, PN512_REG_AUTOTEST, 0x09); - - ac_buffer_init(&null_array, null_array_buf, 1); - - pn512_fifo_write(pPN512, &null_array); - pn512_cmd_exec(pPN512, PN512_CMD_CRC); - while (pn512_cmd_get(pPN512) != PN512_CMD_IDLE); - - DBGX_ENTER(); - NFC_DBG("Test result:"); - while (pn512_fifo_length(pPN512)) { - ac_buffer_builder_t read_byte; - ac_buffer_builder_init(&read_byte, null_array_buf, 1); - - pn512_fifo_read(pPN512, &read_byte); - DBGX("%02x ", null_array_buf[0]); - } - DBGX("\n"); - DBGX_LEAVE(); -#endif - - r = pn512_register_read(pPN512, PN512_REG_VERSION); - - NFC_DBG_BLOCK( - NFC_DBG("PN512 version %02x", r); - ) - - if ((r != 0x82) && (r != 0xB1) && (r != 0xB2)) { - return NFC_ERR_UNSUPPORTED; //PN512 not found - } - - return NFC_OK; -} - -/** Get pointer to nfc_transceiver_t structure - * \param pPN512 pointer to pn512_t instance - * \return pointer to initialized nfc_transceiver_t instance - */ -nfc_transceiver_t *pn512_get_transceiver(pn512_t *pPN512) -{ - return &pPN512->transceiver; -} - -void pn512_set_protocols(nfc_transceiver_t *pTransceiver, nfc_tech_t initiators, nfc_tech_t targets, polling_options_t options) -{ - pn512_t *pPN512 = (pn512_t *) pTransceiver; - //If different, reconfigure - if (memcmp(&initiators, &pPN512->config.initiators, sizeof(nfc_tech_t)) || memcmp(&targets, &pPN512->config.targets, sizeof(nfc_tech_t))) { - pPN512->config.initiators = initiators; - if (memcmp(&targets, &pPN512->config.targets, sizeof(nfc_tech_t))) { - pPN512->config.targets = targets; - pn512_poll_setup(pPN512); - } - pTransceiver->initiator_ntarget = false; - memset(&pTransceiver->active_tech, 0, sizeof(nfc_tech_t)); - } - pPN512->config.options = options; -} - -void pn512_poll(nfc_transceiver_t *pTransceiver) -{ - pn512_t *pPN512 = (pn512_t *) pTransceiver; - pPN512->nextFrameMode = pn512_transceive_mode_transceive; - pn512_poll_hw(pPN512, pn512_transceiver_callback); -} - -void pn512_set_crc(nfc_transceiver_t *pTransceiver, bool crc_out, bool crc_in) -{ - pn512_t *pPN512 = (pn512_t *) pTransceiver; - pn512_framing_crc_set(pPN512, crc_out, crc_in); -} - -void pn512_set_timeout(nfc_transceiver_t *pTransceiver, int timeout) -{ - pn512_t *pPN512 = (pn512_t *) pTransceiver; - pPN512->timeout = timeout; -} - -void pn512_set_transceive_options(nfc_transceiver_t *pTransceiver, bool transmit, bool receive, bool repoll) -{ - pn512_t *pPN512 = (pn512_t *) pTransceiver; - if (transmit && receive) { - pPN512->nextFrameMode = pn512_transceive_mode_transceive; - } else if (transmit && repoll) { - pPN512->nextFrameMode = pn512_transceive_mode_transmit_and_target_autocoll; - } else if (transmit) { - pPN512->nextFrameMode = pn512_transceive_mode_transmit; - } else if (receive) { - pPN512->nextFrameMode = pn512_transceive_mode_receive; - } else { - pPN512->nextFrameMode = pn512_transceive_mode_target_autocoll; - } -} - -void pn512_set_transceive_framing(nfc_transceiver_t *pTransceiver, nfc_framing_t framing) -{ - pn512_t *pPN512 = (pn512_t *) pTransceiver; - pn512_framing_set(pPN512, framing); - - //Switch NFC tech if NFC DEP - if (pTransceiver->active_tech.nfc_nfc_dep_a - || pTransceiver->active_tech.nfc_nfc_dep_f_212 - || pTransceiver->active_tech.nfc_nfc_dep_f_424) { - //FIXME - pTransceiver->active_tech.nfc_nfc_dep_a = 0; - pTransceiver->active_tech.nfc_nfc_dep_f_212 = 0; - pTransceiver->active_tech.nfc_nfc_dep_f_424 = 0; - switch (framing) { - case nfc_framing_target_a_106: - case nfc_framing_initiator_a_106: - pTransceiver->active_tech.nfc_nfc_dep_a = 1; - break; - case nfc_framing_target_f_212: - case nfc_framing_initiator_f_212: - pTransceiver->active_tech.nfc_nfc_dep_f_212 = 1; - break; - case nfc_framing_target_f_424: - case nfc_framing_initiator_f_424: - pTransceiver->active_tech.nfc_nfc_dep_f_424 = 1; - break; - default: - break; - } - } -} - -void pn512_set_write(nfc_transceiver_t *pTransceiver, ac_buffer_t *pWriteBuf) -{ - pn512_t *pPN512 = (pn512_t *) pTransceiver; - if (pWriteBuf == NULL) { - ac_buffer_init(&pPN512->writeBuf, NULL, 0); - return; - } - ac_buffer_dup(&pPN512->writeBuf, pWriteBuf); -} - -ac_buffer_t *pn512_get_read(nfc_transceiver_t *pTransceiver) -{ - pn512_t *pPN512 = (pn512_t *) pTransceiver; - return ac_buffer_builder_buffer(&pPN512->readBufBldr); -} - -void pn512_set_last_byte_length(nfc_transceiver_t *pTransceiver, size_t lastByteLength) -{ - pn512_t *pPN512 = (pn512_t *) pTransceiver; - if ((lastByteLength > 8) || (lastByteLength == 0)) { - lastByteLength = 8; - } - pPN512->writeLastByteLength = lastByteLength; -} - -void pn512_set_first_byte_align(nfc_transceiver_t *pTransceiver, size_t firstByteAlign) -{ - pn512_t *pPN512 = (pn512_t *) pTransceiver; - firstByteAlign &= 0x7; - pPN512->readFirstByteAlign = firstByteAlign; -} - -size_t pn512_get_last_byte_length(nfc_transceiver_t *pTransceiver) -{ - pn512_t *pPN512 = (pn512_t *) pTransceiver; - return pPN512->readLastByteLength; -} - -void pn512_transceive(nfc_transceiver_t *pTransceiver) -{ - pn512_t *pPN512 = (pn512_t *) pTransceiver; - pn512_transceive_hw(pPN512, pPN512->nextFrameMode, pn512_transceiver_callback); - pPN512->nextFrameMode = pn512_transceive_mode_transceive; -} - -void pn512_abort(nfc_transceiver_t *pTransceiver) -{ - pn512_t *pPN512 = (pn512_t *) pTransceiver; - nfc_scheduler_dequeue_task(&pTransceiver->scheduler, true, &pPN512->transceiver.task); -} - -void pn512_close(nfc_transceiver_t *pTransceiver) -{ - //pn512_t* pPN512 = (pn512_t*) pTransceiver; - (void) pTransceiver; - //TODO - return; -} - -void pn512_sleep(nfc_transceiver_t *pTransceiver, bool sleep) -{ - pn512_t *pPN512 = (pn512_t *) pTransceiver; - - if (sleep) { - pn512_register_write(pPN512, PN512_REG_COMMAND, 0x30); //Receiver off + soft power down - } else { - pn512_register_write(pPN512, PN512_REG_COMMAND, 0x00); - while (pn512_register_read(pPN512, PN512_REG_COMMAND) & 0x10); - } -} - -void pn512_transceiver_callback(pn512_t *pPN512, nfc_err_t ret) -{ - transceiver_callback(&pPN512->transceiver, ret); -} - -/** - * @} - * @} - * */ diff --git a/features/nfc/stack/transceiver/pn512/pn512.h b/features/nfc/stack/transceiver/pn512/pn512.h deleted file mode 100644 index 9af06b2..0000000 --- a/features/nfc/stack/transceiver/pn512/pn512.h +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright (c) 2013-2018, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * 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. - */ -/** - * \file pn512.h - * \copyright Copyright (c) ARM Ltd 2013 - * \author Donatien Garnier - */ - -#ifndef PN512_H_ -#define PN512_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "stack/nfc_common.h" -#include "transceiver/transceiver.h" - -#include "pn512_types.h" -#include "pn512_callback.h" - -typedef enum __pn512_state { - pn512_state_ready, - pn512_state_target_autocoll, - pn512_state_initiator_transceive_first_frame, - pn512_state_transceive, - pn512_state_transceive_last_frame, -} pn512_state_t; - -typedef enum __pn512_transceive_mode { - pn512_transceive_mode_idle, - pn512_transceive_mode_target_autocoll, - pn512_transceive_mode_transmit, - pn512_transceive_mode_transmit_and_target_autocoll, - pn512_transceive_mode_transceive, - pn512_transceive_mode_receive, -} pn512_transceive_mode_t; - -struct __pn512 { - nfc_transceiver_t transceiver; - //Impl specific - pn512_registers_t registers; - bool rf_on; - struct { - bool out; - bool in; - } crc; - int timeout; - - struct { - nfc_tech_t initiators; - nfc_tech_t targets; - polling_options_t options; - } config; - - //Transceive options - pn512_transceive_mode_t nextFrameMode; - - nfc_framing_t framing; - uint16_t irqsEn; - uint8_t payload[256]; //Incoming buffer - - ac_buffer_builder_t readBufBldr; - ac_buffer_t writeBuf; - - uint8_t readFirstByteAlign; - uint8_t readLastByteLength; - uint8_t writeLastByteLength; - - //Task parameters - struct { - //Polling - struct { - enum { - pn512_polling_state_start_listening, - - pn512_polling_state_listen_wait_for_remote_field, - pn512_polling_state_listen_anticollision, - - pn512_polling_state_listen_no_target_found, - - pn512_polling_state_start_polling, - - pn512_polling_state_rf_collision_avoidance, // TID + n × TRFW, n is random, TID>4096/(13.56E6) ~ 302.06us, TRFW=51/(13.56E6) ~ 37.76us - pn512_polling_state_polling_nfc_a_start, - pn512_polling_state_polling_nfc_a_gt, // guard time nfc a >= 5.0 ms - pn512_polling_state_polling_nfc_a_anticollision, // polling for nfc a - pn512_polling_state_polling_nfc_b_start, - pn512_polling_state_polling_nfc_b_gt, // guard time nfc b >= 5.0 ms - pn512_polling_state_polling_nfc_b_anticollision, // polling for nfc b - pn512_polling_state_polling_nfc_f_start, - pn512_polling_state_polling_nfc_f_gt, // guard time nfc f >= 20 ms - pn512_polling_state_polling_nfc_f_anticollision, // polling for nfc f - - pn512_polling_state_finish_polling, - - } state; - - pn512_cb_t cb; - } poll; - struct { - pn512_cb_t cb; - pn512_transceive_mode_t mode; - } transceive; - struct { - pn512_cb_t cb; - } rf; - struct { - union { - // ISO A - struct { - bool more_targets; // Collision detected - uint8_t cascade_level; - uint8_t cln[5]; - uint8_t valid_bits; // valid bits within cascade level - } iso_a; - // ISO B - struct { - bool more_targets; // Collision detected - uint8_t slots_num_exponent; - uint8_t slot_number; - bool found_one; - } iso_b; - }; - pn512_cb_t cb; - } anticollision; - }; - -}; - -nfc_err_t pn512_init(pn512_t *pPN512, nfc_transport_t *pTransport, nfc_scheduler_timer_t *pTimer); - -nfc_transceiver_t *pn512_get_transceiver(pn512_t *pPN512); - -#ifdef __cplusplus -} -#endif - -#endif /* PN512_H_ */ diff --git a/features/nfc/stack/transceiver/pn512/pn512_callback.h b/features/nfc/stack/transceiver/pn512/pn512_callback.h deleted file mode 100644 index 2ab8c3d..0000000 --- a/features/nfc/stack/transceiver/pn512/pn512_callback.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2015-2018, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * 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. - */ -/** - * \file pn512_callback.h - * \copyright Copyright (c) ARM Ltd 2015 - * \author Donatien Garnier - */ - -#ifndef PN512_CALLBACK_H_ -#define PN512_CALLBACK_H_ - -#include "stack/nfc_common.h" -#include "pn512_types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef void (*pn512_cb_t)(pn512_t *pPN512, nfc_err_t ret); - -#ifdef __cplusplus -} -#endif - -#endif /* PN512_CALLBACK_H_ */ diff --git a/features/nfc/stack/transceiver/pn512/pn512_cmd.c b/features/nfc/stack/transceiver/pn512/pn512_cmd.c deleted file mode 100644 index 34bfac1..0000000 --- a/features/nfc/stack/transceiver/pn512/pn512_cmd.c +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (c) 2013-2018, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * 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. - */ -/** - * \file pn512_cmd.c - * \copyright Copyright (c) ARM Ltd 2013 - * \author Donatien Garnier - * \details Format and execute PN512 commands - * \internal - */ - -#define __DEBUG__ 0 -#ifndef __MODULE__ -#define __MODULE__ "pn512_cmd.c" -#endif -#include "stack/nfc_errors.h" - -#include "pn512_cmd.h" - -#define PN512_FIFO_SIZE 64 - -#include "pn512.h" -#include "pn512_registers.h" -#include "pn512_irq.h" -#include "pn512_hw.h" - -/** \addtogroup PN512 - * \internal - * @{ - * \name Commands - * @{ - */ - -/** \internal Initialize underlying pn512_cmd_t structure - * \param pPN512 pointer to pn512_t structure - */ -void pn512_cmd_init(pn512_t *pPN512) -{ - (void) pPN512; -} - -//Fifo read / write -/** \internal Write bytes to FIFO - * \param pPN512 pointer to pn512_t structure - * \param pData buffer to write - */ -void pn512_fifo_write(pn512_t *pPN512, ac_buffer_t *pData) -{ - uint8_t fifo_space = pn512_fifo_space(pPN512); //Do not call this fn twice - size_t len = ac_buffer_reader_readable(pData); - len = MIN(fifo_space, len); - - pn512_register_switch_page(pPN512, PN512_REG_FIFODATA); - pn512_hw_write_buffer(pPN512, PN512_REG_FIFODATA, pData, len); -} - -/** \internal Read bytes from FIFO - * \param pPN512 pointer to pn512_t structure - * \param pData buffer in which to read - */ -void pn512_fifo_read(pn512_t *pPN512, ac_buffer_builder_t *pData) -{ - uint8_t fifo_len = pn512_fifo_length(pPN512); //Do not call this fn twice - size_t len = ac_buffer_builder_writable(pData); - len = MIN(fifo_len, len); - - pn512_register_switch_page(pPN512, PN512_REG_FIFODATA); - pn512_hw_read_buffer(pPN512, PN512_REG_FIFODATA, pData, len); -} - -/** \internal Clear FIFO - * Removes any bytes left in FIFO - * \param pPN512 pointer to pn512_t structure - */ -void pn512_fifo_clear(pn512_t *pPN512) -{ - pn512_register_write(pPN512, PN512_REG_FIFOLEVEL, 0x80); //Flush FIFO -} - -/** \internal Get space in FIFO - * \param pPN512 pointer to pn512_t structure - * \return number of bytes that can be written to FIFO - */ -size_t pn512_fifo_space(pn512_t *pPN512) -{ - return PN512_FIFO_SIZE - pn512_register_read(pPN512, PN512_REG_FIFOLEVEL); -} - -/** \internal Get FIFO length - * \param pPN512 pointer to pn512_t structure - * \return number of bytes that can be read from FIFO - */ -size_t pn512_fifo_length(pn512_t *pPN512) -{ - return pn512_register_read(pPN512, PN512_REG_FIFOLEVEL); -} - -/** \internal Execute command - * \param pPN512 pointer to pn512_t structure - * \param cmd PN512 command to execute - */ -void pn512_cmd_exec(pn512_t *pPN512, uint8_t cmd) -{ - pn512_register_write(pPN512, PN512_REG_COMMAND, cmd); -} - -/** \internal Wait for command completion - * \param pPN512 pointer to pn512_t structure - * \param timeout timeout in milliseconds or -1 for blocking mode - * \return NFC_OK on success or NFC_ERR_TIMEOUT on timeout - */ -nfc_err_t pn512_cmd_wait_idle(pn512_t *pPN512, int timeout) -{ - (void) timeout; - while (pn512_cmd_get(pPN512) != PN512_CMD_IDLE) { - - } - return NFC_OK; -} - - -/** \internal Read executed command - * \param pPN512 pointer to pn512_t structure - * \return PN512 command being executed - */ -uint8_t pn512_cmd_get(pn512_t *pPN512) -{ - return pn512_register_read(pPN512, PN512_REG_COMMAND) & PN512_CMD_REG_MASK; -} - -/** - * @} - * @} - * */ - diff --git a/features/nfc/stack/transceiver/pn512/pn512_cmd.h b/features/nfc/stack/transceiver/pn512/pn512_cmd.h deleted file mode 100644 index ec1d553..0000000 --- a/features/nfc/stack/transceiver/pn512/pn512_cmd.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2013-2018, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * 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. - */ -/** - * \file pn512_cmd.h - * \copyright Copyright (c) ARM Ltd 2013 - * \author Donatien Garnier - */ - -#ifndef PN512_CMD_H_ -#define PN512_CMD_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "stack/nfc_common.h" -#include "pn512.h" - -#define PN512_CMD_IDLE 0x00 //No action, cancels current command execution -#define PN512_CMD_MEM 0x01 //Stores 25 bytes into the internal buffer -#define PN512_CMD_CONFIG 0x01 //Configures the PN512 for FeliCa, MIFARE and NFCIP-1 communication -#define PN512_CMD_RNDIDG 0x02 //Generates a 10-byte random ID number -#define PN512_CMD_CRC 0x03 //Activates the CRC coprocessor or performs a self test -#define PN512_CMD_TRANSMIT 0x04 //Transmits data from the FIFO buffer -#define PN512_CMD_NOCHANGE 0x07 //No command change -#define PN512_CMD_RECEIVE 0x08 //Activates the receiver circuits -#define PN512_CMD_TRANSCEIVE 0x0C //Transmits data from FIFO buffer to antenna and automatically activates the receiver after transmission -#define PN512_CMD_AUTOCOLL 0x0D //Handles FeliCa polling (Card Operation mode only) and MIFARE anticollision (Card Operation mode only) -#define PN512_CMD_MFAUTH 0x0E //Performs the MIFARE standard authentication as a reader -#define PN512_CMD_SOFTRST 0x0F //Resets the PN512 - -#define PN512_CMD_REG_MASK 0x0F - -void pn512_cmd_init(pn512_t *pPN512); - -//Fifo read / write - -void pn512_fifo_write(pn512_t *pPN512, ac_buffer_t *pData); -void pn512_fifo_read(pn512_t *pPN512, ac_buffer_builder_t *pData); - -//Fifo clear -void pn512_fifo_clear(pn512_t *pPN512); - -//Fifo bytes read -size_t pn512_fifo_space(pn512_t *pPN512); -size_t pn512_fifo_length(pn512_t *pPN512); - -//Execute command -void pn512_cmd_exec(pn512_t *pPN512, uint8_t cmd); - -//Wait for command completion -nfc_err_t pn512_cmd_wait_idle(pn512_t *pPN512, int timeout); - -//Read executed command -uint8_t pn512_cmd_get(pn512_t *pPN512); - - -#ifdef __cplusplus -} -#endif - -#endif /* PN512_CMD_H_ */ diff --git a/features/nfc/stack/transceiver/pn512/pn512_hw.c b/features/nfc/stack/transceiver/pn512/pn512_hw.c deleted file mode 100644 index 922c078..0000000 --- a/features/nfc/stack/transceiver/pn512/pn512_hw.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2013-2018, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * 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. - */ -/** - * \file pn512_hw.c - * \copyright Copyright (c) ARM Ltd 2013 - * \author Donatien Garnier - * \details Format and execute PN512 frames - */ - -#include "stack/nfc_errors.h" - -#include "pn512_hw.h" - -//Platform specific -#include "platform/nfc_transport.h" - - - -/** \addtogroup PN512 - * \internal - * @{ - * \name Hardware - * @{ - */ - -/** \internal Initialize underlying pn512_hw_t structure - * \param pPN512 pointer to pn512_t structure - */ -void pn512_hw_init(pn512_t *pPN512) -{ - //Nothing to init in this implementation - (void) pPN512; -} - - -/** - * @} - * @} - * */ - diff --git a/features/nfc/stack/transceiver/pn512/pn512_hw.h b/features/nfc/stack/transceiver/pn512/pn512_hw.h deleted file mode 100644 index b193517..0000000 --- a/features/nfc/stack/transceiver/pn512/pn512_hw.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (c) 2013-2018, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * 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. - */ -/** - * \file pn512_hw.h - * \copyright Copyright (c) ARM Ltd 2013 - * \author Donatien Garnier - */ - -#ifndef PN512_HW_H_ -#define PN512_HW_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "stack/nfc_common.h" -#include "pn512.h" - -//Utility for transport: SPI address read/write -#define PN512_SPI_ADDR_R(x) ((1<<7) | ((x) << 1)) -#define PN512_SPI_ADDR_W(x) ((0<<7) | ((x) << 1)) - -void pn512_hw_init(pn512_t *pPN512); - -/** \internal Write bytes at the specified address on the underlying transport link - * \param pPN512 pointer to pn512_t structure - * \param addr address at which to write - * \param buf buffer to write - * \param len length of buffer - */ -static inline void pn512_hw_write(pn512_t *pPN512, uint8_t addr, uint8_t *buf, size_t len) -{ - nfc_transport_write(((nfc_transceiver_t *)pPN512)->pTransport, addr, buf, len); -} - -/** \internal Read bytes from the specified address on the underlying transport link - * \param pPN512 pointer to pn512_t structure - * \param addr address from which to read - * \param buf buffer to read - * \param len length of buffer - */ -static inline void pn512_hw_read(pn512_t *pPN512, uint8_t addr, uint8_t *buf, size_t len) -{ - nfc_transport_read(((nfc_transceiver_t *)pPN512)->pTransport, addr, buf, len); -} - -static inline void pn512_hw_write_buffer(pn512_t *pPN512, uint8_t addr, ac_buffer_t *pData, size_t len) -{ - while (len > 0) { - if (ac_buffer_reader_readable(pData) == 0) { - return; - } - size_t cpyLen = MIN(len, ac_buffer_reader_current_buffer_length(pData)); - nfc_transport_write(((nfc_transceiver_t *)pPN512)->pTransport, addr, ac_buffer_reader_current_buffer_pointer(pData), cpyLen); - ac_buffer_read_n_skip(pData, cpyLen); - len -= cpyLen; - } -} - -static inline void pn512_hw_read_buffer(pn512_t *pPN512, uint8_t addr, ac_buffer_builder_t *pData, size_t len) -{ - while (len > 0) { - if (ac_buffer_builder_writable(pData) == 0) { - return; - } - //Read payload - size_t cpyLen = MIN(len, ac_buffer_builder_space(pData)); - nfc_transport_read(((nfc_transceiver_t *)pPN512)->pTransport, addr, ac_buffer_builder_write_position(pData), cpyLen); - ac_buffer_builder_write_n_skip(pData, cpyLen); - len -= cpyLen; - } -} - -#ifdef __cplusplus -} -#endif - -#endif /* PN512_HW_H_ */ diff --git a/features/nfc/stack/transceiver/pn512/pn512_internal.h b/features/nfc/stack/transceiver/pn512/pn512_internal.h deleted file mode 100644 index ffff027..0000000 --- a/features/nfc/stack/transceiver/pn512/pn512_internal.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) 2013-2018, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * 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. - */ -/** - * \file pn512_internal.h - * \copyright Copyright (c) ARM Ltd 2013 - * \author Donatien Garnier - */ - -#ifndef PN512_INTERNAL_H_ -#define PN512_INTERNAL_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "stack/nfc_common.h" -#include "transceiver/transceiver_internal.h" - -#include "pn512.h" -#include "pn512_callback.h" - -//Public -void pn512_set_protocols(nfc_transceiver_t *pTransceiver, nfc_tech_t initiators, nfc_tech_t targets, polling_options_t options); -void pn512_poll(nfc_transceiver_t *pTransceiver); -void pn512_set_crc(nfc_transceiver_t *pTransceiver, bool crc_out, bool crc_in); -void pn512_set_timeout(nfc_transceiver_t *pTransceiver, int timeout); -void pn512_set_transceive_options(nfc_transceiver_t *pTransceiver, bool transmit, bool receive, bool repoll); -void pn512_set_transceive_framing(nfc_transceiver_t *pTransceiver, nfc_framing_t framing); -void pn512_set_write(nfc_transceiver_t *pTransceiver, ac_buffer_t *pWriteBuf); -ac_buffer_t *pn512_get_read(nfc_transceiver_t *pTransceiver); -size_t pn512_get_last_byte_length(nfc_transceiver_t *pTransceiver); -void pn512_set_last_byte_length(nfc_transceiver_t *pTransceiver, size_t lastByteLength); -void pn512_set_first_byte_align(nfc_transceiver_t *pTransceiver, size_t firstByteAlign); -void pn512_abort(nfc_transceiver_t *pTransceiver); -void pn512_transceive(nfc_transceiver_t *pTransceiver); -void pn512_close(nfc_transceiver_t *pTransceiver); -void pn512_sleep(nfc_transceiver_t *pTransceiver, bool sleep); - -void pn512_transceiver_callback(pn512_t *pPN512, nfc_err_t ret); - -static inline void pn512_rf_callback(pn512_t *pPN512, nfc_err_t ret) -{ - pPN512->rf.cb(pPN512, ret); -} - -static inline void pn512_poll_callback(pn512_t *pPN512, nfc_err_t ret) -{ - pPN512->poll.cb(pPN512, ret); -} - -static inline void pn512_anticollision_callback(pn512_t *pPN512, nfc_err_t ret) -{ - pPN512->anticollision.cb(pPN512, ret); -} - -static inline void pn512_transceive_callback(pn512_t *pPN512, nfc_err_t ret) -{ - pPN512->transceive.cb(pPN512, ret); -} - - - -#ifdef __cplusplus -} -#endif - -#endif /* PN512_INTERNAL_H_ */ diff --git a/features/nfc/stack/transceiver/pn512/pn512_irq.c b/features/nfc/stack/transceiver/pn512/pn512_irq.c deleted file mode 100644 index 1c8c82e..0000000 --- a/features/nfc/stack/transceiver/pn512/pn512_irq.c +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2013-2018, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * 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. - */ -/** - * \file pn512_irq.c - * \copyright Copyright (c) ARM Ltd 2013 - * \author Donatien Garnier - * \details Manage PN512 interrupt requests - */ - -#define __DEBUG__ 0 -#ifndef __MODULE__ -#define __MODULE__ "pn512_irq.c" -#endif -#include "stack/nfc_errors.h" - -#include "pn512_irq.h" -#include "pn512_registers.h" -#include "pn512_hw.h" -#include "pn512.h" - -/** \addtogroup PN512 - * \internal - * @{ - * \name Interrupts - * @{ - */ - - - - - - -/** - * @} - * @} - * */ diff --git a/features/nfc/stack/transceiver/pn512/pn512_irq.h b/features/nfc/stack/transceiver/pn512/pn512_irq.h deleted file mode 100644 index 9c56544..0000000 --- a/features/nfc/stack/transceiver/pn512/pn512_irq.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (c) 2013-2018, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * 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. - */ -/** - * \file pn512_irq.h - * \copyright Copyright (c) ARM Ltd 2013 - * \author Donatien Garnier - */ - -#ifndef PN512_IRQ_H_ -#define PN512_IRQ_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "stack/nfc_common.h" -#include "pn512.h" -#include "pn512_registers.h" - -#define PN512_IRQ_TX (1<<6) -#define PN512_IRQ_RX (1<<5) -#define PN512_IRQ_IDLE (1<<4) -#define PN512_IRQ_HIGH_ALERT (1<<3) -#define PN512_IRQ_LOW_ALERT (1<<2) -#define PN512_IRQ_ERR (1<<1) -#define PN512_IRQ_TIMER (1<<0) - -#define PN512_IRQ_SIGIN (1<<(4+8)) -#define PN512_IRQ_MODE (1<<(3+8)) -#define PN512_IRQ_CRC (1<<(2+8)) -#define PN512_IRQ_RF_ON (1<<(1+8)) -#define PN512_IRQ_RF_OFF (1<<(0+8)) - -#define PN512_IRQ_NONE 0x00 -#define PN512_IRQ_ALL 0x1F7F - -#define PN512_REG_COMIEN_MASK 0x7F -#define PN512_REG_COMIEN_VAL 0x00 - -#define PN512_REG_DIVIEN_MASK 0x1F -#define PN512_REG_DIVIEN_VAL 0x80 - -#define PN512_REG_COMIRQ_MASK 0x7F -#define PN512_REG_COMIRQ_CLEAR 0x00 - -#define PN512_REG_DIVIRQ_MASK 0x1F -#define PN512_REG_DIVIRQ_CLEAR 0x00 - -/** \internal Set IRQ enable registers - * \param pPN512 pointer to pn512_t structure - * \param irqs MSB is DIVIEN value, LSB is COMIEN value - */ -static inline void pn512_irq_set(pn512_t *pPN512, uint16_t irqs) //ORed -{ - pn512_register_write(pPN512, PN512_REG_COMIEN, PN512_REG_COMIEN_VAL | (PN512_REG_COMIEN_MASK & (irqs & 0xFF))); - pn512_register_write(pPN512, PN512_REG_DIVIEN, PN512_REG_DIVIEN_VAL | (PN512_REG_DIVIEN_MASK & (irqs >> 8))); - pPN512->irqsEn = irqs; -} - -/** \internal Get IRQ enable registers - * \param pPN512 pointer to pn512_t structure - * \return MSB is DIVIEN value, LSB is COMIEN value - */ -static inline uint16_t pn512_irq_enabled(pn512_t *pPN512) //ORed -{ - return pPN512->irqsEn /*(pn512_register_read(pPN512, PN512_REG_COMIEN_VAL) & PN512_REG_COMIEN_MASK) - | ((pn512_register_read(pPN512, PN512_REG_DIVIEN_VAL) & PN512_REG_DIVIEN_MASK) << 8)*/; -} - -/** \internal Get IRQ status registers (masked with enabled IRQ register) - * \param pPN512 pointer to pn512_t structure - * \return MSB is DIVIRQ value, LSB is COMIRQ value - */ -static inline uint16_t pn512_irq_get(pn512_t *pPN512) //ORed -{ - return ((pn512_register_read(pPN512, PN512_REG_COMIRQ) & PN512_REG_COMIEN_MASK) - | ((pn512_register_read(pPN512, PN512_REG_DIVIRQ) & PN512_REG_DIVIEN_MASK) << 8)) & pPN512->irqsEn; -} - -/** \internal Clear some interrupts - * \param pPN512 pointer to pn512_t structure - * \param irqs MSB is DIVIEN value, LSB is COMIEN value - */ -static inline void pn512_irq_clear(pn512_t *pPN512, uint16_t irqs) -{ - pn512_register_write(pPN512, PN512_REG_COMIRQ, PN512_REG_COMIRQ_CLEAR | (PN512_REG_COMIRQ_MASK & (irqs & 0xFF))); - pn512_register_write(pPN512, PN512_REG_DIVIRQ, PN512_REG_DIVIRQ_CLEAR | (PN512_REG_DIVIRQ_MASK & (irqs >> 8))); -} - -#ifdef __cplusplus -} -#endif - -#endif /* PN512_IRQ_H_ */ diff --git a/features/nfc/stack/transceiver/pn512/pn512_poll.c b/features/nfc/stack/transceiver/pn512/pn512_poll.c deleted file mode 100644 index ad349c5..0000000 --- a/features/nfc/stack/transceiver/pn512/pn512_poll.c +++ /dev/null @@ -1,1268 +0,0 @@ -/* - * Copyright (c) 2014-2018, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * 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. - */ -/** - * \file pn512_poll.c - * \copyright Copyright (c) ARM Ltd 2014 - * \author Donatien Garnier - */ - -#define __DEBUG__ 0 -#ifndef __MODULE__ -#define __MODULE__ "pn512_poll.c" -#endif - -#include "stack/nfc_errors.h" - -#include "pn512.h" -#include "pn512_poll.h" -#include "pn512_transceive.h" -#include "pn512_registers.h" -#include "pn512_rf.h" -#include "pn512_cmd.h" -#include "pn512_internal.h" - -#define TIMEOUT 1000 - -static void pn512_target_anticollision(pn512_t *pPN512, pn512_cb_t cb); -static void pn512_initiator_isoa_anticollision(pn512_t *pPN512, pn512_cb_t cb); - -static inline bool pn512_config_initiator(pn512_t *pPN512) -{ - return (pPN512->config.initiators.nfc_iso_dep_a | pPN512->config.initiators.nfc_iso_dep_b | - pPN512->config.initiators.nfc_nfc_dep_a | pPN512->config.initiators.nfc_nfc_dep_f_212 | pPN512->config.initiators.nfc_nfc_dep_f_424 | - pPN512->config.initiators.nfc_type1 | pPN512->config.initiators.nfc_type2 | pPN512->config.initiators.nfc_type3) != 0; -} - -static inline bool pn512_config_target(pn512_t *pPN512) -{ - return (pPN512->config.targets.nfc_iso_dep_a | pPN512->config.targets.nfc_iso_dep_b | - pPN512->config.targets.nfc_nfc_dep_a | pPN512->config.targets.nfc_nfc_dep_f_212 | pPN512->config.initiators.nfc_nfc_dep_f_424 | - pPN512->config.targets.nfc_type1 | pPN512->config.targets.nfc_type2 | pPN512->config.targets.nfc_type3) != 0; -} - -void pn512_target_anticollision_complete(pn512_t *pPN512, nfc_err_t ret) -{ - - bool iso14443a = pPN512->config.targets.nfc_type2 || pPN512->config.targets.nfc_iso_dep_a || pPN512->config.targets.nfc_nfc_dep_a; //We do not support type 1 card emulation so irrelevant - bool felica = pPN512->config.targets.nfc_type3 || pPN512->config.targets.nfc_nfc_dep_f_212 || pPN512->config.targets.nfc_nfc_dep_f_424; - - nfc_transceiver_t *pTransceiver = &pPN512->transceiver; - if (ret) { - NFC_WARN("Returned %d", ret); - pn512_anticollision_callback(pPN512, ret); - return; - } - - //Data available in FIFO - if (pPN512->readLastByteLength != 8) { //We should receive a full byte - NFC_WARN("Not enough data in FIFO"); - pn512_anticollision_callback(pPN512, NFC_ERR_PROTOCOL); - return; - } - - //If successful, update state machine - if (iso14443a && felica) { - //Update current protocol accordingly - uint8_t txmode = pn512_register_read(pPN512, PN512_REG_TXMODE); - if ((txmode & 0x03) == 0x00) { - pn512_framing_set(pPN512, nfc_framing_target_a_106); - - NFC_DBG("A 106"); - felica = false; - } else if ((txmode & 0x03) == 0x02) { - if ((txmode & 0x70) == 0x20) { - //424kbps - NFC_DBG("F 424"); - pn512_framing_set(pPN512, nfc_framing_target_f_424); - } else { - //212kbps - NFC_DBG("F 212"); - pn512_framing_set(pPN512, nfc_framing_target_f_212); - } - iso14443a = false; - } else { - //Unsupported mode, exit - pn512_anticollision_callback(pPN512, NFC_ERR_UNSUPPORTED); - return; - } - } - - if (iso14443a) { - if (ac_buffer_reader_readable(ac_buffer_builder_buffer(&pPN512->readBufBldr)) == 0) { - pn512_anticollision_callback(pPN512, NFC_ERR_PROTOCOL); - return; - } - - //Halt device, so that if anticollision is restarted it's in the correct state (cleared automatically by RF reset) - pn512_register_write(pPN512, PN512_REG_MIFNFC, 0x62 | 0x04); - - //Copy buffer to peek - ac_buffer_t readBufDup; - ac_buffer_dup(&readBufDup, ac_buffer_builder_buffer(&pPN512->readBufBldr)); - - uint8_t b0 = ac_buffer_read_nu8(&readBufDup); - - //Get first byte - //Read FIFO to see if the target was selected as NFC-DEP, ISO-DEP or proprietary (NFC Type 2) - //F0 --> NFC-DEP - //E0 --> ISO-DEP - //Anything else --> NFC Type 2 - - //First check if this could be NFC-DEP - if (pPN512->config.targets.nfc_nfc_dep_a && (b0 == 0xF0)) { - pTransceiver->active_tech.nfc_nfc_dep_a = true; - } else if (pPN512->config.targets.nfc_iso_dep_a && (b0 == 0xE0)) { - pTransceiver->active_tech.nfc_iso_dep_a = true; - } else if (pPN512->config.targets.nfc_type2) { - pTransceiver->active_tech.nfc_type2 = true; - } else { - //Unknown tech, return error - pn512_anticollision_callback(pPN512, NFC_ERR_UNSUPPORTED); - return; - } - - //Give control to higher layer - pn512_anticollision_callback(pPN512, NFC_OK); - return; - } else if (felica) { - //First check if this could be NFC-DEP - if ((pPN512->config.targets.nfc_nfc_dep_f_212 || pPN512->config.targets.nfc_nfc_dep_f_424)) { - if (pPN512->framing == nfc_framing_target_f_424) { - pTransceiver->active_tech.nfc_nfc_dep_f_424 = true; - } else { - pTransceiver->active_tech.nfc_nfc_dep_f_212 = true; - } - } else { - pn512_anticollision_callback(pPN512, NFC_ERR_UNSUPPORTED); - return; - } - } - - //NFC-IP 1 active mode is not supported by other devices so ignore it for now - pn512_anticollision_callback(pPN512, NFC_OK); -} - - -void pn512_target_anticollision(pn512_t *pPN512, pn512_cb_t cb) -{ - pPN512->anticollision.cb = cb; - - //Reset active states - pPN512->transceiver.initiator_ntarget = false; - pPN512->transceiver.active_tech.nfc_type1 = pPN512->transceiver.active_tech.nfc_type2 = pPN512->transceiver.active_tech.nfc_type3 - = pPN512->transceiver.active_tech.nfc_iso_dep_a = pPN512->transceiver.active_tech.nfc_nfc_dep_a = - pPN512->transceiver.active_tech.nfc_nfc_dep_f_212 = pPN512->transceiver.active_tech.nfc_nfc_dep_f_424 = 0; - - pn512_set_timeout((nfc_transceiver_t *)pPN512, -1); //Should only fail on RF drop - - pn512_transceive_hw(pPN512, pn512_transceive_mode_target_autocoll, pn512_target_anticollision_complete); -} - -// ISO A - -#define ISO14443A_BUF_SIZE 8 - -#define REQA 0x26 -#define SEL(n) (0x93 + (n)*2) -#define NVB(bits) ( (((2*8 + (bits))>>3)<<4) | ((bits) & 0x7) ) -#define HALTA1 0x50 -#define HALTA2 0x00 -#define CT 0x88 - -static void pn512_initiator_isoa_anticollision_reqa(pn512_t *pPN512); -static void pn512_initiator_isoa_anticollision_atqa(pn512_t *pPN512, nfc_err_t ret); -static void pn512_initiator_isoa_anticollision_cascade_1(pn512_t *pPN512); -static void pn512_initiator_isoa_anticollision_cascade_2(pn512_t *pPN512, nfc_err_t ret); -static void pn512_initiator_isoa_anticollision_cascade_3(pn512_t *pPN512, nfc_err_t ret); -static void pn512_initiator_isoa_anticollision_cascade_4(pn512_t *pPN512, nfc_err_t ret); -static void pn512_initiator_isoa_anticollision_complete(pn512_t *pPN512); - -void pn512_initiator_isoa_anticollision(pn512_t *pPN512, pn512_cb_t cb) -{ - pPN512->anticollision.cb = cb; - - // Reset transceive mode - pPN512->transceive.mode = pn512_transceive_mode_idle; - - pn512_initiator_isoa_anticollision_reqa(pPN512); -} - -void pn512_initiator_isoa_anticollision_reqa(pn512_t *pPN512) -{ - ac_buffer_builder_t *pDataOutBldr = &pPN512->readBufBldr; - ac_buffer_builder_reset(pDataOutBldr); - - pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].nfcA.uidLength = 0; - - ac_buffer_builder_write_nu8(pDataOutBldr, REQA); - pn512_set_last_byte_length((nfc_transceiver_t *)pPN512, 7); //Only 7 bits in this first command - // FIXME PN512 Anomaly: pn512_register_write(pPN512, PN512_REG_COLL, 0x00); // Set MSB to 0, to accept collisions - pn512_set_crc((nfc_transceiver_t *)pPN512, false, false); - pn512_set_timeout((nfc_transceiver_t *)pPN512, 4); - pn512_set_write((nfc_transceiver_t *)pPN512, ac_buffer_builder_buffer(pDataOutBldr)); - - pn512_transceive_hw(pPN512, pn512_transceive_mode_transceive, pn512_initiator_isoa_anticollision_atqa); -} - -void pn512_initiator_isoa_anticollision_atqa(pn512_t *pPN512, nfc_err_t ret) -{ - // Clear collisions register - // FIXME PN512 Anomaly: pn512_register_write(pPN512, PN512_REG_COLL, 0x80); // Set MSB to 1, to treat collisions as errors - - if (ret && (ret != NFC_ERR_COLLISION)) { // There might be collisions here - NFC_WARN("Did not receive ATQA: error %d", ret); - pn512_anticollision_callback(pPN512, NFC_ERR_NOPEER); - return; - } - - ac_buffer_t *pResp = pn512_get_read((nfc_transceiver_t *)pPN512); - - if (ac_buffer_reader_readable(pResp) != 2) { - NFC_WARN("Wrong length (%u bytes)", ac_buffer_reader_readable(pResp)); - pn512_anticollision_callback(pPN512, NFC_ERR_PROTOCOL); - return; - } - - NFC_DBG("Got ATQA:"); - NFC_DBG_BLOCK(ac_buffer_dump(pResp);) - - // Ignore ATQA as there can be collisions - ac_buffer_read_n_bytes(pResp, pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].nfcA.atqa, 2); - - //Start cascading - pPN512->anticollision.iso_a.cascade_level = 1; - pPN512->anticollision.iso_a.valid_bits = 0; - pPN512->anticollision.iso_a.more_targets = false; - memset(pPN512->anticollision.iso_a.cln, 0, 5); - - pn512_initiator_isoa_anticollision_cascade_1(pPN512); -} - -void pn512_initiator_isoa_anticollision_cascade_1(pn512_t *pPN512) -{ - ac_buffer_builder_t *pDataOutBldr = &pPN512->readBufBldr; - ac_buffer_builder_reset(pDataOutBldr); - - //SEL - ac_buffer_builder_write_nu8(pDataOutBldr, SEL(pPN512->anticollision.iso_a.cascade_level - 1)); //SEL: Cascade level - ac_buffer_builder_write_nu8(pDataOutBldr, NVB(pPN512->anticollision.iso_a.valid_bits)); //First NVB: Bytecount = 2, Bitcount = 0, then adapt if collision detected - - NFC_DBG("SEL - cascade level %u, %u valid bits - NVB %u", pPN512->anticollision.iso_a.cascade_level, pPN512->anticollision.iso_a.valid_bits, NVB(pPN512->anticollision.iso_a.valid_bits)); - - if (pPN512->anticollision.iso_a.valid_bits > 0) { - // Transmit first part of uid - ac_buffer_builder_write_n_bytes(pDataOutBldr, pPN512->anticollision.iso_a.cln, (pPN512->anticollision.iso_a.valid_bits >> 3) + ((pPN512->anticollision.iso_a.valid_bits & 0x7) ? 1 : 0)); - pn512_set_last_byte_length((nfc_transceiver_t *)pPN512, pPN512->anticollision.iso_a.valid_bits & 0x7); - pn512_set_first_byte_align((nfc_transceiver_t *)pPN512, pPN512->anticollision.iso_a.valid_bits & 0x7); - } - - // FIXME PN512 Anomaly: pn512_register_write(pPN512, PN512_REG_COLL, 0x00); // Set MSB to 0, to accept collisions - pn512_set_crc((nfc_transceiver_t *)pPN512, false, false); - pn512_set_timeout((nfc_transceiver_t *)pPN512, 30); - pn512_set_write((nfc_transceiver_t *)pPN512, ac_buffer_builder_buffer(pDataOutBldr)); - - - pn512_register_write(pPN512, PN512_REG_COMIRQ, 2); - NFC_DBG("IRQ status %04X", ((pn512_register_read(pPN512, PN512_REG_COMIRQ)) - | ((pn512_register_read(pPN512, PN512_REG_DIVIRQ)) << 8))); - - pn512_transceive_hw(pPN512, pn512_transceive_mode_transceive, pn512_initiator_isoa_anticollision_cascade_2); -} - -void pn512_initiator_isoa_anticollision_cascade_2(pn512_t *pPN512, nfc_err_t ret) -{ - ac_buffer_t *pResp = pn512_get_read((nfc_transceiver_t *)pPN512); - - // Load & clear collisions register - // FIXME PN512 Anomaly: pn512_register_write(pPN512, PN512_REG_COLL, 0x80); // Set MSB to 1, to treat collisions as errors - - if (ret && (ret != NFC_ERR_COLLISION)) { // There might be collisions here - NFC_WARN("Did not receive response: error %d", ret); - pn512_anticollision_callback(pPN512, ret); - return; - } - - // We should receive 5 bytes back minus all the CLn bits that we have transmitted; we ignore all bits from the first collision - size_t expected_resp_bits = (5 << 3) - pPN512->anticollision.iso_a.valid_bits; - - // Check for collision - uint8_t valid_bits = expected_resp_bits; - if (ret == NFC_ERR_COLLISION) { - uint8_t coll_reg = pn512_register_read(pPN512, PN512_REG_COLL); - - // FIXME - PN512 error - //if( !(coll_reg & 0x20) ) // bit 5 is CollPosNotValidSet - { - valid_bits = (coll_reg & 0x1f); - - if (valid_bits == 0) { - valid_bits = 32; - } - - valid_bits--; - - NFC_DBG("Collision detected, %u valid bits", valid_bits); - if (valid_bits < expected_resp_bits) { - // Collision detected - pPN512->anticollision.iso_a.more_targets = true; - } else { - valid_bits = expected_resp_bits; - } - } - } - - size_t resp_sz = (valid_bits >> 3) + ((valid_bits & 0x7) ? 1 : 0); - if (ac_buffer_reader_readable(pResp) < resp_sz) { - (void) pn512_register_read(pPN512, PN512_REG_COLL); - - NFC_WARN("Wrong length (%u instead of %u - valid bits %u)", ac_buffer_reader_readable(pResp), resp_sz, valid_bits); - pn512_anticollision_callback(pPN512, NFC_ERR_PROTOCOL); - return; - } - - // Read bytes - uint8_t bufIn[5] = {0}; - ac_buffer_read_n_bytes(pResp, bufIn + (pPN512->anticollision.iso_a.valid_bits >> 3), resp_sz); - - // Mask out valid bits that are already known - bufIn[pPN512->anticollision.iso_a.valid_bits >> 3] &= 0xff << (pPN512->anticollision.iso_a.valid_bits & 0x7); - - // Update number of valid bits - pPN512->anticollision.iso_a.valid_bits += valid_bits; - - // Mask out bits past valid bits in last byte - bufIn[pPN512->anticollision.iso_a.valid_bits >> 3] &= 0xff >> ((8 - pPN512->anticollision.iso_a.valid_bits) & 0x7); - - // Now remember bits before collision - for (size_t p = 0; p < 5; p++) { - pPN512->anticollision.iso_a.cln[p] |= bufIn[p]; - } - - // If we have all bits, then check BCC, go to next step - if (pPN512->anticollision.iso_a.valid_bits < 5 * 8) { // Collision, add a 1 at the end of known bits to resolve collision - pPN512->anticollision.iso_a.cln[pPN512->anticollision.iso_a.valid_bits >> 3] |= (1 << (pPN512->anticollision.iso_a.valid_bits & 0x7)); - pPN512->anticollision.iso_a.valid_bits++; - - // Restart first step with more valid bits - pn512_initiator_isoa_anticollision_cascade_1(pPN512); - return; - } - - //Check BCC if all bits are valid - if (pPN512->anticollision.iso_a.cln[4] != (pPN512->anticollision.iso_a.cln[0] ^ pPN512->anticollision.iso_a.cln[1] ^ pPN512->anticollision.iso_a.cln[2] ^ pPN512->anticollision.iso_a.cln[3])) { - NFC_WARN("Wrong BCC %02X != %02X", bufIn[4], bufIn[0] ^ bufIn[1] ^ bufIn[2] ^ bufIn[3]); - pn512_anticollision_callback(pPN512, NFC_ERR_COLLISION); - return; //TODO handle this properly - } - - if (pPN512->anticollision.iso_a.cln[0] == CT) { - //Not the last cascade level - if (pPN512->anticollision.iso_a.cascade_level == 3) { // not allowed - NFC_WARN("Cascade tag present in cascade level 3"); - pn512_anticollision_callback(pPN512, NFC_ERR_PROTOCOL); - return; - } - memcpy(&pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].nfcA.uid[(pPN512->anticollision.iso_a.cascade_level - 1) * 3], &pPN512->anticollision.iso_a.cln[1], 3); - pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].nfcA.uidLength += 3; - } else { - //Last cascade level - memcpy(&pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].nfcA.uid[(pPN512->anticollision.iso_a.cascade_level - 1) * 3], &pPN512->anticollision.iso_a.cln[0], 4); - pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].nfcA.uidLength += 4; - } - - ac_buffer_builder_t *pDataOutBldr = &pPN512->readBufBldr; - ac_buffer_builder_reset(pDataOutBldr); - - //Select and get SAK - ac_buffer_builder_write_nu8(pDataOutBldr, SEL(pPN512->anticollision.iso_a.cascade_level - 1)); //SEL: Cascade level - ac_buffer_builder_write_nu8(pDataOutBldr, NVB(40)); //NVB: 40 valid bits = 5 bytes - - //Transmit last 4 transmitted UID bytes + BCC (including cascade byte if relevant) - ac_buffer_builder_write_n_bytes(pDataOutBldr, pPN512->anticollision.iso_a.cln, 5); - - NFC_DBG("Selecting target"); - - //This time compute & check CRC - pn512_set_crc((nfc_transceiver_t *)pPN512, true, true); - pn512_set_write((nfc_transceiver_t *)pPN512, ac_buffer_builder_buffer(pDataOutBldr)); - pn512_transceive_hw(pPN512, pn512_transceive_mode_transceive, pn512_initiator_isoa_anticollision_cascade_3); -} - -static void pn512_initiator_isoa_anticollision_cascade_3(pn512_t *pPN512, nfc_err_t ret) -{ - ac_buffer_t *pResp = pn512_get_read((nfc_transceiver_t *)pPN512); - - if (ret) { - NFC_WARN("Did not receive response: error %d", ret); - pn512_anticollision_callback(pPN512, ret); - return; - } - - if (ac_buffer_reader_readable(pResp) != 1) { - NFC_WARN("Wrong length"); - pn512_anticollision_callback(pPN512, NFC_ERR_PROTOCOL); - return; - } - - pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].nfcA.sak = ac_buffer_read_nu8(pResp); - NFC_DBG("Got SAK %02X", pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].nfcA.sak); - - //Check SAK - if (pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].nfcA.sak & 0x04) { - //Continue anticollision - pPN512->anticollision.iso_a.cascade_level++; - pPN512->anticollision.iso_a.valid_bits = 0; - memset(pPN512->anticollision.iso_a.cln, 0, 5); - pn512_initiator_isoa_anticollision_cascade_1(pPN512); - } else { - //Anticollision complete - - NFC_DBG("Found one target- SAK = %02X", pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].nfcA.sak); - - //Analyze SAK - memset(&pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].type, 0, sizeof(nfc_tech_t)); - - if (pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].nfcA.sak & 0x40) { //NFC-IP1 compliant - pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].type.nfc_nfc_dep_a = true; - } - if ((pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].nfcA.sak & 0x20) - && pPN512->config.initiators.nfc_iso_dep_a) { //ISO-14443A-4 compliant - pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].type.nfc_iso_dep_a = true; - } - if (!(pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].nfcA.sak & 0x60) - && pPN512->config.initiators.nfc_type2) { //Potentially NFC Type 2 (or Mifare, etc) - pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].type.nfc_type2 = true; - } - - // Unknown target - if (!pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].type.nfc_iso_dep_a - && !pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].type.nfc_nfc_dep_a - && !pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].type.nfc_type2 - ) { - pn512_anticollision_callback(pPN512, NFC_ERR_NOPEER); - return; - } - - // Valid target detected - pPN512->transceiver.active_tech = pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].type; - pPN512->transceiver.remote_targets_count++; - - if (!pPN512->config.options.bail_at_first_target - && pPN512->anticollision.iso_a.more_targets - && (pPN512->transceiver.remote_targets_count < MUNFC_MAX_REMOTE_TARGETS)) { - // Halt target and continue with others - ac_buffer_builder_t *pDataOutBldr = &pPN512->readBufBldr; - ac_buffer_builder_reset(pDataOutBldr); - - //HALTA - ac_buffer_builder_write_nu8(pDataOutBldr, HALTA1); - ac_buffer_builder_write_nu8(pDataOutBldr, HALTA2); - - pn512_set_crc((nfc_transceiver_t *)pPN512, true, false); - pn512_set_timeout((nfc_transceiver_t *)pPN512, 30); - pn512_set_write((nfc_transceiver_t *)pPN512, ac_buffer_builder_buffer(pDataOutBldr)); - pn512_transceive_hw(pPN512, pn512_transceive_mode_transmit, pn512_initiator_isoa_anticollision_cascade_4); - return; - } - - // Leave it activated and finish! - pn512_initiator_isoa_anticollision_complete(pPN512); - } -} - -static void pn512_initiator_isoa_anticollision_cascade_4(pn512_t *pPN512, nfc_err_t ret) -{ - if (ret) { - NFC_WARN("Could not halt device: error %d", ret); - pn512_anticollision_callback(pPN512, ret); - return; - } - - // Start again - pn512_initiator_isoa_anticollision_reqa(pPN512); -} - -void pn512_initiator_isoa_anticollision_complete(pn512_t *pPN512) -{ - pn512_anticollision_callback(pPN512, NFC_OK); -} - -// ISO B -static void pn512_initiator_isob_anticollision(pn512_t *pPN512, pn512_cb_t cb); -static void pn512_initiator_isob_anticollision_reqb(pn512_t *pPN512); -static void pn512_initiator_isob_anticollision_atqb(pn512_t *pPN512, nfc_err_t ret); -static void pn512_initiator_isob_anticollision_next_slot(pn512_t *pPN512); -static void pn512_initiator_isob_anticollision_haltb_resp(pn512_t *pPN512, nfc_err_t ret); -static void pn512_initiator_isob_anticollision_complete(pn512_t *pPN512); - -#define REQB 0x05 -#define HALTB 0x50 - -void pn512_initiator_isob_anticollision(pn512_t *pPN512, pn512_cb_t cb) -{ - pPN512->anticollision.cb = cb; - pPN512->anticollision.iso_b.slots_num_exponent = 0; // Start with one slot - pPN512->anticollision.iso_b.slot_number = 0; - pPN512->anticollision.iso_b.found_one = false; - - // Reset transceive mode - pPN512->transceive.mode = pn512_transceive_mode_idle; - - pn512_initiator_isob_anticollision_reqb(pPN512); -} - -void pn512_initiator_isob_anticollision_reqb(pn512_t *pPN512) -{ - ac_buffer_builder_t *pDataOutBldr = &pPN512->readBufBldr; - ac_buffer_builder_reset(pDataOutBldr); - - if (pPN512->anticollision.iso_b.slot_number == 0) { - // Send REQB/WUPB - pPN512->anticollision.iso_b.more_targets = false; - - ac_buffer_builder_write_nu8(pDataOutBldr, REQB); - ac_buffer_builder_write_nu8(pDataOutBldr, 0x00); // AFI: All card types should respond - uint8_t wup = 0; - if ( - pPN512->anticollision.iso_b.slots_num_exponent == 0 - //&& (pPN512->anticollision.iso_b.slot_number == 0) - ) { - wup |= 0x8; // Send Wake-Up command on first iteration - } - ac_buffer_builder_write_nu8(pDataOutBldr, wup | (pPN512->anticollision.iso_b.slots_num_exponent & 0x7)); // Param: number of slots - } else { - // Just send slot marker - ac_buffer_builder_write_nu8(pDataOutBldr, REQB | ((pPN512->anticollision.iso_b.slot_number & 0xf) << 4)); - } - - pn512_set_crc((nfc_transceiver_t *)pPN512, true, true); - pn512_set_timeout((nfc_transceiver_t *)pPN512, 18); - pn512_set_write((nfc_transceiver_t *)pPN512, ac_buffer_builder_buffer(pDataOutBldr)); - pn512_transceive_hw(pPN512, pn512_transceive_mode_transceive, pn512_initiator_isob_anticollision_atqb); -} - -void pn512_initiator_isob_anticollision_atqb(pn512_t *pPN512, nfc_err_t ret) -{ - // Three cases: - // - 1 response --> store response, halt PICC and check next slot number - // - No response --> check next slot number - // - Collision --> check next slot number but we will have to increment number of slots - ac_buffer_t *pResp = pn512_get_read((nfc_transceiver_t *)pPN512); - - if (ret && (ret != NFC_ERR_COLLISION) && (ret != NFC_ERR_WRONG_COMM) && (ret != NFC_ERR_TIMEOUT)) { - NFC_WARN("Did not receive ATQB: error %u", ret); - pn512_anticollision_callback(pPN512, NFC_ERR_PROTOCOL); - return; - } - - // Increment slot number - pPN512->anticollision.iso_b.slot_number++; - - if ((ret == NFC_ERR_COLLISION) || (ret == NFC_ERR_WRONG_COMM)) { - pPN512->anticollision.iso_b.more_targets = true; - } else if (!ret) { - pPN512->anticollision.iso_b.found_one = true; - - // Decode ATQB - if (ac_buffer_reader_readable(pResp) != 12) { - NFC_WARN("Wrong length (%u bytes)", ac_buffer_reader_readable(pResp)); - pn512_anticollision_callback(pPN512, NFC_ERR_PROTOCOL); - return; - } - - NFC_DBG("Got ATQB:"); - NFC_DBG_BLOCK(ac_buffer_dump(pResp);) - - // Check first byte - uint8_t atqb0 = ac_buffer_read_nu8(pResp); - if (atqb0 != 0x50) { - NFC_WARN("Wrong first byte for ATQB: %02X", atqb0); - pn512_anticollision_callback(pPN512, NFC_ERR_PROTOCOL); - return; - } - - memset(&pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].type, 0, sizeof(nfc_tech_t)); - pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].type.nfc_iso_dep_b = true; - - // Save PUPI, application data & protocol info - ac_buffer_read_n_bytes(pResp, pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].nfcB.pupi, 4); - ac_buffer_read_n_bytes(pResp, pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].nfcB.application_data, 4); - ac_buffer_read_n_bytes(pResp, pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].nfcB.protocol_info, 3); - - // Valid target detected - pPN512->transceiver.active_tech = pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].type; - pPN512->transceiver.remote_targets_count++; - - if (!pPN512->config.options.bail_at_first_target - && (pPN512->anticollision.iso_b.more_targets || (pPN512->anticollision.iso_b.slot_number < (1 << pPN512->anticollision.iso_b.slots_num_exponent))) - && (pPN512->transceiver.remote_targets_count < MUNFC_MAX_REMOTE_TARGETS)) { - // Halt target and continue with others - ac_buffer_builder_t *pDataOutBldr = &pPN512->readBufBldr; - ac_buffer_builder_reset(pDataOutBldr); - - // Halt PICC and move on to the next slot - - //HALTB - ac_buffer_builder_write_nu8(pDataOutBldr, HALTB); - ac_buffer_builder_write_n_bytes(pDataOutBldr, pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count - 1].nfcB.pupi, 4); - - pn512_set_crc((nfc_transceiver_t *)pPN512, true, true); - pn512_set_timeout((nfc_transceiver_t *)pPN512, 30); - pn512_set_write((nfc_transceiver_t *)pPN512, ac_buffer_builder_buffer(pDataOutBldr)); - pn512_transceive_hw(pPN512, pn512_transceive_mode_transceive, pn512_initiator_isob_anticollision_haltb_resp); - return; - } else { - pn512_initiator_isob_anticollision_complete(pPN512); - return; - } - } - - // Move on to the next slot - pn512_initiator_isob_anticollision_next_slot(pPN512); -} - -void pn512_initiator_isob_anticollision_next_slot(pn512_t *pPN512) -{ - if (pPN512->anticollision.iso_b.slot_number >= (1 << pPN512->anticollision.iso_b.slots_num_exponent)) { - if (!pPN512->anticollision.iso_b.more_targets) { - // No further collisions to resolve - pn512_initiator_isob_anticollision_complete(pPN512); - return; - } - if (pPN512->anticollision.iso_b.slots_num_exponent >= 4) { - // Cannot handle more than 16 slots - pn512_initiator_isob_anticollision_complete(pPN512); - return; - } - pPN512->anticollision.iso_b.slots_num_exponent++; - pPN512->anticollision.iso_b.slot_number = 0; - } - pn512_initiator_isob_anticollision_reqb(pPN512); -} - -void pn512_initiator_isob_anticollision_haltb_resp(pn512_t *pPN512, nfc_err_t ret) -{ - // Check for response - if (ret) { - NFC_WARN("Did not receive HALTB response: error %u", ret); - pn512_anticollision_callback(pPN512, NFC_ERR_PROTOCOL); - return; - } - - ac_buffer_t *pResp = pn512_get_read((nfc_transceiver_t *)pPN512); - - if (ac_buffer_reader_readable(pResp) != 1) { - NFC_WARN("Wrong length (%u bytes)", ac_buffer_reader_readable(pResp)); - pn512_anticollision_callback(pPN512, NFC_ERR_PROTOCOL); - return; - } - - NFC_DBG("Got HALTB response:"); - NFC_DBG_BLOCK(ac_buffer_dump(pResp);) - - // Check byte - uint8_t haltbr = ac_buffer_read_nu8(pResp); - if (haltbr != 0x00) { - NFC_WARN("Wrong byte for HALTB response: %02X", haltbr); - pn512_anticollision_callback(pPN512, NFC_ERR_PROTOCOL); - return; - } - - // PICC halted, move to next slot - pn512_initiator_isob_anticollision_next_slot(pPN512); -} - -void pn512_initiator_isob_anticollision_complete(pn512_t *pPN512) -{ - if (pPN512->anticollision.iso_b.found_one) { - pn512_anticollision_callback(pPN512, NFC_OK); - } else { - pn512_anticollision_callback(pPN512, NFC_ERR_NOPEER); - } -} - -// Felica -static void pn512_initiator_felica_anticollision(pn512_t *pPN512, pn512_cb_t cb); -static void pn512_initiator_felica_anticollision_reqc(pn512_t *pPN512); -static void pn512_initiator_felica_anticollision_atqc(pn512_t *pPN512, nfc_err_t ret); -static void pn512_initiator_felica_anticollision_complete(pn512_t *pPN512); - -#define REQC 0x00 - -void pn512_initiator_felica_anticollision(pn512_t *pPN512, pn512_cb_t cb) -{ - pPN512->anticollision.cb = cb; - - // Reset transceive mode - pPN512->transceive.mode = pn512_transceive_mode_idle; - - pn512_initiator_felica_anticollision_reqc(pPN512); -} - -void pn512_initiator_felica_anticollision_reqc(pn512_t *pPN512) -{ - ac_buffer_builder_t *pDataOutBldr = &pPN512->readBufBldr; - ac_buffer_builder_reset(pDataOutBldr); - - ac_buffer_builder_write_nu8(pDataOutBldr, 6); //Length - ac_buffer_builder_write_nu8(pDataOutBldr, REQC); - ac_buffer_builder_write_nu16(pDataOutBldr, 0xFFFF); //Any system code - ac_buffer_builder_write_nu8(pDataOutBldr, 0x00); // Padding - ac_buffer_builder_write_nu8(pDataOutBldr, 0x07); // 8 time slots, more would overflow the rx buffer if many cards responded - - pn512_set_crc((nfc_transceiver_t *)pPN512, true, true); - pn512_set_timeout((nfc_transceiver_t *)pPN512, 13); //8 timeslots at 212kbps - pn512_set_write((nfc_transceiver_t *)pPN512, ac_buffer_builder_buffer(pDataOutBldr)); - - pn512_framing_rx_multiple_enable(pPN512); // Set RxMultiple bit - - pn512_transceive_hw(pPN512, pn512_transceive_mode_transceive, pn512_initiator_felica_anticollision_atqc); -} - -void pn512_initiator_felica_anticollision_atqc(pn512_t *pPN512, nfc_err_t ret) -{ - ac_buffer_t *pResp = pn512_get_read((nfc_transceiver_t *)pPN512); - - if (ret || (ac_buffer_reader_readable(pResp) == 0)) { - NFC_WARN("Did not receive ATQC: error %d", ret); - pn512_anticollision_callback(pPN512, NFC_ERR_NOPEER); - return; - } - - // We might have multiple responses - NFC_DBG("Got ATQC:"); - NFC_DBG_BLOCK(ac_buffer_dump(pResp);) - - while (ac_buffer_reader_readable(pResp) > 0) { - if (ac_buffer_reader_readable(pResp) != 18 + 1) { // ATQC is 18 bytes, 1 byte for errors added by PN512 - NFC_WARN("Wrong length (%d bytes)", ac_buffer_reader_readable(pResp)); - pn512_anticollision_callback(pPN512, NFC_ERR_PROTOCOL); - return; - } - - // First byte is length, check that it's correct - uint8_t frame_length = ac_buffer_read_nu8(pResp); - uint8_t atqc0 = ac_buffer_read_nu8(pResp); - if ((frame_length != 18) || (atqc0 != 0x01)) { - NFC_WARN("Wrong ATQC frame"); - pn512_anticollision_callback(pPN512, NFC_ERR_PROTOCOL); - return; - } - - // Read NFCID2 - ac_buffer_read_n_bytes(pResp, pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].nfcF.nfcid2, 8); - - // Discard padding bytes - ac_buffer_read_n_skip(pResp, 8); - - // Read error register - uint8_t err_reg = ac_buffer_read_nu8(pResp); - if (err_reg & 0x1f) { - // Error within this time slot, skip - continue; - } - - //Populate tech accordingly - memset(&pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].type, 0, sizeof(nfc_tech_t)); - if ( - (pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].nfcF.nfcid2[0] == 0x01) - && (pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].nfcF.nfcid2[1] == 0xFE) - ) { - // NFC-DEP supported - pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].type.nfc_nfc_dep_f_212 = 1; - } else { - // Type 3 supported - pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].type.nfc_type3 = 1; - } - pPN512->transceiver.active_tech = pPN512->transceiver.remote_targets[pPN512->transceiver.remote_targets_count].type; - pPN512->transceiver.remote_targets_count++; - - // Only continue if we can have more targets - if (!pPN512->config.options.bail_at_first_target - && (pPN512->transceiver.remote_targets_count < MUNFC_MAX_REMOTE_TARGETS)) { - continue; - } - break; - } - - pn512_initiator_felica_anticollision_complete(pPN512); -} - -void pn512_initiator_felica_anticollision_complete(pn512_t *pPN512) -{ - pn512_anticollision_callback(pPN512, NFC_OK); -} - -void pn512_poll_setup(pn512_t *pPN512) -{ - bool target = pPN512->config.targets.nfc_type2 - || pPN512->config.targets.nfc_type3 - || pPN512->config.targets.nfc_iso_dep_a - || pPN512->config.targets.nfc_nfc_dep_a - || pPN512->config.targets.nfc_nfc_dep_f_212 - || pPN512->config.targets.nfc_nfc_dep_f_424; - -// No need for initiator-specific configuration at this stage, but keep this just in case -// bool initiator = pPN512->config.initiators.nfc_type1 -// || pPN512->config.initiators.nfc_type2 -// || pPN512->config.initiators.nfc_type3 -// || pPN512->config.initiators.nfc_iso_dep_a -// || pPN512->config.initiators.nfc_nfc_dep_a -// || pPN512->config.initiators.nfc_nfc_dep_f_212 -// || pPN512->config.initiators.nfc_nfc_dep_f_424; - - if (target) { - NFC_DBG("Configure anticoll/polling response"); - //Setup ATQA, SAK and Felica polling response - pn512_fifo_clear(pPN512); - - ac_buffer_builder_t *pDataCfgBldr = &pPN512->readBufBldr; - ac_buffer_builder_reset(pDataCfgBldr); - - //Write ATQA - ac_buffer_builder_write_nu8(pDataCfgBldr, 0x04); - ac_buffer_builder_write_nu8(pDataCfgBldr, 0x00); - - //Write NFCID1 (0s as it will be randomly generated) - first byte will be set to 0x08 by HW according to NFC-IP1 - for (int i = 0; i < 3; i++) { - ac_buffer_builder_write_nu8(pDataCfgBldr, 0x00); - } - - //Write SAK - uint8_t sak = 0x00; //Default SAK (UID complete) - if (pPN512->config.targets.nfc_iso_dep_a) { - sak |= 0x20; //This target is ISO-14443A-4 compliant - } - if (pPN512->config.targets.nfc_nfc_dep_a) { - sak |= 0x40; //This target is NFC-IP1 compliant - } - ac_buffer_builder_write_nu8(pDataCfgBldr, sak); - - //Write NFCID2 (xx 0xfe according to NFC-IP1 and 0s as 6 bytes will be randomly generated) - if (pPN512->config.targets.nfc_nfc_dep_f_212 || pPN512->config.targets.nfc_nfc_dep_f_424) { - //Byte 1 is 0x01 if supporting NFC-IP1 - ac_buffer_builder_write_nu8(pDataCfgBldr, 0x01); - } else if (pPN512->config.targets.nfc_type3) { //NFC-IP will have priority over type 3 tag emulation - //Byte 1 is 0x02 if supporting Type 3 tag platform - ac_buffer_builder_write_nu8(pDataCfgBldr, 0x02); - } else { - ac_buffer_builder_write_nu8(pDataCfgBldr, 0x00); - } - ac_buffer_builder_write_nu8(pDataCfgBldr, 0xFE); - - for (int i = 0; i < 6; i++) { - ac_buffer_builder_write_nu8(pDataCfgBldr, 0x00); - } - - //2 PAD0 bytes (Felica spec) - this would code the manufacturer + IC code (0xFFFF for NFC-IP1 tags) - ac_buffer_builder_write_nu8(pDataCfgBldr, 0xFF); - ac_buffer_builder_write_nu8(pDataCfgBldr, 0xFF); - - //3 PAD1 bytes - ac_buffer_builder_write_nu8(pDataCfgBldr, 0x00); - ac_buffer_builder_write_nu8(pDataCfgBldr, 0x00); - ac_buffer_builder_write_nu8(pDataCfgBldr, 0x00); - - if (!(pPN512->config.targets.nfc_nfc_dep_f_212 || pPN512->config.targets.nfc_nfc_dep_f_424) - && pPN512->config.targets.nfc_type3) { - ac_buffer_builder_write_nu8(pDataCfgBldr, 0x01); //MRTI Check - ac_buffer_builder_write_nu8(pDataCfgBldr, 0x01); //MRTI Update - } else { - ac_buffer_builder_write_nu8(pDataCfgBldr, 0x00); - ac_buffer_builder_write_nu8(pDataCfgBldr, 0x00); - } - - //1 PAD2 byte - ac_buffer_builder_write_nu8(pDataCfgBldr, 0x00); - - //2 system code bytes - if (!(pPN512->config.targets.nfc_nfc_dep_f_212 || pPN512->config.targets.nfc_nfc_dep_f_424) - && pPN512->config.targets.nfc_type3) { - ac_buffer_builder_write_nu8(pDataCfgBldr, 0x12); - ac_buffer_builder_write_nu8(pDataCfgBldr, 0xFC); - } else { - ac_buffer_builder_write_nu8(pDataCfgBldr, 0xFF); //Wildcard system code - ac_buffer_builder_write_nu8(pDataCfgBldr, 0xFF); - } - - //Write NFCID3 - ac_buffer_builder_write_nu8(pDataCfgBldr, 0x00); - - pn512_fifo_write(pPN512, ac_buffer_builder_buffer(pDataCfgBldr)); - - pn512_cmd_exec(pPN512, PN512_CMD_CONFIG); - pn512_cmd_wait_idle(pPN512, -1); - - NFC_DBG("Overwrite NFCIDs with random numbers"); - - //Overwrite NFCIDs with random numbers - pn512_cmd_exec(pPN512, PN512_CMD_RNDIDG); - pn512_cmd_wait_idle(pPN512, -1); - } -} - -static void pn512_poll_iteration(pn512_t *pPN512, nfc_err_t ret); -static void pn512_poll_delay_complete(uint32_t events, void *pUserData) -{ - pn512_t *pPN512 = (pn512_t *) pUserData; - - if (events & EVENT_ABORTED) { - pn512_poll_callback(pPN512, NFC_ERR_ABORTED); - return; - } - - pn512_poll_iteration(pPN512, NFC_OK); -} - -static void pn512_poll_delay(pn512_t *pPN512, uint32_t timeout) -{ - task_init(&pPN512->transceiver.task, EVENT_TIMEOUT, timeout, pn512_poll_delay_complete, pPN512); - nfc_scheduler_queue_task(&pPN512->transceiver.scheduler, &pPN512->transceiver.task); -} - -void pn512_poll_iteration(pn512_t *pPN512, nfc_err_t ret) -{ - do { - if (pPN512->poll.state == pn512_polling_state_start_listening) { - NFC_DBG("pn512_polling_state_start_listening"); - // Start with listening - if (!pn512_config_target(pPN512)) { - // Otherwise switch to next step - pPN512->poll.state = pn512_polling_state_start_polling; - continue; - } - - pPN512->poll.state = pn512_polling_state_listen_wait_for_remote_field; - - // Shortcut if target is halted (means RF field is still here) - if (pn512_register_read(pPN512, PN512_REG_MIFNFC) & 0x04) { - continue; - } - - // Fix for PN512 bug that sometimes detects its own RF field - // if(pPN512->rf_on) - { - //Switch RF field off - pn512_rf_field_switch_off(pPN512); - NFC_DBG("RF field switched off"); - } - - NFC_DBG("Target anticollision"); - - bool iso14443a = pPN512->config.targets.nfc_type2 || pPN512->config.targets.nfc_iso_dep_a || pPN512->config.targets.nfc_nfc_dep_a; - bool felica = pPN512->config.targets.nfc_type3 || pPN512->config.targets.nfc_nfc_dep_f_212 || pPN512->config.targets.nfc_nfc_dep_f_424; - - NFC_DBG("Switch in target mode and set framing: ISO A: %s; Felica: %s", iso14443a ? "Yes" : "No", felica ? "Yes" : "No"); - - //Switch in target mode - if (iso14443a && felica) { - pn512_framing_set(pPN512, nfc_framing_target_mode_detector); - } else if (iso14443a) { - pn512_framing_set(pPN512, nfc_framing_target_a_106); - } else if (felica) { - pn512_framing_set(pPN512, nfc_framing_target_f_212); - } - - pn512_rf_field_wait_for_external(pPN512, pPN512->config.options.listen_for, pn512_poll_iteration); - return; - } - - if (pPN512->poll.state == pn512_polling_state_listen_wait_for_remote_field) { - NFC_DBG("pn512_polling_state_listen_wait_for_remote_field"); - - if (!pn512_config_target(pPN512)) { - // Otherwise switch to next step - pPN512->poll.state = pn512_polling_state_start_listening; - continue; - } - - if (ret == NFC_ERR_TIMEOUT) { - // Continue polling - pPN512->poll.state = pn512_polling_state_start_polling; - continue; - } - - if (ret) { - pn512_poll_callback(pPN512, ret); - return; - } - - pPN512->poll.state = pn512_polling_state_listen_anticollision; - - pn512_target_anticollision(pPN512, pn512_poll_iteration); - return; - } - - if (pPN512->poll.state == pn512_polling_state_listen_anticollision) { - NFC_DBG("pn512_polling_state_listen_anticollision"); - - if (ret == NFC_ERR_FIELD) { - // This means that a remote field was dropped - give it another chance - pPN512->poll.state = pn512_polling_state_listen_wait_for_remote_field; - pn512_rf_field_switch_off(pPN512); - pn512_rf_field_wait_for_external(pPN512, pPN512->config.options.listen_for, pn512_poll_iteration); - return; - } - - if (ret) { - pn512_poll_callback(pPN512, ret); - return; - } - - // Be safe, not sure what the framing is - pPN512->framing = nfc_framing_unknown; - - pn512_poll_callback(pPN512, NFC_OK); - return; - } - - if (pPN512->poll.state == pn512_polling_state_start_polling) { - NFC_DBG("pn512_polling_state_start_polling"); - - if (!pn512_config_initiator(pPN512)) { - // Otherwise switch to next step - pPN512->poll.state = pn512_polling_state_start_listening; - continue; - } - - // Try to activate RF field - pPN512->poll.state = pn512_polling_state_rf_collision_avoidance; - - pn512_rf_field_nfcip1_rf_collision_avoidance(pPN512, pn512_poll_iteration); - return; - } - - if (pPN512->poll.state == pn512_polling_state_rf_collision_avoidance) { - NFC_DBG("pn512_polling_state_rf_collision_avoidance"); - - if (ret) { - pn512_poll_callback(pPN512, ret); - return; - } - - NFC_DBG("Own RF field is %s", pPN512->rf_on ? "on" : "off"); - - if (!pPN512->rf_on) { - // Go back to listening, target framing is still valid so no need to reset it - pPN512->poll.state = pn512_polling_state_listen_wait_for_remote_field; - continue; - } - - pPN512->poll.state = pn512_polling_state_polling_nfc_a_start; - } - - if (pPN512->poll.state == pn512_polling_state_polling_nfc_a_start) { - NFC_DBG("pn512_polling_state_polling_nfc_a_start"); - - //Check if ISO A is needed - bool nfc_a = pPN512->config.initiators.nfc_type2 || pPN512->config.initiators.nfc_iso_dep_a || pPN512->config.initiators.nfc_nfc_dep_a; //We do not support type 1 card emulation so irrelevant - if (!nfc_a) { - // Continue with NFC B - pPN512->poll.state = pn512_polling_state_polling_nfc_b_start; - continue; - } - - pPN512->transceiver.initiator_ntarget = true; - pn512_framing_set(pPN512, nfc_framing_initiator_a_106); - - pPN512->poll.state = pn512_polling_state_polling_nfc_a_gt; - pn512_poll_delay(pPN512, 10 + 5); // Guard time for ISO A is 5 ms - return; - } - - if (pPN512->poll.state == pn512_polling_state_polling_nfc_a_gt) { - NFC_DBG("pn512_polling_state_polling_nfc_a_gt"); - - // Start anticollision - pPN512->poll.state = pn512_polling_state_polling_nfc_a_anticollision; - pn512_initiator_isoa_anticollision(pPN512, pn512_poll_iteration); - return; - } - - if (pPN512->poll.state == pn512_polling_state_polling_nfc_a_anticollision) { - NFC_DBG("pn512_polling_state_polling_nfc_a_anticollision"); - - if (ret == NFC_ERR_NOPEER) { - NFC_DBG("Not found"); - // Continue with NFC B - pPN512->poll.state = pn512_polling_state_polling_nfc_b_start; - continue; - } - - if ((ret == NFC_OK) && (pPN512->config.options.bail_at_first_tech || (pPN512->transceiver.remote_targets_count == MUNFC_MAX_REMOTE_TARGETS))) { - // At least one target found, exit polling loop - pn512_poll_callback(pPN512, NFC_OK); - return; - } - - if (ret == NFC_ERR_ABORTED) { - pn512_poll_callback(pPN512, ret); - return; - } - - // Continue with NFC B - pPN512->poll.state = pn512_polling_state_polling_nfc_b_start; - continue; - } - - if (pPN512->poll.state == pn512_polling_state_polling_nfc_b_start) { - NFC_DBG("pn512_polling_state_polling_nfc_b_start"); - - //Check if ISO B is needed - bool nfc_b = pPN512->config.initiators.nfc_iso_dep_b; - if (!nfc_b) { - // Continue with NFC F - pPN512->poll.state = pn512_polling_state_polling_nfc_f_start; - continue; - } - - pPN512->transceiver.initiator_ntarget = true; - pn512_framing_set(pPN512, nfc_framing_initiator_b_106); - - pPN512->poll.state = pn512_polling_state_polling_nfc_b_gt; - pn512_poll_delay(pPN512, 10 + 5); // Guard time for ISO B is 5 ms - return; - } - - if (pPN512->poll.state == pn512_polling_state_polling_nfc_b_gt) { - NFC_DBG("pn512_polling_state_polling_nfc_b_gt"); - - // Start anticollision - pPN512->poll.state = pn512_polling_state_polling_nfc_b_anticollision; - pn512_initiator_isob_anticollision(pPN512, pn512_poll_iteration); - return; - } - - if (pPN512->poll.state == pn512_polling_state_polling_nfc_b_anticollision) { - NFC_DBG("pn512_polling_state_polling_nfc_b_anticollision"); - - if (ret == NFC_ERR_NOPEER) { - NFC_DBG("Not found"); - // Continue with NFC F - pPN512->poll.state = pn512_polling_state_polling_nfc_f_start; - continue; - } - - if ((ret == NFC_OK) - && (pPN512->config.options.bail_at_first_tech - || (pPN512->transceiver.remote_targets_count - == MUNFC_MAX_REMOTE_TARGETS))) { - // At least one target found, exit polling loop - pn512_poll_callback(pPN512, NFC_OK); - return; - } - - if (ret == NFC_ERR_ABORTED) { - pn512_poll_callback(pPN512, ret); - return; - } - - // Continue with NFC F - pPN512->poll.state = pn512_polling_state_polling_nfc_f_start; - continue; - } - - if (pPN512->poll.state == pn512_polling_state_polling_nfc_f_start) { - NFC_DBG("pn512_polling_state_polling_nfc_f_start"); - - //Check if Felica is needed - bool nfc_f = pPN512->config.initiators.nfc_type3 || pPN512->config.initiators.nfc_nfc_dep_f_212; - if (!nfc_f) { - // Wrap up - pPN512->poll.state = pn512_polling_state_finish_polling; - continue; - } - - pPN512->transceiver.initiator_ntarget = true; - pn512_framing_set(pPN512, nfc_framing_initiator_f_212); - - pPN512->poll.state = pn512_polling_state_polling_nfc_f_gt; - pn512_poll_delay(pPN512, 20); // Guard time for Felica is 20 ms - return; - } - - if (pPN512->poll.state == pn512_polling_state_polling_nfc_f_gt) { - NFC_DBG("pn512_polling_state_polling_nfc_f_gt"); - - // Start anticollision - pPN512->poll.state = pn512_polling_state_polling_nfc_f_anticollision; - pn512_initiator_felica_anticollision(pPN512, pn512_poll_iteration); - return; - } - - if (pPN512->poll.state == pn512_polling_state_polling_nfc_f_anticollision) { - NFC_DBG("pn512_polling_state_polling_nfc_f_anticollision"); - - if (ret == NFC_ERR_NOPEER) { - NFC_DBG("Not found"); - // Resolve polling - pPN512->poll.state = pn512_polling_state_finish_polling; - continue; - } - - if ((ret == NFC_OK) && (pPN512->config.options.bail_at_first_tech || (pPN512->transceiver.remote_targets_count == MUNFC_MAX_REMOTE_TARGETS))) { - // At least one target found, exit polling loop - pn512_poll_callback(pPN512, NFC_OK); - return; - } - - if (ret == NFC_ERR_ABORTED) { - pn512_poll_callback(pPN512, ret); - return; - } - - // Resolve polling - pPN512->poll.state = pn512_polling_state_finish_polling; - continue; - } - - if (pPN512->poll.state == pn512_polling_state_finish_polling) { - if (pPN512->transceiver.remote_targets_count > 0) { - pn512_poll_callback(pPN512, NFC_OK); - } else { - pn512_poll_callback(pPN512, NFC_ERR_NOPEER); - } - return; - } - - } while (true); -} - -// Main polling loop function -void pn512_poll_hw(pn512_t *pPN512, pn512_cb_t cb) -{ - nfc_transceiver_t *pTransceiver = (nfc_transceiver_t *)pPN512; - pPN512->poll.cb = cb; - - //Reset active state - pTransceiver->initiator_ntarget = false; - memset(&pTransceiver->active_tech, 0, sizeof(nfc_tech_t)); - - //Reset discovered targets - pTransceiver->remote_targets_count = 0; - - //Initialize state machine - pPN512->poll.state = pn512_polling_state_start_listening; - - if (!pn512_config_target(pPN512) && !pn512_config_initiator(pPN512)) { - pn512_poll_callback(pPN512, NFC_ERR_PARAMS); - return; - } - - //First iteration - pn512_poll_iteration(pPN512, NFC_OK); -} diff --git a/features/nfc/stack/transceiver/pn512/pn512_poll.h b/features/nfc/stack/transceiver/pn512/pn512_poll.h deleted file mode 100644 index a048912..0000000 --- a/features/nfc/stack/transceiver/pn512/pn512_poll.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2014-2018, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * 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. - */ -/** - * \file pn512_poll.h - * \copyright Copyright (c) ARM Ltd 2014 - * \author Donatien Garnier - */ - -#ifndef PN512_POLL_H_ -#define PN512_POLL_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "stack/nfc_common.h" - -void pn512_poll_setup(pn512_t *pPN512); -void pn512_poll_hw(pn512_t *pPN512, pn512_cb_t cb); - - -#ifdef __cplusplus -} -#endif - -#endif /* PN512_POLL_H_ */ diff --git a/features/nfc/stack/transceiver/pn512/pn512_registers.c b/features/nfc/stack/transceiver/pn512/pn512_registers.c deleted file mode 100644 index a751dff..0000000 --- a/features/nfc/stack/transceiver/pn512/pn512_registers.c +++ /dev/null @@ -1,153 +0,0 @@ - -/* - * Copyright (c) 2013-2018, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * 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. - */ -/** - * \file pn512_registers.c - * \copyright Copyright (c) ARM Ltd 2013 - * \author Donatien Garnier - * \details Access to PN512 registers - */ - - -#define __DEBUG__ 0 -#ifndef __MODULE__ -#define __MODULE__ "pn512_registers.c" -#endif -#include "stack/nfc_errors.h" - -#include "pn512_registers.h" -#include "pn512_hw.h" -#include "pn512.h" - -#define REGISTER_PAGE(x) ((x)>>4) -#define REGISTER_ADDR(x) ((x)&0xF) - -/** \addtogroup PN512 - * \internal - * @{ - * \name Registers - * @{ - */ - -static void pn512_register_switch_page_intl(pn512_t *pPN512, uint8_t page); - -/** \internal Initialize underlying pn512_registers_t structure - * \param pPN512 pointer to pn512_t structure - */ -void pn512_registers_init(pn512_t *pPN512) -{ - pPN512->registers.registers_page = 0; -} - -#define PN512_CFG_INIT_LEN 9 -static const uint8_t PN512_CFG_INIT_REGS[] = { - PN512_REG_DIVIEN, - PN512_REG_MODE, - PN512_REG_GSNOFF, - PN512_REG_RFCFG, - PN512_REG_CWGSP, - PN512_REG_MIFNFC, - PN512_REG_FELNFC2, - PN512_REG_RXSEL, - PN512_REG_TYPEB -}; -static const uint8_t PN512_CFG_INIT_VALS[] = { - 0x80, - 0x3F, - 0xF2, - 0x68, - 0x3F, - 0x62, - 0x80, - 0x84, - 0x00 -}; //Timer: For now max prescaler, max reload value - -/** \internal Switch to known (0) registers page, reset registers state - * \param pPN512 pointer to pn512_t structure - */ -void pn512_registers_reset(pn512_t *pPN512) -{ - pn512_register_switch_page_intl(pPN512, 0); - for (int i = 0; i < PN512_CFG_INIT_LEN; i++) { - pn512_register_write(pPN512, PN512_CFG_INIT_REGS[i], PN512_CFG_INIT_VALS[i]); - } -} - -/** \internal Write register - * \param pPN512 pointer to pn512_t structure - * \param address register address - * \param data value to write in register - */ -void pn512_register_write(pn512_t *pPN512, uint8_t address, uint8_t data) -{ - NFC_DBG("Write [%02x] << %02x", address, data); - if (REGISTER_PAGE(address) != pPN512->registers.registers_page) { - pn512_register_switch_page_intl(pPN512, REGISTER_PAGE(address)); - } - address = REGISTER_ADDR(address); - pn512_hw_write(pPN512, address, &data, 1); -} - -/** \internal Read register - * \param pPN512 pointer to pn512_t structure - * \param address register address - * \return data value read from register - */ -uint8_t pn512_register_read(pn512_t *pPN512, uint8_t address) -{ - uint8_t data; - NFC_DBG_BLOCK( - uint8_t __dbg_addr; - __dbg_addr = address; //FIXME - ) - if (REGISTER_PAGE(address) != pPN512->registers.registers_page) { - pn512_register_switch_page_intl(pPN512, REGISTER_PAGE(address)); - } - address = REGISTER_ADDR(address); - pn512_hw_read(pPN512, address, &data, 1); - NFC_DBG("Read [%02x] >> %02x", __dbg_addr, data); - return data; -} - -void pn512_register_switch_page(pn512_t *pPN512, uint8_t address) -{ - if (REGISTER_PAGE(address) != pPN512->registers.registers_page) { - pn512_register_switch_page_intl(pPN512, REGISTER_PAGE(address)); - } -} - -/** \internal Switch registers page - * \param pPN512 pointer to pn512_t structure - * \param page registers page - */ -void pn512_register_switch_page_intl(pn512_t *pPN512, uint8_t page) -{ - uint8_t pageRegValue; - pageRegValue = (1 << 7) | page; - - pn512_hw_write(pPN512, PN512_REG_PAGE, &pageRegValue, 1); - - pPN512->registers.registers_page = page; -} - - - -/** - * @} - * @} - * */ diff --git a/features/nfc/stack/transceiver/pn512/pn512_registers.h b/features/nfc/stack/transceiver/pn512/pn512_registers.h deleted file mode 100644 index 4d3cf49..0000000 --- a/features/nfc/stack/transceiver/pn512/pn512_registers.h +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (c) 2013-2018, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * 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. - */ -/** - * \file pn512_registers.h - * \copyright Copyright (c) ARM Ltd 2013 - * \author Donatien Garnier - */ - -#ifndef PN512_REGISTERS_H_ -#define PN512_REGISTERS_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "stack/nfc_common.h" -#include "pn512.h" - -//Page 0 - Command and Status -#define PN512_REG_PAGE 0x00 //Selects the register page -#define PN512_REG_COMMAND 0x01 //Starts and stops command execution -#define PN512_REG_COMIEN 0x02 //Controls bits to enable and disable the passing of Interrupt Requests -#define PN512_REG_DIVIEN 0x03 //Controls bits to enable and disable the passing of Interrupt Requests -#define PN512_REG_COMIRQ 0x04 //Contains Interrupt Request bits -#define PN512_REG_DIVIRQ 0x05 //Contains Interrupt Request bits -#define PN512_REG_ERROR 0x06 //Error bits showing the error status of the last command executed -#define PN512_REG_STATUS1 0x07 //Contains status bits for communication -#define PN512_REG_STATUS2 0x08 //Contains status bits of the receiver and transmitter -#define PN512_REG_FIFODATA 0x09 //In- and output of 64 byte FIFO-buffer -#define PN512_REG_FIFOLEVEL 0x0A //Indicates the number of bytes stored in the FIFO -#define PN512_REG_WATERLEVEL 0x0B //Defines the level for FIFO under- and overflow warning -#define PN512_REG_CONTROL 0x0C //Contains miscellaneous Control Registers -#define PN512_REG_BITFRAMING 0x0D //Adjustments for bit oriented frames -#define PN512_REG_COLL 0x0E //Bit position of the first bit collision detected on the RF-interface - -//Page 1 - Command -//#define PN512_REG_PAGE 0x10 //Selects the register page -#define PN512_REG_MODE 0x11 //Defines general modes for transmitting and receiving -#define PN512_REG_TXMODE 0x12 //Defines the data rate and framing during transmission -#define PN512_REG_RXMODE 0x13 //Defines the data rate and framing during receiving -#define PN512_REG_TXCONTROL 0x14 //Controls the logical behavior of the antenna driver pins TX1 and TX2 -#define PN512_REG_TXAUTO 0x15 //Controls the setting of the antenna drivers -#define PN512_REG_TXSEL 0x16 //Selects the internal sources for the antenna driver -#define PN512_REG_RXSEL 0x17 //Selects internal receiver settings -#define PN512_REG_RXTHRESHOLD 0x18 //Selects thresholds for the bit decoder -#define PN512_REG_DEMOD 0x19 //Defines demodulator settings -#define PN512_REG_FELNFC1 0x1A //Defines the length of the valid range for the receive package -#define PN512_REG_FELNFC2 0x1B //Defines the length of the valid range for the receive package -#define PN512_REG_MIFNFC 0x1C //Controls the communication in ISO/IEC 14443/MIFARE and NFC target mode at 106 kbit -#define PN512_REG_MANUALRCV 0x1D //Allows manual fine tuning of the internal receiver -#define PN512_REG_TYPEB 0x1E //Configure the ISO/IEC 14443 type B -#define PN512_REG_SERIALSPEED 0x1F //Selects the speed of the serial UART interface - -//Page 2 - CFG -//#define PN512_REG_PAGE 0x20 //Selects the register page -#define PN512_REG_CRCRESULT_MSB 0x21 //Shows the actual MSB and LSB values of the CRC calculation -#define PN512_REG_CRCRESULT_LSB 0x22 //Shows the actual MSB and LSB values of the CRC calculation -#define PN512_REG_GSNOFF 0x23 //Selects the conductance of the antenna driver pins TX1 and TX2 for modulation, when the driver is switched off -#define PN512_REG_MODWIDTH 0x24 //Controls the setting of the ModWidth -#define PN512_REG_TXBITPHASE 0x25 //Adjust the TX bit phase at 106 kbit -#define PN512_REG_RFCFG 0x26 //Configures the receiver gain and RF level -#define PN512_REG_GSNON 0x27 //Selects the conductance of the antenna driver pins TX1 and TX2 for modulation when the drivers are switched on -#define PN512_REG_CWGSP 0x28 //Selects the conductance of the antenna driver pins TX1 and TX2 for modulation during times of no modulation -#define PN512_REG_MODGSP 0x29 //Selects the conductance of the antenna driver pins TX1 and TX2 for modulation during modulation -#define PN512_REG_TMODE_TPRESCALERHIGH 0x2A //Defines settings for the internal timer -#define PN512_REG_TPRESCALERLOW 0x2B //Defines settings for the internal timer -#define PN512_REG_TRELOADHIGH 0x2C //Describes the 16-bit timer reload value -#define PN512_REG_TRELOADLOW 0x2D //Describes the 16-bit timer reload value -#define PN512_REG_TCOUNTERVALHIGH 0x2E //Shows the 16-bit actual timer value -#define PN512_REG_TCOUNTERVALLOW 0x2F //Shows the 16-bit actual timer value - -//Page 3 - TestRegister -//#define PN512_REG_PAGE 0x30 //Selects the register page -#define PN512_REG_TESTSEL1 0x31 //General test signal configuration -#define PN512_REG_TESTSEL2 0x32 //General test signal configuration and PRBS control -#define PN512_REG_TESTPINEN 0x33 //Enables pin output driver on 8-bit parallel bus (Note: For serial interfaces only) -#define PN512_REG_TESTPINVALUE 0x34 //Defines the values for the 8-bit parallel bus when it is used as I/O bus -#define PN512_REG_TESTBUS 0x35 //Shows the status of the internal testbus -#define PN512_REG_AUTOTEST 0x36 //Controls the digital selftest -#define PN512_REG_VERSION 0x37 //Shows the version -#define PN512_REG_ANALOGTEST 0x38 //Controls the pins AUX1 and AUX2 -#define PN512_REG_TESTDAC1 0x39 //Defines the test value for the TestDAC1 -#define PN512_REG_TESTDAC2 0x3A //Defines the test value for the TestDAC2 -#define PN512_REG_TESTADC 0x3B //Shows the actual value of ADC I and Q - - -void pn512_registers_init(pn512_t *pPN512); -void pn512_registers_reset(pn512_t *pPN512); - -void pn512_register_write(pn512_t *pPN512, uint8_t address, uint8_t data); -uint8_t pn512_register_read(pn512_t *pPN512, uint8_t address); - -void pn512_register_switch_page(pn512_t *pPN512, uint8_t address); - -#ifdef __cplusplus -} -#endif - -#endif /* PN512_REGISTERS_H_ */ diff --git a/features/nfc/stack/transceiver/pn512/pn512_rf.c b/features/nfc/stack/transceiver/pn512/pn512_rf.c deleted file mode 100644 index bbee18f..0000000 --- a/features/nfc/stack/transceiver/pn512/pn512_rf.c +++ /dev/null @@ -1,329 +0,0 @@ -/* - * Copyright (c) 2014-2018, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * 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. - */ -/** - * \file pn512_rf.c - * \copyright Copyright (c) ARM Ltd 2014 - * \author Donatien Garnier - */ - -#define __DEBUG__ 0 -#ifndef __MODULE__ -#define __MODULE__ "pn512_rf.c" -#endif - -#include "stack/nfc_errors.h" - -#include "pn512_callback.h" -#include "pn512_rf.h" -#include "pn512_registers.h" -#include "pn512_timer.h" -#include "pn512_irq.h" -#include "pn512.h" -#include "pn512_internal.h" - -#include "stdlib.h" //For rand() func - -#define PN512_FRAMING_REGS 6 -static const uint8_t framing_registers[] = { PN512_REG_MODE, PN512_REG_TXMODE, PN512_REG_RXMODE, PN512_REG_MODGSP, PN512_REG_RXTHRESHOLD, PN512_REG_MODWIDTH }; -static const uint8_t framing_registers_mode_detector[] = { 0x3B, 0x80, 0x80, 0x3F, 0x55, 0x26 }; -static const uint8_t framing_registers_initiator_iso14443a_106k[] = { 0x3D, 0x80, 0x80, 0x3F, 0x55, 0x26 }; -static const uint8_t framing_registers_initiator_iso14443b_106k[] = { 0x3F, 0x83, 0x83, 0x04, 0x50, 0x26 }; -static const uint8_t framing_registers_target_iso14443a_106k[] = { 0x3D, 0x80, 0x80, 0x3F, 0x55, 0x26 }; -static const uint8_t framing_registers_felica_212k[] = { 0x3A, 0x92, 0x92, 0x12, 0x55, 0x15 }; -static const uint8_t framing_registers_felica_414k[] = { 0x3A, 0xA2, 0xA2, 0x12, 0x55, 0x0A }; - -nfc_err_t pn512_framing_set(pn512_t *pPN512, nfc_framing_t framing) -{ - if (framing == pPN512->framing) { //No need to do anything - return NFC_OK; - } - - NFC_DBG("Switching to %u", framing); - - const uint8_t *framing_registers_values; - switch (framing) { - case nfc_framing_target_mode_detector: - framing_registers_values = framing_registers_mode_detector; - break; - case nfc_framing_target_a_106: - framing_registers_values = framing_registers_target_iso14443a_106k; - break; - case nfc_framing_initiator_a_106: - framing_registers_values = framing_registers_initiator_iso14443a_106k; - break; - case nfc_framing_initiator_b_106: - framing_registers_values = framing_registers_initiator_iso14443b_106k; - break; - case nfc_framing_target_f_212: - case nfc_framing_initiator_f_212: - framing_registers_values = framing_registers_felica_212k; - break; - case nfc_framing_target_f_424: - case nfc_framing_initiator_f_424: - framing_registers_values = framing_registers_felica_414k; - break; - default: - return NFC_ERR_UNSUPPORTED; - } - - for (int i = 0; i < PN512_FRAMING_REGS; i++) { - pn512_register_write(pPN512, framing_registers[i], framing_registers_values[i]); - } - - pPN512->framing = framing; - pPN512->crc.out = true; - pPN512->crc.in = true; - - //TODO initiator: PN512_REG_MODGSP - - switch (pPN512->framing) { - case nfc_framing_initiator_a_106: - case nfc_framing_initiator_b_106: - case nfc_framing_initiator_f_212: - case nfc_framing_initiator_f_424: - pn512_register_write(pPN512, PN512_REG_CONTROL, 0x10); //Act as initiator - break; - case nfc_framing_target_mode_detector: - case nfc_framing_target_a_106: - case nfc_framing_target_f_212: - case nfc_framing_target_f_424: - pn512_register_write(pPN512, PN512_REG_CONTROL, 0x00); //Act as target - break; - default: - return NFC_ERR_UNSUPPORTED; - } -#if 1 - if ( - pPN512->framing == nfc_framing_initiator_a_106 - //|| (pPN512->framing == pn512_framing_target_iso14443a_106k) - ) { - //Enable 100% ASK Modulation - pn512_register_write(pPN512, PN512_REG_TXAUTO, pn512_register_read(pPN512, PN512_REG_TXAUTO) | 0x40); - } else { - pn512_register_write(pPN512, PN512_REG_TXAUTO, pn512_register_read(pPN512, PN512_REG_TXAUTO) & (~0x40)); - } -#endif - return NFC_OK; -} - -nfc_err_t pn512_framing_crc_set(pn512_t *pPN512, bool out, bool in) -{ - const uint8_t *framing_registers_values; - switch (pPN512->framing) { - case nfc_framing_target_mode_detector: - framing_registers_values = framing_registers_mode_detector; - break; - case nfc_framing_target_a_106: - framing_registers_values = framing_registers_target_iso14443a_106k; - break; - case nfc_framing_initiator_a_106: - framing_registers_values = framing_registers_initiator_iso14443a_106k; - break; - case nfc_framing_initiator_b_106: - framing_registers_values = framing_registers_initiator_iso14443b_106k; - break; - case nfc_framing_target_f_212: - case nfc_framing_initiator_f_212: - framing_registers_values = framing_registers_felica_212k; - break; - case nfc_framing_target_f_424: - case nfc_framing_initiator_f_424: - framing_registers_values = framing_registers_felica_414k; - break; - default: - return NFC_ERR_UNSUPPORTED; - } - - if (pPN512->crc.out != out) { - pn512_register_write(pPN512, framing_registers[1], (framing_registers_values[1] & 0x7F) | (out ? 0x80 : 0x00)); //TXMODE - pPN512->crc.out = out; - } - if (pPN512->crc.in != in) { - pn512_register_write(pPN512, framing_registers[2], (framing_registers_values[2] & 0x7F) | (in ? 0x80 : 0x00)); //RXMODE - pPN512->crc.in = in; - } - - return NFC_OK; -} - -nfc_err_t pn512_framing_rx_multiple_enable(pn512_t *pPN512) -{ - const uint8_t *framing_registers_values; - switch (pPN512->framing) { - case nfc_framing_target_mode_detector: - framing_registers_values = framing_registers_mode_detector; - break; - case nfc_framing_target_a_106: - framing_registers_values = framing_registers_target_iso14443a_106k; - break; - case nfc_framing_initiator_a_106: - framing_registers_values = framing_registers_initiator_iso14443a_106k; - break; - case nfc_framing_initiator_b_106: - framing_registers_values = framing_registers_initiator_iso14443b_106k; - break; - case nfc_framing_target_f_212: - case nfc_framing_initiator_f_212: - framing_registers_values = framing_registers_felica_212k; - break; - case nfc_framing_target_f_424: - case nfc_framing_initiator_f_424: - framing_registers_values = framing_registers_felica_414k; - break; - default: - return NFC_ERR_UNSUPPORTED; - } - - pn512_register_write(pPN512, framing_registers[2], (framing_registers_values[2] & 0x7F) | (pPN512->crc.in ? 0x80 : 0x00) | 0x04); //RXMODE - - return NFC_OK; -} - -void pn512_rf_field_switch_off(pn512_t *pPN512) -{ - pn512_register_write(pPN512, PN512_REG_TXAUTO, 0x00); - pn512_register_write(pPN512, PN512_REG_TXCONTROL, 0x80); - pPN512->rf_on = false; -} - -void pn512_rf_field_nfcip1_rf_collision_avoidance_complete(uint32_t events, void *pUserData) -{ - pn512_t *pPN512 = (pn512_t *) pUserData; - - uint16_t irq_res = pn512_irq_get(pPN512); - - (void) events; - - pn512_timer_stop(pPN512); - pn512_timer_config(pPN512, false, 0, 0xffff); //Deactivate autostart - pn512_irq_set(pPN512, PN512_IRQ_NONE); - pn512_irq_clear(pPN512, PN512_IRQ_RF_ON | PN512_IRQ_TIMER); - - if (irq_res & PN512_IRQ_RF_ON) { - NFC_DBG("External field on"); - - //Clear TXAUTO register - pn512_register_write(pPN512, PN512_REG_TXAUTO, 0x00); - - pPN512->rf_on = false; //External field on - pn512_rf_callback(pPN512, NFC_OK); - return; - } - - //Has our RF field been switched on? - if (pn512_register_read(pPN512, PN512_REG_TXAUTO) & 0x40) { //InitialRFOn bit is cleared automatically, if the RF field is switched on - NFC_ERR("InitialRFOn bit still set"); - pn512_rf_callback(pPN512, NFC_ERR_UNKNOWN); - return; - } - - pPN512->rf_on = true; //Own field on and guard time ok - - NFC_DBG("RF field enabled"); - pn512_rf_callback(pPN512, NFC_OK); -} - -void pn512_rf_field_nfcip1_rf_collision_avoidance(pn512_t *pPN512, pn512_cb_t cb) -{ - pPN512->rf.cb = cb; - pn512_irq_clear(pPN512, PN512_IRQ_RF_ON | PN512_IRQ_TIMER); - - //If our field is switched on, Wait TIRFG according to NFC-IP1 = 5ms => 67800 clock edges = (3+1)*8475 - pn512_timer_config(pPN512, true, 3, 8475); - - pn512_irq_set(pPN512, PN512_IRQ_RF_ON /* External field switched on */ - | PN512_IRQ_TIMER /* Timer reached 0 */); - - //Try to enable RF field in compliance with NFC-IP1 - pn512_register_write(pPN512, PN512_REG_TXAUTO, 0x0F); - - //Is external RF Field already on? - if (pn512_register_read(pPN512, PN512_REG_STATUS1) & 0x4) { - NFC_DBG("External field already on"); - pPN512->rf_on = false; //External field on - - //Cancel - pn512_timer_stop(pPN512); - pn512_timer_config(pPN512, false, 0, 0xffff); //Deactivate autostart - pn512_irq_clear(pPN512, PN512_IRQ_RF_ON | PN512_IRQ_TIMER); - pn512_rf_callback(pPN512, NFC_OK); - return; - } - - //Queue task to process IRQ - task_init(&pPN512->transceiver.task, EVENT_HW_INTERRUPT | EVENT_TIMEOUT, -1, pn512_rf_field_nfcip1_rf_collision_avoidance_complete, pPN512); - nfc_scheduler_queue_task(&pPN512->transceiver.scheduler, &pPN512->transceiver.task); -} - -void pn512_rf_field_wait_for_external_complete_task(uint32_t events, void *pUserData) -{ - pn512_t *pPN512 = (pn512_t *) pUserData; - - NFC_DBG("%lu events", events); - - //Wake up PN512 - pn512_register_write(pPN512, PN512_REG_COMMAND, 0x00); - while (pn512_register_read(pPN512, PN512_REG_COMMAND) & 0x10); - - pn512_irq_set(pPN512, PN512_IRQ_NONE); - pn512_irq_clear(pPN512, PN512_IRQ_RF_ON); - - if (events & EVENT_ABORTED) { - pn512_rf_callback(pPN512, NFC_ERR_ABORTED); - return; - } - - if (events & EVENT_TIMEOUT) { - NFC_DBG("Timeout"); - pn512_rf_callback(pPN512, NFC_ERR_TIMEOUT); - return; - } - - NFC_DBG("On"); - pn512_rf_callback(pPN512, NFC_OK); -} - -void pn512_rf_field_wait_for_external(pn512_t *pPN512, int timeout, pn512_cb_t cb) -{ - pPN512->rf.cb = cb; - - pn512_irq_clear(pPN512, PN512_IRQ_RF_ON); - - NFC_DBG("Wait for RF field to come up (timeout %d)", timeout); - - //Is external RF Field already on? - pn512_irq_set(pPN512, PN512_IRQ_RF_ON /* External field switched on */); - if (pn512_register_read(pPN512, PN512_REG_STATUS1) & 0x4) { - NFC_DBG("RF field already on"); - pn512_irq_set(pPN512, PN512_IRQ_NONE); - pn512_irq_clear(pPN512, PN512_IRQ_RF_ON); - - pn512_rf_callback(pPN512, NFC_OK); - return; - } - - //Send PN512 to sleep mode - pn512_register_write(pPN512, PN512_REG_COMMAND, 0x30); //Receiver off + soft power down - - //Queue task to process IRQ - task_init(&pPN512->transceiver.task, EVENT_HW_INTERRUPT | EVENT_TIMEOUT, timeout, pn512_rf_field_wait_for_external_complete_task, pPN512); - nfc_scheduler_queue_task(&pPN512->transceiver.scheduler, &pPN512->transceiver.task); -} - - - - diff --git a/features/nfc/stack/transceiver/pn512/pn512_rf.h b/features/nfc/stack/transceiver/pn512/pn512_rf.h deleted file mode 100644 index 34d965a..0000000 --- a/features/nfc/stack/transceiver/pn512/pn512_rf.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2014-2018, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * 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. - */ -/** - * \file pn512_rf.h - * \copyright Copyright (c) ARM Ltd 2014 - * \author Donatien Garnier - */ - -#ifndef PN512_RF_H_ -#define PN512_RF_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "stack/nfc_common.h" -#include "pn512_types.h" -#include "pn512_callback.h" -#include "pn512.h" - -nfc_err_t pn512_framing_set(pn512_t *pPN512, nfc_framing_t framing); - -nfc_err_t pn512_framing_crc_set(pn512_t *pPN512, bool out, bool in); - -nfc_err_t pn512_framing_rx_multiple_enable(pn512_t *pPN512); - -#define PN512_FRAMING_IS_TARGET( framing ) ((framing) <= nfc_framing_target_f_424) - -void pn512_rf_field_switch_off(pn512_t *pPN512); - -void pn512_rf_field_nfcip1_rf_collision_avoidance(pn512_t *pPN512, pn512_cb_t cb); - -void pn512_rf_field_wait_for_external(pn512_t *pPN512, int timeout, pn512_cb_t cb); - - -#ifdef __cplusplus -} -#endif - -#endif /* PN512_RF_H_ */ diff --git a/features/nfc/stack/transceiver/pn512/pn512_timer.c b/features/nfc/stack/transceiver/pn512/pn512_timer.c deleted file mode 100644 index 60334a8..0000000 --- a/features/nfc/stack/transceiver/pn512/pn512_timer.c +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2014-2018, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * 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. - */ -/** - * \file pn512_timer.c - * \copyright Copyright (c) ARM Ltd 2014 - * \author Donatien Garnier - */ - -#include "stack/nfc_errors.h" - -#include "pn512_timer.h" -#include "pn512_registers.h" - -void pn512_timer_config(pn512_t *pPN512, bool autostart, uint16_t prescaler, uint16_t countdown_value) -{ - pn512_timer_stop(pPN512); //just in case... - - pn512_register_write(pPN512, PN512_REG_TRELOADLOW, countdown_value & 0xFF); - pn512_register_write(pPN512, PN512_REG_TRELOADHIGH, (countdown_value >> 8) & 0xFF); - - pn512_register_write(pPN512, PN512_REG_TPRESCALERLOW, prescaler & 0xFF); - pn512_register_write(pPN512, PN512_REG_TMODE_TPRESCALERHIGH, (autostart ? 0x80 : 0x00) | ((prescaler >> 8) & 0x0F)); -} - -void pn512_timer_start(pn512_t *pPN512) -{ - //The control register also contains the initiator bit that we must set correctly - switch (pPN512->framing) { - case nfc_framing_initiator_a_106: - case nfc_framing_initiator_f_212: - case nfc_framing_initiator_f_424: - pn512_register_write(pPN512, PN512_REG_CONTROL, 0x50); - break; - case nfc_framing_target_mode_detector: - case nfc_framing_target_a_106: - case nfc_framing_target_f_212: - case nfc_framing_target_f_424: - default: - pn512_register_write(pPN512, PN512_REG_CONTROL, 0x40); - break; - } -} - -void pn512_timer_stop(pn512_t *pPN512) -{ - //The control register also contains the initiator bit that we must set correctly - switch (pPN512->framing) { - case nfc_framing_initiator_a_106: - case nfc_framing_initiator_f_212: - case nfc_framing_initiator_f_424: - pn512_register_write(pPN512, PN512_REG_CONTROL, 0x90); - break; - case nfc_framing_target_mode_detector: - case nfc_framing_target_a_106: - case nfc_framing_target_f_212: - case nfc_framing_target_f_424: - default: - pn512_register_write(pPN512, PN512_REG_CONTROL, 0x80); - break; - } -} diff --git a/features/nfc/stack/transceiver/pn512/pn512_timer.h b/features/nfc/stack/transceiver/pn512/pn512_timer.h deleted file mode 100644 index ae85edd..0000000 --- a/features/nfc/stack/transceiver/pn512/pn512_timer.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2014-2018, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * 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. - */ -/** - * \file pn512_timer.h - * \copyright Copyright (c) ARM Ltd 2014 - * \author Donatien Garnier - */ - -#ifndef PN512_TIMER_H_ -#define PN512_TIMER_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "stack/nfc_common.h" -#include "pn512_types.h" - -void pn512_timer_config(pn512_t *pPN512, bool autostart, uint16_t prescaler, uint16_t countdown_value); - -void pn512_timer_start(pn512_t *pPN512); -void pn512_timer_stop(pn512_t *pPN512); - -#ifdef __cplusplus -} -#endif - -#endif /* PN512_TIMER_H_ */ diff --git a/features/nfc/stack/transceiver/pn512/pn512_transceive.c b/features/nfc/stack/transceiver/pn512/pn512_transceive.c deleted file mode 100644 index 304ae88..0000000 --- a/features/nfc/stack/transceiver/pn512/pn512_transceive.c +++ /dev/null @@ -1,441 +0,0 @@ -/* - * Copyright (c) 2014-2018, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * 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. - */ -/** - * \file pn512_transceive.c - * \copyright Copyright (c) ARM Ltd 2014 - * \author Donatien Garnier - */ - -#define __DEBUG__ 0 -#ifndef __MODULE__ -#define __MODULE__ "pn512_transceive.c" -#endif - -#include "stack/nfc_errors.h" - -#include "pn512.h" -#include "pn512_transceive.h" -#include "pn512_rf.h" -#include "pn512_irq.h" -#include "pn512_cmd.h" -#include "pn512_registers.h" -#include "pn512_internal.h" - - -#define TIMEOUT 1000 - -void pn512_transceive_hw_tx_iteration(pn512_t *pPN512, bool start) -{ - uint16_t irqs_en = pn512_irq_enabled(pPN512); - - if (ac_buffer_reader_readable(&pPN512->writeBuf) > 0) { - //Fill FIFO - pn512_fifo_write(pPN512, &pPN512->writeBuf); - - if (ac_buffer_reader_readable(&pPN512->writeBuf) > 0) { //Did not fit in FIFO - pn512_irq_clear(pPN512, PN512_IRQ_LOW_ALERT); - //Has low FIFO alert IRQ already been enabled? - if (!(irqs_en & PN512_IRQ_LOW_ALERT)) { - irqs_en |= PN512_IRQ_LOW_ALERT; - pn512_irq_set(pPN512, irqs_en); - } - } else { - if (irqs_en & PN512_IRQ_LOW_ALERT) { - //Buffer has been fully sent - irqs_en &= ~PN512_IRQ_LOW_ALERT; - pn512_irq_set(pPN512, irqs_en); - } - } - } - - - if (start) { - if ((pPN512->transceive.mode == pn512_transceive_mode_transmit) || (pPN512->transceive.mode == pn512_transceive_mode_transmit_and_target_autocoll)) { - //Update bitframing register - pn512_register_write(pPN512, PN512_REG_BITFRAMING, - 0x00 | ((pPN512->readFirstByteAlign & 0x7) << 4) | (pPN512->writeLastByteLength & 0x7)); - - //Use transmit command - pn512_cmd_exec(pPN512, PN512_CMD_TRANSMIT); - } else { - NFC_DBG("Bitframing %02X", 0x80 | ((pPN512->readFirstByteAlign & 0x7) << 4) | (pPN512->writeLastByteLength & 0x7)); - //Update bitframing register to start transmission - pn512_register_write(pPN512, PN512_REG_BITFRAMING, - 0x80 | ((pPN512->readFirstByteAlign & 0x7) << 4) | (pPN512->writeLastByteLength & 0x7)); - } - - //Reset last byte length, first byte align - pPN512->writeLastByteLength = 8; - pPN512->readFirstByteAlign = 0; - } - - //Queue task to process IRQ - task_init(&pPN512->transceiver.task, EVENT_HW_INTERRUPT | EVENT_TIMEOUT, TIMEOUT, pn512_transceive_hw_tx_task, pPN512); - nfc_scheduler_queue_task(&pPN512->transceiver.scheduler, &pPN512->transceiver.task); -} - -void pn512_transceive_hw_tx_task(uint32_t events, void *pUserData) -{ - pn512_t *pPN512 = (pn512_t *) pUserData; - - if (events & EVENT_ABORTED) { - //Stop command - pn512_cmd_exec(pPN512, PN512_CMD_IDLE); - pPN512->transceive.mode = pn512_transceive_mode_idle; - - NFC_ERR("Aborted TX"); - - pn512_irq_set(pPN512, PN512_IRQ_NONE); - pn512_irq_clear(pPN512, PN512_IRQ_ALL); - - pn512_transceive_callback(pPN512, NFC_ERR_ABORTED); - return; - } - - NFC_DBG("TX task"); - if (events & EVENT_TIMEOUT) { - // Check status - NFC_DBG("Status = %02X %02X", pn512_register_read(pPN512, PN512_REG_STATUS1), pn512_register_read(pPN512, PN512_REG_STATUS2)); - - //Stop command - pn512_cmd_exec(pPN512, PN512_CMD_IDLE); - pPN512->transceive.mode = pn512_transceive_mode_idle; - - NFC_ERR("Timeout on TX"); - - pn512_irq_set(pPN512, PN512_IRQ_NONE); - pn512_irq_clear(pPN512, PN512_IRQ_ALL); - - //Call callback - pn512_transceive_callback(pPN512, NFC_ERR_TIMEOUT); - return; - } - - uint16_t irqs_en = pn512_irq_enabled(pPN512); - uint16_t irqs = pn512_irq_get(pPN512); - - if (irqs & PN512_IRQ_RF_OFF) { - //Stop command - pn512_cmd_exec(pPN512, PN512_CMD_IDLE); - pPN512->transceive.mode = pn512_transceive_mode_idle; - - pn512_irq_set(pPN512, PN512_IRQ_NONE); - pn512_irq_clear(pPN512, PN512_IRQ_ALL); - NFC_WARN("RF Off"); - pn512_transceive_callback(pPN512, NFC_ERR_FIELD); - return; - } - if (irqs & PN512_IRQ_TX) { - if (irqs_en & PN512_IRQ_LOW_ALERT) { - //If the transmission has been completed without us getting a chance to fill the buffer up it means that we had a buffer underflow - NFC_ERR("Buffer underflow"); - pn512_irq_set(pPN512, PN512_IRQ_NONE); - pn512_irq_clear(pPN512, PN512_IRQ_ALL); - - pn512_transceive_callback(pPN512, NFC_ERR_UNDERFLOW); - return; - } - - //Transmission complete - pn512_irq_set(pPN512, PN512_IRQ_NONE); - pn512_irq_clear(pPN512, PN512_IRQ_TX | PN512_IRQ_LOW_ALERT); - - //Start receiving - NFC_DBG("Transmission complete"); - if (pPN512->transceive.mode != pn512_transceive_mode_transmit) { - if (pPN512->transceive.mode == pn512_transceive_mode_transmit_and_target_autocoll) { - //Make sure bitframing reg is clean - pn512_register_write(pPN512, PN512_REG_BITFRAMING, 0x00); - - pn512_cmd_exec(pPN512, PN512_CMD_IDLE); - pn512_transceive_hw_rx_start(pPN512); - - //Start autocoll - pn512_cmd_exec(pPN512, PN512_CMD_AUTOCOLL); - } else { - pn512_transceive_hw_rx_start(pPN512); - } - return; - } else { - pn512_irq_set(pPN512, PN512_IRQ_NONE); - pn512_irq_clear(pPN512, PN512_IRQ_RX | PN512_IRQ_HIGH_ALERT); - - pn512_transceive_callback(pPN512, NFC_OK); - return; - } - } - if ((irqs & PN512_IRQ_LOW_ALERT) && (ac_buffer_reader_readable(&pPN512->writeBuf) > 0)) { - //Continue to fill FIFO - pn512_irq_clear(pPN512, PN512_IRQ_LOW_ALERT); - - pn512_transceive_hw_tx_iteration(pPN512, false); - return; - } - - if (irqs & PN512_IRQ_IDLE) { - pn512_irq_clear(pPN512, PN512_IRQ_ERR); - - NFC_ERR("Modem went to idle"); - - pn512_cmd_exec(pPN512, PN512_CMD_IDLE); - pPN512->transceive.mode = pn512_transceive_mode_idle; - - pn512_irq_set(pPN512, PN512_IRQ_NONE); - pn512_irq_clear(pPN512, PN512_IRQ_ALL); - pn512_transceive_callback(pPN512, NFC_ERR_WRONG_COMM); - return; - } - - //Call back function - pn512_transceive_hw_tx_iteration(pPN512, false); -} - -void pn512_transceive_hw_rx_start(pn512_t *pPN512) -{ - uint16_t irqs_en = PN512_IRQ_RX | PN512_IRQ_HIGH_ALERT | PN512_IRQ_ERR; - if (PN512_FRAMING_IS_TARGET(pPN512->framing)) { - irqs_en |= PN512_IRQ_RF_OFF; - } - - pn512_irq_set(pPN512, irqs_en); - - //Reset buffer except if data should be appended to this -- TODO - ac_buffer_builder_reset(&pPN512->readBufBldr); - - //Queue task to process IRQ - task_init(&pPN512->transceiver.task, EVENT_HW_INTERRUPT | EVENT_TIMEOUT, - pPN512->timeout, pn512_transceive_hw_rx_task, pPN512); - nfc_scheduler_queue_task(&pPN512->transceiver.scheduler, - &pPN512->transceiver.task); -} - -void pn512_transceive_hw_rx_task(uint32_t events, void *pUserData) -{ - pn512_t *pPN512 = (pn512_t *) pUserData; - - NFC_DBG("RX task"); - if (events & EVENT_ABORTED) { - //Stop command - pn512_cmd_exec(pPN512, PN512_CMD_IDLE); - pPN512->transceive.mode = pn512_transceive_mode_idle; - - NFC_ERR("Aborted RX"); - - pn512_irq_set(pPN512, PN512_IRQ_NONE); - pn512_irq_clear(pPN512, PN512_IRQ_ALL); - - pn512_transceive_callback(pPN512, NFC_ERR_ABORTED); - return; - } - - if (events & EVENT_TIMEOUT) { - NFC_WARN("Timeout"); - //Stop command - pn512_cmd_exec(pPN512, PN512_CMD_IDLE); - pPN512->transceive.mode = pn512_transceive_mode_idle; - - pn512_irq_set(pPN512, PN512_IRQ_NONE); - pn512_irq_clear(pPN512, PN512_IRQ_ALL); - - //Call callback - pn512_transceive_callback(pPN512, NFC_ERR_TIMEOUT); - return; - } - - uint16_t irqs = pn512_irq_get(pPN512); - NFC_DBG("irqs %04x", irqs); - bool collision_detected = false; - if (irqs & PN512_IRQ_ERR) { - pn512_irq_clear(pPN512, PN512_IRQ_ERR); - - uint8_t err_reg = pn512_register_read(pPN512, PN512_REG_ERROR); - NFC_ERR("Got error - error reg is %02X", err_reg); - // if err_reg == 0, sticky error that must have been cleared automatically, continue - if (err_reg != 0) { - //If it's a collsision, flag it but still carry on with RX procedure - collision_detected = true; - - if ((err_reg == 0x08) || (err_reg == 0x0A)) { // Collision (and maybe parity) (and no other error) - irqs &= ~PN512_IRQ_ERR; - irqs |= PN512_IRQ_RX; - } else { - NFC_DBG_BLOCK( - //Empty FIFO into buffer - pn512_fifo_read(pPN512, &pPN512->readBufBldr); - - NFC_DBG("Received"); - ac_buffer_dump(ac_buffer_builder_buffer(&pPN512->readBufBldr)); - - NFC_DBG("Computed CRC = %02X %02X", pn512_register_read(pPN512, PN512_REG_CRCRESULT_MSB), pn512_register_read(pPN512, PN512_REG_CRCRESULT_LSB)); - - ) - - //Stop command - pn512_cmd_exec(pPN512, PN512_CMD_IDLE); - pPN512->transceive.mode = pn512_transceive_mode_idle; - - pn512_irq_set(pPN512, PN512_IRQ_NONE); - pn512_irq_clear(pPN512, PN512_IRQ_ALL); - - //Call callback - pn512_transceive_callback(pPN512, NFC_ERR_WRONG_COMM); - return; - } - } - } - if ((irqs & PN512_IRQ_RX) || (irqs & PN512_IRQ_HIGH_ALERT)) { - //Empty FIFO into buffer - pn512_fifo_read(pPN512, &pPN512->readBufBldr); - - if ((ac_buffer_builder_writable(&pPN512->readBufBldr) == 0) && (pn512_fifo_length(pPN512) > 0)) { - //Stop command - pn512_cmd_exec(pPN512, PN512_CMD_IDLE); - pPN512->transceive.mode = pn512_transceive_mode_idle; - - NFC_WARN("RX buffer overflow"); - - pn512_irq_set(pPN512, PN512_IRQ_NONE); - pn512_irq_clear(pPN512, PN512_IRQ_ALL); - //Call callback - pn512_transceive_callback(pPN512, NFC_ERR_BUFFER_TOO_SMALL); - return; //overflow - } - - if (irqs & PN512_IRQ_HIGH_ALERT) { - NFC_DBG("High alert"); - pn512_irq_clear(pPN512, PN512_IRQ_HIGH_ALERT); - } - - if (irqs & PN512_IRQ_RX) { - pn512_irq_clear(pPN512, PN512_IRQ_RX); - - size_t last_byte_length = pn512_register_read(pPN512, PN512_REG_CONTROL) & 0x7; - if (last_byte_length == 0) { - last_byte_length = 8; - } - pPN512->readLastByteLength = last_byte_length; - - pn512_irq_set(pPN512, PN512_IRQ_NONE); - pn512_irq_clear(pPN512, PN512_IRQ_RX | PN512_IRQ_HIGH_ALERT); - - NFC_DBG("Received:"); - NFC_DBG_BLOCK(ac_buffer_dump(ac_buffer_builder_buffer(&pPN512->readBufBldr));) - - if ((pPN512->transceive.mode == pn512_transceive_mode_target_autocoll) || (pPN512->transceive.mode == pn512_transceive_mode_transmit_and_target_autocoll)) { - //Check if target was activated - if (!(pn512_register_read(pPN512, PN512_REG_STATUS2) & 0x10)) { - pPN512->transceive.mode = pn512_transceive_mode_idle; - - pn512_irq_set(pPN512, PN512_IRQ_NONE); - pn512_irq_clear(pPN512, PN512_IRQ_ALL); - //Call callback - pn512_transceive_callback(pPN512, NFC_ERR_PROTOCOL); - return; - } - //PN512 switches to transceive automatically - pPN512->transceive.mode = pn512_transceive_mode_transceive; - } else if (pPN512->transceive.mode == pn512_transceive_mode_receive) { - pPN512->transceive.mode = pn512_transceive_mode_transceive; - //pn512_cmd_exec(pPN512, PN512_CMD_IDLE); //Useful? - } - - if (!collision_detected) { - pn512_transceive_callback(pPN512, NFC_OK); - } else { - pn512_transceive_callback(pPN512, NFC_ERR_COLLISION); - } - - return; - } - } - if (irqs & PN512_IRQ_RF_OFF) { - //Stop command - pn512_cmd_exec(pPN512, PN512_CMD_IDLE); - pPN512->transceive.mode = pn512_transceive_mode_idle; - - pn512_irq_set(pPN512, PN512_IRQ_NONE); - pn512_irq_clear(pPN512, PN512_IRQ_ALL); - - //Call callback - pn512_transceive_callback(pPN512, NFC_ERR_FIELD); - return; - } - - //Queue task to process IRQ - task_init(&pPN512->transceiver.task, EVENT_HW_INTERRUPT | EVENT_TIMEOUT, - pPN512->timeout, pn512_transceive_hw_rx_task, pPN512); - nfc_scheduler_queue_task(&pPN512->transceiver.scheduler, - &pPN512->transceiver.task); -} - -void pn512_transceive_hw(pn512_t *pPN512, pn512_transceive_mode_t mode, pn512_cb_t cb) -{ - uint16_t irqs_en; - - //Store callback - pPN512->transceive.cb = cb; - - //Clear FIFO - pn512_fifo_clear(pPN512); - - //Clear previous IRQs if present - pn512_irq_clear(pPN512, PN512_IRQ_RX | PN512_IRQ_TX | PN512_IRQ_HIGH_ALERT | PN512_IRQ_LOW_ALERT | PN512_IRQ_ERR | PN512_IRQ_IDLE | PN512_IRQ_RF_OFF); - - if (PN512_FRAMING_IS_TARGET(pPN512->framing)) { - //RF off? - if (!(pn512_register_read(pPN512, PN512_REG_STATUS1) & 0x04)) { - //Call callback - pn512_transceive_callback(pPN512, NFC_ERR_FIELD); - return; - } - } else if ((pPN512->transceive.mode != mode) && (mode == pn512_transceive_mode_transceive)) { - pn512_cmd_exec(pPN512, PN512_CMD_TRANSCEIVE); - } - - pPN512->transceive.mode = mode; - - if (mode == pn512_transceive_mode_receive) { - pn512_cmd_exec(pPN512, PN512_CMD_IDLE); - pn512_transceive_hw_rx_start(pPN512); - pn512_cmd_exec(pPN512, PN512_CMD_TRANSCEIVE); - } else if (mode == pn512_transceive_mode_target_autocoll) { - //Make sure bitframing reg is clean - pn512_register_write(pPN512, PN512_REG_BITFRAMING, 0x00); - - pn512_transceive_hw_rx_start(pPN512); - - //Start autocoll - pn512_cmd_exec(pPN512, PN512_CMD_AUTOCOLL); - return; - } else { - NFC_DBG("Sending:"); - NFC_DBG_BLOCK(ac_buffer_dump(&pPN512->writeBuf);) - - //Transmit a frame to remote target/initiator - irqs_en = PN512_IRQ_TX | PN512_IRQ_IDLE; - if (PN512_FRAMING_IS_TARGET(pPN512->framing)) { - irqs_en |= PN512_IRQ_RF_OFF; - } - - pn512_irq_set(pPN512, irqs_en); - - pn512_transceive_hw_tx_iteration(pPN512, true); - } -} - - - diff --git a/features/nfc/stack/transceiver/pn512/pn512_transceive.h b/features/nfc/stack/transceiver/pn512/pn512_transceive.h deleted file mode 100644 index 1c3f224..0000000 --- a/features/nfc/stack/transceiver/pn512/pn512_transceive.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2014-2018, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * 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. - */ -/** - * \file pn512_transceive.h - * \copyright Copyright (c) ARM Ltd 2014 - * \author Donatien Garnier - */ - -#ifndef PN512_TRANSCEIVE_H_ -#define PN512_TRANSCEIVE_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "stack/nfc_common.h" -#include "pn512.h" - -void pn512_transceive_hw(pn512_t *pPN512, pn512_transceive_mode_t mode, pn512_cb_t cb); - -void pn512_transceive_hw_tx_task(uint32_t events, void *pUserData); -void pn512_transceive_hw_tx_iteration(pn512_t *pPN512, bool start); - -void pn512_transceive_hw_rx_start(pn512_t *pPN512); -void pn512_transceive_hw_rx_task(uint32_t events, void *pUserData); - - -#ifdef __cplusplus -} -#endif - -#endif /* PN512_TRANSCEIVE_H_ */ diff --git a/features/nfc/stack/transceiver/pn512/pn512_types.h b/features/nfc/stack/transceiver/pn512/pn512_types.h deleted file mode 100644 index efefefd..0000000 --- a/features/nfc/stack/transceiver/pn512/pn512_types.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2015-2018, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * 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. - */ -/** - * \file pn512_types.h - * \copyright Copyright (c) ARM Ltd 2015 - * \author Donatien Garnier - */ - -#ifndef TRANSCEIVER_PN512_PN512_TYPES_H_ -#define TRANSCEIVER_PN512_PN512_TYPES_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "stack/nfc_common.h" - -typedef struct __pn512 pn512_t; - -typedef struct __pn512_registers { - int8_t registers_page; -} pn512_registers_t; - - - -#ifdef __cplusplus -} -#endif - -#endif /* TRANSCEIVER_PN512_PN512_TYPES_H_ */ diff --git a/features/nfc/stack/transceiver/protocols.h b/features/nfc/stack/transceiver/protocols.h deleted file mode 100644 index 6b62f6a..0000000 --- a/features/nfc/stack/transceiver/protocols.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (c) 2013-2018, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * 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. - */ -/** - * \file protocols.h - * \copyright Copyright (c) ARM Ltd 2013 - * \author Donatien Garnier - * \details List of RF protocols - */ - -/** \addtogroup Transceiver - * @{ - * \name Protocols and RF configuration - * @{ - */ - -#ifndef PROTOCOLS_H_ -#define PROTOCOLS_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "stack/nfc_common.h" - -typedef enum __RF_PROTOCOL { - __RF_PROTOCOL_UNKNOWN = 0, - //Reader - RF_PROTOCOL_ISO_14443_A_READER, - RF_PROTOCOL_ISO_14443_B_READER, - RF_PROTOCOL_INNOVATRON_READER, - RF_PROTOCOL_ISO_15693_READER, - RF_PROTOCOL_FELICA_READER, - //... add other protocols here - RF_PROTOCOL_ISO_14443_A_TARGET, - RF_PROTOCOL_ISO_14443_B_TARGET, - RF_PROTOCOL_INNOVATRON_TARGET, - RF_PROTOCOL_ISO_15693_TARGET, - RF_PROTOCOL_FELICA_TARGET, - RF_PROTOCOL_ISO_DEP_TARGET, //ISO 14443-4 transport protocol - RF_PROTOCOL_NFC_DEP_TARGET, //NFC-IP 1 transport protocol - //... add other protocols here - -} RF_PROTOCOL; - -#define RF_PROTOCOL_IS_TARGET(x) ((x)>=RF_PROTOCOL_ISO_14443_A_TARGET) -#define RF_PROTOCOL_IS_READER(x) (!RF_PROTOCOL_IS_TARGET(x)) - -typedef uint32_t RF_OPTION; -//These options can be ORed -#define RF_OPTION_NONE 0x00 -#define RF_OPTION_COMPUTE_CRC 0x01 -#define RF_OPTION_COMPUTE_PARITY 0x02 -#define RF_OPTION_CHECK_CRC 0x04 -#define RF_OPTION_CHECK_PARITY 0x08 -#define RF_OPTION_CLOSE 0x10 //Last frame - -typedef enum __RF_BITRATE { - RF_BITRATE_106K = 0x00, - RF_BITRATE_212K = 0x01, - RF_BITRATE_424K = 0x02, - RF_BITRATE_848K = 0x03, - -} RF_BITRATE; - -#ifdef __cplusplus -} -#endif - -#endif /* PROTOCOLS_H_ */ - -/** - * @} - * @} - * */ - diff --git a/features/nfc/stack/transceiver/transceiver.c b/features/nfc/stack/transceiver/transceiver.c deleted file mode 100644 index 42d835a..0000000 --- a/features/nfc/stack/transceiver/transceiver.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2013-2018, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * 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. - */ -/** - * \file transceiver.c - * \copyright Copyright (c) ARM Ltd 2013 - * \author Donatien Garnier - * \details Transceiver - */ - -/** \addtogroup Transceiver - * @{ - * \name Initialization - * @{ - */ - -#include "transceiver.h" - -/** Initialize nfc_transceiver_t structure - * \param pTransceiver pointer to nfc_transceiver_t structure to initialize - * \param pTransport pointer to already initialized nfc_transport_t structure - * \param pImpl pointer to the structure implementing the transceiver interface (eg pn512_t or pn532_t) - */ -void transceiver_init(nfc_transceiver_t *pTransceiver, nfc_transport_t *pTransport, nfc_scheduler_timer_t *pTimer) -{ - pTransceiver->pTransport = pTransport; - nfc_scheduler_init(&pTransceiver->scheduler, pTimer); -} - - -/** - * @} - * @} - * */ diff --git a/features/nfc/stack/transceiver/transceiver.h b/features/nfc/stack/transceiver/transceiver.h deleted file mode 100644 index 864aeff..0000000 --- a/features/nfc/stack/transceiver/transceiver.h +++ /dev/null @@ -1,272 +0,0 @@ -/* - * Copyright (c) 2013-2018, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * 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. - */ -/** - * \file transceiver.h - * \copyright Copyright (c) ARM Ltd 2013 - * \author Donatien Garnier - */ - -#ifndef TRANSCEIVER_H_ -#define TRANSCEIVER_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "stack/nfc_common.h" - -typedef struct __nfc_tech nfc_tech_t; -typedef struct __transceiver nfc_transceiver_t; -typedef struct __transceiver_impl transceiver_impl_t; - -#include "protocols.h" -#include "platform/nfc_transport.h" -#include "platform/nfc_scheduler.h" - -enum __nfc_framing { - nfc_framing_unknown, - - nfc_framing_target_mode_detector, //Framing is unknown and will be detected by the hardware - nfc_framing_target_a_106, - nfc_framing_target_b_106, - nfc_framing_target_f_212, - nfc_framing_target_f_424, - - nfc_framing_initiator_a_106, - nfc_framing_initiator_b_106, - nfc_framing_initiator_f_212, - nfc_framing_initiator_f_424, -}; -typedef enum __nfc_framing nfc_framing_t; - -struct __nfc_tech { - unsigned int nfc_type1 : 1; - unsigned int nfc_type2 : 1; - unsigned int nfc_type3 : 1; - unsigned int nfc_iso_dep_a : 1; - unsigned int nfc_iso_dep_b : 1; - unsigned int nfc_nfc_dep_a : 1; - unsigned int nfc_nfc_dep_f_212 : 1; - unsigned int nfc_nfc_dep_f_424 : 1; -}; - -typedef struct __polling_options polling_options_t; -struct __polling_options { - unsigned int bail_at_first_target : 1; - unsigned int bail_at_first_tech : 1; - int32_t listen_for; -}; - -typedef void (*transceiver_cb_t)(nfc_transceiver_t *pTransceiver, nfc_err_t ret, void *pUserData); -typedef void (*set_protocols_fn_t)(nfc_transceiver_t *pTransceiver, nfc_tech_t initiators, nfc_tech_t targets, polling_options_t options); -typedef void (*poll_fn_t)(nfc_transceiver_t *pTransceiver); -typedef void (*set_crc_fn_t)(nfc_transceiver_t *pTransceiver, bool crcOut, bool crcIn); -typedef void (*set_timeout_fn_t)(nfc_transceiver_t *pTransceiver, int timeout); -typedef void (*set_transceive_options_fn_t)(nfc_transceiver_t *pTransceiver, bool transmit, bool receive, bool repoll); -typedef void (*set_transceive_framing_fn_t)(nfc_transceiver_t *pTransceiver, nfc_framing_t framing); -typedef void (*set_write_fn_t)(nfc_transceiver_t *pTransceiver, ac_buffer_t *pWriteBuf); //Set write buffer -typedef ac_buffer_t *(*get_read_fn_t)(nfc_transceiver_t *pTransceiver); //Get read buffer -typedef size_t (*get_last_byte_length_fn_t)(nfc_transceiver_t *pTransceiver); -typedef void (*set_last_byte_length_fn_t)(nfc_transceiver_t *pTransceiver, size_t lastByteLength); -typedef size_t (*get_first_byte_align_fn_t)(nfc_transceiver_t *pTransceiver); -typedef void (*set_first_byte_align_fn_t)(nfc_transceiver_t *pTransceiver, size_t firstByteAlign); -typedef void (*transceive_fn_t)(nfc_transceiver_t *pTransceiver); -typedef void (*abort_fn_t)(nfc_transceiver_t *pTransceiver); -typedef void (*close_fn_t)(nfc_transceiver_t *pTransceiver); -typedef void (*sleep_fn_t)(nfc_transceiver_t *pTransceiver, bool sleep); - -struct __transceiver_impl { - set_protocols_fn_t set_protocols; - poll_fn_t poll; - set_crc_fn_t set_crc; - set_timeout_fn_t set_timeout; - set_transceive_options_fn_t set_transceive_options; - set_transceive_framing_fn_t set_transceive_framing; - set_write_fn_t set_write; - get_read_fn_t get_read; - set_last_byte_length_fn_t set_last_byte_length; - get_last_byte_length_fn_t get_last_byte_length; - set_first_byte_align_fn_t set_first_byte_align; - transceive_fn_t transceive; - abort_fn_t abort; - close_fn_t close; - sleep_fn_t sleep; -}; - -typedef struct __nfc_a_info nfc_a_info_t; -struct __nfc_a_info { - uint8_t uid[10]; - size_t uidLength; - uint8_t sak; - uint8_t atqa[2]; -}; - -typedef struct __nfc_b_info nfc_b_info_t; -struct __nfc_b_info { - uint8_t pupi[4]; - uint8_t application_data[4]; - uint8_t protocol_info[3]; -}; - -typedef struct __nfc_f_info nfc_f_info_t; -struct __nfc_f_info { - uint8_t nfcid2[8]; -}; - -typedef struct __nfc_info nfc_info_t; - -struct __nfc_info { - nfc_tech_t type; - union { - nfc_a_info_t nfcA; - nfc_b_info_t nfcB; - nfc_f_info_t nfcF; - }; -}; - -#define MUNFC_MAX_REMOTE_TARGETS 4 -struct __transceiver { - const transceiver_impl_t *fn; //vtable - - bool initiator_ntarget; - nfc_info_t remote_targets[MUNFC_MAX_REMOTE_TARGETS]; - size_t remote_targets_count; - - nfc_tech_t active_tech; - - transceiver_cb_t cb; //Callback to upper layer - void *pUserData; - nfc_task_t task; //Task for deferred execution - - nfc_transport_t *pTransport; - nfc_scheduler_t scheduler; -}; - -void transceiver_init(nfc_transceiver_t *pTransceiver, nfc_transport_t *pTransport, nfc_scheduler_timer_t *pTimer); - -static inline void transceiver_set_protocols(nfc_transceiver_t *pTransceiver, nfc_tech_t initiators, nfc_tech_t targets, polling_options_t options) -{ - pTransceiver->fn->set_protocols(pTransceiver, initiators, targets, options); -} - -static inline void transceiver_poll(nfc_transceiver_t *pTransceiver, transceiver_cb_t cb, void *pUserData) -{ - pTransceiver->cb = cb; - pTransceiver->pUserData = pUserData; - pTransceiver->fn->poll(pTransceiver); -} - -static inline void transceiver_set_crc(nfc_transceiver_t *pTransceiver, bool crcOut, bool crcIn) -{ - pTransceiver->fn->set_crc(pTransceiver, crcOut, crcIn); -} - -static inline void transceiver_set_timeout(nfc_transceiver_t *pTransceiver, int timeout) -{ - pTransceiver->fn->set_timeout(pTransceiver, timeout); -} - -static inline void transceiver_set_transceive_options(nfc_transceiver_t *pTransceiver, bool transmit, bool receive, bool repoll) -{ - pTransceiver->fn->set_transceive_options(pTransceiver, transmit, receive, repoll); -} - -static inline void transceiver_set_transceive_framing(nfc_transceiver_t *pTransceiver, nfc_framing_t framing) -{ - pTransceiver->fn->set_transceive_framing(pTransceiver, framing); -} - -static inline void transceiver_set_write(nfc_transceiver_t *pTransceiver, ac_buffer_t *pWriteBuf) -{ - pTransceiver->fn->set_write(pTransceiver, pWriteBuf); -} - -static inline ac_buffer_t *transceiver_get_read(nfc_transceiver_t *pTransceiver) -{ - return pTransceiver->fn->get_read(pTransceiver); -} - -static inline size_t transceiver_get_last_byte_length(nfc_transceiver_t *pTransceiver) -{ - return pTransceiver->fn->get_last_byte_length(pTransceiver); -} - -static inline void transceiver_set_last_byte_length(nfc_transceiver_t *pTransceiver, size_t lastByteLength) -{ - pTransceiver->fn->set_last_byte_length(pTransceiver, lastByteLength); -} - -static inline void transceiver_set_first_byte_align(nfc_transceiver_t *pTransceiver, size_t firstByteAlign) -{ - pTransceiver->fn->set_first_byte_align(pTransceiver, firstByteAlign); -} - -static inline void nfc_transceiver_transceive(nfc_transceiver_t *pTransceiver, transceiver_cb_t cb, void *pUserData) -{ - pTransceiver->cb = cb; - pTransceiver->pUserData = pUserData; - pTransceiver->fn->transceive(pTransceiver); -} - -static inline void transceiver_abort(nfc_transceiver_t *pTransceiver) -{ - pTransceiver->fn->abort(pTransceiver); -} - -static inline void transceiver_close(nfc_transceiver_t *pTransceiver) -{ - pTransceiver->fn->close(pTransceiver); -} - -static inline bool transceiver_is_initiator_mode(nfc_transceiver_t *pTransceiver) -{ - return pTransceiver->initiator_ntarget; -} - -static inline nfc_tech_t transceiver_get_active_techs(nfc_transceiver_t *pTransceiver) -{ - return pTransceiver->active_tech; -} - -static inline nfc_scheduler_t *transceiver_get_scheduler(nfc_transceiver_t *pTransceiver) -{ - return &pTransceiver->scheduler; -} - -static inline const nfc_info_t *transceiver_get_remote_target_info(nfc_transceiver_t *pTransceiver, size_t number) -{ - if (number > pTransceiver->remote_targets_count) { - return NULL; - } - return &pTransceiver->remote_targets[number]; -} - -static inline size_t transceiver_get_remote_targets_count(nfc_transceiver_t *pTransceiver) -{ - return pTransceiver->remote_targets_count; -} - -static inline void transceiver_sleep(nfc_transceiver_t *pTransceiver, bool sleep) -{ - pTransceiver->fn->sleep(pTransceiver, sleep); -} - -#ifdef __cplusplus -} -#endif - -#endif /* TRANSCEIVER_H_ */ diff --git a/features/nfc/stack/transceiver/transceiver_internal.h b/features/nfc/stack/transceiver/transceiver_internal.h deleted file mode 100644 index c689d11..0000000 --- a/features/nfc/stack/transceiver/transceiver_internal.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2015-2018, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * 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. - */ -/** - * \file transceiver_internal.h - * \copyright Copyright (c) ARM Ltd 2015 - * \author Donatien Garnier - */ - -#ifndef TRANSCEIVER_INTERNAL_H_ -#define TRANSCEIVER_INTERNAL_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "stack/nfc_common.h" -#include "transceiver.h" - -static inline void transceiver_callback(nfc_transceiver_t *pTransceiver, nfc_err_t ret) -{ - pTransceiver->cb(pTransceiver, ret, pTransceiver->pUserData); -} - -#ifdef __cplusplus -} -#endif - -#endif /* TRANSCEIVER_INTERNAL_H_ */