Compare commits
31 Commits
db9da30f94
...
dedf68879f
| Author | SHA1 | Date |
|---|---|---|
|
|
dedf68879f | |
|
|
a0c8cc62df | |
|
|
77b3564677 | |
|
|
051063e684 | |
|
|
7c1cfde6a0 | |
|
|
d4995fa2a9 | |
|
|
fb5c4babce | |
|
|
4ba1a1e1dd | |
|
|
6b9a687ff9 | |
|
|
02b5dafca9 | |
|
|
f04cd16bee | |
|
|
c5ba2d8d32 | |
|
|
a22791c9e0 | |
|
|
dc2a364afb | |
|
|
114b664d78 | |
|
|
739ff4d637 | |
|
|
2acf248583 | |
|
|
f18aa00322 | |
|
|
87baa97c3f | |
|
|
8dcbbe0d72 | |
|
|
b624d06ca0 | |
|
|
c249df8756 | |
|
|
b2161211c5 | |
|
|
0ee8a990a7 | |
|
|
dc0f16b1d2 | |
|
|
c4ce803d62 | |
|
|
34cacf4cf2 | |
|
|
4157558e84 | |
|
|
40b85488dc | |
|
|
7584563002 | |
|
|
e233233b94 |
122
.gitlab-ci.yml
122
.gitlab-ci.yml
|
|
@ -4,7 +4,6 @@ variables:
|
||||||
stages:
|
stages:
|
||||||
- build
|
- build
|
||||||
- unit_test
|
- unit_test
|
||||||
- hardware_test
|
|
||||||
- deploy
|
- deploy
|
||||||
|
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
|
|
@ -21,7 +20,7 @@ build windows/x64:
|
||||||
- build
|
- build
|
||||||
expire_in: 3 days
|
expire_in: 3 days
|
||||||
tags:
|
tags:
|
||||||
- icsneo-windows
|
- libicsneo-win-x64
|
||||||
|
|
||||||
unit_test windows/x64:
|
unit_test windows/x64:
|
||||||
stage: unit_test
|
stage: unit_test
|
||||||
|
|
@ -32,7 +31,7 @@ unit_test windows/x64:
|
||||||
needs:
|
needs:
|
||||||
- build windows/x64
|
- build windows/x64
|
||||||
tags:
|
tags:
|
||||||
- icsneo-windows
|
- libicsneo-win-x64
|
||||||
timeout: 5m
|
timeout: 5m
|
||||||
|
|
||||||
build windows/x86:
|
build windows/x86:
|
||||||
|
|
@ -45,7 +44,7 @@ build windows/x86:
|
||||||
- build
|
- build
|
||||||
expire_in: 3 days
|
expire_in: 3 days
|
||||||
tags:
|
tags:
|
||||||
- icsneo-windows
|
- libicsneo-win-x64
|
||||||
|
|
||||||
unit_test windows/x86:
|
unit_test windows/x86:
|
||||||
stage: unit_test
|
stage: unit_test
|
||||||
|
|
@ -56,7 +55,7 @@ unit_test windows/x86:
|
||||||
needs:
|
needs:
|
||||||
- build windows/x86
|
- build windows/x86
|
||||||
tags:
|
tags:
|
||||||
- icsneo-windows
|
- libicsneo-win-x64
|
||||||
timeout: 5m
|
timeout: 5m
|
||||||
|
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
|
|
@ -307,119 +306,6 @@ unit_test linux/fedora/39/amd64/clang:
|
||||||
needs:
|
needs:
|
||||||
- build linux/fedora/39/amd64/clang
|
- build linux/fedora/39/amd64/clang
|
||||||
|
|
||||||
.hw_test: &hw_test
|
|
||||||
stage: hardware_test
|
|
||||||
tags:
|
|
||||||
- libicsneo_hil
|
|
||||||
timeout: 5m
|
|
||||||
script:
|
|
||||||
- echo $GUEST_OS_TAG
|
|
||||||
- echo $DEVICE_PORT
|
|
||||||
- /opt/libvirt-driver/prepare.sh
|
|
||||||
- /opt/libvirt-driver/run.sh
|
|
||||||
after_script:
|
|
||||||
- /opt/libvirt-driver/cleanup.sh
|
|
||||||
allow_failure: true
|
|
||||||
|
|
||||||
.fedora38_needs: &fedora38_needs
|
|
||||||
needs:
|
|
||||||
- job: build linux/fedora/38/amd64/clang
|
|
||||||
artifacts: true
|
|
||||||
|
|
||||||
hardware_test fedora38-red2:
|
|
||||||
<<: *hw_test
|
|
||||||
<<: *fedora38_needs
|
|
||||||
variables:
|
|
||||||
GUEST_OS_TAG: fedora38
|
|
||||||
DEVICE_PORT: ETH_A
|
|
||||||
|
|
||||||
hardware_test fedora38-vcan42:
|
|
||||||
<<: *hw_test
|
|
||||||
<<: *fedora38_needs
|
|
||||||
variables:
|
|
||||||
GUEST_OS_TAG: fedora38
|
|
||||||
DEVICE_PORT: USB_D
|
|
||||||
|
|
||||||
hardware_test fedora38-fire3:
|
|
||||||
<<: *hw_test
|
|
||||||
<<: *fedora38_needs
|
|
||||||
variables:
|
|
||||||
GUEST_OS_TAG: fedora38
|
|
||||||
DEVICE_PORT: ETH_B
|
|
||||||
|
|
||||||
hardware_test fedora38-vcan42-EL:
|
|
||||||
<<: *hw_test
|
|
||||||
<<: *fedora38_needs
|
|
||||||
variables:
|
|
||||||
GUEST_OS_TAG: fedora38
|
|
||||||
DEVICE_PORT: USB_C
|
|
||||||
|
|
||||||
.ubuntu2204_needs: &ubuntu2204_needs
|
|
||||||
needs:
|
|
||||||
- job: build linux/ubuntu/2204/amd64/clang
|
|
||||||
artifacts: true
|
|
||||||
|
|
||||||
hardware_test ubuntu2204-red2:
|
|
||||||
<<: *hw_test
|
|
||||||
<<: *ubuntu2204_needs
|
|
||||||
variables:
|
|
||||||
GUEST_OS_TAG: ubuntu22.04
|
|
||||||
DEVICE_PORT: ETH_A
|
|
||||||
|
|
||||||
hardware_test ubuntu2204-vcan42:
|
|
||||||
<<: *hw_test
|
|
||||||
<<: *ubuntu2204_needs
|
|
||||||
variables:
|
|
||||||
GUEST_OS_TAG: ubuntu22.04
|
|
||||||
DEVICE_PORT: USB_D
|
|
||||||
|
|
||||||
hardware_test ubuntu2204-fire3:
|
|
||||||
<<: *hw_test
|
|
||||||
<<: *ubuntu2204_needs
|
|
||||||
variables:
|
|
||||||
GUEST_OS_TAG: ubuntu22.04
|
|
||||||
DEVICE_PORT: ETH_B
|
|
||||||
|
|
||||||
hardware_test ubuntu2204-vcan42-EL:
|
|
||||||
<<: *hw_test
|
|
||||||
<<: *ubuntu2204_needs
|
|
||||||
variables:
|
|
||||||
GUEST_OS_TAG: ubuntu22.04
|
|
||||||
DEVICE_PORT: USB_C
|
|
||||||
|
|
||||||
.win10_needs: &win10_needs
|
|
||||||
needs:
|
|
||||||
- job: build windows/x64
|
|
||||||
artifacts: true
|
|
||||||
|
|
||||||
hardware_test win10-red2:
|
|
||||||
<<: *hw_test
|
|
||||||
<<: *win10_needs
|
|
||||||
variables:
|
|
||||||
GUEST_OS_TAG: win10
|
|
||||||
DEVICE_PORT: ETH_A
|
|
||||||
|
|
||||||
hardware_test win10-vcan42:
|
|
||||||
<<: *hw_test
|
|
||||||
<<: *win10_needs
|
|
||||||
variables:
|
|
||||||
GUEST_OS_TAG: win10
|
|
||||||
DEVICE_PORT: USB_D
|
|
||||||
|
|
||||||
hardware_test win10-fire3:
|
|
||||||
<<: *hw_test
|
|
||||||
<<: *win10_needs
|
|
||||||
variables:
|
|
||||||
GUEST_OS_TAG: win10
|
|
||||||
DEVICE_PORT: ETH_B
|
|
||||||
|
|
||||||
hardware_test win10-vcan42-EL:
|
|
||||||
<<: *hw_test
|
|
||||||
<<: *win10_needs
|
|
||||||
variables:
|
|
||||||
GUEST_OS_TAG: win10
|
|
||||||
DEVICE_PORT: USB_C
|
|
||||||
|
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
# Python Module
|
# Python Module
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
cmake_minimum_required(VERSION 3.12)
|
cmake_minimum_required(VERSION 3.16)
|
||||||
project(libicsneo VERSION 0.3.0)
|
project(libicsneo VERSION 0.3.0)
|
||||||
|
|
||||||
cmake_policy(SET CMP0074 NEW)
|
cmake_policy(SET CMP0074 NEW)
|
||||||
|
|
@ -7,14 +7,13 @@ if(POLICY CMP0135)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
option(LIBICSNEO_BUILD_UNIT_TESTS "Build unit tests." OFF)
|
option(LIBICSNEO_BUILD_UNIT_TESTS "Build unit tests." OFF)
|
||||||
option(LIBICSNEO_BUILD_SYSTEM_TESTS "Build system tests." OFF)
|
|
||||||
option(LIBICSNEO_BUILD_DOCS "Build documentation. Don't use in Visual Studio." OFF)
|
option(LIBICSNEO_BUILD_DOCS "Build documentation. Don't use in Visual Studio." OFF)
|
||||||
option(LIBICSNEO_BUILD_EXAMPLES "Build examples." ON)
|
option(LIBICSNEO_BUILD_EXAMPLES "Build examples." ON)
|
||||||
option(LIBICSNEO_BUILD_ICSNEOC "Build dynamic C library" ON)
|
option(LIBICSNEO_BUILD_ICSNEOC "Build dynamic C library" ON)
|
||||||
option(LIBICSNEO_BUILD_ICSNEOC_STATIC "Build static C library" ON)
|
option(LIBICSNEO_BUILD_ICSNEOC_STATIC "Build static C library" ON)
|
||||||
option(LIBICSNEO_BUILD_ICSNEOLEGACY "Build icsnVC40 compatibility library" ON)
|
option(LIBICSNEO_BUILD_ICSNEOLEGACY "Build icsnVC40 compatibility library" ON)
|
||||||
option(LIBICSNEO_BUILD_ICSNEOLEGACY_STATIC "Build static icsnVC40 compatibility library" ON)
|
option(LIBICSNEO_BUILD_ICSNEOLEGACY_STATIC "Build static icsnVC40 compatibility library" ON)
|
||||||
set(LIBICSNEO_NPCAP_INCLUDE_DIR "" CACHE STRING "Npcap include directory; set to build with Npcap")
|
set(LIBICSNEO_NPCAP_INCLUDE_DIR "C:/Users/Vit/source/repos/npcap-sdk-1.13/Include" CACHE STRING "Npcap include directory; set to build with Npcap")
|
||||||
|
|
||||||
# Device Drivers
|
# Device Drivers
|
||||||
# You almost certainly don't want firmio for your build,
|
# You almost certainly don't want firmio for your build,
|
||||||
|
|
@ -111,6 +110,7 @@ endif()
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
set(PLATFORM_SRC
|
set(PLATFORM_SRC
|
||||||
|
platform/windows/strings.cpp
|
||||||
platform/windows/registry.cpp
|
platform/windows/registry.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -246,6 +246,9 @@ set(SRC_FILES
|
||||||
communication/message/linmessage.cpp
|
communication/message/linmessage.cpp
|
||||||
communication/message/livedatamessage.cpp
|
communication/message/livedatamessage.cpp
|
||||||
communication/message/tc10statusmessage.cpp
|
communication/message/tc10statusmessage.cpp
|
||||||
|
communication/message/gptpstatusmessage.cpp
|
||||||
|
communication/message/ethernetstatusmessage.cpp
|
||||||
|
communication/message/macsecmessage.cpp
|
||||||
communication/packet/flexraypacket.cpp
|
communication/packet/flexraypacket.cpp
|
||||||
communication/packet/canpacket.cpp
|
communication/packet/canpacket.cpp
|
||||||
communication/packet/a2bpacket.cpp
|
communication/packet/a2bpacket.cpp
|
||||||
|
|
@ -273,6 +276,7 @@ set(SRC_FILES
|
||||||
communication/driver.cpp
|
communication/driver.cpp
|
||||||
communication/livedata.cpp
|
communication/livedata.cpp
|
||||||
communication/ringbuffer.cpp
|
communication/ringbuffer.cpp
|
||||||
|
communication/crc32.cpp
|
||||||
device/extensions/flexray/extension.cpp
|
device/extensions/flexray/extension.cpp
|
||||||
device/extensions/flexray/controller.cpp
|
device/extensions/flexray/controller.cpp
|
||||||
device/idevicesettings.cpp
|
device/idevicesettings.cpp
|
||||||
|
|
@ -525,6 +529,7 @@ if(LIBICSNEO_BUILD_UNIT_TESTS)
|
||||||
test/unit/livedataencoderdecodertest.cpp
|
test/unit/livedataencoderdecodertest.cpp
|
||||||
test/unit/ringbuffertest.cpp
|
test/unit/ringbuffertest.cpp
|
||||||
test/unit/apperrordecodertest.cpp
|
test/unit/apperrordecodertest.cpp
|
||||||
|
test/unit/windowsstrings.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(libicsneo-unit-tests gtest gtest_main)
|
target_link_libraries(libicsneo-unit-tests gtest gtest_main)
|
||||||
|
|
@ -537,22 +542,6 @@ if(LIBICSNEO_BUILD_UNIT_TESTS)
|
||||||
add_test(NAME libicsneo-unit-test-suite COMMAND libicsneo-unit-tests)
|
add_test(NAME libicsneo-unit-test-suite COMMAND libicsneo-unit-tests)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(LIBICSNEO_BUILD_SYSTEM_TESTS)
|
|
||||||
if(DEFINED ENV{LIBICSNEO_SYSTEM_TESTS})
|
|
||||||
include(FetchContent)
|
|
||||||
file(MAKE_DIRECTORY test/system)
|
|
||||||
FetchContent_Declare(
|
|
||||||
SystemTests
|
|
||||||
GIT_REPOSITORY $ENV{LIBICSNEO_SYSTEM_TESTS}
|
|
||||||
GIT_TAG main
|
|
||||||
SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/test/system
|
|
||||||
)
|
|
||||||
FetchContent_MakeAvailable(SystemTests)
|
|
||||||
else()
|
|
||||||
message("System test repo not defined!")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(CPACK_PROJECT_NAME ${PROJECT_NAME})
|
set(CPACK_PROJECT_NAME ${PROJECT_NAME})
|
||||||
set(CPACK_PROJECT_VERSION ${PROJECT_VERSION})
|
set(CPACK_PROJECT_VERSION ${PROJECT_VERSION})
|
||||||
include(CPack)
|
include(CPack)
|
||||||
30
LICENSE
30
LICENSE
|
|
@ -1,13 +1,29 @@
|
||||||
Copyright 2018-2024 Intrepid Control Systems, Inc.
|
Copyright (c) 2018-2025 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:
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
1. Redistributions of source code must retain the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer.
|
||||||
|
|
||||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
|
||||||
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
3. Neither the name of the copyright holder nor the names of its contributors
|
||||||
|
may be used to endorse or promote products derived from this software without
|
||||||
|
specific prior written permission.
|
||||||
|
|
||||||
4. It is forbidden to use this library or derivatives to interface with vehicle networking hardware not produced by Intrepid Control Systems, Inc.
|
4. It is forbidden to use this library or derivatives to interface with vehicle
|
||||||
|
networking hardware not produced by Intrepid Control Systems, Inc.
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ BEGIN
|
||||||
VALUE "FileDescription", "Intrepid Control Systems Open Device Communication C API"
|
VALUE "FileDescription", "Intrepid Control Systems Open Device Communication C API"
|
||||||
VALUE "FileVersion", VER_FILEVERSION_STR
|
VALUE "FileVersion", VER_FILEVERSION_STR
|
||||||
VALUE "InternalName", "icsneoc.dll"
|
VALUE "InternalName", "icsneoc.dll"
|
||||||
VALUE "LegalCopyright", "Intrepid Control Systems, Inc. (C) 2018-2024"
|
VALUE "LegalCopyright", "Intrepid Control Systems, Inc. (C) 2018-2025"
|
||||||
VALUE "OriginalFilename", "icsneoc.dll"
|
VALUE "OriginalFilename", "icsneoc.dll"
|
||||||
VALUE "ProductName", "libicsneo"
|
VALUE "ProductName", "libicsneo"
|
||||||
VALUE "ProductVersion", VER_PRODUCTVERSION_STR
|
VALUE "ProductVersion", VER_PRODUCTVERSION_STR
|
||||||
|
|
|
||||||
|
|
@ -120,6 +120,7 @@ static constexpr const char* DISK_NOT_CONNECTED = "The program tried to access a
|
||||||
static constexpr const char* UNEXPECTED_RESPONSE = "Received an unexpected or invalid response from the device.";
|
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* LIN_SETTINGS_NOT_AVAILABLE = "LIN settings are not available for this device.";
|
||||||
static constexpr const char* MODE_NOT_FOUND = "The mode was not found.";
|
static constexpr const char* MODE_NOT_FOUND = "The mode was not found.";
|
||||||
|
static constexpr const char* GPTP_NOT_SUPPORTED = "GPTP clock synchronization is not supported on this device.";
|
||||||
|
|
||||||
// Transport Errors
|
// Transport Errors
|
||||||
static constexpr const char* FAILED_TO_READ = "A read operation failed.";
|
static constexpr const char* FAILED_TO_READ = "A read operation failed.";
|
||||||
|
|
@ -185,6 +186,7 @@ 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* 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* UNKNOWN = "An unknown internal error occurred.";
|
||||||
static constexpr const char* INVALID = "An invalid internal error occurred.";
|
static constexpr const char* INVALID = "An invalid internal error occurred.";
|
||||||
|
|
||||||
const char* APIEvent::DescriptionForType(Type type) {
|
const char* APIEvent::DescriptionForType(Type type) {
|
||||||
switch(type) {
|
switch(type) {
|
||||||
// API Errors
|
// API Errors
|
||||||
|
|
@ -345,6 +347,8 @@ const char* APIEvent::DescriptionForType(Type type) {
|
||||||
return GETIFADDRS_ERROR;
|
return GETIFADDRS_ERROR;
|
||||||
case Type::SendToError:
|
case Type::SendToError:
|
||||||
return SEND_TO_ERROR;
|
return SEND_TO_ERROR;
|
||||||
|
case Type::GPTPNotSupported:
|
||||||
|
return GPTP_NOT_SUPPORTED;
|
||||||
|
|
||||||
// FTD3XX
|
// FTD3XX
|
||||||
case Type::FTOK:
|
case Type::FTOK:
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,18 @@
|
||||||
cmake_minimum_required(VERSION 3.20)
|
cmake_minimum_required(VERSION 3.20)
|
||||||
|
|
||||||
set(PYBIND11_FINDPYTHON ON)
|
set(PYBIND11_FINDPYTHON ON)
|
||||||
|
|
||||||
|
if(PYBIND11_ROOT)
|
||||||
find_package(pybind11 CONFIG REQUIRED)
|
find_package(pybind11 CONFIG REQUIRED)
|
||||||
|
else()
|
||||||
|
include(FetchContent)
|
||||||
|
FetchContent_Declare(
|
||||||
|
pybind11
|
||||||
|
GIT_REPOSITORY https://github.com/pybind/pybind11.git
|
||||||
|
GIT_TAG v2.13.6
|
||||||
|
)
|
||||||
|
FetchContent_MakeAvailable(pybind11)
|
||||||
|
endif()
|
||||||
|
|
||||||
pybind11_add_module(icsneopy
|
pybind11_add_module(icsneopy
|
||||||
icsneopy/api/event.cpp
|
icsneopy/api/event.cpp
|
||||||
|
|
@ -12,15 +23,29 @@ pybind11_add_module(icsneopy
|
||||||
icsneopy/communication/network.cpp
|
icsneopy/communication/network.cpp
|
||||||
icsneopy/communication/message/message.cpp
|
icsneopy/communication/message/message.cpp
|
||||||
icsneopy/communication/message/canmessage.cpp
|
icsneopy/communication/message/canmessage.cpp
|
||||||
|
icsneopy/communication/message/canerrormessage.cpp
|
||||||
icsneopy/communication/message/ethernetmessage.cpp
|
icsneopy/communication/message/ethernetmessage.cpp
|
||||||
icsneopy/communication/message/linmessage.cpp
|
icsneopy/communication/message/linmessage.cpp
|
||||||
icsneopy/communication/message/tc10statusmessage.cpp
|
icsneopy/communication/message/tc10statusmessage.cpp
|
||||||
icsneopy/communication/message/mdiomessage.cpp
|
icsneopy/communication/message/mdiomessage.cpp
|
||||||
|
icsneopy/communication/message/gptpstatusmessage.cpp
|
||||||
|
icsneopy/communication/message/ethernetstatusmessage.cpp
|
||||||
|
icsneopy/communication/message/macsecmessage.cpp
|
||||||
|
icsneopy/communication/message/scriptstatusmessage.cpp
|
||||||
icsneopy/communication/message/callback/messagecallback.cpp
|
icsneopy/communication/message/callback/messagecallback.cpp
|
||||||
icsneopy/communication/message/filter/messagefilter.cpp
|
icsneopy/communication/message/filter/messagefilter.cpp
|
||||||
|
icsneopy/disk/diskdriver.cpp
|
||||||
icsneopy/device/device.cpp
|
icsneopy/device/device.cpp
|
||||||
icsneopy/icsneocpp.cpp
|
icsneopy/icsneocpp.cpp
|
||||||
)
|
)
|
||||||
target_link_libraries(icsneopy PRIVATE icsneocpp)
|
target_link_libraries(icsneopy PRIVATE icsneocpp)
|
||||||
|
|
||||||
install(TARGETS icsneopy LIBRARY DESTINATION .)
|
install(TARGETS icsneopy LIBRARY DESTINATION icsneopy)
|
||||||
|
|
||||||
|
find_program(STUBGEN_EXE stubgen)
|
||||||
|
if(STUBGEN_EXE)
|
||||||
|
add_custom_command(TARGET icsneopy POST_BUILD COMMAND stubgen -m icsneopy -o .)
|
||||||
|
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/icsneopy.pyi py.typed DESTINATION icsneopy)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
install(FILES __init__.py DESTINATION icsneopy)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
from .icsneopy import *
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
#include <pybind11/pybind11.h>
|
||||||
|
#include <pybind11/stl.h>
|
||||||
|
#include <pybind11/functional.h>
|
||||||
|
|
||||||
|
#include "icsneo/communication/message/canerrormessage.h"
|
||||||
|
|
||||||
|
namespace icsneo {
|
||||||
|
|
||||||
|
void init_errorcodes(pybind11::module_& m) {
|
||||||
|
pybind11::enum_<CANErrorCode>(m, "CANErrorCode")
|
||||||
|
.value("NoError", CANErrorCode::NoError)
|
||||||
|
.value("StuffError", CANErrorCode::StuffError)
|
||||||
|
.value("FormError", CANErrorCode::FormError)
|
||||||
|
.value("AckError", CANErrorCode::AckError)
|
||||||
|
.value("Bit1Error", CANErrorCode::Bit1Error)
|
||||||
|
.value("Bit0Error", CANErrorCode::Bit0Error)
|
||||||
|
.value("CRCError", CANErrorCode::CRCError)
|
||||||
|
.value("NoChange", CANErrorCode::NoChange);
|
||||||
|
}
|
||||||
|
|
||||||
|
void init_canerrormessage(pybind11::module_& m) {
|
||||||
|
init_errorcodes(m);
|
||||||
|
pybind11::class_<CANErrorMessage, std::shared_ptr<CANErrorMessage>, Message>(m, "CANErrorMessage")
|
||||||
|
.def_readonly("network", &CANErrorMessage::network)
|
||||||
|
.def_readonly("transmitErrorCount", &CANErrorMessage::transmitErrorCount)
|
||||||
|
.def_readonly("receiveErrorCount", &CANErrorMessage::receiveErrorCount)
|
||||||
|
.def_readonly("busOff", &CANErrorMessage::busOff)
|
||||||
|
.def_readonly("errorPassive", &CANErrorMessage::errorPassive)
|
||||||
|
.def_readonly("errorWarn", &CANErrorMessage::errorWarn)
|
||||||
|
.def_readonly("dataErrorCode", &CANErrorMessage::dataErrorCode)
|
||||||
|
.def_readonly("errorCode", &CANErrorMessage::errorCode);
|
||||||
|
|
||||||
|
|
||||||
|
m.attr("CANErrorCountMessage") = m.attr("CANErrorMessage");
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace icsneo
|
||||||
|
|
||||||
|
|
@ -15,7 +15,7 @@ void init_ethernetmessage(pybind11::module_& m) {
|
||||||
.def(pybind11::init())
|
.def(pybind11::init())
|
||||||
.def_readwrite("preemptionEnabled", &EthernetMessage::preemptionEnabled)
|
.def_readwrite("preemptionEnabled", &EthernetMessage::preemptionEnabled)
|
||||||
.def_readwrite("preemptionFlags", &EthernetMessage::preemptionFlags)
|
.def_readwrite("preemptionFlags", &EthernetMessage::preemptionFlags)
|
||||||
.def_readwrite("fcsAvailable", &EthernetMessage::fcsAvailable)
|
.def_readwrite("fcs", &EthernetMessage::fcs)
|
||||||
.def_readwrite("frameTooShort", &EthernetMessage::frameTooShort)
|
.def_readwrite("frameTooShort", &EthernetMessage::frameTooShort)
|
||||||
.def_readwrite("noPadding", &EthernetMessage::noPadding)
|
.def_readwrite("noPadding", &EthernetMessage::noPadding)
|
||||||
.def("get_destination_mac", &EthernetMessage::getDestinationMAC, pybind11::return_value_policy::reference)
|
.def("get_destination_mac", &EthernetMessage::getDestinationMAC, pybind11::return_value_policy::reference)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
#include <pybind11/pybind11.h>
|
||||||
|
#include <pybind11/stl.h>
|
||||||
|
#include <pybind11/functional.h>
|
||||||
|
|
||||||
|
#include "icsneo/communication/message/ethernetstatusmessage.h"
|
||||||
|
|
||||||
|
namespace icsneo {
|
||||||
|
|
||||||
|
void init_ethernetstatusmessage(pybind11::module_& m) {
|
||||||
|
pybind11::class_<EthernetStatusMessage, std::shared_ptr<EthernetStatusMessage>, Message> ethernetStatusMessage(m, "EthernetStatusMessage");
|
||||||
|
|
||||||
|
pybind11::enum_<EthernetStatusMessage::LinkSpeed>(ethernetStatusMessage, "LinkSpeed")
|
||||||
|
.value("LinkSpeedAuto", EthernetStatusMessage::LinkSpeed::LinkSpeedAuto)
|
||||||
|
.value("LinkSpeed10", EthernetStatusMessage::LinkSpeed::LinkSpeed10)
|
||||||
|
.value("LinkSpeed100", EthernetStatusMessage::LinkSpeed::LinkSpeed100)
|
||||||
|
.value("LinkSpeed1000", EthernetStatusMessage::LinkSpeed::LinkSpeed1000)
|
||||||
|
.value("LinkSpeed2500", EthernetStatusMessage::LinkSpeed::LinkSpeed2500)
|
||||||
|
.value("LinkSpeed5000", EthernetStatusMessage::LinkSpeed::LinkSpeed5000)
|
||||||
|
.value("LinkSpeed10000", EthernetStatusMessage::LinkSpeed::LinkSpeed10000);
|
||||||
|
|
||||||
|
pybind11::enum_<EthernetStatusMessage::LinkMode>(ethernetStatusMessage, "LinkMode")
|
||||||
|
.value("LinkModeAuto", EthernetStatusMessage::LinkMode::LinkModeAuto)
|
||||||
|
.value("LinkModeMaster", EthernetStatusMessage::LinkMode::LinkModeMaster)
|
||||||
|
.value("LinkModeSlave", EthernetStatusMessage::LinkMode::LinkModeSlave)
|
||||||
|
.value("LinkModeInvalid", EthernetStatusMessage::LinkMode::LinkModeInvalid);
|
||||||
|
|
||||||
|
ethernetStatusMessage
|
||||||
|
.def_readonly("network", &EthernetStatusMessage::network)
|
||||||
|
.def_readonly("state", &EthernetStatusMessage::state)
|
||||||
|
.def_readonly("speed", &EthernetStatusMessage::speed)
|
||||||
|
.def_readonly("duplex", &EthernetStatusMessage::duplex)
|
||||||
|
.def_readonly("mode", &EthernetStatusMessage::mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace icsneo
|
||||||
|
|
@ -8,6 +8,8 @@ namespace icsneo {
|
||||||
|
|
||||||
void init_messagefilter(pybind11::module_& m) {
|
void init_messagefilter(pybind11::module_& m) {
|
||||||
pybind11::class_<MessageFilter, std::shared_ptr<MessageFilter>>(m, "MessageFilter")
|
pybind11::class_<MessageFilter, std::shared_ptr<MessageFilter>>(m, "MessageFilter")
|
||||||
|
.def(pybind11::init())
|
||||||
|
.def(pybind11::init<Message::Type>())
|
||||||
.def(pybind11::init<Network::NetID>());
|
.def(pybind11::init<Network::NetID>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,79 @@
|
||||||
|
#include <pybind11/pybind11.h>
|
||||||
|
#include <pybind11/stl.h>
|
||||||
|
#include <pybind11/functional.h>
|
||||||
|
|
||||||
|
#include "icsneo/communication/message/gptpstatusmessage.h"
|
||||||
|
|
||||||
|
namespace icsneo {
|
||||||
|
|
||||||
|
void init_gptpstatusmessage(pybind11::module_& m) {
|
||||||
|
pybind11::class_<GPTPStatus, std::shared_ptr<GPTPStatus>, Message> gptpStatus(m, "GPTPStatus");
|
||||||
|
|
||||||
|
pybind11::class_<GPTPStatus::Timestamp>(gptpStatus, "Timestamp")
|
||||||
|
.def_readonly("seconds", &GPTPStatus::Timestamp::seconds)
|
||||||
|
.def_readonly("nanoseconds", &GPTPStatus::Timestamp::nanoseconds)
|
||||||
|
.def("to_seconds", &GPTPStatus::Timestamp::toSeconds, pybind11::call_guard<pybind11::gil_scoped_release>());
|
||||||
|
|
||||||
|
pybind11::class_<GPTPStatus::ScaledNanoSeconds>(gptpStatus, "ScaledNanoSeconds")
|
||||||
|
.def_readonly("nanosecondsMSB", &GPTPStatus::ScaledNanoSeconds::nanosecondsMSB)
|
||||||
|
.def_readonly("nanosecondsLSB", &GPTPStatus::ScaledNanoSeconds::nanosecondsLSB)
|
||||||
|
.def_readonly("fractionalNanoseconds", &GPTPStatus::ScaledNanoSeconds::fractionalNanoseconds);
|
||||||
|
|
||||||
|
pybind11::class_<GPTPStatus::PortID>(gptpStatus, "PortID")
|
||||||
|
.def_readonly("clockIdentity", &GPTPStatus::PortID::clockIdentity)
|
||||||
|
.def_readonly("portNumber", &GPTPStatus::PortID::portNumber);
|
||||||
|
|
||||||
|
pybind11::class_<GPTPStatus::ClockQuality>(gptpStatus, "ClockQuality")
|
||||||
|
.def_readonly("clockClass", &GPTPStatus::ClockQuality::clockClass)
|
||||||
|
.def_readonly("clockAccuracy", &GPTPStatus::ClockQuality::clockAccuracy)
|
||||||
|
.def_readonly("offsetScaledLogVariance", &GPTPStatus::ClockQuality::offsetScaledLogVariance);
|
||||||
|
|
||||||
|
pybind11::class_<GPTPStatus::SystemID>(gptpStatus, "SystemID")
|
||||||
|
.def_readonly("priority1", &GPTPStatus::SystemID::priority1)
|
||||||
|
.def_readonly("clockQuality", &GPTPStatus::SystemID::clockQuality)
|
||||||
|
.def_readonly("priority2", &GPTPStatus::SystemID::priority2)
|
||||||
|
.def_readonly("clockID", &GPTPStatus::SystemID::clockID);
|
||||||
|
|
||||||
|
pybind11::class_<GPTPStatus::PriorityVector>(gptpStatus, "PriorityVector")
|
||||||
|
.def_readonly("sysID", &GPTPStatus::PriorityVector::sysID)
|
||||||
|
.def_readonly("stepsRemoved", &GPTPStatus::PriorityVector::stepsRemoved)
|
||||||
|
.def_readonly("portID", &GPTPStatus::PriorityVector::portID)
|
||||||
|
.def_readonly("portNumber", &GPTPStatus::PriorityVector::portNumber);
|
||||||
|
|
||||||
|
pybind11::class_<GPTPStatus::ParentDS>(gptpStatus, "ParentDS")
|
||||||
|
.def_readonly("parentPortIdentity", &GPTPStatus::ParentDS::parentPortIdentity)
|
||||||
|
.def_readonly("cumulativeRateRatio", &GPTPStatus::ParentDS::cumulativeRateRatio)
|
||||||
|
.def_readonly("grandmasterIdentity", &GPTPStatus::ParentDS::grandmasterIdentity)
|
||||||
|
.def_readonly("gmClockQualityClockClass", &GPTPStatus::ParentDS::gmClockQualityClockClass)
|
||||||
|
.def_readonly("gmClockQualityClockAccuracy", &GPTPStatus::ParentDS::gmClockQualityClockAccuracy)
|
||||||
|
.def_readonly("gmClockQualityOffsetScaledLogVariance", &GPTPStatus::ParentDS::gmClockQualityOffsetScaledLogVariance)
|
||||||
|
.def_readonly("gmPriority1", &GPTPStatus::ParentDS::gmPriority1)
|
||||||
|
.def_readonly("gmPriority2", &GPTPStatus::ParentDS::gmPriority2);
|
||||||
|
|
||||||
|
pybind11::class_<GPTPStatus::CurrentDS>(gptpStatus, "CurrentDS")
|
||||||
|
.def_readonly("stepsRemoved", &GPTPStatus::CurrentDS::stepsRemoved)
|
||||||
|
.def_readonly("offsetFromMaster", &GPTPStatus::CurrentDS::offsetFromMaster)
|
||||||
|
.def_readonly("lastgmPhaseChange", &GPTPStatus::CurrentDS::lastgmPhaseChange)
|
||||||
|
.def_readonly("lastgmFreqChange", &GPTPStatus::CurrentDS::lastgmFreqChange)
|
||||||
|
.def_readonly("gmTimeBaseIndicator", &GPTPStatus::CurrentDS::gmTimeBaseIndicator)
|
||||||
|
.def_readonly("gmChangeCount", &GPTPStatus::CurrentDS::gmChangeCount)
|
||||||
|
.def_readonly("timeOfLastgmChangeEvent", &GPTPStatus::CurrentDS::timeOfLastgmChangeEvent)
|
||||||
|
.def_readonly("timeOfLastgmPhaseChangeEvent", &GPTPStatus::CurrentDS::timeOfLastgmPhaseChangeEvent)
|
||||||
|
.def_readonly("timeOfLastgmFreqChangeEvent", &GPTPStatus::CurrentDS::timeOfLastgmFreqChangeEvent);
|
||||||
|
|
||||||
|
gptpStatus.def_readonly("currentTime", &GPTPStatus::currentTime)
|
||||||
|
.def_readonly("gmPriority", &GPTPStatus::gmPriority)
|
||||||
|
.def_readonly("msOffsetNs", &GPTPStatus::msOffsetNs)
|
||||||
|
.def_readonly("isSync", &GPTPStatus::isSync)
|
||||||
|
.def_readonly("linkStatus", &GPTPStatus::linkStatus)
|
||||||
|
.def_readonly("linkDelayNS", &GPTPStatus::linkDelayNS)
|
||||||
|
.def_readonly("selectedRole", &GPTPStatus::selectedRole)
|
||||||
|
.def_readonly("asCapable", &GPTPStatus::asCapable)
|
||||||
|
.def_readonly("isSyntonized", &GPTPStatus::isSyntonized)
|
||||||
|
.def_readonly("lastRXSyncTS", &GPTPStatus::lastRXSyncTS)
|
||||||
|
.def_readonly("currentDS", &GPTPStatus::currentDS)
|
||||||
|
.def_readonly("parentDS", &GPTPStatus::parentDS);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace icsneo
|
||||||
|
|
@ -0,0 +1,160 @@
|
||||||
|
#include <pybind11/pybind11.h>
|
||||||
|
#include <pybind11/stl.h>
|
||||||
|
#include <pybind11/functional.h>
|
||||||
|
|
||||||
|
#include "icsneo/communication/message/macsecmessage.h"
|
||||||
|
|
||||||
|
namespace icsneo {
|
||||||
|
|
||||||
|
void init_macsecmessage(pybind11::module_ & m)
|
||||||
|
{
|
||||||
|
pybind11::enum_<MACsecPacketType>(m, "MACsecPacketType")
|
||||||
|
.value("NoVLAN_OrMPLS", MACsecPacketType::NoVLANOrMPLS)
|
||||||
|
.value("SingleVLAN", MACsecPacketType::SingleVLAN)
|
||||||
|
.value("DualVLAN", MACsecPacketType::DualVLAN)
|
||||||
|
.value("MPLS", MACsecPacketType::MPLS)
|
||||||
|
.value("SingleVLAN_FollowByMPLS", MACsecPacketType::SingleVLANFollowedByMPLS)
|
||||||
|
.value("DualVLAN_FollowByMPLS", MACsecPacketType::DualVLANFollowedByMPLS)
|
||||||
|
.value("Unsupported", MACsecPacketType::Unsupported);
|
||||||
|
|
||||||
|
pybind11::enum_<MACsecValidateFrameType>(m, "MACsecValidateFrameType")
|
||||||
|
.value("Disabled", MACsecValidateFrameType::Disabled)
|
||||||
|
.value("Check", MACsecValidateFrameType::Check)
|
||||||
|
.value("Strict", MACsecValidateFrameType::Strict)
|
||||||
|
.value("NA", MACsecValidateFrameType::NA);
|
||||||
|
|
||||||
|
pybind11::enum_<MACsecSecTagIcvStripType>(m, "MACsecSecTagIcvStripType")
|
||||||
|
.value("StripBoth", MACsecSecTagIcvStripType::StripBoth)
|
||||||
|
.value("StripSecTagPreserveICV", MACsecSecTagIcvStripType::StripSecTagPreserveICV)
|
||||||
|
.value("PreserveSecTagStripICV", MACsecSecTagIcvStripType::PreserveSecTagStripICV)
|
||||||
|
.value("PreserveBoth", MACsecSecTagIcvStripType::PreserveBoth);
|
||||||
|
|
||||||
|
pybind11::enum_<MACsecCipherSuiteType>(m, "MACsecCipherSuiteType")
|
||||||
|
.value("AES_128", MACsecCipherSuiteType::GcmAes128)
|
||||||
|
.value("AES_256", MACsecCipherSuiteType::GcmAes256)
|
||||||
|
.value("AES_128_XPN", MACsecCipherSuiteType::GcmAes128Xpn)
|
||||||
|
.value("AES_256_XPN", MACsecCipherSuiteType::GcmAes256Xpn);
|
||||||
|
|
||||||
|
pybind11::class_<MACsecVLANTag, std::shared_ptr<MACsecVLANTag>>(m, "MACsecVLANTag")
|
||||||
|
.def(pybind11::init())
|
||||||
|
.def_readwrite("vid", &MACsecVLANTag::vid)
|
||||||
|
.def_readwrite("pri_cfi", &MACsecVLANTag::priCfi);
|
||||||
|
|
||||||
|
pybind11::class_<MACsecMPLSOuter, std::shared_ptr<MACsecMPLSOuter>>(m, "MACsecMPLSOuter")
|
||||||
|
.def(pybind11::init())
|
||||||
|
.def_readwrite("mpls_label", &MACsecMPLSOuter::mplsLabel)
|
||||||
|
.def_readwrite("exp", &MACsecMPLSOuter::exp);
|
||||||
|
|
||||||
|
pybind11::class_<MACsecRule, std::shared_ptr<MACsecRule>>(m, "MACsecRule")
|
||||||
|
.def(pybind11::init())
|
||||||
|
.def_readwrite("index", &MACsecRule::index)
|
||||||
|
.def_readwrite("keyMacDa", &MACsecRule::keyMacDa)
|
||||||
|
.def_readwrite("maskMacDa", &MACsecRule::maskMacDa)
|
||||||
|
.def_readwrite("keyMacSa", &MACsecRule::keyMacSa)
|
||||||
|
.def_readwrite("maskMacSa", &MACsecRule::maskMacSa)
|
||||||
|
.def_readwrite("keyEthertype", &MACsecRule::keyEthertype)
|
||||||
|
.def_readwrite("maskEthertype", &MACsecRule::maskEthertype)
|
||||||
|
.def_readwrite("keyVlanTagOuter1", &MACsecRule::keyVlanTagOuter1)
|
||||||
|
.def_readwrite("keyMplsOuter1", &MACsecRule::keyMplsOuter1)
|
||||||
|
.def_readwrite("maskVlanTagOuter1", &MACsecRule::maskVlanTagOuter1)
|
||||||
|
.def_readwrite("maskMplsOuter1", &MACsecRule::maskMplsOuter1)
|
||||||
|
.def_readwrite("keyVlanTagOuter2", &MACsecRule::keyVlanTagOuter2)
|
||||||
|
.def_readwrite("keyMplsOuter2", &MACsecRule::keyMplsOuter2)
|
||||||
|
.def_readwrite("maskVlanTagOuter2", &MACsecRule::maskVlanTagOuter2)
|
||||||
|
.def_readwrite("maskMplsOuter2", &MACsecRule::maskMplsOuter2)
|
||||||
|
.def_readwrite("keyBonusData", &MACsecRule::keyBonusData)
|
||||||
|
.def_readwrite("maskBonusData", &MACsecRule::maskBonusData)
|
||||||
|
.def_readwrite("keyTagMatchBitmap", &MACsecRule::keyTagMatchBitmap)
|
||||||
|
.def_readwrite("maskTagMatchBitmap", &MACsecRule::maskTagMatchBitmap)
|
||||||
|
.def_readwrite("keyPacketType", &MACsecRule::keyPacketType)
|
||||||
|
.def_readwrite("maskPacketType", &MACsecRule::maskPacketType)
|
||||||
|
.def_readwrite("keyInnerVlanType", &MACsecRule::keyInnerVlanType)
|
||||||
|
.def_readwrite("maskInnerVlanType", &MACsecRule::maskInnerVlanType)
|
||||||
|
.def_readwrite("keyOuterVlanType", &MACsecRule::keyOuterVlanType)
|
||||||
|
.def_readwrite("maskOuterVlanType", &MACsecRule::maskOuterVlanType)
|
||||||
|
.def_readwrite("keyNumTags", &MACsecRule::keyNumTags)
|
||||||
|
.def_readwrite("maskNumTags", &MACsecRule::maskNumTags)
|
||||||
|
.def_readwrite("keyExpress", &MACsecRule::keyExpress)
|
||||||
|
.def_readwrite("maskExpress", &MACsecRule::maskExpress)
|
||||||
|
.def_readwrite("isMpls", &MACsecRule::isMpls)
|
||||||
|
.def_readwrite("enable", &MACsecRule::enable);
|
||||||
|
|
||||||
|
pybind11::class_<MACsecMap, std::shared_ptr<MACsecMap>>(m, "MACsecMap")
|
||||||
|
.def(pybind11::init())
|
||||||
|
.def_readwrite("index", &MACsecMap::index)
|
||||||
|
.def_readwrite("secTagSci", &MACsecMap::secTagSci)
|
||||||
|
.def_readwrite("secYIndex", &MACsecMap::secYIndex)
|
||||||
|
.def_readwrite("isControlPacket", &MACsecMap::isControlPacket)
|
||||||
|
.def_readwrite("scIndex", &MACsecMap::scIndex)
|
||||||
|
.def_readwrite("auxiliaryPlcy", &MACsecMap::auxiliaryPlcy)
|
||||||
|
.def_readwrite("ruleId", &MACsecMap::ruleId)
|
||||||
|
.def_readwrite("enable", &MACsecMap::enable);
|
||||||
|
|
||||||
|
pybind11::class_<MACsecSecY, std::shared_ptr<MACsecSecY>>(m, "MACsecSecY")
|
||||||
|
.def(pybind11::init())
|
||||||
|
.def_readwrite("index", &MACsecSecY::index)
|
||||||
|
.def_readwrite("controlledPortEnabled", &MACsecSecY::controlledPortEnabled)
|
||||||
|
.def_readwrite("frameValidationType", &MACsecSecY::frameValidationType)
|
||||||
|
.def_readwrite("secTagIcvStripType", &MACsecSecY::secTagIcvStripType)
|
||||||
|
.def_readwrite("cipher", &MACsecSecY::cipher)
|
||||||
|
.def_readwrite("confidentialOffset", &MACsecSecY::confidentialOffset)
|
||||||
|
.def_readwrite("icvIncludesDaSa", &MACsecSecY::icvIncludesDaSa)
|
||||||
|
.def_readwrite("replayProtect", &MACsecSecY::replayProtect)
|
||||||
|
.def_readwrite("replayWindow", &MACsecSecY::replayWindow)
|
||||||
|
.def_readwrite("protectFrames", &MACsecSecY::protectFrames)
|
||||||
|
.def_readwrite("secTagOffset", &MACsecSecY::secTagOffset)
|
||||||
|
.def_readwrite("secTagTci", &MACsecSecY::secTagTci)
|
||||||
|
.def_readwrite("mtu", &MACsecSecY::mtu)
|
||||||
|
.def_readwrite("enable", &MACsecSecY::enable);
|
||||||
|
|
||||||
|
pybind11::class_<MACsecSc, std::shared_ptr<MACsecSc>>(m, "MACsecSc")
|
||||||
|
.def(pybind11::init())
|
||||||
|
.def_readwrite("index", &MACsecSc::index)
|
||||||
|
.def_readwrite("secYIndex", &MACsecSc::secYIndex)
|
||||||
|
.def_readwrite("sci", &MACsecSc::sci)
|
||||||
|
.def_readwrite("saIndex0", &MACsecSc::saIndex0)
|
||||||
|
.def_readwrite("saIndex1", &MACsecSc::saIndex1)
|
||||||
|
.def_readwrite("saIndex0InUse", &MACsecSc::saIndex0InUse)
|
||||||
|
.def_readwrite("saIndex1InUse", &MACsecSc::saIndex1InUse)
|
||||||
|
.def_readwrite("enableAutoRekey", &MACsecSc::enableAutoRekey)
|
||||||
|
.def_readwrite("isActiveSa1", &MACsecSc::isActiveSa1)
|
||||||
|
.def_readwrite("enable", &MACsecSc::enable);
|
||||||
|
|
||||||
|
pybind11::class_<MACsecSa, std::shared_ptr<MACsecSa>>(m, "MACsecSa")
|
||||||
|
.def(pybind11::init())
|
||||||
|
.def_readwrite("index", &MACsecSa::index)
|
||||||
|
.def_readwrite("sak", &MACsecSa::sak)
|
||||||
|
.def_readwrite("hashKey", &MACsecSa::hashKey)
|
||||||
|
.def_readwrite("salt", &MACsecSa::salt)
|
||||||
|
.def_readwrite("ssci", &MACsecSa::ssci)
|
||||||
|
.def_readwrite("an", &MACsecSa::an)
|
||||||
|
.def_readwrite("nextPn", &MACsecSa::nextPn)
|
||||||
|
.def_readwrite("enable", &MACsecSa::enable);
|
||||||
|
|
||||||
|
pybind11::class_<MACSecFlags, std::shared_ptr<MACSecFlags>>(m, "MACSecFlags")
|
||||||
|
.def(pybind11::init())
|
||||||
|
.def_readwrite("en", &MACSecFlags::en);
|
||||||
|
|
||||||
|
pybind11::class_<MACsecConfig, std::shared_ptr<MACsecConfig>>(m, "MACsecConfig")
|
||||||
|
.def(pybind11::init())
|
||||||
|
.def_readwrite("flags", &MACsecConfig::flags)
|
||||||
|
.def_readwrite("rule", &MACsecConfig::rule)
|
||||||
|
.def_readwrite("map", &MACsecConfig::map)
|
||||||
|
.def_readwrite("secy", &MACsecConfig::secy)
|
||||||
|
.def_readwrite("sc", &MACsecConfig::sc)
|
||||||
|
.def_readwrite("sa", &MACsecConfig::sa);
|
||||||
|
|
||||||
|
pybind11::class_<MACSecGlobalFlags, std::shared_ptr<MACSecGlobalFlags>>(m, "MACSecGlobalFlags")
|
||||||
|
.def(pybind11::init())
|
||||||
|
.def_readwrite("en", &MACSecGlobalFlags::en)
|
||||||
|
.def_readwrite("nvm", &MACSecGlobalFlags::nvm);
|
||||||
|
|
||||||
|
pybind11::class_<MACsecMessage, std::shared_ptr<MACsecMessage>>(m, "MACsecMessage")
|
||||||
|
.def(pybind11::init())
|
||||||
|
.def_readwrite("flags", &MACsecMessage::flags)
|
||||||
|
.def_readwrite("rx", &MACsecMessage::rx)
|
||||||
|
.def_readwrite("tx", &MACsecMessage::tx);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace icsneo
|
||||||
|
|
||||||
|
|
@ -11,6 +11,7 @@ void init_message(pybind11::module_& m) {
|
||||||
pybind11::enum_<Message::Type>(message, "Type")
|
pybind11::enum_<Message::Type>(message, "Type")
|
||||||
.value("Frame", Message::Type::Frame)
|
.value("Frame", Message::Type::Frame)
|
||||||
.value("CANErrorCount", Message::Type::CANErrorCount)
|
.value("CANErrorCount", Message::Type::CANErrorCount)
|
||||||
|
.value("CANError", Message::Type::CANError)
|
||||||
.value("LINHeaderOnly", Message::Type::LINHeaderOnly)
|
.value("LINHeaderOnly", Message::Type::LINHeaderOnly)
|
||||||
.value("LINBreak", Message::Type::LINBreak)
|
.value("LINBreak", Message::Type::LINBreak)
|
||||||
.value("Invalid", Message::Type::Invalid)
|
.value("Invalid", Message::Type::Invalid)
|
||||||
|
|
@ -31,7 +32,9 @@ void init_message(pybind11::module_& m) {
|
||||||
.value("LiveData", Message::Type::LiveData)
|
.value("LiveData", Message::Type::LiveData)
|
||||||
.value("HardwareInfo", Message::Type::HardwareInfo)
|
.value("HardwareInfo", Message::Type::HardwareInfo)
|
||||||
.value("TC10Status", Message::Type::TC10Status)
|
.value("TC10Status", Message::Type::TC10Status)
|
||||||
.value("AppError", Message::Type::AppError);
|
.value("AppError", Message::Type::AppError)
|
||||||
|
.value("GPTPStatus", Message::Type::GPTPStatus)
|
||||||
|
.value("EthernetStatus", Message::Type::EthernetStatus);
|
||||||
|
|
||||||
message.def(pybind11::init<Message::Type>());
|
message.def(pybind11::init<Message::Type>());
|
||||||
message.def_readonly("type", &Message::type);
|
message.def_readonly("type", &Message::type);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
#include <pybind11/pybind11.h>
|
||||||
|
#include <pybind11/stl.h>
|
||||||
|
#include <pybind11/functional.h>
|
||||||
|
|
||||||
|
#include "icsneo/communication/message/scriptstatusmessage.h"
|
||||||
|
|
||||||
|
namespace icsneo {
|
||||||
|
|
||||||
|
void init_scriptstatusmessage(pybind11::module_& m) {
|
||||||
|
pybind11::class_<ScriptStatusMessage, std::shared_ptr<ScriptStatusMessage>, Message>(m, "ScriptStatusMessage")
|
||||||
|
.def_readonly("isEncrypted", &ScriptStatusMessage::isEncrypted)
|
||||||
|
.def_readonly("isCoreminiRunning", &ScriptStatusMessage::isCoreminiRunning)
|
||||||
|
.def_readonly("sectorOverflows", &ScriptStatusMessage::sectorOverflows)
|
||||||
|
.def_readonly("numRemainingSectorBuffers", &ScriptStatusMessage::numRemainingSectorBuffers)
|
||||||
|
.def_readonly("lastSector", &ScriptStatusMessage::lastSector)
|
||||||
|
.def_readonly("readBinSize", &ScriptStatusMessage::readBinSize)
|
||||||
|
.def_readonly("minSector", &ScriptStatusMessage::minSector)
|
||||||
|
.def_readonly("maxSector", &ScriptStatusMessage::maxSector)
|
||||||
|
.def_readonly("currentSector", &ScriptStatusMessage::currentSector)
|
||||||
|
.def_readonly("coreminiCreateTime", &ScriptStatusMessage::coreminiCreateTime)
|
||||||
|
.def_readonly("fileChecksum", &ScriptStatusMessage::fileChecksum)
|
||||||
|
.def_readonly("coreminiVersion", &ScriptStatusMessage::coreminiVersion)
|
||||||
|
.def_readonly("coreminiHeaderSize", &ScriptStatusMessage::coreminiHeaderSize)
|
||||||
|
.def_readonly("diagnosticErrorCode", &ScriptStatusMessage::diagnosticErrorCode)
|
||||||
|
.def_readonly("diagnosticErrorCodeCount", &ScriptStatusMessage::diagnosticErrorCodeCount)
|
||||||
|
.def_readonly("maxCoreminiSizeKB", &ScriptStatusMessage::maxCoreminiSizeKB);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace icsneo
|
||||||
|
|
||||||
|
|
@ -5,40 +5,51 @@
|
||||||
|
|
||||||
#include "icsneo/device/device.h"
|
#include "icsneo/device/device.h"
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
namespace icsneo {
|
namespace icsneo {
|
||||||
|
|
||||||
void init_device(pybind11::module_& m) {
|
void init_device(pybind11::module_& m) {
|
||||||
pybind11::class_<Device, std::shared_ptr<Device>>(m, "Device")
|
pybind11::class_<Device, std::shared_ptr<Device>>(m, "Device")
|
||||||
.def("get_type", &Device::getType)
|
.def("__repr__", &Device::describe)
|
||||||
.def("get_serial", &Device::getSerial)
|
.def("add_message_callback", &Device::addMessageCallback, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||||
.def("get_serial_number", &Device::getSerialNumber)
|
.def("clear_script", &Device::clearScript, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||||
.def("get_product_name", &Device::getProductName)
|
.def("close", &Device::close, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||||
.def("open", [](Device& device) { return device.open(); })
|
.def("describe", &Device::describe)
|
||||||
.def("close", &Device::close)
|
.def("disable_message_polling", &Device::disableMessagePolling, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||||
.def("is_open", &Device::isOpen)
|
.def("enable_message_polling", &Device::enableMessagePolling, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||||
.def("go_online", &Device::goOnline)
|
|
||||||
.def("go_offline", &Device::goOffline)
|
|
||||||
.def("is_online", &Device::isOnline).def("enable_message_polling", &Device::enableMessagePolling)
|
|
||||||
.def("disable_message_polling", &Device::disableMessagePolling)
|
|
||||||
.def("is_message_polling_enabled", &Device::isMessagePollingEnabled)
|
|
||||||
.def("get_messages", [](Device& device) { return device.getMessages(); })
|
|
||||||
.def("get_current_message_count", &Device::getCurrentMessageCount)
|
.def("get_current_message_count", &Device::getCurrentMessageCount)
|
||||||
|
.def("get_gptp_status", &Device::getGPTPStatus, pybind11::arg("timeout") = std::chrono::milliseconds(100), pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||||
|
.def("get_messages", [](Device& device) { return device.getMessages(); }, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||||
.def("get_polling_message_limit", &Device::getPollingMessageLimit)
|
.def("get_polling_message_limit", &Device::getPollingMessageLimit)
|
||||||
.def("set_polling_message_limit", &Device::setPollingMessageLimit)
|
.def("get_product_name", &Device::getProductName)
|
||||||
.def("add_message_callback", &Device::addMessageCallback)
|
.def("get_rtc", &Device::getRTC, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||||
.def("remove_message_callback", &Device::removeMessageCallback)
|
.def("get_script_status", &Device::getScriptStatus, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||||
.def("transmit", pybind11::overload_cast<std::shared_ptr<Frame>>(&Device::transmit))
|
.def("get_serial_number", &Device::getSerialNumber)
|
||||||
|
.def("get_serial", &Device::getSerial)
|
||||||
.def("get_supported_rx_networks", &Device::getSupportedRXNetworks, pybind11::return_value_policy::reference)
|
.def("get_supported_rx_networks", &Device::getSupportedRXNetworks, pybind11::return_value_policy::reference)
|
||||||
.def("get_supported_tx_networks", &Device::getSupportedTXNetworks, pybind11::return_value_policy::reference)
|
.def("get_supported_tx_networks", &Device::getSupportedTXNetworks, pybind11::return_value_policy::reference)
|
||||||
.def("get_rtc", &Device::getRTC)
|
.def("get_tc10_status", &Device::getTC10Status, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||||
.def("set_rtc", &Device::setRTC)
|
.def("get_type", &Device::getType)
|
||||||
.def("describe", &Device::describe)
|
.def("go_offline", &Device::goOffline, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||||
|
.def("go_online", &Device::goOnline, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||||
|
.def("is_message_polling_enabled", &Device::isMessagePollingEnabled)
|
||||||
.def("is_online_supported", &Device::isOnlineSupported)
|
.def("is_online_supported", &Device::isOnlineSupported)
|
||||||
|
.def("is_online", &Device::isOnline)
|
||||||
|
.def("is_open", &Device::isOpen)
|
||||||
|
.def("open", [](Device& device) { return device.open(); }, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||||
|
.def("prepare_script_load", &Device::prepareScriptLoad, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||||
|
.def("remove_message_callback", &Device::removeMessageCallback, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||||
|
.def("request_tc10_sleep", &Device::requestTC10Sleep, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||||
|
.def("request_tc10_wake", &Device::requestTC10Wake, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||||
|
.def("set_polling_message_limit", &Device::setPollingMessageLimit)
|
||||||
|
.def("set_rtc", &Device::setRTC, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||||
|
.def("start_script", &Device::startScript, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||||
|
.def("stop_script", &Device::stopScript, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||||
.def("supports_tc10", &Device::supportsTC10)
|
.def("supports_tc10", &Device::supportsTC10)
|
||||||
.def("request_tc10_wake", &Device::requestTC10Wake)
|
.def("transmit", pybind11::overload_cast<std::shared_ptr<Frame>>(&Device::transmit), pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||||
.def("request_tc10_sleep", &Device::requestTC10Sleep)
|
.def("upload_coremini", [](Device& device, std::string& path, Disk::MemoryType memType) { std::ifstream ifs(path, std::ios::binary); return device.uploadCoremini(ifs, memType); }, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||||
.def("get_tc10_status", &Device::getTC10Status)
|
.def("write_macsec_config", &Device::writeMACsecConfig, pybind11::call_guard<pybind11::gil_scoped_release>());
|
||||||
.def("__repr__", &Device::describe);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace icsneo
|
} // namespace icsneo
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
#include <pybind11/pybind11.h>
|
||||||
|
#include <pybind11/stl.h>
|
||||||
|
#include <pybind11/functional.h>
|
||||||
|
|
||||||
|
#include "icsneo/disk/diskdriver.h"
|
||||||
|
|
||||||
|
namespace icsneo {
|
||||||
|
|
||||||
|
void init_diskdriver(pybind11::module_& m) {
|
||||||
|
auto disk = m.def_submodule("disk");
|
||||||
|
pybind11::enum_<Disk::Access>(disk, "Access")
|
||||||
|
.value("None", Disk::Access::None)
|
||||||
|
.value("EntireCard", Disk::Access::EntireCard)
|
||||||
|
.value("VSA", Disk::Access::VSA);
|
||||||
|
pybind11::enum_<Disk::MemoryType>(disk, "MemoryType")
|
||||||
|
.value("Flash", Disk::MemoryType::Flash)
|
||||||
|
.value("SD", Disk::MemoryType::SD);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace icsneo
|
||||||
|
|
@ -13,16 +13,24 @@ void init_network(pybind11::module_&);
|
||||||
void init_devicetype(pybind11::module_&);
|
void init_devicetype(pybind11::module_&);
|
||||||
void init_message(pybind11::module_&);
|
void init_message(pybind11::module_&);
|
||||||
void init_canmessage(pybind11::module_&);
|
void init_canmessage(pybind11::module_&);
|
||||||
|
void init_canerrormessage(pybind11::module_&);
|
||||||
void init_ethernetmessage(pybind11::module_&);
|
void init_ethernetmessage(pybind11::module_&);
|
||||||
void init_linmessage(pybind11::module_&);
|
void init_linmessage(pybind11::module_&);
|
||||||
void init_tc10statusmessage(pybind11::module_&);
|
void init_tc10statusmessage(pybind11::module_&);
|
||||||
|
void init_gptpstatusmessage(pybind11::module_&);
|
||||||
void init_mdiomessage(pybind11::module_&);
|
void init_mdiomessage(pybind11::module_&);
|
||||||
|
void init_ethernetstatusmessage(pybind11::module_&);
|
||||||
|
void init_macsecmessage(pybind11::module_&);
|
||||||
|
void init_scriptstatusmessage(pybind11::module_&);
|
||||||
|
void init_diskdriver(pybind11::module_&);
|
||||||
void init_device(pybind11::module_&);
|
void init_device(pybind11::module_&);
|
||||||
void init_messagefilter(pybind11::module_&);
|
void init_messagefilter(pybind11::module_&);
|
||||||
void init_messagecallback(pybind11::module_&);
|
void init_messagecallback(pybind11::module_&);
|
||||||
void init_version(pybind11::module_&);
|
void init_version(pybind11::module_&);
|
||||||
|
|
||||||
PYBIND11_MODULE(icsneopy, m) {
|
PYBIND11_MODULE(icsneopy, m) {
|
||||||
|
pybind11::options options;
|
||||||
|
options.disable_enum_members_docstring();
|
||||||
m.doc() = "libicsneo Python module";
|
m.doc() = "libicsneo Python module";
|
||||||
|
|
||||||
init_event(m);
|
init_event(m);
|
||||||
|
|
@ -33,12 +41,18 @@ PYBIND11_MODULE(icsneopy, m) {
|
||||||
init_network(m);
|
init_network(m);
|
||||||
init_message(m);
|
init_message(m);
|
||||||
init_canmessage(m);
|
init_canmessage(m);
|
||||||
|
init_canerrormessage(m);
|
||||||
init_ethernetmessage(m);
|
init_ethernetmessage(m);
|
||||||
init_linmessage(m);
|
init_linmessage(m);
|
||||||
init_tc10statusmessage(m);
|
init_tc10statusmessage(m);
|
||||||
|
init_gptpstatusmessage(m);
|
||||||
init_mdiomessage(m);
|
init_mdiomessage(m);
|
||||||
|
init_ethernetstatusmessage(m);
|
||||||
|
init_macsecmessage(m);
|
||||||
|
init_scriptstatusmessage(m);
|
||||||
init_messagefilter(m);
|
init_messagefilter(m);
|
||||||
init_messagecallback(m);
|
init_messagecallback(m);
|
||||||
|
init_diskdriver(m);
|
||||||
init_device(m);
|
init_device(m);
|
||||||
|
|
||||||
m.def("find_all_devices", &FindAllDevices);
|
m.def("find_all_devices", &FindAllDevices);
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
cmake -GNinja -Bbuild -DCMAKE_BUILD_TYPE=Release -DLIBICSNEO_BUILD_EXAMPLES=ON \
|
cmake -GNinja -Bbuild -DCMAKE_BUILD_TYPE=Release -DLIBICSNEO_BUILD_EXAMPLES=ON \
|
||||||
-DLIBICSNEO_BUILD_UNIT_TESTS=ON -DLIBICSNEO_BUILD_SYSTEM_TESTS=ON -DLIBICSNEO_ENABLE_TCP=OFF || exit 1
|
-DLIBICSNEO_BUILD_UNIT_TESTS=ON -DLIBICSNEO_ENABLE_TCP=OFF || exit 1
|
||||||
|
|
||||||
cmake --build build || exit 1
|
cmake --build build || exit 1
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ REM build
|
||||||
cd build
|
cd build
|
||||||
set CFLAGS=/WX
|
set CFLAGS=/WX
|
||||||
set CXXFLAGS=/WX
|
set CXXFLAGS=/WX
|
||||||
cmake -GNinja -DCMAKE_BUILD_TYPE=RelWithDebInfo -DLIBICSNEO_BUILD_UNIT_TESTS=ON -DLIBICSNEO_BUILD_SYSTEM_TESTS=ON -DLIBICSNEO_ENABLE_TCP=ON ..
|
cmake -GNinja -DCMAKE_BUILD_TYPE=RelWithDebInfo -DLIBICSNEO_BUILD_UNIT_TESTS=ON -DLIBICSNEO_ENABLE_TCP=ON ..
|
||||||
if %errorlevel% neq 0 exit /b %errorlevel%
|
if %errorlevel% neq 0 exit /b %errorlevel%
|
||||||
cmake --build .
|
cmake --build .
|
||||||
if %errorlevel% neq 0 exit /b %errorlevel%
|
if %errorlevel% neq 0 exit /b %errorlevel%
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,2 @@
|
||||||
call "%VCVARS32%"
|
call "%VCVARS32_2022%"
|
||||||
call "ci\build-windows.bat"
|
call "ci\build-windows.bat"
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,2 @@
|
||||||
call "%VCVARS64%"
|
call "%VCVARS64_2022%"
|
||||||
call "ci\build-windows.bat"
|
call "ci\build-windows.bat"
|
||||||
|
|
|
||||||
|
|
@ -37,29 +37,28 @@ bool Communication::open() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Communication::spawnThreads() {
|
void Communication::spawnThreads() {
|
||||||
|
closing = false;
|
||||||
readTaskThread = std::thread(&Communication::readTask, this);
|
readTaskThread = std::thread(&Communication::readTask, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Communication::joinThreads() {
|
void Communication::joinThreads() {
|
||||||
closing = true;
|
|
||||||
|
|
||||||
if(pauseReadTask) {
|
if(pauseReadTask) {
|
||||||
resumeReads();
|
resumeReads();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
closing = true;
|
||||||
if(readTaskThread.joinable())
|
if(readTaskThread.joinable())
|
||||||
readTaskThread.join();
|
readTaskThread.join();
|
||||||
closing = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Communication::close() {
|
bool Communication::close() {
|
||||||
joinThreads();
|
|
||||||
|
|
||||||
if(!isOpen() && !isDisconnected()) {
|
if(!isOpen() && !isDisconnected()) {
|
||||||
report(APIEvent::Type::DeviceCurrentlyClosed, APIEvent::Severity::Error);
|
report(APIEvent::Type::DeviceCurrentlyClosed, APIEvent::Severity::Error);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
joinThreads();
|
||||||
|
|
||||||
return driver->close();
|
return driver->close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,69 @@
|
||||||
|
/*
|
||||||
|
* crc32.c
|
||||||
|
*
|
||||||
|
* Created on: Jun 22, 2020
|
||||||
|
* Author: BJones
|
||||||
|
*/
|
||||||
|
#include "icsneo/communication/crc32.h"
|
||||||
|
|
||||||
|
static const unsigned long crc32_table[256] = { 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535,
|
||||||
|
0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2,
|
||||||
|
0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F,
|
||||||
|
0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
|
||||||
|
0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC, 0x51DE003A, 0xC8D75180,
|
||||||
|
0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11,
|
||||||
|
0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, 0x7807C9A2,
|
||||||
|
0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
|
||||||
|
0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3,
|
||||||
|
0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC,
|
||||||
|
0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525,
|
||||||
|
0x206F85B3, 0xB966D409, 0xCE61E49F, 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
|
||||||
|
0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E,
|
||||||
|
0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB,
|
||||||
|
0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8,
|
||||||
|
0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60,
|
||||||
|
0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9,
|
||||||
|
0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226,
|
||||||
|
0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B,
|
||||||
|
0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
|
||||||
|
0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354,
|
||||||
|
0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5,
|
||||||
|
0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E,
|
||||||
|
0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D };
|
||||||
|
|
||||||
|
uint32_t crc32(uint32_t crc, const unsigned char* buf, uint32_t len)
|
||||||
|
{
|
||||||
|
unsigned char octet;
|
||||||
|
const unsigned char* p = buf;
|
||||||
|
|
||||||
|
crc = ~crc;
|
||||||
|
while (len--)
|
||||||
|
{
|
||||||
|
octet = *p++; /* Cast to unsigned octet. */
|
||||||
|
crc = (crc >> 8) ^ crc32_table[(crc & 0xff) ^ octet];
|
||||||
|
}
|
||||||
|
return ~crc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned char rev_crc32_table[256];
|
||||||
|
|
||||||
|
static void revgen(void)
|
||||||
|
{
|
||||||
|
unsigned char k;
|
||||||
|
|
||||||
|
for (k = 0; k < 256; k++)
|
||||||
|
rev_crc32_table[crc32_table[k] >> 24] = k;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t revcrc32(uint32_t crc, const unsigned char* buf, uint32_t len)
|
||||||
|
{
|
||||||
|
unsigned char k;
|
||||||
|
revgen();
|
||||||
|
crc = ~crc;
|
||||||
|
while (len--)
|
||||||
|
{
|
||||||
|
k = rev_crc32_table[crc >> 24];
|
||||||
|
crc = ((crc ^ crc32_table[k]) << 8) | (k ^ buf[len]);
|
||||||
|
}
|
||||||
|
return ~crc;
|
||||||
|
}
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
#include "icsneo/communication/message/serialnumbermessage.h"
|
#include "icsneo/communication/message/serialnumbermessage.h"
|
||||||
#include "icsneo/communication/message/resetstatusmessage.h"
|
#include "icsneo/communication/message/resetstatusmessage.h"
|
||||||
#include "icsneo/communication/message/readsettingsmessage.h"
|
#include "icsneo/communication/message/readsettingsmessage.h"
|
||||||
#include "icsneo/communication/message/canerrorcountmessage.h"
|
#include "icsneo/communication/message/canerrormessage.h"
|
||||||
#include "icsneo/communication/message/neoreadmemorysdmessage.h"
|
#include "icsneo/communication/message/neoreadmemorysdmessage.h"
|
||||||
#include "icsneo/communication/message/flashmemorymessage.h"
|
#include "icsneo/communication/message/flashmemorymessage.h"
|
||||||
#include "icsneo/communication/message/extendedresponsemessage.h"
|
#include "icsneo/communication/message/extendedresponsemessage.h"
|
||||||
|
|
@ -19,7 +19,9 @@
|
||||||
#include "icsneo/communication/message/diskdatamessage.h"
|
#include "icsneo/communication/message/diskdatamessage.h"
|
||||||
#include "icsneo/communication/message/hardwareinfo.h"
|
#include "icsneo/communication/message/hardwareinfo.h"
|
||||||
#include "icsneo/communication/message/tc10statusmessage.h"
|
#include "icsneo/communication/message/tc10statusmessage.h"
|
||||||
|
#include "icsneo/communication/message/gptpstatusmessage.h"
|
||||||
#include "icsneo/communication/message/apperrormessage.h"
|
#include "icsneo/communication/message/apperrormessage.h"
|
||||||
|
#include "icsneo/communication/message/ethernetstatusmessage.h"
|
||||||
#include "icsneo/communication/command.h"
|
#include "icsneo/communication/command.h"
|
||||||
#include "icsneo/device/device.h"
|
#include "icsneo/device/device.h"
|
||||||
#include "icsneo/communication/packet/canpacket.h"
|
#include "icsneo/communication/packet/canpacket.h"
|
||||||
|
|
@ -93,7 +95,7 @@ bool Decoder::decode(std::shared_ptr<Message>& result, const std::shared_ptr<Pac
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Message::Type::CANErrorCount: {
|
case Message::Type::CANErrorCount: {
|
||||||
CANErrorCountMessage& can = *static_cast<CANErrorCountMessage*>(result.get());
|
CANErrorMessage& can = *static_cast<CANErrorMessage*>(result.get());
|
||||||
can.network = packet->network;
|
can.network = packet->network;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -178,6 +180,7 @@ bool Decoder::decode(std::shared_ptr<Message>& result, const std::shared_ptr<Pac
|
||||||
|
|
||||||
LINMessage& msg = *static_cast<LINMessage*>(result.get());
|
LINMessage& msg = *static_cast<LINMessage*>(result.get());
|
||||||
msg.network = packet->network;
|
msg.network = packet->network;
|
||||||
|
msg.timestamp *= timestampResolution;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case Network::Type::MDIO: {
|
case Network::Type::MDIO: {
|
||||||
|
|
@ -236,21 +239,26 @@ bool Decoder::decode(std::shared_ptr<Message>& result, const std::shared_ptr<Pac
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = HardwareCANPacket::DecodeToMessage(packet->data);
|
const auto can = std::dynamic_pointer_cast<CANMessage>(HardwareCANPacket::DecodeToMessage(packet->data));
|
||||||
if(!result) {
|
if(!can) {
|
||||||
report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::Error);
|
report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::Error);
|
||||||
return false; // A nullptr was returned, the packet was malformed
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Timestamps are in (resolution) ns increments since 1/1/2007 GMT 00:00:00.0000
|
if(can->arbid == 0x162) {
|
||||||
// The resolution depends on the device
|
result = EthernetStatusMessage::DecodeToMessage(can->data);
|
||||||
auto* raw = dynamic_cast<RawMessage*>(result.get());
|
|
||||||
if(raw == nullptr) {
|
if(!result) {
|
||||||
report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::Error);
|
report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::Error);
|
||||||
return false; // A nullptr was returned, the packet was malformed
|
return false;
|
||||||
}
|
}
|
||||||
raw->timestamp *= timestampResolution;
|
} else {
|
||||||
raw->network = packet->network;
|
// TODO: move more handleNeoVIMessage handling here, the Decoder layer will parse the message and the Device layer can cache the values
|
||||||
|
can->network = packet->network;
|
||||||
|
result = can;
|
||||||
|
}
|
||||||
|
|
||||||
|
result->timestamp *= timestampResolution;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case Network::NetID::DeviceStatus: {
|
case Network::NetID::DeviceStatus: {
|
||||||
|
|
@ -284,11 +292,11 @@ bool Decoder::decode(std::shared_ptr<Message>& result, const std::shared_ptr<Pac
|
||||||
}
|
}
|
||||||
case Network::NetID::ExtendedCommand: {
|
case Network::NetID::ExtendedCommand: {
|
||||||
|
|
||||||
if(packet->data.size() < sizeof(ExtendedResponseMessage::PackedGenericResponse))
|
if(packet->data.size() < sizeof(ExtendedResponseMessage::ResponseHeader))
|
||||||
break; // Handle as a raw message, might not be a generic response
|
break; // Handle as a raw message, might not be a generic response
|
||||||
|
|
||||||
const auto& resp = *reinterpret_cast<ExtendedResponseMessage::PackedGenericResponse*>(packet->data.data());
|
const auto& resp = *reinterpret_cast<ExtendedResponseMessage::ResponseHeader*>(packet->data.data());
|
||||||
switch(resp.header.command) {
|
switch(resp.command) {
|
||||||
case ExtendedCommand::GetComponentVersions:
|
case ExtendedCommand::GetComponentVersions:
|
||||||
result = ComponentVersionPacket::DecodeToMessage(packet->data);
|
result = ComponentVersionPacket::DecodeToMessage(packet->data);
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -298,15 +306,23 @@ bool Decoder::decode(std::shared_ptr<Message>& result, const std::shared_ptr<Pac
|
||||||
case ExtendedCommand::GenericBinaryInfo:
|
case ExtendedCommand::GenericBinaryInfo:
|
||||||
result = GenericBinaryStatusPacket::DecodeToMessage(packet->data);
|
result = GenericBinaryStatusPacket::DecodeToMessage(packet->data);
|
||||||
return true;
|
return true;
|
||||||
case ExtendedCommand::GenericReturn:
|
case ExtendedCommand::GenericReturn: {
|
||||||
result = std::make_shared<ExtendedResponseMessage>(resp.command, resp.returnCode);
|
if(packet->data.size() < sizeof(ExtendedResponseMessage::PackedGenericResponse))
|
||||||
|
break;
|
||||||
|
const auto& packedResp = *reinterpret_cast<ExtendedResponseMessage::PackedGenericResponse*>(packet->data.data());
|
||||||
|
result = std::make_shared<ExtendedResponseMessage>(packedResp.command, packedResp.returnCode);
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
case ExtendedCommand::LiveData:
|
case ExtendedCommand::LiveData:
|
||||||
result = HardwareLiveDataPacket::DecodeToMessage(packet->data, report);
|
result = HardwareLiveDataPacket::DecodeToMessage(packet->data, report);
|
||||||
return true;
|
return true;
|
||||||
case ExtendedCommand::GetTC10Status:
|
case ExtendedCommand::GetTC10Status:
|
||||||
result = TC10StatusMessage::DecodeToMessage(packet->data);
|
result = TC10StatusMessage::DecodeToMessage(packet->data);
|
||||||
return true;
|
return true;
|
||||||
|
case ExtendedCommand::GetGPTPStatus: {
|
||||||
|
result = GPTPStatus::DecodeToMessage(packet->data, report);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
// No defined handler, treat this as a RawMessage
|
// No defined handler, treat this as a RawMessage
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -265,6 +265,8 @@ bool Encoder::encode(const Packetizer& packetizer, std::vector<uint8_t>& result,
|
||||||
case Command::GetMainVersion:
|
case Command::GetMainVersion:
|
||||||
case Command::GetSecondaryVersions:
|
case Command::GetSecondaryVersions:
|
||||||
case Command::NeoReadMemory:
|
case Command::NeoReadMemory:
|
||||||
|
case Command::ClearCoreMini:
|
||||||
|
case Command::LoadCoreMini:
|
||||||
// There is a firmware handling idiosyncrasy with these commands
|
// There is a firmware handling idiosyncrasy with these commands
|
||||||
// They must be encoded in the short format
|
// They must be encoded in the short format
|
||||||
m51msg->forceShortFormat = true;
|
m51msg->forceShortFormat = true;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,57 @@
|
||||||
|
#include "icsneo/communication/message/ethernetstatusmessage.h"
|
||||||
|
|
||||||
|
using namespace icsneo;
|
||||||
|
|
||||||
|
#pragma pack(push, 1)
|
||||||
|
enum LinkSpeed {
|
||||||
|
ethSpeed10,
|
||||||
|
ethSpeed100,
|
||||||
|
ethSpeed1000,
|
||||||
|
ethSpeedAutoNeg,
|
||||||
|
ethSpeed2500,
|
||||||
|
ethSpeed5000,
|
||||||
|
ethSpeed10000,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum LinkMode {
|
||||||
|
OPETH_LINK_AUTO,
|
||||||
|
OPETH_LINK_MASTER,
|
||||||
|
OPETH_LINK_SLAVE,
|
||||||
|
OPETH_LINK_INVALID = 255,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Packet {
|
||||||
|
uint8_t state;
|
||||||
|
uint8_t speed;
|
||||||
|
uint8_t duplex;
|
||||||
|
uint16_t network;
|
||||||
|
uint8_t mode;
|
||||||
|
};
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
std::shared_ptr<Message> EthernetStatusMessage::DecodeToMessage(const std::vector<uint8_t>& bytestream) {
|
||||||
|
if(bytestream.size() < sizeof(Packet)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
Packet* packet = (Packet*)bytestream.data();
|
||||||
|
LinkSpeed speed;
|
||||||
|
switch(packet->speed) {
|
||||||
|
case ethSpeed10: speed = EthernetStatusMessage::LinkSpeed::LinkSpeed10; break;
|
||||||
|
case ethSpeed100: speed = EthernetStatusMessage::LinkSpeed::LinkSpeed100; break;
|
||||||
|
case ethSpeed1000: speed = EthernetStatusMessage::LinkSpeed::LinkSpeed1000; break;
|
||||||
|
case ethSpeedAutoNeg: speed = EthernetStatusMessage::LinkSpeed::LinkSpeedAuto; break;
|
||||||
|
case ethSpeed2500: speed = EthernetStatusMessage::LinkSpeed::LinkSpeed2500; break;
|
||||||
|
case ethSpeed5000: speed = EthernetStatusMessage::LinkSpeed::LinkSpeed5000; break;
|
||||||
|
case ethSpeed10000: speed = EthernetStatusMessage::LinkSpeed::LinkSpeed10000; break;
|
||||||
|
default: return nullptr;
|
||||||
|
}
|
||||||
|
LinkMode mode;
|
||||||
|
switch(packet->mode) {
|
||||||
|
case OPETH_LINK_INVALID: mode = EthernetStatusMessage::LinkMode::LinkModeInvalid; break;
|
||||||
|
case OPETH_LINK_AUTO: mode = EthernetStatusMessage::LinkMode::LinkModeAuto; break;
|
||||||
|
case OPETH_LINK_MASTER: mode = EthernetStatusMessage::LinkMode::LinkModeMaster; break;
|
||||||
|
case OPETH_LINK_SLAVE: mode = EthernetStatusMessage::LinkMode::LinkModeSlave; break;
|
||||||
|
default: return nullptr;
|
||||||
|
}
|
||||||
|
return std::make_shared<EthernetStatusMessage>(packet->network, packet->state, speed, packet->duplex, mode);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,219 @@
|
||||||
|
#include <icsneo/communication/message/gptpstatusmessage.h>
|
||||||
|
#include <icsneo/communication/message/extendedresponsemessage.h>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
namespace icsneo {
|
||||||
|
typedef double float64;
|
||||||
|
typedef int64_t time_interval;
|
||||||
|
typedef uint64_t _clock_identity;
|
||||||
|
|
||||||
|
|
||||||
|
#pragma pack(push, 1)
|
||||||
|
|
||||||
|
struct port_identity {
|
||||||
|
_clock_identity clock_identity;
|
||||||
|
uint16_t port_number;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _scaled_ns {
|
||||||
|
int16_t nanoseconds_msb;
|
||||||
|
int64_t nanoseconds_lsb;
|
||||||
|
int16_t fractional_nanoseconds;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _clock_quality {
|
||||||
|
uint8_t clock_class;
|
||||||
|
uint8_t clock_accuracy;
|
||||||
|
uint16_t offset_scaled_log_variance;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct system_identity {
|
||||||
|
uint8_t priority_1;
|
||||||
|
struct _clock_quality clock_quality;
|
||||||
|
uint8_t priority_2;
|
||||||
|
_clock_identity clock_identity;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _timestamp {
|
||||||
|
uint16_t seconds_msb;
|
||||||
|
uint32_t seconds_lsb;
|
||||||
|
uint32_t nanoseconds;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct priority_vector {
|
||||||
|
struct system_identity sysid;
|
||||||
|
uint16_t steps_removed;
|
||||||
|
struct port_identity portid;
|
||||||
|
uint16_t port_number;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// IEEE 802.1AS-2020 14.3
|
||||||
|
// This is a read-only data structure
|
||||||
|
struct _current_ds {
|
||||||
|
uint16_t steps_removed;
|
||||||
|
time_interval offset_from_master;
|
||||||
|
struct _scaled_ns last_gm_phase_change;
|
||||||
|
float64 last_gm_freq_change;
|
||||||
|
uint16_t gm_time_base_indicator;
|
||||||
|
uint32_t gm_change_count;
|
||||||
|
uint32_t time_of_last_gm_change_event;
|
||||||
|
uint32_t time_of_last_gm_phase_change_event;
|
||||||
|
uint32_t time_of_last_gm_freq_change_event;
|
||||||
|
};
|
||||||
|
|
||||||
|
// IEEE 802.1AS-2020 14.4
|
||||||
|
// This is a read-only data structure
|
||||||
|
struct _parent_ds {
|
||||||
|
struct port_identity parent_port_identity;
|
||||||
|
int32_t cumulative_rate_ratio;
|
||||||
|
_clock_identity grandmaster_identity;
|
||||||
|
uint8_t gm_clock_quality_clock_class;
|
||||||
|
uint8_t gm_clock_quality_clock_accuracy;
|
||||||
|
uint16_t gm_clock_quality_offset_scaled_log_variance;
|
||||||
|
uint8_t gm_priority1;
|
||||||
|
uint8_t gm_priority2;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GPTPStatus
|
||||||
|
{
|
||||||
|
struct _timestamp current_time;
|
||||||
|
struct priority_vector gm_priority;
|
||||||
|
int64_t ms_offset_ns;
|
||||||
|
uint8_t is_sync;
|
||||||
|
uint8_t link_status;
|
||||||
|
int64_t link_delay_ns;
|
||||||
|
uint8_t selected_role;
|
||||||
|
uint8_t as_capable;
|
||||||
|
uint8_t is_syntonized;
|
||||||
|
struct _timestamp last_rx_sync_ts; // t2 in IEEE 1588-2019 Figure-16
|
||||||
|
struct _current_ds current_ds;
|
||||||
|
struct _parent_ds parent_ds;
|
||||||
|
};
|
||||||
|
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
static void SetField(GPTPStatus::Timestamp& output, const _timestamp& input) {
|
||||||
|
output.seconds = ((uint64_t)(input.seconds_msb) << 32) | ((uint64_t)input.seconds_lsb);
|
||||||
|
output.nanoseconds = input.nanoseconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SetField(GPTPStatus::PortID& output, const port_identity& input) {
|
||||||
|
output.clockIdentity = input.clock_identity;
|
||||||
|
output.portNumber = input.port_number;
|
||||||
|
}
|
||||||
|
static void SetField(GPTPStatus::ClockQuality& output, const _clock_quality& input) {
|
||||||
|
output.clockClass = input.clock_class;
|
||||||
|
output.clockAccuracy = input.clock_accuracy;
|
||||||
|
output.offsetScaledLogVariance = input.offset_scaled_log_variance;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SetField(GPTPStatus::SystemID& output, const system_identity& input) {
|
||||||
|
output.priority1 = input.priority_1;
|
||||||
|
SetField(output.clockQuality, input.clock_quality);
|
||||||
|
output.priority2 = input.priority_2;
|
||||||
|
output.clockID = input.clock_identity;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SetField(GPTPStatus::ScaledNanoSeconds& output, const _scaled_ns& input) {
|
||||||
|
output.nanosecondsMSB = input.nanoseconds_msb;
|
||||||
|
output.nanosecondsLSB = input.nanoseconds_lsb;
|
||||||
|
output.fractionalNanoseconds = input.fractional_nanoseconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SetField(GPTPStatus::PriorityVector& output, const priority_vector& input) {
|
||||||
|
SetField(output.sysID, input.sysid);
|
||||||
|
output.stepsRemoved = input.steps_removed;
|
||||||
|
SetField(output.portID, input.portid);
|
||||||
|
output.portNumber = input.port_number;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SetField(GPTPStatus::CurrentDS& output, const _current_ds& input) {
|
||||||
|
output.stepsRemoved = input.steps_removed;
|
||||||
|
output.offsetFromMaster = input.offset_from_master;
|
||||||
|
SetField(output.lastgmPhaseChange, input.last_gm_phase_change);
|
||||||
|
output.lastgmFreqChange = input.last_gm_freq_change;
|
||||||
|
output.gmTimeBaseIndicator = input.gm_time_base_indicator;
|
||||||
|
output.gmChangeCount = input.gm_change_count;
|
||||||
|
output.timeOfLastgmChangeEvent = input.time_of_last_gm_change_event;
|
||||||
|
output.timeOfLastgmPhaseChangeEvent = input.time_of_last_gm_phase_change_event;
|
||||||
|
output.timeOfLastgmFreqChangeEvent = input.time_of_last_gm_freq_change_event;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SetField(GPTPStatus::ParentDS& output, const _parent_ds& input) {
|
||||||
|
SetField(output.parentPortIdentity, input.parent_port_identity);
|
||||||
|
output.cumulativeRateRatio = input.cumulative_rate_ratio;
|
||||||
|
output.grandmasterIdentity = input.grandmaster_identity;
|
||||||
|
output.gmClockQualityClockClass = input.gm_clock_quality_clock_class;
|
||||||
|
output.gmClockQualityClockAccuracy = input.gm_clock_quality_clock_accuracy;
|
||||||
|
output.gmClockQualityOffsetScaledLogVariance = input.gm_clock_quality_offset_scaled_log_variance;
|
||||||
|
output.gmPriority1 = input.gm_priority1;
|
||||||
|
output.gmPriority2 = input.gm_priority2;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[maybe_unused]] static void SetField(uint8_t& output, const uint8_t& input) {
|
||||||
|
output = input;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[maybe_unused]] static void SetField(uint16_t& output, const uint16_t& input) {
|
||||||
|
output = input;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[maybe_unused]] static void SetField(uint32_t& output, const uint32_t& input) {
|
||||||
|
output = input;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[maybe_unused]] static void SetField(uint64_t& output, const uint64_t& input) {
|
||||||
|
output = input;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[maybe_unused]] static void SetField(int8_t& output, const int8_t& input) {
|
||||||
|
output = input;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[maybe_unused]] static void SetField(int16_t& output, const int16_t& input) {
|
||||||
|
output = input;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[maybe_unused]] static void SetField(int32_t& output, const int32_t& input) {
|
||||||
|
output = input;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[maybe_unused]] static void SetField(int64_t& output, const int64_t& input) {
|
||||||
|
output = input;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<GPTPStatus> GPTPStatus::DecodeToMessage(std::vector<uint8_t>& bytes, const device_eventhandler_t&) {
|
||||||
|
|
||||||
|
// The following does not lead to overflow since we only call this function if it has at least ResponseHeader length bytes
|
||||||
|
std::shared_ptr<GPTPStatus> res = std::make_shared<GPTPStatus>();
|
||||||
|
auto* header = reinterpret_cast<ExtendedResponseMessage::ResponseHeader*>(bytes.data());
|
||||||
|
uint16_t length = header->length;
|
||||||
|
_GPTPStatus* input = reinterpret_cast<_GPTPStatus*>(bytes.data() + sizeof(ExtendedResponseMessage::ResponseHeader));
|
||||||
|
|
||||||
|
#define CheckLengthAndSet(output, input) if(length >= sizeof(decltype(input))) { \
|
||||||
|
SetField(output, input); \
|
||||||
|
length -= sizeof(decltype(input)); \
|
||||||
|
} else {\
|
||||||
|
memset(&output, 0, sizeof(decltype(output))); \
|
||||||
|
length = 0; \
|
||||||
|
res->shortFormat = true; \
|
||||||
|
}
|
||||||
|
|
||||||
|
CheckLengthAndSet(res->currentTime, input->current_time);
|
||||||
|
CheckLengthAndSet(res->gmPriority, input->gm_priority);
|
||||||
|
CheckLengthAndSet(res->msOffsetNs, input->ms_offset_ns);
|
||||||
|
CheckLengthAndSet(res->isSync, input->is_sync);
|
||||||
|
CheckLengthAndSet(res->linkStatus, input->link_status);
|
||||||
|
CheckLengthAndSet(res->linkDelayNS, input->link_delay_ns);
|
||||||
|
CheckLengthAndSet(res->selectedRole, input->selected_role);
|
||||||
|
CheckLengthAndSet(res->asCapable, input->as_capable);
|
||||||
|
CheckLengthAndSet(res->isSyntonized, input->is_syntonized);
|
||||||
|
CheckLengthAndSet(res->lastRXSyncTS, input->last_rx_sync_ts);
|
||||||
|
CheckLengthAndSet(res->currentDS, input->current_ds);
|
||||||
|
CheckLengthAndSet(res->parentDS, input->parent_ds);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,531 @@
|
||||||
|
#include "icsneo/communication/message/macsecmessage.h"
|
||||||
|
|
||||||
|
#include "icsneo/communication/crc32.h"
|
||||||
|
#include <memory>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <iostream>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
namespace icsneo
|
||||||
|
{
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable : 4201) // nameless struct/union
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#pragma pack(push, 1)
|
||||||
|
/* MACsec Rule */
|
||||||
|
/**
|
||||||
|
* @brief Structure of Vlan tag
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint16_t vid; /*!< 12 bits */
|
||||||
|
uint8_t priCfi; /*!< PRI - 3 bits, CFI - 1bit */
|
||||||
|
} MACSEC_VLANTAG_t;
|
||||||
|
/**
|
||||||
|
* @brief Structure of MPLS
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint32_t mplsLabel; /*!< 20 bits */
|
||||||
|
uint8_t exp; /*!< 3 bits */
|
||||||
|
} MACSEC_MPLS_OUTER_t;
|
||||||
|
/**
|
||||||
|
* @brief Define Encoded Packet Type from the parser
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static constexpr int MACSEC_SETTINGS_RULE_SIZE = 88;
|
||||||
|
typedef union _MACSecRule
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint8_t index;
|
||||||
|
uint8_t keyMacDa[6]; /*!< MAC DA field extracted from the packet */
|
||||||
|
uint8_t maskMacDa[6]; /*!< Set bits to 1 to mask/exclude corresponding flowid_tcam_data bit from compare */
|
||||||
|
uint8_t keyMacSa[6]; /*!< MAC SA field extracted from the packet */
|
||||||
|
uint8_t maskMacSa[6]; /*!< Set bits to 1 to mask/exclude corresponding flowid_tcam_data bit from compare */
|
||||||
|
uint16_t keyEthertype; /*!< First E-Type found in the packet that doesn't match one of the preconfigured custom tag. */
|
||||||
|
uint16_t maskEthertype; /*!< Set bits to 1 to mask/exclude corresponding flowid_tcam_data bit from compare */
|
||||||
|
MACSEC_VLANTAG_t keyVlanTagOuter1; /*!< outermost/1st VLAN ID {8'd0, VLAN_ID[11:0]}, or 20-bit MPLS label. */
|
||||||
|
MACSEC_MPLS_OUTER_t keyMplsOuter1;
|
||||||
|
MACSEC_VLANTAG_t maskVlanTagOuter1; /*!< Set bits to 1 to mask/exclude corresponding flowid_tcam_data bit from compare */
|
||||||
|
MACSEC_MPLS_OUTER_t maskMplsOuter1;
|
||||||
|
MACSEC_VLANTAG_t keyVlanTagOuter2; /*!< 2nd outermost VLAN ID {8'd0, VLAN_ID[11:0]}, or 20-bit MPLS label. */
|
||||||
|
MACSEC_MPLS_OUTER_t keyMplsOuter2;
|
||||||
|
MACSEC_VLANTAG_t maskVlanTagOuter2; /*!< Set bits to 1 to mask/exclude corresponding flowid_tcam_data bit from compare */
|
||||||
|
MACSEC_MPLS_OUTER_t maskMplsOuter2;
|
||||||
|
uint16_t keyBonusData; /*!< 2 bytes of additional bonus data extracted from one of the custom tags. */
|
||||||
|
uint16_t maskBonusData; /*!< Set bits to 1 to mask/exclude corresponding flowid_tcam_data bit from compare */
|
||||||
|
uint8_t
|
||||||
|
keyTagMatchBitmap; /*!< 8 bits total. Maps 1 to 1 bitwise with the set of custom tags. (set bit[N]=1 if check Nth custom tag) */
|
||||||
|
uint8_t maskTagMatchBitmap; /*!< Set bits to 1 to mask/exclude corresponding flowid_tcam_data bit from compare */
|
||||||
|
uint8_t keyPacketType; /*!< Encoded Packet Type, see MACSEC_PACKET_TYPE */
|
||||||
|
uint8_t maskPacketType; /*!< Set bits to 1 to mask/exclude corresponding flowid_tcam_data bit from compare */
|
||||||
|
uint16_t
|
||||||
|
keyInnerVlanType; /*!< 3 bits total. Encoded value indicating which VLAN TPID value matched for the second outermost VLAN Tag. */
|
||||||
|
uint16_t maskInnerVlanType; /*!< Set bits to 1 to mask/exclude corresponding flowid_tcam_data bit from compare */
|
||||||
|
uint16_t keyOuterVlanType; /*!< 3 bits total. Encoded value indicating which VLAN TPID value matched for the outermost VLAN Tag. */
|
||||||
|
uint16_t maskOuterVlanType; /*!< Set bits to 1 to mask/exclude corresponding flowid_tcam_data bit from compare */
|
||||||
|
uint8_t
|
||||||
|
keyNumTags; /*!< 7 bits total. Number of VLAN/custom tags or MPLS lables detected. Ingress: before SecTag; Egress: total detected. Exclude MCS header tags. i.e. Bit 2: 2 tags/labels before SecTAG...Bit 6: 6 or more tags/labels before SecTAG. */
|
||||||
|
uint8_t maskNumTags; /*!< Set bits to 1 to mask/exclude corresponding flowid_tcam_data bit from compare */
|
||||||
|
uint8_t keyExpress; /*!< 1 bits. Express packet. */
|
||||||
|
uint8_t maskExpress; /*!< Set bits to 1 to mask/exclude corresponding flowid_tcam_data bit from compare */
|
||||||
|
uint8_t isMpls;
|
||||||
|
uint8_t rsvd[5];
|
||||||
|
uint8_t enable;
|
||||||
|
};
|
||||||
|
uint8_t byte[MACSEC_SETTINGS_RULE_SIZE];
|
||||||
|
} MACSecRule_t;
|
||||||
|
/* MACsec Map */
|
||||||
|
static constexpr int MACSEC_SETTINGS_MAP_SIZE = 20;
|
||||||
|
typedef union _MACSecMap
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint8_t index;
|
||||||
|
uint64_t secTagSci; /*!< Identifies the SecTAG SCI for this Flow. */
|
||||||
|
uint8_t secYIndex; /*!< index for entry in Egress secY Policy */
|
||||||
|
uint8_t isControlPacket; /*!< Identifies all packets matching this index lookup as control packets. */
|
||||||
|
uint8_t scIndex; /*!< Identifies the SC for this Flow. */
|
||||||
|
uint8_t auxiliaryPlcy; /*!< Auxiliary policy bits. */
|
||||||
|
uint8_t ruleId; /*!< Identifies the Rule for this Flow. */
|
||||||
|
uint8_t rsvd[5];
|
||||||
|
uint8_t enable;
|
||||||
|
};
|
||||||
|
uint8_t byte[MACSEC_SETTINGS_MAP_SIZE];
|
||||||
|
} MACSecMap_t;
|
||||||
|
/* MACsec SecY */
|
||||||
|
/**
|
||||||
|
* @brief Define the permit police for frames as defined in 802.1ae
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static constexpr int MACSEC_SETTINGS_SECY_SIZE = 24;
|
||||||
|
typedef union _MACSecSecY
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint8_t index; /*!< Identifies the SecY for this Flow. */
|
||||||
|
uint8_t controlledPortEnabled; /*!< Enable (or disable) operation of the Controlled port associated with this SecY */
|
||||||
|
uint8_t frameValidationType; /*!< see MACSEC_VALIDATEFRAME */
|
||||||
|
uint8_t secTagIcvStripType; /*!< see MACSEC_STRIP_SECTAG_ICV */
|
||||||
|
uint8_t cipher; /*!< Define the cipher suite to use for this SecY see MACSEC_CIPHER_SUITE */
|
||||||
|
uint8_t confidentialOffset; /*!< Define the number of bytes that are unencrypted following the SecTag. */
|
||||||
|
uint8_t icvIncludesDaSa; /*!< When set, the outer DA/SA bytes are included in the authentication GHASH calculation */
|
||||||
|
uint8_t replayProtect; /*!< Enables Anti-Replay protection */
|
||||||
|
uint32_t replayWindow; /*!< Unsigned value indicating the size of the anti-replay window. */
|
||||||
|
uint8_t
|
||||||
|
protectFrames; /*!< 0 = do not encrypt or authenticate this packet; 1 = always Authenticate frame and if SecTag.TCI.E = 1 encrypt the packet as well. */
|
||||||
|
uint8_t
|
||||||
|
secTagOffset; /*!< Define the offset in bytes from either the start of the packet or a matching Etype depending on SecTag_Insertion_Mode. */
|
||||||
|
uint8_t secTagTci; /*!< Tag Control Information excluding the AN field which originates from the SA Policy table */
|
||||||
|
uint16_t mtu; /*!< Specifies the outgoing MTU for this SecY */
|
||||||
|
uint8_t rsvd[6];
|
||||||
|
uint8_t enable;
|
||||||
|
};
|
||||||
|
uint8_t byte[MACSEC_SETTINGS_SECY_SIZE];
|
||||||
|
} MACSecSecY_t;
|
||||||
|
/* MACsec SC */
|
||||||
|
static constexpr int MACSEC_SETTINGS_SC_SIZE = 24;
|
||||||
|
typedef union _MACSecSc
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint8_t index; /*!< SC index. */
|
||||||
|
uint8_t secYIndex; /*!< SecY associated with this packet. */
|
||||||
|
uint64_t sci; /*!< The Secure Channel Identifier. */
|
||||||
|
uint8_t saIndex0; /*!< Define the 1st SA to use */
|
||||||
|
uint8_t saIndex1; /*!< Define the 2nd SA to use */
|
||||||
|
uint8_t saIndex0InUse; /*!< Specifies whether 1st SA is in use or not. */
|
||||||
|
uint8_t saIndex1InUse; /*!< Specifies whether 2nd SA is in use or not. */
|
||||||
|
uint8_t enableAutoRekey; /*!< If enabled, then once the pn_threshold is reached, auto rekey will happen. */
|
||||||
|
uint8_t
|
||||||
|
isActiveSa1; /*!< If set, then sa_index1 is the currently active SA index. If cleared, the sa_index0 is the currently active SA index). */
|
||||||
|
uint8_t rsvd[7];
|
||||||
|
uint8_t enable;
|
||||||
|
};
|
||||||
|
uint8_t byte[MACSEC_SETTINGS_SC_SIZE];
|
||||||
|
} MACSecSc_t;
|
||||||
|
/* MACsec SA */
|
||||||
|
static constexpr int MACSEC_SETTINGS_SA_SIZE = 80;
|
||||||
|
typedef union _MACSecSa
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint8_t index; /*!< SA index */
|
||||||
|
uint8_t
|
||||||
|
sak[32]; /*!< 256b SAK: Define the encryption key to be used to encrypte this packet. The lower 128 bits are used for 128-bit ciphers. */
|
||||||
|
uint8_t hashKey[16]; /*!< 128b Hash Key: Key used for authentication. */
|
||||||
|
uint8_t salt[12]; /*!< 96b Salt value: Salt value used in XPN ciphers. */
|
||||||
|
uint32_t ssci; /*!< 32b SSCI value: Short Secure Channel Identifier, used in XPN ciphers. */
|
||||||
|
uint8_t an; /*!< 2b SecTag Association Number (AN) */
|
||||||
|
uint64_t nextPn; /*!< 64b next_pn value: Next packet number to insert into outgoing packet on a particular SA. */
|
||||||
|
uint8_t rsvd[5];
|
||||||
|
uint8_t enable;
|
||||||
|
};
|
||||||
|
uint8_t byte[MACSEC_SETTINGS_SA_SIZE];
|
||||||
|
} MACSecSa_t;
|
||||||
|
/* MACsec Flags */
|
||||||
|
static constexpr int MACSEC_SETTINGS_FLAGS_SIZE = 4;
|
||||||
|
typedef union _MACSecFlags
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint32_t en : 1; // '1' = enable; '0' = disable
|
||||||
|
uint32_t reserved : 31;
|
||||||
|
};
|
||||||
|
uint32_t flags_32b;
|
||||||
|
} MACSecFlags_t;
|
||||||
|
/* MACSec Settings for 1 port/phy */
|
||||||
|
typedef struct MACSEC_CONFIG_t
|
||||||
|
{
|
||||||
|
MACSecFlags_t flags;
|
||||||
|
MACSecRule_t rule[MACsecConfig::NumRules];
|
||||||
|
MACSecMap_t map[MACsecConfig::NumMaps];
|
||||||
|
MACSecSecY_t secy[MACsecConfig::NumSecY];
|
||||||
|
MACSecSc_t sc[MACsecConfig::NumSc];
|
||||||
|
MACSecSa_t sa[MACsecConfig::NumSa];
|
||||||
|
} MACSEC_CONFIG;
|
||||||
|
typedef union _MACSecGlobalFlags
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint32_t en : 1; // '1' = enable; '0' = disable
|
||||||
|
uint32_t nvm : 1; // store macsec config in non-volatile memory
|
||||||
|
uint32_t reserved : 30;
|
||||||
|
};
|
||||||
|
uint32_t flags_32b;
|
||||||
|
} MACSecGlobalFlags_t;
|
||||||
|
#define MACSEC_SETTINGS_SIZE (2040) // leave space for expansion and keep nicely aligned for flashing
|
||||||
|
typedef union _MACSEC_SETTINGS
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
MACSecGlobalFlags_t flags;
|
||||||
|
MACSEC_CONFIG rx;
|
||||||
|
MACSEC_CONFIG tx;
|
||||||
|
};
|
||||||
|
uint8_t byte[MACSEC_SETTINGS_SIZE];
|
||||||
|
} MACSEC_SETTINGS;
|
||||||
|
|
||||||
|
#define MACSEC_SETTINGS_VERSION 1
|
||||||
|
struct MACSEC_SETTINGS_W_HDR
|
||||||
|
{
|
||||||
|
uint16_t version;
|
||||||
|
uint16_t len;
|
||||||
|
uint32_t crc32;
|
||||||
|
MACSEC_SETTINGS macsec;
|
||||||
|
};
|
||||||
|
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
std::shared_ptr<MACsecMessage> MACsecMessage::DecodeToMessage(const std::vector<uint8_t>& bytestream, const device_eventhandler_t& report)
|
||||||
|
{
|
||||||
|
if (bytestream.empty() || (bytestream.size() < sizeof(MACSEC_SETTINGS_W_HDR)))
|
||||||
|
{
|
||||||
|
report(APIEvent::Type::RequiredParameterNull, APIEvent::Severity::Error);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
MACSEC_SETTINGS_W_HDR* macsecArgs = (MACSEC_SETTINGS_W_HDR*)bytestream.data();
|
||||||
|
if (macsecArgs->version != MACSEC_SETTINGS_VERSION)
|
||||||
|
{
|
||||||
|
report(APIEvent::Type::SettingsVersionError, APIEvent::Severity::Error);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
if (macsecArgs->len != sizeof(MACSEC_SETTINGS))
|
||||||
|
{
|
||||||
|
report(APIEvent::Type::SettingsLengthError, APIEvent::Severity::Error);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
const auto crcCalculted = crc32(0, (uint8_t*)&macsecArgs->macsec, macsecArgs->len);
|
||||||
|
if (macsecArgs->crc32 != crcCalculted)
|
||||||
|
{
|
||||||
|
report(APIEvent::Type::SettingsChecksumError, APIEvent::Severity::Error);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto msg = std::make_shared<MACsecMessage>();
|
||||||
|
|
||||||
|
const auto& copyConfig = [](const MACSEC_CONFIG& source, MACsecConfig& dest)
|
||||||
|
{
|
||||||
|
dest.flags.en = source.flags.en;
|
||||||
|
for (int index = 0; index < MACsecConfig::NumRules; index++)
|
||||||
|
{
|
||||||
|
if(!source.rule[index].enable) continue;
|
||||||
|
#undef __COPY_ITEM
|
||||||
|
#define __COPY_ITEM(___name__) dest.rule[index].___name__ = (decltype(dest.rule[index].___name__))source.rule[index].___name__
|
||||||
|
#undef __COPY_ARR
|
||||||
|
#define __COPY_ARR(___name__) (void)memcpy(dest.rule[index].___name__.data(), source.rule[index].___name__, dest.rule[index].___name__.size())
|
||||||
|
__COPY_ITEM(index);
|
||||||
|
__COPY_ARR(keyMacDa);
|
||||||
|
__COPY_ARR(maskMacDa);
|
||||||
|
__COPY_ARR(keyMacSa);
|
||||||
|
__COPY_ARR(maskMacSa);
|
||||||
|
__COPY_ITEM(keyVlanTagOuter1.vid);
|
||||||
|
__COPY_ITEM(keyVlanTagOuter1.priCfi);
|
||||||
|
__COPY_ITEM(keyMplsOuter1.mplsLabel);
|
||||||
|
__COPY_ITEM(keyMplsOuter1.exp);
|
||||||
|
__COPY_ITEM(maskVlanTagOuter1.vid);
|
||||||
|
__COPY_ITEM(maskVlanTagOuter1.priCfi);
|
||||||
|
__COPY_ITEM(maskMplsOuter1.mplsLabel);
|
||||||
|
__COPY_ITEM(maskMplsOuter1.exp);
|
||||||
|
__COPY_ITEM(keyVlanTagOuter2.vid);
|
||||||
|
__COPY_ITEM(keyVlanTagOuter2.priCfi);
|
||||||
|
__COPY_ITEM(keyMplsOuter2.mplsLabel);
|
||||||
|
__COPY_ITEM(keyMplsOuter2.exp);
|
||||||
|
__COPY_ITEM(maskVlanTagOuter2.vid);
|
||||||
|
__COPY_ITEM(maskVlanTagOuter2.priCfi);
|
||||||
|
__COPY_ITEM(maskMplsOuter2.mplsLabel);
|
||||||
|
__COPY_ITEM(maskMplsOuter2.exp);
|
||||||
|
__COPY_ITEM(keyEthertype);
|
||||||
|
__COPY_ITEM(maskEthertype);
|
||||||
|
__COPY_ITEM(keyBonusData);
|
||||||
|
__COPY_ITEM(maskBonusData);
|
||||||
|
__COPY_ITEM(keyTagMatchBitmap);
|
||||||
|
__COPY_ITEM(maskTagMatchBitmap);
|
||||||
|
__COPY_ITEM(keyPacketType);
|
||||||
|
__COPY_ITEM(maskPacketType);
|
||||||
|
__COPY_ITEM(keyInnerVlanType);
|
||||||
|
__COPY_ITEM(maskInnerVlanType);
|
||||||
|
__COPY_ITEM(keyOuterVlanType);
|
||||||
|
__COPY_ITEM(maskOuterVlanType);
|
||||||
|
__COPY_ITEM(keyNumTags);
|
||||||
|
__COPY_ITEM(maskNumTags);
|
||||||
|
__COPY_ITEM(keyExpress);
|
||||||
|
__COPY_ITEM(maskExpress);
|
||||||
|
__COPY_ITEM(isMpls);
|
||||||
|
__COPY_ITEM(enable);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int index = 0; index < MACsecConfig::NumMaps; index++)
|
||||||
|
{
|
||||||
|
if(!source.map[index].enable) continue;
|
||||||
|
#undef __COPY_ITEM
|
||||||
|
#define __COPY_ITEM(___name__) dest.map[index].___name__ = source.map[index].___name__
|
||||||
|
__COPY_ITEM(index);
|
||||||
|
__COPY_ITEM(secTagSci);
|
||||||
|
__COPY_ITEM(secYIndex);
|
||||||
|
__COPY_ITEM(isControlPacket);
|
||||||
|
__COPY_ITEM(scIndex);
|
||||||
|
__COPY_ITEM(auxiliaryPlcy);
|
||||||
|
__COPY_ITEM(ruleId);
|
||||||
|
__COPY_ITEM(enable);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int index = 0; index < MACsecConfig::NumSecY; index++)
|
||||||
|
{
|
||||||
|
if(!source.secy[index].enable) continue;
|
||||||
|
#undef __COPY_ITEM
|
||||||
|
#define __COPY_ITEM(___name__) dest.secy[index].___name__ = (decltype(dest.secy[index].___name__))source.secy[index].___name__
|
||||||
|
__COPY_ITEM(index);
|
||||||
|
__COPY_ITEM(controlledPortEnabled);
|
||||||
|
__COPY_ITEM(frameValidationType);
|
||||||
|
__COPY_ITEM(secTagIcvStripType);
|
||||||
|
__COPY_ITEM(cipher);
|
||||||
|
__COPY_ITEM(confidentialOffset);
|
||||||
|
__COPY_ITEM(icvIncludesDaSa);
|
||||||
|
__COPY_ITEM(replayProtect);
|
||||||
|
__COPY_ITEM(replayWindow);
|
||||||
|
__COPY_ITEM(protectFrames);
|
||||||
|
__COPY_ITEM(secTagOffset);
|
||||||
|
__COPY_ITEM(secTagTci);
|
||||||
|
__COPY_ITEM(mtu);
|
||||||
|
__COPY_ITEM(enable);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int index = 0; index < MACsecConfig::NumSc; index++)
|
||||||
|
{
|
||||||
|
if(!source.sc[index].enable) continue;
|
||||||
|
#undef __COPY_ITEM
|
||||||
|
#define __COPY_ITEM(___name__) dest.sc[index].___name__ = source.sc[index].___name__
|
||||||
|
__COPY_ITEM(index);
|
||||||
|
__COPY_ITEM(secYIndex);
|
||||||
|
__COPY_ITEM(sci);
|
||||||
|
__COPY_ITEM(saIndex0);
|
||||||
|
__COPY_ITEM(saIndex1);
|
||||||
|
__COPY_ITEM(saIndex0InUse);
|
||||||
|
__COPY_ITEM(saIndex1InUse);
|
||||||
|
__COPY_ITEM(enableAutoRekey);
|
||||||
|
__COPY_ITEM(isActiveSa1);
|
||||||
|
__COPY_ITEM(enable);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int index = 0; index < MACsecConfig::NumSa; index++)
|
||||||
|
{
|
||||||
|
if(!source.sa[index].enable) continue;
|
||||||
|
#undef __COPY_ITEM
|
||||||
|
#define __COPY_ITEM(___name__) dest.sa[index].___name__ = source.sa[index].___name__
|
||||||
|
#undef __COPY_ARR
|
||||||
|
#define __COPY_ARR(___name__) (void)memcpy(dest.sa[index].___name__.data(), source.sa[index].___name__, dest.sa[index].___name__.size())
|
||||||
|
__COPY_ITEM(index);
|
||||||
|
__COPY_ARR(sak);
|
||||||
|
__COPY_ARR(hashKey);
|
||||||
|
__COPY_ARR(salt);
|
||||||
|
__COPY_ITEM(ssci);
|
||||||
|
__COPY_ITEM(an);
|
||||||
|
__COPY_ITEM(nextPn);
|
||||||
|
__COPY_ITEM(enable);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
msg->flags.en = macsecArgs->macsec.flags.en;
|
||||||
|
copyConfig(macsecArgs->macsec.rx, msg->rx);
|
||||||
|
copyConfig(macsecArgs->macsec.tx, msg->tx);
|
||||||
|
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MACsecMessage::EncodeFromMessage(std::vector<uint8_t>& bytestream, const device_eventhandler_t& report) const
|
||||||
|
{
|
||||||
|
MACSEC_SETTINGS_W_HDR* macsecArgs;
|
||||||
|
|
||||||
|
bytestream.resize(sizeof(MACSEC_SETTINGS_W_HDR), 0);
|
||||||
|
macsecArgs = (MACSEC_SETTINGS_W_HDR*)bytestream.data();
|
||||||
|
|
||||||
|
macsecArgs->version = MACSEC_SETTINGS_VERSION;
|
||||||
|
macsecArgs->len = sizeof(MACSEC_SETTINGS_W_HDR);
|
||||||
|
|
||||||
|
const auto& copyConfig = [](const MACsecConfig& source, MACSEC_CONFIG& dest)
|
||||||
|
{
|
||||||
|
dest.flags.en = (uint8_t)source.flags.en;
|
||||||
|
for (int index = 0; index < MACsecConfig::NumRules; index++)
|
||||||
|
{
|
||||||
|
if(!source.rule[index].enable) continue;
|
||||||
|
#undef __COPY_ITEM
|
||||||
|
#define __COPY_ITEM(___name__) dest.rule[index].___name__ = (decltype(dest.rule[index].___name__))source.rule[index].___name__
|
||||||
|
#undef __COPY_ARR
|
||||||
|
#define __COPY_ARR(___name__) (void)memcpy(dest.rule[index].___name__, source.rule[index].___name__.data(), source.rule[index].___name__.size())
|
||||||
|
__COPY_ITEM(index);
|
||||||
|
__COPY_ARR(keyMacDa);
|
||||||
|
__COPY_ARR(maskMacDa);
|
||||||
|
__COPY_ARR(keyMacSa);
|
||||||
|
__COPY_ARR(maskMacSa);
|
||||||
|
__COPY_ITEM(keyVlanTagOuter1.vid);
|
||||||
|
__COPY_ITEM(keyVlanTagOuter1.priCfi);
|
||||||
|
__COPY_ITEM(keyMplsOuter1.mplsLabel);
|
||||||
|
__COPY_ITEM(keyMplsOuter1.exp);
|
||||||
|
__COPY_ITEM(maskVlanTagOuter1.vid);
|
||||||
|
__COPY_ITEM(maskVlanTagOuter1.priCfi);
|
||||||
|
__COPY_ITEM(maskMplsOuter1.mplsLabel);
|
||||||
|
__COPY_ITEM(maskMplsOuter1.exp);
|
||||||
|
__COPY_ITEM(keyVlanTagOuter2.vid);
|
||||||
|
__COPY_ITEM(keyVlanTagOuter2.priCfi);
|
||||||
|
__COPY_ITEM(keyMplsOuter2.mplsLabel);
|
||||||
|
__COPY_ITEM(keyMplsOuter2.exp);
|
||||||
|
__COPY_ITEM(maskVlanTagOuter2.vid);
|
||||||
|
__COPY_ITEM(maskVlanTagOuter2.priCfi);
|
||||||
|
__COPY_ITEM(maskMplsOuter2.mplsLabel);
|
||||||
|
__COPY_ITEM(maskMplsOuter2.exp);
|
||||||
|
__COPY_ITEM(keyEthertype);
|
||||||
|
__COPY_ITEM(maskEthertype);
|
||||||
|
__COPY_ITEM(keyBonusData);
|
||||||
|
__COPY_ITEM(maskBonusData);
|
||||||
|
__COPY_ITEM(keyTagMatchBitmap);
|
||||||
|
__COPY_ITEM(maskTagMatchBitmap);
|
||||||
|
__COPY_ITEM(keyPacketType);
|
||||||
|
__COPY_ITEM(maskPacketType);
|
||||||
|
__COPY_ITEM(keyInnerVlanType);
|
||||||
|
__COPY_ITEM(maskInnerVlanType);
|
||||||
|
__COPY_ITEM(keyOuterVlanType);
|
||||||
|
__COPY_ITEM(maskOuterVlanType);
|
||||||
|
__COPY_ITEM(keyNumTags);
|
||||||
|
__COPY_ITEM(maskNumTags);
|
||||||
|
__COPY_ITEM(keyExpress);
|
||||||
|
__COPY_ITEM(maskExpress);
|
||||||
|
__COPY_ITEM(isMpls);
|
||||||
|
__COPY_ITEM(enable);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int index = 0; index < MACsecConfig::NumMaps; index++)
|
||||||
|
{
|
||||||
|
if(!source.map[index].enable) continue;
|
||||||
|
#undef __COPY_ITEM
|
||||||
|
#define __COPY_ITEM(___name__) dest.map[index].___name__ = source.map[index].___name__
|
||||||
|
__COPY_ITEM(index);
|
||||||
|
__COPY_ITEM(secTagSci);
|
||||||
|
__COPY_ITEM(secYIndex);
|
||||||
|
__COPY_ITEM(isControlPacket);
|
||||||
|
__COPY_ITEM(scIndex);
|
||||||
|
__COPY_ITEM(auxiliaryPlcy);
|
||||||
|
__COPY_ITEM(ruleId);
|
||||||
|
__COPY_ITEM(enable);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int index = 0; index < MACsecConfig::NumSecY; index++)
|
||||||
|
{
|
||||||
|
if(!source.secy[index].enable) continue;
|
||||||
|
#undef __COPY_ITEM
|
||||||
|
#define __COPY_ITEM(___name__) dest.secy[index].___name__ = (decltype(dest.secy[index].___name__))source.secy[index].___name__
|
||||||
|
__COPY_ITEM(index);
|
||||||
|
__COPY_ITEM(controlledPortEnabled);
|
||||||
|
__COPY_ITEM(frameValidationType);
|
||||||
|
__COPY_ITEM(secTagIcvStripType);
|
||||||
|
__COPY_ITEM(cipher);
|
||||||
|
__COPY_ITEM(confidentialOffset);
|
||||||
|
__COPY_ITEM(icvIncludesDaSa);
|
||||||
|
__COPY_ITEM(replayProtect);
|
||||||
|
__COPY_ITEM(replayWindow);
|
||||||
|
__COPY_ITEM(protectFrames);
|
||||||
|
__COPY_ITEM(secTagOffset);
|
||||||
|
__COPY_ITEM(secTagTci);
|
||||||
|
__COPY_ITEM(mtu);
|
||||||
|
__COPY_ITEM(enable);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int index = 0; index < MACsecConfig::NumSc; index++)
|
||||||
|
{
|
||||||
|
if(!source.sc[index].enable) continue;
|
||||||
|
#undef __COPY_ITEM
|
||||||
|
#define __COPY_ITEM(___name__) dest.sc[index].___name__ = source.sc[index].___name__
|
||||||
|
__COPY_ITEM(index);
|
||||||
|
__COPY_ITEM(secYIndex);
|
||||||
|
__COPY_ITEM(sci);
|
||||||
|
__COPY_ITEM(saIndex0);
|
||||||
|
__COPY_ITEM(saIndex1);
|
||||||
|
__COPY_ITEM(saIndex0InUse);
|
||||||
|
__COPY_ITEM(saIndex1InUse);
|
||||||
|
__COPY_ITEM(enableAutoRekey);
|
||||||
|
__COPY_ITEM(isActiveSa1);
|
||||||
|
__COPY_ITEM(enable);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int index = 0; index < MACsecConfig::NumSa; index++)
|
||||||
|
{
|
||||||
|
if(!source.sa[index].enable) continue;
|
||||||
|
#undef __COPY_ITEM
|
||||||
|
#define __COPY_ITEM(___name__) dest.sa[index].___name__ = source.sa[index].___name__
|
||||||
|
#undef __COPY_ARR
|
||||||
|
#define __COPY_ARR(___name__) (void)memcpy(dest.sa[index].___name__, source.sa[index].___name__.data(), source.sa[index].___name__.size())
|
||||||
|
__COPY_ITEM(index);
|
||||||
|
__COPY_ARR(sak);
|
||||||
|
__COPY_ARR(hashKey);
|
||||||
|
__COPY_ARR(salt);
|
||||||
|
__COPY_ITEM(ssci);
|
||||||
|
__COPY_ITEM(an);
|
||||||
|
__COPY_ITEM(nextPn);
|
||||||
|
__COPY_ITEM(enable);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
macsecArgs->macsec.flags.en = this->flags.en;
|
||||||
|
macsecArgs->macsec.flags.nvm = this->flags.nvm;
|
||||||
|
|
||||||
|
copyConfig(this->rx, macsecArgs->macsec.rx);
|
||||||
|
copyConfig(this->tx, macsecArgs->macsec.tx);
|
||||||
|
|
||||||
|
macsecArgs->crc32 = crc32(0, (uint8_t*)&macsecArgs->macsec, sizeof(MACSEC_SETTINGS));
|
||||||
|
|
||||||
|
(void)report;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace icsneo
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#include "icsneo/communication/message/neomessage.h"
|
#include "icsneo/communication/message/neomessage.h"
|
||||||
#include "icsneo/communication/message/canmessage.h"
|
#include "icsneo/communication/message/canmessage.h"
|
||||||
#include "icsneo/communication/message/ethernetmessage.h"
|
#include "icsneo/communication/message/ethernetmessage.h"
|
||||||
#include "icsneo/communication/message/canerrorcountmessage.h"
|
#include "icsneo/communication/message/canerrormessage.h"
|
||||||
#include "icsneo/communication/message/linmessage.h"
|
#include "icsneo/communication/message/linmessage.h"
|
||||||
|
|
||||||
using namespace icsneo;
|
using namespace icsneo;
|
||||||
|
|
@ -51,7 +51,7 @@ neomessage_t icsneo::CreateNeoMessage(const std::shared_ptr<Message> message) {
|
||||||
eth.status.incompleteFrame = ethmsg->frameTooShort;
|
eth.status.incompleteFrame = ethmsg->frameTooShort;
|
||||||
// TODO Fill in extra status bits
|
// TODO Fill in extra status bits
|
||||||
//eth.status.xyz = ethmsg->preemptionEnabled;
|
//eth.status.xyz = ethmsg->preemptionEnabled;
|
||||||
//eth.status.xyz = ethmsg->fcsAvailable;
|
//eth.status.xyz = ethmsg->fcs;
|
||||||
//eth.status.xyz = ethmsg->noPadding;
|
//eth.status.xyz = ethmsg->noPadding;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -104,7 +104,7 @@ neomessage_t icsneo::CreateNeoMessage(const std::shared_ptr<Message> message) {
|
||||||
}
|
}
|
||||||
case Message::Type::CANErrorCount: {
|
case Message::Type::CANErrorCount: {
|
||||||
neomessage_can_error_t& canerror = *(neomessage_can_error_t*)&neomsg;
|
neomessage_can_error_t& canerror = *(neomessage_can_error_t*)&neomsg;
|
||||||
auto canerrormsg = std::static_pointer_cast<CANErrorCountMessage>(message);
|
auto canerrormsg = std::static_pointer_cast<CANErrorMessage>(message);
|
||||||
canerror.transmitErrorCount = canerrormsg->transmitErrorCount;
|
canerror.transmitErrorCount = canerrormsg->transmitErrorCount;
|
||||||
canerror.receiveErrorCount = canerrormsg->receiveErrorCount;
|
canerror.receiveErrorCount = canerrormsg->receiveErrorCount;
|
||||||
canerror.status.canBusOff = canerrormsg->busOff;
|
canerror.status.canBusOff = canerrormsg->busOff;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
#include "icsneo/communication/packet/canpacket.h"
|
#include "icsneo/communication/packet/canpacket.h"
|
||||||
#include "icsneo/communication/message/canerrorcountmessage.h"
|
#include "icsneo/communication/message/canerrormessage.h"
|
||||||
|
|
||||||
using namespace icsneo;
|
using namespace icsneo;
|
||||||
|
|
||||||
|
|
@ -53,16 +53,18 @@ static std::optional<uint8_t> CAN_LengthToDLC(size_t dataLength, bool fd)
|
||||||
|
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Message> HardwareCANPacket::DecodeToMessage(const std::vector<uint8_t>& bytestream) {
|
std::shared_ptr<Message> HardwareCANPacket::DecodeToMessage(const std::vector<uint8_t>& bytestream) {
|
||||||
const HardwareCANPacket* data = (const HardwareCANPacket*)bytestream.data();
|
const HardwareCANPacket* data = (const HardwareCANPacket*)bytestream.data();
|
||||||
|
const HardwareCANErrorPacket* errPacket = (const HardwareCANErrorPacket*)bytestream.data();
|
||||||
if(data->dlc.RB1) { // Change counts reporting
|
if(errPacket->ERROR_INDICATOR) {
|
||||||
|
auto msg = std::make_shared<CANErrorMessage>();
|
||||||
const bool busOff = data->data[0] & 0b00100000;
|
msg->receiveErrorCount = errPacket->REC;
|
||||||
|
msg->transmitErrorCount = errPacket->TEC;
|
||||||
auto msg = std::make_shared<CANErrorCountMessage>(data->data[2], data->data[1], busOff);
|
msg->errorWarn = HardwareCANErrorPacket::GetErrorWarn(errPacket->flags);
|
||||||
|
msg->errorPassive = HardwareCANErrorPacket::GetErrorPassive(errPacket->flags);
|
||||||
|
msg->busOff = HardwareCANErrorPacket::GetBusOff(errPacket->flags);
|
||||||
|
msg->errorCode = (CANErrorCode)errPacket->error_code;
|
||||||
|
msg->dataErrorCode = (CANErrorCode)errPacket->brs_data_error_code;
|
||||||
// This timestamp is raw off the device (in timestampResolution increments)
|
// This timestamp is raw off the device (in timestampResolution increments)
|
||||||
// Decoder will fix as it has information about the timestampResolution increments
|
// Decoder will fix as it has information about the timestampResolution increments
|
||||||
msg->timestamp = data->timestamp.TS;
|
msg->timestamp = data->timestamp.TS;
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,8 @@ std::shared_ptr<EthernetMessage> HardwareEthernetPacket::DecodeToMessage(const s
|
||||||
if(packet->Length < 4)
|
if(packet->Length < 4)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
const size_t ethernetFrameSize = packet->Length - (sizeof(uint16_t) * 2);
|
const size_t fcsSize = packet->header.FCS_AVAIL ? 4 : 0;
|
||||||
const size_t bytestreamExpectedSize = sizeof(HardwareEthernetPacket) + ethernetFrameSize;
|
const size_t bytestreamExpectedSize = sizeof(HardwareEthernetPacket) + packet->Length;
|
||||||
const size_t bytestreamActualSize = bytestream.size();
|
const size_t bytestreamActualSize = bytestream.size();
|
||||||
if(bytestreamActualSize < bytestreamExpectedSize)
|
if(bytestreamActualSize < bytestreamExpectedSize)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
@ -37,8 +37,6 @@ std::shared_ptr<EthernetMessage> HardwareEthernetPacket::DecodeToMessage(const s
|
||||||
if(message.preemptionEnabled)
|
if(message.preemptionEnabled)
|
||||||
message.preemptionFlags = (uint8_t)((rawWords[0] & 0x03F8) >> 4);
|
message.preemptionFlags = (uint8_t)((rawWords[0] & 0x03F8) >> 4);
|
||||||
|
|
||||||
message.fcsAvailable = packet->header.FCS_AVAIL;
|
|
||||||
|
|
||||||
message.frameTooShort = packet->header.RUNT_FRAME;
|
message.frameTooShort = packet->header.RUNT_FRAME;
|
||||||
if(message.frameTooShort)
|
if(message.frameTooShort)
|
||||||
message.error = true;
|
message.error = true;
|
||||||
|
|
@ -47,12 +45,15 @@ std::shared_ptr<EthernetMessage> HardwareEthernetPacket::DecodeToMessage(const s
|
||||||
// Decoder will fix as it has information about the timestampResolution increments
|
// Decoder will fix as it has information about the timestampResolution increments
|
||||||
message.timestamp = packet->timestamp.TS;
|
message.timestamp = packet->timestamp.TS;
|
||||||
|
|
||||||
// Network ID is also not set, this will be fixed in the Decoder as well
|
const std::vector<uint8_t>::const_iterator databegin = bytestream.begin() + sizeof(HardwareEthernetPacket);
|
||||||
|
const std::vector<uint8_t>::const_iterator dataend = databegin + packet->Length - fcsSize;
|
||||||
const std::vector<uint8_t>::const_iterator databegin = bytestream.begin() + (sizeof(HardwareEthernetPacket) - (sizeof(uint16_t) * 2));
|
|
||||||
const std::vector<uint8_t>::const_iterator dataend = databegin + ethernetFrameSize;
|
|
||||||
message.data.insert(message.data.begin(), databegin, dataend);
|
message.data.insert(message.data.begin(), databegin, dataend);
|
||||||
|
|
||||||
|
if(fcsSize) {
|
||||||
|
uint32_t& fcs = message.fcs.emplace();
|
||||||
|
std::copy(dataend, dataend + fcsSize, (uint8_t*)&fcs);
|
||||||
|
}
|
||||||
|
|
||||||
return messagePtr;
|
return messagePtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -88,6 +88,10 @@ Device::~Device() {
|
||||||
disableMessagePolling();
|
disableMessagePolling();
|
||||||
if(isOpen())
|
if(isOpen())
|
||||||
close();
|
close();
|
||||||
|
if(heartbeatThread.joinable()) {
|
||||||
|
stopHeartbeatThread = true;
|
||||||
|
heartbeatThread.join();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t Device::getTimestampResolution() const {
|
uint16_t Device::getTimestampResolution() const {
|
||||||
|
|
@ -218,8 +222,7 @@ bool Device::open(OpenFlags flags, OpenStatusHandler handler) {
|
||||||
if(block) // Extensions say no
|
if(block) // Extensions say no
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Get component versions *after* the extension "onDeviceOpen" hooks (e.g. device reflashes)
|
// Get component versions again *after* the extension "onDeviceOpen" hooks (e.g. device reflashes)
|
||||||
|
|
||||||
if(supportsComponentVersions()) {
|
if(supportsComponentVersions()) {
|
||||||
if(auto compVersions = com->getComponentVersionsSync())
|
if(auto compVersions = com->getComponentVersionsSync())
|
||||||
componentVersions = std::move(*compVersions);
|
componentVersions = std::move(*compVersions);
|
||||||
|
|
@ -246,6 +249,12 @@ bool Device::open(OpenFlags flags, OpenStatusHandler handler) {
|
||||||
handleInternalMessage(message);
|
handleInternalMessage(message);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
// Clear the previous heartbeat thread, in case open() was called on this instance more than once
|
||||||
|
if(heartbeatThread.joinable())
|
||||||
|
heartbeatThread.join();
|
||||||
|
|
||||||
|
stopHeartbeatThread = false;
|
||||||
|
|
||||||
heartbeatThread = std::thread([this]() {
|
heartbeatThread = std::thread([this]() {
|
||||||
EventManager::GetInstance().downgradeErrorsOnCurrentThread();
|
EventManager::GetInstance().downgradeErrorsOnCurrentThread();
|
||||||
|
|
||||||
|
|
@ -271,12 +280,12 @@ bool Device::open(OpenFlags flags, OpenStatusHandler handler) {
|
||||||
}
|
}
|
||||||
|
|
||||||
while(!stopHeartbeatThread) {
|
while(!stopHeartbeatThread) {
|
||||||
// Wait for 110ms for a possible heartbeat
|
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(110));
|
|
||||||
std::unique_lock<std::mutex> recvLk(receivedMessageMutex);
|
std::unique_lock<std::mutex> recvLk(receivedMessageMutex);
|
||||||
if(receivedMessage) {
|
// Wait for 110ms for a possible heartbeat
|
||||||
|
if(heartbeatCV.wait_for(recvLk, std::chrono::milliseconds(110), [&]() { return receivedMessage; })) {
|
||||||
receivedMessage = false;
|
receivedMessage = false;
|
||||||
} else {
|
} else if(!stopHeartbeatThread) { // Add this condition here in case the thread was stopped while waiting for the last message
|
||||||
|
|
||||||
// Some communication, such as the bootloader and extractor interfaces, must
|
// Some communication, such as the bootloader and extractor interfaces, must
|
||||||
// redirect the input stream from the device as it will no longer be in the
|
// redirect the input stream from the device as it will no longer be in the
|
||||||
// packet format we expect here. As a result, status updates will not reach
|
// packet format we expect here. As a result, status updates will not reach
|
||||||
|
|
@ -285,9 +294,8 @@ bool Device::open(OpenFlags flags, OpenStatusHandler handler) {
|
||||||
// otherwise quiet stream. This lock makes sure suppressDisconnects() will
|
// otherwise quiet stream. This lock makes sure suppressDisconnects() will
|
||||||
// block until we've either gotten our status update or disconnected from
|
// block until we've either gotten our status update or disconnected from
|
||||||
// the device.
|
// the device.
|
||||||
std::lock_guard<std::mutex> lk(heartbeatMutex);
|
std::unique_lock<std::mutex> lk(heartbeatMutex);
|
||||||
if(heartbeatSuppressed())
|
if(heartbeatSuppressed()) continue;
|
||||||
continue;
|
|
||||||
|
|
||||||
// No heartbeat received, request a status
|
// No heartbeat received, request a status
|
||||||
com->sendCommand(Command::RequestStatusUpdate);
|
com->sendCommand(Command::RequestStatusUpdate);
|
||||||
|
|
@ -297,8 +305,8 @@ bool Device::open(OpenFlags flags, OpenStatusHandler handler) {
|
||||||
receivedMessage = false;
|
receivedMessage = false;
|
||||||
} else {
|
} else {
|
||||||
if(!stopHeartbeatThread && !isDisconnected()) {
|
if(!stopHeartbeatThread && !isDisconnected()) {
|
||||||
|
close();
|
||||||
report(APIEvent::Type::DeviceDisconnected, APIEvent::Severity::Error);
|
report(APIEvent::Type::DeviceDisconnected, APIEvent::Severity::Error);
|
||||||
com->driver->close();
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -348,6 +356,15 @@ APIEvent::Type Device::attemptToBeginCommunication() {
|
||||||
else
|
else
|
||||||
versions = std::move(*maybeVersions);
|
versions = std::move(*maybeVersions);
|
||||||
|
|
||||||
|
|
||||||
|
// Get component versions before the extension "onDeviceOpen" hooks so that we can properly check verisons
|
||||||
|
if(supportsComponentVersions()) {
|
||||||
|
if(auto compVersions = com->getComponentVersionsSync())
|
||||||
|
componentVersions = std::move(*compVersions);
|
||||||
|
else
|
||||||
|
return getCommunicationNotEstablishedError();
|
||||||
|
}
|
||||||
|
|
||||||
return APIEvent::Type::NoErrorFound;
|
return APIEvent::Type::NoErrorFound;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -371,10 +388,6 @@ bool Device::close() {
|
||||||
|
|
||||||
internalHandlerCallbackID = 0;
|
internalHandlerCallbackID = 0;
|
||||||
|
|
||||||
if(heartbeatThread.joinable())
|
|
||||||
heartbeatThread.join();
|
|
||||||
stopHeartbeatThread = false;
|
|
||||||
|
|
||||||
forEachExtension([](const std::shared_ptr<DeviceExtension>& ext) { ext->onDeviceClose(); return true; });
|
forEachExtension([](const std::shared_ptr<DeviceExtension>& ext) { ext->onDeviceClose(); return true; });
|
||||||
return com->close();
|
return com->close();
|
||||||
}
|
}
|
||||||
|
|
@ -806,12 +819,6 @@ std::shared_ptr<HardwareInfo> Device::getHardwareInfo(std::chrono::milliseconds
|
||||||
report(APIEvent::Type::DeviceCurrentlyClosed, APIEvent::Severity::Error);
|
report(APIEvent::Type::DeviceCurrentlyClosed, APIEvent::Severity::Error);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!isOnline()) {
|
|
||||||
report(APIEvent::Type::DeviceCurrentlyOffline, APIEvent::Severity::Error);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto filter = std::make_shared<MessageFilter>(Message::Type::HardwareInfo);
|
auto filter = std::make_shared<MessageFilter>(Message::Type::HardwareInfo);
|
||||||
|
|
||||||
auto response = com->waitForMessageSync([this]() {
|
auto response = com->waitForMessageSync([this]() {
|
||||||
|
|
@ -1691,7 +1698,10 @@ void Device::stopScriptStatusThreadIfNecessary(std::unique_lock<std::mutex> lk)
|
||||||
Lifetime Device::suppressDisconnects() {
|
Lifetime Device::suppressDisconnects() {
|
||||||
std::lock_guard<std::mutex> lk(heartbeatMutex);
|
std::lock_guard<std::mutex> lk(heartbeatMutex);
|
||||||
heartbeatSuppressedByUser++;
|
heartbeatSuppressedByUser++;
|
||||||
return Lifetime([this] { std::lock_guard<std::mutex> lk2(heartbeatMutex); heartbeatSuppressedByUser--; });
|
return Lifetime([this] {
|
||||||
|
std::lock_guard<std::mutex> lk2(heartbeatMutex);
|
||||||
|
heartbeatSuppressedByUser--;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void Device::addExtension(std::shared_ptr<DeviceExtension>&& extension) {
|
void Device::addExtension(std::shared_ptr<DeviceExtension>&& extension) {
|
||||||
|
|
@ -1721,15 +1731,6 @@ void Device::handleInternalMessage(std::shared_ptr<Message> message) {
|
||||||
case Message::Type::RawMessage: {
|
case Message::Type::RawMessage: {
|
||||||
auto rawMessage = std::static_pointer_cast<RawMessage>(message);
|
auto rawMessage = std::static_pointer_cast<RawMessage>(message);
|
||||||
switch(rawMessage->network.getNetID()) {
|
switch(rawMessage->network.getNetID()) {
|
||||||
case Network::NetID::Device: {
|
|
||||||
// Device is not guaranteed to be a CANMessage, it might be a RawMessage
|
|
||||||
// if it couldn't be decoded to a CANMessage. We only care about the
|
|
||||||
// CANMessage decoding right now.
|
|
||||||
auto canmsg = std::dynamic_pointer_cast<CANMessage>(message);
|
|
||||||
if(canmsg)
|
|
||||||
handleNeoVIMessage(std::move(canmsg));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case Network::NetID::DeviceStatus:
|
case Network::NetID::DeviceStatus:
|
||||||
// Device Status format is unique per device, so the devices need to decode it themselves
|
// Device Status format is unique per device, so the devices need to decode it themselves
|
||||||
handleDeviceStatus(rawMessage);
|
handleDeviceStatus(rawMessage);
|
||||||
|
|
@ -1739,6 +1740,15 @@ void Device::handleInternalMessage(std::shared_ptr<Message> message) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case Message::Type::Frame: {
|
||||||
|
// Device is not guaranteed to be a CANMessage, it might be a RawMessage
|
||||||
|
// if it couldn't be decoded to a CANMessage. We only care about the
|
||||||
|
// CANMessage decoding right now.
|
||||||
|
auto canmsg = std::dynamic_pointer_cast<CANMessage>(message);
|
||||||
|
if(canmsg)
|
||||||
|
handleNeoVIMessage(std::move(canmsg));
|
||||||
|
break;
|
||||||
|
}
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
forEachExtension([&](const std::shared_ptr<DeviceExtension>& ext) {
|
forEachExtension([&](const std::shared_ptr<DeviceExtension>& ext) {
|
||||||
|
|
@ -1984,11 +1994,6 @@ std::optional<size_t> Device::getGenericBinarySize(uint16_t binaryIndex) {
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!isOnline()) {
|
|
||||||
report(APIEvent::Type::DeviceCurrentlyOffline, APIEvent::Severity::Error);
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<uint8_t> args = GenericBinaryStatusPacket::EncodeArguments(binaryIndex);
|
std::vector<uint8_t> args = GenericBinaryStatusPacket::EncodeArguments(binaryIndex);
|
||||||
|
|
||||||
std::shared_ptr<Message> response = com->waitForMessageSync(
|
std::shared_ptr<Message> response = com->waitForMessageSync(
|
||||||
|
|
@ -2051,6 +2056,40 @@ bool Device::readBinaryFile(std::ostream& stream, uint16_t binaryIndex) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Device::writeBinaryFile(const std::vector<uint8_t>& in, uint16_t binaryIndex)
|
||||||
|
{
|
||||||
|
auto timeout = std::chrono::milliseconds(100);
|
||||||
|
|
||||||
|
auto size = in.size();
|
||||||
|
|
||||||
|
std::vector<uint8_t> arguments(sizeof(ExtendedDataMessage::ExtendedDataHeader) + ExtendedDataMessage::MaxExtendedDataBufferSize);
|
||||||
|
ExtendedDataMessage::ExtendedDataHeader& parameters = *reinterpret_cast<ExtendedDataMessage::ExtendedDataHeader*>(arguments.data());
|
||||||
|
|
||||||
|
auto filter = std::make_shared<MessageFilter>(Network::NetID::ExtendedData);
|
||||||
|
|
||||||
|
for (size_t offset = 0; offset < size; offset += ExtendedDataMessage::MaxExtendedDataBufferSize)
|
||||||
|
{
|
||||||
|
parameters.subCommand = ExtendedDataSubCommand::GenericBinaryWrite;
|
||||||
|
parameters.userValue = static_cast<uint32_t>(binaryIndex);
|
||||||
|
parameters.offset = static_cast<uint32_t>(offset);
|
||||||
|
parameters.length = static_cast<uint32_t>(std::min(ExtendedDataMessage::MaxExtendedDataBufferSize, size - offset));
|
||||||
|
(void)memcpy(&arguments[sizeof(ExtendedDataMessage::ExtendedDataHeader)], &in[offset], parameters.length);
|
||||||
|
|
||||||
|
std::shared_ptr<Message> response = com->waitForMessageSync(
|
||||||
|
[this, arguments]() {
|
||||||
|
return com->sendCommand(Command::ExtendedData, arguments);
|
||||||
|
},
|
||||||
|
filter,
|
||||||
|
timeout
|
||||||
|
);
|
||||||
|
if (!response) {
|
||||||
|
report(APIEvent::Type::NoDeviceResponse, APIEvent::Severity::Error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool Device::subscribeLiveData(std::shared_ptr<LiveDataCommandMessage> message) {
|
bool Device::subscribeLiveData(std::shared_ptr<LiveDataCommandMessage> message) {
|
||||||
if(!supportsLiveData()) {
|
if(!supportsLiveData()) {
|
||||||
report(APIEvent::Type::LiveDataNotSupported, APIEvent::Severity::Error);
|
report(APIEvent::Type::LiveDataNotSupported, APIEvent::Severity::Error);
|
||||||
|
|
@ -3335,3 +3374,43 @@ std::optional<TC10StatusMessage> Device::getTC10Status(Network::NetID network) {
|
||||||
|
|
||||||
return *typed;
|
return *typed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<GPTPStatus> Device::getGPTPStatus(std::chrono::milliseconds timeout) {
|
||||||
|
if(!supportsGPTP()) {
|
||||||
|
report(APIEvent::Type::GPTPNotSupported, APIEvent::Severity::Error);
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!isOpen()) {
|
||||||
|
report(APIEvent::Type::DeviceCurrentlyClosed, APIEvent::Severity::Error);
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Message> response = com->waitForMessageSync(
|
||||||
|
[this](){
|
||||||
|
return com->sendCommand(ExtendedCommand::GetGPTPStatus, {});
|
||||||
|
},
|
||||||
|
std::make_shared<MessageFilter>(Message::Type::GPTPStatus),
|
||||||
|
timeout
|
||||||
|
);
|
||||||
|
|
||||||
|
if(!response) {
|
||||||
|
report(APIEvent::Type::NoDeviceResponse, APIEvent::Severity::Error);
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
auto retMsg = std::static_pointer_cast<GPTPStatus>(response);
|
||||||
|
if(!retMsg) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
return *retMsg;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Device::writeMACsecConfig(const MACsecMessage& message, uint16_t binaryIndex)
|
||||||
|
{
|
||||||
|
std::vector<uint8_t> raw;
|
||||||
|
|
||||||
|
message.EncodeFromMessage(raw, report);
|
||||||
|
|
||||||
|
return writeBinaryFile(raw, binaryIndex);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ subprocess.call('cd ..; doxygen docs/icsneoc/Doxyfile', shell=True)
|
||||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
|
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
|
||||||
|
|
||||||
project = 'libicsneo'
|
project = 'libicsneo'
|
||||||
copyright = '2024, Intrepid Control Systems, Inc.'
|
copyright = '2024-2025, Intrepid Control Systems, Inc.'
|
||||||
author = 'Intrepid Control Systems, Inc.'
|
author = 'Intrepid Control Systems, Inc.'
|
||||||
|
|
||||||
# -- General configuration ---------------------------------------------------
|
# -- General configuration ---------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -6,4 +6,5 @@ Python API
|
||||||
:members:
|
:members:
|
||||||
:undoc-members:
|
:undoc-members:
|
||||||
:show-inheritance:
|
:show-inheritance:
|
||||||
|
:imported-members:
|
||||||
:special-members: __init__
|
:special-members: __init__
|
||||||
|
|
|
||||||
|
|
@ -50,3 +50,41 @@ Receive CAN frames on HSCAN
|
||||||
|
|
||||||
# rx for 10s
|
# rx for 10s
|
||||||
time.sleep(10)
|
time.sleep(10)
|
||||||
|
|
||||||
|
|
||||||
|
Monitor Ethernet Status
|
||||||
|
=======================
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
import icsneopy
|
||||||
|
import time
|
||||||
|
|
||||||
|
def main():
|
||||||
|
devices = icsneopy.find_all_devices()
|
||||||
|
if len(devices) == 0:
|
||||||
|
print("error: no devices found")
|
||||||
|
return False
|
||||||
|
|
||||||
|
device = devices[0]
|
||||||
|
print(f"info: monitoring Ethernet status on {device}")
|
||||||
|
|
||||||
|
def on_message(message):
|
||||||
|
print(f"info: network: {message.network}, state: {message.state}, speed: {message.speed}, duplex: {message.duplex}, mode: {message.mode}")
|
||||||
|
|
||||||
|
filter = icsneopy.MessageFilter(icsneopy.Message.Type.EthernetStatus)
|
||||||
|
callback = icsneopy.MessageCallback(on_message, filter)
|
||||||
|
device.add_message_callback(callback)
|
||||||
|
|
||||||
|
if not device.open():
|
||||||
|
print("error: unable to open device")
|
||||||
|
return False
|
||||||
|
|
||||||
|
if not device.go_online():
|
||||||
|
print("error: unable to go online")
|
||||||
|
return False
|
||||||
|
|
||||||
|
while True:
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
main()
|
||||||
|
|
|
||||||
|
|
@ -267,7 +267,7 @@ void printMessage(const std::shared_ptr<icsneo::Message>& message) {
|
||||||
} // end of icsneo::Message::Type::Frame
|
} // end of icsneo::Message::Type::Frame
|
||||||
case icsneo::Message::Type::CANErrorCount: {
|
case icsneo::Message::Type::CANErrorCount: {
|
||||||
// A message of type CANErrorCount is guaranteed to be a CANErrorCount, so we can static cast safely
|
// A message of type CANErrorCount is guaranteed to be a CANErrorCount, so we can static cast safely
|
||||||
auto cec = std::static_pointer_cast<icsneo::CANErrorCountMessage>(message);
|
auto cec = std::static_pointer_cast<icsneo::CANErrorMessage>(message);
|
||||||
std::cout << "\t\t" << cec->network << " error counts changed, REC=" << cec->receiveErrorCount
|
std::cout << "\t\t" << cec->network << " error counts changed, REC=" << cec->receiveErrorCount
|
||||||
<< " TEC=" << cec->transmitErrorCount << " (" << (cec->busOff ? "" : "Not ") << "Bus Off)" << std::endl;
|
<< " TEC=" << cec->transmitErrorCount << " (" << (cec->busOff ? "" : "Not ") << "Bus Off)" << std::endl;
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -252,7 +252,7 @@ int main() {
|
||||||
} // end of icsneo::Message::Type::Frame
|
} // end of icsneo::Message::Type::Frame
|
||||||
case icsneo::Message::Type::CANErrorCount: {
|
case icsneo::Message::Type::CANErrorCount: {
|
||||||
// A message of type CANErrorCount is guaranteed to be a CANErrorCount, so we can static cast safely
|
// A message of type CANErrorCount is guaranteed to be a CANErrorCount, so we can static cast safely
|
||||||
auto cec = std::static_pointer_cast<icsneo::CANErrorCountMessage>(message);
|
auto cec = std::static_pointer_cast<icsneo::CANErrorMessage>(message);
|
||||||
|
|
||||||
// Print the error counts
|
// Print the error counts
|
||||||
std::cout << "\t\t" << cec->network << " error counts changed, REC=" << std::to_string(cec->receiveErrorCount)
|
std::cout << "\t\t" << cec->network << " error counts changed, REC=" << std::to_string(cec->receiveErrorCount)
|
||||||
|
|
|
||||||
|
|
@ -109,6 +109,7 @@ public:
|
||||||
LINSettingsNotAvailable = 0x2053,
|
LINSettingsNotAvailable = 0x2053,
|
||||||
ModeNotFound = 0x2054,
|
ModeNotFound = 0x2054,
|
||||||
AppErrorParsingFailed = 0x2055,
|
AppErrorParsingFailed = 0x2055,
|
||||||
|
GPTPNotSupported = 0x2056,
|
||||||
|
|
||||||
// Transport Events
|
// Transport Events
|
||||||
FailedToRead = 0x3000,
|
FailedToRead = 0x3000,
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,7 @@ enum class ExtendedCommand : uint16_t {
|
||||||
StartDHCPServer = 0x0016,
|
StartDHCPServer = 0x0016,
|
||||||
StopDHCPServer = 0x0017,
|
StopDHCPServer = 0x0017,
|
||||||
GetSupportedFeatures = 0x0018,
|
GetSupportedFeatures = 0x0018,
|
||||||
|
GetGPTPStatus = 0x0019,
|
||||||
GetComponentVersions = 0x001A,
|
GetComponentVersions = 0x001A,
|
||||||
Reboot = 0x001C,
|
Reboot = 0x001C,
|
||||||
SetRootFSEntryFlags = 0x0027,
|
SetRootFSEntryFlags = 0x0027,
|
||||||
|
|
@ -72,6 +73,7 @@ enum class ExtendedResponse : int32_t {
|
||||||
|
|
||||||
enum class ExtendedDataSubCommand : uint32_t {
|
enum class ExtendedDataSubCommand : uint32_t {
|
||||||
GenericBinaryRead = 13,
|
GenericBinaryRead = 13,
|
||||||
|
GenericBinaryWrite = 14,
|
||||||
};
|
};
|
||||||
|
|
||||||
#pragma pack(push,1)
|
#pragma pack(push,1)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
/*
|
||||||
|
* crc32.h
|
||||||
|
*
|
||||||
|
* Created on: Jun 22, 2020
|
||||||
|
* Author: BJones
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef CRC32_H_
|
||||||
|
#define CRC32_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When any data/buffer is run through calCRC(), then the resulting CRC value
|
||||||
|
* is appended to the end of the data/buffer and the data/buffer is rerun
|
||||||
|
* through calCRC(), the result will be CRC32_IDENT
|
||||||
|
*/
|
||||||
|
#define CRC32_IDENT (0x2144DF1C) /**< CRC check value */
|
||||||
|
|
||||||
|
#define CRC32_ISVALID(crc) ((crc) == CRC32_IDENT)
|
||||||
|
|
||||||
|
uint32_t crc32(uint32_t crc, const unsigned char* buf, uint32_t len);
|
||||||
|
uint32_t revcrc32(uint32_t crc, const unsigned char* buf, uint32_t len);
|
||||||
|
|
||||||
|
#endif // CRC32_H_
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
#ifndef __CANERRORCOUNTMESSAGE_H_
|
|
||||||
#define __CANERRORCOUNTMESSAGE_H_
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
|
|
||||||
#include "icsneo/communication/message/message.h"
|
|
||||||
|
|
||||||
namespace icsneo {
|
|
||||||
|
|
||||||
class CANErrorCountMessage : public Message {
|
|
||||||
public:
|
|
||||||
CANErrorCountMessage(uint8_t tec, uint8_t rec, bool busOffFlag)
|
|
||||||
: Message(Message::Type::CANErrorCount), transmitErrorCount(tec), receiveErrorCount(rec), busOff(busOffFlag){}
|
|
||||||
|
|
||||||
Network network;
|
|
||||||
uint8_t transmitErrorCount;
|
|
||||||
uint8_t receiveErrorCount;
|
|
||||||
bool busOff;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // __cplusplus
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
#ifndef __CANERRORMESSAGE_H_
|
||||||
|
#define __CANERRORMESSAGE_H_
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
|
||||||
|
#include "icsneo/communication/message/message.h"
|
||||||
|
|
||||||
|
namespace icsneo {
|
||||||
|
|
||||||
|
enum class CANErrorCode : uint8_t
|
||||||
|
{
|
||||||
|
NoError = 0,
|
||||||
|
StuffError = 1,
|
||||||
|
FormError = 2,
|
||||||
|
AckError = 3,
|
||||||
|
Bit1Error = 4,
|
||||||
|
Bit0Error = 5,
|
||||||
|
CRCError = 6,
|
||||||
|
NoChange = 7
|
||||||
|
};
|
||||||
|
class CANErrorMessage : public Message {
|
||||||
|
public:
|
||||||
|
CANErrorMessage() : Message(Type::CANError) {}
|
||||||
|
Network network;
|
||||||
|
uint8_t transmitErrorCount;
|
||||||
|
uint8_t receiveErrorCount;
|
||||||
|
bool busOff;
|
||||||
|
bool errorPassive;
|
||||||
|
bool errorWarn;
|
||||||
|
CANErrorCode dataErrorCode;
|
||||||
|
CANErrorCode errorCode;
|
||||||
|
};
|
||||||
|
|
||||||
|
using CANErrorCountMessage = CANErrorMessage;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // __cplusplus
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -35,7 +35,7 @@ class EthernetMessage : public Frame {
|
||||||
public:
|
public:
|
||||||
bool preemptionEnabled = false;
|
bool preemptionEnabled = false;
|
||||||
uint8_t preemptionFlags = 0;
|
uint8_t preemptionFlags = 0;
|
||||||
bool fcsAvailable = false;
|
std::optional<uint32_t> fcs;
|
||||||
bool frameTooShort = false;
|
bool frameTooShort = false;
|
||||||
bool noPadding = false;
|
bool noPadding = false;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
#ifndef __ETHERNETSTATUSMESSAGE_H__
|
||||||
|
#define __ETHERNETSTATUSMESSAGE_H__
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
|
||||||
|
#include "icsneo/communication/message/message.h"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace icsneo {
|
||||||
|
|
||||||
|
class EthernetStatusMessage : public Message {
|
||||||
|
public:
|
||||||
|
enum class LinkSpeed {
|
||||||
|
LinkSpeedAuto,
|
||||||
|
LinkSpeed10,
|
||||||
|
LinkSpeed100,
|
||||||
|
LinkSpeed1000,
|
||||||
|
LinkSpeed2500,
|
||||||
|
LinkSpeed5000,
|
||||||
|
LinkSpeed10000,
|
||||||
|
};
|
||||||
|
enum class LinkMode {
|
||||||
|
LinkModeAuto,
|
||||||
|
LinkModeMaster,
|
||||||
|
LinkModeSlave,
|
||||||
|
LinkModeInvalid,
|
||||||
|
};
|
||||||
|
EthernetStatusMessage(Network net, bool state, LinkSpeed speed, bool duplex, LinkMode mode) : Message(Type::EthernetStatus),
|
||||||
|
network(net), state(state), speed(speed), duplex(duplex), mode(mode) {}
|
||||||
|
Network network;
|
||||||
|
bool state;
|
||||||
|
LinkSpeed speed;
|
||||||
|
bool duplex;
|
||||||
|
LinkMode mode;
|
||||||
|
static std::shared_ptr<Message> DecodeToMessage(const std::vector<uint8_t>& bytestream);
|
||||||
|
};
|
||||||
|
|
||||||
|
}; // namespace icsneo
|
||||||
|
|
||||||
|
#endif // __cplusplus
|
||||||
|
|
||||||
|
#endif // __ETHERNETSTATUSMESSAGE_H__
|
||||||
|
|
@ -0,0 +1,103 @@
|
||||||
|
#ifndef __GPTPSTATUSMESSAGE_H_
|
||||||
|
#define __GPTPSTATUSMESSAGE_H_
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
|
||||||
|
#include "icsneo/communication/message/message.h"
|
||||||
|
#include "icsneo/communication/command.h"
|
||||||
|
#include "icsneo/api/eventmanager.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace icsneo {
|
||||||
|
|
||||||
|
class GPTPStatus : public Message {
|
||||||
|
public:
|
||||||
|
typedef uint64_t TimeInterval;
|
||||||
|
typedef uint64_t ClockID;
|
||||||
|
|
||||||
|
struct Timestamp {
|
||||||
|
uint64_t seconds;
|
||||||
|
uint32_t nanoseconds;
|
||||||
|
|
||||||
|
double toSeconds() const {
|
||||||
|
static constexpr double billion = 1e9;
|
||||||
|
return (double)seconds + ((double)nanoseconds) / billion;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ScaledNanoSeconds {
|
||||||
|
int16_t nanosecondsMSB; // The most significant bits
|
||||||
|
int64_t nanosecondsLSB; // The least significant bits
|
||||||
|
int16_t fractionalNanoseconds; // Fractional part
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PortID {
|
||||||
|
ClockID clockIdentity;
|
||||||
|
uint16_t portNumber;
|
||||||
|
};
|
||||||
|
struct ClockQuality {
|
||||||
|
uint8_t clockClass;
|
||||||
|
uint8_t clockAccuracy;
|
||||||
|
uint16_t offsetScaledLogVariance;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SystemID {
|
||||||
|
uint8_t priority1;
|
||||||
|
ClockQuality clockQuality;
|
||||||
|
uint8_t priority2;
|
||||||
|
ClockID clockID;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PriorityVector {
|
||||||
|
SystemID sysID;
|
||||||
|
uint16_t stepsRemoved;
|
||||||
|
PortID portID;
|
||||||
|
uint16_t portNumber;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ParentDS {
|
||||||
|
PortID parentPortIdentity;
|
||||||
|
int32_t cumulativeRateRatio;
|
||||||
|
ClockID grandmasterIdentity;
|
||||||
|
uint8_t gmClockQualityClockClass;
|
||||||
|
uint8_t gmClockQualityClockAccuracy;
|
||||||
|
uint16_t gmClockQualityOffsetScaledLogVariance;
|
||||||
|
uint8_t gmPriority1;
|
||||||
|
uint8_t gmPriority2;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CurrentDS {
|
||||||
|
uint16_t stepsRemoved;
|
||||||
|
TimeInterval offsetFromMaster;
|
||||||
|
ScaledNanoSeconds lastgmPhaseChange;
|
||||||
|
double lastgmFreqChange;
|
||||||
|
uint16_t gmTimeBaseIndicator;
|
||||||
|
uint32_t gmChangeCount;
|
||||||
|
uint32_t timeOfLastgmChangeEvent;
|
||||||
|
uint32_t timeOfLastgmPhaseChangeEvent;
|
||||||
|
uint32_t timeOfLastgmFreqChangeEvent;
|
||||||
|
};
|
||||||
|
|
||||||
|
GPTPStatus() : Message(Message::Type::GPTPStatus) {}
|
||||||
|
static std::shared_ptr<GPTPStatus> DecodeToMessage(std::vector<uint8_t>& bytes, const device_eventhandler_t& report);
|
||||||
|
|
||||||
|
Timestamp currentTime;
|
||||||
|
PriorityVector gmPriority;
|
||||||
|
int64_t msOffsetNs;
|
||||||
|
uint8_t isSync;
|
||||||
|
uint8_t linkStatus;
|
||||||
|
int64_t linkDelayNS;
|
||||||
|
uint8_t selectedRole;
|
||||||
|
uint8_t asCapable;
|
||||||
|
uint8_t isSyntonized;
|
||||||
|
Timestamp lastRXSyncTS; // t2 in IEEE 1588-2019 Figure-16
|
||||||
|
CurrentDS currentDS;
|
||||||
|
ParentDS parentDS;
|
||||||
|
|
||||||
|
bool shortFormat = false; // Set to true if the above variables weren't set (some firmware versions do not contain all the above variables)
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
@ -0,0 +1,200 @@
|
||||||
|
#ifndef __MACSECMESSAGE_H__
|
||||||
|
#define __MACSECMESSAGE_H__
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
|
||||||
|
#include "icsneo/communication/message/message.h"
|
||||||
|
#include "icsneo/communication/packet.h"
|
||||||
|
#include "icsneo/api/eventmanager.h"
|
||||||
|
#include <vector>
|
||||||
|
#include <memory>
|
||||||
|
#include <array>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
namespace icsneo {
|
||||||
|
|
||||||
|
struct MACsecVLANTag
|
||||||
|
{
|
||||||
|
uint16_t vid; /*!< 12 bits */
|
||||||
|
uint8_t priCfi; /*!< PRI - 3 bits, CFI - 1bit */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MACsecMPLSOuter
|
||||||
|
{
|
||||||
|
uint32_t mplsLabel; /*!< 20 bits */
|
||||||
|
uint8_t exp; /*!< 3 bits */
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class MACsecPacketType : uint8_t
|
||||||
|
{
|
||||||
|
NoVLANOrMPLS = 0,
|
||||||
|
SingleVLAN = 1,
|
||||||
|
DualVLAN = 2,
|
||||||
|
MPLS = 3,
|
||||||
|
SingleVLANFollowedByMPLS = 4,
|
||||||
|
DualVLANFollowedByMPLS = 5,
|
||||||
|
Unsupported = 6,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MACsecRule
|
||||||
|
{
|
||||||
|
uint8_t index;
|
||||||
|
std::array<uint8_t, 6> keyMacDa; /*!< MAC DA field extracted from the packet */
|
||||||
|
std::array<uint8_t, 6> maskMacDa; /*!< Set bits to 1 to mask/exclude corresponding flowid_tcam_data bit from compare */
|
||||||
|
std::array<uint8_t, 6> keyMacSa; /*!< MAC SA field extracted from the packet */
|
||||||
|
std::array<uint8_t, 6> maskMacSa; /*!< Set bits to 1 to mask/exclude corresponding flowid_tcam_data bit from compare */
|
||||||
|
uint16_t keyEthertype; /*!< First E-Type found in the packet that doesn't match one of the preconfigured custom tag. */
|
||||||
|
uint16_t maskEthertype; /*!< Set bits to 1 to mask/exclude corresponding flowid_tcam_data bit from compare */
|
||||||
|
MACsecVLANTag keyVlanTagOuter1; /*!< outermost/1st VLAN ID {8'd0, VLAN_ID[11:0]}, or 20-bit MPLS label. */
|
||||||
|
MACsecMPLSOuter keyMplsOuter1;
|
||||||
|
MACsecVLANTag maskVlanTagOuter1; /*!< Set bits to 1 to mask/exclude corresponding flowid_tcam_data bit from compare */
|
||||||
|
MACsecMPLSOuter maskMplsOuter1;
|
||||||
|
MACsecVLANTag keyVlanTagOuter2; /*!< 2nd outermost VLAN ID {8'd0, VLAN_ID[11:0]}, or 20-bit MPLS label. */
|
||||||
|
MACsecMPLSOuter keyMplsOuter2;
|
||||||
|
MACsecVLANTag maskVlanTagOuter2; /*!< Set bits to 1 to mask/exclude corresponding flowid_tcam_data bit from compare */
|
||||||
|
MACsecMPLSOuter maskMplsOuter2;
|
||||||
|
uint16_t keyBonusData; /*!< 2 bytes of additional bonus data extracted from one of the custom tags. */
|
||||||
|
uint16_t maskBonusData; /*!< Set bits to 1 to mask/exclude corresponding flowid_tcam_data bit from compare */
|
||||||
|
uint8_t keyTagMatchBitmap; /*!< 8 bits total. Maps 1 to 1 bitwise with the set of custom tags. (set bit[N]=1 if check Nth custom tag) */
|
||||||
|
uint8_t maskTagMatchBitmap; /*!< Set bits to 1 to mask/exclude corresponding flowid_tcam_data bit from compare */
|
||||||
|
MACsecPacketType keyPacketType; /*!< Encoded Packet Type, see MACSEC_PACKET_TYPE */
|
||||||
|
uint8_t maskPacketType; /*!< Set bits to 1 to mask/exclude corresponding flowid_tcam_data bit from compare */
|
||||||
|
uint16_t keyInnerVlanType; /*!< 3 bits total. Encoded value indicating which VLAN TPID value matched for the second outermost VLAN Tag. */
|
||||||
|
uint16_t maskInnerVlanType; /*!< Set bits to 1 to mask/exclude corresponding flowid_tcam_data bit from compare */
|
||||||
|
uint16_t keyOuterVlanType; /*!< 3 bits total. Encoded value indicating which VLAN TPID value matched for the outermost VLAN Tag. */
|
||||||
|
uint16_t maskOuterVlanType; /*!< Set bits to 1 to mask/exclude corresponding flowid_tcam_data bit from compare */
|
||||||
|
uint8_t keyNumTags; /*!< 7 bits total. Number of VLAN/custom tags or MPLS lables detected. Ingress: before SecTag; Egress: total detected. Exclude MCS header tags. i.e. Bit 2: 2 tags/labels before SecTAG...Bit 6: 6 or more tags/labels before SecTAG. */
|
||||||
|
uint8_t maskNumTags; /*!< Set bits to 1 to mask/exclude corresponding flowid_tcam_data bit from compare */
|
||||||
|
bool keyExpress; /*!< 1 bits. Express packet. */
|
||||||
|
uint8_t maskExpress; /*!< Set bits to 1 to mask/exclude corresponding flowid_tcam_data bit from compare */
|
||||||
|
bool isMpls;
|
||||||
|
bool enable;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MACsecMap
|
||||||
|
{
|
||||||
|
uint8_t index;
|
||||||
|
uint64_t secTagSci; /*!< Identifies the SecTAG SCI for this Flow. */
|
||||||
|
uint8_t secYIndex; /*!< index for entry in Egress secY Policy */
|
||||||
|
bool isControlPacket; /*!< Identifies all packets matching this index lookup as control packets. */
|
||||||
|
uint8_t scIndex; /*!< Identifies the SC for this Flow. */
|
||||||
|
uint8_t auxiliaryPlcy; /*!< Auxiliary policy bits. */
|
||||||
|
uint8_t ruleId; /*!< Identifies the Rule for this Flow. */
|
||||||
|
bool enable;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class MACsecValidateFrameType : uint8_t
|
||||||
|
{
|
||||||
|
Disabled = 0, /*!< Disable validation */
|
||||||
|
Check = 1, /*!< Enable validation, do not discard invalid frames*/
|
||||||
|
Strict = 2, /*!< Enable validation and discard invalid frames */
|
||||||
|
NA = 3 /*!< No processing or accounting */
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class MACsecSecTagIcvStripType : uint8_t
|
||||||
|
{
|
||||||
|
StripBoth = 0, /*!< Strip both SecTag and ICV from packet */
|
||||||
|
StripSecTagPreserveICV = 1,
|
||||||
|
PreserveSecTagStripICV = 2, /*!< Preserve SecTag, Strip ICV */
|
||||||
|
PreserveBoth = 3 /*!< Preserve both SecTag and ICV */
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class MACsecCipherSuiteType : uint8_t
|
||||||
|
{
|
||||||
|
GcmAes128 = 0,
|
||||||
|
GcmAes256 = 1,
|
||||||
|
GcmAes128Xpn = 2,
|
||||||
|
GcmAes256Xpn = 3
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MACsecSecY
|
||||||
|
{
|
||||||
|
uint8_t index; /*!< Identifies the SecY for this Flow. */
|
||||||
|
bool controlledPortEnabled; /*!< Enable (or disable) operation of the Controlled port associated with this SecY */
|
||||||
|
MACsecValidateFrameType frameValidationType; /*!< see MACSEC_VALIDATEFRAME */
|
||||||
|
MACsecSecTagIcvStripType secTagIcvStripType; /*!< see MACSEC_STRIP_SECTAG_ICV */
|
||||||
|
MACsecCipherSuiteType cipher; /*!< Define the cipher suite to use for this SecY see MACSEC_CIPHER_SUITE */
|
||||||
|
uint8_t confidentialOffset; /*!< Define the number of bytes that are unencrypted following the SecTag. */
|
||||||
|
bool icvIncludesDaSa; /*!< When set, the outer DA/SA bytes are included in the authentication GHASH calculation */
|
||||||
|
bool replayProtect; /*!< Enables Anti-Replay protection */
|
||||||
|
uint32_t replayWindow; /*!< Unsigned value indicating the size of the anti-replay window. */
|
||||||
|
bool protectFrames; /*!< 0 = do not encrypt or authenticate this packet; 1 = always Authenticate frame and if SecTag.TCI.E = 1 encrypt the packet as well. */
|
||||||
|
uint8_t secTagOffset; /*!< Define the offset in bytes from either the start of the packet or a matching Etype depending on SecTag_Insertion_Mode. */
|
||||||
|
uint8_t secTagTci; /*!< Tag Control Information excluding the AN field which originates from the SA Policy table */
|
||||||
|
uint16_t mtu; /*!< Specifies the outgoing MTU for this SecY */
|
||||||
|
bool enable;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MACsecSc
|
||||||
|
{
|
||||||
|
uint8_t index; /*!< SC index. */
|
||||||
|
uint8_t secYIndex; /*!< SecY associated with this packet. */
|
||||||
|
uint64_t sci; /*!< The Secure Channel Identifier. */
|
||||||
|
uint8_t saIndex0; /*!< Define the 1st SA to use */
|
||||||
|
uint8_t saIndex1; /*!< Define the 2nd SA to use */
|
||||||
|
bool saIndex0InUse; /*!< Specifies whether 1st SA is in use or not. */
|
||||||
|
bool saIndex1InUse; /*!< Specifies whether 2nd SA is in use or not. */
|
||||||
|
bool enableAutoRekey; /*!< If enabled, then once the pn_threshold is reached, auto rekey will happen. */
|
||||||
|
bool isActiveSa1; /*!< If set, then sa_index1 is the currently active SA index. If cleared, the sa_index0 is the currently active SA index). */
|
||||||
|
bool enable;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MACsecSa
|
||||||
|
{
|
||||||
|
uint8_t index; /*!< SA index */
|
||||||
|
std::array<uint8_t, 32> sak; /*!< 256b SAK: Define the encryption key to be used to encrypte this packet. The lower 128 bits are used for 128-bit ciphers. */
|
||||||
|
std::array<uint8_t, 16> hashKey; /*!< 128b Hash Key: Key used for authentication. */
|
||||||
|
std::array<uint8_t, 12> salt; /*!< 96b Salt value: Salt value used in XPN ciphers. */
|
||||||
|
uint32_t ssci; /*!< 32b SSCI value: Short Secure Channel Identifier, used in XPN ciphers. */
|
||||||
|
uint8_t an; /*!< 2b SecTag Association Number (AN) */
|
||||||
|
uint64_t nextPn; /*!< 64b next_pn value: Next packet number to insert into outgoing packet on a particular SA. */
|
||||||
|
bool enable;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MACSecFlags
|
||||||
|
{
|
||||||
|
bool en; // '1' = enable; '0' = disable
|
||||||
|
};
|
||||||
|
|
||||||
|
/* MACSec Settings for 1 port/phy */
|
||||||
|
struct MACsecConfig
|
||||||
|
{
|
||||||
|
static constexpr int NumFlags = 1;
|
||||||
|
static constexpr int NumRules = 2;
|
||||||
|
static constexpr int NumMaps = 2;
|
||||||
|
static constexpr int NumSecY = 2;
|
||||||
|
static constexpr int NumSc = 2;
|
||||||
|
static constexpr int NumSa = 4;
|
||||||
|
|
||||||
|
MACSecFlags flags;
|
||||||
|
std::array<MACsecRule, NumRules> rule;
|
||||||
|
std::array<MACsecMap, NumMaps> map;
|
||||||
|
std::array<MACsecSecY, NumSecY> secy;
|
||||||
|
std::array<MACsecSc, NumSc> sc;
|
||||||
|
std::array<MACsecSa, NumSa> sa;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MACSecGlobalFlags
|
||||||
|
{
|
||||||
|
bool en; // '1' = enable; '0' = disable
|
||||||
|
bool nvm; // store macsec config in non-volatile memory
|
||||||
|
};
|
||||||
|
|
||||||
|
class MACsecMessage : public Message
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MACsecMessage(void) : Message(Message::Type::RawMessage) {}
|
||||||
|
|
||||||
|
MACSecGlobalFlags flags;
|
||||||
|
MACsecConfig rx;
|
||||||
|
MACsecConfig tx;
|
||||||
|
|
||||||
|
static std::shared_ptr<MACsecMessage> DecodeToMessage(const std::vector<uint8_t>& bytestream, const device_eventhandler_t& report);
|
||||||
|
bool EncodeFromMessage(std::vector<uint8_t>& bytestream, const device_eventhandler_t& report) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // __cplusplus
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -17,6 +17,7 @@ public:
|
||||||
Frame = 0,
|
Frame = 0,
|
||||||
|
|
||||||
CANErrorCount = 0x100,
|
CANErrorCount = 0x100,
|
||||||
|
CANError = 0x100,
|
||||||
|
|
||||||
LINHeaderOnly = 0x200,
|
LINHeaderOnly = 0x200,
|
||||||
LINBreak = 0x201,
|
LINBreak = 0x201,
|
||||||
|
|
@ -41,6 +42,8 @@ public:
|
||||||
HardwareInfo = 0x8010,
|
HardwareInfo = 0x8010,
|
||||||
TC10Status = 0x8011,
|
TC10Status = 0x8011,
|
||||||
AppError = 0x8012,
|
AppError = 0x8012,
|
||||||
|
GPTPStatus = 0x8013,
|
||||||
|
EthernetStatus = 0x8014,
|
||||||
};
|
};
|
||||||
|
|
||||||
Message(Type t) : type(t) {}
|
Message(Type t) : type(t) {}
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ namespace icsneo {
|
||||||
|
|
||||||
typedef uint16_t icscm_bitfield;
|
typedef uint16_t icscm_bitfield;
|
||||||
|
|
||||||
|
#pragma pack(push,2)
|
||||||
struct HardwareCANPacket {
|
struct HardwareCANPacket {
|
||||||
static std::shared_ptr<Message> DecodeToMessage(const std::vector<uint8_t>& bytestream);
|
static std::shared_ptr<Message> DecodeToMessage(const std::vector<uint8_t>& bytestream);
|
||||||
static bool EncodeFromMessage(const CANMessage& message, std::vector<uint8_t>& bytestream, const device_eventhandler_t& report);
|
static bool EncodeFromMessage(const CANMessage& message, std::vector<uint8_t>& bytestream, const device_eventhandler_t& report);
|
||||||
|
|
@ -50,6 +51,28 @@ struct HardwareCANPacket {
|
||||||
uint64_t IsExtended : 1;
|
uint64_t IsExtended : 1;
|
||||||
} timestamp;
|
} timestamp;
|
||||||
};
|
};
|
||||||
|
struct HardwareCANErrorPacket {
|
||||||
|
uint8_t error_code;
|
||||||
|
uint8_t brs_data_error_code;
|
||||||
|
|
||||||
|
uint16_t reserved;
|
||||||
|
|
||||||
|
uint16_t DLC : 4;
|
||||||
|
uint16_t : 4;
|
||||||
|
uint16_t ERROR_INDICATOR : 1;
|
||||||
|
uint16_t : 7;
|
||||||
|
|
||||||
|
uint8_t flags;
|
||||||
|
uint8_t REC;
|
||||||
|
uint8_t TEC;
|
||||||
|
|
||||||
|
static bool GetErrorWarn(uint8_t flags) { return flags & 0b0000'0001; }
|
||||||
|
static bool GetErrorPassive(uint8_t flags) { return flags & 0b0000'1000; }
|
||||||
|
static bool GetBusOff(uint8_t flags) { return flags & 0b0010'0000; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,8 @@
|
||||||
|
|
||||||
namespace icsneo {
|
namespace icsneo {
|
||||||
|
|
||||||
|
#pragma pack(push, 2)
|
||||||
|
|
||||||
typedef uint16_t icscm_bitfield;
|
typedef uint16_t icscm_bitfield;
|
||||||
|
|
||||||
struct HardwareEthernetPacket {
|
struct HardwareEthernetPacket {
|
||||||
|
|
@ -42,6 +44,8 @@ struct HardwareEthernetPacket {
|
||||||
uint16_t Length;
|
uint16_t Length;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // __cplusplus
|
#endif // __cplusplus
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@
|
||||||
#include "icsneo/communication/message/extendeddatamessage.h"
|
#include "icsneo/communication/message/extendeddatamessage.h"
|
||||||
#include "icsneo/communication/message/livedatamessage.h"
|
#include "icsneo/communication/message/livedatamessage.h"
|
||||||
#include "icsneo/communication/message/tc10statusmessage.h"
|
#include "icsneo/communication/message/tc10statusmessage.h"
|
||||||
|
#include "icsneo/communication/message/macsecmessage.h"
|
||||||
#include "icsneo/communication/packet/genericbinarystatuspacket.h"
|
#include "icsneo/communication/packet/genericbinarystatuspacket.h"
|
||||||
#include "icsneo/communication/packet/livedatapacket.h"
|
#include "icsneo/communication/packet/livedatapacket.h"
|
||||||
#include "icsneo/device/extensions/flexray/controller.h"
|
#include "icsneo/device/extensions/flexray/controller.h"
|
||||||
|
|
@ -50,6 +51,7 @@
|
||||||
#include "icsneo/disk/vsa/vsa.h"
|
#include "icsneo/disk/vsa/vsa.h"
|
||||||
#include "icsneo/disk/vsa/vsaparser.h"
|
#include "icsneo/disk/vsa/vsaparser.h"
|
||||||
#include "icsneo/communication/message/versionmessage.h"
|
#include "icsneo/communication/message/versionmessage.h"
|
||||||
|
#include "icsneo/communication/message/gptpstatusmessage.h"
|
||||||
|
|
||||||
|
|
||||||
#define ICSNEO_FINDABLE_DEVICE_BASE(className, type) \
|
#define ICSNEO_FINDABLE_DEVICE_BASE(className, type) \
|
||||||
|
|
@ -623,6 +625,7 @@ public:
|
||||||
|
|
||||||
std::optional<size_t> getGenericBinarySize(uint16_t binaryIndex);
|
std::optional<size_t> getGenericBinarySize(uint16_t binaryIndex);
|
||||||
bool readBinaryFile(std::ostream& stream, uint16_t binaryIndex);
|
bool readBinaryFile(std::ostream& stream, uint16_t binaryIndex);
|
||||||
|
bool writeBinaryFile(const std::vector<uint8_t>& in, uint16_t binaryIndex);
|
||||||
bool subscribeLiveData(std::shared_ptr<LiveDataCommandMessage> message);
|
bool subscribeLiveData(std::shared_ptr<LiveDataCommandMessage> message);
|
||||||
bool unsubscribeLiveData(const LiveDataHandle& handle);
|
bool unsubscribeLiveData(const LiveDataHandle& handle);
|
||||||
bool clearAllLiveData();
|
bool clearAllLiveData();
|
||||||
|
|
@ -728,11 +731,17 @@ public:
|
||||||
|
|
||||||
virtual bool supportsTC10() const { return false; }
|
virtual bool supportsTC10() const { return false; }
|
||||||
|
|
||||||
|
virtual bool supportsGPTP() const { return false; }
|
||||||
|
|
||||||
bool requestTC10Wake(Network::NetID network);
|
bool requestTC10Wake(Network::NetID network);
|
||||||
|
|
||||||
bool requestTC10Sleep(Network::NetID network);
|
bool requestTC10Sleep(Network::NetID network);
|
||||||
|
|
||||||
std::optional<TC10StatusMessage> getTC10Status(Network::NetID network);
|
std::optional<TC10StatusMessage> getTC10Status(Network::NetID network);
|
||||||
|
std::optional<GPTPStatus> getGPTPStatus(std::chrono::milliseconds timeout = std::chrono::milliseconds(100));
|
||||||
|
|
||||||
|
/* MACsec support */
|
||||||
|
virtual bool writeMACsecConfig(const MACsecMessage& message, uint16_t binaryIndex);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool online = false;
|
bool online = false;
|
||||||
|
|
|
||||||
|
|
@ -455,9 +455,10 @@ typedef struct RAD_GPTP_SETTINGS_t
|
||||||
uint8_t clockaccuracy;
|
uint8_t clockaccuracy;
|
||||||
uint8_t priority2;
|
uint8_t priority2;
|
||||||
uint16_t offset_scaled_log_variance;
|
uint16_t offset_scaled_log_variance;
|
||||||
uint8_t gPTPportRole[RAD_GPTP_NUM_PORTS];
|
uint8_t gptpPortRole;
|
||||||
uint8_t portEnable[RAD_GPTP_NUM_PORTS];
|
uint8_t gptpEnabledPort;
|
||||||
uint8_t rsvd[16];
|
uint8_t enableClockSyntonization;
|
||||||
|
uint8_t rsvd[15];
|
||||||
} RAD_GPTP_SETTINGS;//36 Bytes with RAD_GPTP_NUM_PORTS = 1
|
} RAD_GPTP_SETTINGS;//36 Bytes with RAD_GPTP_NUM_PORTS = 1
|
||||||
#define RAD_GPTP_SETTINGS_SIZE 36
|
#define RAD_GPTP_SETTINGS_SIZE 36
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,10 @@ protected:
|
||||||
std::optional<MemoryAddress> getCoreminiStartAddressSD() const override {
|
std::optional<MemoryAddress> getCoreminiStartAddressSD() const override {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool supportsComponentVersions() const override { return true; }
|
||||||
|
bool supportsGPTP() const override { return true; }
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -79,6 +79,8 @@ protected:
|
||||||
|
|
||||||
bool supportsLiveData() const override { return true; }
|
bool supportsLiveData() const override { return true; }
|
||||||
|
|
||||||
|
bool supportsGPTP() const override { return true; }
|
||||||
|
|
||||||
std::optional<MemoryAddress> getCoreminiStartAddressFlash() const override {
|
std::optional<MemoryAddress> getCoreminiStartAddressFlash() const override {
|
||||||
return 33*1024*1024;
|
return 33*1024*1024;
|
||||||
}
|
}
|
||||||
|
|
@ -90,6 +92,7 @@ protected:
|
||||||
bool supportsEraseMemory() const override {
|
bool supportsEraseMemory() const override {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
bool supportsComponentVersions() const override { return true; }
|
bool supportsComponentVersions() const override { return true; }
|
||||||
|
bool supportsGPTP() const override { return true; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
NeoVIRED2(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) {
|
NeoVIRED2(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) {
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t getEthernetActivationLineCount() const override { return 1; }
|
size_t getEthernetActivationLineCount() const override { return 1; }
|
||||||
|
bool supportsGPTP() const override { return true; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
RADA2B(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) {
|
RADA2B(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) {
|
||||||
|
|
@ -77,6 +78,7 @@ protected:
|
||||||
std::optional<MemoryAddress> getCoreminiStartAddressSD() const override {
|
std::optional<MemoryAddress> getCoreminiStartAddressSD() const override {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
bool getEthPhyRegControlSupported() const override { return true; }
|
bool getEthPhyRegControlSupported() const override { return true; }
|
||||||
|
bool supportsGPTP() const override { return true; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
using Device::Device;
|
using Device::Device;
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,7 @@ public:
|
||||||
bool getEthPhyRegControlSupported() const override { return true; }
|
bool getEthPhyRegControlSupported() const override { return true; }
|
||||||
|
|
||||||
bool supportsTC10() const override { return true; }
|
bool supportsTC10() const override { return true; }
|
||||||
|
bool supportsGPTP() const override { return true; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
RADComet3(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) {
|
RADComet3(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) {
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t getEthernetActivationLineCount() const override { return 1; }
|
size_t getEthernetActivationLineCount() const override { return 1; }
|
||||||
|
bool supportsGPTP() const override { return true; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
RADGalaxy(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) {
|
RADGalaxy(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) {
|
||||||
|
|
|
||||||
|
|
@ -65,6 +65,7 @@ public:
|
||||||
size_t getEthernetActivationLineCount() const override { return 1; }
|
size_t getEthernetActivationLineCount() const override { return 1; }
|
||||||
|
|
||||||
bool supportsTC10() const override { return true; }
|
bool supportsTC10() const override { return true; }
|
||||||
|
bool supportsGPTP() const override { return true; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
RADGalaxy2(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) {
|
RADGalaxy2(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) {
|
||||||
|
|
|
||||||
|
|
@ -22,10 +22,11 @@ public:
|
||||||
|
|
||||||
bool getEthPhyRegControlSupported() const override { return true; }
|
bool getEthPhyRegControlSupported() const override { return true; }
|
||||||
bool supportsTC10() const override { return true; }
|
bool supportsTC10() const override { return true; }
|
||||||
|
bool supportsGPTP() const override { return true; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
RADGigastar(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) {
|
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 {
|
void setupPacketizer(Packetizer& packetizer) override {
|
||||||
|
|
|
||||||
|
|
@ -76,6 +76,7 @@ namespace icsneo
|
||||||
bool getEthPhyRegControlSupported() const override { return true; }
|
bool getEthPhyRegControlSupported() const override { return true; }
|
||||||
|
|
||||||
bool supportsTC10() const override { return true; }
|
bool supportsTC10() const override { return true; }
|
||||||
|
bool supportsGPTP() const override { return true; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
RADGigastar2(neodevice_t neodevice, const driver_factory_t &makeDriver) : Device(neodevice)
|
RADGigastar2(neodevice_t neodevice, const driver_factory_t &makeDriver) : Device(neodevice)
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ public:
|
||||||
ICSNEO_FINDABLE_DEVICE(RADMars, DeviceType::RADMars, "GL");
|
ICSNEO_FINDABLE_DEVICE(RADMars, DeviceType::RADMars, "GL");
|
||||||
|
|
||||||
size_t getEthernetActivationLineCount() const override { return 1; }
|
size_t getEthernetActivationLineCount() const override { return 1; }
|
||||||
|
bool supportsGPTP() const override { return true; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
RADMars(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) {
|
RADMars(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) {
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
#include "icsneo/communication/message/ethernetmessage.h"
|
#include "icsneo/communication/message/ethernetmessage.h"
|
||||||
#include "icsneo/communication/message/flexray/flexraymessage.h"
|
#include "icsneo/communication/message/flexray/flexraymessage.h"
|
||||||
#include "icsneo/communication/message/iso9141message.h"
|
#include "icsneo/communication/message/iso9141message.h"
|
||||||
#include "icsneo/communication/message/canerrorcountmessage.h"
|
#include "icsneo/communication/message/canerrormessage.h"
|
||||||
#include "icsneo/communication/message/ethphymessage.h"
|
#include "icsneo/communication/message/ethphymessage.h"
|
||||||
#include "icsneo/communication/message/i2cmessage.h"
|
#include "icsneo/communication/message/i2cmessage.h"
|
||||||
#include "icsneo/communication/message/a2bmessage.h"
|
#include "icsneo/communication/message/a2bmessage.h"
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
#ifndef __WINDOWS_STRINGS_H__
|
||||||
|
#define __WINDOWS_STRINGS_H__
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace icsneo {
|
||||||
|
|
||||||
|
// Helper function to convert UTF-16 to UTF-8 strings (wide to standard)
|
||||||
|
std::string convertWideString(const std::wstring& value);
|
||||||
|
|
||||||
|
// Helper function to convert UTF-8 to UTF-16 strings (standard to wide)
|
||||||
|
std::wstring convertStringToWide(const std::string& value);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // __cplusplus
|
||||||
|
|
||||||
|
#endif // __WINDOWS_STRINGS_H__
|
||||||
|
|
@ -95,6 +95,8 @@ bool FTD3XX::close() {
|
||||||
addEvent(ret, APIEvent::Severity::EventWarning);
|
addEvent(ret, APIEvent::Severity::EventWarning);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handle.reset();
|
||||||
|
|
||||||
setIsClosing(false);
|
setIsClosing(false);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -88,6 +88,21 @@ void TCP::Socket::poll(uint16_t event, uint32_t msTimeout) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void TCP::Find(std::vector<FoundDevice>& found) {
|
void TCP::Find(std::vector<FoundDevice>& found) {
|
||||||
|
static const auto tcpDisabled = []() -> bool {
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable : 4996)
|
||||||
|
#endif
|
||||||
|
const auto disabled = std::getenv("LIBICSNEO_DISABLE_TCP");
|
||||||
|
return disabled ? std::stoi(disabled) : false;
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
if(tcpDisabled()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
static const auto MDNS_PORT = htons((unsigned short)5353);
|
static const auto MDNS_PORT = htons((unsigned short)5353);
|
||||||
static const auto MDNS_IP = htonl((((uint32_t)224U) << 24U) | ((uint32_t)251U));
|
static const auto MDNS_IP = htonl((((uint32_t)224U) << 24U) | ((uint32_t)251U));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,9 +34,12 @@ PCAPDLL::PCAPDLL()
|
||||||
int len = GetSystemDirectory(dllPath, 480); // be safe
|
int len = GetSystemDirectory(dllPath, 480); // be safe
|
||||||
if (len) {
|
if (len) {
|
||||||
_tcscat_s(dllPath, 512, TEXT("\\Npcap"));
|
_tcscat_s(dllPath, 512, TEXT("\\Npcap"));
|
||||||
cookie = AddDllDirectory(dllPath);
|
WCHAR dllPath_w[512] = { 0 };
|
||||||
|
if (mbstowcs(dllPath_w, dllPath, 512)) {
|
||||||
|
cookie = AddDllDirectory(dllPath_w);
|
||||||
}
|
}
|
||||||
dll = LoadLibraryEx(TEXT("wpcap.dll"), nullptr, LOAD_LIBRARY_SEARCH_USER_DIRS);
|
}
|
||||||
|
dll = LoadLibraryEx(TEXT("wpcap.dll"), nullptr, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS);
|
||||||
|
|
||||||
if (cookie)
|
if (cookie)
|
||||||
RemoveDllDirectory(cookie);
|
RemoveDllDirectory(cookie);
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
#include <winsock2.h>
|
#include <winsock2.h>
|
||||||
|
|
||||||
#include "icsneo/platform/windows/pcap.h"
|
#include "icsneo/platform/windows/pcap.h"
|
||||||
|
#include "icsneo/platform/windows/strings.h"
|
||||||
#include "icsneo/communication/network.h"
|
#include "icsneo/communication/network.h"
|
||||||
#include "icsneo/communication/communication.h"
|
#include "icsneo/communication/communication.h"
|
||||||
#include "icsneo/communication/ethernetpacketizer.h"
|
#include "icsneo/communication/ethernetpacketizer.h"
|
||||||
|
|
@ -11,14 +12,12 @@
|
||||||
#include <pcap.h>
|
#include <pcap.h>
|
||||||
#include <iphlpapi.h>
|
#include <iphlpapi.h>
|
||||||
#pragma comment(lib, "IPHLPAPI.lib")
|
#pragma comment(lib, "IPHLPAPI.lib")
|
||||||
#include <codecvt>
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <locale>
|
#include <locale>
|
||||||
|
|
||||||
using namespace icsneo;
|
using namespace icsneo;
|
||||||
|
|
||||||
static std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
|
|
||||||
|
|
||||||
std::vector<PCAP::NetworkInterface> PCAP::knownInterfaces;
|
std::vector<PCAP::NetworkInterface> PCAP::knownInterfaces;
|
||||||
|
|
||||||
|
|
@ -80,8 +79,8 @@ void PCAP::Find(std::vector<FoundDevice>& found) {
|
||||||
|
|
||||||
memcpy(iface.macAddress, aa->PhysicalAddress, sizeof(iface.macAddress));
|
memcpy(iface.macAddress, aa->PhysicalAddress, sizeof(iface.macAddress));
|
||||||
iface.nameFromWin32API = aa->AdapterName;
|
iface.nameFromWin32API = aa->AdapterName;
|
||||||
iface.descriptionFromWin32API = converter.to_bytes(aa->Description);
|
iface.descriptionFromWin32API = convertWideString(aa->Description);
|
||||||
iface.friendlyNameFromWin32API = converter.to_bytes(aa->FriendlyName);
|
iface.friendlyNameFromWin32API = convertWideString(aa->FriendlyName);
|
||||||
if(iface.descriptionFromWin32API.find("LAN9512/LAN9514") != std::string::npos) {
|
if(iface.descriptionFromWin32API.find("LAN9512/LAN9514") != std::string::npos) {
|
||||||
// This is an Ethernet EVB device
|
// This is an Ethernet EVB device
|
||||||
iface.fullName = "Intrepid Ethernet EVB ( " + iface.friendlyNameFromWin32API + " : " + iface.descriptionFromWin32API + " )";
|
iface.fullName = "Intrepid Ethernet EVB ( " + iface.friendlyNameFromWin32API + " : " + iface.descriptionFromWin32API + " )";
|
||||||
|
|
@ -187,7 +186,7 @@ bool PCAP::IsHandleValid(neodevice_handle_t handle) {
|
||||||
return (netifIndex < knownInterfaces.size());
|
return (netifIndex < knownInterfaces.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
PCAP::PCAP(const device_eventhandler_t& err, neodevice_t& forDevice) : Driver(err), device(forDevice), pcap(PCAPDLL::getInstance()), ethPacketizer(err) {
|
PCAP::PCAP(const device_eventhandler_t& eventHandler, neodevice_t& forDevice) : Driver(eventHandler), pcap(PCAPDLL::getInstance()), device(forDevice), ethPacketizer(eventHandler) {
|
||||||
if(IsHandleValid(device.handle)) {
|
if(IsHandleValid(device.handle)) {
|
||||||
iface = knownInterfaces[(device.handle >> 24) & 0xFF];
|
iface = knownInterfaces[(device.handle >> 24) & 0xFF];
|
||||||
iface.fp = nullptr; // We're going to open our own connection to the interface. This should already be nullptr but just in case.
|
iface.fp = nullptr; // We're going to open our own connection to the interface. This should already be nullptr but just in case.
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
#include "icsneo/platform/windows/registry.h"
|
#include "icsneo/platform/windows/registry.h"
|
||||||
|
#include "icsneo/platform/windows/strings.h"
|
||||||
#include "icsneo/platform/windows.h"
|
#include "icsneo/platform/windows.h"
|
||||||
#include <codecvt>
|
#include <codecvt>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
@ -6,8 +7,6 @@
|
||||||
|
|
||||||
using namespace icsneo;
|
using namespace icsneo;
|
||||||
|
|
||||||
static std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
|
|
||||||
|
|
||||||
class Key {
|
class Key {
|
||||||
public:
|
public:
|
||||||
Key(std::wstring path, bool readwrite = false);
|
Key(std::wstring path, bool readwrite = false);
|
||||||
|
|
@ -95,8 +94,8 @@ bool Registry::Get(std::wstring path, std::wstring key, std::wstring& value) {
|
||||||
|
|
||||||
bool Registry::Get(std::string path, std::string key, std::string& value) {
|
bool Registry::Get(std::string path, std::string key, std::string& value) {
|
||||||
std::wstring wvalue;
|
std::wstring wvalue;
|
||||||
bool ret = Get(converter.from_bytes(path), converter.from_bytes(key), wvalue);
|
bool ret = Get(convertStringToWide(path), convertStringToWide(key), wvalue);
|
||||||
value = converter.to_bytes(wvalue);
|
value = convertWideString(wvalue);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -116,5 +115,5 @@ bool Registry::Get(std::wstring path, std::wstring key, uint32_t& value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Registry::Get(std::string path, std::string key, uint32_t& value) {
|
bool Registry::Get(std::string path, std::string key, uint32_t& value) {
|
||||||
return Get(converter.from_bytes(path), converter.from_bytes(key), value);
|
return Get(convertStringToWide(path), convertStringToWide(key), value);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
#include <string>
|
||||||
|
#include <Windows.h>
|
||||||
|
|
||||||
|
#include <icsneo/platform/windows/strings.h>
|
||||||
|
|
||||||
|
// Helper function to convert UTF-16 to UTF-8 strings (wide to standard)
|
||||||
|
std::string icsneo::convertWideString(const std::wstring& value) {
|
||||||
|
// Get the width of the string (character count)
|
||||||
|
int width = WideCharToMultiByte(CP_UTF8, 0, (LPWSTR)value.c_str(), -1, 0, 0, NULL, NULL);
|
||||||
|
// Create the new string
|
||||||
|
std::string new_string(width+1, '\0');
|
||||||
|
// fill the new string with the converted characters
|
||||||
|
WideCharToMultiByte(CP_UTF8, 0, (LPWSTR)value.c_str(), -1, new_string.data(), width, NULL, NULL);
|
||||||
|
return new_string;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Helper function to convert UTF-8 to UTF-16 strings (standard to wide)
|
||||||
|
std::wstring icsneo::convertStringToWide(const std::string& value) {
|
||||||
|
// Get the width of the string (character count)
|
||||||
|
int width = MultiByteToWideChar(CP_UTF8, 0, value.c_str(), -1, NULL, 0);
|
||||||
|
// Create the new string
|
||||||
|
std::wstring new_string(width+1, '\0');
|
||||||
|
// fill the new string with the converted characters
|
||||||
|
MultiByteToWideChar(CP_UTF8, 0, value.c_str(), -1, (LPWSTR)new_string.data(), width);
|
||||||
|
return new_string;
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
#include "icsneo/platform/windows/ftdi.h"
|
#include "icsneo/platform/windows/ftdi.h"
|
||||||
|
#include "icsneo/platform/windows/strings.h"
|
||||||
#include "icsneo/platform/ftdi.h"
|
#include "icsneo/platform/ftdi.h"
|
||||||
#include "icsneo/platform/registry.h"
|
#include "icsneo/platform/registry.h"
|
||||||
#include "icsneo/device/founddevice.h"
|
#include "icsneo/device/founddevice.h"
|
||||||
|
|
@ -15,7 +16,6 @@
|
||||||
|
|
||||||
using namespace icsneo;
|
using namespace icsneo;
|
||||||
|
|
||||||
static std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
|
|
||||||
static const std::wstring DRIVER_SERVICES_REG_KEY = L"SYSTEM\\CurrentControlSet\\services\\";
|
static const std::wstring DRIVER_SERVICES_REG_KEY = L"SYSTEM\\CurrentControlSet\\services\\";
|
||||||
static const std::wstring ALL_ENUM_REG_KEY = L"SYSTEM\\CurrentControlSet\\Enum\\";
|
static const std::wstring ALL_ENUM_REG_KEY = L"SYSTEM\\CurrentControlSet\\Enum\\";
|
||||||
static constexpr unsigned int RETRY_TIMES = 5;
|
static constexpr unsigned int RETRY_TIMES = 5;
|
||||||
|
|
@ -95,7 +95,7 @@ void VCP::Find(std::vector<FoundDevice>& found, std::vector<std::wstring> driver
|
||||||
if(!device.productId)
|
if(!device.productId)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
std::string serial = converter.to_bytes(oss.str());
|
std::string serial = convertWideString(oss.str());
|
||||||
// The serial number should not have a path slash in it. If it does, that means we don't have the real serial.
|
// The serial number should not have a path slash in it. If it does, that means we don't have the real serial.
|
||||||
if(serial.find_first_of('\\') != std::string::npos) {
|
if(serial.find_first_of('\\') != std::string::npos) {
|
||||||
// The serial number was not in the first serenum key where we expected it.
|
// The serial number was not in the first serenum key where we expected it.
|
||||||
|
|
@ -142,12 +142,12 @@ void VCP::Find(std::vector<FoundDevice>& found, std::vector<std::wstring> driver
|
||||||
// This is a device with characters in the serial number
|
// This is a device with characters in the serial number
|
||||||
if(correctSerial.size() != 6)
|
if(correctSerial.size() != 6)
|
||||||
continue;
|
continue;
|
||||||
serial = converter.to_bytes(correctSerial);
|
serial = convertWideString(correctSerial);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
std::wstringstream soss;
|
std::wstringstream soss;
|
||||||
soss << sn;
|
soss << sn;
|
||||||
serial = converter.to_bytes(soss.str());
|
serial = convertWideString(soss.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
if(serial.find_first_of('\\') != std::string::npos)
|
if(serial.find_first_of('\\') != std::string::npos)
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
[build-system]
|
[build-system]
|
||||||
requires = ["scikit-build-core", "pybind11", "setuptools>=64", "setuptools-scm>=8"]
|
requires = ["scikit-build-core", "pybind11", "setuptools>=64", "setuptools-scm>=8", "mypy"]
|
||||||
build-backend = "scikit_build_core.build"
|
build-backend = "scikit_build_core.build"
|
||||||
|
|
||||||
[project]
|
[project]
|
||||||
|
|
@ -47,3 +47,7 @@ local_scheme = "no-local-version"
|
||||||
[tool.scikit-build.cmake.define]
|
[tool.scikit-build.cmake.define]
|
||||||
LIBICSNEO_ENABLE_BINDINGS_PYTHON = true
|
LIBICSNEO_ENABLE_BINDINGS_PYTHON = true
|
||||||
LIBICSNEO_ENABLE_TCP = true
|
LIBICSNEO_ENABLE_TCP = true
|
||||||
|
CMAKE_MSVC_RUNTIME_LIBRARY = "MultiThreaded"
|
||||||
|
|
||||||
|
[tool.cibuildwheel]
|
||||||
|
skip = "pp*"
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
#include <icsneo/platform/windows/strings.h>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
TEST(WindowsUtilTest, testConvertWideString) {
|
||||||
|
#ifdef WIN32
|
||||||
|
std::wstring wideString(L"Hello World!");
|
||||||
|
auto normalString = icsneo::convertWideString(wideString);
|
||||||
|
|
||||||
|
ASSERT_STREQ(normalString.c_str(), "Hello World!");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(WindowsUtilTest, testConvertStringToWide) {
|
||||||
|
#ifdef WIN32
|
||||||
|
std::string normalString("Hello World!");
|
||||||
|
auto wideString = icsneo::convertStringToWide(normalString);
|
||||||
|
|
||||||
|
ASSERT_STREQ(wideString.c_str(), L"Hello World!");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
@ -55,7 +55,7 @@
|
||||||
#include <io.h>
|
#include <io.h>
|
||||||
|
|
||||||
#ifndef __MINGW32__
|
#ifndef __MINGW32__
|
||||||
#include "IP6_misc.h"
|
#include "ip6_misc.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define caddr_t char*
|
#define caddr_t char*
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue