Import Mbed OS hard-float snapshot

This commit is contained in:
Beslan
2026-06-01 20:15:04 +03:00
commit d3738e2f89
16278 changed files with 10628036 additions and 0 deletions

View File

@@ -0,0 +1,289 @@
/*
* 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.
*/
#include <string>
#include <vector>
#include <stdarg.h>
#include <stdlib.h>
#include <ctype.h>
#include "mbed_events.h"
#include "mbed-client-cli/ns_cmdline.h"
#include "rtos/Thread.h"
#include "NFCTestShim.h"
#include "NFCCommands.h"
#if MBED_CONF_NFCEEPROM
#include "NFCEEPROMDriver.h"
#include "NFCProcessEEPROM.h"
#endif
using mbed::nfc::nfc_rf_protocols_bitmask_t;
events::EventQueue HandleTestCommand::_nfcQueue;
rtos::Thread nfcThread;
bool human_trace_enabled = true;
NFCTestShim *HandleTestCommand::new_testshim()
{
#if MBED_CONF_NFCEEPROM
mbed::nfc::NFCEEPROMDriver &eeprom_driver = get_eeprom_driver(_nfcQueue);
return ((NFCTestShim *)(new NFCProcessEEPROM(_nfcQueue, eeprom_driver)));
#else
return ((NFCTestShim *)(new NFCProcessController(_nfcQueue)));
#endif // EEPROM
}
void HandleTestCommand::nfc_routine()
{
_nfcQueue.dispatch_forever();
}
void trace_printf(const char *fmt, ...)
{
if (human_trace_enabled) {
va_list ap;
va_start(ap, fmt);
cmd_vprintf(fmt, ap);
va_end(ap);
}
}
HandleTestCommand::HandleTestCommand()
{
osStatus status = nfcThread.start(mbed::callback(&HandleTestCommand::nfc_routine));
MBED_ASSERT(status == osOK);
}
int HandleTestCommand::cmd_get_last_nfc_error(int argc, char *argv[])
{
_nfcQueue.call(NFCTestShim::cmd_get_last_nfc_error);
return (CMDLINE_RETCODE_EXCUTING_CONTINUE);
}
/** returns compile time flag if NFC EEPROM was compiled */
int HandleTestCommand::cmd_get_conf_nfceeprom(int argc, char *argv[])
{
_nfcQueue.call(NFCTestShim::cmd_get_conf_nfceeprom);
return (CMDLINE_RETCODE_EXCUTING_CONTINUE);
}
int HandleTestCommand::cmd_set_trace(int argc, char *argv[])
{
human_trace_enabled = false;
if (argc > 1) {
static char buffer[7];
char *p_buffer = buffer;
strncpy(buffer, argv[1], sizeof(buffer) - 1);
buffer[sizeof(buffer) - 1] = 0;
while (*p_buffer) {
*p_buffer = toupper(*p_buffer);
p_buffer++;
}
cmd_printf(buffer);
human_trace_enabled = (0 == strcmp(buffer, "TRUE")) || (0 == strcmp(buffer, "1")) || (0 == strcmp(buffer, "ON"));
}
cmd_printf("set trace '%s'", (human_trace_enabled ? "true" : "false"));
return (CMDLINE_RETCODE_SUCCESS);
}
////////////////////////////////////////////////////////////////////////////////////
int HandleTestCommand::cmd_set_last_nfc_error(int argc, char *argv[])
{
if (argc <= 1) {
cmd_printf("setlastnfcerror() invalid parameter(s)\r\n");
return (CMDLINE_RETCODE_INVALID_PARAMETERS);
} else {
int value = strtol(argv[1], NULL, 10);
_nfcQueue.call(NFCTestShim::cmd_set_last_nfc_error, value);
}
return (CMDLINE_RETCODE_EXCUTING_CONTINUE);
}
int HandleTestCommand::cmd_get_max_ndef(int argc, char *argv[])
{
if (pNFC_Test_Shim) {
_nfcQueue.call(pNFC_Test_Shim, &NFCTestShim::cmd_get_max_ndef);
return CMDLINE_RETCODE_EXCUTING_CONTINUE;
}
return CMDLINE_RETCODE_FAIL;
}
int HandleTestCommand::cmd_init_nfc(int argc, char *argv[])
{
if (pNFC_Test_Shim) {
cmd_printf("WARN init called again!\r\n"); // only legal here, if eeprom driver stops talking
} else {
pNFC_Test_Shim = new_testshim();
}
_nfcQueue.call(pNFC_Test_Shim, &NFCTestShim::cmd_init);
return (CMDLINE_RETCODE_EXCUTING_CONTINUE);
}
int HandleTestCommand::cmd_read_message(int argc, char *argv[])
{
_nfcQueue.call(pNFC_Test_Shim, &NFCTestShim::cmd_read_nfc_contents);
return (CMDLINE_RETCODE_EXCUTING_CONTINUE);
}
int HandleTestCommand::cmd_set_smartposter(int argc, char *argv[])
{
// args are "setsmartposter", "<uri>"
if (argc <= 1) {
cmd_printf("setlastnfcerror() invalid parameter(s)\r\n");
return (CMDLINE_RETCODE_INVALID_PARAMETERS);
} else {
// parse arg and queue it up
char *uri = (char *) malloc(strlen(argv[1]) + 1);
if (uri) {
strcpy(uri, argv[1]);
_nfcQueue.call(pNFC_Test_Shim, &NFCTestShim::cmd_set_smartposter,
uri); // called thread must free
} else {
cmd_printf("WARN out of memory!\r\n");
return (CMDLINE_RETCODE_FAIL);
}
}
return (CMDLINE_RETCODE_EXCUTING_CONTINUE);
}
int HandleTestCommand::cmd_erase(int argc, char *argv[])
{
_nfcQueue.call(pNFC_Test_Shim, &NFCTestShim::cmd_erase);
return (CMDLINE_RETCODE_EXCUTING_CONTINUE);
}
int HandleTestCommand::cmd_write_long_ndef_message(int argc, char *argv[])
{
size_t length, idx, sourceLength;
static const char alphabet[] = "thequickbrownfoxjumpedoverthelazydog";
char *data;
const char *sourceMessage;
// expect 2 or 3 args "<cmd> <length> [optional-text]"
if (argc < 2) {
cmd_printf("supply length of message\r\n");
return (CMDLINE_RETCODE_INVALID_PARAMETERS);
}
int converted = sscanf(argv[1], "%d", &length);
if (1 != converted) {
cmd_printf("Cannot convert value to int\r\n");
return (CMDLINE_RETCODE_INVALID_PARAMETERS);
}
// check that it would not overflow
if (length > MBED_CONF_APP_TEST_NDEF_MSG_MAX) {
cmd_printf("Buffer length may not exceed %d !\r\n", (int)MBED_CONF_APP_TEST_NDEF_MSG_MAX);
return (CMDLINE_RETCODE_FAIL);
}
data = (char *) malloc(length + 1);
if (!data) {
cmd_printf("WARN out of memory!\r\n");
return (CMDLINE_RETCODE_FAIL);
}
if (argc > 2) {
// user provided text to copy into text NDEF record
sourceMessage = argv[2];
} else {
// use our internal default message to copy into the text NDEF
sourceMessage = alphabet;
}
sourceLength = strlen(sourceMessage);
for (idx = 0; idx < length; idx++) {
data[idx] = sourceMessage[idx % sourceLength];
}
data[length] = '\0';
// method must release buffer
_nfcQueue.call(pNFC_Test_Shim, &NFCTestShim::cmd_write_long, data);
return (CMDLINE_RETCODE_EXCUTING_CONTINUE);
}
int HandleTestCommand::cmd_start_discovery(int argc, char *argv[])
{
if ((argc > 1) && (0 == strcmp(argv[1], "man"))) {
trace_printf("User must restart discovery manually()\r\n");
_nfcQueue.call(pNFC_Test_Shim, &NFCTestShim::cmd_start_discovery, false);
} else {
trace_printf("App will restart discovery loop on auto()\r\n");
_nfcQueue.call(pNFC_Test_Shim, &NFCTestShim::cmd_start_discovery, true);
}
return (CMDLINE_RETCODE_EXCUTING_CONTINUE);
}
int HandleTestCommand::cmd_stop_discovery(int argc, char *argv[])
{
_nfcQueue.call(pNFC_Test_Shim, &NFCTestShim::cmd_stop_discovery);
return (CMDLINE_RETCODE_EXCUTING_CONTINUE);
}
int HandleTestCommand::cmd_get_supported_rf_protocols(int argc, char *argv[])
{
_nfcQueue.call(pNFC_Test_Shim, &NFCTestShim::cmd_get_rf_protocols);
return (CMDLINE_RETCODE_EXCUTING_CONTINUE);
}
bool HandleTestCommand::set_protocol_target(
nfc_rf_protocols_bitmask_t &bitmask, const char *protocolName)
{
bool parsed = false;
if (0 == strcmp(protocolName, "t1t")) {
parsed = bitmask.target_t1t = true;
}
if (0 == strcmp(protocolName, "t2t")) {
parsed = bitmask.target_t2t = true;
}
if (0 == strcmp(protocolName, "t3t")) {
parsed = bitmask.target_t3t = true;
}
if (0 == strcmp(protocolName, "t5t")) {
parsed = bitmask.target_t5t = true;
}
if (0 == strcmp(protocolName, "isodep")) {
parsed = bitmask.target_iso_dep = true;
}
if (0 == strcmp(protocolName, "nfcdep")) {
parsed = bitmask.target_nfc_dep = true;
}
return (parsed);
}
int HandleTestCommand::cmd_configure_rf_protocols(int argc, char *argv[])
{
nfc_rf_protocols_bitmask_t protocols = { 0 };
int argindex = argc;
while (argindex > 1) {
if (!set_protocol_target(protocols, argv[argindex - 1])) {
cmd_printf("Unknown protocol %s", argv[argindex - 1]);
return (CMDLINE_RETCODE_INVALID_PARAMETERS);
}
argindex--;
}
_nfcQueue.call(pNFC_Test_Shim, &NFCTestShim::cmd_configure_rf_protocols,
protocols);
return (CMDLINE_RETCODE_EXCUTING_CONTINUE);
}

