Files
Micha AhrweilerandGitHub e0529dde03 Remove newlines from VERSION command
The newlines from the VERSION command response are removed, as they differ from the specification of "101:OK WITH TEXT"
2016-10-11 13:11:01 +02:00

626 lines
17 KiB
C

#include "Commands.h"
#include <stdio.h>
#include <avr/pgmspace.h>
#include "XModem.h"
#include "../Settings.h"
#include "../Chameleon-Mini.h"
#include "../LUFA/Version.h"
#include "../Configuration.h"
#include "../Random.h"
#include "../Memory.h"
#include "../System.h"
#include "../Button.h"
#include "../AntennaLevel.h"
#include "../Battery.h"
#include "../Codec/Codec.h"
extern Reader14443Command Reader14443CurrentCommand;
extern const PROGMEM CommandEntryType CommandTable[];
CommandStatusIdType CommandGetVersion(char* OutParam)
{
snprintf_P(OutParam, TERMINAL_BUFFER_SIZE, PSTR(
"ChameleonMini RevG %S using LUFA %S compiled with AVR-GCC %S. Based on the open-source NFC tool ChameleonMini. https://github.com/emsec/ChameleonMini commit %S"
), PSTR(CHAMELEON_MINI_VERSION_STRING), PSTR(LUFA_VERSION_STRING), PSTR(__VERSION__), PSTR(COMMIT_ID)
);
return COMMAND_INFO_OK_WITH_TEXT_ID;
}
CommandStatusIdType CommandGetConfig(char* OutParam)
{
ConfigurationGetByName(OutParam, TERMINAL_BUFFER_SIZE);
return COMMAND_INFO_OK_WITH_TEXT_ID;
}
CommandStatusIdType CommandSetConfig(char* OutMessage, const char* InParam)
{
if (COMMAND_IS_SUGGEST_STRING(InParam)) {
ConfigurationGetList(OutMessage, TERMINAL_BUFFER_SIZE);
return COMMAND_INFO_OK_WITH_TEXT_ID;
} else if (ConfigurationSetByName(InParam)) {
SettingsSave();
return COMMAND_INFO_OK_ID;
} else {
return COMMAND_ERR_INVALID_PARAM_ID;
}
}
CommandStatusIdType CommandGetUid(char* OutParam)
{
uint8_t UidBuffer[COMMAND_UID_BUFSIZE];
uint16_t UidSize = ActiveConfiguration.UidSize;
if (UidSize == 0)
{
snprintf_P(OutParam, TERMINAL_BUFFER_SIZE, PSTR("NO UID."));
return COMMAND_INFO_OK_WITH_TEXT_ID;
}
ApplicationGetUid(UidBuffer);
BufferToHexString(OutParam, TERMINAL_BUFFER_SIZE,
UidBuffer, UidSize);
return COMMAND_INFO_OK_WITH_TEXT_ID;
}
CommandStatusIdType CommandSetUid(char* OutMessage, const char* InParam)
{
uint8_t UidBuffer[COMMAND_UID_BUFSIZE];
uint16_t UidSize = ActiveConfiguration.UidSize;
if (strcmp_P(InParam, PSTR(COMMAND_UID_RANDOM)) == 0) {
/* Load with random bytes */
for (uint8_t i=0; i<UidSize; i++) {
UidBuffer[i] = RandomGetByte();
}
} else {
/* Convert to Bytes */
if (HexStringToBuffer(UidBuffer, sizeof(UidBuffer), InParam) != UidSize) {
/* Malformed input. Abort */
return COMMAND_ERR_INVALID_PARAM_ID;
}
}
ApplicationSetUid(UidBuffer);
return COMMAND_INFO_OK_ID;
}
CommandStatusIdType CommandGetReadOnly(char* OutParam)
{
if (ActiveConfiguration.ReadOnly) {
OutParam[0] = COMMAND_CHAR_TRUE;
} else {
OutParam[0] = COMMAND_CHAR_FALSE;
}
OutParam[1] = '\0';
return COMMAND_INFO_OK_WITH_TEXT_ID;
}
CommandStatusIdType CommandSetReadOnly(char* OutMessage, const char* InParam)
{
if (InParam[1] == '\0') {
if (InParam[0] == COMMAND_CHAR_TRUE) {
ActiveConfiguration.ReadOnly = true;
return COMMAND_INFO_OK_ID;
} else if (InParam[0] == COMMAND_CHAR_FALSE) {
ActiveConfiguration.ReadOnly = false;
return COMMAND_INFO_OK_ID;
} else if (InParam[0] == COMMAND_CHAR_SUGGEST) {
snprintf_P(OutMessage, TERMINAL_BUFFER_SIZE, PSTR("%c,%c"), COMMAND_CHAR_TRUE, COMMAND_CHAR_FALSE);
return COMMAND_INFO_OK_WITH_TEXT_ID;
}
}
return COMMAND_ERR_INVALID_PARAM_ID;
}
CommandStatusIdType CommandExecUpload(char* OutMessage)
{
XModemReceive(MemoryUploadBlock);
return COMMAND_INFO_XMODEM_WAIT_ID;
}
CommandStatusIdType CommandExecDownload(char* OutMessage)
{
XModemSend(MemoryDownloadBlock);
return COMMAND_INFO_XMODEM_WAIT_ID;
}
CommandStatusIdType CommandExecReset(char* OutMessage)
{
USB_Detach();
USB_Disable();
SystemReset();
return COMMAND_INFO_OK_ID;
}
#ifdef SUPPORT_FIRMWARE_UPGRADE
CommandStatusIdType CommandExecUpgrade(char* OutMessage)
{
USB_Detach();
USB_Disable();
SystemEnterBootloader();
return COMMAND_INFO_OK_ID;
}
#endif
CommandStatusIdType CommandGetMemSize(char* OutParam)
{
snprintf_P(OutParam, TERMINAL_BUFFER_SIZE, PSTR("%u"), ActiveConfiguration.MemorySize);
return COMMAND_INFO_OK_WITH_TEXT_ID;
}
CommandStatusIdType CommandGetUidSize(char* OutParam)
{
snprintf_P(OutParam, TERMINAL_BUFFER_SIZE, PSTR("%u"), ActiveConfiguration.UidSize);
return COMMAND_INFO_OK_WITH_TEXT_ID;
}
CommandStatusIdType CommandGetRButton(char* OutParam)
{
ButtonGetActionByName(BUTTON_R_PRESS_SHORT, OutParam, TERMINAL_BUFFER_SIZE);
return COMMAND_INFO_OK_WITH_TEXT_ID;
}
CommandStatusIdType CommandSetRButton(char* OutMessage, const char* InParam)
{
if (COMMAND_IS_SUGGEST_STRING(InParam)) {
/* Get suggestion list */
ButtonGetActionList(OutMessage, TERMINAL_BUFFER_SIZE);
return COMMAND_INFO_OK_WITH_TEXT_ID;
} else if (ButtonSetActionByName(BUTTON_R_PRESS_SHORT, InParam)) {
/* Try to set action name */
SettingsSave();
return COMMAND_INFO_OK_ID;
} else {
return COMMAND_ERR_INVALID_PARAM_ID;
}
}
CommandStatusIdType CommandGetRButtonLong(char* OutParam)
{
ButtonGetActionByName(BUTTON_R_PRESS_LONG, OutParam, TERMINAL_BUFFER_SIZE);
return COMMAND_INFO_OK_WITH_TEXT_ID;
}
CommandStatusIdType CommandSetRButtonLong(char* OutMessage, const char* InParam)
{
if (COMMAND_IS_SUGGEST_STRING(InParam)) {
/* Get suggestion list */
ButtonGetActionList(OutMessage, TERMINAL_BUFFER_SIZE);
return COMMAND_INFO_OK_WITH_TEXT_ID;
} else if (ButtonSetActionByName(BUTTON_R_PRESS_LONG, InParam)) {
/* Try to set action name */
SettingsSave();
return COMMAND_INFO_OK_ID;
} else {
return COMMAND_ERR_INVALID_PARAM_ID;
}
}
CommandStatusIdType CommandGetLButton(char* OutParam)
{
ButtonGetActionByName(BUTTON_L_PRESS_SHORT, OutParam, TERMINAL_BUFFER_SIZE);
return COMMAND_INFO_OK_WITH_TEXT_ID;
}
CommandStatusIdType CommandSetLButton(char* OutMessage, const char* InParam)
{
if (COMMAND_IS_SUGGEST_STRING(InParam)) {
/* Get suggestion list */
ButtonGetActionList(OutMessage, TERMINAL_BUFFER_SIZE);
return COMMAND_INFO_OK_WITH_TEXT_ID;
} else if (ButtonSetActionByName(BUTTON_L_PRESS_SHORT, InParam)) {
/* Try to set action name */
SettingsSave();
return COMMAND_INFO_OK_ID;
} else {
return COMMAND_ERR_INVALID_PARAM_ID;
}
}
CommandStatusIdType CommandGetLButtonLong(char* OutParam)
{
ButtonGetActionByName(BUTTON_L_PRESS_LONG, OutParam, TERMINAL_BUFFER_SIZE);
return COMMAND_INFO_OK_WITH_TEXT_ID;
}
CommandStatusIdType CommandSetLButtonLong(char* OutMessage, const char* InParam)
{
if (COMMAND_IS_SUGGEST_STRING(InParam)) {
/* Get suggestion list */
ButtonGetActionList(OutMessage, TERMINAL_BUFFER_SIZE);
return COMMAND_INFO_OK_WITH_TEXT_ID;
} else if (ButtonSetActionByName(BUTTON_L_PRESS_LONG, InParam)) {
/* Try to set action name */
SettingsSave();
return COMMAND_INFO_OK_ID;
} else {
return COMMAND_ERR_INVALID_PARAM_ID;
}
}
CommandStatusIdType CommandGetLedGreen(char* OutParam)
{
LEDGetFuncByName(LED_GREEN, OutParam, TERMINAL_BUFFER_SIZE);
return COMMAND_INFO_OK_WITH_TEXT_ID;
}
CommandStatusIdType CommandSetLedGreen(char* OutMessage, const char* InParam)
{
if (COMMAND_IS_SUGGEST_STRING(InParam)) {
LEDGetFuncList(OutMessage, TERMINAL_BUFFER_SIZE);
return COMMAND_INFO_OK_WITH_TEXT_ID;
} else if (LEDSetFuncByName(LED_GREEN, InParam)) {
SettingsSave();
return COMMAND_INFO_OK_ID;
} else {
return COMMAND_ERR_INVALID_PARAM_ID;
}
}
CommandStatusIdType CommandGetLedRed(char* OutParam)
{
LEDGetFuncByName(LED_RED, OutParam, TERMINAL_BUFFER_SIZE);
return COMMAND_INFO_OK_WITH_TEXT_ID;
}
CommandStatusIdType CommandSetLedRed(char* OutMessage, const char* InParam)
{
if (COMMAND_IS_SUGGEST_STRING(InParam)) {
LEDGetFuncList(OutMessage, TERMINAL_BUFFER_SIZE);
return COMMAND_INFO_OK_WITH_TEXT_ID;
} else if (LEDSetFuncByName(LED_RED, InParam)) {
SettingsSave();
return COMMAND_INFO_OK_ID;
} else {
return COMMAND_ERR_INVALID_PARAM_ID;
}
}
CommandStatusIdType CommandGetLogMode(char* OutParam)
{
/* Get Logmode */
LogGetModeByName(OutParam, TERMINAL_BUFFER_SIZE);
return COMMAND_INFO_OK_WITH_TEXT_ID;
}
CommandStatusIdType CommandSetLogMode(char* OutMessage, const char* InParam)
{
if (COMMAND_IS_SUGGEST_STRING(InParam)) {
LogGetModeList(OutMessage, TERMINAL_BUFFER_SIZE);
return COMMAND_INFO_OK_WITH_TEXT_ID;
} else if (LogSetModeByName(InParam)) {
SettingsSave();
return COMMAND_INFO_OK_ID;
} else {
return COMMAND_ERR_INVALID_PARAM_ID;
}
}
CommandStatusIdType CommandGetLogMem(char* OutParam)
{
snprintf_P(OutParam, TERMINAL_BUFFER_SIZE,
PSTR("%u"), LogMemFree());
return COMMAND_INFO_OK_WITH_TEXT_ID;
}
CommandStatusIdType CommandExecLogDownload(char* OutMessage)
{
XModemSend(LogMemLoadBlock);
return COMMAND_INFO_XMODEM_WAIT_ID;
}
CommandStatusIdType CommandExecStoreLog(char* OutMessage)
{
LogSRAMToFRAM();
return COMMAND_INFO_OK_ID;
}
CommandStatusIdType CommandExecLogClear(char* OutMessage)
{
LogMemClear();
return COMMAND_INFO_OK_ID;
}
CommandStatusIdType CommandGetSetting(char* OutParam)
{
SettingsGetActiveByName(OutParam, TERMINAL_BUFFER_SIZE);
return COMMAND_INFO_OK_WITH_TEXT_ID;
}
CommandStatusIdType CommandSetSetting(char* OutMessage, const char* InParam)
{
if (SettingsSetActiveByName(InParam)) {
SettingsSave();
return COMMAND_INFO_OK_ID;
} else {
return COMMAND_ERR_INVALID_PARAM_ID;
}
}
CommandStatusIdType CommandExecClear(char* OutMessage)
{
MemoryClear();
return COMMAND_INFO_OK_ID;
}
CommandStatusIdType CommandExecStore(char* OutMessage)
{
MemoryStore();
return COMMAND_INFO_OK_ID;
}
CommandStatusIdType CommandExecRecall(char* OutMessage)
{
MemoryRecall();
return COMMAND_INFO_OK_ID;
}
CommandStatusIdType CommandGetCharging(char* OutMessage)
{
if (BatteryIsCharging()) {
return COMMAND_INFO_TRUE_ID;
} else {
return COMMAND_INFO_FALSE_ID;
}
}
CommandStatusIdType CommandExecHelp(char* OutMessage)
{
const CommandEntryType* EntryPtr = CommandTable;
uint16_t ByteCount = TERMINAL_BUFFER_SIZE - 1; /* Account for '\0' */
while(strcmp_P(COMMAND_LIST_END, EntryPtr->Command) != 0 && ByteCount > 0) {
const char* CommandName = EntryPtr->Command;
char c;
while( (c = pgm_read_byte(CommandName)) != '\0' && ByteCount > 1) {
*OutMessage++ = c;
CommandName++;
ByteCount--;
}
*OutMessage++ = ',';
ByteCount--;
EntryPtr++;
}
*--OutMessage = '\0';
return COMMAND_INFO_OK_WITH_TEXT_ID;
}
CommandStatusIdType CommandGetRssi(char* OutParam)
{
snprintf_P(OutParam, TERMINAL_BUFFER_SIZE,
PSTR("%5u mV"), AntennaLevelGet());
return COMMAND_INFO_OK_WITH_TEXT_ID;
}
CommandStatusIdType CommandGetSysTick(char* OutParam)
{
snprintf_P(OutParam, TERMINAL_BUFFER_SIZE, PSTR("%4.4X"), SystemGetSysTick());
return COMMAND_INFO_OK_WITH_TEXT_ID;
}
CommandStatusIdType CommandExecParamSend(char* OutMessage, const char* InParams)
{
if (GlobalSettings.ActiveSettingPtr->Configuration != CONFIG_ISO14443A_READER)
return COMMAND_ERR_INVALID_USAGE_ID;
ApplicationReset();
Reader14443CurrentCommand = Reader14443_Send;
char const * paramTwo = strchr(InParams, ' ');
uint16_t length;
if (paramTwo == NULL) // this means, we have to calculate the length
{
length = strlen(InParams);
if (length&1) // return error when length is odd
return COMMAND_ERR_INVALID_PARAM_ID;
length /= 2;
if (length == 1)
{
ReaderSendBitCount = 7; // this is a short frame
} else {
ReaderSendBitCount = length * 8;
}
} else if(paramTwo == (InParams+4)) { // we have a bitcount prepended
uint8_t tmp[2];
HexStringToBuffer(tmp, 2, InParams);
ReaderSendBitCount = (tmp[0]<<8) + tmp[1]; // set our BitCount to the given value
InParams = ++paramTwo; // set InParams to the beginning of the second parameter
length = strlen(InParams);
if ((length&1) || (length / 2 * 8) < ReaderSendBitCount) // this parameter is malformed, if it is odd or if there are less bits than the BitCount indicates
return COMMAND_ERR_INVALID_PARAM_ID;
} else { // any other case means we have malformed parameters
return COMMAND_ERR_INVALID_PARAM_ID;
}
HexStringToBuffer(ReaderSendBuffer, (ReaderSendBitCount+7)/8, InParams);
Reader14443ACodecStart();
return TIMEOUT_COMMAND;
}
CommandStatusIdType CommandExecParamSendRaw(char* OutMessage, const char* InParams)
{
if (GlobalSettings.ActiveSettingPtr->Configuration != CONFIG_ISO14443A_READER)
return COMMAND_ERR_INVALID_USAGE_ID;
ApplicationReset();
Reader14443CurrentCommand = Reader14443_Send_Raw;
char const * paramTwo = strchr(InParams, ' ');
uint16_t length;
if (paramTwo == NULL) // this means, we have to calculate the length
{
length = strlen(InParams);
if (length&1) // return error when length is odd
return COMMAND_ERR_INVALID_PARAM_ID;
length /= 2;
if (length == 1)
{
ReaderSendBitCount = 7; // this is a short frame
} else {
length *= 8;
ReaderSendBitCount = length - (length % 9); // how many bytes+paritybit match into our input?
}
} else if(paramTwo == (InParams+4)) { // we have a bitcount prepended
uint8_t tmp[2];
HexStringToBuffer(tmp, 2, InParams);
ReaderSendBitCount = (tmp[0]<<8) + tmp[1]; // set our BitCount to the given value
if (ReaderSendBitCount != 7 && (ReaderSendBitCount % 8)) // since we have to add parity bits here (in case this is not a short frame), the number of bits to be sent has to be a multiple of 8
return COMMAND_ERR_INVALID_PARAM_ID;
InParams = ++paramTwo; // set InParams to the beginning of the second parameter
length = strlen(InParams);
if ((length&1) || (length / 2 * 8) < ReaderSendBitCount) // this parameter is malformed, if it is odd or if there are less bits than the BitCount indicates
return COMMAND_ERR_INVALID_PARAM_ID;
} else { // any other case means we have malformed parameters
return COMMAND_ERR_INVALID_PARAM_ID;
}
HexStringToBuffer(ReaderSendBuffer, (ReaderSendBitCount+7)/8, InParams);
Reader14443ACodecStart();
return TIMEOUT_COMMAND;
}
CommandStatusIdType CommandExecDumpMFU(char* OutMessage)
{
if (GlobalSettings.ActiveSettingPtr->Configuration != CONFIG_ISO14443A_READER)
return COMMAND_ERR_INVALID_USAGE_ID;
ApplicationReset();
Reader14443CurrentCommand = Reader14443_Read_MF_Ultralight;
Reader14443AAppInit();
Reader14443ACodecStart();
CommandLinePendingTaskTimeout = &Reader14443AAppTimeout;
return TIMEOUT_COMMAND;
}
CommandStatusIdType CommandExecGetUid(char* OutMessage) // this function is for reading the uid in reader mode
{
if (GlobalSettings.ActiveSettingPtr->Configuration != CONFIG_ISO14443A_READER)
return COMMAND_ERR_INVALID_USAGE_ID;
ApplicationReset();
Reader14443CurrentCommand = Reader14443_Get_UID;
Reader14443AAppInit();
Reader14443ACodecStart();
CommandLinePendingTaskTimeout = &Reader14443AAppTimeout;
return TIMEOUT_COMMAND;
}
CommandStatusIdType CommandExecIdentifyCard(char* OutMessage)
{
if (GlobalSettings.ActiveSettingPtr->Configuration != CONFIG_ISO14443A_READER)
return COMMAND_ERR_INVALID_USAGE_ID;
ApplicationReset();
Reader14443CurrentCommand = Reader14443_Indentify;
Reader14443AAppInit();
Reader14443ACodecStart();
CommandLinePendingTaskTimeout = &Reader14443AAppTimeout;
return TIMEOUT_COMMAND;
}
CommandStatusIdType CommandGetTimeout(char* OutParam)
{
snprintf_P(OutParam, TERMINAL_BUFFER_SIZE, PSTR("%u ms"), GlobalSettings.ActiveSettingPtr->PendingTaskTimeout * 100);
return COMMAND_INFO_OK_WITH_TEXT_ID;
}
CommandStatusIdType CommandSetTimeout(char* OutMessage, const char* InParam)
{
if (COMMAND_IS_SUGGEST_STRING(InParam))
{
snprintf_P(OutMessage, TERMINAL_BUFFER_SIZE, PSTR("0 = no timeout\r\n1-600 = 100 ms - 60000 ms timeout"));
return COMMAND_INFO_OK_WITH_TEXT_ID;
}
uint16_t tmp = 601;
if (!sscanf(InParam, "%5d", &tmp) || tmp > 600)
return COMMAND_ERR_INVALID_PARAM_ID;
GlobalSettings.ActiveSettingPtr->PendingTaskTimeout = tmp;
return COMMAND_INFO_OK_ID;
}
CommandStatusIdType CommandGetThreshold(char* OutParam)
{
snprintf_P(OutParam, TERMINAL_BUFFER_SIZE, PSTR("%u"), ReaderThreshold);
return COMMAND_INFO_OK_WITH_TEXT_ID;
}
CommandStatusIdType CommandSetThreshold(char* OutMessage, const char* InParam)
{
if (COMMAND_IS_SUGGEST_STRING(InParam))
{
snprintf_P(OutMessage, TERMINAL_BUFFER_SIZE, PSTR("Any integer from 0 to %u. Reference voltage will be (VCC * THRESHOLD / 4095) mV."), CODEC_MAXIMUM_THRESHOLD);
return COMMAND_INFO_OK_WITH_TEXT_ID;
}
uint16_t tmp = 0;
if (!sscanf(InParam, "%5d", &tmp) || tmp > CODEC_MAXIMUM_THRESHOLD)
return COMMAND_ERR_INVALID_PARAM_ID;
DACB.CH0DATA = tmp;
ReaderThreshold = tmp;
return COMMAND_INFO_OK_ID;
}
CommandStatusIdType CommandSetField(char* OutMessage, const char* InParam)
{
if (COMMAND_IS_SUGGEST_STRING(InParam))
{
snprintf_P(OutMessage, TERMINAL_BUFFER_SIZE, PSTR("%c,%c"), COMMAND_CHAR_TRUE, COMMAND_CHAR_FALSE);
return COMMAND_INFO_OK_WITH_TEXT_ID;
}
if (InParam[0] == COMMAND_CHAR_TRUE)
{
CodecReaderFieldStart();
} else if(InParam[0] == COMMAND_CHAR_FALSE) {
CodecReaderFieldStop();
} else {
return COMMAND_ERR_INVALID_PARAM_ID;
}
return COMMAND_INFO_OK_ID;
}
CommandStatusIdType CommandGetField(char* OutMessage)
{
if (CodecGetReaderField())
OutMessage[0] = COMMAND_CHAR_TRUE;
else
OutMessage[0] = COMMAND_CHAR_FALSE;
OutMessage[1] = '\0';
return COMMAND_INFO_OK_WITH_TEXT_ID;
}