Files

628 lines
18 KiB
C
Raw Permalink Normal View History

2016-10-07 23:44:50 +02:00
/*
* 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[] = {
2019-11-15 10:21:40 +01:00
{
.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
},
2019-11-15 10:21:40 +01:00
{
.Command = COMMAND_READONLY,
.ExecFunc = NO_FUNCTION,
.ExecParamFunc = NO_FUNCTION,
.GetFunc = CommandGetReadOnly,
.SetFunc = CommandSetReadOnly
2016-10-07 23:44:50 +02:00
2019-11-15 10:21:40 +01:00
},
{
.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
},
2016-10-07 23:44:50 +02:00
#ifdef SUPPORT_FIRMWARE_UPGRADE
2019-11-15 10:21:40 +01:00
{
.Command = COMMAND_UPGRADE,
.ExecFunc = CommandExecUpgrade,
.ExecParamFunc = NO_FUNCTION,
.SetFunc = NO_FUNCTION,
.GetFunc = NO_FUNCTION
},
2016-10-07 23:44:50 +02:00
#endif
2019-11-15 10:21:40 +01:00
{
.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
},
2020-10-14 20:22:46 +02:00
#ifdef CONFIG_ISO14443A_READER_SUPPORT
2019-11-15 10:21:40 +01:00
{
.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
},
2019-11-20 07:04:55 -06:00
{
.Command = COMMAND_CLONE_MFU,
.ExecFunc = CommandExecCloneMFU,
.ExecParamFunc = NO_FUNCTION,
.SetFunc = NO_FUNCTION,
.GetFunc = NO_FUNCTION
},
2019-11-15 10:21:40 +01:00
{
.Command = COMMAND_IDENTIFY_CARD,
.ExecFunc = CommandExecIdentifyCard,
.ExecParamFunc = NO_FUNCTION,
.SetFunc = NO_FUNCTION,
.GetFunc = NO_FUNCTION
},
2020-10-14 20:22:46 +02:00
#endif
2019-11-15 10:21:40 +01:00
{
.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
},
2020-10-14 20:22:46 +02:00
#ifdef CONFIG_ISO14443A_READER_SUPPORT
2019-11-15 10:21:40 +01:00
{
.Command = COMMAND_CLONE,
.ExecFunc = CommandExecClone,
.ExecParamFunc = NO_FUNCTION,
.SetFunc = NO_FUNCTION,
.GetFunc = NO_FUNCTION
},
2020-10-14 20:22:46 +02:00
#endif
2019-11-15 12:10:19 +01:00
{
.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
2019-11-15 10:21:40 +01:00
}
2016-10-07 23:44:50 +02:00
};
#define STATUS_TABLE_ENTRY(Id, Text) \
{ Id, STRINGIFY(Id) ":" Text }
typedef struct {
CommandStatusIdType Id;
CommandStatusMessageType Message;
} CommandStatusType;
static const CommandStatusType PROGMEM StatusTable[] = {
2019-11-15 10:21:40 +01:00
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),
2016-10-07 23:44:50 +02:00
};
static uint16_t BufferIdx;
2019-11-15 10:21:40 +01:00
void (*CommandLinePendingTaskTimeout)(void) = NO_FUNCTION; // gets called on Timeout
2016-10-07 23:44:50 +02:00
static bool TaskPending = false;
static uint16_t TaskPendingSince;
2019-11-15 10:21:40 +01:00
static const char *GetStatusMessageP(CommandStatusIdType StatusId) {
2016-10-07 23:44:50 +02:00
uint8_t i;
for (i = 0; i < ARRAY_COUNT(StatusTable); i++) {
2016-10-07 23:44:50 +02:00
if (pgm_read_byte(&StatusTable[i].Id) == StatusId)
return StatusTable[i].Message;
}
2019-11-15 10:21:40 +01:00
return (void *) 0;
2016-10-07 23:44:50 +02:00
}
static CommandStatusIdType CallCommandFunc(
2019-11-15 10:21:40 +01:00
const CommandEntryType *CommandEntry, char CommandDelimiter, char *pParam) {
char *pTerminalBuffer = (char *) TerminalBuffer;
CommandStatusIdType Status = COMMAND_ERR_INVALID_USAGE_ID;
2016-10-07 23:44:50 +02:00
2017-11-07 15:53:23 +01:00
/* 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) */
}
2016-10-07 23:44:50 +02:00
2019-11-15 10:21:40 +01:00
if (Status == TIMEOUT_COMMAND) {
2017-11-07 15:53:23 +01:00
TaskPending = true;
TaskPendingSince = SystemGetSysTick();
}
2016-10-07 23:44:50 +02:00
2017-11-07 15:53:23 +01:00
/* This delimiter has not been registered with this command */
return Status;
2016-10-07 23:44:50 +02:00
}
2019-11-15 10:21:40 +01:00
void CommandExecute(const char *command) {
uint8_t i;
2019-11-15 10:21:40 +01:00
for (i = 0; i < ARRAY_COUNT(CommandTable); i++) {
if (strcmp_P(command, CommandTable[i].Command) == 0) {
CallCommandFunc(&CommandTable[i], CHAR_EXEC_MODE, NULL);
break;
}
}
}
2019-11-15 10:21:40 +01:00
static void DecodeCommand(void) {
uint8_t i;
bool CommandFound = false;
CommandStatusIdType StatusId = COMMAND_ERR_UNKNOWN_CMD_ID;
char *pTerminalBuffer = (char *) TerminalBuffer;
2016-10-07 23:44:50 +02:00
2019-11-15 10:21:40 +01:00
/* Do some sanity check first */
if (!IS_COMMAND_DELIMITER(pTerminalBuffer[0])) {
char *pCommandDelimiter = pTerminalBuffer;
char CommandDelimiter = '\0';
2016-10-07 23:44:50 +02:00
2019-11-15 10:21:40 +01:00
/* Search for command delimiter, store it and replace with '\0' */
while (!(IS_COMMAND_DELIMITER(*pCommandDelimiter)))
pCommandDelimiter++;
2016-10-07 23:44:50 +02:00
2019-11-15 10:21:40 +01:00
CommandDelimiter = *pCommandDelimiter;
*pCommandDelimiter = '\0';
2016-10-07 23:44:50 +02:00
2019-11-15 10:21:40 +01:00
/* 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;
2016-10-07 23:44:50 +02:00
2019-11-15 10:21:40 +01:00
pTerminalBuffer[0] = '\0';
CommandFound = true;
2016-10-07 23:44:50 +02:00
2019-11-15 10:21:40 +01:00
StatusId = CallCommandFunc(&CommandTable[i], CommandDelimiter, pParam);
2016-10-07 23:44:50 +02:00
2019-11-15 10:21:40 +01:00
break;
}
}
2016-10-07 23:44:50 +02:00
}
2019-11-15 10:21:40 +01:00
if (StatusId == TIMEOUT_COMMAND) // it is a timeout command, so we return
return;
2016-10-07 23:44:50 +02:00
2019-11-15 10:21:40 +01:00
/* Send command status message */
TerminalSendStringP(GetStatusMessageP(StatusId));
TerminalSendStringP(PSTR(STATUS_MESSAGE_TRAILER));
2016-10-07 23:44:50 +02:00
2019-11-15 10:21:40 +01:00
if (CommandFound && (pTerminalBuffer[0] != '\0')) {
/* Send optional answer */
TerminalSendString(pTerminalBuffer);
TerminalSendStringP(PSTR(OPTIONAL_ANSWER_TRAILER));
}
2016-10-07 23:44:50 +02:00
}
2019-11-15 10:21:40 +01:00
void CommandLineInit(void) {
BufferIdx = 0;
2016-10-07 23:44:50 +02:00
}
bool CommandLineProcessByte(uint8_t Byte) {
2017-11-07 15:53:23 +01:00
if (IS_CHARACTER(Byte)) {
/* Store uppercase character */
if (IS_LOWERCASE(Byte)) {
Byte = TO_UPPERCASE(Byte);
}
2016-10-07 23:44:50 +02:00
2017-11-07 15:53:23 +01:00
/* 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;
2016-10-07 23:44:50 +02:00
2017-11-07 15:53:23 +01:00
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 */
}
2016-10-07 23:44:50 +02:00
2017-11-07 15:53:23 +01:00
return true;
2016-10-07 23:44:50 +02:00
}
2019-11-15 10:21:40 +01:00
INLINE void Timeout(void) {
2017-11-07 15:53:23 +01:00
TaskPending = false;
TerminalSendStringP(GetStatusMessageP(COMMAND_ERR_TIMEOUT_ID));
TerminalSendStringP(PSTR(STATUS_MESSAGE_TRAILER));
2016-10-07 23:44:50 +02:00
2019-11-15 10:21:40 +01:00
if (CommandLinePendingTaskTimeout != NO_FUNCTION) {
2017-11-07 15:53:23 +01:00
CommandLinePendingTaskTimeout(); // call the function that ends the task
CommandLinePendingTaskTimeout = NO_FUNCTION;
}
2016-10-07 23:44:50 +02:00
}
2019-11-15 10:21:40 +01:00
void CommandLineTick(void) {
2017-11-07 15:53:23 +01:00
if (TaskPending &&
GlobalSettings.ActiveSettingPtr->PendingTaskTimeout != 0 && // 0 means no timeout
2019-11-15 10:21:40 +01:00
SYSTICK_DIFF_100MS(TaskPendingSince) >= GlobalSettings.ActiveSettingPtr->PendingTaskTimeout) { // timeout expired
2017-11-07 15:53:23 +01:00
Timeout();
}
2016-10-07 23:44:50 +02:00
}
2019-11-15 10:21:40 +01:00
void CommandLinePendingTaskBreak(void) {
2017-11-07 15:53:23 +01:00
if (!TaskPending)
return;
2016-10-07 23:44:50 +02:00
2017-11-07 15:53:23 +01:00
Timeout();
2016-10-07 23:44:50 +02:00
}
2019-11-15 10:21:40 +01:00
void CommandLinePendingTaskFinished(CommandStatusIdType ReturnStatusID, char const *const OutMessage) {
2017-11-07 15:53:23 +01:00
if (!TaskPending) // if no task is pending, no task can be finished
return;
TaskPending = false;
2016-10-07 23:44:50 +02:00
2017-11-07 15:53:23 +01:00
TerminalSendStringP(GetStatusMessageP(ReturnStatusID));
TerminalSendStringP(PSTR(STATUS_MESSAGE_TRAILER));
2016-10-07 23:44:50 +02:00
2019-11-15 10:21:40 +01:00
if (OutMessage != NULL) {
2017-11-07 15:53:23 +01:00
TerminalSendString(OutMessage);
TerminalSendStringP(PSTR(OPTIONAL_ANSWER_TRAILER));
}
2016-10-07 23:44:50 +02:00
}
2019-11-15 10:21:40 +01:00
void CommandLineAppendData(void const *const Buffer, uint16_t Bytes) {
char *pTerminalBuffer = (char *) TerminalBuffer;
2016-10-07 23:44:50 +02:00
uint16_t tmpBytes = Bytes;
if (Bytes > (TERMINAL_BUFFER_SIZE / 2))
2017-11-07 15:53:23 +01:00
tmpBytes = TERMINAL_BUFFER_SIZE / 2;
2016-10-07 23:44:50 +02:00
Bytes -= tmpBytes;
BufferToHexString(pTerminalBuffer, TERMINAL_BUFFER_SIZE, Buffer, tmpBytes);
2016-10-07 23:44:50 +02:00
TerminalSendString(pTerminalBuffer);
uint8_t i = 1;
2019-11-15 10:21:40 +01:00
while (Bytes > (TERMINAL_BUFFER_SIZE / 2)) {
2017-11-07 15:53:23 +01:00
Bytes -= TERMINAL_BUFFER_SIZE / 2;
BufferToHexString(pTerminalBuffer, TERMINAL_BUFFER_SIZE, Buffer + i * TERMINAL_BUFFER_SIZE / 2, TERMINAL_BUFFER_SIZE);
2016-10-07 23:44:50 +02:00
TerminalSendString(pTerminalBuffer);
2017-11-07 15:53:23 +01:00
i++;
2016-10-07 23:44:50 +02:00
}
2019-11-15 10:21:40 +01:00
if (Bytes > 0) {
BufferToHexString(pTerminalBuffer, TERMINAL_BUFFER_SIZE, Buffer + i * TERMINAL_BUFFER_SIZE / 2, Bytes);
2016-10-07 23:44:50 +02:00
TerminalSendString(pTerminalBuffer);
}
TerminalSendStringP(PSTR(OPTIONAL_ANSWER_TRAILER));
}