mirror of https://github.com/ARMmbed/mbed-os.git
				
				
				
			
						commit
						f82feecc51
					
				| 
						 | 
					@ -0,0 +1,499 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * 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 <events/mbed_events.h>
 | 
				
			||||||
 | 
					#include "NFCEEPROMDriver.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if !MBED_CONF_NFCEEPROM
 | 
				
			||||||
 | 
					#error [NOT_SUPPORTED] NFC EEPROM not supported for this target
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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 fist 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, 4);
 | 
				
			||||||
 | 
					                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);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -10,5 +10,5 @@
 | 
				
			||||||
    "EXPAND_AS_DEFINED": "",
 | 
					    "EXPAND_AS_DEFINED": "",
 | 
				
			||||||
    "SKIP_FUNCTION_MACROS": "NO",
 | 
					    "SKIP_FUNCTION_MACROS": "NO",
 | 
				
			||||||
    "STRIP_CODE_COMMENTS": "NO",
 | 
					    "STRIP_CODE_COMMENTS": "NO",
 | 
				
			||||||
    "EXCLUDE_PATTERNS": "*/tools/* */targets/* */features/mbedtls/* */features/storage/* */features/unsupported/* */BUILD/* */rtos/TARGET_CORTEX/rtx*/* */cmsis/* */features/lwipstack/* */nanostack/sal-stack-nanostack/* */nanostack/coap-service/* */ble/generic/* */ble/pal/*  */mbed-trace/* */mbed-coap/* */nanostack-libservice/* */mbed-client-randlib/* */nanostack/sal-stack-nanostack-eventloop/*"
 | 
					    "EXCLUDE_PATTERNS": "*/tools/* */targets/* */features/mbedtls/* */features/storage/* */features/unsupported/* */BUILD/* */rtos/TARGET_CORTEX/rtx*/* */cmsis/* */features/lwipstack/* */nanostack/sal-stack-nanostack/* */nanostack/coap-service/* */ble/generic/* */ble/pal/* */mbed-trace/* */mbed-coap/* */nanostack-libservice/* */mbed-client-randlib/* */nanostack/sal-stack-nanostack-eventloop/* */features/nfc/stack/*"
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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_ */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @}
 | 
				
			||||||
 | 
					 * @}
 | 
				
			||||||
 | 
					 * */
 | 
				
			||||||
| 
						 | 
					@ -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_ */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @}
 | 
				
			||||||
 | 
					 * @}
 | 
				
			||||||
 | 
					 * */
 | 
				
			||||||
| 
						 | 
					@ -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_ */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @}
 | 
				
			||||||
 | 
					 * @}
 | 
				
			||||||
 | 
					 * */
 | 
				
			||||||
| 
						 | 
					@ -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
 | 
				
			||||||
| 
						 | 
					@ -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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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_ */
 | 
				
			||||||
| 
						 | 
					@ -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
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -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;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -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;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -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);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -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 <stdint.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#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
 | 
				
			||||||
| 
						 | 
					@ -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 <stdint.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#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
 | 
				
			||||||
| 
						 | 
					@ -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 <stdint.h>
 | 
				
			||||||
 | 
					#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
 | 
				
			||||||
| 
						 | 
					@ -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
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,189 @@
 | 
				
			||||||
 | 
					/* 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 <stdint.h>
 | 
				
			||||||
 | 
					#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 {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class NFCRemoteInitiator;
 | 
				
			||||||
 | 
					class NFCRemoteTarget;
 | 
				
			||||||
 | 
					class NFCControllerDriver;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @addtogroup nfc
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * 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<NFCRemoteInitiator> &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<NFCRemoteTarget> &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<uint8_t> &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<uint8_t> _ndef_buffer;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @}
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace nfc
 | 
				
			||||||
 | 
					} // namespace mbed
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					@ -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 <stdint.h>
 | 
				
			||||||
 | 
					#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
 | 
				
			||||||
| 
						 | 
					@ -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 <stdint.h>
 | 
				
			||||||
 | 
					#include <stdbool.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#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
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,164 @@
 | 
				
			||||||
 | 
					/* 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 <stdint.h>
 | 
				
			||||||
 | 
					#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<uint8_t> &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_bytes,
 | 
				
			||||||
 | 
					        nfc_eeprom_write_write_size,
 | 
				
			||||||
 | 
					        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;
 | 
				
			||||||
 | 
					    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
 | 
				
			||||||
| 
						 | 
					@ -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 <stdint.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#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
 | 
				
			||||||
| 
						 | 
					@ -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 <stdint.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#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<uint8_t> &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<const uint8_t> &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<uint8_t> &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
 | 
				
			||||||
| 
						 | 
					@ -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 <stdint.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#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
 | 
				
			||||||
| 
						 | 
					@ -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 <stdint.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#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<uint8_t> &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
 | 
				
			||||||
| 
						 | 
					@ -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 <stdint.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#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<uint8_t> &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
 | 
				
			||||||
| 
						 | 
					@ -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 <stdint.h>
 | 
				
			||||||
 | 
					#include <stddef.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#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<uint8_t> &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
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,201 @@
 | 
				
			||||||
 | 
					/* 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 <stdint.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#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<uint8_t> &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<uint8_t> &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<uint8_t> &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<const uint8_t> 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<uint8_t> _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_ */
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,178 @@
 | 
				
			||||||
 | 
					/* 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 <stdlib.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#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<const uint8_t> &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_ */
 | 
				
			||||||
