Added error reporting to idevicesettings

checksum-failure-logging
EricLiu2000 2019-06-11 17:37:59 -04:00
parent 965679c370
commit a16f2843d8
4 changed files with 221 additions and 39 deletions

View File

@ -59,6 +59,17 @@ static constexpr const char* ERROR_SETTINGS_VERSION = "The settings version is i
static constexpr const char* ERROR_SETTINGS_LENGTH = "The settings length is incorrect, please update your firmware with neoVI Explorer."; static constexpr const char* ERROR_SETTINGS_LENGTH = "The settings length is incorrect, please update your firmware with neoVI Explorer.";
static constexpr const char* ERROR_SETTINGS_CHECKSUM = "The settings checksum is incorrect, attempting to set defaults may remedy this issue."; static constexpr const char* ERROR_SETTINGS_CHECKSUM = "The settings checksum is incorrect, attempting to set defaults may remedy this issue.";
static constexpr const char* ERROR_SETTINGS_NOT_AVAILABLE = "Settings are not available for this device."; static constexpr const char* ERROR_SETTINGS_NOT_AVAILABLE = "Settings are not available for this device.";
static constexpr const char* ERROR_SETTINGS_READONLY = "Settings are read-only for this device.";
static constexpr const char* ERROR_CAN_SETTINGS_NOT_AVAILABLE = "CAN settings are not available for this device.";
static constexpr const char* ERROR_CANFD_SETTINGS_NOT_AVAILABLE = "CANFD settings are not available for this device.";
static constexpr const char* ERROR_LSFTCAN_SETTINGS_NOT_AVAILABLE = "LSFTCAN settings are not available for this device.";
static constexpr const char* ERROR_SWCAN_SETTINGS_NOT_AVAILABLE = "SWCAN settings are not available for this device.";
static constexpr const char* ERROR_BAUDRATE_NOT_FOUND = "The baudrate was not found.";
static constexpr const char* ERROR_BAD_NETWORK_TYPE = "The network type was not found.";
static constexpr const char* ERROR_DEVICE_FIRMWARE_OUT_OF_DATE = "The device firmware is out of date. New API functionality may not be supported.";
static constexpr const char* ERROR_SETTINGS_STRUCTURE_MISMATCH = "Unexpected settings structure for this device.";
static constexpr const char* ERROR_SETTINGS_STRUCTURE_TRUNCATED = "Settings structure is longer than the device supports and will be truncated.";
static constexpr const char* ERROR_NO_DEVICE_RESPONSE = "Expected a response from the device but none were found.";
// Transport Errors // Transport Errors
static constexpr const char* ERROR_FAILED_TO_READ = "A read operation failed."; static constexpr const char* ERROR_FAILED_TO_READ = "A read operation failed.";
@ -108,6 +119,26 @@ const char* APIError::DescriptionForType(ErrorType type) {
return ERROR_SETTINGS_CHECKSUM; return ERROR_SETTINGS_CHECKSUM;
case SettingsNotAvailable: case SettingsNotAvailable:
return ERROR_SETTINGS_NOT_AVAILABLE; return ERROR_SETTINGS_NOT_AVAILABLE;
case SettingsReadOnly:
return ERROR_SETTINGS_READONLY;
case CANSettingsNotAvailable:
return ERROR_CAN_SETTINGS_NOT_AVAILABLE;
case CANFDSettingsNotAvailable:
return ERROR_CANFD_SETTINGS_NOT_AVAILABLE;
case LSFTCANSettingsNotAvailable:
return ERROR_LSFTCAN_SETTINGS_NOT_AVAILABLE;
case SWCANSettingsNotAvailable:
return ERROR_SWCAN_SETTINGS_NOT_AVAILABLE;
case BaudrateNotFound:
return ERROR_BAUDRATE_NOT_FOUND;
case DeviceFirmwareOutOfDate:
return ERROR_DEVICE_FIRMWARE_OUT_OF_DATE;
case SettingsStructureMismatch:
return ERROR_SETTINGS_STRUCTURE_MISMATCH;
case SettingsStructureTruncated:
return ERROR_SETTINGS_STRUCTURE_TRUNCATED;
case NoDeviceResponse:
return ERROR_NO_DEVICE_RESPONSE;
// Transport Errors // Transport Errors
case FailedToRead: case FailedToRead:
@ -145,6 +176,8 @@ APIError::Severity APIError::SeverityForType(ErrorType type) {
case DeviceCurrentlyClosed: case DeviceCurrentlyClosed:
// Device Warnings // Device Warnings
case PollingMessageOverflow: case PollingMessageOverflow:
case DeviceFirmwareOutOfDate:
case SettingsStructureTruncated:
// Transport Warnings // Transport Warnings
case PCAPCouldNotStart: case PCAPCouldNotStart:
case PCAPCouldNotFindDevices: case PCAPCouldNotFindDevices:
@ -164,6 +197,14 @@ APIError::Severity APIError::SeverityForType(ErrorType type) {
case SettingsLengthError: case SettingsLengthError:
case SettingsChecksumError: case SettingsChecksumError:
case SettingsNotAvailable: case SettingsNotAvailable:
case SettingsReadOnly:
case CANSettingsNotAvailable:
case CANFDSettingsNotAvailable:
case LSFTCANSettingsNotAvailable:
case SWCANSettingsNotAvailable:
case BaudrateNotFound:
case SettingsStructureMismatch:
case NoDeviceResponse:
// Transport Errors // Transport Errors
case FailedToRead: case FailedToRead:
case FailedToWrite: case FailedToWrite:

View File

@ -183,8 +183,20 @@ bool IDeviceSettings::refresh(bool ignoreChecksum) {
} }
bool IDeviceSettings::apply(bool temporary) { bool IDeviceSettings::apply(bool temporary) {
if(!settingsLoaded || disabled || readonly) if(readonly) {
err(APIError::SettingsReadOnly);
return false; return false;
}
if(disabled) {
err(APIError::SettingsNotAvailable);
return false;
}
if(!settingsLoaded) {
err(APIError::SettingsReadError);
return false;
}
std::vector<uint8_t> bytestream; std::vector<uint8_t> bytestream;
bytestream.resize(7 + settings.size()); bytestream.resize(7 + settings.size());
@ -202,7 +214,11 @@ bool IDeviceSettings::apply(bool temporary) {
std::shared_ptr<Message> msg = com->waitForMessageSync(std::make_shared<Main51MessageFilter>(Command::SetSettings), std::chrono::milliseconds(1000)); std::shared_ptr<Message> msg = com->waitForMessageSync(std::make_shared<Main51MessageFilter>(Command::SetSettings), std::chrono::milliseconds(1000));
if(!msg || msg->data[0] != 1) { // We did not receive a response if(!msg || msg->data[0] != 1) { // We did not receive a response
refresh(); // Attempt to get the settings from the device so we're up to date if possible // Attempt to get the settings from the device so we're up to date if possible
if(refresh()) {
// refresh succeeded but previously there was an error
err(APIError::NoDeviceResponse);
}
return false; return false;
} }
@ -217,7 +233,11 @@ bool IDeviceSettings::apply(bool temporary) {
com->sendCommand(Command::SetSettings, bytestream); com->sendCommand(Command::SetSettings, bytestream);
msg = com->waitForMessageSync(std::make_shared<Main51MessageFilter>(Command::SetSettings), std::chrono::milliseconds(1000)); msg = com->waitForMessageSync(std::make_shared<Main51MessageFilter>(Command::SetSettings), std::chrono::milliseconds(1000));
if(!msg || msg->data[0] != 1) { if(!msg || msg->data[0] != 1) {
refresh(); // Attempt to get the settings from the device so we're up to date if possible
if(refresh()) {
// refresh succeeded but previously there was an error
err(APIError::NoDeviceResponse);
}
return false; return false;
} }
@ -228,17 +248,32 @@ bool IDeviceSettings::apply(bool temporary) {
refresh(); // Refresh our buffer with what the device has, whether we were successful or not refresh(); // Refresh our buffer with what the device has, whether we were successful or not
return (msg && msg->data[0] == 1); // Device sends 0x01 for success bool ret = (msg && msg->data[0] == 1); // Device sends 0x01 for success
if(!ret) {
err(APIError::FailedToWrite);
}
return ret;
} }
bool IDeviceSettings::applyDefaults(bool temporary) { bool IDeviceSettings::applyDefaults(bool temporary) {
if(disabled || readonly) if(disabled) {
err(APIError::SettingsNotAvailable);
return false; return false;
}
if(readonly) {
err(APIError::SettingsReadOnly);
return false;
}
com->sendCommand(Command::SetDefaultSettings); com->sendCommand(Command::SetDefaultSettings);
std::shared_ptr<Message> msg = com->waitForMessageSync(std::make_shared<Main51MessageFilter>(Command::SetDefaultSettings), std::chrono::milliseconds(1000)); std::shared_ptr<Message> msg = com->waitForMessageSync(std::make_shared<Main51MessageFilter>(Command::SetDefaultSettings), std::chrono::milliseconds(1000));
if(!msg || msg->data[0] != 1) { if(!msg || msg->data[0] != 1) {
refresh(); // Attempt to get the settings from the device so we're up to date if possible
if(refresh()) {
// refresh succeeded but previously there was an error
err(APIError::NoDeviceResponse);
}
return false; return false;
} }
@ -263,7 +298,11 @@ bool IDeviceSettings::applyDefaults(bool temporary) {
com->sendCommand(Command::SetSettings, bytestream); com->sendCommand(Command::SetSettings, bytestream);
msg = com->waitForMessageSync(std::make_shared<Main51MessageFilter>(Command::SetSettings), std::chrono::milliseconds(1000)); msg = com->waitForMessageSync(std::make_shared<Main51MessageFilter>(Command::SetSettings), std::chrono::milliseconds(1000));
if(!msg || msg->data[0] != 1) { if(!msg || msg->data[0] != 1) {
refresh(); // Attempt to get the settings from the device so we're up to date if possible
if(refresh()) {
// refresh succeeded but previously there was an error
err(APIError::NoDeviceResponse);
}
return false; return false;
} }
@ -274,45 +313,79 @@ bool IDeviceSettings::applyDefaults(bool temporary) {
refresh(); // Refresh our buffer with what the device has, whether we were successful or not refresh(); // Refresh our buffer with what the device has, whether we were successful or not
return (msg && msg->data[0] == 1); // Device sends 0x01 for success bool ret = (msg && msg->data[0] == 1); // Device sends 0x01 for success
if(!ret) {
err(APIError::FailedToWrite);
}
return ret;
} }
int64_t IDeviceSettings::getBaudrateFor(Network net) const { int64_t IDeviceSettings::getBaudrateFor(Network net) const {
if(!settingsLoaded || disabled) if(disabled) {
err(APIError::SettingsNotAvailable);
return -1; return -1;
}
if(!settingsLoaded) {
err(APIError::SettingsReadError);
return -1;
}
switch(net.getType()) { switch(net.getType()) {
case Network::Type::CAN: { case Network::Type::CAN: {
const CAN_SETTINGS* cfg = getCANSettingsFor(net); const CAN_SETTINGS* cfg = getCANSettingsFor(net);
if(cfg == nullptr) if(cfg == nullptr) {
err(APIError::CANFDSettingsNotAvailable);
return -1; return -1;
}
int64_t baudrate = GetBaudrateValueForEnum((CANBaudrate)cfg->Baudrate); int64_t baudrate = GetBaudrateValueForEnum((CANBaudrate)cfg->Baudrate);
if(baudrate == -1) if(baudrate == -1) {
err(APIError::BaudrateNotFound);
return -1; return -1;
}
return baudrate; return baudrate;
} }
default: default:
err(APIError::BadNetworkType);
return -1; return -1;
} }
} }
bool IDeviceSettings::setBaudrateFor(Network net, int64_t baudrate) { bool IDeviceSettings::setBaudrateFor(Network net, int64_t baudrate) {
if(!settingsLoaded || disabled || readonly) if(disabled) {
err(APIError::SettingsNotAvailable);
return false; return false;
}
if(!settingsLoaded) {
err(APIError::SettingsReadError);
return false;
}
if(readonly) {
err(APIError::SettingsReadOnly);
return false;
}
switch(net.getType()) { switch(net.getType()) {
case Network::Type::CAN: { case Network::Type::CAN: {
if(baudrate > 1000000) // This is an FD baudrate. Use setFDBaudrateFor instead. if(baudrate > 1000000) { // This is an FD baudrate. Use setFDBaudrateFor instead.
err(APIError::CANFDSettingsNotAvailable);
return false; return false;
}
CAN_SETTINGS* cfg = getMutableCANSettingsFor(net); CAN_SETTINGS* cfg = getMutableCANSettingsFor(net);
if(cfg == nullptr) if(cfg == nullptr) {
err(APIError::CANSettingsNotAvailable);
return false; return false;
}
CANBaudrate newBaud = GetEnumValueForBaudrate(baudrate); CANBaudrate newBaud = GetEnumValueForBaudrate(baudrate);
if(newBaud == (CANBaudrate)-1) if(newBaud == (CANBaudrate)-1) {
err(APIError::BaudrateNotFound);
return false; return false;
}
cfg->Baudrate = (uint8_t)newBaud; cfg->Baudrate = (uint8_t)newBaud;
cfg->auto_baud = false; cfg->auto_baud = false;
cfg->SetBaudrate = AUTO; // Device will use the baudrate value to set the TQ values cfg->SetBaudrate = AUTO; // Device will use the baudrate value to set the TQ values
@ -320,12 +393,16 @@ bool IDeviceSettings::setBaudrateFor(Network net, int64_t baudrate) {
} }
case Network::Type::LSFTCAN: { case Network::Type::LSFTCAN: {
CAN_SETTINGS* cfg = getMutableLSFTCANSettingsFor(net); CAN_SETTINGS* cfg = getMutableLSFTCANSettingsFor(net);
if(cfg == nullptr) if(cfg == nullptr) {
err(APIError::LSFTCANSettingsNotAvailable);
return false; return false;
}
CANBaudrate newBaud = GetEnumValueForBaudrate(baudrate); CANBaudrate newBaud = GetEnumValueForBaudrate(baudrate);
if(newBaud == (CANBaudrate)-1) if(newBaud == (CANBaudrate)-1) {
err(APIError::BaudrateNotFound);
return false; return false;
}
cfg->Baudrate = (uint8_t)newBaud; cfg->Baudrate = (uint8_t)newBaud;
cfg->auto_baud = false; cfg->auto_baud = false;
cfg->SetBaudrate = AUTO; // Device will use the baudrate value to set the TQ values cfg->SetBaudrate = AUTO; // Device will use the baudrate value to set the TQ values
@ -333,77 +410,126 @@ bool IDeviceSettings::setBaudrateFor(Network net, int64_t baudrate) {
} }
case Network::Type::SWCAN: { case Network::Type::SWCAN: {
SWCAN_SETTINGS* cfg = getMutableSWCANSettingsFor(net); SWCAN_SETTINGS* cfg = getMutableSWCANSettingsFor(net);
if(cfg == nullptr) if(cfg == nullptr) {
err(APIError::SWCANSettingsNotAvailable);
return false; return false;
}
CANBaudrate newBaud = GetEnumValueForBaudrate(baudrate); CANBaudrate newBaud = GetEnumValueForBaudrate(baudrate);
if(newBaud == (CANBaudrate)-1) if(newBaud == (CANBaudrate)-1) {
err(APIError::BaudrateNotFound);
return false; return false;
}
cfg->Baudrate = (uint8_t)newBaud; cfg->Baudrate = (uint8_t)newBaud;
cfg->auto_baud = false; cfg->auto_baud = false;
cfg->SetBaudrate = AUTO; // Device will use the baudrate value to set the TQ values cfg->SetBaudrate = AUTO; // Device will use the baudrate value to set the TQ values
return true; return true;
} }
default: default:
err(APIError::BadNetworkType);
return false; return false;
} }
} }
int64_t IDeviceSettings::getFDBaudrateFor(Network net) const { int64_t IDeviceSettings::getFDBaudrateFor(Network net) const {
if(!settingsLoaded || disabled) if(disabled) {
err(APIError::SettingsNotAvailable);
}
if(!settingsLoaded) {
err(APIError::SettingsReadError);
return -1; return -1;
}
switch(net.getType()) { switch(net.getType()) {
case Network::Type::CAN: { case Network::Type::CAN: {
const CANFD_SETTINGS* cfg = getCANFDSettingsFor(net); const CANFD_SETTINGS* cfg = getCANFDSettingsFor(net);
if(cfg == nullptr) if(cfg == nullptr) {
err(APIError::CANFDSettingsNotAvailable);
return -1; return -1;
}
int64_t baudrate = GetBaudrateValueForEnum((CANBaudrate)cfg->FDBaudrate); int64_t baudrate = GetBaudrateValueForEnum((CANBaudrate)cfg->FDBaudrate);
if(baudrate == -1) if(baudrate == -1) {
err(APIError::BaudrateNotFound);
return -1; return -1;
}
return baudrate; return baudrate;
} }
default: default:
err(APIError::BadNetworkType);
return -1; return -1;
} }
} }
bool IDeviceSettings::setFDBaudrateFor(Network net, int64_t baudrate) { bool IDeviceSettings::setFDBaudrateFor(Network net, int64_t baudrate) {
if(!settingsLoaded || disabled || readonly) if(!settingsLoaded) {
err(APIError::SettingsReadError);
return false; return false;
}
if(disabled) {
err(APIError::SettingsNotAvailable);
return false;
}
if(readonly) {
err(APIError::SettingsReadOnly);
return false;
}
switch(net.getType()) { switch(net.getType()) {
case Network::Type::CAN: { case Network::Type::CAN: {
CANFD_SETTINGS* cfg = getMutableCANFDSettingsFor(net); CANFD_SETTINGS* cfg = getMutableCANFDSettingsFor(net);
if(cfg == nullptr) if(cfg == nullptr) {
err(APIError::CANFDSettingsNotAvailable);
return false; return false;
}
CANBaudrate newBaud = GetEnumValueForBaudrate(baudrate); CANBaudrate newBaud = GetEnumValueForBaudrate(baudrate);
if(newBaud == (CANBaudrate)-1) if(newBaud == (CANBaudrate)-1) {
err(APIError::BaudrateNotFound);
return false; return false;
}
cfg->FDBaudrate = (uint8_t)newBaud; cfg->FDBaudrate = (uint8_t)newBaud;
return true; return true;
} }
default: default:
err(APIError::BadNetworkType);
return false; return false;
} }
} }
template<typename T> bool IDeviceSettings::applyStructure(const T& newStructure) { template<typename T> bool IDeviceSettings::applyStructure(const T& newStructure) {
if(!settingsLoaded || disabled || readonly) if(!settingsLoaded) {
err(APIError::SettingsReadError);
return false; return false;
}
// This function is only called from C++ so the callers structure size and ours should never differ if(disabled) {
if(sizeof(T) != structSize) err(APIError::SettingsNotAvailable);
return false;
}
if(readonly) {
err(APIError::SettingsReadOnly);
return false;
}
// This function is only called from C++ so the caller's structure size and ours should never differ
if(sizeof(T) != structSize) {
err(APIError::SettingsStructureMismatch);
return false; // The wrong structure was passed in for the current device return false; // The wrong structure was passed in for the current device
}
size_t copySize = sizeof(T); size_t copySize = sizeof(T);
if(copySize > settings.size()) if(copySize > settings.size()) {
err(APIError::SettingsStructureTruncated);
copySize = settings.size(); // TODO Warn user that their structure is truncated copySize = settings.size(); // TODO Warn user that their structure is truncated
}
// TODO Warn user that the device firmware doesn't support all the settings in the current API // Warn user that the device firmware doesn't support all the settings in the current API
//if(copySize < settings.size()) if(copySize < settings.size())
err(APIError::DeviceFirmwareOutOfDate);
memcpy(settings.data(), &newStructure, structSize); memcpy(settings.data(), &newStructure, structSize);
return apply(); return apply();

View File

@ -50,6 +50,17 @@ public:
SettingsLengthError = 0x2005, SettingsLengthError = 0x2005,
SettingsChecksumError = 0x2006, SettingsChecksumError = 0x2006,
SettingsNotAvailable = 0x2007, SettingsNotAvailable = 0x2007,
SettingsReadOnly = 0x2008,
CANSettingsNotAvailable = 0x2009,
CANFDSettingsNotAvailable = 0x2010,
LSFTCANSettingsNotAvailable = 0x2011,
SWCANSettingsNotAvailable = 0x2012,
BaudrateNotFound = 0x2013,
BadNetworkType = 0x2014,
DeviceFirmwareOutOfDate = 0x2015,
SettingsStructureMismatch = 0x2016,
SettingsStructureTruncated = 0x2017,
NoDeviceResponse = 0x2018,
// Transport Errors // Transport Errors
FailedToRead = 0x3000, FailedToRead = 0x3000,

View File

@ -399,13 +399,17 @@ public:
const size_t& getSize() const { return structSize; } const size_t& getSize() const { return structSize; }
// if settings are disabled for this device. always false unless constructed null
bool disabled = false; bool disabled = false;
bool readonly = false; bool readonly = false;
bool disableGSChecksumming = false; bool disableGSChecksumming = false;
protected: protected:
std::shared_ptr<Communication> com; std::shared_ptr<Communication> com;
device_errorhandler_t err; device_errorhandler_t err;
size_t structSize; size_t structSize;
// if we hold any local copies of the device settings
bool settingsLoaded = false; bool settingsLoaded = false;
std::vector<uint8_t> settings; // For writing settings to, calling apply() should copy over to device RAM (and EEPROM) std::vector<uint8_t> settings; // For writing settings to, calling apply() should copy over to device RAM (and EEPROM)