mirror of
https://github.com/RfidResearchGroup/ChameleonMini.git
synced 2026-05-12 11:20:37 -07:00
Had to make some minor changes to Commands.c and CommandLine.c to allow building without these codecs
628 lines
18 KiB
C
628 lines
18 KiB
C
/*
|
|
* CommandLine.c
|
|
*
|
|
* Created on: 04.05.2013
|
|
* Author: skuser
|
|
*/
|
|
|
|
#include "CommandLine.h"
|
|
#include "Settings.h"
|
|
#include "System.h"
|
|
|
|
#define CHAR_GET_MODE '?' /* <Command>? */
|
|
#define CHAR_SET_MODE '=' /* <Command>=<Param> */
|
|
#define CHAR_EXEC_MODE '\0' /* <Command> */
|
|
#define CHAR_EXEC_MODE_PARAM ' ' /* <Command> <Param> ... <ParamN> */
|
|
|
|
#define IS_COMMAND_DELIMITER(c) ( \
|
|
((c) == CHAR_EXEC_MODE) || ((c) == CHAR_GET_MODE) || ((c) == CHAR_SET_MODE) || ((c) == CHAR_EXEC_MODE_PARAM) \
|
|
)
|
|
|
|
#define IS_CHARACTER(c) ( \
|
|
( ((c) >= 'A') && ((c) <= 'Z') ) || \
|
|
( ((c) >= 'a') && ((c) <= 'z') ) || \
|
|
( ((c) >= '0') && ((c) <= '9') ) || \
|
|
( ((c) == '_') ) || \
|
|
( ((c) == CHAR_GET_MODE) || ((c) == CHAR_SET_MODE) || ((c) == CHAR_EXEC_MODE_PARAM) ) \
|
|
)
|
|
|
|
#define IS_LOWERCASE(c) ( ((c) >= 'a') && ((c) <= 'z') )
|
|
#define TO_UPPERCASE(c) ( (c) - 'a' + 'A' )
|
|
|
|
#define IS_WHITESPACE(c) ( ((c) == ' ') || ((c) == '\t') )
|
|
|
|
#define NO_FUNCTION ((void*) 0)
|
|
|
|
#define STATUS_MESSAGE_TRAILER "\r\n"
|
|
#define OPTIONAL_ANSWER_TRAILER "\r\n"
|
|
|
|
/* Include all command functions */
|
|
#include "Commands.h"
|
|
|
|
const PROGMEM CommandEntryType CommandTable[] = {
|
|
{
|
|
.Command = COMMAND_VERSION,
|
|
.ExecFunc = NO_FUNCTION,
|
|
.ExecParamFunc = NO_FUNCTION,
|
|
.SetFunc = NO_FUNCTION,
|
|
.GetFunc = CommandGetVersion,
|
|
},
|
|
{
|
|
.Command = COMMAND_CONFIG,
|
|
.ExecFunc = NO_FUNCTION,
|
|
.ExecParamFunc = NO_FUNCTION,
|
|
.SetFunc = CommandSetConfig,
|
|
.GetFunc = CommandGetConfig
|
|
},
|
|
{
|
|
.Command = COMMAND_UID,
|
|
.ExecFunc = NO_FUNCTION,
|
|
.ExecParamFunc = NO_FUNCTION,
|
|
.SetFunc = CommandSetUid,
|
|
.GetFunc = CommandGetUid
|
|
},
|
|
{
|
|
.Command = COMMAND_ATQA,
|
|
.ExecFunc = NO_FUNCTION,
|
|
.ExecParamFunc = NO_FUNCTION,
|
|
.SetFunc = CommandSetAtqa,
|
|
.GetFunc = CommandGetAtqa
|
|
},
|
|
{
|
|
.Command = COMMAND_SAK,
|
|
.ExecFunc = NO_FUNCTION,
|
|
.ExecParamFunc = NO_FUNCTION,
|
|
.SetFunc = CommandSetSak,
|
|
.GetFunc = CommandGetSak
|
|
},
|
|
{
|
|
.Command = COMMAND_READONLY,
|
|
.ExecFunc = NO_FUNCTION,
|
|
.ExecParamFunc = NO_FUNCTION,
|
|
.GetFunc = CommandGetReadOnly,
|
|
.SetFunc = CommandSetReadOnly
|
|
|
|
},
|
|
{
|
|
.Command = COMMAND_UPLOAD,
|
|
.ExecFunc = CommandExecUpload,
|
|
.ExecParamFunc = NO_FUNCTION,
|
|
.SetFunc = NO_FUNCTION,
|
|
.GetFunc = NO_FUNCTION
|
|
},
|
|
{
|
|
.Command = COMMAND_DOWNLOAD,
|
|
.ExecFunc = CommandExecDownload,
|
|
.ExecParamFunc = NO_FUNCTION,
|
|
.SetFunc = NO_FUNCTION,
|
|
.GetFunc = NO_FUNCTION
|
|
},
|
|
{
|
|
.Command = COMMAND_RESET,
|
|
.ExecFunc = CommandExecReset,
|
|
.ExecParamFunc = NO_FUNCTION,
|
|
.SetFunc = NO_FUNCTION,
|
|
.GetFunc = NO_FUNCTION
|
|
},
|
|
#ifdef SUPPORT_FIRMWARE_UPGRADE
|
|
{
|
|
.Command = COMMAND_UPGRADE,
|
|
.ExecFunc = CommandExecUpgrade,
|
|
.ExecParamFunc = NO_FUNCTION,
|
|
.SetFunc = NO_FUNCTION,
|
|
.GetFunc = NO_FUNCTION
|
|
},
|
|
#endif
|
|
{
|
|
.Command = COMMAND_MEMSIZE,
|
|
.ExecFunc = NO_FUNCTION,
|
|
.ExecParamFunc = NO_FUNCTION,
|
|
.SetFunc = NO_FUNCTION,
|
|
.GetFunc = CommandGetMemSize
|
|
},
|
|
{
|
|
.Command = COMMAND_UIDSIZE,
|
|
.ExecFunc = NO_FUNCTION,
|
|
.ExecParamFunc = NO_FUNCTION,
|
|
.SetFunc = NO_FUNCTION,
|
|
.GetFunc = CommandGetUidSize
|
|
},
|
|
{
|
|
.Command = COMMAND_RBUTTON,
|
|
.ExecFunc = NO_FUNCTION,
|
|
.ExecParamFunc = NO_FUNCTION,
|
|
.SetFunc = CommandSetRButton,
|
|
.GetFunc = CommandGetRButton
|
|
},
|
|
{
|
|
.Command = COMMAND_RBUTTON_LONG,
|
|
.ExecFunc = NO_FUNCTION,
|
|
.ExecParamFunc = NO_FUNCTION,
|
|
.SetFunc = CommandSetRButtonLong,
|
|
.GetFunc = CommandGetRButtonLong
|
|
},
|
|
{
|
|
.Command = COMMAND_LBUTTON,
|
|
.ExecFunc = NO_FUNCTION,
|
|
.ExecParamFunc = NO_FUNCTION,
|
|
.SetFunc = CommandSetLButton,
|
|
.GetFunc = CommandGetLButton
|
|
},
|
|
{
|
|
.Command = COMMAND_LBUTTON_LONG,
|
|
.ExecFunc = NO_FUNCTION,
|
|
.ExecParamFunc = NO_FUNCTION,
|
|
.SetFunc = CommandSetLButtonLong,
|
|
.GetFunc = CommandGetLButtonLong
|
|
},
|
|
{
|
|
.Command = COMMAND_LEDGREEN,
|
|
.ExecFunc = NO_FUNCTION,
|
|
.ExecParamFunc = NO_FUNCTION,
|
|
.SetFunc = CommandSetLedGreen,
|
|
.GetFunc = CommandGetLedGreen
|
|
},
|
|
{
|
|
.Command = COMMAND_LEDRED,
|
|
.ExecFunc = NO_FUNCTION,
|
|
.ExecParamFunc = NO_FUNCTION,
|
|
.SetFunc = CommandSetLedRed,
|
|
.GetFunc = CommandGetLedRed
|
|
},
|
|
{
|
|
.Command = COMMAND_LOGMODE,
|
|
.ExecFunc = NO_FUNCTION,
|
|
.ExecParamFunc = NO_FUNCTION,
|
|
.SetFunc = CommandSetLogMode,
|
|
.GetFunc = CommandGetLogMode
|
|
},
|
|
{
|
|
.Command = COMMAND_LOGMEM,
|
|
.ExecFunc = NO_FUNCTION,
|
|
.ExecParamFunc = NO_FUNCTION,
|
|
.SetFunc = NO_FUNCTION,
|
|
.GetFunc = CommandGetLogMem
|
|
},
|
|
{
|
|
.Command = COMMAND_LOGDOWNLOAD,
|
|
.ExecFunc = CommandExecLogDownload,
|
|
.ExecParamFunc = NO_FUNCTION,
|
|
.SetFunc = NO_FUNCTION,
|
|
.GetFunc = NO_FUNCTION
|
|
},
|
|
{
|
|
.Command = COMMAND_STORELOG,
|
|
.ExecFunc = CommandExecStoreLog,
|
|
.ExecParamFunc = NO_FUNCTION,
|
|
.SetFunc = NO_FUNCTION,
|
|
.GetFunc = NO_FUNCTION
|
|
},
|
|
{
|
|
.Command = COMMAND_LOGCLEAR,
|
|
.ExecFunc = CommandExecLogClear,
|
|
.ExecParamFunc = NO_FUNCTION,
|
|
.SetFunc = NO_FUNCTION,
|
|
.GetFunc = NO_FUNCTION
|
|
},
|
|
{
|
|
.Command = COMMAND_SETTING,
|
|
.ExecFunc = NO_FUNCTION,
|
|
.ExecParamFunc = NO_FUNCTION,
|
|
.SetFunc = CommandSetSetting,
|
|
.GetFunc = CommandGetSetting
|
|
},
|
|
{
|
|
.Command = COMMAND_CLEAR,
|
|
.ExecFunc = CommandExecClear,
|
|
.ExecParamFunc = NO_FUNCTION,
|
|
.SetFunc = NO_FUNCTION,
|
|
.GetFunc = NO_FUNCTION
|
|
},
|
|
{
|
|
.Command = COMMAND_STORE,
|
|
.ExecFunc = CommandExecStore,
|
|
.ExecParamFunc = NO_FUNCTION,
|
|
.SetFunc = NO_FUNCTION,
|
|
.GetFunc = NO_FUNCTION
|
|
},
|
|
{
|
|
.Command = COMMAND_RECALL,
|
|
.ExecFunc = CommandExecRecall,
|
|
.ExecParamFunc = NO_FUNCTION,
|
|
.SetFunc = NO_FUNCTION,
|
|
.GetFunc = NO_FUNCTION
|
|
},
|
|
{
|
|
.Command = COMMAND_CHARGING,
|
|
.ExecFunc = NO_FUNCTION,
|
|
.ExecParamFunc = NO_FUNCTION,
|
|
.SetFunc = NO_FUNCTION,
|
|
.GetFunc = CommandGetCharging
|
|
},
|
|
{
|
|
.Command = COMMAND_HELP,
|
|
.ExecFunc = CommandExecHelp,
|
|
.ExecParamFunc = NO_FUNCTION,
|
|
.SetFunc = NO_FUNCTION,
|
|
.GetFunc = NO_FUNCTION
|
|
},
|
|
{
|
|
.Command = COMMAND_RSSI,
|
|
.ExecFunc = NO_FUNCTION,
|
|
.ExecParamFunc = NO_FUNCTION,
|
|
.SetFunc = NO_FUNCTION,
|
|
.GetFunc = CommandGetRssi
|
|
},
|
|
{
|
|
.Command = COMMAND_SYSTICK,
|
|
.ExecFunc = NO_FUNCTION,
|
|
.ExecParamFunc = NO_FUNCTION,
|
|
.SetFunc = NO_FUNCTION,
|
|
.GetFunc = CommandGetSysTick
|
|
},
|
|
#ifdef CONFIG_ISO14443A_READER_SUPPORT
|
|
{
|
|
.Command = COMMAND_SEND_RAW,
|
|
.ExecFunc = NO_FUNCTION,
|
|
.ExecParamFunc = CommandExecParamSendRaw,
|
|
.SetFunc = NO_FUNCTION,
|
|
.GetFunc = NO_FUNCTION
|
|
},
|
|
{
|
|
.Command = COMMAND_SEND,
|
|
.ExecFunc = NO_FUNCTION,
|
|
.ExecParamFunc = CommandExecParamSend,
|
|
.SetFunc = NO_FUNCTION,
|
|
.GetFunc = NO_FUNCTION
|
|
},
|
|
{
|
|
.Command = COMMAND_GETUID,
|
|
.ExecFunc = CommandExecGetUid,
|
|
.ExecParamFunc = NO_FUNCTION,
|
|
.SetFunc = NO_FUNCTION,
|
|
.GetFunc = NO_FUNCTION
|
|
},
|
|
{
|
|
.Command = COMMAND_DUMP_MFU,
|
|
.ExecFunc = CommandExecDumpMFU,
|
|
.ExecParamFunc = NO_FUNCTION,
|
|
.SetFunc = NO_FUNCTION,
|
|
.GetFunc = NO_FUNCTION
|
|
},
|
|
{
|
|
.Command = COMMAND_CLONE_MFU,
|
|
.ExecFunc = CommandExecCloneMFU,
|
|
.ExecParamFunc = NO_FUNCTION,
|
|
.SetFunc = NO_FUNCTION,
|
|
.GetFunc = NO_FUNCTION
|
|
},
|
|
{
|
|
.Command = COMMAND_IDENTIFY_CARD,
|
|
.ExecFunc = CommandExecIdentifyCard,
|
|
.ExecParamFunc = NO_FUNCTION,
|
|
.SetFunc = NO_FUNCTION,
|
|
.GetFunc = NO_FUNCTION
|
|
},
|
|
#endif
|
|
{
|
|
.Command = COMMAND_TIMEOUT,
|
|
.ExecFunc = NO_FUNCTION,
|
|
.ExecParamFunc = NO_FUNCTION,
|
|
.SetFunc = CommandSetTimeout,
|
|
.GetFunc = CommandGetTimeout
|
|
},
|
|
{
|
|
.Command = COMMAND_THRESHOLD,
|
|
.ExecFunc = NO_FUNCTION,
|
|
.ExecParamFunc = NO_FUNCTION,
|
|
.SetFunc = CommandSetThreshold,
|
|
.GetFunc = CommandGetThreshold
|
|
},
|
|
{
|
|
.Command = COMMAND_AUTOCALIBRATE,
|
|
.ExecFunc = CommandExecAutocalibrate,
|
|
.ExecParamFunc = NO_FUNCTION,
|
|
.SetFunc = NO_FUNCTION,
|
|
.GetFunc = NO_FUNCTION
|
|
},
|
|
{
|
|
.Command = COMMAND_FIELD,
|
|
.ExecFunc = NO_FUNCTION,
|
|
.ExecParamFunc = NO_FUNCTION,
|
|
.SetFunc = CommandSetField,
|
|
.GetFunc = CommandGetField
|
|
},
|
|
#ifdef CONFIG_ISO14443A_READER_SUPPORT
|
|
{
|
|
.Command = COMMAND_CLONE,
|
|
.ExecFunc = CommandExecClone,
|
|
.ExecParamFunc = NO_FUNCTION,
|
|
.SetFunc = NO_FUNCTION,
|
|
.GetFunc = NO_FUNCTION
|
|
},
|
|
#endif
|
|
{
|
|
.Command = COMMAND_SETUIDMODE,
|
|
.ExecFunc = NO_FUNCTION,
|
|
.ExecParamFunc = NO_FUNCTION,
|
|
.SetFunc = CommandSetUidMode,
|
|
.GetFunc = CommandGetUidMode
|
|
},
|
|
{
|
|
.Command = COMMAND_SETSAKMODE,
|
|
.ExecFunc = NO_FUNCTION,
|
|
.ExecParamFunc = NO_FUNCTION,
|
|
.SetFunc = CommandSetSakMode,
|
|
.GetFunc = CommandGetSakMode
|
|
},
|
|
{
|
|
.Command = COMMAND_SETLEDMODE,
|
|
.ExecFunc = NO_FUNCTION,
|
|
.ExecParamFunc = NO_FUNCTION,
|
|
.SetFunc = CommandSetLedMode,
|
|
.GetFunc = CommandGetLedMode
|
|
},
|
|
{
|
|
.Command = COMMAND_DETECTION,
|
|
.ExecFunc = NO_FUNCTION,
|
|
.ExecParamFunc = NO_FUNCTION,
|
|
.SetFunc = CommandSetDetection,
|
|
.GetFunc = CommandGetDetection,
|
|
},
|
|
{
|
|
.Command = COMMAND_BAUDRATE,
|
|
.ExecFunc = NO_FUNCTION,
|
|
.ExecParamFunc = NO_FUNCTION,
|
|
// .SetFunc = CommandSetBaudrate,
|
|
.SetFunc = NO_FUNCTION,
|
|
.GetFunc = CommandGetBaudrate,
|
|
},
|
|
{
|
|
/* This has to be last element */
|
|
.Command = COMMAND_LIST_END,
|
|
.ExecFunc = NO_FUNCTION,
|
|
.ExecParamFunc = NO_FUNCTION,
|
|
.SetFunc = NO_FUNCTION,
|
|
.GetFunc = NO_FUNCTION
|
|
}
|
|
};
|
|
|
|
#define STATUS_TABLE_ENTRY(Id, Text) \
|
|
{ Id, STRINGIFY(Id) ":" Text }
|
|
|
|
typedef struct {
|
|
CommandStatusIdType Id;
|
|
CommandStatusMessageType Message;
|
|
} CommandStatusType;
|
|
|
|
static const CommandStatusType PROGMEM StatusTable[] = {
|
|
STATUS_TABLE_ENTRY(COMMAND_INFO_OK_ID, COMMAND_INFO_OK),
|
|
STATUS_TABLE_ENTRY(COMMAND_INFO_OK_WITH_TEXT_ID, COMMAND_INFO_OK_WITH_TEXT),
|
|
STATUS_TABLE_ENTRY(COMMAND_INFO_XMODEM_WAIT_ID, COMMAND_INFO_XMODEM_WAIT),
|
|
STATUS_TABLE_ENTRY(COMMAND_ERR_UNKNOWN_CMD_ID, COMMAND_ERR_UNKNOWN_CMD),
|
|
STATUS_TABLE_ENTRY(COMMAND_ERR_INVALID_USAGE_ID, COMMAND_ERR_INVALID_USAGE),
|
|
STATUS_TABLE_ENTRY(COMMAND_ERR_INVALID_PARAM_ID, COMMAND_ERR_INVALID_PARAM),
|
|
STATUS_TABLE_ENTRY(COMMAND_INFO_FALSE_ID, COMMAND_INFO_FALSE),
|
|
STATUS_TABLE_ENTRY(COMMAND_INFO_TRUE_ID, COMMAND_INFO_TRUE),
|
|
STATUS_TABLE_ENTRY(COMMAND_ERR_TIMEOUT_ID, COMMAND_ERR_TIMEOUT),
|
|
};
|
|
|
|
static uint16_t BufferIdx;
|
|
|
|
void (*CommandLinePendingTaskTimeout)(void) = NO_FUNCTION; // gets called on Timeout
|
|
static bool TaskPending = false;
|
|
static uint16_t TaskPendingSince;
|
|
|
|
static const char *GetStatusMessageP(CommandStatusIdType StatusId) {
|
|
uint8_t i;
|
|
|
|
for (i = 0; i < ARRAY_COUNT(StatusTable); i++) {
|
|
if (pgm_read_byte(&StatusTable[i].Id) == StatusId)
|
|
return StatusTable[i].Message;
|
|
}
|
|
|
|
return (void *) 0;
|
|
}
|
|
|
|
static CommandStatusIdType CallCommandFunc(
|
|
const CommandEntryType *CommandEntry, char CommandDelimiter, char *pParam) {
|
|
char *pTerminalBuffer = (char *) TerminalBuffer;
|
|
CommandStatusIdType Status = COMMAND_ERR_INVALID_USAGE_ID;
|
|
|
|
/* Call appropriate function depending on CommandDelimiter */
|
|
if (CommandDelimiter == CHAR_GET_MODE) {
|
|
CommandGetFuncType GetFunc = pgm_read_ptr(&CommandEntry->GetFunc);
|
|
if (GetFunc != NO_FUNCTION) {
|
|
Status = GetFunc(pTerminalBuffer);
|
|
}
|
|
} else if (CommandDelimiter == CHAR_SET_MODE) {
|
|
CommandSetFuncType SetFunc = pgm_read_ptr(&CommandEntry->SetFunc);
|
|
if (SetFunc != NO_FUNCTION) {
|
|
Status = SetFunc(pTerminalBuffer, pParam);
|
|
}
|
|
} else if (CommandDelimiter == CHAR_EXEC_MODE) {
|
|
CommandExecFuncType ExecFunc = pgm_read_ptr(&CommandEntry->ExecFunc);
|
|
if (ExecFunc != NO_FUNCTION) {
|
|
Status = ExecFunc(pTerminalBuffer);
|
|
}
|
|
} else if (CommandDelimiter == CHAR_EXEC_MODE_PARAM) {
|
|
CommandExecParamFuncType ExecParamFunc = pgm_read_ptr(&CommandEntry->ExecParamFunc);
|
|
if (ExecParamFunc != NO_FUNCTION) {
|
|
Status = ExecParamFunc(pTerminalBuffer, pParam);
|
|
}
|
|
} else {
|
|
/* This should not happen (TM) */
|
|
}
|
|
|
|
if (Status == TIMEOUT_COMMAND) {
|
|
TaskPending = true;
|
|
TaskPendingSince = SystemGetSysTick();
|
|
}
|
|
|
|
/* This delimiter has not been registered with this command */
|
|
return Status;
|
|
}
|
|
|
|
void CommandExecute(const char *command) {
|
|
uint8_t i;
|
|
|
|
for (i = 0; i < ARRAY_COUNT(CommandTable); i++) {
|
|
if (strcmp_P(command, CommandTable[i].Command) == 0) {
|
|
CallCommandFunc(&CommandTable[i], CHAR_EXEC_MODE, NULL);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void DecodeCommand(void) {
|
|
uint8_t i;
|
|
bool CommandFound = false;
|
|
CommandStatusIdType StatusId = COMMAND_ERR_UNKNOWN_CMD_ID;
|
|
char *pTerminalBuffer = (char *) TerminalBuffer;
|
|
|
|
/* Do some sanity check first */
|
|
if (!IS_COMMAND_DELIMITER(pTerminalBuffer[0])) {
|
|
char *pCommandDelimiter = pTerminalBuffer;
|
|
char CommandDelimiter = '\0';
|
|
|
|
/* Search for command delimiter, store it and replace with '\0' */
|
|
while (!(IS_COMMAND_DELIMITER(*pCommandDelimiter)))
|
|
pCommandDelimiter++;
|
|
|
|
CommandDelimiter = *pCommandDelimiter;
|
|
*pCommandDelimiter = '\0';
|
|
|
|
/* Search in command table */
|
|
for (i = 0; i < ARRAY_COUNT(CommandTable); i++) {
|
|
if (strcmp_P(pTerminalBuffer, CommandTable[i].Command) == 0) {
|
|
/* Command found. Clear buffer, and call appropriate function */
|
|
char *pParam = ++pCommandDelimiter;
|
|
|
|
pTerminalBuffer[0] = '\0';
|
|
CommandFound = true;
|
|
|
|
StatusId = CallCommandFunc(&CommandTable[i], CommandDelimiter, pParam);
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (StatusId == TIMEOUT_COMMAND) // it is a timeout command, so we return
|
|
return;
|
|
|
|
/* Send command status message */
|
|
TerminalSendStringP(GetStatusMessageP(StatusId));
|
|
TerminalSendStringP(PSTR(STATUS_MESSAGE_TRAILER));
|
|
|
|
if (CommandFound && (pTerminalBuffer[0] != '\0')) {
|
|
/* Send optional answer */
|
|
TerminalSendString(pTerminalBuffer);
|
|
TerminalSendStringP(PSTR(OPTIONAL_ANSWER_TRAILER));
|
|
}
|
|
}
|
|
|
|
void CommandLineInit(void) {
|
|
BufferIdx = 0;
|
|
}
|
|
|
|
bool CommandLineProcessByte(uint8_t Byte) {
|
|
if (IS_CHARACTER(Byte)) {
|
|
/* Store uppercase character */
|
|
if (IS_LOWERCASE(Byte)) {
|
|
Byte = TO_UPPERCASE(Byte);
|
|
}
|
|
|
|
/* Prevent buffer overflow and account for '\0' */
|
|
if (BufferIdx < TERMINAL_BUFFER_SIZE - 1) {
|
|
TerminalBuffer[BufferIdx++] = Byte;
|
|
}
|
|
} else if (Byte == '\r') {
|
|
/* Process on \r. Terminate string and decode. */
|
|
TerminalBuffer[BufferIdx] = '\0';
|
|
BufferIdx = 0;
|
|
|
|
if (!TaskPending)
|
|
DecodeCommand();
|
|
} else if (Byte == '\b') {
|
|
/* Backspace. Delete last character in buffer. */
|
|
if (BufferIdx > 0) {
|
|
BufferIdx--;
|
|
}
|
|
} else if (Byte == 0x1B) {
|
|
/* Drop buffer on escape */
|
|
BufferIdx = 0;
|
|
} else {
|
|
/* Ignore other chars */
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
INLINE void Timeout(void) {
|
|
TaskPending = false;
|
|
TerminalSendStringP(GetStatusMessageP(COMMAND_ERR_TIMEOUT_ID));
|
|
TerminalSendStringP(PSTR(STATUS_MESSAGE_TRAILER));
|
|
|
|
if (CommandLinePendingTaskTimeout != NO_FUNCTION) {
|
|
CommandLinePendingTaskTimeout(); // call the function that ends the task
|
|
CommandLinePendingTaskTimeout = NO_FUNCTION;
|
|
}
|
|
}
|
|
|
|
void CommandLineTick(void) {
|
|
if (TaskPending &&
|
|
GlobalSettings.ActiveSettingPtr->PendingTaskTimeout != 0 && // 0 means no timeout
|
|
SYSTICK_DIFF_100MS(TaskPendingSince) >= GlobalSettings.ActiveSettingPtr->PendingTaskTimeout) { // timeout expired
|
|
Timeout();
|
|
}
|
|
}
|
|
|
|
void CommandLinePendingTaskBreak(void) {
|
|
if (!TaskPending)
|
|
return;
|
|
|
|
Timeout();
|
|
}
|
|
|
|
void CommandLinePendingTaskFinished(CommandStatusIdType ReturnStatusID, char const *const OutMessage) {
|
|
if (!TaskPending) // if no task is pending, no task can be finished
|
|
return;
|
|
TaskPending = false;
|
|
|
|
TerminalSendStringP(GetStatusMessageP(ReturnStatusID));
|
|
TerminalSendStringP(PSTR(STATUS_MESSAGE_TRAILER));
|
|
|
|
if (OutMessage != NULL) {
|
|
TerminalSendString(OutMessage);
|
|
TerminalSendStringP(PSTR(OPTIONAL_ANSWER_TRAILER));
|
|
}
|
|
}
|
|
|
|
void CommandLineAppendData(void const *const Buffer, uint16_t Bytes) {
|
|
char *pTerminalBuffer = (char *) TerminalBuffer;
|
|
|
|
uint16_t tmpBytes = Bytes;
|
|
if (Bytes > (TERMINAL_BUFFER_SIZE / 2))
|
|
tmpBytes = TERMINAL_BUFFER_SIZE / 2;
|
|
Bytes -= tmpBytes;
|
|
|
|
BufferToHexString(pTerminalBuffer, TERMINAL_BUFFER_SIZE, Buffer, tmpBytes);
|
|
TerminalSendString(pTerminalBuffer);
|
|
|
|
uint8_t i = 1;
|
|
while (Bytes > (TERMINAL_BUFFER_SIZE / 2)) {
|
|
Bytes -= TERMINAL_BUFFER_SIZE / 2;
|
|
BufferToHexString(pTerminalBuffer, TERMINAL_BUFFER_SIZE, Buffer + i * TERMINAL_BUFFER_SIZE / 2, TERMINAL_BUFFER_SIZE);
|
|
TerminalSendString(pTerminalBuffer);
|
|
i++;
|
|
}
|
|
|
|
if (Bytes > 0) {
|
|
BufferToHexString(pTerminalBuffer, TERMINAL_BUFFER_SIZE, Buffer + i * TERMINAL_BUFFER_SIZE / 2, Bytes);
|
|
TerminalSendString(pTerminalBuffer);
|
|
}
|
|
|
|
TerminalSendStringP(PSTR(OPTIONAL_ANSWER_TRAILER));
|
|
}
|