View File

@@ -0,0 +1,112 @@
/*
* 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 _NFCCOMMANDS_H_INCLUDED
#define _NFCCOMMANDS_H_INCLUDED
#if MBED_CONF_NFCEEPROM
#include "NFCProcessEEPROM.h"
#else
#include "NFCProcessCtrl.h"
#endif
// see https://support.microsoft.com/en-my/help/208427/maximum-url-length-is-2-083-characters-in-internet-explorer
#define MAX_URL_LENGTH 2000
#ifndef MBED_CONF_NFCEEPROM
#define MBED_CONF_NFCEEPROM false
#endif
/**
* \brief adds human-readable traces not needed by the framework, filter is via a switch set_trace_enable()
* \param fmt standard printf formatter
* \param varargs
*/
void trace_printf(const char *fmt, ...);
/**
* \brief turns on human readable traces
* \param enabled : set to false to disable the extra traces
*/
void set_trace_enable(bool enabled = true);
/**
* HandleTestCommand turns all the typed-in/serial commands into function calls sent via a eventqueue to the driver
* shim/wrapper class.
* Methods with cmd_ prefix map to the serial commands, and are building blocks for test cases and scenarios. The
* first function a test must call is typically the initnfc command. Commands report back a test verdict, and a
* NFC status code. The test verdict is always success unless the command is not allowed. Tests much check the
* NFC error code for NFC_OK or zero; this pattern allows us to write negative tests which expect a specific NFC error.
*
* Handlers are statics because the test framework is not supporting C++
*/
class HandleTestCommand {
public:
HandleTestCommand();
/** return and clear the last result code. Type "help getlastnfcerror" for a list of error codes */
static int cmd_get_last_nfc_error(int argc, char *argv[]);
/** internal function to test getlastnfcerror */
static int cmd_set_last_nfc_error(int argc, char *argv[]);
/** returns compile time flag if NFC EEPROM was compiled */
static int cmd_get_conf_nfceeprom(int argc, char *argv[]);
static int cmd_set_trace(int argc, char *argv[]);
/** For EEPROM, returns the driver max_ndef value, else returns the app config MBED_CONF_APP_TEST_NDEF_MSG_MAX */
static int cmd_get_max_ndef(int argc, char *argv[]);
/** Init must be called before invoking any other calls, obtains a driver reference and initializes driver */
static int cmd_init_nfc(int argc, char *argv[]);
/** write a smartposter url, 'Sp' NDEF to the target */
static int cmd_set_smartposter(int argc, char *argv[]);
/** erases the EEPROM if present */
static int cmd_erase(int argc, char *argv[]);
/** Returns a CSV list of protocols supported */
static int cmd_get_supported_rf_protocols(int argc, char *argv[]);
/** Sets the protocols supported (unimplemented) */
static int cmd_configure_rf_protocols(int argc, char *argv[]);
/** starts the NFC discovery loop if controller, has no effect on EEPROM */
static int cmd_start_discovery(int argc, char *argv[]);
/** stops the NFC discovery loop if controller */
static int cmd_stop_discovery(int argc, char *argv[]);
/** read raw EEPROM contents, reads a buffer if a controller is used */
static int cmd_read_message(int argc, char *argv[]);
/** write a text 'T' NDEF message to the target */
static int cmd_write_long_ndef_message(int argc, char *argv[]);
private:
/** set corresponding mask bit on in referenced structure, return false if the supplied string cannot parse */
static bool set_protocol_target(mbed::nfc::nfc_rf_protocols_bitmask_t &bitmask, const char *protocolName);
static NFCTestShim *new_testshim();
static void nfc_routine();
static events::EventQueue _nfcQueue;
};
// un-implemented or sparse support in drivers, so not covered
int cmd_is_iso7816_supported(int argc, char *argv[]);
int cmd_add_iso7816_application(int argc, char *argv[]);
int cmd_set_tagtype(int argc, char *argv[]);
int cmd_get_tagtype(int argc, char *argv[]);
#endif // _NFCCOMMANDS_H_INCLUDED

View File

@@ -0,0 +1,207 @@
/*
* 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.
*/
#include <stdio.h>
#include <stdarg.h>
#include <cstring>
#include <string.h>
#include "mbed_events.h"
#include "mbed-client-cli/ns_cmdline.h"
#include "nfc/stack/nfc_errors.h"
#include "nfc/ndef/common/Text.h"
#include "nfc/ndef/common/URI.h"
#include "nfc/ndef/common/Mime.h"
#include "nfc/ndef/MessageBuilder.h"
#include "nfc/ndef/common/util.h"
#include "NFCCommands.h"
#include "NFCProcessCtrl.h"
#include "SmartPoster.h"
using mbed::Span;
#if ! MBED_CONF_NFCEEPROM
using mbed::nfc::nfc_rf_protocols_bitmask_t;
using mbed::nfc::ndef::MessageBuilder;
using mbed::nfc::ndef::RecordType;
using mbed::nfc::ndef::Record;
using mbed::nfc::ndef::RecordID;
using mbed::nfc::ndef::RecordPayload;
using mbed::nfc::ndef::common::span_from_cstr;
using mbed::nfc::ndef::common::Mime;
using mbed::nfc::ndef::common::Text;
using mbed::nfc::ndef::common::URI;
using mbed::nfc::NFCController;
/**
* Implements NFCRemoteInitiator::Delegate, NFCController::Delegate
*/
NFCProcessController::NFCProcessController(events::EventQueue &queue) :
NFCTestShim(queue),
// pins: mosi, miso, sclk, ssel, irq, rst
_pn512_transport(D11, D12, D13, D10, A1, A0), _pn512_driver(
&_pn512_transport),
_nfc_controller(&_pn512_driver, &queue, _ndef_buffer)
{
}
/**
* Initialise and configure the NFC controller.
*
* @return NFC_OK in case of success or a meaningful error code in case of
* failure.
*/
nfc_err_t NFCProcessController::init()
{
trace_printf("init()\r\n");
// register callbacks
_nfc_controller.set_delegate(this);
return _nfc_controller.initialize();
}
void NFCProcessController::cmd_get_max_ndef()
{
cmd_printf("{{maxndef=%d}}\r\n", (int)MBED_CONF_APP_TEST_NDEF_MSG_MAX);
cmd_ready(CMDLINE_RETCODE_SUCCESS);
}
/**
* Start the discovery of peers.
*
* @return NFC_OK in case of success or a meaningful error code in case of
* failure.
*/
nfc_err_t NFCProcessController::start_discovery()
{
trace_printf("start_discovery()\r\n");
return _nfc_controller.start_discovery();
}
/**
* Stop discovery.
*
* @return NFC_OK in case of success or a meaningful error code in case of
* failure.
*/
nfc_err_t NFCProcessController::stop_discovery()
{
trace_printf("stop_discovery()\r\n");
return _nfc_controller.cancel_discovery();
}
nfc_rf_protocols_bitmask_t NFCProcessController::get_rf_protocols()
{
trace_printf("get_supported_rf_protocols()\r\n");
return _nfc_controller.get_supported_rf_protocols();
}
nfc_err_t NFCProcessController::set_rf_protocols(
nfc_rf_protocols_bitmask_t protocols)
{
trace_printf("configure_rf_protocols()\r\n");
return _nfc_controller.configure_rf_protocols(protocols);
}
/* ------------------------------------------------------------------------
* Implementation of NFCRemoteInitiator::Delegate
*/
void NFCProcessController::on_connected()
{
cmd_printf("on_connected()\r\n");
}
void NFCProcessController::on_disconnected()
{
cmd_printf("on_disconnected()\r\n");
// reset the state of the remote initiator
_nfc_remote_initiator->set_delegate(NULL);
_nfc_remote_initiator.reset();
// restart peer discovery
_nfc_controller.start_discovery();
}
void NFCProcessController::parse_ndef_message(
const Span<const uint8_t> &buffer)
{
size_t len = buffer.size();
// copy remotely written message into our dummy buffer
if (len <= sizeof(_ndef_write_buffer)) {
trace_printf("Store remote ndef message of size %d\r\n", len);
memcpy(_ndef_write_buffer, buffer.data(), len);
_ndef_write_buffer_used = len;
} else {
trace_printf("Remote ndef message of size %d too large!\r\n", len);
}
}
size_t NFCProcessController::build_ndef_message(const Span<uint8_t> &buffer)
{
trace_printf("Copying message %d bytes to query buffer\r\n",
_ndef_write_buffer_used);
memcpy(buffer.data(), _ndef_write_buffer, _ndef_write_buffer_used);
for (size_t k = 0; k < _ndef_write_buffer_used; k++) {
cmd_printf("%02x ", buffer[k]);
}
return _ndef_write_buffer_used;
}
const char *NFCProcessController::str_discovery_terminated_reason(
nfc_discovery_terminated_reason_t reason)
{
static const char *reasons[4] = { "completed", "cancelled", "rf error"};
switch (reason) {
case nfc_discovery_terminated_completed :
case nfc_discovery_terminated_canceled:
case nfc_discovery_terminated_rf_error:
return reasons[reason];
}
return "unexpected!";
}
void NFCProcessController::on_discovery_terminated(
nfc_discovery_terminated_reason_t reason)
{
trace_printf("on_discovery_terminated(%s)\r\n",
str_discovery_terminated_reason(reason));
if (reason != nfc_discovery_terminated_completed
&& this->_discovery_restart) {
start_discovery();
}
}
void NFCProcessController::on_nfc_initiator_discovered(
const SharedPtr<mbed::nfc::NFCRemoteInitiator> &nfc_initiator)
{
trace_printf("on_nfc_initiator_discovered()\r\n");
// setup the local remote initiator
_nfc_remote_initiator = nfc_initiator;
_nfc_remote_initiator->set_delegate(this);
_nfc_remote_initiator->connect();
}
#endif // #if ! MBED_CONF_NFCEEPROM

View File

@@ -0,0 +1,88 @@
/*
* 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 _NFCPROCESS_H_INCLUDED
#define _NFCPROCESS_H_INCLUDED
#include <string>
#include <vector>
#include <stdio.h>
#include <stdarg.h>
#include "mbed_events.h"
#include "nfc/ndef/MessageBuilder.h"
#include "nfc/ndef/common/URI.h"
#include "nfc/ndef/common/util.h"
#include "NFCTestShim.h"
#if !MBED_CONF_NFCEEPROM
#include "nfc/nfcdefinitions.h"
#ifdef TARGET_PN512
#include "nfc/controllers/PN512Driver.h"
#include "nfc/controllers/PN512SPITransportDriver.h"
#endif
#include "nfc/NFCRemoteInitiator.h"
#include "nfc/NFCController.h"
#include "nfc/ndef/common/util.h"
/**
* Wrapper class handles calls and callbacks for NFC controller drivers. Note, that users must call "start"
* in order to start the discovery loop for controllers. An internal buffer stores the NFC message and records.
*/
class NFCProcessController: NFCTestShim,
mbed::nfc::NFCRemoteInitiator::Delegate,
mbed::nfc::NFCController::Delegate {
public:
NFCProcessController(events::EventQueue &queue);
void cmd_get_max_ndef();
nfc_err_t init();
nfc_err_t start_discovery();
nfc_err_t stop_discovery();
mbed::nfc::nfc_rf_protocols_bitmask_t get_rf_protocols();
nfc_err_t set_rf_protocols(mbed::nfc::nfc_rf_protocols_bitmask_t protocols);
virtual void parse_ndef_message(const mbed::Span<const uint8_t> &buffer);
virtual size_t build_ndef_message(const mbed::Span<uint8_t> &buffer);
const char *str_discovery_terminated_reason(
nfc_discovery_terminated_reason_t reason);
private:
// these events are handled, to restart discovery
/**
* Implementation of NFCRemoteEndpoint::Delegate */
virtual void on_connected();
/**
* Implementation of NFCRemoteEndpoint::Delegate */
virtual void on_disconnected();
/**
* Implementation of NFCController::Delegate */
virtual void on_discovery_terminated(
nfc_discovery_terminated_reason_t reason);
/**
* Implementation of NFCController::Delegate */
virtual void on_nfc_initiator_discovered(
const SharedPtr<mbed::nfc::NFCRemoteInitiator> &nfc_initiator);
private:
mbed::nfc::PN512SPITransportDriver _pn512_transport;
mbed::nfc::PN512Driver _pn512_driver;
mbed::nfc::NFCController _nfc_controller;
SharedPtr<mbed::nfc::NFCRemoteInitiator> _nfc_remote_initiator;
};
#endif // Controller
#endif // _NFCPROCESS_H_INCLUDED

View File

@@ -0,0 +1,146 @@
/*
* 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.
*/
#include <stdio.h>
#include <stdarg.h>
#include <cstring>
#include <string.h>
#include <stdlib.h>
#include "mbed_events.h"
#include "mbed-client-cli/ns_cmdline.h"
#include "nfc/stack/nfc_errors.h"
#include "nfc/ndef/common/Text.h"
#include "nfc/ndef/common/URI.h"
#include "nfc/ndef/common/Mime.h"
#include "nfc/ndef/MessageBuilder.h"
#include "nfc/ndef/common/util.h"
#if MBED_CONF_NFCEEPROM
#include "NFCEEPROMDriver.h"
#include "NFCProcessEEPROM.h"
#include "SmartPoster.h"
using mbed::Span;
using mbed::nfc::ndef::MessageBuilder;
using mbed::nfc::ndef::RecordType;
using mbed::nfc::ndef::Record;
using mbed::nfc::ndef::RecordID;
using mbed::nfc::ndef::RecordPayload;
using mbed::nfc::ndef::common::span_from_cstr;
using mbed::nfc::ndef::common::Mime;
using mbed::nfc::ndef::common::Text;
using mbed::nfc::ndef::common::URI;
using mbed::nfc::NFCEEPROM;
using mbed::nfc::NFCEEPROMDriver;
// implements : mbed::nfc::NFCEEPROM::Delegate
NFCProcessEEPROM::NFCProcessEEPROM(events::EventQueue &queue, NFCEEPROMDriver &eeprom_driver) :
NFCTestShim(queue), _eeprom(&eeprom_driver, &queue, _ndef_buffer), _ptr_eeprom_driver(&eeprom_driver)
{}
nfc_err_t NFCProcessEEPROM::init()
{
nfc_err_t err = _eeprom.initialize();
if (err != NFC_OK) {
cmd_printf("NFCProcessEEPROM::init() (error: %d)!\r\n", err);
_queue.break_dispatch();
} else {
cmd_printf("NFCProcessEEPROM::init() OK\r\n");
}
_eeprom.set_delegate(this);
return (err);
}
void NFCProcessEEPROM::cmd_get_max_ndef()
{
cmd_printf("{{maxndef=%d}}\r\n", (int)_ptr_eeprom_driver->read_max_size());
cmd_ready(CMDLINE_RETCODE_SUCCESS);
}
void NFCProcessEEPROM::queue_write_call()
{
cmd_printf("NFCProcessEEPROM::queue_write_call() entry\r\n");
_queue.call(&_eeprom, &NFCEEPROM::write_ndef_message);
}
void NFCProcessEEPROM::queue_read_call()
{
cmd_printf("NFCProcessEEPROM::queue_read_call() entry\r\n");
_queue.call(&_eeprom, &NFCEEPROM::read_ndef_message);
}
void NFCProcessEEPROM::queue_erase_call()
{
cmd_printf("NFCProcessEEPROM::queue_erase_call() entry\r\n");
_queue.call(&_eeprom, &NFCEEPROM::erase_ndef_message);
}
void NFCProcessEEPROM::on_ndef_message_written(nfc_err_t result)
{
set_last_nfc_error(result);
if (result == NFC_OK) {
cmd_printf("message written successfully\r\n");
} else {
cmd_printf("Failed to write (error: %d)!\r\n", result);
}
// complete the async test method here
cmd_ready(CMDLINE_RETCODE_SUCCESS);
}
void NFCProcessEEPROM::on_ndef_message_read(nfc_err_t result)
{
set_last_nfc_error(result);
if (result == NFC_OK) {
cmd_printf("message read successfully\r\n");
} else {
cmd_printf("Failed to read (error: %d)!\r\n", result);
}
// complete the async test method here
cmd_ready(CMDLINE_RETCODE_SUCCESS);
}
void NFCProcessEEPROM::on_ndef_message_erased(nfc_err_t result)
{
set_last_nfc_error(result);
if (result == NFC_OK) {
cmd_printf("message erased successfully\r\n");
} else {
cmd_printf("Failed to erase (error: %d)!\r\n", result);
}
// complete the async test method here
cmd_ready(CMDLINE_RETCODE_SUCCESS);
}
void NFCProcessEEPROM::parse_ndef_message(const Span<const uint8_t> &buffer)
{
cmd_printf("Received an ndef message of size %d\r\n", buffer.size());
print_ndef_message(buffer, buffer.size());
}
size_t NFCProcessEEPROM::build_ndef_message(const Span<uint8_t> &buffer)
{
cmd_printf("Copying ndef message %d bytes into buffer\r\n", _ndef_write_buffer_used);
// make a copy into our buffer
memcpy(buffer.data(), _ndef_write_buffer, _ndef_write_buffer_used);
for (size_t k = 0; k < _ndef_write_buffer_used; k++) {
cmd_printf("%02x ", buffer[k]);
}
return _ndef_write_buffer_used;
}
#endif // MBED_CONF_NFCEEPROM

View File

@@ -0,0 +1,62 @@
/*
* 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 _NFCPROCESS_H_INCLUDED
#define _NFCPROCESS_H_INCLUDED
#include <string>
#include <vector>
#include <stdio.h>
#include <stdarg.h>
#include "nfc/ndef/MessageBuilder.h"
#include "nfc/ndef/common/URI.h"
#include "nfc/ndef/common/util.h"
#include "NFCTestShim.h"
#if MBED_CONF_NFCEEPROM
#include "NFCEEPROM.h"
#include "EEPROMDriver.h"
/**
* Wrapper class handles events specific to the EEPROM driver.
*/
class NFCProcessEEPROM : NFCTestShim, mbed::nfc::NFCEEPROM::Delegate {
public:
NFCProcessEEPROM(events::EventQueue &queue, mbed::nfc::NFCEEPROMDriver &eeprom_driver);
virtual nfc_err_t init();
void queue_write_call();
void queue_write_long_call();
void queue_read_call();
void queue_erase_call();
virtual void cmd_get_max_ndef();
private:
virtual void on_ndef_message_written(nfc_err_t result);
virtual void on_ndef_message_read(nfc_err_t result);
virtual void parse_ndef_message(const mbed::Span<const uint8_t> &buffer);
virtual size_t build_ndef_message(const mbed::Span<uint8_t> &buffer);
virtual void on_ndef_message_erased(nfc_err_t result);
private:
mbed::nfc::NFCEEPROM _eeprom;
mbed::nfc::NFCEEPROMDriver *_ptr_eeprom_driver;
};
#endif // eeprom
#endif // _NFCPROCESS_H_INCLUDED

View File

@@ -0,0 +1,408 @@
/*
* 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.
*/
#include <stdio.h>
#include <stdarg.h>
#include <cstring>
#include <string.h>
#include <stdlib.h>
#include "mbed-client-cli/ns_cmdline.h"
#include "nfc/ndef/common/Text.h"
#include "nfc/ndef/common/URI.h"
#include "nfc/ndef/common/Mime.h"
#include "nfc/ndef/MessageBuilder.h"
#include "nfc/ndef/common/util.h"
#include "nfc/nfcdefinitions.h"
#include "NFCEEPROMDriver.h"
#include "NFCCommands.h"
#include "NFCTestShim.h"
#include "SmartPoster.h"
using mbed::Span;
using mbed::nfc::ndef::MessageBuilder;
using mbed::nfc::ndef::RecordType;
using mbed::nfc::ndef::common::span_from_cstr;
using mbed::nfc::ndef::common::Text;
using mbed::nfc::ndef::common::URI;
using mbed::nfc::nfc_rf_protocols_bitmask_t;
// statics
namespace {
char const *uri_prefix_string[] = { "",
"http://www.",
"https://www.",
"http://",
"https://",
"tel:",
"mailto:",
"ftp://anonymous:anonymous@",
"ftp://ftp.",
"ftps://",
"sftp://",
"smb://",
"nfs://",
"ftp://",
"dav://",
"news:",
"telnet://",
"imap:",
"rstp://",
"urn:",
"pop:",
"sip:",
"sips:",
"tftp:",
"btspp://",
"btl2cap://",
"btgoep://",
"tcpobex://",
"irdaobex://",
"file://",
"urn:epc:id:",
"urn:epc:tag:",
"urn:epc:pat:",
"urn:epc:raw:",
"urn:epc:",
"urn:nfc:"
};
}
int NFCTestShim::last_nfc_error = 0;
NFCTestShim *pNFC_Test_Shim = NULL;
NFCTestShim::NFCTestShim(events::EventQueue &queue) :
_ndef_write_buffer_used(0), _ndef_poster_message(_ndef_write_buffer),
_discovery_restart(true), // on disconnect, will restart discovery
_queue(queue)
{
}
void NFCTestShim::cmd_get_last_nfc_error()
{
get_last_nfc_error();
}
void NFCTestShim::cmd_set_last_nfc_error(int err)
{
set_last_nfc_error(err);
cmd_ready(CMDLINE_RETCODE_SUCCESS);
}
void NFCTestShim::cmd_get_conf_nfceeprom()
{
get_conf_nfceeprom();
}
/** \brief The last failed NFC API call status, gets cleared upon reading it.
* \return void The NFC error is set asyncronously by sending text back over serial
*/
void NFCTestShim::get_last_nfc_error()
{
int last = last_nfc_error;
last_nfc_error = 0;
// return data as text to the plugin framework
cmd_printf("{{lastnfcerror=%d}}\r\n", last);
cmd_ready(CMDLINE_RETCODE_SUCCESS);
}
void NFCTestShim::set_last_nfc_error(int err)
{
last_nfc_error = err;
cmd_printf("\r\n{{lastnfcerror=%d}}\r\n", last_nfc_error);
}
// if an NFC EEPROM driver is configured
void NFCTestShim::get_conf_nfceeprom()
{
set_last_nfc_error(NFC_OK);
// return data as text to the plugin framework
cmd_printf("{{iseeprom=%s}}\r\n", (MBED_CONF_NFCEEPROM ? "true" : "false"));
cmd_ready(CMDLINE_RETCODE_SUCCESS);
}
void NFCTestShim::print_ndef_message(const Span<const uint8_t> &buffer,
size_t length)
{
// return data as text to the plugin framework
cmd_printf("{{nfcmessage=");
for (size_t k = 0; k < length; k++) {
cmd_printf("%02x ", buffer.data()[k]);
}
cmd_printf("}}\r\n");
}
URI::uri_identifier_code_t NFCTestShim::get_ndef_record_type(char const *url)
{
size_t i;
int len, bestLen = -1, index = -1;
// find largest matching prefix
for (i = 1; i < sizeof(uri_prefix_string) / sizeof(uri_prefix_string[0]); i++) {
len = strlen(uri_prefix_string[i]);
if (0 == strncmp(uri_prefix_string[i], url, len)) {
if (len > bestLen) {
index = i;
bestLen = len;
}
}
}
return (URI::uri_identifier_code_t)index;
}
char const *NFCTestShim::get_ndef_record_type_prefix(URI::uri_identifier_code_t id)
{
if ((id < 1) | (id > sizeof(uri_prefix_string) / sizeof(uri_prefix_string[0]))) {
return (""); // unknown case
}
return (::uri_prefix_string[(int)id]);
}
void NFCTestShim::cmd_init()
{
nfc_err_t ret = init();
set_last_nfc_error(ret);
if (NFC_OK != ret) {
cmd_ready(CMDLINE_RETCODE_FAIL);
} else {
cmd_ready(CMDLINE_RETCODE_SUCCESS);
}
}
void NFCTestShim::cmd_get_rf_protocols()
{
#if MBED_CONF_NFCEEPROM
cmd_printf("EEPROM cannot get protocol()\r\n");
set_last_nfc_error(NFC_ERR_UNSUPPORTED);
cmd_ready(CMDLINE_RETCODE_INVALID_PARAMETERS);
#else
nfc_rf_protocols_bitmask_t protocols = get_rf_protocols();
static char strSupported[7 * 6 + 1] = "";
if (protocols.target_t1t) {
strcat(strSupported, "t1t,");
}
if (protocols.target_t2t) {
strcat(strSupported, "t2t,");
}
if (protocols.target_t3t) {
strcat(strSupported, "t3t,");
}
if (protocols.target_iso_dep) {
strcat(strSupported, "isodep,");
}
if (protocols.target_nfc_dep) {
strcat(strSupported, "nfcdep,");
}
if (protocols.target_t5t) {
strcat(strSupported, "t5t,");
}
if (strlen(strSupported)) {
strSupported[strlen(strSupported) - 1] = '\0'; // strip trailing comma
}
// return data as text to the plugin framework
cmd_printf("{{protocols=%s}}", strSupported);
set_last_nfc_error(NFC_OK);
cmd_ready(CMDLINE_RETCODE_SUCCESS);
#endif
}
void NFCTestShim::cmd_configure_rf_protocols(
nfc_rf_protocols_bitmask_t protocols)
{
#if MBED_CONF_NFCEEPROM
cmd_printf("EEPROM cannot set protocol()\r\n");
set_last_nfc_error(NFC_ERR_UNSUPPORTED);
cmd_ready(CMDLINE_RETCODE_INVALID_PARAMETERS);
#else
nfc_err_t err = set_rf_protocols(protocols);
set_last_nfc_error(err);
if (NFC_OK != err) {
cmd_ready(CMDLINE_RETCODE_FAIL);
} else {
cmd_ready(CMDLINE_RETCODE_SUCCESS);
}
#endif
}
/** \brief Copy data from the Controller buffer, or if EEPROM will initiate a read of the
* eeprom contents which get dumped as a string {{bytes=XX XX XX XX.. }} and parsed by
* the framework
* \return void An ICETEA error code and NFC error is set asyncronously
*/
void NFCTestShim::cmd_read_nfc_contents()
{
#if MBED_CONF_NFCEEPROM
((NFCProcessEEPROM *)this)->queue_read_call();
trace_printf("NFCTestShim::cmd_read_nfc_contents() exit\r\n");
#else
// returns last message "written", since we cannot read
print_ndef_message(_ndef_write_buffer, _ndef_write_buffer_used);
trace_printf("Controller buffer data size=%d\r\n", _ndef_write_buffer_used);
set_last_nfc_error(NFC_OK);
trace_printf("NFCTestShim::cmd_read_nfc_contents() exit\r\n");
cmd_ready(CMDLINE_RETCODE_SUCCESS);
#endif
}
void NFCTestShim::cmd_erase()
{
#if MBED_CONF_NFCEEPROM
((NFCProcessEEPROM *)this)->queue_erase_call();
#else
trace_printf("Erase (reset) controller msg buffer\r\n");
_ndef_write_buffer_used = 0;
memset(_ndef_write_buffer, 0, sizeof(_ndef_write_buffer));
set_last_nfc_error(NFC_OK);
cmd_ready(CMDLINE_RETCODE_SUCCESS);
#endif
}
/** \brief Writes a Text T record buffer with really long message - length checks to be done by driver only.
* If an NFC controller, no write to the chip happens, we copy the data into a Controller buffer
* \param text_string This method must free the passed in pointer
* \return void An ICETEA error code and NFC error is set asynchronously
*/
void NFCTestShim::cmd_write_long(char *text_string)
{
MessageBuilder builder(_ndef_poster_message);
Text text(Text::UTF8, span_from_cstr("en-US"),
span_from_cstr((const char *)(text_string)));
text.append_as_record(builder, true);
_ndef_write_buffer_used = builder.get_message().size();
trace_printf("Composed NDEF message %d bytes\r\n", _ndef_write_buffer_used);
#if MBED_CONF_NFCEEPROM
((NFCProcessEEPROM *)this)->queue_write_call();
#else
// not on a wire, and we just stored the message in _ndef_write_buffer above
set_last_nfc_error(NFC_OK);
cmd_ready(CMDLINE_RETCODE_SUCCESS);
#endif
free(text_string); // free buffer allocated by the command class now
trace_printf("NFCTestShim::write_long() exit\r\n");
}
/** \brief Write a URI Use case would be to prompt to install an app from the appstore using the tag
* \param uri This method must free the passed in pointer
* \return void An ICETEA error code and NFC error is set asyncronously
*/
void NFCTestShim::cmd_set_smartposter(char *cmdUri)
{
MessageBuilder builder(_ndef_poster_message);
struct SPBuilder: MessageBuilder::PayloadBuilder {
SPBuilder(char *cmd_uri)
{
URI::uri_identifier_code_t uri_id = get_ndef_record_type(cmd_uri);
char *urlbegin = cmd_uri
+ strlen(get_ndef_record_type_prefix(uri_id));
uri = URI(uri_id, span_from_cstr(urlbegin));
cmd_printf("{{uri_id=%d}}\r\n", (int) uri_id);
}
virtual size_t size() const
{
return uri.get_record_size();
}
virtual void build(const Span<uint8_t> &buffer) const
{
MessageBuilder smart_poster_builder(buffer);
uri.append_as_record(smart_poster_builder, true);
}
URI uri;
};
builder.append_record(
RecordType(RecordType::well_known_type, span_from_cstr("Sp")),
SPBuilder(cmdUri), true);
_ndef_write_buffer_used = builder.get_message().size();
trace_printf("Composed NDEF message %d bytes\r\n", _ndef_write_buffer_used);
#if MBED_CONF_NFCEEPROM
((NFCProcessEEPROM *)this)->queue_write_call();
#else
// not on a wire, so the call just stores the message in a buffer
set_last_nfc_error(NFC_OK);
cmd_ready(CMDLINE_RETCODE_SUCCESS);
#endif
trace_printf("NFCTestShim::setsmartposter() exit\r\n");
free(cmdUri);
}
// disabled in EEPROMs, overridden if controller present
void NFCTestShim::cmd_start_discovery(bool manual)
{
#if MBED_CONF_NFCEEPROM
cmd_printf("EEPROM cannot start_discovery()\r\n");
set_last_nfc_error(NFC_ERR_UNSUPPORTED);
cmd_ready(CMDLINE_RETCODE_INVALID_PARAMETERS);
#else
// todo: Jira logged. remove hard coded protocol
nfc_rf_protocols_bitmask_t protocols = { 0 };
protocols.target_iso_dep = 1;
nfc_err_t err = set_rf_protocols(protocols);
if (manual) {
set_discovery_restart_manual();
} else {
set_discovery_restart_auto();
}
err = start_discovery();
set_last_nfc_error(err);
if (NFC_OK != err) {
cmd_ready(CMDLINE_RETCODE_FAIL);
} else {
cmd_ready(CMDLINE_RETCODE_SUCCESS);
}
#endif
}
// disabled in EEPROMs, overridden if controller present
void NFCTestShim::cmd_stop_discovery()
{
#if MBED_CONF_NFCEEPROM
cmd_printf("EEPROM cannot stop_discovery()\r\n");
set_last_nfc_error(NFC_ERR_UNSUPPORTED);
cmd_ready(CMDLINE_RETCODE_INVALID_PARAMETERS);
#else
nfc_err_t err = stop_discovery();
set_last_nfc_error(err);
if (NFC_OK != err) {
cmd_ready(CMDLINE_RETCODE_FAIL);
} else {
cmd_ready(CMDLINE_RETCODE_SUCCESS);
}
#endif
}

View File

@@ -0,0 +1,111 @@
/*
* 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 _NFCTESTSHIM_H_INCLUDED
#define _NFCTESTSHIM_H_INCLUDED
#include <string>
#include <vector>
#include <stdio.h>
#include <stdarg.h>
#include "mbed_config.h"
#include "nfc/ndef/MessageBuilder.h"
#include "nfc/ndef/common/URI.h"
#include "nfc/ndef/common/util.h"
#include "nfc/NFCDefinitions.h"
/**
* Test app driver wrapper. This is a base class containing shared EEPROM and Controller test data + logic.
* Variations for the 2 different kinds of driver supported are delegated to derived classes.
*/
class NFCTestShim {
public:
NFCTestShim(events::EventQueue &queue);
static void cmd_get_last_nfc_error();
static void cmd_set_last_nfc_error(int err);
static void cmd_get_conf_nfceeprom();
/**
* For an EEPROM, this queries and responds with the flash size,
* For a Controller, responds with the config macro TEST_NDEF_MSG_MAX
*/
virtual void cmd_get_max_ndef() = 0;
static void get_last_nfc_error();
static void set_last_nfc_error(int err);
static void get_conf_nfceeprom();
static void print_ndef_message(const mbed::Span<const uint8_t> &buffer,
size_t length);
static mbed::nfc::ndef::common::URI::uri_identifier_code_t get_ndef_record_type(char const *url);
static char const *get_ndef_record_type_prefix(mbed::nfc::ndef::common::URI::uri_identifier_code_t id);
void cmd_init();
void cmd_set_smartposter(char *cmdUri);
void cmd_erase();
void cmd_write_long(char *text_string);
void cmd_read_nfc_contents();
void cmd_start_discovery(bool manual = false);
void cmd_stop_discovery();
void cmd_configure_rf_protocols(mbed::nfc::nfc_rf_protocols_bitmask_t protocols);
void cmd_get_rf_protocols();
protected:
// implement/declare EEPROM and Controller model underlying common BH and delegate specializations
virtual nfc_err_t init() = 0;
virtual nfc_err_t set_rf_protocols(mbed::nfc::nfc_rf_protocols_bitmask_t protocols)
{
return NFC_ERR_UNSUPPORTED ;
};
virtual mbed::nfc::nfc_rf_protocols_bitmask_t get_rf_protocols()
{
mbed::nfc::nfc_rf_protocols_bitmask_t none;
memset((void *)&none, 0, sizeof(none));
return none;
};
virtual nfc_err_t start_discovery()
{
return NFC_ERR_UNSUPPORTED ;
};
virtual nfc_err_t stop_discovery()
{
return NFC_ERR_UNSUPPORTED ;
};
void set_discovery_restart_auto()
{
_discovery_restart = true;
};
void set_discovery_restart_manual()
{
_discovery_restart = false;
};
protected:
size_t _ndef_write_buffer_used;
mbed::Span<uint8_t> _ndef_poster_message; // message to build and send
uint8_t _ndef_write_buffer[MBED_CONF_APP_TEST_NDEF_MSG_MAX]; // if this buffer is smaller than the EEPROM, the driver may crash see IOTPAN-297
uint8_t _ndef_buffer[MBED_CONF_APP_TEST_NDEF_MSG_MAX]; // driver I/O buffer
bool _discovery_restart; // default true, restart discovery loop again on remote disconnect
events::EventQueue &_queue;
private:
static int last_nfc_error;
};
// forward declare single instance
extern NFCTestShim *pNFC_Test_Shim;
#endif // _NFCTESTSHIM_H_INCLUDED

View File

@@ -0,0 +1,247 @@
/* 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.
*/
#include "SmartPoster.h"
#include "nfc/ndef/common/Text.h"
#include "nfc/ndef/common/URI.h"
#include "nfc/ndef/common/Mime.h"
#include "nfc/ndef/MessageBuilder.h"
#include "nfc/ndef/common/util.h"
using mbed::Span;
using mbed::nfc::ndef::MessageBuilder;
using mbed::nfc::ndef::RecordType;
using mbed::nfc::ndef::Record;
using mbed::nfc::ndef::RecordID;
using mbed::nfc::ndef::RecordPayload;
using mbed::nfc::ndef::common::span_from_cstr;
using mbed::nfc::ndef::common::Mime;
using mbed::nfc::ndef::common::Text;
using mbed::nfc::ndef::common::URI;
// todo: this class probably needs to be in the nfc module itself
namespace {
static RecordType smart_poster_record_type()
{
return RecordType(RecordType::well_known_type, span_from_cstr("Sp"));
}
static RecordType action_record_type()
{
return RecordType(RecordType::well_known_type, span_from_cstr("act"));
}
static RecordType size_record_type()
{
return RecordType(RecordType::well_known_type, span_from_cstr("s"));
}
static RecordType type_record_type()
{
return RecordType(RecordType::well_known_type, span_from_cstr("T"));
}
static size_t compute_record_size(const RecordType &type,
const RecordPayload &payload)
{
return MessageBuilder::compute_record_size(
Record(type, payload, RecordID(), false, false));
}
} // end of anonymous namespace
SmartPoster::SmartPoster(const URI &uri) :
_uri(uri), _action(), _resource_size(0), _action_set(false), _resource_size_set(
false)
{
}
void SmartPoster::set_title(const Text &text)
{
_title = text;
}
void SmartPoster::set_icon(const Mime &icon)
{
_icon = icon;
}
void SmartPoster::set_action(action_t action)
{
_action = action;
_action_set = true;
}
void SmartPoster::set_resource_size(uint32_t size)
{
_resource_size = size;
_resource_size_set = true;
}
void SmartPoster::set_resource_type(Span<const uint8_t> &type)
{
_type.set_text(Text::UTF8, Span<const uint8_t>(), type);
}
bool SmartPoster::append_record(MessageBuilder &ndef_builder,
bool is_last_record) const
{
if (_uri.get_uri_field().empty()) {
return false;
}
struct PayloadBuilder: MessageBuilder::PayloadBuilder {
PayloadBuilder(const SmartPoster &sp) :
sp(sp)
{
}
virtual size_t size() const
{
return sp.get_uri_record_size() + sp.get_title_record_size()
+ sp.get_icon_record_size() + sp.get_action_record_size()
+ sp.get_resource_size_record_size()
+ sp.get_type_record_size();
}
virtual void build(const Span<uint8_t> &buffer) const
{
MessageBuilder smart_poster_builder(buffer);
sp.append_title(smart_poster_builder);
sp.append_icon(smart_poster_builder);
sp.append_resource_size(smart_poster_builder);
sp.append_type(smart_poster_builder);
sp.append_action(smart_poster_builder);
sp.append_uri(smart_poster_builder);
}
const SmartPoster &sp;
};
bool result = ndef_builder.append_record(smart_poster_record_type(),
PayloadBuilder(*this), is_last_record);
return result;
}
void SmartPoster::append_uri(MessageBuilder &builder) const
{
_uri.append_as_record(builder, true);
}
size_t SmartPoster::get_uri_record_size() const
{
return _uri.get_record_size();
}
void SmartPoster::append_title(MessageBuilder &builder) const
{
if (_title.get_text().empty()) {
return;
}
_title.append_as_record(builder);
}
size_t SmartPoster::get_title_record_size() const
{
if (_title.get_text().empty()) {
return 0;
}
return _title.get_record_size();
}
void SmartPoster::append_icon(MessageBuilder &builder) const
{
if (_icon.get_mime_content().empty()) {
return;
}
_icon.append_as_record(builder);
}
size_t SmartPoster::get_icon_record_size() const
{
if (_icon.get_mime_content().empty()) {
return 0;
}
return _icon.get_record_size();
}
void SmartPoster::append_action(MessageBuilder &builder) const
{
if (!_action_set) {
return;
}
const uint8_t action_value[1] = { _action };
builder.append_record(action_record_type(), action_value);
}
size_t SmartPoster::get_action_record_size() const
{
if (!_action_set) {
return 0;
}
const uint8_t action_value[1] = { _action };
return compute_record_size(action_record_type(), action_value);
}
void SmartPoster::append_resource_size(MessageBuilder &builder) const
{
if (!_resource_size_set) {
return;
}
uint8_t value[4];
std::reverse_copy(&_resource_size, &_resource_size + 4, value);
builder.append_record(size_record_type(), value);
}
size_t SmartPoster::get_resource_size_record_size() const
{
if (!_resource_size_set) {
return 0;
}
uint8_t value[4];
return compute_record_size(size_record_type(), value);
}
void SmartPoster::append_type(MessageBuilder &builder) const
{
if (_type.get_text().empty()) {
return;
}
builder.append_record(type_record_type(), _type.get_text());
}
size_t SmartPoster::get_type_record_size() const
{
if (_type.get_text().empty()) {
return 0;
}
return compute_record_size(type_record_type(), _type.get_text());
}

View File

@@ -0,0 +1,138 @@
/* 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 SMARTPOSTER_H_
#define SMARTPOSTER_H_
#include "nfc/ndef/common/Text.h"
#include "nfc/ndef/common/URI.h"
#include "nfc/ndef/common/Mime.h"
#include "nfc/ndef/MessageBuilder.h"
/**
* Smart poster object.
*
* A smart poster is one of the basic use case of NFC. It encapsulates a URI to
* a resource and meta-data of the resource.
*
* Meta-data are optional, they can be:
* - title: name of the resource
* - icon: image/media associated to the resource
* - action: Action the peer should execute upon reception of the smart poster
* - size: The size of the resource.
* - type: Mime type of the resource.
*
* @note It obeys to value semantic and can be copied around.
*/
class SmartPoster {
public:
typedef mbed::nfc::ndef::common::Mime Mime;
typedef mbed::nfc::ndef::common::Text Text;
typedef mbed::nfc::ndef::common::URI URI;
typedef mbed::nfc::ndef::MessageBuilder MessageBuilder;
/**
* Type of actions that should be executed upon smart poster reception.
*/
enum action_t {
EXECUTE, //!< EXECUTE
SAVE, //!< SAVE
EDIT //!< EDIT
};
/**
* Construct a smart poster.
*
* @param uri The URI to the resource.
*/
SmartPoster(const URI &uri);
/**
* Set the title of the resource.
*
* @param text The title of the resource to set.
*/
void set_title(const Text &text);
/**
* Set the icon of the resource.
*
* @param icon The icon to set.
*/
void set_icon(const Mime &icon);
/**
* Set the action to trigger upon smart poster reception.
*
* @param action The action to do upon reception.
*/
void set_action(action_t action);
/**
* Set the size of the resource.
*
* @param size The size of the resource.
*/
void set_resource_size(uint32_t size);
/**
* Set the type of the resource.
*
* @param resource_type The type of the resource pointed by the URI.
*/
void set_resource_type(mbed::Span<const uint8_t> &resource_type);
/**
* Append the smart poster as a ndef record.
*
* @param ndef_builder The message builder where the record is appended.
* @param is_last_record Indicates if this message is the last one.
*
* @return true if the message has been appended to the builder or false
* otherwise.
*/
bool append_record(MessageBuilder &ndef_builder, bool is_last_record) const;
private:
void append_uri(MessageBuilder &builder) const;
size_t get_uri_record_size() const;
void append_title(MessageBuilder &builder) const;
size_t get_title_record_size() const;
void append_icon(MessageBuilder &builder) const;
size_t get_icon_record_size() const;
void append_action(MessageBuilder &builder) const;
size_t get_action_record_size() const;
void append_resource_size(MessageBuilder &builder) const;
size_t get_resource_size_record_size() const;
void append_type(MessageBuilder &builder) const;
size_t get_type_record_size() const;
URI _uri;
Text _title;
Mime _icon;
action_t _action;
uint32_t _resource_size;
Text _type;
bool _action_set : 1;
bool _resource_size_set : 1;
};
#endif /* SMARTPOSTER_H_ */

View File

@@ -0,0 +1,157 @@
/*
* 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.
*/
#include <stdint.h>
#include <stdio.h>
#include <stdarg.h>
#include <string>
#include <vector>
#include <stdlib.h>
#include "platform/Span.h"
#include "mbed_events.h"
#include "mbed-client-cli/ns_cmdline.h"
#include "NFCTestShim.h"
#include "NFCCommands.h"
#if MBED_CONF_NFCEEPROM
using mbed::nfc::NFCEEPROM;
using mbed::nfc::NFCEEPROMDriver;
#else
#ifndef TARGET_PN512
#warning [NOT_SUPPORTED] NFC not supported for this target
#endif
#endif // MBED_CONF_NFCEEPROM
const char *errorcodes = // descriptions from nfc/stack/nfc_errors.h
" 0 NFC_OK\r\n"
" 1 NFC_ERR_UNKNOWN\r\n"
" 2 NFC_ERR_LENGTH\r\n"
" 3 NFC_ERR_NOT_FOUND\r\n"
" 4 NFC_ERR_UNSUPPORTED\r\n"
" 5 NFC_ERR_PARAMS\r\n"
" 6 NFC_ERR_BUFFER_TOO_SMALL\r\n"
" 7 NFC_ERR_TIMEOUT\r\n"
" 8 NFC_ERR_CRC\r\n"
" 9 NFC_ERR_NOPEER\r\n"
"10 NFC_ERR_PARITY\r\n"
"11 NFC_ERR_FIELD\r\n"
"12 NFC_ERR_COLLISION\r\n"
"13 NFC_ERR_WRONG_COMM\r\n"
"14 NFC_ERR_PROTOCOL\r\n"
"15 NFC_ERR_BUSY\r\n"
"16 NFC_ERR_CONTROLLER\r\n"
"17 NFC_ERR_HALTED\r\n"
"18 NFC_ERR_MAC\r\n"
"19 NFC_ERR_UNDERFLOW\r\n"
"20 NFC_ERR_DISCONNECTED\r\n"
"21 NFC_ERR_ABORTED\r\n";
void wrap_printf(const char *f, va_list a)
{
vprintf(f, a);
}
/** Disables VT100 etc. for easy manual UI interaction */
int set_easy_printer(int argc, char *argv[])
{
const char msg[][20] =
{ "echo off", "set --retcode true", "set --vt100 off" };
for (size_t i = 0; i < (sizeof(msg) / sizeof(msg[0])); i++) {
cmd_exe((char *) msg[i]);
}
return (CMDLINE_RETCODE_SUCCESS);
}
/**
* This test app can be used standalone interactively with at 115200 baud terminal. It is designed to work with the
* IceTea test framework https://os.mbed.com/docs/latest/tools/icetea-testing-applications.html . This app does
* not run test cases, it wraps functions in the API in ways that let us test multiple cases and scenarios.
* Test commands are routed in the CommandHandler class to an eventqueue, so it interfaces to the driver
* on a separate driver thread, which means test functions complete asynchronously.
* The driver is only called in a thread in the shim or wrapper class called NFCTestShim, which handles driver
* callbacks and completes the async part of a test function. NFCTestShim has specializations for NFC controllers
* and EEPROMS. The classes NFCProcessController and NFCProcessEEPROM respectively implement the needed specialization.
*
* If using an NFC EEPROM, an extra library is needed. Please see the documentation in the README.MD for instructions
* on how to modify this test for new drivers/targets, and the steps to run this test suite.
*/
int main()
{
cmd_init(&wrap_printf);
HandleTestCommand handleCommands; // For handling test commands and set nfc message queue
cmd_add("getlastnfcerror", HandleTestCommand::cmd_get_last_nfc_error,
"last NFC error code", errorcodes);
cmd_add("setlastnfcerror", HandleTestCommand::cmd_set_last_nfc_error,
"self-test", "for self-test only");
cmd_add("iseeprom", HandleTestCommand::cmd_get_conf_nfceeprom,
"get NFC configEEPROM present",
"true if config exists, else false");
cmd_add("initnfc", HandleTestCommand::cmd_init_nfc, "init NFC driver",
"call first");
cmd_add("getmaxndef", HandleTestCommand::cmd_get_max_ndef, "get max NDEF record target supports",
"returns the eeprom size, or max buffer if a controller");
cmd_add("init", HandleTestCommand::cmd_init_nfc, "alias initnfc",
"call first");
cmd_add("setsmartposter", HandleTestCommand::cmd_set_smartposter,
"send smartposter NDEF", "<uri>");
cmd_add("readmessage", HandleTestCommand::cmd_read_message,
"read EEPROM else return last message", "returns hex dump");
cmd_add("read", HandleTestCommand::cmd_read_message, "alias readmessage",
"returns hex dump");
cmd_add("erase", HandleTestCommand::cmd_erase,
"erase EEPROM or clear last message", "erase entire flash/buffer");
cmd_add("writelong", HandleTestCommand::cmd_write_long_ndef_message,
"fill T NDEF with pattern up to <length>",
"writelong <length> [messagetorepeat='thequickbrownfoxisadog']");
cmd_add("start", HandleTestCommand::cmd_start_discovery,
"start discovery [auto=autorestart|man=manual]",
"loop restarts by default, man to disable");
cmd_add("stop", HandleTestCommand::cmd_stop_discovery, "stop discovery",
"[wait=0] with optional wait for session end");
cmd_add("getprotocols", HandleTestCommand::cmd_get_supported_rf_protocols,
"get supported protocols", "returns CSV list, see setprotocols");
cmd_add("setprotocols", HandleTestCommand::cmd_configure_rf_protocols,
"set rf protocols", "-p [t1t]/[t2t]/[t3t]/[isodep]/[nfcdep]/[t5t]");
cmd_add("easy", set_easy_printer, "Use human readable terminal output",
"echo off,vt100 off,return-codes visible");
cmd_add("trace", HandleTestCommand::cmd_set_trace, "detailed tracing on/off, ",
"Defaults to enabled; values like 'on','true','1' all turn it on, anything else turns off detailed tracing.");
#if MBED_CONF_NFCEEPROM
cmd_printf("MBED NFC EEPROM defined\r\n");
#else
cmd_printf("MBED NFC Controller tests\r\n");
#endif
#ifdef TARGET_M24SR
cmd_printf("Using driver: M24SR\r\n");
#endif
#ifdef TARGET_PN512
cmd_printf("Using driver: PN512\r\n");
#endif
{
int c;
while ((c = getc(stdin)) != EOF) {
cmd_char_input(c);
}
}
return 0;
}

View File

@@ -0,0 +1,28 @@
{
"config": {
"TEST_NDEF_MSG_MAX": {
"help": "NFC-Driver buffer (EEPROM and Controller) maximum MAX Size of NFC message(s) driver buffer",
"value": 4096
}
},
"target_overrides": {
"DISCO_L475VG_IOT01A": {
"target.extra_labels_add": ["M24SR"],
"MBED_NFC_M24SR.nfceeprom": true
},
"NUCLEO_F401RE": {
"target.extra_labels_add": ["PN512"],
"MBED_NFC_M24SR.nfceeprom": false
},
"NUCLEO_F746ZG": {
"target.extra_labels_add": ["M24SR"],
"MBED_NFC_M24SR.X_NUCLEO_NFC01A1": true,
"MBED_NFC_M24SR.nfceeprom": true
},
"NUCLEO_F429ZI": {
"target.extra_labels_add": ["M24SR"],
"MBED_NFC_M24SR.X_NUCLEO_NFC01A1": true,
"MBED_NFC_M24SR.nfceeprom": true
}
}
}

View File

@@ -0,0 +1,46 @@
/*
* 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.
*/
#include <stdio.h>
#include <stdarg.h>
#include "platform/FileHandle.h"
#include "drivers/BufferedSerial.h"
/**
* Macros for setting console flow control.
*/
#define CONSOLE_FLOWCONTROL_RTS 1
#define CONSOLE_FLOWCONTROL_CTS 2
#define CONSOLE_FLOWCONTROL_RTSCTS 3
#define mbed_console_concat_(x) CONSOLE_FLOWCONTROL_##x
#define mbed_console_concat(x) mbed_console_concat_(x)
#define CONSOLE_FLOWCONTROL mbed_console_concat(MBED_CONF_TARGET_CONSOLE_UART_FLOW_CONTROL)
#define SERIAL_CONSOLE_BAUD_RATE 115200
mbed::FileHandle *mbed::mbed_override_console(int)
{
static mbed::BufferedSerial console(
STDIO_UART_TX, STDIO_UART_RX, SERIAL_CONSOLE_BAUD_RATE
);
#if CONSOLE_FLOWCONTROL == CONSOLE_FLOWCONTROL_RTS
mbed::console.set_flow_control(SerialBase::RTS, STDIO_UART_RTS, NC);
#elif CONSOLE_FLOWCONTROL == CONSOLE_FLOWCONTROL_CTS
mbed::console.set_flow_control(SerialBase::CTS, NC, STDIO_UART_CTS);
#elif CONSOLE_FLOWCONTROL == CONSOLE_FLOWCONTROL_RTSCTS
mbed::console.set_flow_control(SerialBase::RTSCTS, STDIO_UART_RTS, STDIO_UART_CTS);
#endif
return &console;
}