diff --git a/api/icsneoc/icsneoc.cpp b/api/icsneoc/icsneoc.cpp index 124c2ae..c165c08 100644 --- a/api/icsneoc/icsneoc.cpp +++ b/api/icsneoc/icsneoc.cpp @@ -212,6 +212,16 @@ bool icsneo_getProductName(const neodevice_t* device, char* str, size_t* maxLeng return true; } +bool icsneo_settingsRefresh(const neodevice_t* device) { + if(!icsneo_isValidNeoDevice(device)) + return false; + + if(!device->device->settings) // Settings are not available for this device + return false; + + return device->device->settings->refresh(); +} + bool icsneo_settingsApply(const neodevice_t* device) { if(!icsneo_isValidNeoDevice(device)) return false; diff --git a/api/icsneoc/include/icsneoc.h b/api/icsneoc/include/icsneoc.h index 7a38c6d..971487c 100644 --- a/api/icsneoc/include/icsneoc.h +++ b/api/icsneoc/include/icsneoc.h @@ -44,6 +44,8 @@ extern bool DLLExport icsneo_setPollingMessageLimit(const neodevice_t* device, s extern bool DLLExport icsneo_getProductName(const neodevice_t* device, char* str, size_t* maxLength); +extern bool DLLExport icsneo_settingsRefresh(const neodevice_t* device); + extern bool DLLExport icsneo_settingsApply(const neodevice_t* device); extern bool DLLExport icsneo_settingsApplyTemporary(const neodevice_t* device); @@ -108,6 +110,9 @@ fn_icsneo_setPollingMessageLimit icsneo_setPollingMessageLimit; typedef bool(*fn_icsneo_getProductName)(const neodevice_t* device, char* str, size_t* maxLength); fn_icsneo_getProductName icsneo_getProductName; +typedef bool(*fn_icsneo_settingsRefresh)(const neodevice_t* device); +fn_icsneo_settingsRefresh icsneo_settingsRefresh; + typedef bool(*fn_icsneo_settingsApply)(const neodevice_t* device); fn_icsneo_settingsApply icsneo_settingsApply; @@ -153,6 +158,7 @@ int icsneo_init() { ICSNEO_IMPORTASSERT(icsneo_getPollingMessageLimit); ICSNEO_IMPORTASSERT(icsneo_setPollingMessageLimit); ICSNEO_IMPORTASSERT(icsneo_getProductName); + ICSNEO_IMPORTASSERT(icsneo_settingsRefresh); ICSNEO_IMPORTASSERT(icsneo_settingsApply); ICSNEO_IMPORTASSERT(icsneo_settingsApplyTemporary); ICSNEO_IMPORTASSERT(icsneo_settingsApplyDefaults); diff --git a/api/icsneolegacy/icsneolegacy.cpp b/api/icsneolegacy/icsneolegacy.cpp index e856a1a..55c0467 100644 --- a/api/icsneolegacy/icsneolegacy.cpp +++ b/api/icsneolegacy/icsneolegacy.cpp @@ -1,9 +1,21 @@ +#ifndef __cplusplus +#error "icsneoc.cpp must be compiled with a C++ compiler!" +#endif + #define ICSNEOC_MAKEDLL #include "api/icsneolegacy/include/icsneolegacy.h" #undef ICSNEOC_MAKEDLL #include "api/icsneoc/include/icsneoc.h" +#include "communication/include/network.h" +#include + +using namespace icsneo; + +typedef uint64_t legacymaphandle_t; +static std::map neodevices; + static NeoDevice OldNeoDeviceFromNew(const neodevice_t* newnd) { NeoDevice oldnd = { 0 }; oldnd.DeviceType = newnd->type; @@ -39,26 +51,43 @@ int icsneoFindNeoDevices(unsigned long DeviceTypes, NeoDevice* pNeoDevice, int* count = bufferSize; *pNumDevices = (int)count; - for(int i = 0; i < count; i++) - pNeoDevice[i] = OldNeoDeviceFromNew(&devices[i]); + for(int i = 0; i < count; i++) { + pNeoDevice[i] = OldNeoDeviceFromNew(&devices[i]); // Write out into user memory + neodevices[uint64_t(devices[i].handle) << 32 | icsneo_serialStringToNum(devices[i].serial)] = devices[i]; // Fill the look up table + } return 1; } -int icsneoOpenNeoDevice(NeoDevice* pNeoDevice, void* hObject, unsigned char* bNetworkIDs, int bConfigRead, int bSyncToPC) { - // TODO Implement - return false; +int icsneoOpenNeoDevice(NeoDevice* pNeoDevice, void** hObject, unsigned char* bNetworkIDs, int bConfigRead, int bSyncToPC) { + if(pNeoDevice == nullptr || hObject == nullptr) + return false; + + neodevice_t* device; + try { + device = &neodevices.at(uint64_t(pNeoDevice->Handle) << 32 | pNeoDevice->SerialNumber); + } catch(std::out_of_range& e) { + return false; + } + + *hObject = device; + if(!icsneo_openDevice(device)) + return false; + icsneo_setPollingMessageLimit(device, 20000); + icsneo_enableMessagePolling(device); + return icsneo_goOnline(device); } int icsneoClosePort(void* hObject, int* pNumberOfErrors) { - // TODO Implement - return false; + if(!icsneoValidateHObject(hObject)) + return false; + neodevice_t* device = (neodevice_t*)hObject; + + return icsneo_closeDevice(device); } -void icsneoFreeObject(void* hObject) { - // TODO Implement - return; -} +// Memory is now managed automatically, this function is unneeded +void icsneoFreeObject(void* hObject) { (void)hObject; return; } int icsneoSerialNumberToString(unsigned long serial, char* data, unsigned long data_size) { size_t length = (size_t)data_size; @@ -67,8 +96,38 @@ int icsneoSerialNumberToString(unsigned long serial, char* data, unsigned long d //Message Functions int icsneoGetMessages(void* hObject, icsSpyMessage* pMsg, int* pNumberOfMessages, int* pNumberOfErrors) { - // TODO Implement - return false; + static neomessage_t messages[20000]; + if(!icsneoValidateHObject(hObject)) + return false; + neodevice_t* device = (neodevice_t*)hObject; + + size_t messageCount = 20000; + if(!icsneo_getMessages(device, messages, &messageCount)) + return false; + + *pNumberOfMessages = (int)messageCount; + *pNumberOfErrors = 0; + + memset(pMsg, 0, sizeof(icsSpyMessage) * messageCount); + for(size_t i = 0; i < messageCount; i++) { + icsSpyMessage& oldmsg = pMsg[i]; + neomessage_t& newmsg = messages[i]; + oldmsg.NumberBytesData = (uint8_t)min(newmsg.length, 255); + oldmsg.NumberBytesHeader = 4; + oldmsg.ExtraDataPtr = (void*)newmsg.data; + memcpy(oldmsg.Data, newmsg.data, min(newmsg.length, 8)); + oldmsg.ArbIDOrHeader = *(uint32_t*)newmsg.header; + oldmsg.ExtraDataPtrEnabled = newmsg.length > 8; + oldmsg.NetworkID = newmsg.netid; + switch(Network::Type(newmsg.type)) { + case Network::Type::CAN: + oldmsg.Protocol = SPY_PROTOCOL_CAN; + break; + // TODO Handle this better + } + } + + return true; } int icsneoTxMessages(void* hObject, icsSpyMessage* pMsg, int lNetworkID, int lNumMessages) { @@ -76,7 +135,7 @@ int icsneoTxMessages(void* hObject, icsSpyMessage* pMsg, int lNetworkID, int lNu return false; } -int icsneoTxMessagesEx(void* hObject,icsSpyMessage* pMsg, unsigned int lNetworkID, unsigned int lNumMessages, unsigned int* NumTxed, unsigned int zero2) { +int icsneoTxMessagesEx(void* hObject, icsSpyMessage* pMsg, unsigned int lNetworkID, unsigned int lNumMessages, unsigned int* NumTxed, unsigned int zero2) { // TODO Implement return false; } @@ -214,7 +273,7 @@ int icsneoGetErrorMessages(void* hObject, int* pErrorMsgs, int* pNumberOfErrors) return false; } -int icsneoGetErrorInfo(int lErrorNumber, TCHAR*szErrorDescriptionShort, TCHAR*szErrorDescriptionLong, int* lMaxLengthShort, int* lMaxLengthLong,int* lErrorSeverity,int* lRestartNeeded) { +int icsneoGetErrorInfo(int lErrorNumber, TCHAR* szErrorDescriptionShort, TCHAR* szErrorDescriptionLong, int* lMaxLengthShort, int* lMaxLengthLong, int* lErrorSeverity, int* lRestartNeeded) { // TODO Implement return false; } @@ -235,14 +294,21 @@ int icsneoISO15765_TransmitMessage(void* hObject, unsigned long ulNetworkID, stC return false; } -int icsneoISO15765_ReceiveMessage(void* hObject,int ulNetworkID, stCM_ISO157652_RxMessage* pMsg) { +int icsneoISO15765_ReceiveMessage(void* hObject, int ulNetworkID, stCM_ISO157652_RxMessage* pMsg) { // TODO Implement return false; } //General Utility Functions int icsneoValidateHObject(void* hObject) { - // TODO Implement + for(auto it = neodevices.begin(); it != neodevices.end(); it++) { + if(&it->second == hObject) { + neodevice_t* device = (neodevice_t*)hObject; + if(icsneo_isValidNeoDevice(device)) + return true; + } + } + return false; } @@ -329,8 +395,14 @@ int icsneoOpenPort(int lPortNumber, int lPortType, int lDriverType, unsigned cha } int icsneoEnableNetworkCom(void* hObject, int Enable) { - // TODO Implement - return false; + if(!icsneoValidateHObject(hObject)) + return false; + neodevice_t* device = (neodevice_t*)hObject; + + if(Enable) + return icsneo_goOnline(device); + else + return icsneo_goOffline(device); } int icsneoFindAllCOMDevices(int lDriverType, int lGetSerialNumbers, int lStopAtFirst, int lUSBCommOnly, int* p_lDeviceTypes, int* p_lComPorts, int* p_lSerialNumbers, int*lNumDevices) { diff --git a/api/icsneolegacy/include/icsneolegacy.h b/api/icsneolegacy/include/icsneolegacy.h index b81c50a..7aa96aa 100644 --- a/api/icsneolegacy/include/icsneolegacy.h +++ b/api/icsneolegacy/include/icsneolegacy.h @@ -14,10 +14,10 @@ extern "C" { //Basic Functions extern int DLLExport icsneoFindNeoDevices(unsigned long DeviceTypes, NeoDevice* pNeoDevice, int* pNumDevices); -extern int DLLExport icsneoOpenNeoDevice(NeoDevice* pNeoDevice, void* hObject, unsigned char* bNetworkIDs, int bConfigRead, int bSyncToPC); +extern int DLLExport icsneoOpenNeoDevice(NeoDevice* pNeoDevice, void** hObject, unsigned char* bNetworkIDs, int bConfigRead, int bSyncToPC); extern int DLLExport icsneoClosePort(void* hObject, int* pNumberOfErrors); extern void DLLExport icsneoFreeObject(void* hObject); -extern int DLLExport icsneoSerialNumberToString(unsigned long serial, char*data,unsigned long data_size); +extern int DLLExport icsneoSerialNumberToString(unsigned long serial, char* data, unsigned long data_size); //Message Functions extern int DLLExport icsneoGetMessages(void* hObject, icsSpyMessage* pMsg, int* pNumberOfMessages, int* pNumberOfErrors); diff --git a/communication/icommunication.cpp b/communication/icommunication.cpp index 146cdf5..2c7dd9b 100644 --- a/communication/icommunication.cpp +++ b/communication/icommunication.cpp @@ -15,7 +15,8 @@ bool ICommunication::read(std::vector& bytes, size_t limit) { size_t actuallyRead = readQueue.try_dequeue_bulk(bytes.data(), limit); - bytes.resize(actuallyRead); + if(bytes.size() > actuallyRead) + bytes.resize(actuallyRead); return true; } diff --git a/communication/include/network.h b/communication/include/network.h index 9a6040b..b6dbd71 100644 --- a/communication/include/network.h +++ b/communication/include/network.h @@ -112,16 +112,19 @@ public: LSFTCAN2 = 99, HW_COM_Latency_Test = 512, Device_Status = 513, + Any = 0xfffe, // Never actually set as type, but used as flag for filtering Invalid = 0xffff }; enum class Type { + Invalid, + Internal, // Used for statuses that don't actually need to be transferred to the client application CAN, LIN, FlexRay, MOST, Ethernet, Other, - Invalid + Any // Never actually set as type, but used as flag for filtering }; static const char* GetTypeString(Type type) { switch(type) { @@ -135,6 +138,8 @@ public: return "MOST"; case Type::Other: return "Other"; + case Type::Internal: + return "Internal"; case Type::Invalid: default: return "Invalid Type"; @@ -173,7 +178,12 @@ public: case NetID::MOST50: case NetID::MOST150: return Type::MOST; + case NetID::RED: + case NetID::Reset_Status: + case NetID::Device_Status: + return Type::Internal; case NetID::Invalid: + case NetID::Any: return Type::Invalid; default: return Type::Other; diff --git a/communication/message/filter/include/messagefilter.h b/communication/message/filter/include/messagefilter.h index 88916f4..2320cc2 100644 --- a/communication/message/filter/include/messagefilter.h +++ b/communication/message/filter/include/messagefilter.h @@ -9,14 +9,14 @@ namespace icsneo { class MessageFilter { public: - MessageFilter() : matchAny(true) {} + MessageFilter() {} MessageFilter(Network::Type type) : type(type) {} MessageFilter(Network::NetID netid) : netid(netid) {} virtual ~MessageFilter() {} + // When getting "all" types of messages, include the ones marked as "internal only" + bool includeInternalInAny = false; virtual bool match(const std::shared_ptr& message) const { - if(matchAny) - return true; if(!matchType(message->network.getType())) return false; if(!matchNetID(message->network.getNetID())) @@ -25,18 +25,16 @@ public: } private: - bool matchAny = false; - - Network::Type type = Network::Type::Invalid; // Matching a type of invalid will match any + Network::Type type = Network::Type::Any; bool matchType(Network::Type mtype) const { - if(type == Network::Type::Invalid) + if(type == Network::Type::Any && (mtype != Network::Type::Internal || includeInternalInAny)) return true; return type == mtype; } - Network::NetID netid = Network::NetID::Invalid; // Matching a netid of invalid will match any + Network::NetID netid = Network::NetID::Any; bool matchNetID(Network::NetID mnetid) const { - if(netid == Network::NetID::Invalid) + if(netid == Network::NetID::Any) return true; return netid == mnetid; } diff --git a/device/device.cpp b/device/device.cpp index 4d643af..30cf0f1 100644 --- a/device/device.cpp +++ b/device/device.cpp @@ -106,7 +106,8 @@ bool Device::getMessages(std::vector>& container, size_ size_t actuallyRead = pollingContainer.try_dequeue_bulk(container.data(), limit); - container.resize(actuallyRead); + if(container.size() > actuallyRead) + container.resize(actuallyRead); return true; } diff --git a/device/idevicesettings.cpp b/device/idevicesettings.cpp index f0449fa..7080c4b 100644 --- a/device/idevicesettings.cpp +++ b/device/idevicesettings.cpp @@ -42,12 +42,12 @@ uint16_t IDeviceSettings::CalculateGSChecksum(const std::vector& settin return gs_crc; } -void IDeviceSettings::refresh(bool ignoreChecksum) { +bool IDeviceSettings::refresh(bool ignoreChecksum) { std::vector rxSettings; bool ret = com->getSettingsSync(rxSettings); if(ret) { if(rxSettings.size() < 6) // We need to at least have the header of GLOBAL_SETTINGS - return; + return false; constexpr size_t gs_size = 3 * sizeof(uint16_t); size_t rxLen = rxSettings.size() - gs_size; @@ -59,17 +59,17 @@ void IDeviceSettings::refresh(bool ignoreChecksum) { if(gs_version != 5) { std::cout << "gs_version was " << gs_version << " instead of 5.\nPlease update your firmware." << std::endl; - return; + return false; } if(rxLen != gs_len) { std::cout << "rxLen was " << rxLen << " and gs_len was " << gs_len << " while reading settings" << std::endl; - return; + return false; } if(!ignoreChecksum && gs_chksum != CalculateGSChecksum(rxSettings)) { std::cout << "Checksum mismatch while reading settings" << std::endl; - return; + return false; } settings = std::move(rxSettings); @@ -79,6 +79,8 @@ void IDeviceSettings::refresh(bool ignoreChecksum) { std::cout << "Settings size was " << settings.size() << " bytes but it should be " << structSize << " bytes for this device" << std::endl; settingsLoaded = false; } + + return settingsLoaded; } } diff --git a/device/include/idevicesettings.h b/device/include/idevicesettings.h index 8c9f649..fb17e6a 100644 --- a/device/include/idevicesettings.h +++ b/device/include/idevicesettings.h @@ -285,7 +285,7 @@ public: virtual ~IDeviceSettings() {} bool ok() { return settingsLoaded; } - void refresh(bool ignoreChecksum = false); // Get from device + bool refresh(bool ignoreChecksum = false); // Get from device // Send to device, if temporary device keeps settings in volatile RAM until power cycle, otherwise saved to EEPROM bool apply(bool temporary = false); diff --git a/device/include/neodevice.h b/device/include/neodevice.h index 82c45a2..3990d2c 100644 --- a/device/include/neodevice.h +++ b/device/include/neodevice.h @@ -21,9 +21,9 @@ typedef int32_t neodevice_handle_t; #pragma pack(push, 1) typedef struct { - devicehandle_t device; - neodevice_handle_t handle; - devicetype_t type; + devicehandle_t device; // Pointer back to the C++ device object + neodevice_handle_t handle; // Handle for use by the underlying driver + devicetype_t type; char serial[7]; } neodevice_t;