| 
						 | 
					@ -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 <stdint.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#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<const uint8_t> &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<const uint8_t> value;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Definition of a Record payload.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @note A payload can be empty.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					typedef Span<const uint8_t> RecordPayload;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Definition of a Record IR.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @note ID's are optional and therefore it can be empty.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					typedef Span<const uint8_t> 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_ */
 | 
				
			||||||
| 
						 | 
					@ -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 <stddef.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#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<typename ParserImplementation, typename ParsingResult>
 | 
				
			||||||
 | 
					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<ParserImplementation *>(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_ */
 | 
				
			||||||
| 
						 | 
					@ -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 <stdint.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#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<const uint8_t> &mime_type,
 | 
				
			||||||
 | 
					        const Span<const uint8_t> &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<const uint8_t> &mime_type,
 | 
				
			||||||
 | 
					        const Span<const uint8_t> &content
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Return the mime type.
 | 
				
			||||||
 | 
					     * @return The mime type.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    Span<const uint8_t> get_mime_type() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Return the content of the mime object.
 | 
				
			||||||
 | 
					     * @return the content of the mime object.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    Span<const uint8_t> 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<MimeParser, Mime> {
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					    bool do_parse(const Record &record, Mime &mime);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @}
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace common
 | 
				
			||||||
 | 
					} // namespace ndef
 | 
				
			||||||
 | 
					} // namespace nfc
 | 
				
			||||||
 | 
					} // namespace mbed
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* NFC_COMMON_MIME_H_ */
 | 
				
			||||||
| 
						 | 
					@ -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.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#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<const uint8_t> &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_ */
 | 
				
			||||||
| 
						 | 
					@ -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 <stdint.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#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<const uint8_t> &language_code,
 | 
				
			||||||
 | 
					        const Span<const uint8_t> &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<const uint8_t> &language_code,
 | 
				
			||||||
 | 
					        const Span<const uint8_t> &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<const uint8_t> get_language_code() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Return the text contained in this object.
 | 
				
			||||||
 | 
					     * @return The text contained in this object.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    Span<const uint8_t> 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<TextParser, Text> {
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					    virtual bool do_parse(const Record &record, Text &text);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @}
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace common
 | 
				
			||||||
 | 
					}  // namespace ndef
 | 
				
			||||||
 | 
					} // namespace nfc
 | 
				
			||||||
 | 
					} // namespace mbed
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* NFC_COMMON_TEXT_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 <stdint.h>
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#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<const uint8_t> &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<const uint8_t> &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<const uint8_t> 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<URIParser, URI> {
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					    bool do_parse(const Record &record, URI &uri);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @}
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace common
 | 
				
			||||||
 | 
					} // namespace ndef
 | 
				
			||||||
 | 
					} // namespace nfc
 | 
				
			||||||
 | 
					} // namespace mbed
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* NFC_COMMON_URI_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<const uint8_t>.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @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<size_t N>
 | 
				
			||||||
 | 
					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<const uint8_t>.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @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<const uint8_t> span_from_cstr(const char *cstr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @}
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace common
 | 
				
			||||||
 | 
					} // namespace ndef
 | 
				
			||||||
 | 
					} // namespace nfc
 | 
				
			||||||
 | 
					} // namespace mbed
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* FEATURES_NFC_SOURCE_NFC_COMMON_UTIL_H_ */
 | 
				
			||||||
