Device: Implement version handling
parent
8be3bbaee5
commit
595cc36545
|
|
@ -130,6 +130,7 @@ set(SRC_FILES
|
||||||
communication/packet/flexraypacket.cpp
|
communication/packet/flexraypacket.cpp
|
||||||
communication/packet/canpacket.cpp
|
communication/packet/canpacket.cpp
|
||||||
communication/packet/ethernetpacket.cpp
|
communication/packet/ethernetpacket.cpp
|
||||||
|
communication/packet/versionpacket.cpp
|
||||||
communication/packet/iso9141packet.cpp
|
communication/packet/iso9141packet.cpp
|
||||||
communication/decoder.cpp
|
communication/decoder.cpp
|
||||||
communication/encoder.cpp
|
communication/encoder.cpp
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
#include "icsneo/communication/message/serialnumbermessage.h"
|
#include "icsneo/communication/message/serialnumbermessage.h"
|
||||||
#include "icsneo/communication/message/filter/main51messagefilter.h"
|
#include "icsneo/communication/message/filter/main51messagefilter.h"
|
||||||
#include "icsneo/communication/message/readsettingsmessage.h"
|
#include "icsneo/communication/message/readsettingsmessage.h"
|
||||||
|
#include "icsneo/communication/message/versionmessage.h"
|
||||||
|
|
||||||
using namespace icsneo;
|
using namespace icsneo;
|
||||||
|
|
||||||
|
|
@ -118,7 +119,6 @@ bool Communication::getSettingsSync(std::vector<uint8_t>& data, std::chrono::mil
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<SerialNumberMessage> Communication::getSerialNumberSync(std::chrono::milliseconds timeout) {
|
std::shared_ptr<SerialNumberMessage> Communication::getSerialNumberSync(std::chrono::milliseconds timeout) {
|
||||||
sendCommand(Command::RequestSerialNumber);
|
|
||||||
std::shared_ptr<Message> msg = waitForMessageSync([this]() {
|
std::shared_ptr<Message> msg = waitForMessageSync([this]() {
|
||||||
return sendCommand(Command::RequestSerialNumber);
|
return sendCommand(Command::RequestSerialNumber);
|
||||||
}, Main51MessageFilter(Command::RequestSerialNumber), timeout);
|
}, Main51MessageFilter(Command::RequestSerialNumber), timeout);
|
||||||
|
|
@ -132,6 +132,37 @@ std::shared_ptr<SerialNumberMessage> Communication::getSerialNumberSync(std::chr
|
||||||
return std::dynamic_pointer_cast<SerialNumberMessage>(m51);
|
return std::dynamic_pointer_cast<SerialNumberMessage>(m51);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
optional< std::vector< optional<DeviceAppVersion> > > Communication::getVersionsSync(std::chrono::milliseconds timeout) {
|
||||||
|
std::vector< optional<DeviceAppVersion> > ret;
|
||||||
|
|
||||||
|
std::shared_ptr<Message> msg = waitForMessageSync([this]() {
|
||||||
|
return sendCommand(Command::GetMainVersion);
|
||||||
|
}, Main51MessageFilter(Command::GetMainVersion), timeout);
|
||||||
|
if(!msg) // Did not receive a message
|
||||||
|
return nullopt;
|
||||||
|
|
||||||
|
auto ver = std::dynamic_pointer_cast<VersionMessage>(msg);
|
||||||
|
if(!ver) // Could not upcast for some reason
|
||||||
|
return nullopt;
|
||||||
|
|
||||||
|
if(!ver->MainChip || ver->Versions.size() != 1)
|
||||||
|
return nullopt;
|
||||||
|
|
||||||
|
ret.push_back(ver->Versions.front());
|
||||||
|
|
||||||
|
msg = waitForMessageSync([this]() {
|
||||||
|
return sendCommand(Command::GetSecondaryVersions);
|
||||||
|
}, Main51MessageFilter(Command::GetSecondaryVersions), timeout);
|
||||||
|
if(msg) { // This one is allowed to fail
|
||||||
|
ver = std::dynamic_pointer_cast<VersionMessage>(msg);
|
||||||
|
if(ver && !ver->MainChip) {
|
||||||
|
ret.insert(ret.end(), ver->Versions.begin(), ver->Versions.end());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
int Communication::addMessageCallback(const MessageCallback& cb) {
|
int Communication::addMessageCallback(const MessageCallback& cb) {
|
||||||
std::lock_guard<std::mutex> lk(messageCallbacksLock);
|
std::lock_guard<std::mutex> lk(messageCallbacksLock);
|
||||||
messageCallbacks.insert(std::make_pair(messageCallbackIDCounter, cb));
|
messageCallbacks.insert(std::make_pair(messageCallbackIDCounter, cb));
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
#include "icsneo/communication/packet/ethernetpacket.h"
|
#include "icsneo/communication/packet/ethernetpacket.h"
|
||||||
#include "icsneo/communication/packet/flexraypacket.h"
|
#include "icsneo/communication/packet/flexraypacket.h"
|
||||||
#include "icsneo/communication/packet/iso9141packet.h"
|
#include "icsneo/communication/packet/iso9141packet.h"
|
||||||
|
#include "icsneo/communication/packet/versionpacket.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
using namespace icsneo;
|
using namespace icsneo;
|
||||||
|
|
@ -179,6 +180,24 @@ bool Decoder::decode(std::shared_ptr<Message>& result, const std::shared_ptr<Pac
|
||||||
result = msg;
|
result = msg;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
case Command::GetMainVersion: {
|
||||||
|
result = HardwareVersionPacket::DecodeMainToMessage(packet->data);
|
||||||
|
if(!result) {
|
||||||
|
report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::Error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case Command::GetSecondaryVersions: {
|
||||||
|
result = HardwareVersionPacket::DecodeSecondaryToMessage(packet->data);
|
||||||
|
if(!result) {
|
||||||
|
report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::Error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
auto msg = std::make_shared<Main51Message>();
|
auto msg = std::make_shared<Main51Message>();
|
||||||
msg->network = packet->network;
|
msg->network = packet->network;
|
||||||
|
|
|
||||||
|
|
@ -153,6 +153,8 @@ bool Encoder::encode(const Packetizer& packetizer, std::vector<uint8_t>& result,
|
||||||
case Command::RequestSerialNumber:
|
case Command::RequestSerialNumber:
|
||||||
case Command::EnableNetworkCommunication:
|
case Command::EnableNetworkCommunication:
|
||||||
case Command::EnableNetworkCommunicationEx:
|
case Command::EnableNetworkCommunicationEx:
|
||||||
|
case Command::GetMainVersion:
|
||||||
|
case Command::GetSecondaryVersions:
|
||||||
// There is a firmware handling idiosyncrasy with these commands
|
// There is a firmware handling idiosyncrasy with these commands
|
||||||
// They must be encoded in the short format
|
// They must be encoded in the short format
|
||||||
m51msg->forceShortFormat = true;
|
m51msg->forceShortFormat = true;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
#include "icsneo/communication/packet/versionpacket.h"
|
||||||
|
|
||||||
|
using namespace icsneo;
|
||||||
|
|
||||||
|
std::shared_ptr<VersionMessage> HardwareVersionPacket::DecodeMainToMessage(const std::vector<uint8_t>& bytestream) {
|
||||||
|
if(bytestream.size() < 3) // Not enough bytes to decode
|
||||||
|
return std::shared_ptr<VersionMessage>();
|
||||||
|
|
||||||
|
auto msg = std::make_shared<VersionMessage>(true);
|
||||||
|
|
||||||
|
optional<DeviceAppVersion>& version = msg->Versions.emplace_back();
|
||||||
|
version.emplace();
|
||||||
|
version->major = bytestream[1];
|
||||||
|
version->minor = bytestream[2];
|
||||||
|
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<VersionMessage> HardwareVersionPacket::DecodeSecondaryToMessage(const std::vector<uint8_t>& bytestream) {
|
||||||
|
auto msg = std::make_shared<VersionMessage>(false);
|
||||||
|
|
||||||
|
size_t bytesLeft = bytestream.size();
|
||||||
|
if(bytesLeft)
|
||||||
|
bytesLeft--; // Disregard command byte
|
||||||
|
while(bytesLeft >= 3) {
|
||||||
|
const bool versionValid = bytestream[bytestream.size() - bytesLeft + 0];
|
||||||
|
optional<DeviceAppVersion>& version = msg->Versions.emplace_back();
|
||||||
|
if(versionValid) {
|
||||||
|
version.emplace();
|
||||||
|
version->major = bytestream[bytestream.size() - bytesLeft + 1];
|
||||||
|
version->minor = bytestream[bytestream.size() - bytesLeft + 2];
|
||||||
|
}
|
||||||
|
bytesLeft -= std::min<size_t>(3, bytesLeft);
|
||||||
|
}
|
||||||
|
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
@ -267,6 +267,8 @@ bool Device::open(OpenFlags flags, OpenStatusHandler handler) {
|
||||||
}
|
}
|
||||||
|
|
||||||
APIEvent::Type Device::attemptToBeginCommunication() {
|
APIEvent::Type Device::attemptToBeginCommunication() {
|
||||||
|
versions.clear();
|
||||||
|
|
||||||
if(!afterCommunicationOpen()) {
|
if(!afterCommunicationOpen()) {
|
||||||
// Very unlikely, at the time of writing this only fails if rawWrite does.
|
// Very unlikely, at the time of writing this only fails if rawWrite does.
|
||||||
// If you're looking for this error, you're probably looking for if(!serial) below.
|
// If you're looking for this error, you're probably looking for if(!serial) below.
|
||||||
|
|
@ -287,6 +289,13 @@ APIEvent::Type Device::attemptToBeginCommunication() {
|
||||||
std::string currentSerial = getNeoDevice().serial;
|
std::string currentSerial = getNeoDevice().serial;
|
||||||
if(currentSerial != serial->deviceSerial)
|
if(currentSerial != serial->deviceSerial)
|
||||||
return APIEvent::Type::IncorrectSerialNumber;
|
return APIEvent::Type::IncorrectSerialNumber;
|
||||||
|
|
||||||
|
auto maybeVersions = com->getVersionsSync();
|
||||||
|
if(!maybeVersions)
|
||||||
|
return getCommunicationNotEstablishedError();
|
||||||
|
else
|
||||||
|
versions = std::move(*maybeVersions);
|
||||||
|
|
||||||
return APIEvent::Type::NoErrorFound;
|
return APIEvent::Type::NoErrorFound;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,11 +9,13 @@ enum class Command : uint8_t {
|
||||||
EnableNetworkCommunication = 0x07,
|
EnableNetworkCommunication = 0x07,
|
||||||
EnableNetworkCommunicationEx = 0x08,
|
EnableNetworkCommunicationEx = 0x08,
|
||||||
RequestSerialNumber = 0xA1,
|
RequestSerialNumber = 0xA1,
|
||||||
|
GetMainVersion = 0xA3, // Previously known as RED_CMD_APP_VERSION_REQ
|
||||||
SetSettings = 0xA4, // Previously known as RED_CMD_SET_BAUD_REQ, follow up with SaveSettings to write to EEPROM
|
SetSettings = 0xA4, // Previously known as RED_CMD_SET_BAUD_REQ, follow up with SaveSettings to write to EEPROM
|
||||||
//GetSettings = 0xA5, // Previously known as RED_CMD_READ_BAUD_REQ, now unused
|
//GetSettings = 0xA5, // Previously known as RED_CMD_READ_BAUD_REQ, now unused
|
||||||
SaveSettings = 0xA6,
|
SaveSettings = 0xA6,
|
||||||
UpdateLEDState = 0xA7,
|
UpdateLEDState = 0xA7,
|
||||||
SetDefaultSettings = 0xA8, // Follow up with SaveSettings to write to EEPROM
|
SetDefaultSettings = 0xA8, // Follow up with SaveSettings to write to EEPROM
|
||||||
|
GetSecondaryVersions = 0xA9, // Previously known as RED_CMD_PERIPHERALS_APP_VERSION_REQ, versions other than the main chip
|
||||||
RequestStatusUpdate = 0xBC,
|
RequestStatusUpdate = 0xBC,
|
||||||
ReadSettings = 0xC7, // Previously known as 3G_READ_SETTINGS_EX
|
ReadSettings = 0xC7, // Previously known as 3G_READ_SETTINGS_EX
|
||||||
MiscControl = 0xE7,
|
MiscControl = 0xE7,
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@
|
||||||
#include "icsneo/communication/packet.h"
|
#include "icsneo/communication/packet.h"
|
||||||
#include "icsneo/communication/message/callback/messagecallback.h"
|
#include "icsneo/communication/message/callback/messagecallback.h"
|
||||||
#include "icsneo/communication/message/serialnumbermessage.h"
|
#include "icsneo/communication/message/serialnumbermessage.h"
|
||||||
|
#include "icsneo/device/deviceversion.h"
|
||||||
#include "icsneo/api/eventmanager.h"
|
#include "icsneo/api/eventmanager.h"
|
||||||
#include "icsneo/communication/packetizer.h"
|
#include "icsneo/communication/packetizer.h"
|
||||||
#include "icsneo/communication/encoder.h"
|
#include "icsneo/communication/encoder.h"
|
||||||
|
|
@ -53,6 +54,7 @@ public:
|
||||||
virtual bool sendCommand(Command cmd, std::vector<uint8_t> arguments = {});
|
virtual bool sendCommand(Command cmd, std::vector<uint8_t> arguments = {});
|
||||||
bool getSettingsSync(std::vector<uint8_t>& data, std::chrono::milliseconds timeout = std::chrono::milliseconds(50));
|
bool getSettingsSync(std::vector<uint8_t>& data, std::chrono::milliseconds timeout = std::chrono::milliseconds(50));
|
||||||
std::shared_ptr<SerialNumberMessage> getSerialNumberSync(std::chrono::milliseconds timeout = std::chrono::milliseconds(50));
|
std::shared_ptr<SerialNumberMessage> getSerialNumberSync(std::chrono::milliseconds timeout = std::chrono::milliseconds(50));
|
||||||
|
optional< std::vector< optional<DeviceAppVersion> > > getVersionsSync(std::chrono::milliseconds timeout = std::chrono::milliseconds(50));
|
||||||
|
|
||||||
int addMessageCallback(const MessageCallback& cb);
|
int addMessageCallback(const MessageCallback& cb);
|
||||||
bool removeMessageCallback(int id);
|
bool removeMessageCallback(int id);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
#ifndef __VERSIONMESSAGE_H_
|
||||||
|
#define __VERSIONMESSAGE_H_
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
|
||||||
|
#include "icsneo/communication/message/message.h"
|
||||||
|
#include "icsneo/device/deviceversion.h"
|
||||||
|
#include "icsneo/platform/optional.h"
|
||||||
|
|
||||||
|
namespace icsneo {
|
||||||
|
|
||||||
|
class VersionMessage : public Message {
|
||||||
|
public:
|
||||||
|
VersionMessage(bool main) : MainChip(main) { network = Network::NetID::Main51; }
|
||||||
|
|
||||||
|
// If true, the included version is for the main chip
|
||||||
|
const bool MainChip;
|
||||||
|
|
||||||
|
// nullopt here indicates invalid
|
||||||
|
std::vector< optional<DeviceAppVersion> > Versions;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // __cplusplus
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
#ifndef __VERSIONPACKET_H__
|
||||||
|
#define __VERSIONPACKET_H__
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
|
||||||
|
#include "icsneo/communication/message/versionmessage.h"
|
||||||
|
#include <cstdint>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace icsneo {
|
||||||
|
|
||||||
|
struct HardwareVersionPacket {
|
||||||
|
static std::shared_ptr<VersionMessage> DecodeMainToMessage(const std::vector<uint8_t>& bytestream);
|
||||||
|
static std::shared_ptr<VersionMessage> DecodeSecondaryToMessage(const std::vector<uint8_t>& bytestream);
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // __cplusplus
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -15,6 +15,7 @@
|
||||||
#include "icsneo/device/idevicesettings.h"
|
#include "icsneo/device/idevicesettings.h"
|
||||||
#include "icsneo/device/nullsettings.h"
|
#include "icsneo/device/nullsettings.h"
|
||||||
#include "icsneo/device/devicetype.h"
|
#include "icsneo/device/devicetype.h"
|
||||||
|
#include "icsneo/device/deviceversion.h"
|
||||||
#include "icsneo/communication/communication.h"
|
#include "icsneo/communication/communication.h"
|
||||||
#include "icsneo/communication/packetizer.h"
|
#include "icsneo/communication/packetizer.h"
|
||||||
#include "icsneo/communication/encoder.h"
|
#include "icsneo/communication/encoder.h"
|
||||||
|
|
@ -210,6 +211,11 @@ public:
|
||||||
NODISCARD("If the Lifetime is not held, disconnects will be immediately unsuppressed")
|
NODISCARD("If the Lifetime is not held, disconnects will be immediately unsuppressed")
|
||||||
Lifetime suppressDisconnects();
|
Lifetime suppressDisconnects();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For use by extensions only. A more stable API will be provided in the future.
|
||||||
|
*/
|
||||||
|
const std::vector<optional<DeviceAppVersion>>& getVersions() const { return versions; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Some alternate communication protocols do not support DFU
|
* Some alternate communication protocols do not support DFU
|
||||||
*/
|
*/
|
||||||
|
|
@ -328,6 +334,7 @@ protected:
|
||||||
private:
|
private:
|
||||||
neodevice_t data;
|
neodevice_t data;
|
||||||
std::shared_ptr<ResetStatusMessage> latestResetStatus;
|
std::shared_ptr<ResetStatusMessage> latestResetStatus;
|
||||||
|
std::vector<optional<DeviceAppVersion>> versions;
|
||||||
|
|
||||||
mutable std::mutex extensionsLock;
|
mutable std::mutex extensionsLock;
|
||||||
std::vector<std::shared_ptr<DeviceExtension>> extensions;
|
std::vector<std::shared_ptr<DeviceExtension>> extensions;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
#ifndef __DEVICEVERSION_H_
|
||||||
|
#define __DEVICEVERSION_H_
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
|
||||||
|
#include "icsneo/platform/optional.h"
|
||||||
|
#include <cstdint>
|
||||||
|
#include <array>
|
||||||
|
|
||||||
|
namespace icsneo {
|
||||||
|
|
||||||
|
struct DeviceAppVersion {
|
||||||
|
uint8_t major = 0;
|
||||||
|
uint8_t minor = 0;
|
||||||
|
|
||||||
|
bool operator!=(const DeviceAppVersion& rhs) const { return major != rhs.major || minor != rhs.minor; }
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace icsneo
|
||||||
|
|
||||||
|
|
||||||
|
#endif // __cplusplus
|
||||||
|
|
||||||
|
#endif
|
||||||
Loading…
Reference in New Issue