|
| 1 | +/* |
| 2 | + * Copyright (c) 2018 ARM Limited. All rights reserved. |
| 3 | + * SPDX-License-Identifier: Apache-2.0 |
| 4 | + * Licensed under the Apache License, Version 2.0 (the License); you may |
| 5 | + * not use this file except in compliance with the License. |
| 6 | + * You may obtain a copy of the License at |
| 7 | + * |
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | + * |
| 10 | + * Unless required by applicable law or agreed to in writing, software |
| 11 | + * distributed under the License is distributed on an AS IS BASIS, WITHOUT |
| 12 | + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | + * See the License for the specific language governing permissions and |
| 14 | + * limitations under the License. |
| 15 | + */ |
| 16 | +#include <string> |
| 17 | +#include <vector> |
| 18 | +#include <stdarg.h> |
| 19 | +#include <stdlib.h> |
| 20 | +#include <ctype.h> |
| 21 | +#include "mbed_events.h" |
| 22 | +#include "mbed-client-cli/ns_cmdline.h" |
| 23 | +#include "rtos/Thread.h" |
| 24 | +#include "NFCTestShim.h" |
| 25 | +#include "NFCCommands.h" |
| 26 | + |
| 27 | +#if MBED_CONF_NFCEEPROM |
| 28 | +#include "NFCEEPROMDriver.h" |
| 29 | +#include "NFCProcessEEPROM.h" |
| 30 | +#endif |
| 31 | + |
| 32 | +using mbed::nfc::nfc_rf_protocols_bitmask_t; |
| 33 | + |
| 34 | +events::EventQueue HandleTestCommand::_nfcQueue; |
| 35 | + |
| 36 | +rtos::Thread nfcThread; |
| 37 | +bool human_trace_enabled = true; |
| 38 | + |
| 39 | +NFCTestShim *HandleTestCommand::new_testshim() |
| 40 | +{ |
| 41 | +#if MBED_CONF_NFCEEPROM |
| 42 | + mbed::nfc::NFCEEPROMDriver &eeprom_driver = get_eeprom_driver(_nfcQueue); |
| 43 | + |
| 44 | + return ((NFCTestShim *)(new NFCProcessEEPROM(_nfcQueue, eeprom_driver))); |
| 45 | +#else |
| 46 | + return ((NFCTestShim *)(new NFCProcessController(_nfcQueue))); |
| 47 | +#endif // EEPROM |
| 48 | + |
| 49 | +} |
| 50 | + |
| 51 | +void HandleTestCommand::nfc_routine() |
| 52 | +{ |
| 53 | + _nfcQueue.dispatch_forever(); |
| 54 | +} |
| 55 | + |
| 56 | +void trace_printf(const char *fmt, ...) |
| 57 | +{ |
| 58 | + if (human_trace_enabled) { |
| 59 | + va_list ap; |
| 60 | + va_start(ap, fmt); |
| 61 | + cmd_vprintf(fmt, ap); |
| 62 | + va_end(ap); |
| 63 | + } |
| 64 | +} |
| 65 | + |
| 66 | +HandleTestCommand::HandleTestCommand() |
| 67 | +{ |
| 68 | + osStatus status = nfcThread.start(mbed::callback(&HandleTestCommand::nfc_routine)); |
| 69 | + MBED_ASSERT(status == osOK); |
| 70 | +} |
| 71 | + |
| 72 | +int HandleTestCommand::cmd_get_last_nfc_error(int argc, char *argv[]) |
| 73 | +{ |
| 74 | + _nfcQueue.call(NFCTestShim::cmd_get_last_nfc_error); |
| 75 | + return (CMDLINE_RETCODE_EXCUTING_CONTINUE); |
| 76 | +} |
| 77 | + |
| 78 | +/** returns compile time flag if NFC EEPROM was compiled */ |
| 79 | +int HandleTestCommand::cmd_get_conf_nfceeprom(int argc, char *argv[]) |
| 80 | +{ |
| 81 | + _nfcQueue.call(NFCTestShim::cmd_get_conf_nfceeprom); |
| 82 | + return (CMDLINE_RETCODE_EXCUTING_CONTINUE); |
| 83 | +} |
| 84 | + |
| 85 | + |
| 86 | + |
| 87 | +int HandleTestCommand::cmd_set_trace(int argc, char *argv[]) |
| 88 | +{ |
| 89 | + human_trace_enabled = false; |
| 90 | + if (argc > 1) { |
| 91 | + static char buffer[7]; |
| 92 | + char *p_buffer = buffer; |
| 93 | + strncpy(buffer, argv[1], sizeof(buffer) - 1); |
| 94 | + buffer[sizeof(buffer) - 1] = 0; |
| 95 | + while (*p_buffer) { |
| 96 | + *p_buffer = toupper(*p_buffer); |
| 97 | + p_buffer++; |
| 98 | + } |
| 99 | + cmd_printf(buffer); |
| 100 | + human_trace_enabled = (0 == strcmp(buffer, "TRUE")) || (0 == strcmp(buffer, "1")) || (0 == strcmp(buffer, "ON")); |
| 101 | + } |
| 102 | + cmd_printf("set trace '%s'", (human_trace_enabled ? "true" : "false")); |
| 103 | + return (CMDLINE_RETCODE_SUCCESS); |
| 104 | +} |
| 105 | + |
| 106 | + |
| 107 | +//////////////////////////////////////////////////////////////////////////////////// |
| 108 | + |
| 109 | +int HandleTestCommand::cmd_set_last_nfc_error(int argc, char *argv[]) |
| 110 | +{ |
| 111 | + if (argc <= 1) { |
| 112 | + cmd_printf("setlastnfcerror() invalid parameter(s)\r\n"); |
| 113 | + return (CMDLINE_RETCODE_INVALID_PARAMETERS); |
| 114 | + } else { |
| 115 | + int value = strtol(argv[1], NULL, 10); |
| 116 | + _nfcQueue.call(NFCTestShim::cmd_set_last_nfc_error, value); |
| 117 | + } |
| 118 | + return (CMDLINE_RETCODE_EXCUTING_CONTINUE); |
| 119 | +} |
| 120 | + |
| 121 | + |
| 122 | +int HandleTestCommand::cmd_get_max_ndef(int argc, char *argv[]) |
| 123 | +{ |
| 124 | + if (pNFC_Test_Shim) { |
| 125 | + _nfcQueue.call(pNFC_Test_Shim, &NFCTestShim::cmd_get_max_ndef); |
| 126 | + return CMDLINE_RETCODE_EXCUTING_CONTINUE; |
| 127 | + } |
| 128 | + return CMDLINE_RETCODE_FAIL; |
| 129 | +} |
| 130 | + |
| 131 | + |
| 132 | +int HandleTestCommand::cmd_init_nfc(int argc, char *argv[]) |
| 133 | +{ |
| 134 | + if (pNFC_Test_Shim) { |
| 135 | + cmd_printf("WARN init called again!\r\n"); // only legal here, if eeprom driver stops talking |
| 136 | + } else { |
| 137 | + pNFC_Test_Shim = new_testshim(); |
| 138 | + } |
| 139 | + _nfcQueue.call(pNFC_Test_Shim, &NFCTestShim::cmd_init); |
| 140 | + return (CMDLINE_RETCODE_EXCUTING_CONTINUE); |
| 141 | +} |
| 142 | + |
| 143 | +int HandleTestCommand::cmd_read_message(int argc, char *argv[]) |
| 144 | +{ |
| 145 | + _nfcQueue.call(pNFC_Test_Shim, &NFCTestShim::cmd_read_nfc_contents); |
| 146 | + |
| 147 | + return (CMDLINE_RETCODE_EXCUTING_CONTINUE); |
| 148 | +} |
| 149 | + |
| 150 | +int HandleTestCommand::cmd_set_smartposter(int argc, char *argv[]) |
| 151 | +{ |
| 152 | + // args are "setsmartposter", "<uri>" |
| 153 | + if (argc <= 1) { |
| 154 | + cmd_printf("setlastnfcerror() invalid parameter(s)\r\n"); |
| 155 | + return (CMDLINE_RETCODE_INVALID_PARAMETERS); |
| 156 | + } else { |
| 157 | + // parse arg and queue it up |
| 158 | + char *uri = (char *) malloc(strlen(argv[1]) + 1); |
| 159 | + if (uri) { |
| 160 | + strcpy(uri, argv[1]); |
| 161 | + _nfcQueue.call(pNFC_Test_Shim, &NFCTestShim::cmd_set_smartposter, |
| 162 | + uri); // called thread must free |
| 163 | + } else { |
| 164 | + cmd_printf("WARN out of memory!\r\n"); |
| 165 | + return (CMDLINE_RETCODE_FAIL); |
| 166 | + } |
| 167 | + } |
| 168 | + return (CMDLINE_RETCODE_EXCUTING_CONTINUE); |
| 169 | +} |
| 170 | + |
| 171 | +int HandleTestCommand::cmd_erase(int argc, char *argv[]) |
| 172 | +{ |
| 173 | + _nfcQueue.call(pNFC_Test_Shim, &NFCTestShim::cmd_erase); |
| 174 | + return (CMDLINE_RETCODE_EXCUTING_CONTINUE); |
| 175 | +} |
| 176 | + |
| 177 | +int HandleTestCommand::cmd_write_long_ndef_message(int argc, char *argv[]) |
| 178 | +{ |
| 179 | + size_t length, idx, sourceLength; |
| 180 | + static const char alphabet[] = "thequickbrownfoxjumpedoverthelazydog"; |
| 181 | + char *data; |
| 182 | + const char *sourceMessage; |
| 183 | + |
| 184 | + // expect 2 or 3 args "<cmd> <length> [optional-text]" |
| 185 | + if (argc < 2) { |
| 186 | + cmd_printf("supply length of message\r\n"); |
| 187 | + return (CMDLINE_RETCODE_INVALID_PARAMETERS); |
| 188 | + } |
| 189 | + |
| 190 | + int converted = sscanf(argv[1], "%d", &length); |
| 191 | + if (1 != converted) { |
| 192 | + cmd_printf("Cannot convert value to int\r\n"); |
| 193 | + return (CMDLINE_RETCODE_INVALID_PARAMETERS); |
| 194 | + } |
| 195 | + // check that it would not overflow |
| 196 | + if (length > MBED_CONF_APP_TEST_NDEF_MSG_MAX) { |
| 197 | + cmd_printf("Buffer length may not exceed %d !\r\n", (int)MBED_CONF_APP_TEST_NDEF_MSG_MAX); |
| 198 | + return (CMDLINE_RETCODE_FAIL); |
| 199 | + } |
| 200 | + |
| 201 | + data = (char *) malloc(length + 1); |
| 202 | + if (!data) { |
| 203 | + cmd_printf("WARN out of memory!\r\n"); |
| 204 | + return (CMDLINE_RETCODE_FAIL); |
| 205 | + } |
| 206 | + if (argc > 2) { |
| 207 | + // user provided text to copy into text NDEF record |
| 208 | + sourceMessage = argv[2]; |
| 209 | + } else { |
| 210 | + // use our internal default message to copy into the text NDEF |
| 211 | + sourceMessage = alphabet; |
| 212 | + } |
| 213 | + sourceLength = strlen(sourceMessage); |
| 214 | + for (idx = 0; idx < length; idx++) { |
| 215 | + data[idx] = sourceMessage[idx % sourceLength]; |
| 216 | + } |
| 217 | + data[length] = '\0'; |
| 218 | + |
| 219 | + // method must release buffer |
| 220 | + _nfcQueue.call(pNFC_Test_Shim, &NFCTestShim::cmd_write_long, data); |
| 221 | + return (CMDLINE_RETCODE_EXCUTING_CONTINUE); |
| 222 | +} |
| 223 | + |
| 224 | +int HandleTestCommand::cmd_start_discovery(int argc, char *argv[]) |
| 225 | +{ |
| 226 | + if ((argc > 1) && (0 == strcmp(argv[1], "man"))) { |
| 227 | + trace_printf("User must restart discovery manually()\r\n"); |
| 228 | + _nfcQueue.call(pNFC_Test_Shim, &NFCTestShim::cmd_start_discovery, false); |
| 229 | + } else { |
| 230 | + trace_printf("App will restart discovery loop on auto()\r\n"); |
| 231 | + _nfcQueue.call(pNFC_Test_Shim, &NFCTestShim::cmd_start_discovery, true); |
| 232 | + } |
| 233 | + return (CMDLINE_RETCODE_EXCUTING_CONTINUE); |
| 234 | +} |
| 235 | + |
| 236 | +int HandleTestCommand::cmd_stop_discovery(int argc, char *argv[]) |
| 237 | +{ |
| 238 | + _nfcQueue.call(pNFC_Test_Shim, &NFCTestShim::cmd_stop_discovery); |
| 239 | + return (CMDLINE_RETCODE_EXCUTING_CONTINUE); |
| 240 | +} |
| 241 | + |
| 242 | +int HandleTestCommand::cmd_get_supported_rf_protocols(int argc, char *argv[]) |
| 243 | +{ |
| 244 | + _nfcQueue.call(pNFC_Test_Shim, &NFCTestShim::cmd_get_rf_protocols); |
| 245 | + return (CMDLINE_RETCODE_EXCUTING_CONTINUE); |
| 246 | +} |
| 247 | + |
| 248 | +bool HandleTestCommand::set_protocol_target( |
| 249 | + nfc_rf_protocols_bitmask_t &bitmask, const char *protocolName) |
| 250 | +{ |
| 251 | + bool parsed = false; |
| 252 | + if (0 == strcmp(protocolName, "t1t")) { |
| 253 | + parsed = bitmask.target_t1t = true; |
| 254 | + } |
| 255 | + if (0 == strcmp(protocolName, "t2t")) { |
| 256 | + parsed = bitmask.target_t2t = true; |
| 257 | + } |
| 258 | + if (0 == strcmp(protocolName, "t3t")) { |
| 259 | + parsed = bitmask.target_t3t = true; |
| 260 | + } |
| 261 | + if (0 == strcmp(protocolName, "t5t")) { |
| 262 | + parsed = bitmask.target_t5t = true; |
| 263 | + } |
| 264 | + if (0 == strcmp(protocolName, "isodep")) { |
| 265 | + parsed = bitmask.target_iso_dep = true; |
| 266 | + } |
| 267 | + if (0 == strcmp(protocolName, "nfcdep")) { |
| 268 | + parsed = bitmask.target_nfc_dep = true; |
| 269 | + } |
| 270 | + return (parsed); |
| 271 | +} |
| 272 | + |
| 273 | +int HandleTestCommand::cmd_configure_rf_protocols(int argc, char *argv[]) |
| 274 | +{ |
| 275 | + nfc_rf_protocols_bitmask_t protocols = { 0 }; |
| 276 | + |
| 277 | + int argindex = argc; |
| 278 | + while (argindex > 1) { |
| 279 | + if (!set_protocol_target(protocols, argv[argindex - 1])) { |
| 280 | + cmd_printf("Unknown protocol %s", argv[argindex - 1]); |
| 281 | + return (CMDLINE_RETCODE_INVALID_PARAMETERS); |
| 282 | + } |
| 283 | + argindex--; |
| 284 | + } |
| 285 | + _nfcQueue.call(pNFC_Test_Shim, &NFCTestShim::cmd_configure_rf_protocols, |
| 286 | + protocols); |
| 287 | + return (CMDLINE_RETCODE_EXCUTING_CONTINUE); |
| 288 | +} |
| 289 | + |
0 commit comments