| 
						 | 
					@ -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 "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
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -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<void>());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // 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
 | 
				
			||||||
| 
						 | 
					@ -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();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,236 @@
 | 
				
			||||||
 | 
					/* 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 namespace mbed;
 | 
				
			||||||
 | 
					using namespace mbed::nfc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					NFCController::NFCController(NFCControllerDriver *driver, events::EventQueue *queue, const Span<uint8_t> &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<NFCRemoteInitiator> 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
 | 
				
			||||||
 | 
					    uint32_t 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)mbed_timer->read_ms();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -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();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,425 @@
 | 
				
			||||||
 | 
					/* 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<uint8_t> &ndef_buffer) : NFCTarget(ndef_buffer),
 | 
				
			||||||
 | 
					    _delegate(NULL), _driver(driver), _initialized(false), _current_op(nfc_eeprom_idle), _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_read_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_bytes;
 | 
				
			||||||
 | 
					            continue_write();
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case nfc_eeprom_read_start_session:
 | 
				
			||||||
 | 
					            if (!success) {
 | 
				
			||||||
 | 
					                handle_error(NFC_ERR_CONTROLLER);
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            _current_op = nfc_eeprom_read_read_size;
 | 
				
			||||||
 | 
					            _driver->read_size();
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        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
 | 
				
			||||||
 | 
					            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
 | 
				
			||||||
 | 
					            continue_write();
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        default:
 | 
				
			||||||
 | 
					            // Should not happen, state machine is broken or driver is doing something wrong
 | 
				
			||||||
 | 
					            handle_error(NFC_ERR_UNKNOWN);
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void NFCEEPROM::on_size_written(bool success)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    switch (_current_op) {
 | 
				
			||||||
 | 
					        case nfc_eeprom_write_write_size:
 | 
				
			||||||
 | 
					            if (!success) {
 | 
				
			||||||
 | 
					                handle_error(NFC_ERR_CONTROLLER);
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // End session
 | 
				
			||||||
 | 
					            _current_op = nfc_eeprom_write_end_session;
 | 
				
			||||||
 | 
					            _operation_result = NFC_OK;
 | 
				
			||||||
 | 
					            _driver->end_session();
 | 
				
			||||||
 | 
					            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;
 | 
				
			||||||
 | 
					            continue_read();
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        default:
 | 
				
			||||||
 | 
					            // Should not happen, state machine is broken or driver is doing something wrong
 | 
				
			||||||
 | 
					            handle_error(NFC_ERR_UNKNOWN);
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void NFCEEPROM::on_bytes_erased(size_t count)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    switch (_current_op) {
 | 
				
			||||||
 | 
					        case nfc_eeprom_erase_erase_bytes:
 | 
				
			||||||
 | 
					            if (count == 0) {
 | 
				
			||||||
 | 
					                handle_error(NFC_ERR_CONTROLLER);
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Update address
 | 
				
			||||||
 | 
					            _eeprom_address += count;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Continue erasing
 | 
				
			||||||
 | 
					            continue_erase();
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        default:
 | 
				
			||||||
 | 
					            // Should not happen, state machine is broken or driver is doing something wrong
 | 
				
			||||||
 | 
					            handle_error(NFC_ERR_UNKNOWN);
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void NFCEEPROM::continue_write()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (ac_buffer_reader_readable(&_ndef_buffer_reader) > 0) {
 | 
				
			||||||
 | 
					        // Continue writing
 | 
				
			||||||
 | 
					        _driver->write_bytes(_eeprom_address, ac_buffer_reader_current_buffer_pointer(&_ndef_buffer_reader), ac_buffer_reader_current_buffer_length(&_ndef_buffer_reader));
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        // Now update size
 | 
				
			||||||
 | 
					        _current_op = nfc_eeprom_write_write_size;
 | 
				
			||||||
 | 
					        _driver->write_size(_eeprom_address);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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
 | 
				
			||||||
 | 
					        _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;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -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;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -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<uint8_t> &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;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -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;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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<uint8_t> &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;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -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<uint8_t> &buffer) :
 | 
				
			||||||
 | 
					    NFCNDEFCapable(buffer)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					NFCTarget::~NFCTarget()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -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<uint8_t> &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();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -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 <string.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "nfc/ndef/MessageBuilder.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace mbed {
 | 
				
			||||||
 | 
					namespace nfc {
 | 
				
			||||||
 | 
					namespace ndef {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					MessageBuilder::MessageBuilder(const Span<uint8_t> &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<uint8_t> &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<const uint8_t> MessageBuilder::get_message() const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (is_message_complete()) {
 | 
				
			||||||
 | 
					        return _message_buffer.first(_position);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        return Span<const uint8_t>();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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 <string.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "nfc/ndef/MessageParser.h"
 | 
				
			||||||
 | 
					#include "nfc/ndef/Record.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace {
 | 
				
			||||||
 | 
					struct buffer_iterator_t {
 | 
				
			||||||
 | 
					    buffer_iterator_t(const mbed::Span<const uint8_t> &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<const uint8_t> get_underlying_buffer() const
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return buffer.last(buffer.size() - position);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					    mbed::Span<const uint8_t> buffer;
 | 
				
			||||||
 | 
					    mbed::Span<const uint8_t>::index_type position;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // end of anonymous namespace
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace mbed {
 | 
				
			||||||
 | 
					namespace nfc {
 | 
				
			||||||
 | 
					namespace ndef {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct MessageParser::parsing_state_t {
 | 
				
			||||||
 | 
					    parsing_state_t(const Span<const uint8_t> &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<const uint8_t> &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<RecordType::tnf_t>(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<uint8_t *>(&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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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
 | 
				
			||||||
| 
						 | 
					@ -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 <string.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#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<const uint8_t> &mime_type,
 | 
				
			||||||
 | 
					    const Span<const uint8_t> &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<const uint8_t> &mime_type,
 | 
				
			||||||
 | 
					    const Span<const uint8_t> &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<const uint8_t> Mime::get_mime_type() const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return make_const_Span(_mime, _type_size);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Span<const uint8_t> 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
 | 
				
			||||||
| 
						 | 
					@ -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<const uint8_t> &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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#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)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    memcpy(_text_record, other._text_record, _text_record_size);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Text::Text(
 | 
				
			||||||
 | 
					    encoding_t text_encoding,
 | 
				
			||||||
 | 
					    const Span<const uint8_t> &language_code,
 | 
				
			||||||
 | 
					    const Span<const uint8_t> &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<const uint8_t> &language_code,
 | 
				
			||||||
 | 
					    const Span<const uint8_t> &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<const uint8_t> Text::get_language_code() const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return make_const_Span(
 | 
				
			||||||
 | 
					               _text_record + language_code_index,
 | 
				
			||||||
 | 
					               _text_record[header_index] & language_code_size_mask
 | 
				
			||||||
 | 
					           );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Span<const uint8_t> Text::get_text() const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (!_text_record) {
 | 
				
			||||||
 | 
					        return Span<const uint8_t>();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    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
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,187 @@
 | 
				
			||||||
 | 
					/* 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 <string.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#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<const uint8_t> &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())
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    _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)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    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<const uint8_t> &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_identifier_code_t>(_uri[uri_id_index]);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Span<const uint8_t> URI::get_uri_field() const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (!_uri) {
 | 
				
			||||||
 | 
					        return Span<const uint8_t>();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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 <string.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "nfc/ndef/common/util.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace mbed {
 | 
				
			||||||
 | 
					namespace nfc {
 | 
				
			||||||
 | 
					namespace ndef {
 | 
				
			||||||
 | 
					namespace common {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Span<const uint8_t> span_from_cstr(const char *cstr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return Span<const uint8_t>((const uint8_t *)cstr, strlen(cstr));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @}
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace common
 | 
				
			||||||
 | 
					} // namespace ndef
 | 
				
			||||||
 | 
					} // namespace nfc
 | 
				
			||||||
 | 
					} // namespace mbed
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @}
 | 
				
			||||||
 | 
					 * @}
 | 
				
			||||||
 | 
					 * */
 | 
				
			||||||
