118 changed files with 1930 additions and 6304 deletions
-56
View File
@@ -171,8 +171,6 @@ test linux/ubuntu/2204/amd64/clang:
paths:
- /var/cache/dnf
script:
- echo max_parallel_downloads=10 >>/etc/dnf/dnf.conf
- echo fastestmirror=True >>/etc/dnf/dnf.conf
- dnf upgrade -y
- dnf install -y g++ libpcap-devel cmake ninja-build libusb1-devel
- sh ci/build-posix.sh
@@ -190,8 +188,6 @@ test linux/ubuntu/2204/amd64/clang:
paths:
- /var/cache/dnf
script:
- echo max_parallel_downloads=10 >>/etc/dnf/dnf.conf
- echo fastestmirror=True >>/etc/dnf/dnf.conf
- dnf upgrade -y
- dnf install -y libpcap-devel libusb1-devel
- build/libicsneo-tests
@@ -205,8 +201,6 @@ test linux/ubuntu/2204/amd64/clang:
paths:
- /var/cache/dnf
script:
- echo max_parallel_downloads=10 >>/etc/dnf/dnf.conf
- echo fastestmirror=True >>/etc/dnf/dnf.conf
- dnf upgrade -y
- dnf install -y clang lld libpcap-devel cmake ninja-build libusb1-devel
- CC=clang CXX=clang++ LDFLAGS=-fuse-ld=lld sh ci/build-posix.sh
@@ -224,8 +218,6 @@ test linux/ubuntu/2204/amd64/clang:
paths:
- /var/cache/dnf
script:
- echo max_parallel_downloads=10 >>/etc/dnf/dnf.conf
- echo fastestmirror=True >>/etc/dnf/dnf.conf
- dnf upgrade -y
- dnf install -y libpcap-devel libusb1-devel
- build/libicsneo-tests
@@ -256,51 +248,3 @@ test linux/fedora/37/amd64/clang:
- build linux/fedora/37/amd64/clang
needs:
- build linux/fedora/37/amd64/clang
build linux/fedora/38/amd64/gcc:
<<: *build_linux_fedora_gcc
image: fedora:38
test linux/fedora/38/amd64/gcc:
<<: *test_linux_fedora_gcc
image: fedora:38
dependencies:
- build linux/fedora/38/amd64/gcc
needs:
- build linux/fedora/38/amd64/gcc
build linux/fedora/38/amd64/clang:
<<: *build_linux_fedora_clang
image: fedora:38
test linux/fedora/38/amd64/clang:
<<: *test_linux_fedora_clang
image: fedora:38
dependencies:
- build linux/fedora/38/amd64/clang
needs:
- build linux/fedora/38/amd64/clang
build linux/fedora/39/amd64/gcc:
<<: *build_linux_fedora_gcc
image: fedora:39
test linux/fedora/39/amd64/gcc:
<<: *test_linux_fedora_gcc
image: fedora:39
dependencies:
- build linux/fedora/39/amd64/gcc
needs:
- build linux/fedora/39/amd64/gcc
build linux/fedora/39/amd64/clang:
<<: *build_linux_fedora_clang
image: fedora:39
test linux/fedora/39/amd64/clang:
<<: *test_linux_fedora_clang
image: fedora:39
dependencies:
- build linux/fedora/39/amd64/clang
needs:
- build linux/fedora/39/amd64/clang
+23 -23
View File
@@ -2,9 +2,6 @@ cmake_minimum_required(VERSION 3.12)
project(libicsneo VERSION 0.3.0)
cmake_policy(SET CMP0074 NEW)
if(POLICY CMP0135)
cmake_policy(SET CMP0135 NEW)
endif()
option(LIBICSNEO_BUILD_TESTS "Build all tests." OFF)
option(LIBICSNEO_BUILD_DOCS "Build documentation. Don't use in Visual Studio." OFF)
@@ -21,6 +18,7 @@ set(LIBICSNEO_NPCAP_INCLUDE_DIR "" CACHE STRING "Npcap include directory; set to
option(LIBICSNEO_ENABLE_FIRMIO "Enable communication between Linux and CoreMini within the same device" OFF)
option(LIBICSNEO_ENABLE_RAW_ETHERNET "Enable devices which communicate over raw ethernet" ON)
option(LIBICSNEO_ENABLE_CDCACM "Enable devices which communicate over USB CDC ACM" ON)
option(LIBICSNEO_ENABLE_ANDROIDUSB "Enable devices which communicate over USB CDC ACM on Android" ON)
option(LIBICSNEO_ENABLE_FTDI "Enable devices which communicate over USB FTDI2XX" ON)
option(LIBICSNEO_ENABLE_TCP "Enable devices which communicate over TCP" OFF)
option(LIBICSNEO_ENABLE_FTD3XX "Enable devices which communicate over USB FTD3XX" ON)
@@ -48,8 +46,6 @@ else() #if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-switch -Wno-unknown-pragmas")
endif()
find_package(Threads REQUIRED)
# doxygen
find_package(Doxygen)
if(DOXYGEN_FOUND)
@@ -122,6 +118,12 @@ if(WIN32)
platform/windows/vcp.cpp
)
endif()
elseif(LIBICSNEO_ENABLE_ANDROIDUSB)
list(APPEND PLATFORM_SRC
platform/android/androidusb.cpp
)
else() # Darwin or Linux
set(PLATFORM_SRC)
@@ -166,6 +168,7 @@ else() # Darwin or Linux
endif()
endif()
if(LIBICSNEO_ENABLE_FTD3XX)
if(NOT FTD3XX_ROOT) # allow system override
include(FetchContent)
@@ -278,22 +281,6 @@ set(SRC_FILES
disk/plasiondiskreaddriver.cpp
disk/extextractordiskreaddriver.cpp
disk/fat.cpp
disk/vsa/vsa.cpp
disk/vsa/vsa02.cpp
disk/vsa/vsa03.cpp
disk/vsa/vsa04.cpp
disk/vsa/vsa05.cpp
disk/vsa/vsa06.cpp
disk/vsa/vsa07.cpp
disk/vsa/vsa08.cpp
disk/vsa/vsa09.cpp
disk/vsa/vsa0b.cpp
disk/vsa/vsa0c.cpp
disk/vsa/vsa0d.cpp
disk/vsa/vsa0e.cpp
disk/vsa/vsa0f.cpp
disk/vsa/vsa6a.cpp
disk/vsa/vsaparser.cpp
${PLATFORM_SRC}
)
@@ -354,7 +341,6 @@ target_include_directories(icsneocpp
${CMAKE_CURRENT_SOURCE_DIR}/include
${LIBICSNEO_EXTENSION_INCLUDE_PATHS}
)
target_link_libraries(icsneocpp PUBLIC Threads::Threads)
set_property(TARGET icsneocpp PROPERTY POSITION_INDEPENDENT_CODE ON)
target_compile_features(icsneocpp PUBLIC cxx_auto_type cxx_constexpr cxx_lambdas cxx_nullptr cxx_range_for cxx_rvalue_references cxx_sizeof_member cxx_strong_enums)
message("Loaded extensions: " ${LIBICSNEO_EXTENSION_TARGETS})
@@ -378,10 +364,18 @@ endif()
if(LIBICSNEO_ENABLE_TCP)
target_compile_definitions(icsneocpp PRIVATE ICSNEO_ENABLE_TCP)
if(WIN32)
target_link_libraries(icsneocpp PRIVATE ws2_32 iphlpapi)
target_link_libraries(icsneocpp PRIVATE ws2_32)
endif()
endif()
if(LIBICSNEO_ENABLE_ANDROIDUSB)
add_library(libusb SHARED IMPORTED)
set_target_properties(libusb PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/third-party/libusb/android/libs/${ANDROID_ABI}/libusb1.0.so)
target_include_directories(icsneocpp PRIVATE third-party/libusb/libusb)
target_compile_definitions(icsneocpp PRIVATE ICSNEO_ENABLE_ANDROIDUSB)
target_link_libraries(icsneocpp PRIVATE android log libusb)
endif()
# fatfs
add_subdirectory(third-party/fatfs)
set_property(TARGET fatfs PROPERTY POSITION_INDEPENDENT_CODE ON)
@@ -401,6 +395,7 @@ if(LIBICSNEO_ENABLE_FTDI)
add_subdirectory(third-party/libftdi)
target_include_directories(icsneocpp PRIVATE ${LIBUSB_INCLUDE_DIR})
find_package(Threads)
set_property(TARGET ftdi1-static PROPERTY POSITION_INDEPENDENT_CODE ON)
target_link_libraries(icsneocpp PUBLIC ftdi1-static)
target_link_libraries(icsneocpp PUBLIC ${CMAKE_THREAD_LIBS_INIT})
@@ -435,6 +430,11 @@ if(LIBICSNEO_BUILD_ICSNEOC)
)
target_link_libraries(icsneoc PRIVATE icsneocpp)
target_compile_features(icsneoc PRIVATE cxx_auto_type cxx_constexpr cxx_lambdas cxx_nullptr cxx_range_for cxx_rvalue_references cxx_sizeof_member cxx_strong_enums)
if(LIBICSNEO_ENABLE_ANDROIDUSB)
target_link_libraries(icsneoc PRIVATE android log)
target_include_directories(icsneoc PRIVATE third-party/libusb/libusb)
target_compile_definitions(icsneoc PRIVATE ICSNEO_ENABLE_ANDROIDUSB)
endif()
endif()
if(LIBICSNEO_BUILD_ICSNEOC_STATIC)
+1 -1
View File
@@ -1,4 +1,4 @@
Copyright 2018-2024 Intrepid Control Systems, Inc.
Copyright 2018-2023 Intrepid Control Systems, Inc.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+15 -19
View File
@@ -111,11 +111,15 @@ bool icsneo_isValidNeoDevice(const neodevice_t* device) {
}
bool icsneo_openDevice(const neodevice_t* device) {
if(!icsneo_isValidNeoDevice(device))
if(!icsneo_isValidNeoDevice(device)) {
//todo error
return false;
}
if(!device->device->open())
return false;
if(!device->device->open()) {
//todo error
return false;
}
// We connected successfully, move the device to connected devices
std::vector<std::vector<std::shared_ptr<Device>>::iterator> itemsToMove;
@@ -144,17 +148,8 @@ bool icsneo_closeDevice(const neodevice_t* device) {
if((*it).get() == device->device)
itemsToDelete.push_back(it);
}
for(auto it : itemsToDelete) {
// Move it back into connectable devices so we can open it again.
// Without this we will be unable to use/reopen the device due to
// icsneo_isValidNeoDevice / icsneo_openDevice checks against this
// container. Since its closed we are in a connectable state again.
// Notice: When we search again this will be cleaned up by
// icsneo_freeUnconnectedDevices()
connectableFoundDevices.push_back(*it);
// Remove it from the connected devices as we are no longer connected.
for(auto it : itemsToDelete)
connectedDevices.erase(it);
}
return true;
}
@@ -229,7 +224,6 @@ bool icsneo_getMessages(const neodevice_t* device, neomessage_t* messages, size_
return false;
*items = storage.size();
for(size_t i = 0; i < *items; i++) {
// For each message, copy into neomessage_t buffer given
messages[i] = CreateNeoMessage(storage[i]);
@@ -750,10 +744,12 @@ int icsneo_getDeviceStatus(const neodevice_t* device, void* status, size_t* size
return true;
}
#ifdef ICSNEO_ENABLE_ANDROIDUSB
bool icsneo_addSysFileDescriptor(int sysFd) {
return icsneo::ANDROIDUSB::addSystemFD(sysFd);
bool icsneo_isOnlineSupported(const neodevice_t* device) {
if(!icsneo_isValidNeoDevice(device))
return false;
return device->device->isOnlineSupported();
}
bool icsneo_removeSysFileDescriptor(int sysFd) {
return icsneo::ANDROIDUSB::removeSystemFD(sysFd);
}
#endif
+1 -1
View File
@@ -29,7 +29,7 @@ BEGIN
VALUE "FileDescription", "Intrepid Control Systems Open Device Communication C API"
VALUE "FileVersion", VER_FILEVERSION_STR
VALUE "InternalName", "icsneoc.dll"
VALUE "LegalCopyright", "Intrepid Control Systems, Inc. (C) 2018-2024"
VALUE "LegalCopyright", "Intrepid Control Systems, Inc. (C) 2018-2023"
VALUE "OriginalFilename", "icsneoc.dll"
VALUE "ProductName", "libicsneo"
VALUE "ProductVersion", VER_PRODUCTVERSION_STR
-34
View File
@@ -72,7 +72,6 @@ static constexpr const char* MESSAGE_MAX_LENGTH_EXCEEDED = "The message was too
static constexpr const char* VALUE_NOT_YET_PRESENT = "The value is not yet present.";
static constexpr const char* TIMEOUT = "The timeout was reached.";
static constexpr const char* WIVI_NOT_SUPPORTED = "Wireless neoVI functions are not supported on this device.";
static constexpr const char* RESTRICTED_ENTRY_FLAG = "Attempted to set a restricted flag in a Root Directory entry.";
// Device Errors
static constexpr const char* POLLING_MESSAGE_OVERFLOW = "Too many messages have been recieved for the polling message buffer, some have been lost!";
@@ -117,8 +116,6 @@ static constexpr const char* A2B_MESSAGE_INCOMPLETE_FRAME = "At least one of the
static constexpr const char* COREMINI_UPLOAD_VERSION_MISMATCH = "The version of the coremini engine on the device and the script uploaded are not the same.";
static constexpr const char* DISK_NOT_CONNECTED = "The program tried to access a disk that is not connected.";
static constexpr const char* UNEXPECTED_RESPONSE = "Received an unexpected or invalid response from the device.";
static constexpr const char* LIN_SETTINGS_NOT_AVAILABLE = "LIN settings are not available for this device.";
static constexpr const char* MODE_NOT_FOUND = "The mode was not found.";
// Transport Errors
static constexpr const char* FAILED_TO_READ = "A read operation failed.";
@@ -172,15 +169,6 @@ static constexpr const char* FT_DEVICE_NOT_CONNECTED = "FTD3XX device not connec
static constexpr const char* FT_INCORRECT_DEVICE_PATH = "Incorrect FTD3XX device path.";
static constexpr const char* FT_OTHER_ERROR = "Other FTD3XX error.";
// VSA
static constexpr const char* VSA_BUFFER_CORRUPTED = "VSA data in record buffer is corrupted.";
static constexpr const char* VSA_TIMESTAMP_NOT_FOUND = "Unable to find a VSA record with a valid timestamp.";
static constexpr const char* VSA_BUFFER_FORMAT_ERROR = "VSA record buffer is formatted incorrectly.";
static constexpr const char* VSA_MAX_READ_ATTEMPTS_REACHED = "Reached max attempts to read VSA records before exit.";
static constexpr const char* VSA_BYTE_PARSE_FAILURE = "Failure to parse record bytes from VSA buffer.";
static constexpr const char* VSA_EXTENDED_MESSAGE_ERROR = "Failure to parse extended message record sequence";
static constexpr const char* VSA_OTHER_ERROR = "Unknown error in VSA read API.";
static constexpr const char* TOO_MANY_EVENTS = "Too many events have occurred. The list has been truncated.";
static constexpr const char* UNKNOWN = "An unknown internal error occurred.";
static constexpr const char* INVALID = "An invalid internal error occurred.";
@@ -219,8 +207,6 @@ const char* APIEvent::DescriptionForType(Type type) {
return TIMEOUT;
case Type::WiVINotSupported:
return WIVI_NOT_SUPPORTED;
case Type::RestrictedEntryFlag:
return RESTRICTED_ENTRY_FLAG;
// Device Errors
case Type::PollingMessageOverflow:
@@ -307,10 +293,6 @@ const char* APIEvent::DescriptionForType(Type type) {
return DISK_NOT_CONNECTED;
case Type::UnexpectedResponse:
return UNEXPECTED_RESPONSE;
case Type::LINSettingsNotAvailable:
return LIN_SETTINGS_NOT_AVAILABLE;
case Type::ModeNotFound:
return MODE_NOT_FOUND;
// Transport Errors
case Type::FailedToRead:
return FAILED_TO_READ;
@@ -411,22 +393,6 @@ const char* APIEvent::DescriptionForType(Type type) {
case Type::FTOtherError:
return FT_OTHER_ERROR;
// VSA
case Type::VSABufferCorrupted:
return VSA_BUFFER_CORRUPTED;
case Type::VSATimestampNotFound:
return VSA_TIMESTAMP_NOT_FOUND;
case Type::VSABufferFormatError:
return VSA_BUFFER_FORMAT_ERROR;
case Type::VSAMaxReadAttemptsReached:
return VSA_MAX_READ_ATTEMPTS_REACHED;
case Type::VSAByteParseFailure:
return VSA_BYTE_PARSE_FAILURE;
case Type::VSAExtendedMessageError:
return VSA_EXTENDED_MESSAGE_ERROR;
case Type::VSAOtherError:
return VSA_OTHER_ERROR;
// Other Errors
case Type::TooManyEvents:
return TOO_MANY_EVENTS;
+2 -1
View File
@@ -1,5 +1,6 @@
#include "icsneo/icsneocpp.h"
#include "icsneo/device/devicefinder.h"
#include <jni.h>
using namespace icsneo;
@@ -45,4 +46,4 @@ void icsneo::SetEventLimit(size_t newLimit) {
size_t icsneo::GetEventLimit() {
return EventManager::GetInstance().getEventLimit();
}
}
@@ -3,6 +3,8 @@
#include <Tchar.h>
//Basic Functions
FINDNEODEVICES icsneoFindNeoDevices;
OPENNEODEVICE icsneoOpenNeoDevice;
OPENDEVICE icsneoOpenDevice;
CLOSEPORT icsneoClosePort;
FREEOBJECT icsneoFreeObject;
@@ -132,6 +134,10 @@ bool LoadDLLAPI(HINSTANCE &hAPIDLL)
if((hAPIDLL = LoadLibrary(_T("icsneo40.dll"))) == NULL)
return false;
icsneoFindNeoDevices = (FINDNEODEVICES) GetProcAddress(hAPIDLL, "icsneoFindNeoDevices");
icsneoOpenNeoDevice = (OPENNEODEVICE) GetProcAddress(hAPIDLL, "icsneoOpenNeoDevice");
icsneoOpenDevice = (OPENDEVICE) GetProcAddress(hAPIDLL, "icsneoOpenDevice");
icsneoClosePort = (CLOSEPORT) GetProcAddress(hAPIDLL, "icsneoClosePort");
icsneoFreeObject = (FREEOBJECT) GetProcAddress(hAPIDLL, "icsneoFreeObject");
@@ -200,7 +206,7 @@ bool LoadDLLAPI(HINSTANCE &hAPIDLL)
icsneoEnableDOIPLine = (ENABLEDOIPACTIVATIONLINE)GetProcAddress(hAPIDLL, "icsneoEnableDOIPLine");
if(!icsneoOpenDevice || !icsneoClosePort || !icsneoFreeObject ||
if(!icsneoFindNeoDevices || !icsneoOpenNeoDevice || !icsneoOpenDevice || !icsneoClosePort || !icsneoFreeObject ||
!icsneoTxMessages || !icsneoGetMessages || !icsneoWaitForRxMessagesWithTimeOut ||
!icsneoGetTimeStampForMsg || !icsneoEnableNetworkRXQueue || !icsneoGetISO15765Status || !icsneoTxMessagesEx ||
!icsneoSetISO15765RxParameters || !icsneoGetConfiguration || !icsneoSendConfiguration ||
@@ -114,6 +114,8 @@ typedef int (__stdcall *SCRIPTWRITEISO15765TXMESSAGE)(void * hObject, unsigned
//Basic Functions
extern FINDNEODEVICES icsneoFindNeoDevices;
extern OPENNEODEVICE icsneoOpenNeoDevice;
extern OPENDEVICE icsneoOpenDevice;
extern CLOSEPORT icsneoClosePort;
extern FREEOBJECT icsneoFreeObject;
+136 -107
View File
@@ -14,6 +14,7 @@
#include "icsneo/communication/network.h"
#include <map>
#include <algorithm>
#include <cstring>
#include <climits>
@@ -26,7 +27,6 @@ using namespace icsneo;
typedef uint64_t legacymaphandle_t;
static std::map<legacymaphandle_t, neodevice_t> neodevices;
static std::map<neodevice_t*, NeoDeviceEx*> openneodevices;
static const std::map<size_t, size_t> mp_netIDToVnetOffSet = {
{NETID_HSCAN, 1},
@@ -52,6 +52,18 @@ static const std::map<size_t, size_t> mp_HWnetIDToCMnetID = {
static unsigned long vnet_table[] = {0, PLASMA_SLAVE1_OFFSET, PLASMA_SLAVE2_OFFSET};
static NeoDevice OldNeoDeviceFromNew(const neodevice_t* newnd)
{
NeoDevice oldnd = {0};
oldnd.DeviceType = newnd->type;
oldnd.SerialNumber = icsneo_serialStringToNum(newnd->serial);
oldnd.NumberOfClients = 0;
oldnd.MaxAllowedClients = 1;
static_assert(sizeof(neodevice_handle_t) == sizeof(oldnd.Handle),
"neodevice_handle_t size must be sizeof(int) for compatibility reasons");
oldnd.Handle = newnd->handle;
return oldnd;
}
static bool NeoMessageToSpyMessage(const neodevice_t* device, const neomessage_t& newmsg, icsSpyMessage& oldmsg)
{
@@ -306,81 +318,109 @@ static inline size_t GetVnetAgnosticNetid(size_t fullNetid)
int LegacyDLLExport icsneoFindDevices(NeoDeviceEx* devs, int* devCount, unsigned int* devTypes, unsigned int devTypeCount,
POptionsFindNeoEx* POptionsFindNeoEx, unsigned int* zero)
{
// Match the legacy API maximum, this derives from the maximum COM Port on old windows versions.
constexpr int MAX_NEO_DEVICES = 255;
// Validate arguments
if (!devCount && *devCount < 0) {
if (!devs || !devCount)
return 0;
}
// return the size only if devs is NULL.
if (!devs)
if (*devCount < 0 || *devCount > 255)
return 0;
// Find the devices without filtering by the device type
// We allow this to find more than the requested number,
// as we may filter out some devices.
constexpr const size_t MAX_DEVICES = 255;
NeoDevice foundDevices[MAX_DEVICES];
int NumDevices = MAX_DEVICES;
int filteredDeviceCount = 0;
if (!icsneoFindNeoDevices(0, foundDevices, &NumDevices))
return 0;
for (auto i = 0; i < NumDevices; i++)
{
icsneo_findAllDevices(nullptr, (size_t*)devCount);
return 1;
}
// shrink the number of devices allowed to find
if (*devCount > MAX_NEO_DEVICES) {
*devCount = MAX_NEO_DEVICES;
}
// Find all the neodevice_t devices
std::vector<neodevice_t> neoDevices(*devCount);
auto neoDevicesSize = neoDevices.size();
icsneo_findAllDevices(neoDevices.data(), &neoDevicesSize);
neoDevices.resize(neoDevicesSize);
// Filter out the devices if needed
// No filtering needed
if (devTypes && devTypeCount > 0) {
neoDevices.erase(
std::remove_if(
neoDevices.begin(),
neoDevices.end(),
[&](const auto& iter) {
for (unsigned int i=0; i < devTypeCount; ++i) {
if (iter.type == devTypes[i]) {
return false;
}
}
return true;
// Check if the next device would overrun the user's buffer
// We check this up here since the documentation allows zero
// to be specified.
if (filteredDeviceCount >= *devCount)
break;
if (devTypes && devTypeCount)
{
for (unsigned int j = 0; j < devTypeCount; j++)
{
if (foundDevices[i].DeviceType == devTypes[j])
{
devs[filteredDeviceCount++].neoDevice = foundDevices[i];
break;
}
),
neoDevices.end()
);
}
// Create a NeoDeviceEx From a neodevice_t
auto _createNeoDeviceExFrom = [](const neodevice_t* neoDevice) -> NeoDeviceEx {
NeoDeviceEx nde = {};
nde.neoDevice.DeviceType = neoDevice->type;
nde.neoDevice.SerialNumber = icsneo_serialStringToNum(neoDevice->serial);
nde.neoDevice.NumberOfClients = 0;
nde.neoDevice.MaxAllowedClients = 1;
static_assert(sizeof(neodevice_handle_t) == sizeof(nde.neoDevice.Handle),
"neodevice_handle_t size must be sizeof(int) for compatibility reasons");
nde.neoDevice.Handle = neoDevice->handle;
return nde;
};
// Create the NeoDeviceEx from the neodevice_t
auto i = 0;
for (const auto& neoDevice : neoDevices) {
// Fill the look up table
neodevices[uint64_t(neoDevice.handle) << 32 | icsneo_serialStringToNum(neoDevice.serial)] = neoDevice;
// Create the NeoDeviceEx
devs[i] = _createNeoDeviceExFrom(&neoDevice);
NeoDeviceEx* nde = &devs[i];
++i;
// Lookup the open NeoDeviceEx devices and match the NumberOfClients value if available.
for (auto& [neo_device, open_nde]: openneodevices) {
// SerialNumber should always be unique so lets compare against that.
if (nde->neoDevice.SerialNumber == open_nde->neoDevice.SerialNumber) {
nde->neoDevice.NumberOfClients = open_nde->neoDevice.NumberOfClients;
}
}
else
{
devs[filteredDeviceCount++].neoDevice = foundDevices[i];
}
}
*devCount = (int)neoDevices.size();
*devCount = filteredDeviceCount;
return 1; // If the function succeeds but no devices are found 1 will still be returned and devCount will equal 0
}
int LegacyDLLExport icsneoFindNeoDevices(unsigned long DeviceTypes, NeoDevice* pNeoDevice, int* pNumDevices)
{
constexpr size_t MAX_DEVICES = 255;
size_t count = MAX_DEVICES;
if (pNumDevices == nullptr)
return 0;
if (pNeoDevice == nullptr)
{
icsneo_findAllDevices(nullptr, &count);
*pNumDevices = (int)count;
return 1;
}
size_t bufferSize = (size_t)*pNumDevices;
if (*pNumDevices < 0 || bufferSize > MAX_DEVICES)
return 0;
neodevice_t devices[MAX_DEVICES];
icsneo_findAllDevices(devices, &count);
if (bufferSize < count)
count = bufferSize;
*pNumDevices = (int)count;
for (size_t 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 LegacyDLLExport 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 (const std::out_of_range&)
{
return false;
}
*hObject = device;
if (!icsneo_openDevice(device))
return false;
return icsneo_setPollingMessageLimit(device, 20000) && icsneo_enableMessagePolling(device) && icsneo_goOnline(device);
}
int LegacyDLLExport icsneoOpenDevice(
NeoDeviceEx* pNeoDeviceEx,
void** hObject,
@@ -403,50 +443,19 @@ int LegacyDLLExport icsneoOpenDevice(
return false;
}
if (pNeoDeviceEx->neoDevice.NumberOfClients >= pNeoDeviceEx->neoDevice.MaxAllowedClients) {
return false;
}
*hObject = device;
if(!icsneo_openDevice(device)) {
if(!icsneo_openDevice(device))
return false;
}
if (icsneo_isOnlineSupported(device)) {
if (!icsneo_setPollingMessageLimit(device, 20000)) {
icsneo_closeDevice(device);
return false;
}
if (!icsneo_enableMessagePolling(device)) {
icsneo_closeDevice(device);
return false;
}
if (!icsneo_goOnline(device)) {
icsneo_closeDevice(device);
return false;
}
}
pNeoDeviceEx->neoDevice.NumberOfClients = 1;
// Add the open NeoDevice to the container so we can decrement NumberOfClients on close
openneodevices[device] = pNeoDeviceEx;
return true;
return icsneo_setPollingMessageLimit(device, 20000) && icsneo_enableMessagePolling(device) && icsneo_goOnline(device);
}
int LegacyDLLExport icsneoClosePort(void* hObject, int* pNumberOfErrors)
{
if (!icsneoValidateHObject(hObject))
return false;
if (pNumberOfErrors) {
*pNumberOfErrors = 0;
}
neodevice_t* device = reinterpret_cast<neodevice_t*>(hObject);
if (openneodevices.find(device) != openneodevices.end()) {
openneodevices[device]->neoDevice.NumberOfClients -= 1;
openneodevices.erase(device);
}
return icsneo_closeDevice(device);
}
@@ -982,7 +991,20 @@ int LegacyDLLExport icsneoScriptWriteAppSignal(void* hObject, unsigned int iInde
return false;
}
//Deprecated (but still suppored in the DLL)
int LegacyDLLExport icsneoOpenPortEx(void* lPortNumber, int lPortType, int lDriverType, int lIPAddressMSB,
int lIPAddressLSBOrBaudRate, int bConfigRead, unsigned char* bNetworkID, int* hObject)
{
// TODO Implement
return false;
}
int LegacyDLLExport icsneoOpenPort(int lPortNumber, int lPortType, int lDriverType, unsigned char *bNetworkID,
unsigned char* bSCPIDs, int* hObject)
{
// TODO Implement
return false;
}
int LegacyDLLExport icsneoEnableNetworkCom(void* hObject, int Enable)
{
@@ -996,6 +1018,19 @@ int LegacyDLLExport icsneoEnableNetworkCom(void* hObject, int Enable)
return icsneo_goOffline(device);
}
int LegacyDLLExport icsneoFindAllCOMDevices(int lDriverType, int lGetSerialNumbers, int lStopAtFirst, int lUSBCommOnly,
int* p_lDeviceTypes, int* p_lComPorts, int* p_lSerialNumbers, int* lNumDevices)
{
// TODO Implement
return false;
}
int LegacyDLLExport icsneoOpenNeoDeviceByChannels(NeoDevice* pNeoDevice, void** hObject, unsigned char* uChannels, int iSize,
int bConfigRead, int iOptions)
{
// TODO Implement
return false;
}
int LegacyDLLExport icsneoGetVCAN4Settings(void* hObject, SVCAN4Settings* pSettings, int iNumBytes)
{
@@ -1080,12 +1115,6 @@ int LegacyDLLExport icsneoGetDeviceSettingsType(void* hObject, EPlasmaIonVnetCha
case NEODEVICE_RED2:
*pDeviceSettingsType = DeviceRed2SettingsType;
break;
case NEODEVICE_FIRE3:
*pDeviceSettingsType = DeviceFire3SettingsType;
break;
case NEODEVICE_FIRE3_FLEXRAY:
*pDeviceSettingsType = DeviceFire3FlexraySettingsType;
break;
default:
return 0;
}
-1
View File
@@ -159,7 +159,6 @@ bool Decoder::decode(std::shared_ptr<Message>& result, const std::shared_ptr<Pac
A2BMessage& msg = *static_cast<A2BMessage*>(result.get());
msg.network = packet->network;
msg.timestamp *= timestampResolution;
return true;
}
case Network::Type::LIN: {
+7 -6
View File
@@ -4,18 +4,20 @@
namespace icsneo {
const size_t HardwareA2BPacket::a2bMessageMaxLength = sizeof(HardwareA2BPacket) + 1024;
const size_t HardwareA2BPacket::coreMiniMessageHeaderSize = 28;
const size_t HardwareA2BPacket::a2bMessageMaxLength = (size_t)HardwareA2BPacket::coreMiniMessageHeaderSize + 1024;
const size_t HardwareA2BPacket::a2bHeaderSize = 6;
std::shared_ptr<Message> HardwareA2BPacket::DecodeToMessage(const std::vector<uint8_t>& bytestream) {
if(bytestream.size() < sizeof(HardwareA2BPacket))
if(bytestream.size() < coreMiniMessageHeaderSize)
{
return nullptr;
}
const HardwareA2BPacket* data = (const HardwareA2BPacket*)bytestream.data();
const HardwareA2BPacket *data = (const HardwareA2BPacket*)bytestream.data();
size_t totalPackedLength = static_cast<size_t>(bytestream.size()) - sizeof(HardwareA2BPacket); // First 28 bytes are message header.
size_t totalPackedLength = static_cast<size_t>(bytestream.size()) - static_cast<size_t>(coreMiniMessageHeaderSize); // First 28 bytes are message header.
std::shared_ptr<A2BMessage> msg = std::make_shared<A2BMessage>(
(uint8_t)data->header.channelNum,
@@ -28,8 +30,7 @@ std::shared_ptr<Message> HardwareA2BPacket::DecodeToMessage(const std::vector<ui
msg->setErrIndicatorBit(data->header.errIndicator);
msg->setSyncFrameBit(data->header.syncFrame);
msg->setRFU2(data->header.rfu2);
msg->timestamp = data->timestamp.TS;
msg->setAudioBuffer(bytestream.begin() + sizeof(HardwareA2BPacket), bytestream.end());
msg->setAudioBuffer(bytestream.begin() + coreMiniMessageHeaderSize, bytestream.end());
return msg;
}
@@ -23,9 +23,6 @@ std::shared_ptr<SupportedFeaturesMessage> SupportedFeaturesPacket::DecodeToMessa
}
// Get a reference to the payload to fully validate the length
const auto& response = *reinterpret_cast<const SupportedFeaturesResponse*>(bytes.data());
if(response.cmdVersion != SupportedFeaturesCommandVersion) {
return msg;
}
// Expected size is the header, cmdVersion and numValidBits fields, plus the number of 32-bit bitfields in the response based on numValidBits
auto expectedSize = sizeof(ExtendedResponseMessage::ResponseHeader) + 4 + ((response.numValidBits + 31) / 32) * 4;
// If the response is malformed (too small), return an empty message
+48 -1199
View File
File diff suppressed because it is too large Load Diff
+10 -18
View File
@@ -15,6 +15,10 @@
#include "icsneo/platform/cdcacm.h"
#endif
#ifdef ICSNEO_ENABLE_ANDROIDUSB
#include "icsneo/platform/android/androidusb.h"
#endif
#ifdef ICSNEO_ENABLE_FTDI
#include "icsneo/platform/ftdi.h"
#endif
@@ -47,18 +51,6 @@ static void makeIfPIDMatches(const FoundDevice& dev, std::vector<std::shared_ptr
into.push_back(std::make_shared<T>(dev));
}
template<typename T>
static void makeIfSerialRangeMatches(const FoundDevice& dev, std::vector<std::shared_ptr<Device>>& into) {
// Relies on the subclass to have
// `static constexpr uint32_t SERIAL_RANGE_LOW = 0x12345678`
// `static constexpr uint32_t SERIAL_RANGE_HIGH = 0x12345678`
// and also a public constructor `T(const FoundDevice& dev)`
// Use macro ICSNEO_FINDABLE_DEVICE_BY_SERIAL_RANGE() to create these
uint32_t serialNum = Device::SerialStringToNum(dev.serial);
if(serialNum >= Device::SerialStringToNum(T::SERIAL_RANGE_LOW) && serialNum <= Device::SerialStringToNum(T::SERIAL_RANGE_HIGH))
into.push_back(std::make_shared<T>(dev));
}
std::vector<std::shared_ptr<Device>> DeviceFinder::FindAll() {
static std::vector<FoundDevice> newDriverFoundDevices;
newDriverFoundDevices.clear();
@@ -77,6 +69,10 @@ std::vector<std::shared_ptr<Device>> DeviceFinder::FindAll() {
#ifdef ICSNEO_ENABLE_CDCACM
CDCACM::Find(newDriverFoundDevices);
#endif
#ifdef ICSNEO_ENABLE_ANDROIDUSB
ANDROIDUSB::Find(newDriverFoundDevices);
#endif
#ifdef ICSNEO_ENABLE_FTDI
@@ -170,11 +166,7 @@ std::vector<std::shared_ptr<Device>> DeviceFinder::FindAll() {
#endif
#ifdef __RADCOMET_H_
makeIfSerialRangeMatches<RADComet>(dev, newFoundDevices);
#endif
#ifdef __RADCOMET2_H_
makeIfSerialRangeMatches<RADComet2>(dev, newFoundDevices);
makeIfSerialMatches<RADCOMET>(dev, newFoundDevices);
#endif
#ifdef __RADEPSILON_H_
@@ -313,7 +305,7 @@ const std::vector<DeviceType>& DeviceFinder::GetSupportedDevices() {
#endif
#ifdef __RADCOMET_H_
RADComet::DEVICE_TYPE,
RADCOMET::DEVICE_TYPE,
#endif
#ifdef __RADEPSILON_H_
-235
View File
@@ -128,37 +128,6 @@ int64_t IDeviceSettings::GetBaudrateValueForEnum(CANBaudrate enumValue) {
}
}
bool IDeviceSettings::ValidateLINBaudrate(int64_t baudrate) {
switch(baudrate) {
case 4800:
// fallthrough
case 9600:
// fallthrough
case 10400:
// fallthrough
case 10417:
// fallthrough
case 10504:
// fallthrough
case 10593:
// fallthrough
case 10684:
// fallthrough
case 10776:
// fallthrough
case 10870:
// fallthrough
case 10965:
// fallthrough
case 11062:
// fallthrough
case 19200:
return true;
default:
return false;
}
}
bool IDeviceSettings::refresh(bool ignoreChecksum) {
if(disabled) {
report(APIEvent::Type::SettingsNotAvailable, APIEvent::Severity::Error);
@@ -445,15 +414,6 @@ int64_t IDeviceSettings::getBaudrateFor(Network net) const {
}
return baudrate;
}
case Network::Type::LIN: {
const LIN_SETTINGS* cfg = getLINSettingsFor(net);
if(cfg == nullptr) {
report(APIEvent::Type::LINSettingsNotAvailable, APIEvent::Severity::Error);
return -1;
}
return cfg->Baudrate;
}
default:
report(APIEvent::Type::UnexpectedNetworkType, APIEvent::Severity::Error);
return -1;
@@ -533,21 +493,6 @@ bool IDeviceSettings::setBaudrateFor(Network net, int64_t baudrate) {
cfg->SetBaudrate = AUTO; // Device will use the baudrate value to set the TQ values
return true;
}
case Network::Type::LIN: {
LIN_SETTINGS* cfg = getMutableLINSettingsFor(net);
if(cfg == nullptr) {
report(APIEvent::Type::LINSettingsNotAvailable, APIEvent::Severity::Error);
return false;
}
bool valid = ValidateLINBaudrate(baudrate);
if(!valid) {
report(APIEvent::Type::BaudrateNotFound, APIEvent::Severity::Error);
return false;
}
cfg->Baudrate = (uint32_t)baudrate;
return true;
}
default:
report(APIEvent::Type::UnexpectedNetworkType, APIEvent::Severity::Error);
return false;
@@ -759,186 +704,6 @@ bool IDeviceSettings::setTerminationFor(Network net, bool enabled) {
return true;
}
std::optional<bool> IDeviceSettings::isCommanderResistorEnabledFor(Network net) const {
if(!settingsLoaded) {
report(APIEvent::Type::SettingsReadError, APIEvent::Severity::Error);
return std::nullopt;
}
if(disabled) {
report(APIEvent::Type::SettingsNotAvailable, APIEvent::Severity::Error);
return std::nullopt;
}
switch(net.getType()) {
case Network::Type::LIN: {
const LIN_SETTINGS* cfg = getLINSettingsFor(net);
if(cfg == nullptr) {
report(APIEvent::Type::LINSettingsNotAvailable, APIEvent::Severity::Error);
return std::nullopt;
}
return (cfg->CommanderResistor != RESISTOR_OFF);
}
default:
report(APIEvent::Type::UnexpectedNetworkType, APIEvent::Severity::Error);
return std::nullopt;
}
}
bool IDeviceSettings::setCommanderResistorFor(Network net, bool resistor_on) {
if(disabled) {
report(APIEvent::Type::SettingsNotAvailable, APIEvent::Severity::Error);
return false;
}
if(!settingsLoaded) {
report(APIEvent::Type::SettingsReadError, APIEvent::Severity::Error);
return false;
}
if(readonly) {
report(APIEvent::Type::SettingsReadOnly, APIEvent::Severity::Error);
return false;
}
switch(net.getType()) {
case Network::Type::LIN: {
LIN_SETTINGS* cfg = getMutableLINSettingsFor(net);
if(cfg == nullptr) {
report(APIEvent::Type::LINSettingsNotAvailable, APIEvent::Severity::Error);
return false;
}
cfg->CommanderResistor = resistor_on ? RESISTOR_ON : RESISTOR_OFF;
return true;
}
default:
report(APIEvent::Type::UnexpectedNetworkType, APIEvent::Severity::Error);
return false;
}
}
std::optional<LINMode> IDeviceSettings::getLINModeFor(Network net) const {
if(!settingsLoaded) {
report(APIEvent::Type::SettingsReadError, APIEvent::Severity::Error);
return std::nullopt;
}
if(disabled) {
report(APIEvent::Type::SettingsNotAvailable, APIEvent::Severity::Error);
return std::nullopt;
}
switch(net.getType()) {
case Network::Type::LIN: {
const LIN_SETTINGS* cfg = getLINSettingsFor(net);
if(cfg == nullptr) {
report(APIEvent::Type::LINSettingsNotAvailable, APIEvent::Severity::Error);
return std::nullopt;
}
return static_cast<LINMode>(cfg->Mode);
}
default:
report(APIEvent::Type::UnexpectedNetworkType, APIEvent::Severity::Error);
return std::nullopt;
}
}
bool IDeviceSettings::setLINModeFor(Network net, LINMode mode) {
if(disabled) {
report(APIEvent::Type::SettingsNotAvailable, APIEvent::Severity::Error);
return false;
}
if(!settingsLoaded) {
report(APIEvent::Type::SettingsReadError, APIEvent::Severity::Error);
return false;
}
if(readonly) {
report(APIEvent::Type::SettingsReadOnly, APIEvent::Severity::Error);
return false;
}
switch(net.getType()) {
case Network::Type::LIN: {
LIN_SETTINGS* cfg = getMutableLINSettingsFor(net);
if(cfg == nullptr) {
report(APIEvent::Type::LINSettingsNotAvailable, APIEvent::Severity::Error);
return false;
}
cfg->Mode = static_cast<uint8_t>(mode);
return true;
}
default:
report(APIEvent::Type::UnexpectedNetworkType, APIEvent::Severity::Error);
return false;
}
}
std::optional<uint8_t> IDeviceSettings::getLINCommanderResponseTimeFor(Network net) const {
if(!settingsLoaded) {
report(APIEvent::Type::SettingsReadError, APIEvent::Severity::Error);
return std::nullopt;
}
if(disabled) {
report(APIEvent::Type::SettingsNotAvailable, APIEvent::Severity::Error);
return std::nullopt;
}
switch(net.getType()) {
case Network::Type::LIN: {
const LIN_SETTINGS* cfg = getLINSettingsFor(net);
if(cfg == nullptr) {
report(APIEvent::Type::LINSettingsNotAvailable, APIEvent::Severity::Error);
return std::nullopt;
}
return cfg->numBitsDelay;
}
default:
report(APIEvent::Type::UnexpectedNetworkType, APIEvent::Severity::Error);
return std::nullopt;
}
}
bool IDeviceSettings::setLINCommanderResponseTimeFor(Network net, uint8_t bits) {
if(disabled) {
report(APIEvent::Type::SettingsNotAvailable, APIEvent::Severity::Error);
return false;
}
if(!settingsLoaded) {
report(APIEvent::Type::SettingsReadError, APIEvent::Severity::Error);
return false;
}
if(readonly) {
report(APIEvent::Type::SettingsReadOnly, APIEvent::Severity::Error);
return false;
}
switch(net.getType()) {
case Network::Type::LIN: {
LIN_SETTINGS* cfg = getMutableLINSettingsFor(net);
if(cfg == nullptr) {
report(APIEvent::Type::LINSettingsNotAvailable, APIEvent::Severity::Error);
return false;
}
cfg->numBitsDelay = bits;
return true;
}
default:
report(APIEvent::Type::UnexpectedNetworkType, APIEvent::Severity::Error);
return false;
}
}
template<typename T> bool IDeviceSettings::applyStructure(const T& newStructure) {
if(!settingsLoaded) {
report(APIEvent::Type::SettingsReadError, APIEvent::Severity::Error);
+8 -12
View File
@@ -18,20 +18,18 @@ std::optional<uint64_t> NeoMemoryDiskDriver::readLogicalDiskAligned(Communicatio
const uint64_t currentSector = pos / SectorSize;
const uint8_t memLocation = (uint8_t)memType;
uint64_t numWords = amount / 2;
auto msg = com.waitForMessageSync([&currentSector, &memLocation, &com, &numWords] {
auto msg = com.waitForMessageSync([&currentSector, &memLocation, &com] {
return com.sendCommand(Command::NeoReadMemory, {
memLocation,
uint8_t(currentSector & 0xFF),
uint8_t((currentSector >> 8) & 0xFF),
uint8_t((currentSector >> 16) & 0xFF),
uint8_t((currentSector >> 24) & 0xFF),
uint8_t(numWords & 0xFF),
uint8_t((numWords >> 8) & 0xFF),
uint8_t((numWords >> 16) & 0xFF),
uint8_t((numWords >> 24) & 0xFF)
uint8_t(SectorSize & 0xFF),
uint8_t((SectorSize >> 8) & 0xFF),
uint8_t((SectorSize >> 16) & 0xFF),
uint8_t((SectorSize >> 24) & 0xFF)
});
}, NeoMemorySDRead, timeout);
@@ -62,17 +60,15 @@ std::optional<uint64_t> NeoMemoryDiskDriver::writeLogicalDiskAligned(Communicati
const uint64_t currentSector = pos / SectorSize;
const uint8_t memLocation = (uint8_t)memType;
uint64_t numWords = amount / 2;
auto msg = com.waitForMessageSync([&currentSector, &memLocation, &com, from, amount, &numWords] {
auto msg = com.waitForMessageSync([&currentSector, &memLocation, &com, from, amount] {
std::vector<uint8_t> command = {
memLocation,
uint8_t(currentSector & 0xFF),
uint8_t((currentSector >> 8) & 0xFF),
uint8_t((currentSector >> 16) & 0xFF),
uint8_t((currentSector >> 24) & 0xFF),
uint8_t(numWords & 0xFF),
uint8_t((numWords >> 8) & 0xFF),
uint8_t(SectorSize & 0xFF),
uint8_t((SectorSize >> 8) & 0xFF),
};
command.insert(command.end(), from, from + amount);
return com.sendCommand(Command::NeoWriteMemory, command);
-43
View File
@@ -1,43 +0,0 @@
#include "icsneo/disk/vsa/vsa.h"
#include "icsneo/communication/packet/ethernetpacket.h"
#include <iostream>
using namespace icsneo;
// VSA Base Class Functions
// VSAMessage Class Functions
std::shared_ptr<Packet> VSAMessage::getPacket() const
{
auto packet = std::make_shared<Packet>();
packet->network = network;
reservePacketData(packet);
packet->data.insert(packet->data.end(), payload.begin(), payload.end());
return packet;
}
// VSAExtendedMessage Class Functions
void VSAExtendedMessage::appendPacket(std::shared_ptr<Packet> packet) const
{
packet->data.insert(packet->data.end(), payload.begin(), payload.end());
// Set the network if not already set (Happens in AA0F records)
if(packet->network.getNetID() == Network::NetID::Invalid) {
packet->network = network;
}
}
void VSAExtendedMessage::truncatePacket(std::shared_ptr<Packet> packet)
{
static constexpr auto EthernetLengthOffset = 26u;
switch(packet->network.getType()) {
case Network::Type::Ethernet:
{
const auto& packetLength = *reinterpret_cast<uint16_t*>(packet->data.data() + EthernetLengthOffset);
const size_t ethernetFrameSize = packetLength - (sizeof(uint16_t) * 2);
const size_t bytestreamExpectedSize = sizeof(HardwareEthernetPacket) + ethernetFrameSize;
packet->data.resize(bytestreamExpectedSize);
}
break;
}
}
-26
View File
@@ -1,26 +0,0 @@
#include "icsneo/disk/vsa/vsa02.h"
using namespace icsneo;
VSA02::VSA02(uint8_t* const recordBytes)
: VSA()
{
setType(VSA::Type::AA02);
constantIndex = *reinterpret_cast<uint16_t*>(recordBytes + 2);
flags = *reinterpret_cast<Flags*>(recordBytes + 4);
pieceCount = recordBytes[5];
timestamp = *reinterpret_cast<uint64_t*>(recordBytes + 6) & UINT63_MAX;
samples.insert(samples.end(), recordBytes + 14, recordBytes + 30);
checksum = *reinterpret_cast<uint16_t*>(recordBytes + 30);
doChecksum(recordBytes);
}
void VSA02::doChecksum(uint8_t* recordBytes)
{
uint16_t* words = reinterpret_cast<uint16_t*>(recordBytes);
uint16_t sum = 0;
for(size_t i = 0; i < 15; i++) {
sum += words[i];
}
setChecksumFailed(sum != checksum);
}
-24
View File
@@ -1,24 +0,0 @@
#include "icsneo/disk/vsa/vsa03.h"
using namespace icsneo;
VSA03::VSA03(uint8_t* const recordBytes)
: VSA()
{
setType(VSA::Type::AA03);
eventType = static_cast<EventType>(*reinterpret_cast<uint16_t*>(recordBytes + 2));
eventData = *reinterpret_cast<uint16_t*>(recordBytes + 4);
timestamp = *reinterpret_cast<uint64_t*>(recordBytes + 6) & UINT63_MAX;
checksum = *reinterpret_cast<uint16_t*>(recordBytes + 14);
doChecksum(recordBytes);
}
void VSA03::doChecksum(uint8_t* recordBytes)
{
uint16_t* words = reinterpret_cast<uint16_t*>(recordBytes);
uint16_t sum = 0;
for(size_t i = 0; i < 7; i++) {
sum += words[i];
}
setChecksumFailed(sum != checksum);
}
-24
View File
@@ -1,24 +0,0 @@
#include "icsneo/disk/vsa/vsa04.h"
using namespace icsneo;
VSA04::VSA04(uint8_t* const recordBytes)
: VSA()
{
setType(VSA::Type::AA04);
flags = *reinterpret_cast<Flags*>(recordBytes + 2);
partitionIndex = *reinterpret_cast<uint16_t*>(recordBytes + 4);
timestamp = *reinterpret_cast<uint64_t*>(recordBytes + 6) & UINT63_MAX;
checksum = *reinterpret_cast<uint16_t*>(recordBytes + 14);
doChecksum(recordBytes);
}
void VSA04::doChecksum(uint8_t* recordBytes)
{
uint16_t* words = reinterpret_cast<uint16_t*>(recordBytes);
uint16_t sum = 0;
for(size_t i = 0; i < 7; i++) {
sum += words[i];
}
setChecksumFailed(sum != checksum);
}
-23
View File
@@ -1,23 +0,0 @@
#include "icsneo/disk/vsa/vsa05.h"
using namespace icsneo;
VSA05::VSA05(uint8_t* const recordBytes)
: VSA()
{
setType(VSA::Type::AA05);
errorType = static_cast<ErrorType>(*reinterpret_cast<uint16_t*>(recordBytes + 2));
errorNetwork = *reinterpret_cast<uint16_t*>(recordBytes + 4);
timestamp = *reinterpret_cast<uint64_t*>(recordBytes + 6) & UINT63_MAX;
checksum = *reinterpret_cast<uint16_t*>(recordBytes + 14);
}
void VSA05::doChecksum(uint8_t* recordBytes)
{
uint16_t* words = reinterpret_cast<uint16_t*>(recordBytes);
uint16_t sum = 0;
for(size_t i = 0; i < 7; i++) {
sum += words[i];
}
setChecksumFailed(sum != checksum);
}
-25
View File
@@ -1,25 +0,0 @@
#include "icsneo/disk/vsa/vsa06.h"
using namespace icsneo;
VSA06::VSA06(uint8_t* const recordBytes)
: VSA()
{
setType(VSA::Type::AA06);
savedSectors.insert(savedSectors.end(), reinterpret_cast<uint32_t*>(recordBytes + 2), reinterpret_cast<uint32_t*>(recordBytes + 18));
error = *reinterpret_cast<uint16_t*>(recordBytes + 18);
savedSectorsHigh = *reinterpret_cast<uint16_t*>(recordBytes + 20);
timestamp = *reinterpret_cast<uint64_t*>(recordBytes + 22) & UINT63_MAX;
checksum = *reinterpret_cast<uint16_t*>(recordBytes + 30);
doChecksum(recordBytes);
}
void VSA06::doChecksum(uint8_t* recordBytes)
{
uint16_t* words = reinterpret_cast<uint16_t*>(recordBytes);
uint16_t sum = 0;
for(size_t i = 0; i < 15; i++) {
sum += words[i];
}
setChecksumFailed(sum != checksum);
}
-25
View File
@@ -1,25 +0,0 @@
#include "icsneo/disk/vsa/vsa07.h"
using namespace icsneo;
VSA07::VSA07(uint8_t* const recordBytes)
: VSA()
{
setType(VSA::Type::AA07);
lastSector = *reinterpret_cast<uint32_t*>(recordBytes + 2);
currentSector = *reinterpret_cast<uint32_t*>(recordBytes + 6);
reserved.insert(reserved.end(), recordBytes + 10, recordBytes + 22);
timestamp = *reinterpret_cast<uint64_t*>(recordBytes + 22) & UINT63_MAX;
checksum = *reinterpret_cast<uint16_t*>(recordBytes + 30);
doChecksum(recordBytes);
}
void VSA07::doChecksum(uint8_t* recordBytes)
{
uint16_t* words = reinterpret_cast<uint16_t*>(recordBytes);
uint16_t sum = 0;
for(size_t i = 0; i < 15; i++) {
sum += words[i];
}
setChecksumFailed(sum != checksum);
}
-24
View File
@@ -1,24 +0,0 @@
#include "icsneo/disk/vsa/vsa08.h"
using namespace icsneo;
VSA08::VSA08(uint8_t* const recordBytes)
: VSA()
{
setType(VSA::Type::AA08);
troubleSramCount.insert(troubleSramCount.end(), recordBytes + 2, recordBytes + 6);
troubleSectors.insert(troubleSectors.end(), reinterpret_cast<uint32_t*>(recordBytes + 6), reinterpret_cast<uint32_t*>(recordBytes + 20));
timestamp = *reinterpret_cast<uint64_t*>(recordBytes + 22) & UINT63_MAX;
checksum = *reinterpret_cast<uint16_t*>(recordBytes + 30);
doChecksum(recordBytes);
}
void VSA08::doChecksum(uint8_t* recordBytes)
{
uint16_t* words = reinterpret_cast<uint16_t*>(recordBytes);
uint16_t sum = 0;
for(size_t i = 0; i < 15; i++) {
sum += words[i];
}
setChecksumFailed(sum != checksum);
}
-32
View File
@@ -1,32 +0,0 @@
#include "icsneo/disk/vsa/vsa09.h"
using namespace icsneo;
VSA09::VSA09(uint8_t* const recordBytes)
: VSA()
{
setType(VSA::Type::AA09);
serialNumber = *reinterpret_cast<uint32_t*>(recordBytes + 2);
firmwareMajorVersion = recordBytes[6];
firmwareMinorVersion = recordBytes[7];
manufactureMajorRevision = recordBytes[8];
manufactureMinorRevision = recordBytes[9];
bootloaderMajorVersion = recordBytes[10];
bootloaderMinorVersion = recordBytes[11];
reserved0.insert(reserved0.end(), recordBytes + 12, recordBytes + 18);
hardwareID = static_cast<HardwareID>(recordBytes[18]);
reserved1.insert(reserved1.end(), recordBytes + 19, recordBytes + 22);
timestamp = *reinterpret_cast<uint64_t*>(recordBytes + 22) & UINT63_MAX;
checksum = *reinterpret_cast<uint16_t*>(recordBytes + 30);
doChecksum(recordBytes);
}
void VSA09::doChecksum(uint8_t* recordBytes)
{
uint16_t* words = reinterpret_cast<uint16_t*>(recordBytes);
uint16_t sum = 0;
for(size_t i = 0; i < 15; i++) {
sum += words[i];
}
setChecksumFailed(sum != checksum);
}
-38
View File
@@ -1,38 +0,0 @@
#include "icsneo/disk/vsa/vsa0b.h"
#include <algorithm>
using namespace icsneo;
static constexpr auto PayloadOffset = 4;
VSA0B::VSA0B(uint8_t* const recordBytes)
: VSAMessage(recordBytes + PayloadOffset, CoreMiniPayloadSize, static_cast<Network::CoreMini>(recordBytes[29]))
{
setType(VSA::Type::AA0B);
captureBitfield = reinterpret_cast<uint16_t*>(recordBytes)[1];
timestamp = *reinterpret_cast<uint64_t*>(recordBytes + 20) & UINT63_MAX;
reserved = recordBytes[28];
checksum = reinterpret_cast<uint16_t*>(recordBytes)[15];
doChecksum(recordBytes);
}
void VSA0B::doChecksum(uint8_t* recordBytes)
{
uint16_t* words = reinterpret_cast<uint16_t*>(recordBytes);
uint16_t sum = 0;
for(size_t i = 0; i < 15; i++) {
sum += words[i];
}
setChecksumFailed(sum != checksum);
}
bool VSA0B::filter(const std::shared_ptr<VSAMessageReadFilter> filter)
{
if((filter->captureBitfield != captureBitfield && filter->captureBitfield != UINT16_MAX) ||
getICSTimestampFromTimepoint(filter->readRange.first) > timestamp ||
getICSTimestampFromTimepoint(filter->readRange.second) < timestamp) {
return false;
}
return true;
}
-27
View File
@@ -1,27 +0,0 @@
#include "icsneo/disk/vsa/vsa0c.h"
using namespace icsneo;
VSA0C::VSA0C(uint8_t* const recordBytes)
: VSA()
{
setType(VSA::Type::AA0C);
captureBitfield = *reinterpret_cast<uint16_t*>(recordBytes + 2);
audioPreamble = recordBytes[4];
audioHeader = recordBytes[5];
pcmData.insert(pcmData.end(), recordBytes + 6, recordBytes + 20);
timestamp = *reinterpret_cast<uint64_t*>(recordBytes + 20) & UINT63_MAX;
vNetBitfield = *reinterpret_cast<VSA0C::VNet*>(recordBytes + 28);
checksum = *reinterpret_cast<uint16_t*>(recordBytes + 30);
doChecksum(recordBytes);
}
void VSA0C::doChecksum(uint8_t* recordBytes)
{
uint16_t* words = reinterpret_cast<uint16_t*>(recordBytes);
uint16_t sum = 0;
for(size_t i = 0; i < 15; i++) {
sum += words[i];
}
setChecksumFailed(sum != checksum);
}
-107
View File
@@ -1,107 +0,0 @@
#include "icsneo/disk/vsa/vsa0d.h"
#include <algorithm>
using namespace icsneo;
static constexpr auto FirstPayloadOffset = 8;
static constexpr auto FirstPayloadSize = 12;
static constexpr auto ConsecutivePayloadOffset = 4;
static constexpr auto LastPayloadSize = 24;
static constexpr auto OtherPayloadSize = 28;
// Parent class functions
VSA0D::VSA0D(uint8_t* const recordBytes, uint8_t* const messageBytes, size_t numBytes, uint32_t& runningChecksum, Network::CoreMini networkId)
: VSAExtendedMessage(messageBytes, numBytes, networkId)
{
static constexpr auto DWordSize = 4;
setType(VSA::Type::AA0D);
setIndex(*reinterpret_cast<uint16_t*>(recordBytes + 2) & 0x01FFu);
setSequenceNum((*reinterpret_cast<uint16_t*>(recordBytes + 2) & 0xFE00u) >> 9);
uint32_t* dwords = reinterpret_cast<uint32_t*>(payload.data());
for(size_t i = 0; i < payload.size() / DWordSize; i++) {
runningChecksum += dwords[i];
}
}
// First Record Functions
VSA0DFirst::VSA0DFirst(uint8_t* const recordBytes, uint32_t& runningChecksum)
: VSA0D(recordBytes, recordBytes + FirstPayloadOffset, FirstPayloadSize, runningChecksum, static_cast<Network::CoreMini>(recordBytes[29]))
{
captureBitfield = *reinterpret_cast<uint16_t*>(recordBytes + 4);
setRecordCount(*reinterpret_cast<uint16_t*>(recordBytes + 6));
timestamp = *reinterpret_cast<uint64_t*>(recordBytes + 20) & UINT63_MAX;
vNetInfo = *reinterpret_cast<VNet*>(recordBytes + 28);
checksum = *reinterpret_cast<uint16_t*>(recordBytes + 30);
doChecksum(recordBytes);
uint32_t* const timestampDWords = reinterpret_cast<uint32_t*>(timestamp);
runningChecksum += timestampDWords[0];
runningChecksum += timestampDWords[1];
}
void VSA0DFirst::doChecksum(uint8_t* recordBytes)
{
uint16_t* words = reinterpret_cast<uint16_t*>(recordBytes);
uint16_t sum = 0;
for(size_t i = 0; i < 15; i++) {
sum += words[i];
}
setChecksumFailed(sum != checksum);
}
void VSA0DFirst::reservePacketData(std::shared_ptr<Packet>& packet) const
{
uint32_t numMessageBytes = (getRecordCount() - 2) * OtherPayloadSize + FirstPayloadSize + LastPayloadSize;
packet->data.reserve(numMessageBytes);
}
void VSA0DFirst::reorderPayload(std::vector<uint8_t>& secondPayload)
{
std::vector<uint8_t> tempPayload;
tempPayload.insert(tempPayload.end(), secondPayload.begin(), secondPayload.begin() + 4);
uint8_t* timestampBytes = reinterpret_cast<uint8_t*>(&timestamp);
if(timestampIsExtended) {
timestampBytes[7] += 0x80;
}
tempPayload.insert(tempPayload.end(), timestampBytes, timestampBytes + 8);
tempPayload.insert(tempPayload.end(), secondPayload.begin() + 4, secondPayload.end());
payload.clear();
secondPayload.clear();
payload.insert(payload.end(), tempPayload.begin(), tempPayload.begin() + 12); // This is done because the capacity of payload is already 12
secondPayload.insert(secondPayload.end(), tempPayload.begin() + 12, tempPayload.end());
}
bool VSA0DFirst::filter(const std::shared_ptr<VSAMessageReadFilter> filter)
{
if((filter->captureBitfield != captureBitfield && filter->captureBitfield != UINT16_MAX) ||
getICSTimestampFromTimepoint(filter->readRange.first) > timestamp ||
getICSTimestampFromTimepoint(filter->readRange.second) < timestamp) {
return false;
}
return true;
}
// Consecutive Record Functions
VSA0DConsecutive::VSA0DConsecutive(uint8_t* const recordBytes, uint32_t& runningChecksum, std::shared_ptr<VSA0DFirst> first, bool isLastRecord)
: VSA0D(recordBytes, recordBytes + ConsecutivePayloadOffset, isLastRecord ? LastPayloadSize : OtherPayloadSize, runningChecksum)
{
this->first = first;
calculatedChecksum = runningChecksum;
if(getIndex() == 1) {
first->reorderPayload(payload);
} else if(isLastRecord) {
recordChecksum = *reinterpret_cast<uint32_t*>(recordBytes + 28);
doChecksum(recordBytes);
} else {
setChecksumFailed(first->getChecksumFailed());
}
setRecordCount(first->getRecordCount());
}
void VSA0DConsecutive::doChecksum(uint8_t* recordBytes)
{
setChecksumFailed(recordBytes && calculatedChecksum != recordChecksum);
}
-114
View File
@@ -1,114 +0,0 @@
#include "icsneo/disk/vsa/vsa0e.h"
#include <algorithm>
using namespace icsneo;
static constexpr auto FirstPayloadOffset = 10;
static constexpr auto FirstPayloadSize = 10;
static constexpr auto ConsecutivePayloadOffset = 4;
static constexpr auto LastPayloadSize = 24;
static constexpr auto OtherPayloadSize = 28;
// Parent class functions
VSA0E::VSA0E(uint8_t* const recordBytes, uint8_t* const messageBytes, size_t numBytes, uint32_t& runningChecksum, Network::CoreMini networkId)
: VSAExtendedMessage(messageBytes, numBytes, networkId)
{
static constexpr auto DWordSize = 4;
setType(VSA::Type::AA0E);
setIndex(static_cast<uint16_t>(recordBytes[2]));
setSequenceNum(static_cast<uint16_t>(recordBytes[3]));
if(getIndex() == 0) {
runningChecksum = (static_cast<uint32_t>(payload[0]) << 16) | (static_cast<uint32_t>(payload[1]) << 24);
uint32_t* dwords = reinterpret_cast<uint32_t*>(payload.data() + 2);
for(size_t i = 0; i < (payload.size() - 2) / DWordSize; i++) {
runningChecksum += dwords[i];
}
} else {
uint32_t* dwords = reinterpret_cast<uint32_t*>(payload.data());
for(size_t i = 0; i < payload.size() / DWordSize; i++) {
runningChecksum += dwords[i];
}
}
}
// First Record Functions
VSA0EFirst::VSA0EFirst(uint8_t* const recordBytes, uint32_t& runningChecksum)
: VSA0E(recordBytes, recordBytes + FirstPayloadOffset, FirstPayloadSize, runningChecksum,
static_cast<Network::CoreMini>(*reinterpret_cast<uint16_t*>(recordBytes + 28)))
{
captureBitfield = *reinterpret_cast<uint16_t*>(recordBytes + 4);
setRecordCount(*reinterpret_cast<uint32_t*>(recordBytes + 6));
timestamp = *reinterpret_cast<uint64_t*>(recordBytes + 20) & UINT63_MAX;
timestampIsExtended = (bool)(*reinterpret_cast<uint64_t*>(recordBytes + 20) & (0x8000000000000000));
checksum = *reinterpret_cast<uint16_t*>(recordBytes + 30);
doChecksum(recordBytes);
}
void VSA0EFirst::doChecksum(uint8_t* recordBytes)
{
uint16_t* words = reinterpret_cast<uint16_t*>(recordBytes);
uint16_t sum = 0;
for(size_t i = 0; i < 15; i++) {
sum += words[i];
}
setChecksumFailed(sum != checksum);
}
void VSA0EFirst::reservePacketData(std::shared_ptr<Packet>& packet) const
{
uint32_t numMessageBytes = (getRecordCount() - 2) * OtherPayloadSize + FirstPayloadSize + LastPayloadSize;
packet->data.reserve(numMessageBytes);
}
bool VSA0EFirst::filter(const std::shared_ptr<VSAMessageReadFilter> filter)
{
if((filter->captureBitfield != captureBitfield && filter->captureBitfield != UINT16_MAX) ||
getICSTimestampFromTimepoint(filter->readRange.first) > timestamp ||
getICSTimestampFromTimepoint(filter->readRange.second) < timestamp) {
return false;
}
return true;
}
void VSA0EFirst::reorderPayload(std::vector<uint8_t>& secondPayload)
{
std::vector<uint8_t> tempPayload;
tempPayload.insert(tempPayload.end(), payload.begin(), payload.end());
tempPayload.insert(tempPayload.end(), secondPayload.begin(), secondPayload.begin() + 6);
uint8_t* timestampBytes = reinterpret_cast<uint8_t*>(&timestamp);
if(timestampIsExtended) {
timestampBytes[7] += 0x80;
}
tempPayload.insert(tempPayload.end(), timestampBytes, timestampBytes + 8);
tempPayload.insert(tempPayload.end(), secondPayload.begin() + 6, secondPayload.end());
payload.clear();
secondPayload.clear();
payload.insert(payload.end(), tempPayload.begin(), tempPayload.begin() + 10); // This is done because the capacity of payload is already 10
secondPayload.insert(secondPayload.end(), tempPayload.begin() + 10, tempPayload.end());
}
// Consecutive Record Functions
VSA0EConsecutive::VSA0EConsecutive(uint8_t* const recordBytes, uint32_t& runningChecksum, std::shared_ptr<VSA0EFirst> first, bool isLastRecord)
: VSA0E(recordBytes, recordBytes + ConsecutivePayloadOffset, isLastRecord ? LastPayloadSize : OtherPayloadSize, runningChecksum)
{
this->first = first;
calculatedChecksum = runningChecksum;
if(getIndex() == 1) {
first->reorderPayload(payload);
} else if(isLastRecord) {
recordChecksum = *reinterpret_cast<uint32_t*>(recordBytes + 28);
doChecksum(recordBytes);
} else {
setChecksumFailed(first->getChecksumFailed());
}
setRecordCount(first->getRecordCount());
}
void VSA0EConsecutive::doChecksum(uint8_t* recordBytes)
{
setChecksumFailed(recordBytes && calculatedChecksum != recordChecksum);
}
-106
View File
@@ -1,106 +0,0 @@
#include "icsneo/disk/vsa/vsa0f.h"
#include <algorithm>
using namespace icsneo;
static constexpr auto FirstPayloadOffset = 18;
static constexpr auto FirstPayloadSize = 14;
static constexpr auto LastPayloadSize = 24;
static constexpr auto OtherPayloadSize = 28;
// Parent class functions
VSA0F::VSA0F(uint8_t* const recordBytes, uint8_t* const messageBytes, size_t numBytes, uint32_t& runningChecksum, Network::CoreMini networkId)
: VSAExtendedMessage(messageBytes, numBytes, networkId)
{
static constexpr auto DWordSize = 4;
setType(VSA::Type::AA0F);
setIndex(*reinterpret_cast<uint16_t*>(recordBytes + 2) & 0x01FFu);
setSequenceNum((*reinterpret_cast<uint16_t*>(recordBytes + 2) & 0xFE00u) >> 9);
if(getIndex() == 0) {
runningChecksum = (static_cast<uint32_t>(payload[0]) << 16) | (static_cast<uint32_t>(payload[1]) << 24);
uint32_t* dwords = reinterpret_cast<uint32_t*>(payload.data() + 2);
for (size_t i = 0; i < (payload.size() - 2) / DWordSize; i++) {
runningChecksum += dwords[i];
}
} else {
uint32_t* dwords = reinterpret_cast<uint32_t*>(recordBytes);
for (size_t i = 0; i < 8; i++) {
runningChecksum += dwords[i];
}
}
}
// First Record Functions
VSA0FFirst::VSA0FFirst(uint8_t* const recordBytes, uint32_t& runningChecksum)
: VSA0F(recordBytes, recordBytes + FirstPayloadOffset, FirstPayloadSize, runningChecksum)
{
captureBitfield = *reinterpret_cast<uint16_t*>(recordBytes + 4);
uint16_t byteCount = *reinterpret_cast<uint16_t*>(recordBytes + 6);
uint16_t recordCount;
if(byteCount <= FirstPayloadSize) {
recordCount = 1;
} else if(byteCount <= FirstPayloadSize + LastPayloadSize) {
recordCount = 2;
} else {
byteCount -= FirstPayloadSize + LastPayloadSize;
recordCount = 2 + byteCount / OtherPayloadSize;
if (byteCount % OtherPayloadSize != 0) {
recordCount += 1;
}
}
setRecordCount(recordCount);
timestamp = *reinterpret_cast<uint64_t*>(recordBytes + 8) & UINT63_MAX;
checksum = *reinterpret_cast<uint16_t*>(recordBytes + 16);
doChecksum(recordBytes);
// Network ID is not found in first record for AA0F
// Only the subsequent records have the Network ID in the payload
}
void VSA0FFirst::doChecksum(uint8_t* recordBytes)
{
uint16_t* words = reinterpret_cast<uint16_t*>(recordBytes);
uint16_t sum = 0;
for (size_t i = 0; i < 15; i++) {
sum += words[i];
}
setChecksumFailed(sum != checksum);
}
void VSA0FFirst::reservePacketData(std::shared_ptr<Packet>& packet) const
{
uint32_t numMessageBytes = (getRecordCount() - 2) * OtherPayloadSize + FirstPayloadSize + LastPayloadSize;
packet->data.reserve(numMessageBytes);
}
bool VSA0FFirst::filter(const std::shared_ptr<VSAMessageReadFilter> filter)
{
if(filter->captureBitfield != captureBitfield ||
getICSTimestampFromTimepoint(filter->readRange.first) > timestamp ||
getICSTimestampFromTimepoint(filter->readRange.second) < timestamp) {
return false;
}
return true;
}
// Consecutive Record Functions
VSA0FConsecutive::VSA0FConsecutive(uint8_t* const recordBytes, uint32_t& runningChecksum, std::shared_ptr<VSA0FFirst> first, bool isLastRecord)
: VSA0F(recordBytes, recordBytes + 4, isLastRecord ? LastPayloadSize : OtherPayloadSize, runningChecksum)
{
this->first = first;
calculatedChecksum = runningChecksum;
if(isLastRecord) {
doChecksum(recordBytes);
} else {
network = Network(static_cast<Network::CoreMini>(*reinterpret_cast<uint16_t*>(recordBytes + 28))); // Network ID is stored in 25th and 26th recordBytes of payload
}
setRecordCount(first->getRecordCount());
}
void VSA0FConsecutive::doChecksum(uint8_t* recordBytes)
{
setChecksumFailed(recordBytes && calculatedChecksum != 0);
}
-37
View File
@@ -1,37 +0,0 @@
#include "icsneo/disk/vsa/vsa6a.h"
#include "icsneo/disk/diskdriver.h"
using namespace icsneo;
static constexpr auto PayloadOffset = 56;
static constexpr auto PayloadSize = 452;
static constexpr auto TimestampOffset = 48;
static constexpr auto TimestampSize = 8;
VSA6A::VSA6A(uint8_t* const recordBytes)
: VSA()
{
setType(VSA::Type::AA6A);
sequenceNum = *reinterpret_cast<uint32_t*>(recordBytes + 34);
totalSectors = *reinterpret_cast<uint32_t*>(recordBytes + 38);
reserved = *reinterpret_cast<uint32_t*>(recordBytes + 42);
timestamp = *reinterpret_cast<uint64_t*>(recordBytes + 46) & UINT63_MAX;
timestampSum = *reinterpret_cast<uint16_t*>(recordBytes + 54);
data.insert(data.end(), recordBytes + 56, recordBytes + 508);
checksum = *reinterpret_cast<uint32_t*>(recordBytes + 508);
doChecksum(recordBytes);
}
void VSA6A::doChecksum(uint8_t* recordBytes)
{
uint32_t sum = 0;
for(size_t i = PayloadOffset; i < PayloadOffset+ PayloadSize; i++) {
sum += recordBytes[i];
}
uint16_t tSum = 0;
for(size_t i = TimestampOffset; i < TimestampOffset + TimestampSize; i++) {
tSum += recordBytes[i];
}
setChecksumFailed(sum != checksum || tSum != timestampSum);
}
-460
View File
@@ -1,460 +0,0 @@
#include "icsneo/disk/vsa/vsaparser.h"
#include "icsneo/disk/vsa/vsa02.h"
#include "icsneo/disk/vsa/vsa03.h"
#include "icsneo/disk/vsa/vsa04.h"
#include "icsneo/disk/vsa/vsa05.h"
#include "icsneo/disk/vsa/vsa06.h"
#include "icsneo/disk/vsa/vsa07.h"
#include "icsneo/disk/vsa/vsa08.h"
#include "icsneo/disk/vsa/vsa09.h"
#include "icsneo/disk/vsa/vsa0b.h"
#include "icsneo/disk/vsa/vsa0c.h"
#include "icsneo/disk/vsa/vsa0d.h"
#include "icsneo/disk/vsa/vsa0e.h"
#include "icsneo/disk/vsa/vsa0f.h"
#include "icsneo/disk/vsa/vsa6a.h"
#include "icsneo/disk/diskdriver.h"
#include <iostream>
using namespace icsneo;
bool VSAParser::parseBytes(uint8_t* const bytes, uint64_t arrLen)
{
uint64_t bytesOffset = 0;
while(bytesOffset + VSA::StandardRecordSize <= arrLen) { // Enough bytes to read for Standard Record
if(bytes[bytesOffset] != 0xAAu) {
// Invalid Input
return false;
}
switch(bytes[bytesOffset + 1]) {
case 0x00u: // Pad Record
bytesOffset += VSA::StandardRecordSize;
break;
case 0x01u: // Message Data (Deprecated)
hasDeprecatedRecords = true;
bytesOffset += VSA::StandardRecordSize;
break;
case 0x02u: // Logdata Record
if(settings.extractAA02) {
vsaRecords.push_back(std::make_shared<VSA02>(bytes + bytesOffset));
}
bytesOffset += VSA::StandardRecordSize;
break;
case 0x03u: // Event Record
if(settings.extractAA03) {
vsaRecords.push_back(std::make_shared<VSA03>(bytes + bytesOffset));
}
bytesOffset += VSA::StandardRecordSize;
break;
case 0x04u: // Partition Info Record
if(settings.extractAA04) {
vsaRecords.push_back(std::make_shared<VSA04>(bytes + bytesOffset));
}
bytesOffset += VSA::StandardRecordSize;
break;
case 0x05u: // Application Error Record
if(settings.extractAA05) {
vsaRecords.push_back(std::make_shared<VSA05>(bytes + bytesOffset));
}
bytesOffset += VSA::StandardRecordSize;
break;
case 0x06u: // Debug/Internal
if(settings.extractAA06) {
vsaRecords.push_back(std::make_shared<VSA06>(bytes + bytesOffset));
}
bytesOffset += VSA::StandardRecordSize;
break;
case 0x07u: // Debug/Internal
if(settings.extractAA07) {
vsaRecords.push_back(std::make_shared<VSA07>(bytes + bytesOffset));
}
bytesOffset += VSA::StandardRecordSize;
break;
case 0x08u: // Buffer Info Record
if(settings.extractAA08) {
vsaRecords.push_back(std::make_shared<VSA08>(bytes + bytesOffset));
}
bytesOffset += VSA::StandardRecordSize;
break;
case 0x09u: // Device Info Record
if(settings.extractAA09) {
vsaRecords.push_back(std::make_shared<VSA09>(bytes + bytesOffset));
}
bytesOffset += VSA::StandardRecordSize;
break;
case 0x0Au: // Logger Info Configuration (Deprecated)
hasDeprecatedRecords = true;
bytesOffset += VSA::StandardRecordSize;
break;
case 0x0Bu: // Message Data
if(settings.extractAA0B) {
auto record = std::make_shared<VSA0B>(bytes + bytesOffset);
vsaRecords.push_back(record);
}
bytesOffset += VSA::StandardRecordSize;
break;
case 0x0Cu: // PCM Audio Data
if(settings.extractAA0C) {
vsaRecords.push_back(std::make_shared<VSA0C>(bytes + bytesOffset));
}
bytesOffset += VSA::StandardRecordSize;
break;
case 0x0Du: // Message Data (Extended)
if(settings.extractAA0D) {
if(!handleExtendedRecord(bytes, bytesOffset, VSA::Type::AA0D)) {
return false;
}
}
bytesOffset += VSA::StandardRecordSize;
break;
case 0x0Eu: // Message Data (Extended)
if(settings.extractAA0E) {
if(!handleExtendedRecord(bytes, bytesOffset, VSA::Type::AA0E)) {
return false;
}
}
bytesOffset += VSA::StandardRecordSize;
break;
case 0x0Fu: // Message Data (Extended)
if(settings.extractAA0F) {
if(!handleExtendedRecord(bytes, bytesOffset, VSA::Type::AA0F)) {
return false;
}
}
bytesOffset += VSA::StandardRecordSize;
break;
case 0x6Au: // Logger Configuration Backup
if(bytesOffset + Disk::SectorSize <= arrLen) {
if(settings.extractAA6A) {
vsaRecords.push_back(std::make_shared<VSA6A>(bytes + bytesOffset));
}
}
bytesOffset += Disk::SectorSize;
break;
default:
// Unhandled VSA Record Type
return false;
break;
}
}
return true;
}
bool VSAParser::handleExtendedRecord(uint8_t* const bytes, uint64_t& bytesOffset, VSA::Type type)
{
// Gather info about the extended record sequence of the record contained in bytes
std::shared_ptr<VSAExtendedMessage> first;
uint16_t seqNum;
ExtendedMessageState::ExtendedRecordSeqInfo* seqInfo;
uint32_t runningChecksum = 0;
switch(type) {
case VSA::Type::AA0D:
first = std::make_shared<VSA0DFirst>(bytes + bytesOffset, runningChecksum);
seqNum = first->getSequenceNum();
seqInfo = &state.vsa0DSeqInfo[seqNum];
break;
case VSA::Type::AA0E:
first = std::make_shared<VSA0EFirst>(bytes + bytesOffset, runningChecksum);
seqNum = first->getSequenceNum();
seqInfo = &state.vsa0ESeqInfo[seqNum];
break;
case VSA::Type::AA0F:
first = std::make_shared<VSA0FFirst>(bytes + bytesOffset, runningChecksum);
seqNum = first->getSequenceNum();
seqInfo = &state.vsa0FSeqInfo[seqNum];
break;
default:
return false; // Invalid type was passed
}
if(seqInfo->nextIndex == 0 && seqInfo->records.size() == 0) { // This is the first record in the sequence
if(first->getIndex() != 0) {
seqInfo->clear();
report(APIEvent::Type::VSAExtendedMessageError, APIEvent::Severity::EventWarning);
return true; // This is not actually the first record
}
seqInfo->records.push_back(first);
seqInfo->totalRecordCount = first->getRecordCount();
seqInfo->nextIndex++;
seqInfo->runningChecksum = runningChecksum;
} else if(seqInfo->nextIndex < seqInfo->totalRecordCount && seqInfo->records.size() > 0) { // Consecutive Record
std::shared_ptr<VSAExtendedMessage> consecutive;
bool isLast = seqInfo->nextIndex == seqInfo->totalRecordCount - 1;
// Construct the consecutive record from bytes
switch(type) {
case VSA::Type::AA0D:
consecutive = std::make_shared<VSA0DConsecutive>(
bytes + bytesOffset,
seqInfo->runningChecksum,
std::dynamic_pointer_cast<VSA0DFirst>(seqInfo->records[0]),
isLast
);
break;
case VSA::Type::AA0E:
consecutive = std::make_shared<VSA0EConsecutive>(
bytes + bytesOffset,
seqInfo->runningChecksum,
std::dynamic_pointer_cast<VSA0EFirst>(seqInfo->records[0]),
isLast
);
break;
case VSA::Type::AA0F:
consecutive = std::make_shared<VSA0FConsecutive>(
bytes + bytesOffset,
seqInfo->runningChecksum,
std::dynamic_pointer_cast<VSA0FFirst>(seqInfo->records[0]),
isLast
);
break;
default:
return false;
}
if(consecutive->getIndex() == seqInfo->nextIndex && consecutive->getSequenceNum() == seqNum) { // This record is valid in the sequence
seqInfo->records.push_back(consecutive);
seqInfo->nextIndex++;
} else { // Sequence is out of order/invalid
// Throw away incomplete sequence and report warning
seqInfo->clear();
report(APIEvent::Type::VSAExtendedMessageError, APIEvent::Severity::EventWarning);
// Save data for new sequence
if(first->getIndex() == 0) {
seqInfo->records.push_back(first);
seqInfo->totalRecordCount = first->getRecordCount();
seqInfo->nextIndex++;
seqInfo->runningChecksum = runningChecksum;
}
return true;
}
if(seqInfo->nextIndex == seqInfo->totalRecordCount) { // This is the last record in the sequence
if(consecutive->getChecksumFailed()) {
// Fail out if checksum fails
seqInfo->clear();
return false;
}
vsaRecords.insert(vsaRecords.end(), seqInfo->records.begin(), seqInfo->records.end());
seqInfo->clear();
}
} else {
return false; // Undefined behavior
}
return true;
}
VSAParser::RecordParseStatus VSAParser::getRecordFromBytes(uint8_t* const bytes, size_t arrLen, std::shared_ptr<VSA>& record)
{
record = nullptr;
if(arrLen < VSA::StandardRecordSize) {
// Not enough bytes
return VSAParser::RecordParseStatus::InsufficientData;
} else if(bytes[0] != 0xAAu) {
return VSAParser::RecordParseStatus::NotARecordStart;
} else {
switch(bytes[1]) {
case 0x00u: // Pad Record
return VSAParser::RecordParseStatus::Pad;
case 0x01u: // Message Data (Deprecated)
return VSAParser::RecordParseStatus::Deprecated;
case 0x02u: // Logdata Record
if(settings.extractAA02) {
record = std::make_shared<VSA02>(bytes);
return VSAParser::RecordParseStatus::Success;
}
break;
case 0x03u: // Event Record
if(settings.extractAA03) {
record = std::make_shared<VSA03>(bytes);
return VSAParser::RecordParseStatus::Success;
}
break;
case 0x04u: // Partition Info Record
if(settings.extractAA04) {
record = std::make_shared<VSA04>(bytes);
return VSAParser::RecordParseStatus::Success;
}
break;
case 0x05u: // Application Error Record
if(settings.extractAA05) {
record = std::make_shared<VSA05>(bytes);
return VSAParser::RecordParseStatus::Success;
}
break;
case 0x06u: // Debug/Internal
if(settings.extractAA06) {
record = std::make_shared<VSA06>(bytes);
return VSAParser::RecordParseStatus::Success;
}
break;
case 0x07u: // Debug/Internal
if(settings.extractAA07) {
record = std::make_shared<VSA07>(bytes);
return VSAParser::RecordParseStatus::Success;
}
break;
case 0x08u: // Buffer Info Record
if(settings.extractAA08) {
record = std::make_shared<VSA08>(bytes);
return VSAParser::RecordParseStatus::Success;
}
break;
case 0x09u: // Device Info Record
if(settings.extractAA09) {
record = std::make_shared<VSA09>(bytes);
return VSAParser::RecordParseStatus::Success;
}
break;
case 0x0Au:
return VSAParser::RecordParseStatus::Deprecated;
case 0x0Bu: // Message Data
if(settings.extractAA0B) {
record = std::make_shared<VSA0B>(bytes);
return VSAParser::RecordParseStatus::Success;
}
break;
case 0x0Cu: // PCM Audio Data
if(settings.extractAA0C) {
record = std::make_shared<VSA0C>(bytes);
return VSAParser::RecordParseStatus::Success;
}
break;
case 0x0Du: // Message Data (Extended)
if(settings.extractAA0D) {
uint32_t payloadChecksum = 0;
const auto& vsa = std::make_shared<VSA0DFirst>(bytes, payloadChecksum);
record = vsa;
if(vsa->getIndex() == 0) {
return VSAParser::RecordParseStatus::Success;
}
// This returns the consecutive record as a first record
return VSAParser::RecordParseStatus::ConsecutiveExtended;
}
break;
case 0x0Eu: // Message Data (Extended)
if(settings.extractAA0E) {
uint32_t payloadChecksum = 0;
const auto& vsa = std::make_shared<VSA0EFirst>(bytes, payloadChecksum);
record = vsa;
if(vsa->getIndex() == 0) {
return VSAParser::RecordParseStatus::Success;
}
// This returns the consecutive record as a first record
return VSAParser::RecordParseStatus::ConsecutiveExtended;
}
break;
case 0x0Fu: // Message Data (Extended)
if(settings.extractAA0F) {
uint32_t payloadChecksum = 0;
const auto& vsa = std::make_shared<VSA0FFirst>(bytes, payloadChecksum);
record = vsa;
if(vsa->getIndex() == 0) {
return VSAParser::RecordParseStatus::Success;
}
// This returns the consecutive record as a first record
return VSAParser::RecordParseStatus::ConsecutiveExtended;
}
break;
case 0x6Au: // Logger Configuration Backup
if(settings.extractAA6A) {
if(arrLen < Disk::SectorSize) {
return VSAParser::RecordParseStatus::InsufficientData;
}
record = std::make_shared<VSA6A>(bytes);
return VSAParser::RecordParseStatus::Success;
}
break;
default:
// Unhandled VSA Record Type
return VSAParser::RecordParseStatus::UnknownRecordType;
break;
}
}
return VSAParser::RecordParseStatus::FilteredOut;
}
void VSAParser::clearParseState()
{
for(size_t i = 0; i < state.vsa0DSeqInfo.size(); i++) {
state.vsa0DSeqInfo[i].clear();
}
for(size_t i = 0; i < state.vsa0ESeqInfo.size(); i++) {
state.vsa0ESeqInfo[i].clear();
}
for(size_t i = 0; i < state.vsa0DSeqInfo.size(); i++) {
state.vsa0ESeqInfo[i].clear();
}
}
bool VSAParser::extractMessagePackets(std::vector<std::shared_ptr<Packet>>& packets)
{
if(settings != Settings::messageRecords()) {
report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error);
return false; // We do not have exclusively message records
}
std::shared_ptr<Packet> packet;
bool activeExtendedMessage = false;
VSA::Type previousRecordType = VSA::Type::Invalid;
for(const auto& record : vsaRecords) {
VSA::Type activeRecordType = record->getType();
switch(activeRecordType) {
// Handle standard message records
case VSA::Type::AA0B: {
if(activeExtendedMessage) {
// Non-terminated extended message record
// There was a failure/unexpected behavior in the parsing process
report(APIEvent::Type::VSAExtendedMessageError, APIEvent::Severity::Error);
return false;
}
std::shared_ptr<VSAMessage> messageRecord = std::dynamic_pointer_cast<VSAMessage>(record);
if(!settings.messageFilter || messageRecord->filter(settings.messageFilter)) {
packet = messageRecord->getPacket();
packets.push_back(packet);
}
packet = nullptr;
break;
}
// Handle extended message records
case VSA::Type::AA0D:
case VSA::Type::AA0E:
case VSA::Type::AA0F: {
std::shared_ptr<VSAExtendedMessage> extendedMessageRecord = std::dynamic_pointer_cast<VSAExtendedMessage>(record);
if(!activeExtendedMessage) { // Start new extended message packet
packet = extendedMessageRecord->getPacket();
activeExtendedMessage = true;
previousRecordType = extendedMessageRecord->getType();
} else if(previousRecordType == activeRecordType) { // Continue existing extended message packet
extendedMessageRecord->appendPacket(packet);
if(extendedMessageRecord->getRecordCount() == static_cast<uint32_t>(extendedMessageRecord->getIndex() + 1)) { // Last record in sequence
if(!settings.messageFilter || extendedMessageRecord->filter(settings.messageFilter)) {
VSAExtendedMessage::truncatePacket(packet);
packets.push_back(packet);
}
activeExtendedMessage = false;
packet = nullptr;
previousRecordType = activeRecordType;
}
} else {
// Non-terminated extended message record
// There was a failure/unexpected behavior in the parsing process
activeExtendedMessage = false;
packet = nullptr;
previousRecordType = VSA::Type::Invalid;
report(APIEvent::Type::VSAOtherError, APIEvent::Severity::Error);
return false;
}
break;
}
default:
// Non-message record discovered
report(APIEvent::Type::VSAOtherError, APIEvent::Severity::Error);
return false;
}
}
vsaRecords.clear();
return true;
}
+1 -1
View File
@@ -64,7 +64,7 @@ master_doc = 'index'
# General information about the project.
project = 'libicsneo'
copyright = '2018-2024, Intrepid Control Systems, Inc.'
copyright = '2018-2023, Intrepid Control Systems, Inc.'
author = 'Intrepid Control Systems, Inc.'
# The version info for the project you're documenting, acts as replacement for
+1 -1
View File
@@ -64,7 +64,7 @@ master_doc = 'index'
# General information about the project.
project = 'libicsneo'
copyright = '2018-2024, Intrepid Control Systems, Inc.'
copyright = '2018-2023, Intrepid Control Systems, Inc.'
author = 'Intrepid Control Systems, Inc.'
# The version info for the project you're documenting, acts as replacement for
-5
View File
@@ -8,7 +8,6 @@ option(LIBICSNEO_BUILD_CPP_LIN_EXAMPLE "Build the LIN example." ON)
option(LIBICSNEO_BUILD_CPP_LIVEDATA_EXAMPLE "Build the Live Data example." ON)
option(LIBICSNEO_BUILD_CPP_COREMINI_EXAMPLE "Build the Coremini example." ON)
option(LIBICSNEO_BUILD_CPP_MDIO_EXAMPLE "Build the MDIO example." ON)
option(LIBICSNEO_BUILD_CPP_VSA_EXAMPLE "Build the VSA example." ON)
# Disabled until we properly build these in-tree
# option(LIBICSNEO_BUILD_CSHARP_INTERACTIVE_EXAMPLE "Build the command-line interactive C# example." OFF)
@@ -54,10 +53,6 @@ if(LIBICSNEO_BUILD_CPP_MDIO_EXAMPLE)
add_subdirectory(cpp/mdio)
endif()
if(LIBICSNEO_BUILD_CPP_VSA_EXAMPLE)
add_subdirectory(cpp/vsa)
endif()
# if(LIBICSNEO_BUILD_CSHARP_INTERACTIVE_EXAMPLE)
# add_subdirectory(csharp)
# endif()
+12
View File
@@ -1,3 +1,15 @@
cmake_minimum_required(VERSION 3.2)
project(libicsneoc-interactive-example VERSION 0.2.0)
include(GNUInstallDirs)
# Include libicsneo's include directory
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../../include)
if(UNIX)
set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS)
endif()
add_executable(libicsneoc-interactive-example src/main.c)
if(UNIX)
target_link_libraries(libicsneoc-interactive-example ${CMAKE_DL_LIBS})
+1 -3
View File
@@ -166,9 +166,7 @@ char getCharInput(int numArgs, ...) {
va_end(vaList);
while(!found) {
if(fgets(input, 99, stdin) == NULL) {
break;
}
fgets(input, 99, stdin);
if(strlen(input) == 2) {
for(int i = 0; i < numArgs; ++i) {
if(input[0] == *(list + i)) {
+3
View File
@@ -1,3 +1,6 @@
cmake_minimum_required(VERSION 3.2)
project(libicsneoc-legacy-lin-example VERSION 0.2.0)
add_executable(libicsneoc-legacy-lin-example lin/main.c)
add_executable(libicsneoc-legacy-device-settings-example deviceSettings/main.c)
target_link_libraries(libicsneoc-legacy-lin-example icsneolegacy)
+8 -7
View File
@@ -37,17 +37,18 @@ int main() {
printf("ICS icsneolegacy.dll version %u\n\n", ver);
// Find and attempt to open device
//legacy open device
int numDevices = 255;
NeoDeviceEx devices[255] = {0};
void* hObject = NULL; // holds a handle to the neoVI object
int numDevices = 10;
NeoDevice devices[10];
void* hObject; // holds a handle to the neoVI object
int iRetVal = 0;
int deviceTypes = 0;
int iResult = 0;
SDeviceSettings pSettings = {0};
SDeviceSettings pSettings;
iRetVal = icsneoFindDevices(devices, &numDevices, NULL, 0, NULL, 0);
if(iRetVal && numDevices > 0) {
iRetVal = icsneoFindNeoDevices(deviceTypes, devices, &numDevices);
if(iRetVal) {
// Attempt to open the selected device, enable message polling, and go online
iRetVal = icsneoOpenDevice(&devices[0], &hObject, NULL, 1, 0, NULL, 0);
iRetVal = icsneoOpenNeoDevice(&devices[0], &hObject, NULL, 1, 0);
if(iRetVal) {
puts("Device found and opened!\n");
} else {
+7 -6
View File
@@ -31,16 +31,17 @@ int main() {
printf("ICS icsneolegacy.dll version %u\n\n", ver);
// Find and attempt to open device
//legacy open device
int numDevices = 255;
NeoDeviceEx devices[255] = {0};
void* hObject = NULL; // holds a handle to the neoVI object
int numDevices = 10;
NeoDevice devices[10];
void* hObject; // holds a handle to the neoVI object
int iRetVal = 0;
int deviceTypes = 0;
int iResult = 0;
iRetVal = icsneoFindDevices(devices, &numDevices, NULL, 0, NULL, 0);
if(iRetVal && numDevices < 0) {
iRetVal = icsneoFindNeoDevices(deviceTypes, devices, &numDevices);
if(iRetVal) {
// Attempt to open the selected device, enable message polling, and go online
iRetVal = icsneoOpenDevice(&devices[0], &hObject, NULL, 1, 0, NULL, 0);
iRetVal = icsneoOpenNeoDevice(&devices[0], &hObject, NULL, 1, 0);
if(iRetVal) {
printf("Device found and opened!\n");
} else {
+12
View File
@@ -1,3 +1,15 @@
cmake_minimum_required(VERSION 3.2)
project(libicsneoc-simple-lin-example VERSION 0.2.0)
include(GNUInstallDirs)
# Include libicsneo's include directory
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../../include)
if(UNIX)
set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS)
endif()
add_executable(libicsneoc-simple-lin-example lin/main.c)
if(UNIX)
target_link_libraries(libicsneoc-simple-lin-example ${CMAKE_DL_LIBS})
+1 -3
View File
@@ -161,9 +161,7 @@ char getCharInput(int numArgs, ...) {
va_end(vaList);
while(!found) {
if(fgets(input, 99, stdin) == NULL) {
break;
}
fgets(input, 99, stdin);
if(strlen(input) == 2) {
for(int i = 0; i < numArgs; ++i) {
if(input[0] == *(list + i)) {
+25
View File
@@ -1,2 +1,27 @@
cmake_minimum_required(VERSION 3.2)
project(libicsneocpp-a2b VERSION 0.2.0)
set(CMAKE_CXX_STANDARD_REQUIRED 11)
include(GNUInstallDirs)
# Add an include directory like so if desired
#include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
# Enable Warnings
if(MSVC)
# Force to always compile with W4
if(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
endif()
else() #if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-switch -Wno-unknown-pragmas")
endif()
# Add libicsneo, usually a git submodule within your project works well
#add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../third-party/libicsneo ${CMAKE_CURRENT_BINARY_DIR}/third-party/libicsneo)
add_executable(libicsneocpp-a2b src/a2b.cpp)
target_link_libraries(libicsneocpp-a2b icsneocpp)
+2 -88
View File
@@ -233,93 +233,11 @@ void example5(std::shared_ptr<icsneo::Device>& rada2b) {
std::thread listenerThread{listener};
// Transmit wave file using example0
example0(rada2b);
listenerThread.join();
}
// Example 6: Retrieving A2B bus status using I2C messaages.
void example6(std::shared_ptr<icsneo::Device>& rada2b) {
std::shared_ptr<icsneo::I2CMessage> msg = std::make_shared<icsneo::I2CMessage>();
std::shared_ptr<icsneo::MessageFilter> msgFilter = std::make_shared<icsneo::MessageFilter>(icsneo::Network::NetID::I2C2);
msg->network = icsneo::Network(icsneo::Network::NetID::I2C2);
msg->controlBytes.resize(1);
msg->controlBytes[0] = static_cast<uint8_t>(0x17u); // Register address for A2B INTTYPE
msg->dataBytes.resize(1, 0);
msg->direction = icsneo::I2CMessage::Direction::Read;
msg->deviceMode = icsneo::I2CMessage::DeviceMode::Controller;
msg->address = static_cast<uint16_t>(0x68); // A2B master node address.
msg->isTXMsg = true;
auto handler = rada2b->addMessageCallback(std::make_shared<icsneo::MessageCallback>(
[] (std::shared_ptr<icsneo::Message> newMsg) {
if(newMsg->type == icsneo::Message::Type::Frame) {
const auto& frame = std::dynamic_pointer_cast<icsneo::Frame>(newMsg);
if(frame && frame->network.getNetID() == icsneo::Network::NetID::I2C2) {
const auto& i2cMessage = std::dynamic_pointer_cast<icsneo::I2CMessage>(frame);
if(!i2cMessage) {
return;
}
if(i2cMessage->controlBytes.size() == 1 && i2cMessage->direction == icsneo::I2CMessage::Direction::Read) {
if(i2cMessage->controlBytes[0] == 0x17u) {
if(i2cMessage->dataBytes.size() == 1) {
std::cout << "Current A2B bus status INTTYPE code: " << static_cast<int>(i2cMessage->dataBytes[0]) << '\n';
}
} else if(i2cMessage->controlBytes[0] == 0x03u) {
if(i2cMessage->dataBytes.size() == 1) {
std::cout << "A2B_PRODUCT register: " << static_cast<int>(i2cMessage->dataBytes[0]) << std::endl;
}
} else if(i2cMessage->controlBytes[0] == 0x02u) {
if(i2cMessage->dataBytes.size() == 1) {
std::cout << "A2B_VENDOR register: " << static_cast<int>(i2cMessage->dataBytes[0]) << std::endl;
}
} else if(i2cMessage->controlBytes[0] == 0x1C) {
if(i2cMessage->dataBytes.size() == 1) {
std::cout << "A2B_INTMSK1 register value: " << static_cast<int>(i2cMessage->dataBytes[0]) << std::endl;
}
}
}
}
}
}
, msgFilter));
if(!rada2b->transmit(msg)) {
std::cout << "Failed to transmit." << std::endl;
}
msg->controlBytes[0] = 0x03; // Address for A2B_PRODUCT register
if(!rada2b->transmit(msg)) {
std::cout << "Failed to transmit." << std::endl;
}
msg->controlBytes[0] = 0x02; // Address for A2B_VENDOR register
if(!rada2b->transmit(msg)) {
std::cout << "Failed to transmit." << std::endl;
}
msg->controlBytes[0] = 0x1C ; // Address for A2B_INTMSK1 register
msg->dataBytes[0] = 0x11;
msg->direction = icsneo::I2CMessage::Direction::Write;
// Write register
if(!rada2b->transmit(msg)) {
std::cout << "Failed to transmit" << std::endl;
}
std::this_thread::sleep_for(std::chrono::milliseconds(2000));
msg->direction = icsneo::I2CMessage::Direction::Read;
// Read register
if(!rada2b->transmit(msg)) {
std::cout << "Failed to transmit." << std::endl;
}
std::this_thread::sleep_for(std::chrono::milliseconds(2000));
rada2b->removeMessageCallback(handler);
}
void displayUsage() {
std::cout << "libicsneo A2B example" << std::endl;
std::cout << "Example must be ran with rada2b as slave on TDM4 32 bit channel size and one ADI master node" << std::endl;
@@ -336,7 +254,6 @@ void displayUsage() {
std::cout << "3\tA2BMessage API" << std::endl;
std::cout << "4\tPackaging and transmitting sine wave using A2BMessage API" << std::endl;
std::cout << "5\tWave loopback" << std::endl;
std::cout << "6\tRead/write I2C registers on A2B board" << std::endl;
}
int main(int argc, char** argv) {
@@ -360,7 +277,7 @@ int main(int argc, char** argv) {
int option = atoi(arguments[2].c_str());
if(option < 0 || option > 6) {
if(option < 0 || option > 5) {
std::cerr << "Invalid usage." << std::endl;
displayUsage();
return EXIT_FAILURE;
@@ -428,9 +345,6 @@ int main(int argc, char** argv) {
case 5:
example5(rada2b);
break;
case 6:
example6(rada2b);
break;
default:
break;
}
+25
View File
@@ -1,2 +1,27 @@
cmake_minimum_required(VERSION 3.2)
project(libicsneocpp-coremini VERSION 0.2.0)
set(CMAKE_CXX_STANDARD_REQUIRED 11)
include(GNUInstallDirs)
# Add an include directory like so if desired
#include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
# Enable Warnings
if(MSVC)
# Force to always compile with W4
if(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
endif()
else() #if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-switch -Wno-unknown-pragmas")
endif()
# Add libicsneo, usually a git submodule within your project works well
#add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../third-party/libicsneo ${CMAKE_CURRENT_BINARY_DIR}/third-party/libicsneo)
add_executable(libicsneocpp-coremini src/coremini.cpp)
target_link_libraries(libicsneocpp-coremini icsneocpp)
+7 -18
View File
@@ -1,5 +1,5 @@
// Usage:
// ./libicsneocpp-coremini [DEVICE_SERIAL] [COREMINI_SCRIPT_PATH] [FLASH | SD]
// ./libicsneocpp-coremini [DEVICE_SERIAL] [COREMINI_SCRIPT_PATH]
#include <iostream>
@@ -8,14 +8,14 @@
void displayUsage() {
std::cout << "Usage:\n";
std::cout << "./libicsneocpp-coremini [DEVICE_SERIAL] [COREMINI_SCRIPT_PATH] [FLASH | SD]\n";
std::cout << "./libicsneocpp-coremini [DEVICE_SERIAL] [COREMINI_SCRIPT_PATH]\n";
}
int main(int argc, char** argv) {
std::vector<std::string> arguments(argv, argv + argc);
if(arguments.size() != 4) {
if(arguments.size() != 3) {
displayUsage();
return EXIT_FAILURE;
}
@@ -50,25 +50,14 @@ int main(int argc, char** argv) {
return EXIT_FAILURE;
}
std::string memTypeString = arguments[3];
icsneo::Disk::MemoryType type;
if(memTypeString == "FLASH") {
type = icsneo::Disk::MemoryType::Flash;
} else if(memTypeString == "SD") {
type = icsneo::Disk::MemoryType::SD;
} else {
std::cout << "Incorrect memory type option" << std::endl;
displayUsage();
return EXIT_FAILURE;
}
if (!device->uploadCoremini(std::make_unique<std::ifstream>(arguments[2], std::ios::binary), type)) {
if (!device->uploadCoremini(std::make_unique<std::ifstream>(arguments[2], std::ios::binary), icsneo::Disk::MemoryType::Flash))
{
std::cout << "Failed to upload coremini" << std::endl;
std::cout << icsneo::GetLastError() << std::endl;
}
if (!device->startScript(type)) {
if (!device->startScript(icsneo::Disk::MemoryType::Flash))
{
std::cout << "Failed to start script" << std::endl;
std::cout << icsneo::GetLastError() << std::endl;
}
+25
View File
@@ -1,2 +1,27 @@
cmake_minimum_required(VERSION 3.2)
project(libicsneocpp-interactive-example VERSION 0.2.0)
set(CMAKE_CXX_STANDARD_REQUIRED 11)
include(GNUInstallDirs)
# Add an include directory like so if desired
#include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
# Enable Warnings
if(MSVC)
# Force to always compile with W4
if(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
endif()
else() #if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-switch -Wno-unknown-pragmas")
endif()
# Add libicsneo, usually a git submodule within your project works well
#add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../third-party/libicsneo ${CMAKE_CURRENT_BINARY_DIR}/third-party/libicsneo)
add_executable(libicsneocpp-interactive-example src/InteractiveExample.cpp)
target_link_libraries(libicsneocpp-interactive-example icsneocpp)
+25
View File
@@ -1,2 +1,27 @@
cmake_minimum_required(VERSION 3.2)
project(libicsneocpp-lin VERSION 0.1.0)
set(CMAKE_CXX_STANDARD_REQUIRED 11)
include(GNUInstallDirs)
# Add an include directory like so if desired
#include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
# Enable Warnings
if(MSVC)
# Force to always compile with W4
if(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
endif()
else() #if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-switch -Wno-unknown-pragmas")
endif()
# Add libicsneo, usually a git submodule within your project works well
#add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../third-party/libicsneo ${CMAKE_CURRENT_BINARY_DIR}/third-party/libicsneo)
add_executable(libicsneocpp-lin src/LINExample.cpp)
target_link_libraries(libicsneocpp-lin icsneocpp)
+57 -63
View File
@@ -7,6 +7,32 @@
#include "icsneo/communication/message/linmessage.h"
/* Note: This example requires LIN 1 and LIN 2 channels to be connected on the device */
char getCharInput(std::vector<char> allowed) {
bool found = false;
std::string input;
while(!found) {
std::cin >> input;
if(input.length() == 1) {
for(char compare : allowed) {
if(compare == input.c_str()[0]) {
found = true;
break;
}
}
}
if(!found) {
std::cout << "Input did not match expected options. Please try again." << std::endl;
std::cout << "<X or x to quit>" << std::endl;
}
}
return input.c_str()[0];
}
int main() {
// Print version
std::cout << "Running libicsneo " << icsneo::GetVersion() << std::endl;
@@ -20,7 +46,7 @@ int main() {
std::cout << '\t' << device->describe() << " @ Handle " << device->getNeoDevice().handle << std::endl;
std::cout << std::endl;
for(auto device : devices) {
for(auto& device : devices) {
std::cout << "Connecting to " << device->describe() << "... ";
bool ret = device->open();
if(!ret) { // Failed to open
@@ -28,54 +54,10 @@ int main() {
std::cout << icsneo::GetLastError() << std::endl << std::endl;
continue;
}
std::cout << "OK" << std::endl << std::endl;
int64_t baud = 19200;
std::cout << "Enable LIN commander resistor... ";
ret = device->settings->setCommanderResistorFor(icsneo::Network::NetID::LIN, true);
std::cout << (ret ? "OK" : "FAIL") << std::endl;
std::cout << "Disable LIN2 commander resistor... ";
ret = device->settings->setCommanderResistorFor(icsneo::Network::NetID::LIN2, false);
std::cout << (ret ? "OK" : "FAIL") << std::endl;
std::cout << "Setting LIN to operate at " << baud << "bit/s... ";
ret = device->settings->setBaudrateFor(icsneo::Network::NetID::LIN, baud);
std::cout << (ret ? "OK" : "FAIL") << std::endl;
std::cout << "Setting LIN2 to operate at " << baud << "bit/s... ";
ret = device->settings->setBaudrateFor(icsneo::Network::NetID::LIN2, baud);
std::cout << (ret ? "OK" : "FAIL") << std::endl;
std::cout << "Setting LIN mode to NORMAL... ";
ret = device->settings->setLINModeFor(icsneo::Network::NetID::LIN, NORMAL_MODE);
std::cout << (ret ? "OK" : "FAIL") << std::endl;
std::cout << "Setting LIN2 mode to NORMAL... ";
ret = device->settings->setLINModeFor(icsneo::Network::NetID::LIN2, NORMAL_MODE);
std::cout << (ret ? "OK" : "FAIL") << std::endl;
std::cout << "Applying settings... ";
ret = device->settings->apply();
std::cout << (ret ? "OK" : "FAIL") << std::endl;
std::cout << "Getting LIN Baudrate... ";
int64_t readBaud = device->settings->getBaudrateFor(icsneo::Network::NetID::LIN);
if(readBaud < 0)
std::cout << "FAIL" << std::endl;
else
std::cout << "OK, " << (readBaud) << "bit/s" << std::endl;
std::cout << "Getting LIN2 Baudrate... ";
readBaud = device->settings->getBaudrateFor(icsneo::Network::NetID::LIN2);
if(readBaud < 0)
std::cout << "FAIL" << std::endl;
else
std::cout << "OK, " << (readBaud) << "bit/s" << std::endl << std::endl;
std::cout << "OK" << std::endl;
// The concept of going "online" tells the connected device to start listening, i.e. ACKing traffic and giving it to us
std::cout << "Going online... ";
std::cout << "\tGoing online... ";
ret = device->goOnline();
if(!ret) {
std::cout << "FAIL" << std::endl;
@@ -86,14 +68,14 @@ int main() {
// A real application would just check the result of icsneo_goOnline() rather than calling this
// This function is intended to be called later on if needed
std::cout << "Checking online status... ";
std::cout << "\tChecking online status... ";
ret = device->isOnline();
if(!ret) {
std::cout << "FAIL\n" << std::endl;
device->close();
continue;
}
std::cout << "OK" << std::endl << std::endl;
std::cout << "OK" << std::endl;
auto handler = device->addMessageCallback(std::make_shared<icsneo::MessageCallback>([&](std::shared_ptr<icsneo::Message> message) {
if(icsneo::Message::Type::Frame == message->type) {
@@ -113,7 +95,7 @@ int main() {
}));
// We can transmit messages
std::cout << "Transmitting a LIN responder data frame... ";
std::cout << "\tTransmitting a LIN responder data frame... ";
auto lin_r = std::make_shared<icsneo::LINMessage>();
lin_r->network = icsneo::Network::NetID::LIN2;
lin_r->ID = 0x11;
@@ -122,7 +104,7 @@ int main() {
ret = device->transmit(lin_r); // This will return false if the device does not support LIN
std::cout << (ret ? "OK" : "FAIL") << std::endl;
std::cout << "Transmitting a LIN commander header... ";
std::cout << "\tTransmitting a LIN commander frame... ";
auto lin_c = std::make_shared<icsneo::LINMessage>();
lin_c->network = icsneo::Network::NetID::LIN;
lin_c->ID = 0x11;
@@ -130,9 +112,7 @@ int main() {
ret = device->transmit(lin_c);
std::cout << (ret ? "OK" : "FAIL") << std::endl << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(100));
std::cout << "Transmitting a LIN commander frame with responder data... ";
std::cout << "\tTransmitting a LIN commander frame with responder data... ";
auto lin_d = std::make_shared<icsneo::LINMessage>();
lin_d->network = icsneo::Network::NetID::LIN;
lin_d->ID = 0x22;
@@ -141,17 +121,31 @@ int main() {
lin_d->data = {0x11, 0x22, 0x33, 0x44, 0xaa, 0xbb, 0xcc, 0xdd};
ret = device->transmit(lin_d);
std::cout << (ret ? "OK" : "FAIL") << std::endl << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(100));
std::cout << "<X or x to quit>\n\n";
// Go offline, stop sending and receiving traffic
device->removeMessageCallback(handler);
std::cout << "Going offline... ";
ret = device->goOffline();
std::cout << (ret ? "OK" : "FAIL") << std::endl;
std::cout << "Disconnecting... ";
ret = device->close();
std::cout << (ret ? "OK\n" : "FAIL\n") << std::endl;
auto shutdown = [&](){
device->removeMessageCallback(handler);
std::cout << "\tGoing offline... ";
ret = device->goOffline();
std::cout << (ret ? "OK" : "FAIL") << std::endl;
std::cout << "\tDisconnecting... ";
ret = device->close();
std::cout << (ret ? "OK\n" : "FAIL\n") << std::endl;
};
while(true) {
char input = getCharInput(std::vector<char> {'X', 'x'});
switch(input) {
case 'X':
case 'x':
shutdown();
printf("Exiting program\n");
return 0;
default:
break;
}
}
}
return 0;
}
+25
View File
@@ -1,2 +1,27 @@
cmake_minimum_required(VERSION 3.2)
project(libicsneocpp-livedata VERSION 0.1.0)
set(CMAKE_CXX_STANDARD_REQUIRED 11)
include(GNUInstallDirs)
# Add an include directory like so if desired
#include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
# Enable Warnings
if(MSVC)
# Force to always compile with W4
if(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
endif()
else() #if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-switch -Wno-unknown-pragmas")
endif()
# Add libicsneo, usually a git submodule within your project works well
#add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../third-party/libicsneo ${CMAKE_CURRENT_BINARY_DIR}/third-party/libicsneo)
add_executable(libicsneocpp-livedata src/LiveDataExample.cpp)
target_link_libraries(libicsneocpp-livedata icsneocpp)
+25
View File
@@ -1,2 +1,27 @@
cmake_minimum_required(VERSION 3.2)
project(libicsneocpp-mdio VERSION 0.1.0)
set(CMAKE_CXX_STANDARD_REQUIRED 11)
include(GNUInstallDirs)
# Add an include directory like so if desired
#include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
# Enable Warnings
if(MSVC)
# Force to always compile with W4
if(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
endif()
else() #if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-switch -Wno-unknown-pragmas")
endif()
# Add libicsneo, usually a git submodule within your project works well
#add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../third-party/libicsneo ${CMAKE_CURRENT_BINARY_DIR}/third-party/libicsneo)
add_executable(libicsneocpp-mdio src/MDIOExample.cpp)
target_link_libraries(libicsneocpp-mdio icsneocpp)
+25
View File
@@ -1,2 +1,27 @@
cmake_minimum_required(VERSION 3.2)
project(libicsneocpp-simple-example VERSION 0.2.0)
set(CMAKE_CXX_STANDARD_REQUIRED 11)
include(GNUInstallDirs)
# Add an include directory like so if desired
#include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
# Enable Warnings
if(MSVC)
# Force to always compile with W4
if(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
endif()
else() #if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-switch -Wno-unknown-pragmas")
endif()
# Add libicsneo, usually a git submodule within your project works well
#add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../third-party/libicsneo ${CMAKE_CURRENT_BINARY_DIR}/third-party/libicsneo)
add_executable(libicsneocpp-simple-example src/SimpleExample.cpp)
target_link_libraries(libicsneocpp-simple-example icsneocpp)
-2
View File
@@ -1,2 +0,0 @@
add_executable(libicsneocpp-vsa-example src/VSAExample.cpp)
target_link_libraries(libicsneocpp-vsa-example icsneocpp)
-251
View File
@@ -1,251 +0,0 @@
#include <iostream>
#include <random>
#include "icsneo/icsneocpp.h"
enum class MessageType {
ShortEth,
LongEth,
CAN,
CANFD
};
const std::vector<std::string> MessageTypeLabels = {"short Ethernet", "long Ethernet", "CAN", "CAN-FD"};
void onEvent(std::shared_ptr<icsneo::APIEvent> event) {
std::cout << event->describe() << std::endl;
}
std::vector<std::shared_ptr<icsneo::Frame>> constructRandomFrames(size_t frameCount, MessageType frameType) {
static constexpr size_t ClassicCANSize = 8;
static constexpr size_t CANFDSize = 64;
static constexpr size_t ShortEthSize = 500;
static constexpr size_t LongEthSize = 1500;
std::vector<std::shared_ptr<icsneo::Frame>> frames;
std::random_device randDev;
std::mt19937 randEngine(randDev());
std::uniform_int_distribution randByteDist(0,255);
auto randByteGen = [&]() -> uint8_t {
return static_cast<uint8_t>(randByteDist(randEngine));
};
for(size_t i = 0; i < frameCount; i++) {
switch(frameType) {
case MessageType::ShortEth:
// Short Ethernet
{
auto frame = std::make_shared<icsneo::EthernetMessage>();
frame->network = icsneo::Network::NetID::Ethernet;
frames.push_back(frame);
frame->data.resize(ShortEthSize);
std::generate(frame->data.begin(), frame->data.end(), randByteGen);
}
break;
case MessageType::LongEth:
// Long Ethernet
{
auto frame = std::make_shared<icsneo::EthernetMessage>();
frame->network = icsneo::Network::NetID::Ethernet;
frames.push_back(frame);
frame->data.resize(LongEthSize);
std::generate(frame->data.begin(), frame->data.end(), randByteGen);
}
break;
case MessageType::CAN:
// Classic CAN
{
auto frame = std::make_shared<icsneo::CANMessage>();
frame->network = icsneo::Network::NetID::HSCAN2;
frames.push_back(frame);
frame->data.resize(ClassicCANSize);
std::generate(frame->data.begin(), frame->data.end(), randByteGen);
}
break;
case MessageType::CANFD:
// CAN FD
{
auto frame = std::make_shared<icsneo::CANMessage>();
frame->network = icsneo::Network::NetID::HSCAN3;
frames.push_back(frame);
frame->data.resize(CANFDSize);
std::generate(frame->data.begin(), frame->data.end(), randByteGen);
frame->isCANFD = true;
}
break;
}
}
return frames;
}
void resetScriptStatus(std::shared_ptr<icsneo::Device> rxDevice, std::shared_ptr<icsneo::Device> txDevice, bool rxInit, bool txInit) {
if(rxInit) {
rxDevice->startScript();
} else {
rxDevice->stopScript();
}
if(txInit) {
txDevice->startScript();
} else {
txDevice->stopScript();
}
}
int main(int argc, char* argv[]) {
if(argc != 3) {
std::cout << "Usage: libicsneocpp-vsa-example <Tx device serial> <Rx device serial>" << std::endl;
return -1;
}
std::string txSerial = argv[1];
std::string rxSerial = argv[2];
// register an event callback so we can see all logged events
icsneo::EventManager::GetInstance().addEventCallback(icsneo::EventCallback(onEvent));
auto devices = icsneo::FindAllDevices();
if(devices.empty()) {
std::cout << "error: no devices found" << std::endl;
return -1;
}
std::shared_ptr<icsneo::Device> txDevice;
std::shared_ptr<icsneo::Device> rxDevice;
for(auto&& d : devices) {
if(txSerial == d->getSerial()) {
txDevice = d;
}
if(rxSerial == d->getSerial()) {
rxDevice = d;
}
}
if(!txDevice) {
std::cout << "error: failed to find a device with serial number: " << txSerial << std::endl;
return -1;
}
if(!rxDevice) {
std::cout << "error: failed to find a device with serial number: " << rxSerial << std::endl;
return -1;
}
std::cout << "info: found " << txDevice->describe() << std::endl;
std::cout << "info: found " << rxDevice->describe() << std::endl;
if(!txDevice->open()) {
std::cout << "error: unable to open device" << std::endl;
}
if(!rxDevice->open()) {
std::cout << "error: unable to open device" << std::endl;
}
const auto& rxInitialCoreminiStatus = rxDevice->getScriptStatus()->isCoreminiRunning;
const auto& txInitialCoreminiStatus = txDevice->getScriptStatus()->isCoreminiRunning;
rxDevice->stopScript();
txDevice->stopScript();
uint64_t origFirstOffset;
std::shared_ptr<icsneo::VSA> origFirstRecord;
if(!rxDevice->findFirstVSARecord(origFirstOffset, origFirstRecord)) {
std::cout << "error: unable to find first VSA record" << std::endl;
resetScriptStatus(rxDevice, txDevice, rxInitialCoreminiStatus, txInitialCoreminiStatus);
return -1;
}
std::cout << "info: found first VSA record at " << origFirstOffset << std::endl;
uint64_t origLastOffset;
std::shared_ptr<icsneo::VSA> origLastRecord;
if(!rxDevice->findLastVSARecord(origLastOffset, origLastRecord)) {
std::cout << "error: unable to find last VSA record" << std::endl;
resetScriptStatus(rxDevice, txDevice, rxInitialCoreminiStatus, txInitialCoreminiStatus);
return -1;
}
std::cout << "info: found last VSA record at " << origLastOffset << std::endl;
uint64_t canFrameCount = 0;
uint64_t ethFrameCount = 0;
rxDevice->addMessageCallback(std::make_shared<icsneo::MessageCallback>([&](std::shared_ptr<icsneo::Message> msg) {
if(msg->type != icsneo::Message::Type::Frame) {
return;
}
const auto frame = std::static_pointer_cast<icsneo::Frame>(msg);
if(frame->network.getType() == icsneo::Network::Type::CAN) {
++canFrameCount;
} else if(frame->network.getType() == icsneo::Network::Type::Ethernet) {
++ethFrameCount;
}
}));
icsneo::VSAExtractionSettings settings;
{
auto& filter = settings.filters.emplace_back();
filter.readRange.first = origLastRecord->getTimestampICSClock() - std::chrono::seconds(20);
filter.readRange.second = origLastRecord->getTimestampICSClock() - std::chrono::seconds(10);
}
{
auto& filter = settings.filters.emplace_back();
filter.readRange.first = origFirstRecord->getTimestampICSClock() + std::chrono::seconds(0);
filter.readRange.second = origFirstRecord->getTimestampICSClock() + std::chrono::seconds(10);
}
std::cout << "info: reading two blocks of VSA, 10s from the start and 10s from the end..." << std::endl;
if(!rxDevice->readVSA(settings)) {
std::cout << "error: unable to read VSA" << std::endl;
resetScriptStatus(rxDevice, txDevice, rxInitialCoreminiStatus, txInitialCoreminiStatus);
return -1;
}
std::cout << "info: processed " << canFrameCount << " CAN frames and " << ethFrameCount << " Ethernet frames" << std::endl;
rxDevice->startScript();
txDevice->goOnline();
const uint8_t NumFrameTypes = 4;
const size_t FrameCountPerType = 2500;
std::vector<std::shared_ptr<icsneo::Frame>> frames;
for(uint8_t i = 0; i < NumFrameTypes; i++) {
std::cout << "info: transmitting " << FrameCountPerType << " random " << MessageTypeLabels[i] << " frames" << std::endl;
auto tempFrames = constructRandomFrames(FrameCountPerType, static_cast<MessageType>(i));
frames.insert(frames.end(), tempFrames.begin(), tempFrames.end());
if(!txDevice->transmit(tempFrames)) {
std::cout << "error: failed to transmit frames" << std::endl;
resetScriptStatus(rxDevice, txDevice, rxInitialCoreminiStatus, txInitialCoreminiStatus);
return -1;
}
std::this_thread::sleep_for(std::chrono::milliseconds(600));
}
size_t currentMessage = 0;
rxDevice->addMessageCallback(std::make_shared<icsneo::MessageCallback>([&](std::shared_ptr<icsneo::Message> msg) {
if(msg->type != icsneo::Message::Type::Frame) {
return;
}
auto frame = std::static_pointer_cast<icsneo::Frame>(msg);
if(frames[currentMessage]->data == frame->data) {
currentMessage++;
}
}));
// Read from original last frame until end of buffer
icsneo::VSAExtractionSettings transmitSettings;
{
auto& filter = transmitSettings.filters.emplace_back();
filter.readRange.first = origLastRecord->getTimestampICSClock();
}
std::cout << "info: reading transmitted random frames..." << std::endl;
if(!rxDevice->readVSA(transmitSettings)) {
std::cout << "error: unable to read VSA" << std::endl;
resetScriptStatus(rxDevice, txDevice, rxInitialCoreminiStatus, txInitialCoreminiStatus);
return -1;
}
std::cout << "info: " << currentMessage << " transmitted frames found" << std::endl;
resetScriptStatus(rxDevice, txDevice, rxInitialCoreminiStatus, txInitialCoreminiStatus);
if(currentMessage != FrameCountPerType * NumFrameTypes) {
std::cout << "error: unable to find all transmitted frames" << std::endl;
return -1;
}
return 0;
}
+727 -727
View File
File diff suppressed because it is too large Load Diff
+1
View File
@@ -1,3 +1,4 @@
package com.example.icsneojava;
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
* Version 4.0.0
+10 -12
View File
@@ -49,7 +49,6 @@ public:
ValueNotYetPresent = 0x1013,
Timeout = 0x1014,
WiVINotSupported = 0x1015,
RestrictedEntryFlag = 0x1016,
// Device Events
PollingMessageOverflow = 0x2000,
@@ -105,8 +104,6 @@ public:
LiveDataEncoderError = 0x2050,
LiveDataDecoderError = 0x2051,
LiveDataNotSupported = 0x2052,
LINSettingsNotAvailable = 0x2053,
ModeNotFound = 0x2054,
// Transport Events
FailedToRead = 0x3000,
@@ -125,6 +122,11 @@ public:
GetIfAddrsError = 0x3108,
SendToError = 0x3109,
MDIOMessageExceedsMaxLength = 0x3110,
DriverTTYPathEmpty = 0x3120,
DriverWasNotNegOne = 0x3121,
DriverTCGetAddrFail = 0x3122,
DriverTCSetAddrFail = 0x3123,
// FTD3XX
FTOK = 0x4000, // placeholder
@@ -161,19 +163,15 @@ public:
FTIncorrectDevicePath = FTOK + 31,
FTOtherError = FTOK + 32,
// VSA
VSABufferCorrupted = 0x5000,
VSATimestampNotFound = VSABufferCorrupted + 1,
VSABufferFormatError = VSABufferCorrupted + 2,
VSAMaxReadAttemptsReached = VSABufferCorrupted + 3,
VSAByteParseFailure = VSABufferCorrupted + 4,
VSAExtendedMessageError = VSABufferCorrupted + 5,
VSAOtherError = VSABufferCorrupted + 6,
// Android USB
AndroidUSBLibusbInitFailed = 0x5000,
AndroidUSBFDWrapFailed = 0x5001,
NoErrorFound = 0xFFFFFFFD,
TooManyEvents = 0xFFFFFFFE,
Unknown = 0xFFFFFFFF
Unknown = 0xFFFFFFFF,
};
enum class Severity : uint8_t {
Any = 0, // Used for filtering, should not appear in data
EventInfo = 0x10,
+1 -2
View File
@@ -31,7 +31,6 @@ enum class Command : uint8_t {
GetVBattReq = 0xDF, // Previously known as RED_CMD_VBATT_REQUEST
ScriptStatus = 0xE0, // Previously known as RED_CMD_SCRIPT_STATUS
MiscControl = 0xE7,
NeoEraseMemory = 0xEA, // Previously known as RED_CMD_ERASE_MEMORY
Extended = 0xF0, // Previously known as RED_CMD_EXT_COMM
ExtendedData = 0xF2, // Previously known as RED_CMD_EXTENDED_DATA
FlexRayControl = 0xF3,
@@ -52,7 +51,7 @@ enum class ExtendedCommand : uint16_t {
GetSupportedFeatures = 0x0018,
GetComponentVersions = 0x001A,
Reboot = 0x001C,
SetRootFSEntryFlags = 0x0027,
SetUploadedFlag = 0x0027,
GenericBinaryInfo = 0x0030,
LiveData = 0x0035,
};
+3 -4
View File
@@ -66,7 +66,7 @@ public:
bool removeMessageCallback(int id);
std::shared_ptr<Message> waitForMessageSync(
const std::shared_ptr<MessageFilter>& f = {},
std::chrono::milliseconds timeout = std::chrono::milliseconds(500)) {
std::chrono::milliseconds timeout = std::chrono::milliseconds(50)) {
return waitForMessageSync([](){ return true; }, f, timeout);
}
// onceWaitingDo is a way to avoid race conditions.
@@ -74,9 +74,7 @@ public:
std::shared_ptr<Message> waitForMessageSync(
std::function<bool(void)> onceWaitingDo,
const std::shared_ptr<MessageFilter>& f = {},
std::chrono::milliseconds timeout = std::chrono::milliseconds(500));
void dispatchMessage(const std::shared_ptr<Message>& msg);
std::chrono::milliseconds timeout = std::chrono::milliseconds(50));
std::function<std::unique_ptr<Packetizer>()> makeConfiguredPacketizer;
std::unique_ptr<Packetizer> packetizer;
@@ -95,6 +93,7 @@ protected:
std::mutex redirectingReadMutex; // Don't allow read to be disabled while in the redirectionFn
std::mutex syncMessageMutex;
void dispatchMessage(const std::shared_ptr<Message>& msg);
void handleInput(Packetizer& p, std::vector<uint8_t>& readBytes);
private:
@@ -29,10 +29,10 @@ public:
if(message->type == Message::Type::Frame || message->type == Message::Type::Main51 ||
message->type == Message::Type::RawMessage || message->type == Message::Type::ReadSettings) {
const auto frame = std::static_pointer_cast<RawMessage>(message);
if(!matchNetworkType(frame->network.getType()))
RawMessage& frame = *static_cast<RawMessage*>(message.get());
if(!matchNetworkType(frame.network.getType()))
return false;
if(!matchNetID(frame->network.getNetID()))
if(!matchNetID(frame.network.getNetID()))
return false;
} else if (netid != Network::NetID::Any || networkType != Network::Type::Any) {
return false; // Filtering on a NetID or Type, but this message doesn't have one
@@ -13,9 +13,6 @@ namespace icsneo {
typedef uint16_t icscm_bitfield;
#pragma pack(push, 2)
struct HardwareA2BPacket {
static std::shared_ptr<Message> DecodeToMessage(const std::vector<uint8_t>& bytestream);
@@ -36,21 +33,12 @@ struct HardwareA2BPacket {
icscm_bitfield : 11;
icscm_bitfield rfu2;
} header;
uint8_t offset[8];
uint16_t stats;
struct {
uint64_t TS : 60;
uint64_t : 3; // Reserved for future status bits
uint64_t IsExtended : 1;
} timestamp;
uint16_t networkID;
uint16_t length;
static const size_t coreMiniMessageHeaderSize;
static const size_t a2bMessageMaxLength;
static const size_t a2bHeaderSize;
};
#pragma pack(pop)
}
#endif // __cplusplus
+3 -223
View File
@@ -43,8 +43,6 @@
#include "icsneo/communication/message/ethphymessage.h"
#include "icsneo/third-party/concurrentqueue/concurrentqueue.h"
#include "icsneo/platform/nodiscard.h"
#include "icsneo/disk/vsa/vsa.h"
#include "icsneo/disk/vsa/vsaparser.h"
#define ICSNEO_FINDABLE_DEVICE_BASE(className, type) \
static constexpr DeviceType::Enum DEVICE_TYPE = type; \
@@ -59,13 +57,6 @@
#define ICSNEO_FINDABLE_DEVICE_BY_PID(className, type, pid) \
static constexpr const uint16_t PRODUCT_ID = pid; \
ICSNEO_FINDABLE_DEVICE_BASE(className, type)
// Devices which are discernable by a serial range
#define ICSNEO_FINDABLE_DEVICE_BY_SERIAL_RANGE(className, type, serialLow, serialHigh) \
static constexpr const char* SERIAL_RANGE_LOW = serialLow; \
static constexpr const char* SERIAL_RANGE_HIGH = serialHigh; \
ICSNEO_FINDABLE_DEVICE_BASE(className, type)
namespace icsneo {
class DeviceExtension;
@@ -157,11 +148,9 @@ public:
int8_t prepareScriptLoad();
bool startScript(Disk::MemoryType memType = Disk::MemoryType::SD);
bool stopScript();
bool clearScript(Disk::MemoryType memType = Disk::MemoryType::SD);
bool clearScript();
bool uploadCoremini(std::unique_ptr<std::istream>&& stream, Disk::MemoryType memType = Disk::MemoryType::SD);
bool eraseScriptMemory(Disk::MemoryType memType, uint64_t amount);
virtual std::optional<MemoryAddress> getCoreminiStartAddressFlash() const {
return std::nullopt;
}
@@ -424,16 +413,6 @@ public:
IsEncrypted = 16,
};
enum RootDirectoryEntryFlags : uint8_t {
IsPrePost = 1,
PrePostTriggered = (1 << 1),
UploadPriority = (1 << 2) | (1 << 3),
CellularEnabled = (1 << 4),
WiFiEnabled = (1 << 5),
Uploaded = (1 << 6),
Unused = (1 << 7)
};
typedef std::function< void(uint64_t value) > ScriptStatusCallback;
/**
@@ -589,20 +568,8 @@ public:
std::optional<EthPhyMessage> sendEthPhyMsg(const EthPhyMessage& message, std::chrono::milliseconds timeout = std::chrono::milliseconds(50));
/**
* Set the flags of the root directory entry specified at given address
*
* Will not allow changes of IsPrePost and PrePostTriggered flags and will produce a warning
* if there is an attempt to do so
*
* @param mask Flags to set, with each bit representing a different entry flag @RootDirectoryEntryFlags
* @param values The values in which to set each flag, each bit corresponding to the flag in the same position
* @param collectionEntryByteAddress The position of the root directory entry in which to set these flags
* @return Success or failure
*/
std::optional<bool> SetRootDirectoryEntryFlags(uint8_t mask, uint8_t values, uint32_t collectionEntryByteAddress);
std::optional<bool> SetCollectionUploaded(uint32_t collectionEntryByteAddress);
std::shared_ptr<Communication> com;
std::unique_ptr<IDeviceSettings> settings;
@@ -612,103 +579,6 @@ public:
bool unsubscribeLiveData(const LiveDataHandle& handle);
bool clearAllLiveData();
// VSA Read functions
/**
* Read VSA message records from disk and dispatch the messages via Communication object. Default behavior excludes
* records older than the current CoreMini script and performs a full disk dump of other records. The CoreMini script is
* also stopped by default.
*
* @param extractionSettings Contains filters and other advanced settings for extraction process
*
* @return Returns false if there were failures during the read or parse processes or issues with record formatting, else true
*/
bool readVSA(const VSAExtractionSettings& extractionSettings = VSAExtractionSettings());
/**
* Determines important metadata about VSA record storage on the disk. Terminates at first failed attempt to retrieve information
*
* @param metadata The metadata object to store the probed information into
* @param extractionSettings The settings for this extraction of VSA data
*
* @return True if all metadata information was successfully found
*/
bool probeVSA(VSAMetadata& metadata, const VSAExtractionSettings& extractionSettings);
/**
* Find the first VSA record chronologically from ring buffer in the VSA log file on disk
*
* @param firstOffset Variable used to pass out offset of first record on the disk
* @param firstRecord Variable used to pass out the first record in the buffer
* @param extractionSettings The settings for this extraction of VSA data
* @param optMetadata Metadata about the current state of the VSA log file
* (Must include valid CoreMini timestamp, disk size, and isOverlapped values)
*
* @return True if the first record was found successfully
*/
bool findFirstVSARecord(uint64_t& firstOffset, std::shared_ptr<VSA>& firstRecord,
const VSAExtractionSettings& extractionSettings = VSAExtractionSettings(), std::optional<VSAMetadata> optMetadata = std::nullopt);
/**
* Find the last record chronologically from ring buffer in the VSA log file with a valid timestamp
*
* @param lastOffset Variable used to pass out the offset of the last record on the disk
* @param lastRecord Variable used to pass out the last record with a valid timestamp
* @param extractionSettings The settings for this extraction of VSA data
* @param optMetadata Metadata about the current state of the VSA log file
* (Must include valid CoreMini timestamp, disk size, and isOverlapped values)
*
* @return True if the last record was found successfully
*/
bool findLastVSARecord(uint64_t& lastOffset, std::shared_ptr<VSA>& lastRecord,
const VSAExtractionSettings& extractionSettings = VSAExtractionSettings(), std::optional<VSAMetadata> optMetadata = std::nullopt);
/**
* Find the closest VSA record to the desired time_point
*
* @param point The desired time_point of the record
* @param vsaOffset Variable used to pass out offset of record closest to the desired time_point
* @param record Variable used to pass out the record closest to the desired time_point
* @param extractionSettings Settings for this extraction of VSA data
* @param optMetadata Optional param to include metadata about the VSA log file on disk
*
* @return Pair containing the location of the record closest to the desired time_point (in bytes from the beginning of VSA log file) and the record itself
*/
bool findVSAOffsetFromTimepoint(
ICSClock::time_point point, uint64_t& vsaOffset, std::shared_ptr<VSA>& record, const VSAExtractionSettings& extractionSettings = VSAExtractionSettings(),
std::optional<VSAMetadata> optMetadata = std::nullopt);
/**
* Parse VSA message records with the given filter and dispatch them with this device's com channel
*
* @param metadata Important information about the VSA logfile (including first record location)
* @param extractionSettings Settings for this extraction of VSA data
* @param filter Struct used to determine which bytes to read and to filter out undesired VSA records
*
* @return True if there were no failures reading from disk, parsing VSA records, or dispatching VSA records
*/
bool parseVSA(
VSAMetadata& metadata, const VSAExtractionSettings& extractionSettings = VSAExtractionSettings(),
const VSAMessageReadFilter& filter = VSAMessageReadFilter());
/**
* Wrapper function for Device::readLogicalDisk(pos, into, amount, ...) that handles the VSA record ring buffer.
* Handles pos that is before the VSA::RecordStartOffset or is larger than the diskSize.
* Sets amount to maximum size of ring buffer if given amount is too large.
*
* @param pos Position to start read from in relation to VSA file start
* @param into The buffer to read bytes into from the disk
* @param amount The number of bytes to read into the buffer
* @param metadata Optional metadata param (used to determine disk size and if disk is overlapped)
*
* @return Returns value of return from readLogicalDisk with the given inputs
*/
std::optional<uint64_t> vsaReadLogicalDisk(
uint64_t pos, uint8_t* into, uint64_t amount, std::optional<VSAMetadata> metadata = std::nullopt
);
virtual bool isOnlineSupported() const { return true; }
protected:
bool online = false;
int messagePollingCallbackID = 0;
@@ -886,96 +756,6 @@ private:
void scriptStatusThreadBody();
void stopScriptStatusThreadIfNecessary(std::unique_lock<std::mutex> lk);
// VSA Read functions
/**
* Read the timestamp from disk of the VSA record stored at pos. If the timestamp is unparsable, attempt to read from
* previous records up to minPos
*
* @param parser The parser that is used to create a VSA record from the given buffer
* @param buffer Vector of bytes that stores a sector from the disk
* @param pos The location that the buffer was read from
* @param minPos The leftmost (minimum) offset from the beginning of the VSA log file to attempt to read from
* @param optMetadata Optional param to include metadata about the VSA log file on disk
*
* @return The timestamp of the first valid record found at or before the given position
*/
std::optional<uint64_t> getVSATimestampOrBefore(VSAParser& parser, std::vector<uint8_t>& buffer, uint64_t pos, uint64_t minPos,
std::optional<VSAMetadata> optMetadata = std::nullopt);
/**
* Read the timestamp from disk of the VSA record stored at pos. If the timestamp is unparsable, attempt to read from
* previous records up to maxPos
*
* @param parser The parser that is used to create a VSA record from the given buffer
* @param buffer Vector of bytes that stores a sector that was previously read from the disk
* @param pos The location that data in the buffer was read from
* @param maxPos The rightmost (maximum) offset from the beginning of the VSA log file to attempt to read from
* @param optMetadata Optional param to include metadata about the VSA log file on disk
*
* @return The timestamp of the first valid record found at or after the given position
*/
std::optional<uint64_t> getVSATimestampOrAfter(VSAParser& parser, std::vector<uint8_t>& buffer, uint64_t pos, uint64_t maxPos,
std::optional<VSAMetadata> optMetadata = std::nullopt);
/**
* Iterate over VSA records and dispatch the messages contained within them. For extended message records, we concatenate the payloads of all of
* the records together before dispatching. Dispatch is performed by Communication::dispatchMessage(...).
*
* @param parser The parser that holds the VSAMessage records to be dispatched
*
* @return True if dispatching of records is successful without unhandled issues from record parse, else false
*/
bool dispatchVSAMessages(VSAParser& parser);
/**
* Determine if the ring buffer for VSA records has filled entirely and looped to the beginning.
*
* @param optMetadata Optional metadata param with partial information about current state of VSA log file
* (Must contain valid disk size and CoreMini timestamp)
*
* @return True if the buffer has looped; Returns std::nullopt if unable to determine
*/
std::optional<bool> isVSAOverlapped(std::optional<VSAMetadata> optMetadata = std::nullopt);
/**
* Find the first extended message record in the sequence of the given extended message record by backtracking in the disk.
* Results are returned by reference (not through the return value)
*
* @param record The extended message record whose sequence for which to find the first record
* @param pos The position of the given record in the VSA log file (in bytes)
* @param parser Used to parse indices and sequence numbers from the extended message records
* @param metadata Optional param to include metadata about the VSA log file on disk
*
* @return True if the first extended message record in the sequence was successfully found
*/
bool findFirstExtendedVSAFromConsecutive(std::shared_ptr<VSAExtendedMessage>& record, uint64_t& pos,
VSAParser& parser, std::optional<VSAMetadata> metadata = std::nullopt);
/**
* Find the first record before the given position that contains a valid timestamp. Results are returned by reference.
*
* @param record The record from which to backtrack in the VSA buffer
* @param pos The position of the given record in the VSA log file (in bytes)
* @param parser Used to parse records from the VSA buffer
*
* @return True if a record with valid timestamp is found within a set number of reads
*/
bool findPreviousRecordWithTimestamp(std::shared_ptr<VSA>& record, uint64_t& pos, VSAParser& parser);
/**
* Get the creation timestamp of the CoreMini script from VSA log file
*
* @return Timestamp in 25 nanosecond ticks since January 1, 2007
*/
std::optional<uint64_t> getCoreMiniScriptTimestamp();
/**
* Get the size of the VSA file storage system from the CoreMini script
*
* @return The size of the vsa log files on the disk
*/
std::optional<uint64_t> getVSADiskSize();
};
}
+4 -62
View File
@@ -536,15 +536,15 @@ enum
BPS117647
};
/* CommanderResistor in LIN_SETTINGS */
enum : uint8_t
/* MasterResistor in LIN_SETTINGS */
enum
{
RESISTOR_ON,
RESISTOR_OFF
};
/* Mode in LIN_SETTINGS */
enum LINMode
enum
{
SLEEP_MODE,
SLOW_MODE,
@@ -558,7 +558,7 @@ typedef struct _LIN_SETTINGS
uint16_t spbrg; /* Precompiled to be 40Mhz/Baudrate/16 - 1. Only used in neoVI FIRE/FIREVNET(4dw) */
uint8_t brgh; /* Must be zero */
uint8_t numBitsDelay;
uint8_t CommanderResistor;
uint8_t MasterResistor;
uint8_t Mode;
} LIN_SETTINGS;
#define LIN_SETTINGS_SIZE 10
@@ -643,7 +643,6 @@ public:
static std::optional<uint16_t> CalculateGSChecksum(const std::vector<uint8_t>& settings, std::optional<size_t> knownSize = std::nullopt);
static CANBaudrate GetEnumValueForBaudrate(int64_t baudrate);
static int64_t GetBaudrateValueForEnum(CANBaudrate enumValue);
static bool ValidateLINBaudrate(int64_t baudrate);
IDeviceSettings(std::shared_ptr<Communication> com, size_t size) : com(com), report(com->report), structSize(size) {}
virtual ~IDeviceSettings() {}
@@ -701,16 +700,6 @@ public:
return reinterpret_cast<SWCAN_SETTINGS*>((void*)(settings.data() + (offset - settingsInDeviceRAM.data())));
}
virtual const LIN_SETTINGS* getLINSettingsFor(Network net) const { (void)net; return nullptr; }
LIN_SETTINGS* getMutableLINSettingsFor(Network net) {
if(disabled || readonly)
return nullptr;
const uint8_t* offset = (const uint8_t*)getLINSettingsFor(net);
if(offset == nullptr)
return nullptr;
return reinterpret_cast<LIN_SETTINGS*>((void*)(settings.data() + (offset - settingsInDeviceRAM.data())));
}
/**
* Some devices have groupings of networks, where software
* switchable termination can only be applied to one network
@@ -764,53 +753,6 @@ public:
*/
bool setTerminationFor(Network net, bool enabled);
/**
* Check whether software switchable commander resistor is currently
* enabled for a given network in the currently active device settings.
*
* Returns true if the call was successful, otherwise an error
* will have been reported in icsneo::getLastError().
*/
std::optional<bool> isCommanderResistorEnabledFor(Network net) const;
/**
* Enable or disable software switchable commander resistor for a given
* network.
*
* Returns true if the call was successful, otherwise an error
* will have been reported in icsneo::getLastError().
*/
bool setCommanderResistorFor(Network net, bool resistor_on);
/**
* Get LIN mode for a given network in the currently active device
* settings.
*/
std::optional<enum LINMode> getLINModeFor(Network net) const;
/**
* Set LIN mode for a given network.
*
* Returns true if the call was successful, otherwise an error
* will have been reported in icsneo::getLastError().
*/
bool setLINModeFor(Network net, enum LINMode mode);
/**
* Get number of bit delays between commander ID and first responder byte for
* a given network in the currently active device settings.
*/
std::optional<uint8_t> getLINCommanderResponseTimeFor(Network net) const;
/**
* Set number of bit delays between commander ID and first responder byte for
* a given network
*
* Returns true if the call was successful, otherwise an error
* will have been reported in icsneo::getLastError().
*/
bool setLINCommanderResponseTimeFor(Network net, uint8_t bits);
const void* getRawStructurePointer() const { return settingsInDeviceRAM.data(); }
void* getMutableRawStructurePointer() { return settings.data(); }
template<typename T> const T* getStructurePointer() const { return reinterpret_cast<const T*>(getRawStructurePointer()); }
@@ -88,17 +88,6 @@ public:
return nullptr;
}
}
const LIN_SETTINGS* getLINSettingsFor(Network net) const override {
auto cfg = getStructurePointer<etherbadge_settings_t>();
if(cfg == nullptr)
return nullptr;
switch(net.getNetID()) {
case Network::NetID::LIN:
return &(cfg->lin1);
default:
return nullptr;
}
}
};
}
@@ -131,23 +131,6 @@ public:
return nullptr;
}
}
const LIN_SETTINGS* getLINSettingsFor(Network net) const override {
auto cfg = getStructurePointer<neovifire_settings_t>();
if(cfg == nullptr)
return nullptr;
switch(net.getNetID()) {
case Network::NetID::LIN:
return &(cfg->lin1);
case Network::NetID::LIN2:
return &(cfg->lin2);
case Network::NetID::LIN3:
return &(cfg->lin3);
case Network::NetID::LIN4:
return &(cfg->lin4);
default:
return nullptr;
}
}
};
}
@@ -6,7 +6,7 @@
#include "icsneo/device/device.h"
#include "icsneo/device/devicetype.h"
#include "icsneo/device/tree/neovifire2/neovifire2settings.h"
#include "icsneo/disk/neomemorydiskdriver.h"
namespace icsneo {
class NeoVIFIRE2 : public Device {
@@ -89,7 +89,7 @@ public:
protected:
NeoVIFIRE2(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) {
initialize<NeoVIFIRE2Settings, Disk::NeoMemoryDiskDriver, Disk::NeoMemoryDiskDriver>(makeDriver);
initialize<NeoVIFIRE2Settings>(makeDriver);
}
void setupSettings(IDeviceSettings& ssettings) override {
@@ -209,28 +209,6 @@ public:
};
}
const LIN_SETTINGS* getLINSettingsFor(Network net) const override {
auto cfg = getStructurePointer<neovifire2_settings_t>();
if(cfg == nullptr)
return nullptr;
switch(net.getNetID()) {
case Network::NetID::LIN:
return &(cfg->lin1);
case Network::NetID::LIN2:
return &(cfg->lin2);
case Network::NetID::LIN3:
return &(cfg->lin3);
case Network::NetID::LIN4:
return &(cfg->lin4);
case Network::NetID::LIN5:
return &(cfg->lin5);
case Network::NetID::LIN6:
return &(cfg->lin6);
default:
return nullptr;
}
}
protected:
ICSNEO_UNALIGNED(const uint64_t*) getTerminationEnables() const override {
auto cfg = getStructurePointer<neovifire2_settings_t>();
@@ -229,32 +229,6 @@ public:
};
}
const LIN_SETTINGS* getLINSettingsFor(Network net) const override {
auto cfg = getStructurePointer<neovifire3_settings_t>();
if(cfg == nullptr)
return nullptr;
switch(net.getNetID()) {
case Network::NetID::LIN:
return &(cfg->lin1);
case Network::NetID::LIN2:
return &(cfg->lin2);
case Network::NetID::LIN3:
return &(cfg->lin3);
case Network::NetID::LIN4:
return &(cfg->lin4);
case Network::NetID::LIN5:
return &(cfg->lin5);
case Network::NetID::LIN6:
return &(cfg->lin6);
case Network::NetID::LIN7:
return &(cfg->lin7);
case Network::NetID::LIN8:
return &(cfg->lin8);
default:
return nullptr;
}
}
protected:
ICSNEO_UNALIGNED(const uint64_t*) getTerminationEnables() const override {
auto cfg = getStructurePointer<neovifire3_settings_t>();
@@ -212,24 +212,6 @@ public:
};
}
const LIN_SETTINGS* getLINSettingsFor(Network net) const override {
auto cfg = getStructurePointer<neovifire3flexray_settings_t>();
if(cfg == nullptr)
return nullptr;
switch(net.getNetID()) {
case Network::NetID::LIN:
return &(cfg->lin1);
case Network::NetID::LIN2:
return &(cfg->lin2);
case Network::NetID::LIN3:
return &(cfg->lin3);
case Network::NetID::LIN4:
return &(cfg->lin4);
default:
return nullptr;
}
}
protected:
ICSNEO_UNALIGNED(const uint64_t*) getTerminationEnables() const override {
auto cfg = getStructurePointer<neovifire3flexray_settings_t>();
@@ -170,20 +170,6 @@ public:
};
}
const LIN_SETTINGS* getLINSettingsFor(Network net) const override {
auto cfg = getStructurePointer<neovired2_settings_t>();
if(cfg == nullptr)
return nullptr;
switch(net.getNetID()) {
case Network::NetID::LIN:
return &(cfg->lin1);
case Network::NetID::LIN2:
return &(cfg->lin2);
default:
return nullptr;
}
}
protected:
ICSNEO_UNALIGNED(const uint64_t*) getTerminationEnables() const override {
auto cfg = getStructurePointer<neovired2_settings_t>();
@@ -33,8 +33,7 @@ typedef struct {
struct
{
uint16_t hwComLatencyTestEn : 1;
uint16_t disableUsbCheckOnBoot : 1;
uint16_t : 14;
uint16_t : 15;
} flags;
uint16_t network_enabled_on_boot;
CAN_SETTINGS can1;
@@ -57,15 +56,11 @@ typedef struct {
uint32_t pwr_man_timeout;
uint16_t pwr_man_enable;
ETHERNET_SETTINGS2 ethernet;
RAD_GPTP_SETTINGS gPTP;
uint64_t network_enables_5;
} rada2b_settings_t;
#pragma pack(pop)
#ifdef __cplusplus
static_assert(sizeof(rada2b_settings_t) == 340, "RAD-A2B settings size mismatch");
#include <iostream>
class RADA2BSettings : public IDeviceSettings {
@@ -89,8 +84,8 @@ public:
};
enum class ChannelSize : uint8_t {
chSize32 = 0,
chSize16 = 1
chSize16 = 0,
chSize32 = 1
};
enum class RADA2BDevice : uint8_t {
@@ -126,18 +121,6 @@ public:
}
}
const LIN_SETTINGS* getLINSettingsFor(Network net) const override {
auto cfg = getStructurePointer<rada2b_settings_t>();
if(cfg == nullptr)
return nullptr;
switch(net.getNetID()) {
case Network::NetID::LIN:
return &(cfg->lin1);
default:
return nullptr;
}
}
TDMMode getTDMMode(RADA2BDevice device) const {
auto cfg = getStructurePointer<rada2b_settings_t>();
auto &deviceSettings = device == RADA2BDevice::Monitor ? cfg->a2b_monitor : cfg->a2b_node;
@@ -153,7 +136,7 @@ public:
auto cfg = getStructurePointer<rada2b_settings_t>();
auto &deviceSettings = device == RADA2BDevice::Monitor ? cfg->a2b_monitor : cfg->a2b_node;
return static_cast<ChannelSize>(deviceSettings.flags & a2bSettingsFlag16bit);
return static_cast<ChannelSize>(~(deviceSettings.flags & a2bSettingsFlag16bit));
}
uint8_t getChannelOffset(RADA2BDevice device, A2BMessage::A2BDirection dir) const {
+47 -9
View File
@@ -3,32 +3,70 @@
#ifdef __cplusplus
#include "icsneo/device/tree/radcomet/radcometbase.h"
#include "icsneo/device/device.h"
#include "icsneo/device/devicetype.h"
#include "icsneo/communication/packetizer.h"
#include "icsneo/communication/decoder.h"
#include "icsneo/device/tree/radcomet/radcometsettings.h"
namespace icsneo {
class RADComet : public RADCometBase {
class RADCOMET : public Device {
public:
// Serial numbers start with RC
// USB PID is 0x1207, standard driver is FTDI3
// Ethernet MAC allocation is 0x1D, standard driver is Raw
ICSNEO_FINDABLE_DEVICE_BY_SERIAL_RANGE(RADComet, DeviceType::RADComet, "RC0000", "RC0299");
ICSNEO_FINDABLE_DEVICE(RADCOMET, DeviceType::RADComet, "RC");
std::string getProductName() const override {
return "RAD-Comet";
static const std::vector<Network>& GetSupportedNetworks() {
static std::vector<Network> supportedNetworks = {
Network::NetID::HSCAN,
Network::NetID::HSCAN2,
Network::NetID::Ethernet,
Network::NetID::OP_Ethernet1,
Network::NetID::OP_Ethernet2,
};
return supportedNetworks;
}
bool getEthPhyRegControlSupported() const override { return true; }
protected:
RADComet(neodevice_t neodevice, const driver_factory_t& makeDriver) : RADCometBase(neodevice) {
initialize<RADCometSettings>(makeDriver);
RADCOMET(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) {
initialize<RADCOMETSettings>(makeDriver);
}
void setupPacketizer(Packetizer& packetizer) override {
Device::setupPacketizer(packetizer);
packetizer.disableChecksum = true;
packetizer.align16bit = false;
}
void setupEncoder(Encoder& encoder) override {
Device::setupEncoder(encoder);
encoder.supportCANFD = true;
encoder.supportEthPhy = true;
}
void setupDecoder(Decoder& decoder) override {
Device::setupDecoder(decoder);
decoder.timestampResolution = 10; // Timestamps are in 10ns increments instead of the usual 25ns
}
void setupSupportedRXNetworks(std::vector<Network>& rxNetworks) override {
for(auto& netid : GetSupportedNetworks())
rxNetworks.emplace_back(netid);
}
// The supported TX networks are the same as the supported RX networks for this device
void setupSupportedTXNetworks(std::vector<Network>& txNetworks) override { setupSupportedRXNetworks(txNetworks); }
};
}
#endif // __cplusplus
#endif
#endif
@@ -1,41 +0,0 @@
#ifndef __RADCOMET2_H_
#define __RADCOMET2_H_
#ifdef __cplusplus
#include "icsneo/device/tree/radcomet/radcometbase.h"
#include "icsneo/device/tree/radcomet/radcometsettings.h"
namespace icsneo {
class RADComet2 : public RADCometBase {
public:
// Serial numbers start with RC, Comet2 starts at RC0300
// USB PID is 0x1207, standard driver is FTDI3
// Ethernet MAC allocation is 0x1D, standard driver is Raw
ICSNEO_FINDABLE_DEVICE_BY_SERIAL_RANGE(RADComet2, DeviceType::RADComet, "RC0300", "RCZZZZ");
std::string getProductName() const override {
return "RAD-Comet 2";
}
const std::vector<Network>& GetSupportedNetworks() override {
static std::vector<Network> supportedNetworks = RADCometBase::GetSupportedNetworks();
supportedNetworks.push_back(Network::NetID::OP_Ethernet3);
supportedNetworks.push_back(Network::NetID::MDIO4);
return supportedNetworks;
}
protected:
RADComet2(neodevice_t neodevice, const driver_factory_t& makeDriver) : RADCometBase(neodevice) {
initialize<RADCometSettings>(makeDriver);
}
};
}
#endif // __cplusplus
#endif
@@ -1,73 +0,0 @@
#ifndef __RADCOMETBASE_H_
#define __RADCOMETBASE_H_
#ifdef __cplusplus
#include "icsneo/device/device.h"
#include "icsneo/device/devicetype.h"
namespace icsneo {
class RADCometBase : public Device {
public:
virtual const std::vector<Network>& GetSupportedNetworks() {
static std::vector<Network> supportedNetworks = {
Network::NetID::HSCAN,
Network::NetID::HSCAN2,
Network::NetID::Ethernet,
Network::NetID::OP_Ethernet1,
Network::NetID::OP_Ethernet2,
Network::NetID::LIN,
Network::NetID::ISO9141,
Network::NetID::MDIO1,
Network::NetID::MDIO2,
Network::NetID::MDIO3,
};
return supportedNetworks;
}
bool getEthPhyRegControlSupported() const override { return true; }
protected:
using Device::Device;
void setupPacketizer(Packetizer& packetizer) override {
Device::setupPacketizer(packetizer);
packetizer.disableChecksum = true;
packetizer.align16bit = false;
}
void setupEncoder(Encoder& encoder) override {
Device::setupEncoder(encoder);
encoder.supportCANFD = true;
encoder.supportEthPhy = true;
}
void setupDecoder(Decoder& decoder) override {
Device::setupDecoder(decoder);
decoder.timestampResolution = 10; // Timestamps are in 10ns increments instead of the usual 25ns
}
void setupSupportedRXNetworks(std::vector<Network>& rxNetworks) override {
for(auto& netid : GetSupportedNetworks())
rxNetworks.emplace_back(netid);
}
// The supported TX networks are the same as the supported RX networks for this device
void setupSupportedTXNetworks(std::vector<Network>& txNetworks) override { setupSupportedRXNetworks(txNetworks); }
std::optional<MemoryAddress> getCoreminiStartAddressFlash() const override {
return 32*1024*1024;
}
};
}
#endif // __cplusplus
#endif
@@ -54,8 +54,6 @@ typedef struct {
// 10T1S
ETHERNET_SETTINGS2 ethT1s2;
ETHERNET10T1S_SETTINGS t1s2;
uint64_t network_enables_5;
LIN_SETTINGS lin1;
} radcomet_settings_t;
#pragma pack(pop)
@@ -63,9 +61,9 @@ typedef struct {
#include <iostream>
class RADCometSettings : public IDeviceSettings {
class RADCOMETSettings : public IDeviceSettings {
public:
RADCometSettings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radcomet_settings_t)) {}
RADCOMETSettings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radcomet_settings_t)) {}
const CAN_SETTINGS* getCANSettingsFor(Network net) const override {
auto cfg = getStructurePointer<radcomet_settings_t>();
if(cfg == nullptr)
@@ -170,18 +170,6 @@ public:
return nullptr;
}
}
const LIN_SETTINGS* getLINSettingsFor(Network net) const override {
auto cfg = getStructurePointer<radgalaxy_settings_t>();
if(cfg == nullptr)
return nullptr;
switch(net.getNetID()) {
case Network::NetID::LIN:
return &(cfg->lin1);
default:
return nullptr;
}
}
};
}
@@ -24,7 +24,7 @@ public:
protected:
RADGigastar(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) {
initialize<RADGigastarSettings>(makeDriver);
initialize<RADGigastarSettings, Disk::ExtExtractorDiskReadDriver, Disk::NeoMemoryDiskDriver>(makeDriver);
}
void setupPacketizer(Packetizer& packetizer) override {
@@ -149,18 +149,6 @@ public:
};
}
const LIN_SETTINGS* getLINSettingsFor(Network net) const override {
auto cfg = getStructurePointer<radgigastar_settings_t>();
if(cfg == nullptr)
return nullptr;
switch(net.getNetID()) {
case Network::NetID::LIN:
return &(cfg->lin1);
default:
return nullptr;
}
}
protected:
ICSNEO_UNALIGNED(const uint64_t*) getTerminationEnables() const override {
auto cfg = getStructurePointer<radgigastar_settings_t>();
@@ -118,17 +118,6 @@ public:
return nullptr;
}
}
const LIN_SETTINGS* getLINSettingsFor(Network net) const override {
auto cfg = getStructurePointer<radjupiter_settings_t>();
if(cfg == nullptr)
return nullptr;
switch(net.getNetID()) {
case Network::NetID::LIN:
return &(cfg->lin1);
default:
return nullptr;
}
}
};
}
@@ -170,18 +170,6 @@ public:
};
}
const LIN_SETTINGS* getLINSettingsFor(Network net) const override {
auto cfg = getStructurePointer<radmars_settings_t>();
if(cfg == nullptr)
return nullptr;
switch(net.getNetID()) {
case Network::NetID::LIN:
return &(cfg->lin1);
default:
return nullptr;
}
}
protected:
ICSNEO_UNALIGNED(const uint64_t*) getTerminationEnables() const override {
auto cfg = getStructurePointer<radmars_settings_t>();
@@ -64,8 +64,6 @@ public:
virtual uint8_t getPhyAddrOrPort() const = 0;
bool isOnlineSupported() const override { return false; }
protected:
using Device::Device;
@@ -25,8 +25,6 @@ public:
bool getEthPhyRegControlSupported() const override { return true; }
bool isOnlineSupported() const override { return false; }
protected:
RADMoon3(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) {
initialize<RADMoon3Settings>(makeDriver);
@@ -104,18 +104,6 @@ public:
return nullptr;
}
}
const LIN_SETTINGS* getLINSettingsFor(Network net) const override {
auto cfg = getStructurePointer<radpluto_settings_t>();
if(cfg == nullptr)
return nullptr;
switch(net.getNetID()) {
case Network::NetID::LIN:
return &(cfg->lin1);
default:
return nullptr;
}
}
};
}
@@ -99,18 +99,6 @@ public:
return nullptr;
}
}
const LIN_SETTINGS* getLINSettingsFor(Network net) const override {
auto cfg = getStructurePointer<radstar2_settings_t>();
if(cfg == nullptr)
return nullptr;
switch(net.getNetID()) {
case Network::NetID::LIN:
return &(cfg->lin1);
default:
return nullptr;
}
}
};
}
@@ -45,18 +45,6 @@ public:
};
}
const LIN_SETTINGS* getLINSettingsFor(Network net) const override {
auto cfg = getStructurePointer<valuecan4_4_2el_settings_t>();
if(cfg == nullptr)
return nullptr;
switch(net.getNetID()) {
case Network::NetID::LIN:
return &(cfg->lin1);
default:
return nullptr;
}
}
protected:
ICSNEO_UNALIGNED(const uint64_t*) getTerminationEnables() const override {
auto cfg = getStructurePointer<valuecan4_4_2el_settings_t>();
@@ -37,18 +37,6 @@ public:
return nullptr;
}
}
const LIN_SETTINGS* getLINSettingsFor(Network net) const override {
auto cfg = getStructurePointer<valuecan4_4_2el_settings_t>();
if(cfg == nullptr)
return nullptr;
switch(net.getNetID()) {
case Network::NetID::LIN:
return &(cfg->lin1);
default:
return nullptr;
}
}
};
}
@@ -59,18 +59,6 @@ public:
};
}
const LIN_SETTINGS* getLINSettingsFor(Network net) const override {
auto cfg = getStructurePointer<valuecan4_4_2el_settings_t>();
if(cfg == nullptr)
return nullptr;
switch(net.getNetID()) {
case Network::NetID::LIN:
return &(cfg->lin1);
default:
return nullptr;
}
}
protected:
ICSNEO_UNALIGNED(const uint64_t*) getTerminationEnables() const override {
auto cfg = getStructurePointer<valuecan4_4_2el_settings_t>();
@@ -27,8 +27,6 @@ public:
return false;
}
bool isOnlineSupported() const override { return false; }
protected:
VividCAN(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) {
initialize<VividCANSettings>(makeDriver);
-313
View File
@@ -1,313 +0,0 @@
#ifndef __VSA_H__
#define __VSA_H__
#ifdef __cplusplus
#include "icsneo/communication/network.h"
#include "icsneo/communication/packet.h"
#include <vector>
#include <memory>
#include <chrono>
#include "stdint.h"
namespace icsneo {
using CaptureBitfield = uint16_t;
static constexpr uint64_t ICSEpochHoursSinceUnix = 13514 * 24; // Number of hours between the start of the Unix epoch and the start of the ICS epoch
static constexpr uint64_t UINT63_MAX = 0x7FFFFFFFFFFFFFFFu;
/**
* Struct that meets Clock format requirements from STL Chrono library.
* Indicates time for for the ICS Epoch (January 1, 2007) in 25 nanosecond ticks.
*/
struct ICSClock {
using rep = uint64_t; // Type for tick count
using period = std::ratio_multiply<std::ratio<25>, std::nano>; // Ratio of tick length to seconds (25 nanoseconds)
using duration = std::chrono::duration<rep, period>; // Type for duration in 25 nanosecond ticks
using time_point = std::chrono::time_point<ICSClock>; // Type for a point in time with respect to ICSClock
static constexpr bool is_steady = true; // This clock does not move backwards
/**
* Get the time_point at the current time with respect to ICSClock
*
* @return Time point at the current time with respect to ICSClock
*/
static time_point now() noexcept
{
return time_point { std::chrono::duration_cast<duration>(std::chrono::system_clock::now().time_since_epoch()) -
std::chrono::hours(ICSEpochHoursSinceUnix) };
}
};
using Timestamp = ICSClock::time_point; // Point in time to start or stop read
class VSA;
/**
* Holds metadata for the VSA log file
*/
struct VSAMetadata {
uint64_t firstRecordLocation = UINT64_MAX; // Location of the record with lowest timestamp in ring buffer
std::shared_ptr<VSA> firstRecord = nullptr; // The record with lowest timestamp
uint64_t lastRecordLocation = UINT64_MAX; // Location of the record with the highest timestamp in ring buffer
std::shared_ptr<VSA> lastRecord = nullptr; // The record with the highest timestamp
uint64_t bufferEnd = UINT64_MAX; // One byte beyond the last byte of the sequence started from lastRecordLocation
uint64_t diskSize = 0; // The size of the vsa log file on the disk
bool isOverlapped = false; // Determines if VSA ring buffer has looped to beginning
uint64_t coreMiniTimestamp = UINT64_MAX; // Timestamp of the CoreMini message in 25 nanosecond ticks since January 1, 2007
};
/**
* Struct used to exclude VSA message records from parse
*/
struct VSAMessageReadFilter {
CaptureBitfield captureBitfield = UINT16_MAX; // The capture from which to gather VSA message records. UINT16_MAX indicates 'all captures'
// The range of timestamps to collect record data from
std::pair<Timestamp, Timestamp> readRange = std::make_pair(Timestamp(ICSClock::duration(0x0ull)), Timestamp(ICSClock::duration(UINT64_MAX)));
static constexpr Timestamp MinTimestamp = Timestamp(ICSClock::duration(0x0ull));
static constexpr Timestamp MaxTimestamp = Timestamp(ICSClock::duration(UINT64_MAX));
};
struct VSAExtractionSettings {
bool parseOldRecords = false;
bool stopCoreMini = true;
std::vector<VSAMessageReadFilter> filters;
};
/**
* Abstract VSA base class to store VSA record data read from VSA log file on disk
*/
class VSA {
public:
virtual ~VSA() = default;
static constexpr size_t StandardRecordSize = 32; // Size of most VSA records
static constexpr uint64_t RecordStartOffset = 0x06000000u; // Offset of VSA record ring buffer from start of VSA log file
/**
* Convert the given time_point object to a timestamp in 25 nanosecond ticks since January 1, 2007
*
* @return Timestamp of the given time_point in 25 nanosecond ticks since January 1, 2007
*/
static uint64_t getICSTimestampFromTimepoint(const Timestamp& point) noexcept { return point.time_since_epoch().count(); }
/**
* Enum to determine what type of record is underlying VSA parent class
*/
enum class Type : uint16_t {
AA00 = 0xAA00u, // Pad
AA01 = 0xAA01u, // Message Data (Deprecated)
AA02 = 0xAA02u, // 'Logdata'
AA03 = 0xAA03u, // Event
AA04 = 0xAA04u, // Partition Info
AA05 = 0xAA05u, // Application Error
AA06 = 0xAA06u, // Internal/Debug
AA07 = 0xAA07u, // Internal/Debug
AA08 = 0xAA08u, // Buffer Info
AA09 = 0xAA09u, // Device Info
AA0A = 0xAA0Au, // Logger Configuration Info (Deprecated)
AA0B = 0xAA0Bu, // Message Data
AA0C = 0xAA0Cu, // PCM Audio Data
AA0D = 0XAA0Du, // Message Data (Extended)
AA0E = 0xAA0Eu, // Message Data (Extended)
AA0F = 0xAA0Fu, // Message Data (Extended)
AA6A = 0xAA6Au, // Logger Configuration Backup (512 Bytes)
Invalid = UINT16_MAX // Used to indicate unset or unhandled VSA record types
};
/**
* Get the record type
*
* @return Type of record
*/
Type getType() const { return type; }
/**
* Get the timestamp stored in this record
*
* @return The record's timestamp in 25 nanosecond ticks since January 1, 2007
*/
virtual uint64_t getTimestamp() = 0;
/**
* Determine whether this record has a valid timestamp. All invalid timestamps are set to the maximum value for a uint64_t.
*
* @return True if the timestamp is set to a valid number
*/
bool isTimestampValid() { return getTimestamp() != UINT64_MAX && !checksumFailed; }
/**
* Determine if the checksum for this record failed
*
* @return True if the checksum does not pass
*/
bool getChecksumFailed() { return checksumFailed; }
/**
* Get the timestamp of this record in C++ native std::chrono::time_point
*
* @return Timestamp of record as an std::chrono::time_point
*/
Timestamp getTimestampICSClock()
{
return Timestamp(std::chrono::duration_cast<ICSClock::duration>(std::chrono::nanoseconds(getTimestamp() * 25)));
}
protected:
/**
* Used to construct a VSA record from child class
*/
VSA() {}
/**
* Used to set the type of this record in child class constructors
*
* @param recordType The type of this record
*/
void setType(Type recordType) { this->type = recordType; }
/**
* Set whether the checksum was passed for this record. This is called in each child class constructor.
*
* @param fail True if checksum did not pass, else false
*/
void setChecksumFailed(bool fail) { checksumFailed = fail; }
private:
/**
* Performs checksum on data in specific record type. Calls VSA::setChecksumFailed(...) from child class.
*
* @param recordBytes Bytestream of record to perform checksum with
*/
virtual void doChecksum(uint8_t* recordBytes) = 0;
Type type = Type::Invalid; // The type of this record
bool checksumFailed = false; // Determines if checksum failed
};
/**
* Interface class for handling common functionality of VSAMessage record types (AA0B, AA0D, AA0E, AA0F)
*/
class VSAMessage : public VSA {
public:
static constexpr size_t CoreMiniPayloadSize = 24; // Size of CoreMini message (payload)
/**
* Construct a packet from the message payload and network
*
* @return Packet constructed from payload and network
*/
std::shared_ptr<Packet> getPacket() const;
/**
* Reserve enough memory to store a CoreMini message in the given packet
*
* @param packet The packet in which we are reserving memory for a message
*/
virtual void reservePacketData(std::shared_ptr<Packet>& packet) const { packet->data.reserve(CoreMiniPayloadSize); }
/**
* Determine whether to filter out this VSAMessage record during parsing
*
* @param filter The filter struct to check this message record against
*
* @return True if this message passes the given filter
*/
virtual bool filter(const std::shared_ptr<VSAMessageReadFilter> filter) = 0;
protected:
/**
* Constructor for normal instance of VSAMessage class
*
* @param messageBytes Bytestream that begins at the start of the message payload
* @param numBytes The number of bytes that the message payload contains
* @param networkId The CoreMini ID of the network for this message
*/
VSAMessage(uint8_t* const messageBytes, size_t numBytes, Network::CoreMini networkId = static_cast<Network::CoreMini>(UINT16_MAX))
: VSA(), payload(messageBytes, messageBytes + numBytes), network(networkId) {}
std::vector<uint8_t> payload; // CoreMini message/payload of VSA record containing message data
Network network; // CoreMini network of this message
};
/**
* Interface class for handling common functionality of VSA Extended Message records (AA0D, AA0E, AA0F)
*/
class VSAExtendedMessage : public VSAMessage {
public:
static void truncatePacket(std::shared_ptr<Packet> packet);
/**
* Appends the payload for this message to the given packet.
* Also sets the network of the packet if unset (used primarily for AA0F records which do not contain the network in the first extended message record).
*
* @param packet The packet to append this record's payload to
*/
void appendPacket(std::shared_ptr<Packet> packet) const;
/**
* Get the total number of records for this extended message
*
* @return Total number of records that this message spans
*/
uint32_t getRecordCount() const { return totalRecordCount; }
/**
* Get the index of this record in the extended message sequence
*
* @return The index of this record
*/
uint16_t getIndex() { return index; };
/**
* Get the numerical id of the sequence of extended message records this record is a part of
*
* @return The sequence number of this extended message record
*/
uint16_t getSequenceNum() { return sequenceNum; }
protected:
/**
* Constructor for normal instance of VSAExtendedMessage
*
* @param messageBytes Bytestream that begins at the start of the message payload
* @param numBytes The length of the message payload in bytes
* @param networkId The CoreMini ID of the network for this message
*/
VSAExtendedMessage(uint8_t* const messageBytes, size_t numBytes, Network::CoreMini networkId = static_cast<Network::CoreMini>(UINT16_MAX))
: VSAMessage(messageBytes, numBytes, networkId) {}
/**
* Set the total number of records for this message
*
* @param recordCount Total number of records for this message
*/
void setRecordCount(uint32_t recordCount) { totalRecordCount = recordCount; }
/**
* Set the index of this record
*
* @param recordIndex The index of this record in its extended message sequence
*/
void setIndex(uint16_t recordIndex) { this->index = recordIndex; }
/**
* Set the sequence number of this record
*
* @param seq The id for the extended message sequence this record is a part of
*/
void setSequenceNum(uint16_t seq) { sequenceNum = seq; }
private:
uint32_t totalRecordCount; // The total number of records for the extended message
uint16_t index; // The index of this record in its extended message sequence
uint16_t sequenceNum; // The id of the sequence of records this record is a part of
};
} // namespace icsneo
#endif // __cplusplus
#endif // __VSA_H__
-55
View File
@@ -1,55 +0,0 @@
#ifndef __VSA02_H__
#define __VSA02_H__
#ifdef __cplusplus
#include "icsneo/disk/vsa/vsa.h"
namespace icsneo {
/**
* Class that contains data for Logdata records
*/
class VSA02 : public VSA {
public:
/**
* Constructor that parses the given bytestream
*
* @param bytes Bystream that contains data for Logdata VSA records
*/
VSA02(uint8_t* const bytes);
/**
* Get the timestamp for this record in 25 nanosecond ticks since January 1, 2007
*
* @return The timestamp for this record in 25 nanosecond ticks since January 1, 2007
*/
uint64_t getTimestamp() override { return timestamp; }
private:
/**
* Perform the checksum for this record
*
* @param bytes Bystream to test against the checksum
*/
void doChecksum(uint8_t* bytes) override;
uint16_t constantIndex; // Index into CoreMini binary where constant data for this record can be found
struct Flags {
bool hasMoreData : 1; // Set to true if there are further Logdata records expected to terminate this "chain"
uint8_t numSamples : 3; // Number of valid samples in samples
bool isAscii : 1; // Set to true if the processing code should treat samples as an ASCII string
bool prefixTime : 1; // Set to true if the function block step that created this record requested that the timestamp be prepended on the output
bool sample0IsHex : 1; // Set to true if the value in sample 0 should be written as hex
bool sample1IsHex : 1; // Set to true if the value in sample 1 shoudl be written as hex
} flags; // Series of flags for this record
uint8_t pieceCount; // Value of the rolling counter for this "chain" of logdata records
uint64_t timestamp; // Timestamp in 25 nanosecond ticks since January 1, 2007
std::vector<uint8_t> samples; // Data for this record that varies based on the above flags. Either 2 32.32 fixed point values or 16 byte ASCII string
uint16_t checksum; // The sum of the previous 15 words
};
} // namespace icsneo
#endif // __cplusplus
#endif // __VSA02_H__
-54
View File
@@ -1,54 +0,0 @@
#ifndef __VSA03_H__
#define __VSA03_H__
#ifdef __cplusplus
#include "icsneo/disk/vsa/vsa.h"
namespace icsneo {
/**
* Class used to store event
*/
class VSA03 : public VSA {
public:
/**
* Constructor that extracts data from the given bytestream
*
* @param bytes Bytestream to extract VSA record data from
*/
VSA03(uint8_t* const bytes);
/**
* Get the timestamp for this record in 25 nanosecond ticks since January 1, 2007
*
* @return The timestamp for this record in 25 nanosecond ticks since January 1, 2007
*/
uint64_t getTimestamp() override { return timestamp; }
private:
/**
* Perform checksum for this record
*
* @param bytes Bytestream to test against the checksum
*/
void doChecksum(uint8_t* bytes) override;
enum class EventType : uint16_t {
CaptureStarted = 0,
StorageReconnected = 3,
FileSystemBufferOverflow = 4,
LoggerWentToSleep = 5,
Internal = 7,
CaptureStopped = 8,
LoggerPowerEvent = 9
} eventType; // Enumerated value indicating which type of event occurred
uint16_t eventData; // Information about the event that is dependent on eventType
uint64_t timestamp; // Timestamp of this record in 25 nanosecond ticks since January 1, 2007
uint16_t checksum; // The sum of the previous 7 words
};
} // namespace icsneo
#endif // __cplusplus
#endif // __VSA03_H__
-49
View File
@@ -1,49 +0,0 @@
#ifndef __VSA04_H__
#define __VSA04_H__
#ifdef __cplusplus
#include "icsneo/disk/vsa/vsa.h"
namespace icsneo {
/**
* Class that contains a partition info record
*/
class VSA04 : public VSA {
public:
/**
* Constructor that created partition info record from bytestream
*
* @param bytes Bytestream to create this record from
*/
VSA04(uint8_t* const bytes);
/**
* Get the timestamp of this record in 25 nanosecond ticks since January 1, 2007
*
* @return Timestamp of this record in 25 nanosecond ticks since January 1, 2007
*/
uint64_t getTimestamp() override { return timestamp; }
private:
/**
* Perform the checksum for this record
*
* @param bytes Bytestream to check against the checksum
*/
void doChecksum(uint8_t* bytes) override;
struct Flags {
bool invalidRequestDetected : 1; // Indicates if an invalid request was detected
uint16_t reserved : 15; // Empty flag bits
} flags; // Mostly empty field for flags
uint16_t partitionIndex; // The index of the partition containing this record
uint64_t timestamp; // Timestamp of this record in 25 nanosecond ticks since January 1, 2007
uint16_t checksum; // Sum of the previous 7 words
};
} // namespace icsneo
#endif // __cplusplus
#endif // __VSA04_H__
-79
View File
@@ -1,79 +0,0 @@
#ifndef __VSA05_H__
#define __VSA05_H__
#ifdef __cplusplus
#include "icsneo/disk/vsa/vsa.h"
namespace icsneo {
/**
* Class that holds data for application error records
*/
class VSA05 : public VSA {
public:
/**
* Constructor to convert bytestream into application error record
*
* @param bytes The bytestream containing the record data
*/
VSA05(uint8_t* const bytes);
/**
* Get the timestamp for this record in 25 nanosecond ticks since January 1, 2007
*
* @return The timestamp for this record in 25 nanosecond ticks since January 1, 2007
*/
uint64_t getTimestamp() override { return timestamp; }
private:
/**
* Perform the checksum on this record
*
* @param bytes Bytestream to test against the checksum
*/
void doChecksum(uint8_t* bytes) override;
enum class ErrorType : uint16_t {
NetworkReceiveBufferOverflow = 0,
NetworkTransmitBufferOverflow = 1,
NetworkTransmitReportBufferOverflow = 2,
PeripheralProcessorCommunicationError = 3,
NetworkPeripheralOverflow = 4,
CommunicationPacketChecksumError = 6,
CommunicationPacketDetectedMissingByte = 7,
FailedToApplySettingsToNetwork = 9,
EnabledNetworkCountExceedsLicenseCapability = 10,
NetworkNotEnabled = 11,
DetectedInvalidTimestamp = 12,
LoadedDefaultSettings = 13,
DeviceAttemptedUnsupportedOperation = 14,
TrasmitBufferFillExceededThreshold = 17,
TransmitRequestedOnInvalidNetwork = 18,
TransmitRequestedOnTransmitIncapableNetwork = 19,
TransmitRequestedWhileControllersInactive = 20,
FilterMatchesExceedLimit = 21,
EthernetPreemptionError = 22,
TransmitWhileControllerModeInvalid = 23,
FragmentedEthernetIPFrame = 25,
TransmitBufferUnderrun = 26,
ActiveCoolingFailureDetected = 27,
OvertemperatureConditionDetected = 28,
UndersizedEthernetFrame = 30,
OversizedEthernetFrame = 31,
SystemWatchdogEventOcurred = 32,
SystemClockFailureDetected = 33,
RecoveredFromSystemClockFailure = 34,
SystemResetFailedPeripheralComponent = 35,
FailedToInitializeLoggerDisk = 41,
AttemptedToApplyInvalidSettingsToNetwork = 42
} errorType; // Enumerated value indicating the type of error that occurred
uint16_t errorNetwork; // When applicable, the enumerated network index that the error occurred on
uint64_t timestamp; // Timestamp of this record in 25 nanosecond ticks since January 1, 2007
uint16_t checksum; // Sum of the previous 7 words
};
} // namespace icsneo
#endif // __cplusplus
#endif // __VSA05_H__
-49
View File
@@ -1,49 +0,0 @@
#ifndef __VSA06_H__
#define __VSA06_H__
#ifdef __cplusplus
#include "icsneo/disk/vsa/vsa.h"
#include <vector>
namespace icsneo {
/**
* Class that holds data for an internal/debug VSA record
*/
class VSA06 : public VSA {
public:
/**
* Constructor to convert bytestream into internal/debug record
*
* @param bytes Bytestream to parse into internal/debug record
*/
VSA06(uint8_t* const bytes);
/**
* Get the timestamp for this record in 25 nanosecond ticks since January 1, 2007
*
* @return The timestamp for this record in 25 nanosecond ticks since January 1, 2007
*/
uint64_t getTimestamp() override { return timestamp; }
private:
/**
* Perform the checksum on this record
*
* @param bytes Bytestream to test against the checksum
*/
void doChecksum(uint8_t* bytes) override;
std::vector<uint32_t> savedSectors; // Unknown
uint16_t error; // Unknown
uint16_t savedSectorsHigh; // Unknown
uint64_t timestamp; // Timestamp for this record in 25 nanosecond ticks since January 1, 2007
uint16_t checksum; // Sum of the previous 15 words
};
} // namespace icsneo
#endif // __cplusplus
#endif // __VSA06_H__
-49
View File
@@ -1,49 +0,0 @@
#ifndef __VSA07_H__
#define __VSA07_H__
#ifdef __cplusplus
#include "icsneo/disk/vsa/vsa.h"
#include <vector>
namespace icsneo {
/**
* Class that holds data for an internal/debug VSA record
*/
class VSA07 : public VSA {
public:
/**
* Constructor to convert bytestream into internal/debug record
*
* @param bytes Bytestream to parse into internal/debug record
*/
VSA07(uint8_t* const bytes);
/**
* Get the timestamp for this record in 25 nanosecond ticks since January 1, 2007
*
* @return The timestamp for this record in 25 nanosecond ticks since January 1, 2007
*/
uint64_t getTimestamp() override { return timestamp; }
private:
/**
* Perform the checksum on this record
*
* @param bytes Bytestream to test against the checksum
*/
void doChecksum(uint8_t* bytes) override;
uint32_t lastSector; // Unknown
uint32_t currentSector; // Unknown
std::vector<uint8_t> reserved; // Unused bytes (12 bytes)
uint64_t timestamp; // Timestamp for this record in 25 nanosecond ticks since January 1, 2007
uint16_t checksum; // Sum of the previous 15 words
};
} // namespace icsneo
#endif // __cplusplus
#endif // __VSA07_H__
-46
View File
@@ -1,46 +0,0 @@
#ifndef __VSA08_H__
#define __VSA08_H__
#ifdef __cplusplus
#include "icsneo/disk/vsa/vsa.h"
namespace icsneo {
/**
* Class to store data for a buffer information record
*/
class VSA08 : public VSA {
public:
/**
* Constructor to convert a bytestream to a buffer info record
*
* @param bytes Bytestream to convert into a buffer record
*/
VSA08(uint8_t* const bytes);
/**
* Get the timestamp for this record in 25 nanosecond ticks since January 1, 2007
*
* @return The timestamp for this record in 25 nanosecond ticks since January 1, 2007
*/
uint64_t getTimestamp() override { return timestamp; }
private:
/**
* Perform the checksum on this record
*
* @param bytes Bytestream to test against the checksum
*/
void doChecksum(uint8_t* bytes) override;
std::vector<uint8_t> troubleSramCount; // Unknown (4 bytes)
std::vector<uint32_t> troubleSectors; // Unknown (16 bytes)
uint64_t timestamp; // Timestamp for this record in 25 nanosecond ticks since January 1, 2007
uint16_t checksum; // Sum of the previous 15 words
};
} // namespace icsneo
#endif // __cplusplus
#endif // __VSA08_H__
-63
View File
@@ -1,63 +0,0 @@
#ifndef __VSA09_H__
#define __VSA09_H__
#ifdef __cplusplus
#include "icsneo/disk/vsa/vsa.h"
namespace icsneo {
/**
* Class used to store data for a Device Information VSA Record
*/
class VSA09 : public VSA {
public:
/**
* Constructor to convert bytestream to Device Information VSA Record
*
* @param bytes Bytestream to convert into Device Information Record
*/
VSA09(uint8_t* const bytes);
/**
* Get the timestamp for this record in 25 nanosecond ticks since January 1, 2007
*
* @return The timestamp for this record in 25 nanosecond ticks since January 1, 2007
*/
uint64_t getTimestamp() override { return timestamp; }
private:
/**
* Perform the checksum on this record
*
* @param bytes Bytestream to test against the checksum
*/
void doChecksum(uint8_t* bytes) override;
uint32_t serialNumber; // Decimal representation of Base-36 serial number
uint8_t firmwareMajorVersion; // Major version of firmware (A for A.B version)
uint8_t firmwareMinorVersion; // Minor version of firmware (B for A.B version)
uint8_t manufactureMajorRevision; // Major version of manufacture revision (A for A.B revision)
uint8_t manufactureMinorRevision; // Minor version of manufacture revision (B for A.B revision)
uint8_t bootloaderMajorVersion; // Major version of bootloader (A for A.B version)
uint8_t bootloaderMinorVersion; // Minor version of bootloader (B for A.B version)
std::vector<uint8_t> reserved0; // Unused bytes (6 bytes)
enum class HardwareID : uint8_t {
NeoVIRED = 0,
NeoVIFIRE = 1,
NeoVIION = 11,
RADGalaxy = 19,
RADMars = 29,
ValueLOG = 31,
NeoVIRED2FIRE3 = 33,
RADGigastar = 36
} hardwareID; // Identifier for specific hardware device type
std::vector<uint8_t> reserved1; // Unused bytes (3 bytes)
uint64_t timestamp; // Timestamp for this record in 25 nanosecond ticks since January 1, 2007
uint16_t checksum; // Sum of the previous 15 words
};
} // namespace icsneo
#endif // __cplusplus
#endif // __VSA09_H__
-57
View File
@@ -1,57 +0,0 @@
#ifndef __VSA0B_H__
#define __VSA0B_H__
#ifdef __cplusplus
#include <vector>
#include "icsneo/disk/vsa/vsa.h"
namespace icsneo {
/**
* Class that holds single-record message records
*/
class VSA0B : public VSAMessage {
public:
/**
* Constructor that reads message record data from bytestream
*
* @param bytes Bytestream to read message record data from
*/
VSA0B(uint8_t* const bytes);
/**
* Determine whether to filter out this message record
*
* @param filter The filter to check this record against
*
* @return True if this record has passed the filter (i.e., is not being filtered out)
*/
bool filter(const std::shared_ptr<VSAMessageReadFilter> filter) override;
/**
* Get the timestamp of this record in 25 nanosecond ticks since January 1, 2007
*
* @return Timestamp of this record in 25 nanosecond ticks since January 1, 2007
*/
uint64_t getTimestamp() override { return timestamp; }
private:
/**
* Perform a checksum on this record
*
* @param bytes Bytestream to test against the checksum
*/
void doChecksum(uint8_t* bytes) override;
uint16_t captureBitfield; // The capture that this record is a part of
uint8_t reserved; // Unused bytes
uint16_t checksum; // Sum of the previous 15 half words
uint64_t timestamp; // Timestamp of this record in 25 nanosecond ticks since January 1, 2007 (extracted from CoreMini message payload)
};
} // namespace icsneo
#endif // __cplusplus
#endif // __VSA0B_H__
-54
View File
@@ -1,54 +0,0 @@
#ifndef __VSA0C_H__
#define __VSA0C_H__
#ifdef __cplusplus
#include "icsneo/disk/vsa/vsa.h"
#include <vector>
namespace icsneo {
/**
* Class used to hold data for a PCM Audio VSA Record
*/
class VSA0C : public VSA {
public:
/**
* Constructor to convert bytestream to PCM Audio Record
*
* @param bytes Bytestream to parse
*/
VSA0C(uint8_t* const bytes);
/**
* Get the timestamp for this record in 25 nanosecond ticks since January 1, 2007
*
* @return The timestamp for this record in 25 nanosecond ticks since January 1, 2007
*/
uint64_t getTimestamp() override { return timestamp; }
private:
/**
* Perform the checksum on this record
*
* @param bytes Bytestream to test against the checksum
*/
void doChecksum(uint8_t* bytes) override;
uint16_t captureBitfield; // Capture this record is a member of (Unused)
uint8_t audioPreamble; // Unknown
uint8_t audioHeader; // Unknown
std::vector<uint8_t> pcmData; // Audio data payload (14 bytes)
uint64_t timestamp; // Timestamp of this record in 25 nanosecond ticks since January 1, 2007
struct VNet {
uint16_t vNetSlot : 2; // Bits to identify VNet slot of this record
uint16_t reserved : 14; // Unused bits
} vNetBitfield; // Struct to ensure VNetSlot is only 2 bits
uint16_t checksum; // Sum of the previous 15 words
};
} // namespace icsneo
#endif // __cplusplus
#endif // __VSA0C_H__

Some files were not shown because too many files have changed in this diff Show More