CLI example for NNN50
Dependencies: NNN50_WIFI_API
Fork of NNN50_WiFi_HelloWorld by
CLI_Source/command-interpreter.cpp@9:871fc0231c7f, 2017-09-14 (annotated)
- Committer:
- silviaChen
- Date:
- Thu Sep 14 01:48:08 2017 +0000
- Revision:
- 9:871fc0231c7f
Support both BLE UART service and WiFi CLI command
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
silviaChen | 9:871fc0231c7f | 1 | /** |
silviaChen | 9:871fc0231c7f | 2 | * File: command-interpreter.c |
silviaChen | 9:871fc0231c7f | 3 | * Description: processes commands incoming over the serial port. |
silviaChen | 9:871fc0231c7f | 4 | * |
silviaChen | 9:871fc0231c7f | 5 | * Copyright 2014 by CYNTEC Corporation. All rights reserved. |
silviaChen | 9:871fc0231c7f | 6 | */ |
silviaChen | 9:871fc0231c7f | 7 | |
silviaChen | 9:871fc0231c7f | 8 | #include <stdint.h> |
silviaChen | 9:871fc0231c7f | 9 | #include <string.h> |
silviaChen | 9:871fc0231c7f | 10 | #include "mbed.h" |
silviaChen | 9:871fc0231c7f | 11 | #include "command-interpreter.h" |
silviaChen | 9:871fc0231c7f | 12 | |
silviaChen | 9:871fc0231c7f | 13 | extern Serial console; |
silviaChen | 9:871fc0231c7f | 14 | |
silviaChen | 9:871fc0231c7f | 15 | // Command parsing state |
silviaChen | 9:871fc0231c7f | 16 | typedef struct { |
silviaChen | 9:871fc0231c7f | 17 | |
silviaChen | 9:871fc0231c7f | 18 | // Finite-state machine's current state. |
silviaChen | 9:871fc0231c7f | 19 | uint8_t state; |
silviaChen | 9:871fc0231c7f | 20 | |
silviaChen | 9:871fc0231c7f | 21 | // The command line is stored in this buffer. |
silviaChen | 9:871fc0231c7f | 22 | uint8_t buffer[CYNTEC_COMMAND_BUFFER_LENGTH]; |
silviaChen | 9:871fc0231c7f | 23 | |
silviaChen | 9:871fc0231c7f | 24 | // Indices of the tokens (command(s) and arguments) in the above buffer. |
silviaChen | 9:871fc0231c7f | 25 | uint8_t tokenIndices[MAX_TOKEN_COUNT]; |
silviaChen | 9:871fc0231c7f | 26 | |
silviaChen | 9:871fc0231c7f | 27 | // The number of tokens read in, including the command(s). |
silviaChen | 9:871fc0231c7f | 28 | uint8_t tokenCount; |
silviaChen | 9:871fc0231c7f | 29 | |
silviaChen | 9:871fc0231c7f | 30 | // Used while reading in the command line. |
silviaChen | 9:871fc0231c7f | 31 | uint8_t index; |
silviaChen | 9:871fc0231c7f | 32 | |
silviaChen | 9:871fc0231c7f | 33 | // First error found in this command. |
silviaChen | 9:871fc0231c7f | 34 | uint8_t error; |
silviaChen | 9:871fc0231c7f | 35 | |
silviaChen | 9:871fc0231c7f | 36 | // The token number of the first true argument after possible nested commands. |
silviaChen | 9:871fc0231c7f | 37 | uint8_t argOffset; |
silviaChen | 9:871fc0231c7f | 38 | |
silviaChen | 9:871fc0231c7f | 39 | //gill |
silviaChen | 9:871fc0231c7f | 40 | uint8_t totalBuffer[CYNTEC_COMMAND_BUFFER_LENGTH]; |
silviaChen | 9:871fc0231c7f | 41 | uint8_t totalIndex; |
silviaChen | 9:871fc0231c7f | 42 | |
silviaChen | 9:871fc0231c7f | 43 | } CyntecCommandState; |
silviaChen | 9:871fc0231c7f | 44 | |
silviaChen | 9:871fc0231c7f | 45 | static CyntecCommandState commandState; |
silviaChen | 9:871fc0231c7f | 46 | |
silviaChen | 9:871fc0231c7f | 47 | // Remember the previous character seen by emberProcessCommandString() to ignore |
silviaChen | 9:871fc0231c7f | 48 | // an LF following a CR. |
silviaChen | 9:871fc0231c7f | 49 | static uint8_t previousCharacter = 0; |
silviaChen | 9:871fc0231c7f | 50 | CyntecCommandEntry *cyntecCurrentCommand; |
silviaChen | 9:871fc0231c7f | 51 | |
silviaChen | 9:871fc0231c7f | 52 | enum { |
silviaChen | 9:871fc0231c7f | 53 | CMD_AWAITING_ARGUMENT, |
silviaChen | 9:871fc0231c7f | 54 | CMD_READING_ARGUMENT, |
silviaChen | 9:871fc0231c7f | 55 | CMD_READING_TO_EOL // clean up after error |
silviaChen | 9:871fc0231c7f | 56 | }; |
silviaChen | 9:871fc0231c7f | 57 | |
silviaChen | 9:871fc0231c7f | 58 | |
silviaChen | 9:871fc0231c7f | 59 | |
silviaChen | 9:871fc0231c7f | 60 | const char* cyntecCommandErrorNames[] = |
silviaChen | 9:871fc0231c7f | 61 | { |
silviaChen | 9:871fc0231c7f | 62 | "", |
silviaChen | 9:871fc0231c7f | 63 | "No such command;", |
silviaChen | 9:871fc0231c7f | 64 | "Wrong number of arguments;", |
silviaChen | 9:871fc0231c7f | 65 | "Argument out of range;", |
silviaChen | 9:871fc0231c7f | 66 | "Argument syntax error;", |
silviaChen | 9:871fc0231c7f | 67 | "No matched argument;", |
silviaChen | 9:871fc0231c7f | 68 | "Wrong command order;", |
silviaChen | 9:871fc0231c7f | 69 | "Invalid state to perform operation;", |
silviaChen | 9:871fc0231c7f | 70 | "Function call fail;" |
silviaChen | 9:871fc0231c7f | 71 | }; |
silviaChen | 9:871fc0231c7f | 72 | |
silviaChen | 9:871fc0231c7f | 73 | /** |
silviaChen | 9:871fc0231c7f | 74 | * @brief Converts a character representation of a hex to real value. |
silviaChen | 9:871fc0231c7f | 75 | * @param c is the hex value in char format |
silviaChen | 9:871fc0231c7f | 76 | * @return the value of the hex otherwise INVALID_HEX_CHARACTER |
silviaChen | 9:871fc0231c7f | 77 | */ |
silviaChen | 9:871fc0231c7f | 78 | |
silviaChen | 9:871fc0231c7f | 79 | uint8_t cyntecAtoi(uint8_t *str, uint8_t len) |
silviaChen | 9:871fc0231c7f | 80 | { |
silviaChen | 9:871fc0231c7f | 81 | uint8_t result = 0; |
silviaChen | 9:871fc0231c7f | 82 | uint8_t i = 0; |
silviaChen | 9:871fc0231c7f | 83 | |
silviaChen | 9:871fc0231c7f | 84 | while( *str != '\0' && i < len) |
silviaChen | 9:871fc0231c7f | 85 | { |
silviaChen | 9:871fc0231c7f | 86 | result *= 10; |
silviaChen | 9:871fc0231c7f | 87 | result = result + ( *str - '0' ); |
silviaChen | 9:871fc0231c7f | 88 | str++; |
silviaChen | 9:871fc0231c7f | 89 | i++; |
silviaChen | 9:871fc0231c7f | 90 | } |
silviaChen | 9:871fc0231c7f | 91 | |
silviaChen | 9:871fc0231c7f | 92 | return result; |
silviaChen | 9:871fc0231c7f | 93 | } |
silviaChen | 9:871fc0231c7f | 94 | int cyntecAtoInt(uint8_t *str) |
silviaChen | 9:871fc0231c7f | 95 | { |
silviaChen | 9:871fc0231c7f | 96 | int result = 0; |
silviaChen | 9:871fc0231c7f | 97 | uint8_t i = 0; |
silviaChen | 9:871fc0231c7f | 98 | bool is_negative = false; |
silviaChen | 9:871fc0231c7f | 99 | |
silviaChen | 9:871fc0231c7f | 100 | if (*str == '-') { |
silviaChen | 9:871fc0231c7f | 101 | is_negative = true; |
silviaChen | 9:871fc0231c7f | 102 | str++; |
silviaChen | 9:871fc0231c7f | 103 | } |
silviaChen | 9:871fc0231c7f | 104 | while( *str != '\0') |
silviaChen | 9:871fc0231c7f | 105 | { |
silviaChen | 9:871fc0231c7f | 106 | result *= 10; |
silviaChen | 9:871fc0231c7f | 107 | result = result + ( *str - '0' ); |
silviaChen | 9:871fc0231c7f | 108 | str++; |
silviaChen | 9:871fc0231c7f | 109 | i++; |
silviaChen | 9:871fc0231c7f | 110 | } |
silviaChen | 9:871fc0231c7f | 111 | |
silviaChen | 9:871fc0231c7f | 112 | if (is_negative) |
silviaChen | 9:871fc0231c7f | 113 | return -result; |
silviaChen | 9:871fc0231c7f | 114 | else |
silviaChen | 9:871fc0231c7f | 115 | return result; |
silviaChen | 9:871fc0231c7f | 116 | } |
silviaChen | 9:871fc0231c7f | 117 | uint8_t cyntecArgToUint8(uint8_t *str, uint8_t len) |
silviaChen | 9:871fc0231c7f | 118 | { |
silviaChen | 9:871fc0231c7f | 119 | uint8_t result = 0; |
silviaChen | 9:871fc0231c7f | 120 | uint8_t num[2]; |
silviaChen | 9:871fc0231c7f | 121 | uint8_t i; |
silviaChen | 9:871fc0231c7f | 122 | |
silviaChen | 9:871fc0231c7f | 123 | if ( len != 2 ) |
silviaChen | 9:871fc0231c7f | 124 | { |
silviaChen | 9:871fc0231c7f | 125 | return 0; |
silviaChen | 9:871fc0231c7f | 126 | } |
silviaChen | 9:871fc0231c7f | 127 | |
silviaChen | 9:871fc0231c7f | 128 | for ( i = 0 ; i < 2 ; i++ ) |
silviaChen | 9:871fc0231c7f | 129 | { |
silviaChen | 9:871fc0231c7f | 130 | if ('0' <= str[i] && str[i] <= '9') |
silviaChen | 9:871fc0231c7f | 131 | num[i] = str[i] - '0'; |
silviaChen | 9:871fc0231c7f | 132 | else if ('a' <= str[i] && str[i] <= 'f') |
silviaChen | 9:871fc0231c7f | 133 | num[i] = str[i] - 'a' + 10; |
silviaChen | 9:871fc0231c7f | 134 | else if ('A' <= str[i] && str[i] <= 'F') |
silviaChen | 9:871fc0231c7f | 135 | num[i] = str[i] - 'A' + 10; |
silviaChen | 9:871fc0231c7f | 136 | else |
silviaChen | 9:871fc0231c7f | 137 | return 0; |
silviaChen | 9:871fc0231c7f | 138 | } |
silviaChen | 9:871fc0231c7f | 139 | |
silviaChen | 9:871fc0231c7f | 140 | result |= num[0] << 4; |
silviaChen | 9:871fc0231c7f | 141 | result |= num[1] << 0; |
silviaChen | 9:871fc0231c7f | 142 | |
silviaChen | 9:871fc0231c7f | 143 | return result; |
silviaChen | 9:871fc0231c7f | 144 | } |
silviaChen | 9:871fc0231c7f | 145 | |
silviaChen | 9:871fc0231c7f | 146 | uint16_t cyntecAtoiUint16(uint8_t *str, uint8_t len) |
silviaChen | 9:871fc0231c7f | 147 | { |
silviaChen | 9:871fc0231c7f | 148 | uint16_t result = 0; |
silviaChen | 9:871fc0231c7f | 149 | uint16_t i = 0; |
silviaChen | 9:871fc0231c7f | 150 | |
silviaChen | 9:871fc0231c7f | 151 | while( *str != '\0' && i < len) |
silviaChen | 9:871fc0231c7f | 152 | { |
silviaChen | 9:871fc0231c7f | 153 | result *= 10; |
silviaChen | 9:871fc0231c7f | 154 | result = result + ( *str - '0' ); |
silviaChen | 9:871fc0231c7f | 155 | str++; |
silviaChen | 9:871fc0231c7f | 156 | i++; |
silviaChen | 9:871fc0231c7f | 157 | } |
silviaChen | 9:871fc0231c7f | 158 | |
silviaChen | 9:871fc0231c7f | 159 | return result; |
silviaChen | 9:871fc0231c7f | 160 | } |
silviaChen | 9:871fc0231c7f | 161 | |
silviaChen | 9:871fc0231c7f | 162 | uint16_t cyntecArgToUint16(uint8_t *str, uint8_t len) |
silviaChen | 9:871fc0231c7f | 163 | { |
silviaChen | 9:871fc0231c7f | 164 | uint16_t result = 0; |
silviaChen | 9:871fc0231c7f | 165 | uint8_t num[4]; |
silviaChen | 9:871fc0231c7f | 166 | uint8_t i; |
silviaChen | 9:871fc0231c7f | 167 | |
silviaChen | 9:871fc0231c7f | 168 | if ( len != 4 ) |
silviaChen | 9:871fc0231c7f | 169 | { |
silviaChen | 9:871fc0231c7f | 170 | return 0; |
silviaChen | 9:871fc0231c7f | 171 | } |
silviaChen | 9:871fc0231c7f | 172 | |
silviaChen | 9:871fc0231c7f | 173 | for ( i = 0 ; i < 4 ; i++ ) |
silviaChen | 9:871fc0231c7f | 174 | { |
silviaChen | 9:871fc0231c7f | 175 | if ('0' <= str[i] && str[i] <= '9') |
silviaChen | 9:871fc0231c7f | 176 | num[i] = str[i] - '0'; |
silviaChen | 9:871fc0231c7f | 177 | else if ('a' <= str[i] && str[i] <= 'f') |
silviaChen | 9:871fc0231c7f | 178 | num[i] = str[i] - 'a' + 10; |
silviaChen | 9:871fc0231c7f | 179 | else if ('A' <= str[i] && str[i] <= 'F') |
silviaChen | 9:871fc0231c7f | 180 | num[i] = str[i] - 'A' + 10; |
silviaChen | 9:871fc0231c7f | 181 | else |
silviaChen | 9:871fc0231c7f | 182 | return 0; |
silviaChen | 9:871fc0231c7f | 183 | } |
silviaChen | 9:871fc0231c7f | 184 | |
silviaChen | 9:871fc0231c7f | 185 | result |= num[0] << 12; |
silviaChen | 9:871fc0231c7f | 186 | result |= num[1] << 8; |
silviaChen | 9:871fc0231c7f | 187 | result |= num[2] << 4; |
silviaChen | 9:871fc0231c7f | 188 | result |= num[3] << 0; |
silviaChen | 9:871fc0231c7f | 189 | |
silviaChen | 9:871fc0231c7f | 190 | return result; |
silviaChen | 9:871fc0231c7f | 191 | } |
silviaChen | 9:871fc0231c7f | 192 | |
silviaChen | 9:871fc0231c7f | 193 | //gill 20150918 |
silviaChen | 9:871fc0231c7f | 194 | uint32_t cyntecHexToUint32(uint8_t *str, uint8_t len) |
silviaChen | 9:871fc0231c7f | 195 | { |
silviaChen | 9:871fc0231c7f | 196 | if (len > 8) |
silviaChen | 9:871fc0231c7f | 197 | return 0; |
silviaChen | 9:871fc0231c7f | 198 | uint32_t result = 0; |
silviaChen | 9:871fc0231c7f | 199 | uint16_t i = 0; |
silviaChen | 9:871fc0231c7f | 200 | |
silviaChen | 9:871fc0231c7f | 201 | while( *str != '\0' && i < len) |
silviaChen | 9:871fc0231c7f | 202 | { |
silviaChen | 9:871fc0231c7f | 203 | result *= 16; |
silviaChen | 9:871fc0231c7f | 204 | result = result + ( *str - '0' ); |
silviaChen | 9:871fc0231c7f | 205 | str++; |
silviaChen | 9:871fc0231c7f | 206 | i++; |
silviaChen | 9:871fc0231c7f | 207 | } |
silviaChen | 9:871fc0231c7f | 208 | |
silviaChen | 9:871fc0231c7f | 209 | return result; |
silviaChen | 9:871fc0231c7f | 210 | } |
silviaChen | 9:871fc0231c7f | 211 | |
silviaChen | 9:871fc0231c7f | 212 | |
silviaChen | 9:871fc0231c7f | 213 | |
silviaChen | 9:871fc0231c7f | 214 | |
silviaChen | 9:871fc0231c7f | 215 | uint8_t cyntecStrCmp(uint8_t *src, uint8_t *dst, uint8_t len) |
silviaChen | 9:871fc0231c7f | 216 | { |
silviaChen | 9:871fc0231c7f | 217 | uint8_t i = 0; |
silviaChen | 9:871fc0231c7f | 218 | |
silviaChen | 9:871fc0231c7f | 219 | while ( *src != '\0' && *dst != '\0' && i < len ) |
silviaChen | 9:871fc0231c7f | 220 | { |
silviaChen | 9:871fc0231c7f | 221 | if ( *src != *dst ) |
silviaChen | 9:871fc0231c7f | 222 | return 0; |
silviaChen | 9:871fc0231c7f | 223 | i++; |
silviaChen | 9:871fc0231c7f | 224 | src++; |
silviaChen | 9:871fc0231c7f | 225 | dst++; |
silviaChen | 9:871fc0231c7f | 226 | } |
silviaChen | 9:871fc0231c7f | 227 | |
silviaChen | 9:871fc0231c7f | 228 | return 1; |
silviaChen | 9:871fc0231c7f | 229 | } |
silviaChen | 9:871fc0231c7f | 230 | |
silviaChen | 9:871fc0231c7f | 231 | // Initialize the state machine. |
silviaChen | 9:871fc0231c7f | 232 | void cyntecCommandReaderInit(void) |
silviaChen | 9:871fc0231c7f | 233 | { |
silviaChen | 9:871fc0231c7f | 234 | commandState.state = CMD_AWAITING_ARGUMENT; |
silviaChen | 9:871fc0231c7f | 235 | commandState.index = 0; |
silviaChen | 9:871fc0231c7f | 236 | commandState.tokenIndices[0] = 0; |
silviaChen | 9:871fc0231c7f | 237 | commandState.tokenCount = 0; |
silviaChen | 9:871fc0231c7f | 238 | commandState.error = CYNTEC_CMD_SUCCESS; |
silviaChen | 9:871fc0231c7f | 239 | commandState.argOffset = 0; |
silviaChen | 9:871fc0231c7f | 240 | cyntecCurrentCommand = NULL; |
silviaChen | 9:871fc0231c7f | 241 | commandState.totalIndex = 0; //gill |
silviaChen | 9:871fc0231c7f | 242 | } |
silviaChen | 9:871fc0231c7f | 243 | |
silviaChen | 9:871fc0231c7f | 244 | static uint8_t tokenLength(uint8_t num) |
silviaChen | 9:871fc0231c7f | 245 | { |
silviaChen | 9:871fc0231c7f | 246 | return (commandState.tokenIndices[num + 1] |
silviaChen | 9:871fc0231c7f | 247 | - commandState.tokenIndices[num]); |
silviaChen | 9:871fc0231c7f | 248 | } |
silviaChen | 9:871fc0231c7f | 249 | |
silviaChen | 9:871fc0231c7f | 250 | static uint8_t *tokenPointer(uint8_t tokenNum) |
silviaChen | 9:871fc0231c7f | 251 | { |
silviaChen | 9:871fc0231c7f | 252 | return (commandState.buffer + commandState.tokenIndices[tokenNum]); |
silviaChen | 9:871fc0231c7f | 253 | } |
silviaChen | 9:871fc0231c7f | 254 | |
silviaChen | 9:871fc0231c7f | 255 | void cyntecCommandActionHandler(const CommandAction action) |
silviaChen | 9:871fc0231c7f | 256 | { |
silviaChen | 9:871fc0231c7f | 257 | (*action)(); |
silviaChen | 9:871fc0231c7f | 258 | clearBuffer(); |
silviaChen | 9:871fc0231c7f | 259 | } |
silviaChen | 9:871fc0231c7f | 260 | |
silviaChen | 9:871fc0231c7f | 261 | static bool getNestedCommand(CyntecCommandEntry *entry, |
silviaChen | 9:871fc0231c7f | 262 | CyntecCommandEntry **nestedCommand) |
silviaChen | 9:871fc0231c7f | 263 | { |
silviaChen | 9:871fc0231c7f | 264 | if ( entry -> action == NULL ) { |
silviaChen | 9:871fc0231c7f | 265 | *nestedCommand = (CyntecCommandEntry*)entry->subMenu; |
silviaChen | 9:871fc0231c7f | 266 | return true; |
silviaChen | 9:871fc0231c7f | 267 | } else { |
silviaChen | 9:871fc0231c7f | 268 | return false; |
silviaChen | 9:871fc0231c7f | 269 | } |
silviaChen | 9:871fc0231c7f | 270 | } |
silviaChen | 9:871fc0231c7f | 271 | |
silviaChen | 9:871fc0231c7f | 272 | static void cyntecPrintCommandUsage(CyntecCommandEntry *entry) |
silviaChen | 9:871fc0231c7f | 273 | { |
silviaChen | 9:871fc0231c7f | 274 | CyntecCommandEntry *commandFinger; |
silviaChen | 9:871fc0231c7f | 275 | |
silviaChen | 9:871fc0231c7f | 276 | if (entry == NULL) { |
silviaChen | 9:871fc0231c7f | 277 | entry = commandFinger = cyntecCommandTable; |
silviaChen | 9:871fc0231c7f | 278 | } else { |
silviaChen | 9:871fc0231c7f | 279 | getNestedCommand(entry, &commandFinger); |
silviaChen | 9:871fc0231c7f | 280 | |
silviaChen | 9:871fc0231c7f | 281 | console.printf("%s-%s\r\n",entry->name,entry->description); |
silviaChen | 9:871fc0231c7f | 282 | } |
silviaChen | 9:871fc0231c7f | 283 | |
silviaChen | 9:871fc0231c7f | 284 | if ( commandFinger != NULL ) { |
silviaChen | 9:871fc0231c7f | 285 | for (; commandFinger->name != NULL; commandFinger++) { |
silviaChen | 9:871fc0231c7f | 286 | console.printf("%s - %s\r\n",commandFinger->name,commandFinger->description); |
silviaChen | 9:871fc0231c7f | 287 | } |
silviaChen | 9:871fc0231c7f | 288 | } |
silviaChen | 9:871fc0231c7f | 289 | |
silviaChen | 9:871fc0231c7f | 290 | } |
silviaChen | 9:871fc0231c7f | 291 | |
silviaChen | 9:871fc0231c7f | 292 | void cyntecCommandErrorHandler(uint8_t status) |
silviaChen | 9:871fc0231c7f | 293 | { |
silviaChen | 9:871fc0231c7f | 294 | //Silvia 20161111 modify |
silviaChen | 9:871fc0231c7f | 295 | console.printf("\r\nERROR;%s\r\n\r\n", cyntecCommandErrorNames[status]); |
silviaChen | 9:871fc0231c7f | 296 | cyntecPrintCommandUsage(cyntecCurrentCommand); |
silviaChen | 9:871fc0231c7f | 297 | } |
silviaChen | 9:871fc0231c7f | 298 | |
silviaChen | 9:871fc0231c7f | 299 | static CyntecCommandEntry *commandLookup(CyntecCommandEntry *commandFinger, |
silviaChen | 9:871fc0231c7f | 300 | uint8_t tokenNum) |
silviaChen | 9:871fc0231c7f | 301 | { |
silviaChen | 9:871fc0231c7f | 302 | uint8_t *inputCommand = tokenPointer(tokenNum); |
silviaChen | 9:871fc0231c7f | 303 | uint8_t inputLength = tokenLength(tokenNum); |
silviaChen | 9:871fc0231c7f | 304 | |
silviaChen | 9:871fc0231c7f | 305 | for (; commandFinger->name != NULL; commandFinger++) { |
silviaChen | 9:871fc0231c7f | 306 | const char *entryFinger = commandFinger->name; |
silviaChen | 9:871fc0231c7f | 307 | uint8_t *inputFinger = inputCommand; |
silviaChen | 9:871fc0231c7f | 308 | for (;; entryFinger++, inputFinger++) { |
silviaChen | 9:871fc0231c7f | 309 | bool endInput = (inputFinger - inputCommand == inputLength); |
silviaChen | 9:871fc0231c7f | 310 | bool endEntry = (*entryFinger == 0); |
silviaChen | 9:871fc0231c7f | 311 | if (endInput && endEntry) { |
silviaChen | 9:871fc0231c7f | 312 | return commandFinger; // Exact match. |
silviaChen | 9:871fc0231c7f | 313 | } else if ((*inputFinger) != (*entryFinger)) { |
silviaChen | 9:871fc0231c7f | 314 | break; |
silviaChen | 9:871fc0231c7f | 315 | } |
silviaChen | 9:871fc0231c7f | 316 | } |
silviaChen | 9:871fc0231c7f | 317 | } |
silviaChen | 9:871fc0231c7f | 318 | return NULL; |
silviaChen | 9:871fc0231c7f | 319 | } |
silviaChen | 9:871fc0231c7f | 320 | |
silviaChen | 9:871fc0231c7f | 321 | void callCommandAction(void) |
silviaChen | 9:871fc0231c7f | 322 | { |
silviaChen | 9:871fc0231c7f | 323 | CyntecCommandEntry *commandFinger = cyntecCommandTable; |
silviaChen | 9:871fc0231c7f | 324 | uint8_t tokenNum = 0; |
silviaChen | 9:871fc0231c7f | 325 | |
silviaChen | 9:871fc0231c7f | 326 | if (commandState.tokenCount == 0) { |
silviaChen | 9:871fc0231c7f | 327 | cyntecCommandReaderInit(); |
silviaChen | 9:871fc0231c7f | 328 | return; |
silviaChen | 9:871fc0231c7f | 329 | } |
silviaChen | 9:871fc0231c7f | 330 | |
silviaChen | 9:871fc0231c7f | 331 | // Lookup the command. |
silviaChen | 9:871fc0231c7f | 332 | while (true) { |
silviaChen | 9:871fc0231c7f | 333 | commandFinger = commandLookup(commandFinger, tokenNum); |
silviaChen | 9:871fc0231c7f | 334 | if (commandFinger == NULL) { |
silviaChen | 9:871fc0231c7f | 335 | commandState.error = CYNTEC_CMD_ERR_NO_SUCH_COMMAND; |
silviaChen | 9:871fc0231c7f | 336 | break; |
silviaChen | 9:871fc0231c7f | 337 | } else { |
silviaChen | 9:871fc0231c7f | 338 | cyntecCurrentCommand = commandFinger; |
silviaChen | 9:871fc0231c7f | 339 | tokenNum += 1; |
silviaChen | 9:871fc0231c7f | 340 | commandState.argOffset += 1; |
silviaChen | 9:871fc0231c7f | 341 | |
silviaChen | 9:871fc0231c7f | 342 | if ( getNestedCommand(commandFinger, &commandFinger) ) { |
silviaChen | 9:871fc0231c7f | 343 | if (tokenNum >= commandState.tokenCount) { |
silviaChen | 9:871fc0231c7f | 344 | commandState.error = CYNTEC_CMD_ERR_WRONG_NUMBER_OF_ARGUMENTS; |
silviaChen | 9:871fc0231c7f | 345 | break; |
silviaChen | 9:871fc0231c7f | 346 | } |
silviaChen | 9:871fc0231c7f | 347 | } else { |
silviaChen | 9:871fc0231c7f | 348 | break; |
silviaChen | 9:871fc0231c7f | 349 | } |
silviaChen | 9:871fc0231c7f | 350 | } |
silviaChen | 9:871fc0231c7f | 351 | } |
silviaChen | 9:871fc0231c7f | 352 | |
silviaChen | 9:871fc0231c7f | 353 | if (commandState.error == CYNTEC_CMD_SUCCESS) { |
silviaChen | 9:871fc0231c7f | 354 | cyntecCommandActionHandler(commandFinger->action); |
silviaChen | 9:871fc0231c7f | 355 | } else { |
silviaChen | 9:871fc0231c7f | 356 | cyntecCommandErrorHandler(commandState.error);; |
silviaChen | 9:871fc0231c7f | 357 | } |
silviaChen | 9:871fc0231c7f | 358 | |
silviaChen | 9:871fc0231c7f | 359 | cyntecCommandReaderInit(); |
silviaChen | 9:871fc0231c7f | 360 | } |
silviaChen | 9:871fc0231c7f | 361 | |
silviaChen | 9:871fc0231c7f | 362 | /* |
silviaChen | 9:871fc0231c7f | 363 | * |
silviaChen | 9:871fc0231c7f | 364 | */ |
silviaChen | 9:871fc0231c7f | 365 | void cyntecEndArgument(uint8_t input) |
silviaChen | 9:871fc0231c7f | 366 | { |
silviaChen | 9:871fc0231c7f | 367 | if (commandState.tokenCount == MAX_TOKEN_COUNT) { |
silviaChen | 9:871fc0231c7f | 368 | commandState.error = CYNTEC_CMD_ERR_WRONG_NUMBER_OF_ARGUMENTS; |
silviaChen | 9:871fc0231c7f | 369 | commandState.state = CMD_READING_TO_EOL; |
silviaChen | 9:871fc0231c7f | 370 | } |
silviaChen | 9:871fc0231c7f | 371 | |
silviaChen | 9:871fc0231c7f | 372 | commandState.tokenCount += 1; |
silviaChen | 9:871fc0231c7f | 373 | commandState.tokenIndices[commandState.tokenCount] = commandState.index; |
silviaChen | 9:871fc0231c7f | 374 | commandState.state = CMD_AWAITING_ARGUMENT; |
silviaChen | 9:871fc0231c7f | 375 | |
silviaChen | 9:871fc0231c7f | 376 | if (input == '\r' || input == '\n') { |
silviaChen | 9:871fc0231c7f | 377 | callCommandAction(); |
silviaChen | 9:871fc0231c7f | 378 | } |
silviaChen | 9:871fc0231c7f | 379 | } |
silviaChen | 9:871fc0231c7f | 380 | |
silviaChen | 9:871fc0231c7f | 381 | /* |
silviaChen | 9:871fc0231c7f | 382 | * |
silviaChen | 9:871fc0231c7f | 383 | */ |
silviaChen | 9:871fc0231c7f | 384 | void cyntecWriteToBuffer(uint8_t input) |
silviaChen | 9:871fc0231c7f | 385 | { |
silviaChen | 9:871fc0231c7f | 386 | if (commandState.index == CYNTEC_COMMAND_BUFFER_LENGTH) { |
silviaChen | 9:871fc0231c7f | 387 | commandState.error = CYNTEC_CMD_ERR_WRONG_NUMBER_OF_ARGUMENTS; |
silviaChen | 9:871fc0231c7f | 388 | commandState.state = CMD_READING_TO_EOL; |
silviaChen | 9:871fc0231c7f | 389 | } else { |
silviaChen | 9:871fc0231c7f | 390 | commandState.buffer[commandState.index] = input; |
silviaChen | 9:871fc0231c7f | 391 | commandState.index += 1; |
silviaChen | 9:871fc0231c7f | 392 | } |
silviaChen | 9:871fc0231c7f | 393 | } |
silviaChen | 9:871fc0231c7f | 394 | |
silviaChen | 9:871fc0231c7f | 395 | |
silviaChen | 9:871fc0231c7f | 396 | /* |
silviaChen | 9:871fc0231c7f | 397 | * Process the given char as a command. |
silviaChen | 9:871fc0231c7f | 398 | */ |
silviaChen | 9:871fc0231c7f | 399 | void cyntecProcessCommandInput(uint8_t input) { |
silviaChen | 9:871fc0231c7f | 400 | |
silviaChen | 9:871fc0231c7f | 401 | bool isEol = false; |
silviaChen | 9:871fc0231c7f | 402 | bool isSpace = false; |
silviaChen | 9:871fc0231c7f | 403 | |
silviaChen | 9:871fc0231c7f | 404 | if (previousCharacter == '\r' && input == '\n') { |
silviaChen | 9:871fc0231c7f | 405 | previousCharacter = input; |
silviaChen | 9:871fc0231c7f | 406 | return; |
silviaChen | 9:871fc0231c7f | 407 | } |
silviaChen | 9:871fc0231c7f | 408 | |
silviaChen | 9:871fc0231c7f | 409 | previousCharacter = input; |
silviaChen | 9:871fc0231c7f | 410 | isEol = ((input == '\r') || (input == '\n')); |
silviaChen | 9:871fc0231c7f | 411 | isSpace = (input == ' '); |
silviaChen | 9:871fc0231c7f | 412 | |
silviaChen | 9:871fc0231c7f | 413 | switch (commandState.state) { |
silviaChen | 9:871fc0231c7f | 414 | case CMD_AWAITING_ARGUMENT: |
silviaChen | 9:871fc0231c7f | 415 | if (!isEol) |
silviaChen | 9:871fc0231c7f | 416 | cyntecWriteToTotalBuffer(input); // total buffer including space |
silviaChen | 9:871fc0231c7f | 417 | if (isEol) { |
silviaChen | 9:871fc0231c7f | 418 | callCommandAction(); |
silviaChen | 9:871fc0231c7f | 419 | } else if (! isSpace) { |
silviaChen | 9:871fc0231c7f | 420 | commandState.state = CMD_READING_ARGUMENT; |
silviaChen | 9:871fc0231c7f | 421 | cyntecWriteToBuffer(input); |
silviaChen | 9:871fc0231c7f | 422 | } |
silviaChen | 9:871fc0231c7f | 423 | break; |
silviaChen | 9:871fc0231c7f | 424 | case CMD_READING_ARGUMENT: |
silviaChen | 9:871fc0231c7f | 425 | if (!isEol) |
silviaChen | 9:871fc0231c7f | 426 | cyntecWriteToTotalBuffer(input); |
silviaChen | 9:871fc0231c7f | 427 | if (isEol || isSpace) { |
silviaChen | 9:871fc0231c7f | 428 | cyntecEndArgument(input); |
silviaChen | 9:871fc0231c7f | 429 | } else { |
silviaChen | 9:871fc0231c7f | 430 | cyntecWriteToBuffer(input); |
silviaChen | 9:871fc0231c7f | 431 | } |
silviaChen | 9:871fc0231c7f | 432 | break; |
silviaChen | 9:871fc0231c7f | 433 | case CMD_READING_TO_EOL: |
silviaChen | 9:871fc0231c7f | 434 | if (isEol) { |
silviaChen | 9:871fc0231c7f | 435 | if (commandState.error != CYNTEC_CMD_SUCCESS) { |
silviaChen | 9:871fc0231c7f | 436 | cyntecCommandErrorHandler(commandState.error); |
silviaChen | 9:871fc0231c7f | 437 | } |
silviaChen | 9:871fc0231c7f | 438 | cyntecCommandReaderInit(); |
silviaChen | 9:871fc0231c7f | 439 | } |
silviaChen | 9:871fc0231c7f | 440 | break; |
silviaChen | 9:871fc0231c7f | 441 | } |
silviaChen | 9:871fc0231c7f | 442 | } |
silviaChen | 9:871fc0231c7f | 443 | |
silviaChen | 9:871fc0231c7f | 444 | |
silviaChen | 9:871fc0231c7f | 445 | /** Retrieves unsigned integer arguments. */ |
silviaChen | 9:871fc0231c7f | 446 | uint8_t *cyntecGetCommandArgument(uint8_t argNum, uint8_t *length) |
silviaChen | 9:871fc0231c7f | 447 | { |
silviaChen | 9:871fc0231c7f | 448 | uint8_t tokenNum = argNum + commandState.argOffset; |
silviaChen | 9:871fc0231c7f | 449 | |
silviaChen | 9:871fc0231c7f | 450 | if (length != NULL) { |
silviaChen | 9:871fc0231c7f | 451 | *length = tokenLength(tokenNum); |
silviaChen | 9:871fc0231c7f | 452 | } |
silviaChen | 9:871fc0231c7f | 453 | return tokenPointer(tokenNum); |
silviaChen | 9:871fc0231c7f | 454 | } |
silviaChen | 9:871fc0231c7f | 455 | |
silviaChen | 9:871fc0231c7f | 456 | void clearBuffer(void) |
silviaChen | 9:871fc0231c7f | 457 | { |
silviaChen | 9:871fc0231c7f | 458 | uint16_t i; |
silviaChen | 9:871fc0231c7f | 459 | for (i=0;i<CYNTEC_COMMAND_BUFFER_LENGTH;i++) |
silviaChen | 9:871fc0231c7f | 460 | { |
silviaChen | 9:871fc0231c7f | 461 | commandState.buffer[i] = NULL; |
silviaChen | 9:871fc0231c7f | 462 | } |
silviaChen | 9:871fc0231c7f | 463 | } |
silviaChen | 9:871fc0231c7f | 464 | |
silviaChen | 9:871fc0231c7f | 465 | /** Retrieves the token count. */ |
silviaChen | 9:871fc0231c7f | 466 | uint8_t cyntecGetCommandTokenCnt() |
silviaChen | 9:871fc0231c7f | 467 | { |
silviaChen | 9:871fc0231c7f | 468 | return commandState.tokenCount; |
silviaChen | 9:871fc0231c7f | 469 | } |
silviaChen | 9:871fc0231c7f | 470 | |
silviaChen | 9:871fc0231c7f | 471 | /* |
silviaChen | 9:871fc0231c7f | 472 | gill add for accept blank in name 20150904 |
silviaChen | 9:871fc0231c7f | 473 | uint8_t *cyntecGetCommandBuffer() |
silviaChen | 9:871fc0231c7f | 474 | void cyntecWriteToTotalBuffer(uint8_t input) |
silviaChen | 9:871fc0231c7f | 475 | uint8_t *cyntecGetCommandTotalBuffer(void) |
silviaChen | 9:871fc0231c7f | 476 | uint8_t cyntecGetTotalIndex(void) |
silviaChen | 9:871fc0231c7f | 477 | */ |
silviaChen | 9:871fc0231c7f | 478 | |
silviaChen | 9:871fc0231c7f | 479 | |
silviaChen | 9:871fc0231c7f | 480 | void cyntecWriteToTotalBuffer(uint8_t input) |
silviaChen | 9:871fc0231c7f | 481 | { |
silviaChen | 9:871fc0231c7f | 482 | if (commandState.totalIndex == CYNTEC_COMMAND_BUFFER_LENGTH) { |
silviaChen | 9:871fc0231c7f | 483 | commandState.error = CYNTEC_CMD_ERR_WRONG_NUMBER_OF_ARGUMENTS; |
silviaChen | 9:871fc0231c7f | 484 | commandState.state = CMD_READING_TO_EOL; |
silviaChen | 9:871fc0231c7f | 485 | } else { |
silviaChen | 9:871fc0231c7f | 486 | commandState.totalBuffer[commandState.totalIndex] = input; |
silviaChen | 9:871fc0231c7f | 487 | commandState.totalIndex += 1; |
silviaChen | 9:871fc0231c7f | 488 | } |
silviaChen | 9:871fc0231c7f | 489 | } |
silviaChen | 9:871fc0231c7f | 490 | |
silviaChen | 9:871fc0231c7f | 491 | uint8_t *cyntecGetCommandTotalBuffer(void) |
silviaChen | 9:871fc0231c7f | 492 | { |
silviaChen | 9:871fc0231c7f | 493 | return commandState.totalBuffer; |
silviaChen | 9:871fc0231c7f | 494 | } |
silviaChen | 9:871fc0231c7f | 495 | |
silviaChen | 9:871fc0231c7f | 496 | uint8_t cyntecGetTotalIndex(void) |
silviaChen | 9:871fc0231c7f | 497 | { |
silviaChen | 9:871fc0231c7f | 498 | return commandState.totalIndex; |
silviaChen | 9:871fc0231c7f | 499 | } |
silviaChen | 9:871fc0231c7f | 500 | |
silviaChen | 9:871fc0231c7f | 501 |