| 
						 | 
					@ -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_ */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @}
 | 
				
			||||||
 | 
					 * @}
 | 
				
			||||||
 | 
					 * */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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_ */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @}
 | 
				
			||||||
 | 
					 * @}
 | 
				
			||||||
 | 
					 * */
 | 
				
			||||||
| 
						 | 
					@ -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_ */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @}
 | 
				
			||||||
 | 
					 * @}
 | 
				
			||||||
 | 
					 * */
 | 
				
			||||||
| 
						 | 
					@ -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
 | 
				
			||||||
| 
						 | 
					@ -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 <stddef.h>
 | 
				
			||||||
 | 
					#include <stdint.h>
 | 
				
			||||||
 | 
					#include <stdbool.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#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;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -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_ */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @}
 | 
				
			||||||
 | 
					 * @}
 | 
				
			||||||
 | 
					 * */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @}
 | 
				
			||||||
 | 
					 * @}
 | 
				
			||||||
 | 
					 * */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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_ */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @}
 | 
				
			||||||
 | 
					 * @}
 | 
				
			||||||
 | 
					 * */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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_ */
 | 
				
			||||||
| 
						 | 
					@ -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;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -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_ */
 | 
				
			||||||
| 
						 | 
					@ -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_ */
 | 
				
			||||||
