diff --git a/CMakeLists.txt b/CMakeLists.txt index 71afa00..f552fcc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -136,6 +136,7 @@ set(SRC_FILES communication/packet/versionpacket.cpp communication/packet/iso9141packet.cpp communication/packet/ethphyregpacket.cpp + communication/packet/logicaldiskinfopacket.cpp communication/decoder.cpp communication/encoder.cpp communication/ethernetpacketizer.cpp diff --git a/communication/communication.cpp b/communication/communication.cpp index d2fd93a..a4d49fd 100644 --- a/communication/communication.cpp +++ b/communication/communication.cpp @@ -181,6 +181,18 @@ optional< std::vector< optional > > Communication::getVersions return ret; } +std::shared_ptr Communication::getLogicalDiskInfoSync(std::chrono::milliseconds timeout) { + static const std::shared_ptr filter = std::make_shared(Message::Type::LogicalDiskInfo); + + std::shared_ptr msg = waitForMessageSync([this]() { + return sendCommand(Command::GetLogicalDiskInfo); + }, filter, timeout); + if(!msg) // Did not receive a message + return {}; + + return std::dynamic_pointer_cast(msg); +} + int Communication::addMessageCallback(const MessageCallback& cb) { std::lock_guard lk(messageCallbacksLock); messageCallbacks.insert(std::make_pair(messageCallbackIDCounter, cb)); diff --git a/communication/decoder.cpp b/communication/decoder.cpp index 5779eab..eb9474f 100644 --- a/communication/decoder.cpp +++ b/communication/decoder.cpp @@ -14,6 +14,7 @@ #include "icsneo/communication/packet/iso9141packet.h" #include "icsneo/communication/packet/versionpacket.h" #include "icsneo/communication/packet/ethphyregpacket.h" +#include "icsneo/communication/packet/logicaldiskinfopacket.h" #include using namespace icsneo; @@ -277,10 +278,17 @@ bool Decoder::decode(std::shared_ptr& result, const std::shared_ptrdata); + if(!result) { + report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::EventWarning); + return false; + } + return true; + } case Network::NetID::EthPHYControl: { result = HardwareEthernetPhyRegisterPacket::DecodeToMessage(packet->data, report); - if(!result) - { + if(!result) { report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::EventWarning); return false; } diff --git a/communication/packet/logicaldiskinfopacket.cpp b/communication/packet/logicaldiskinfopacket.cpp new file mode 100644 index 0000000..79bc3da --- /dev/null +++ b/communication/packet/logicaldiskinfopacket.cpp @@ -0,0 +1,12 @@ +#include "icsneo/communication/packet/logicaldiskinfopacket.h" + +using namespace icsneo; + +std::shared_ptr LogicalDiskInfoPacket::DecodeToMessage(const std::vector& bytestream) { + // Make sure we have enough to read the packet length first + if(bytestream.size() < sizeof(LogicalDiskInfoPacket)) + return {}; + + const LogicalDiskInfoPacket* packet = reinterpret_cast(bytestream.data()); + return std::make_shared(packet->isConnected != 0, packet->numSectors, packet->hiddenSectors, packet->bytesPerSector); +} \ No newline at end of file diff --git a/device/device.cpp b/device/device.cpp index ecde903..5d00b73 100644 --- a/device/device.cpp +++ b/device/device.cpp @@ -502,6 +502,36 @@ optional Device::writeLogicalDisk(uint64_t pos, const uint8_t* from, u return diskWriteDriver->writeLogicalDisk(*com, report, *diskReadDriver, pos, from, amount, timeout); } +optional Device::isLogicalDiskConnected() { + if(!isOpen()) { + report(APIEvent::Type::DeviceCurrentlyClosed, APIEvent::Severity::Error); + return nullopt; + } + + const auto info = com->getLogicalDiskInfoSync(); + if (!info) { + report(APIEvent::Type::Timeout, APIEvent::Severity::Error); + return nullopt; + } + + return info->connected; +} + +optional Device::getLogicalDiskSize() { + if(!isOpen()) { + report(APIEvent::Type::DeviceCurrentlyClosed, APIEvent::Severity::Error); + return nullopt; + } + + const auto info = com->getLogicalDiskInfoSync(); + if (!info) { + report(APIEvent::Type::Timeout, APIEvent::Severity::Error); + return nullopt; + } + + return info->getReportedSize(); +} + optional Device::getDigitalIO(IO type, size_t number /* = 1 */) { if(number == 0) { // Start counting from 1 report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error); diff --git a/include/icsneo/communication/command.h b/include/icsneo/communication/command.h index cbc09ed..406623e 100644 --- a/include/icsneo/communication/command.h +++ b/include/icsneo/communication/command.h @@ -17,11 +17,12 @@ enum class Command : uint8_t { UpdateLEDState = 0xA7, 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 + GetLogicalDiskInfo = 0xBB, // Previously known as RED_CMD_GET_SDCARD_INFO RequestStatusUpdate = 0xBC, ReadSettings = 0xC7, // Previously known as 3G_READ_SETTINGS_EX SetVBattMonitor = 0xDB, // Previously known as RED_CMD_CM_VBATT_MONITOR RequestBitSmash = 0xDC, // Previously known as RED_CMD_CM_BITSMASH - GetVBattReq = 0xDF, // Previously known as RED_CMD_VBATT_REQUEST + GetVBattReq = 0xDF, // Previously known as RED_CMD_VBATT_REQUEST MiscControl = 0xE7, Extended = 0xF0, FlexRayControl = 0xF3, diff --git a/include/icsneo/communication/communication.h b/include/icsneo/communication/communication.h index dfa49b6..ee9c2a9 100644 --- a/include/icsneo/communication/communication.h +++ b/include/icsneo/communication/communication.h @@ -9,6 +9,7 @@ #include "icsneo/communication/packet.h" #include "icsneo/communication/message/callback/messagecallback.h" #include "icsneo/communication/message/serialnumbermessage.h" +#include "icsneo/communication/message/logicaldiskinfomessage.h" #include "icsneo/device/deviceversion.h" #include "icsneo/api/eventmanager.h" #include "icsneo/communication/packetizer.h" @@ -56,7 +57,8 @@ public: bool getSettingsSync(std::vector& data, std::chrono::milliseconds timeout = std::chrono::milliseconds(50)); std::shared_ptr getSerialNumberSync(std::chrono::milliseconds timeout = std::chrono::milliseconds(50)); optional< std::vector< optional > > getVersionsSync(std::chrono::milliseconds timeout = std::chrono::milliseconds(50)); - + std::shared_ptr getLogicalDiskInfoSync(std::chrono::milliseconds timeout = std::chrono::milliseconds(50)); + int addMessageCallback(const MessageCallback& cb); bool removeMessageCallback(int id); std::shared_ptr waitForMessageSync( diff --git a/include/icsneo/communication/message/logicaldiskinfomessage.h b/include/icsneo/communication/message/logicaldiskinfomessage.h new file mode 100644 index 0000000..f46bf4b --- /dev/null +++ b/include/icsneo/communication/message/logicaldiskinfomessage.h @@ -0,0 +1,29 @@ +#ifndef __LOGICALDISKINFOMESSAGE_H_ +#define __LOGICALDISKINFOMESSAGE_H_ + +#ifdef __cplusplus + +#include "icsneo/communication/message/message.h" +#include + +namespace icsneo { + +class LogicalDiskInfoMessage : public Message { +public: + LogicalDiskInfoMessage(bool isConnected, uint32_t numSectors, uint32_t numHidden, uint32_t sectorSize) : + Message(Message::Type::LogicalDiskInfo), connected(isConnected), sectors(numSectors), + hiddenSectors(numHidden), bytesPerSector(sectorSize) {} + + const bool connected; + const uint32_t sectors; + const uint32_t hiddenSectors; + const uint32_t bytesPerSector; + + uint64_t getReportedSize() const { return uint64_t(sectors) * bytesPerSector; } +}; + +} + +#endif // __cplusplus + +#endif \ No newline at end of file diff --git a/include/icsneo/communication/message/message.h b/include/icsneo/communication/message/message.h index c26bc7e..eb04658 100644 --- a/include/icsneo/communication/message/message.h +++ b/include/icsneo/communication/message/message.h @@ -27,6 +27,7 @@ public: Main51 = 0x8005, FlexRayControl = 0x8006, EthernetPhyRegister = 0x8007, + LogicalDiskInfo = 0x8008, }; Message(Type t) : type(t) {} diff --git a/include/icsneo/communication/network.h b/include/icsneo/communication/network.h index 73ab8dd..4909c73 100644 --- a/include/icsneo/communication/network.h +++ b/include/icsneo/communication/network.h @@ -117,6 +117,7 @@ public: HSCAN7 = 97, LIN6 = 98, LSFTCAN2 = 99, + LogicalDiskInfo = 187, EthPHYControl = 239, FlexRayControl = 243, HW_COM_Latency_Test = 512, @@ -271,6 +272,7 @@ public: case NetID::FlexRayControl: case NetID::Main51: case NetID::ReadSettings: + case NetID::LogicalDiskInfo: case NetID::EthPHYControl: case NetID::NeoMemorySDRead: return Type::Internal; @@ -507,6 +509,8 @@ public: return "LIN 6"; case NetID::LSFTCAN2: return "LSFTCAN 2"; + case NetID::LogicalDiskInfo: + return "Logical Disk Information"; case NetID::EthPHYControl: return "Ethernet PHY Register Control"; case NetID::FlexRayControl: @@ -907,6 +911,7 @@ private: #define ICSNEO_NETID_HSCAN7 97 #define ICSNEO_NETID_LIN6 98 #define ICSNEO_NETID_LSFTCAN2 99 +#define ICSNEO_NETID_LOGICAL_DISK_INFO 187 #define ICSNEO_NETID_ETH_PHY_CONTROL 239 #define ICSNEO_NETID_FLEXRAY_CONTROL 243 #define ICSNEO_NETID_HW_COM_LATENCY_TEST 512 diff --git a/include/icsneo/communication/packet/logicaldiskinfopacket.h b/include/icsneo/communication/packet/logicaldiskinfopacket.h new file mode 100644 index 0000000..5ddcb5e --- /dev/null +++ b/include/icsneo/communication/packet/logicaldiskinfopacket.h @@ -0,0 +1,28 @@ +#ifndef __LOGICALDISKINFOPACKET_H__ +#define __LOGICALDISKINFOPACKET_H__ + +#ifdef __cplusplus + +#include "icsneo/communication/message/logicaldiskinfomessage.h" +#include "icsneo/api/eventmanager.h" +#include +#include + +namespace icsneo { + +#pragma pack(push,2) +struct LogicalDiskInfoPacket { + static std::shared_ptr DecodeToMessage(const std::vector& bytestream); + + uint16_t isConnected; + uint32_t numSectors; + uint32_t hiddenSectors; + uint32_t bytesPerSector; +}; +#pragma pack(pop) + +} + +#endif // __cplusplus + +#endif \ No newline at end of file diff --git a/include/icsneo/device/device.h b/include/icsneo/device/device.h index 8952ddb..d5997a6 100644 --- a/include/icsneo/device/device.h +++ b/include/icsneo/device/device.h @@ -176,6 +176,28 @@ public: optional writeLogicalDisk(uint64_t pos, const uint8_t* from, uint64_t amount, std::chrono::milliseconds timeout = Disk::DefaultTimeout); + /** + * Check if the logical disk is connected. This means the disk is inserted, + * and if required (for instance for multi-card configurations), configured + * properly. + * + * This method is synchronous and contacts the device for the latest status. + * + * `icsneo::nullopt` will be returned if the device does not respond in a + * timely manner. + */ + optional isLogicalDiskConnected(); + + /** + * Get the size of the connected logical disk in bytes. + * + * This method is synchronous and contacts the device for the latest status. + * + * `icsneo::nullopt` will be returned if the device does not respond in a + * timely manner, or if the disk is disconnected/improperly configured. + */ + optional getLogicalDiskSize(); + /** * Retrieve the number of Ethernet (DoIP) Activation lines present * on this device.