| 
						 | 
					@ -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_ */
 | 
				
			||||||
| 
						 | 
					@ -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
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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_ */
 | 
				
			||||||
| 
						 | 
					@ -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;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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_ */
 | 
				
			||||||
| 
						 | 
					@ -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);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @}
 | 
				
			||||||
 | 
					 * @}
 | 
				
			||||||
 | 
					 * */
 | 
				
			||||||
| 
						 | 
					@ -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_ */
 | 
				
			||||||
| 
						 | 
					@ -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_ */
 | 
				
			||||||
| 
						 | 
					@ -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;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @}
 | 
				
			||||||
 | 
					 * @}
 | 
				
			||||||
 | 
					 * */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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_ */
 | 
				
			||||||
| 
						 | 
					@ -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;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @}
 | 
				
			||||||
 | 
					 * @}
 | 
				
			||||||
 | 
					 * */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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_ */
 | 
				
			||||||
| 
						 | 
					@ -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_ */
 | 
				
			||||||
| 
						 | 
					@ -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
 | 
				
			||||||
 | 
					 *  @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @}
 | 
				
			||||||
 | 
					 * @}
 | 
				
			||||||
 | 
					 * */
 | 
				
			||||||
| 
						 | 
					@ -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_ */
 | 
				
			||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| 
						 | 
					@ -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_ */
 | 
				
			||||||
| 
						 | 
					@ -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;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @}
 | 
				
			||||||
 | 
					 * @}
 | 
				
			||||||
 | 
					 * */
 | 
				
			||||||
| 
						 | 
					@ -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_ */
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,326 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * 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);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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_ */
 | 
				
			||||||
| 
						 | 
					@ -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;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -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_ */
 | 
				
			||||||
| 
						 | 
					@ -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);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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_ */
 | 
				
			||||||
| 
						 | 
					@ -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_ */
 | 
				
			||||||
| 
						 | 
					@ -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_ */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @}
 | 
				
			||||||
 | 
					 * @}
 | 
				
			||||||
 | 
					 * */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @}
 | 
				
			||||||
 | 
					 * @}
 | 
				
			||||||
 | 
					 * */
 | 
				
			||||||
| 
						 | 
					@ -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_ */
 | 
				
			||||||
| 
						 | 
					@ -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_ */
 | 
				
			||||||
| 
						 | 
					@ -305,7 +305,7 @@ struct Span {
 | 
				
			||||||
        _data(other.data())
 | 
					        _data(other.data())
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        MBED_STATIC_ASSERT(
 | 
					        MBED_STATIC_ASSERT(
 | 
				
			||||||
            (span_detail::is_convertible<OtherElementType (*)[], ElementType (*)[]>::value),
 | 
					            (span_detail::is_convertible<OtherElementType (*)[1], ElementType (*)[1]>::value),
 | 
				
			||||||
            "OtherElementType(*)[] should be convertible to ElementType (*)[]"
 | 
					            "OtherElementType(*)[] should be convertible to ElementType (*)[]"
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -594,7 +594,7 @@ struct Span<ElementType, SPAN_DYNAMIC_EXTENT> {
 | 
				
			||||||
        _data(other.data()), _size(other.size())
 | 
					        _data(other.data()), _size(other.size())
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        MBED_STATIC_ASSERT(
 | 
					        MBED_STATIC_ASSERT(
 | 
				
			||||||
            (span_detail::is_convertible<OtherElementType (*)[], ElementType (*)[]>::value),
 | 
					            (span_detail::is_convertible<OtherElementType (*)[1], ElementType (*)[1]>::value),
 | 
				
			||||||
            "OtherElementType(*)[] should be convertible to ElementType (*)[]"
 | 
					            "OtherElementType(*)[] should be convertible to ElementType (*)[]"
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue