78 Commits
Author SHA1 Message Date
Max BrombachandKyle Schwarz 1a7bc4df47 Device: RADJupiter: Add bootloader pipeline 2026-02-12 17:05:39 -05:00
Max BrombachandKyle Schwarz 20a2474508 Device: Settings: Add missing bit-packed variables to CAN_SETTINGS 2026-02-12 16:25:57 -05:00
Thomas StoddardandKyle Schwarz d18ca9e6eb Device: RAD-Galaxy: Add support for Analog Output 2026-02-11 18:43:30 -05:00
Max BrombachandKyle Schwarz 6cda765fe0 Device: FIRE2: Skip flashing Core chip when chip variant is unknown 2026-02-10 21:20:47 -05:00
Jonathan SchwartzandKyle Schwarz 730aaf5fed Device: FIRE3: Update disk counts 2026-02-06 14:32:31 -05:00
Kyle Schwarz 1f10adb760 ThirdParty: Update icspb & libredxx 2026-01-30 17:12:09 -05:00
Thomas StoddardandKyle Schwarz 6a32823a0f Device: FlexRay: Add additional configuration options for Controller and Cluster 2026-01-30 13:06:39 -05:00
Thomas StoddardandKyle Schwarz 5f16adc103 Device: RADComet3: Add Ethernet settings 2026-01-28 16:00:39 -05:00
Jonathan SchwartzandKyle Schwarz f6926cbb22 Device: Unlock network mutex when going offline 2026-01-27 15:22:12 -05:00
Thomas StoddardandKyle Schwarz 4c7b8e107a Device: RADComet: Add T1S settings 2026-01-23 13:03:39 -05:00
Jonathan SchwartzandKyle Schwarz 0e55101a16 Device: goOnline: Refactor network locking
Only lock known networks.
2026-01-22 16:46:51 -05:00
Max BrombachandKyle Schwarz 68ebb6dae4 Device: Add EnterApplicationPhases step 2026-01-20 14:25:29 -05:00
Jonathan SchwartzandKyle Schwarz 8cb62c2cae Device: Carry bootloader version for potential compatibility checks 2026-01-12 17:45:10 -05:00
Kyle Schwarz d74051f57e Driver: Servd: Refactor to TCP 2026-01-12 13:03:55 -05:00
Thomas Stoddard 530a99d264 Add T1S PLCA and related settings support for Fire3T1S, RadComet3, RadGigaStar2, and RadMoonT1S devices 2026-01-09 18:16:10 +00:00
Thomas StoddardandKyle Schwarz 5ee450353b Bindings: Python: Add T1S members 2026-01-07 23:32:20 -05:00
Thomas StoddardandKyle Schwarz 516bca682c EthernetMessage: Add T1S symbol support 2026-01-07 16:34:34 -05:00
Jonathan SchwartzandKyle Schwarz 3f5150bef3 FirmIO: Fix instability and memory leak issues 2026-01-07 13:35:23 -05:00
Thomas StoddardandKyle Schwarz 2a2d55f20d Bindings: Python : Add baudrate and LIN mode methods 2026-01-07 10:51:25 -05:00
Thomas StoddardandKyle Schwarz 977677e3af Bindings: Add LiveData and LiveDataMessage support in Python bindings 2026-01-05 10:40:14 -05:00
Kyle Schwarz 000036f745 Driver: DXX: Update
Fixes D2XX HANDLE leak.
2025-12-19 22:30:14 -05:00
Kyle Schwarz be6a15c017 Device: Galaxy2: Update supported networks 2025-12-18 12:22:12 -05:00
Nicholas ZamoraandKyle Schwarz 5288385495 Driver: DXX: Update libredxx for FT260 support 2025-12-16 11:05:11 -05:00
Max Brombach d6d9fc16ef Device: Update chips for ValueCAN4_2EL bootloader 2025-12-10 19:47:23 +00:00
Kyle Schwarz dbab92b25c Bindings: Python: Migrate to smart_holder 2025-12-09 14:24:40 -05:00
Max Brombach 579160f6d4 Device: Fix Epsilon-XL bootloader pipeline and chip info 2025-12-08 21:16:14 +00:00
Emily Brooks 737d5ceb3b TransmitMessage: Mark timestamp as extended when using CAN FD 2025-12-05 13:53:26 -05:00
Emily Brooks 95521a5548 TransmitMessage: Add TX support for neoVI network 2025-12-05 10:53:53 -05:00
Emily BrooksandKyle Schwarz 16cd476c01 Network: neoVI: Add TX support 2025-12-03 14:43:35 -05:00
Thomas StoddardandKyle Schwarz d328d314b6 Bindings: Python: Update pybind11
Updates to 3.0.1 and switches to smart_holder & native_enum.
2025-11-24 11:56:09 -05:00
Bryant JonesandKyle Schwarz 7b5b94d980 Docs: Python: Add SPI example 2025-11-20 17:08:30 -05:00
Kyle Schwarz fedb4b88f3 Build: Update icspb 2025-11-10 11:29:42 -05:00
Kyle Schwarz 5cac3a4600 Examples: Remove commented example 2025-11-05 12:01:58 -05:00
Yasser YassineandKyle Schwarz 9ff4bf7d0d MACsec: Refactor API 2025-11-05 12:00:07 -05:00
Kyle Schwarz 30c009fe8f Device: Refactor online keep alive 2025-11-04 16:24:49 -05:00
Max BrombachandKyle Schwarz 51e4fdc6d9 Device: Update tree structs and add size checks to non-deprecated devices 2025-11-04 14:29:37 -05:00
Yasser YassineandKyle Schwarz 39b54d8c4e Device: Fix bootloader phases 2025-11-04 12:37:19 -05:00
Kyle Schwarz 615b7d8d56 Bindings: Python: Document 3.14 support 2025-11-04 11:51:55 -05:00
Kyle Schwarz e3f4bbdc73 Device: sendEthPhyMsg(): Drop online requirement 2025-11-04 11:06:51 -05:00
Nicholas ZamoraandKyle Schwarz 563c444def Device: Add RAD-Gemini 2025-11-03 09:37:50 -05:00
Kyle Schwarz 3f3300d677 Communication: EthernetStatusMessage: Handle BASE-T invalid case 2025-10-31 12:31:03 -04:00
Max BrombachandKyle Schwarz b9e3542bcf Device: Use variant Core chip and fix ZChip flash for FIRE2 2025-10-31 12:02:02 -04:00
Kyle Schwarz 7f192a0cea Network: Use Type::AutomotiveEthernet 2025-10-30 23:40:30 -04:00
Kyle Schwarz 3b60bfc986 CI: Add Fedora 43 & drop 41 2025-10-30 21:21:07 -04:00
Kyle Schwarz d51f88d023 Communication: EthernetStatusMessage: Add BASE-T support 2025-10-30 21:13:20 -04:00
Kyle Schwarz f3cb41d60b Communication: Network: Add Type::AutomotiveEthernet
Also condense switch statements
2025-10-30 21:11:23 -04:00
Yasser YassineandKyle Schwarz 1b00c6a05b Gigastar(2): Fix bootloaders steps 2025-10-30 14:37:12 -04:00
Kyle Schwarz ebf9409c18 Device: Guard mutex usage 2025-10-30 11:18:12 -04:00
Kyle Schwarz 83ab65b062 Device: Fix NeoVI message guard 2025-10-29 15:37:58 -04:00
Kyle Schwarz 7f1668a55b Device: Move network mutex to goOnline 2025-10-29 15:24:03 -04:00
Max Brombach 10ffd756a1 Device: Remove erroneous API error in VSA buffer overlap check 2025-10-29 12:56:46 -04:00
Jonathan SchwartzandKyle Schwarz c2f1022858 Device: Add network mutex support 2025-10-24 12:12:36 -04:00
Kyle Schwarz bf311ebe30 Communication: Add NeoVI timestamps 2025-10-21 15:18:26 -04:00
Max BrombachandKyle Schwarz 5cdaeb1edc Communication: Remove CoreMiniExtendedMsgHdr from HardwareLINPacket struct 2025-10-16 13:31:20 -04:00
Kyle Schwarz deabc2cff4 Linux: Update udev rules
Always unbind ftdi_sio for ICS devices
2025-10-13 09:28:04 -04:00
Yasser YassineandKyle Schwarz b48160286b Device: Add reconnect() 2025-10-11 16:33:22 -04:00
Kyle Schwarz 5d672d48d4 Bindings: Python: Add get_chip_versions 2025-10-09 22:51:18 -04:00
Kyle Schwarz 495632ddb7 Driver: DXX: Add PLASMA 2025-10-09 21:56:48 -04:00
Kyle Schwarz 3668b86f37 Linux: Update udev rules
libredxx doesn't use ftdi_sio
2025-10-09 21:54:57 -04:00
Yasser YassineandKyle Schwarz 0bd733bc5d Device: Add bootloader information & getChipVersions() 2025-10-09 21:21:45 -04:00
Emily BrooksandKyle Schwarz 99a2ca4f0d Device: WiVI: Add VIN support 2025-10-08 15:49:03 -04:00
Kyle Schwarz ec350b522a DeviceSettings: Remove checksum validation 2025-10-06 15:36:55 -04:00
Thomas StoddardandKyle Schwarz 895cd0792c Communication: I2C: Fix invalid packet logic 2025-10-02 10:12:15 -04:00
Max BrombachandKyle Schwarz a5ec9a2d20 VSA: Fix incorrect bytesRead value for end of overlapped buffer 2025-09-30 14:03:21 -04:00
Max BrombachandKyle Schwarz b9d3dde8d5 VSA: Remove packet truncation mechanism 2025-09-30 11:41:40 -04:00
Kyle Schwarz 11643e2281 Bindings: Python: Add EthPhyMessage
Also fixes PhyMessages for RADEpsilon(XL)
2025-09-29 17:17:26 -04:00
Max BrombachandKyle Schwarz f22d666f94 VSA: Discard timestamp top bit 2025-09-24 14:13:29 -04:00
Bryant JonesandKyle Schwarz 58b22da09b Device: Add neoVI FIRE3 T1S/LIN 2025-09-18 17:18:27 -04:00
Yasser YassineandKyle Schwarz 88d32128c9 Communication: Add SPI support 2025-09-17 13:30:12 -04:00
Kyle Schwarz 6d82289864 Driver: DXX: Update libredxx 2025-09-16 11:42:13 -04:00
Kyle Schwarz 674e905340 Driver: CDCACM: Add missing Darwin frameworks 2025-09-15 15:57:16 -04:00
Kyle Schwarz 8b7e2556a0 Driver: DXX: Fix ION, FIRE, ValueCAN3, & VividCAN 2025-09-10 10:11:08 -04:00
Max BrombachandKyle Schwarz fbdab1e998 Communication: Fix MultiChannelCommunication race 2025-09-09 15:52:54 -04:00
Max Brombach f53bc2e920 Fix FlexRay extension bugs and implement FlexRay example 2025-09-04 14:27:32 +00:00
Bryant JonesandKyle Schwarz a9e1f24f67 Device: Comet: Fix networks 2025-09-02 10:26:50 -04:00
Kyle Schwarz b10e29b8f5 Driver: DXX: Update libredxx 2025-08-28 23:24:04 -04:00
Thomas StoddardandKyle Schwarz 3c0c0dd44c Docs: Refactor icsneopy examples 2025-08-28 11:40:57 -04:00
Kyle Schwarz cf2cf3e28b CMake: Disable libredxx install 2025-08-28 10:09:30 -04:00
271 changed files with 11346 additions and 3426 deletions
+42 -42
View File
@@ -1,5 +1,6 @@
variables: variables:
DEBIAN_FRONTEND: noninteractive DEBIAN_FRONTEND: noninteractive
LIBICSNEO_ICSPB_REPO: https://gitlab-ci-token:${CI_JOB_TOKEN}@${LIBICSNEO_ICSPB_GIT}
stages: stages:
- build - build
@@ -13,7 +14,7 @@ stages:
build windows/x64: build windows/x64:
stage: build stage: build
script: script:
- CMD.EXE /C ci\build-windows64.bat - cmd /C ci\build-windows64.bat
artifacts: artifacts:
when: always when: always
paths: paths:
@@ -37,7 +38,7 @@ unit_test windows/x64:
build windows/x86: build windows/x86:
stage: build stage: build
script: script:
- CMD.EXE /C ci\build-windows32.bat - cmd /C ci\build-windows32.bat
artifacts: artifacts:
when: always when: always
paths: paths:
@@ -67,7 +68,9 @@ unit_test windows/x86:
script: script:
- apt update -y - apt update -y
- apt upgrade -y - apt upgrade -y
- apt install -y g++ ninja-build cmake libpcap-dev git - apt install -y g++ ninja-build cmake libpcap-dev git ca-certificates
- echo "$ICS_IPA_CA_CRT" >/usr/local/share/ca-certificates/ica-ipa-ca.crt
- update-ca-certificates --fresh
- sh ci/build-posix.sh - sh ci/build-posix.sh
artifacts: artifacts:
when: always when: always
@@ -93,7 +96,9 @@ unit_test windows/x86:
script: script:
- apt update -y - apt update -y
- apt upgrade -y - apt upgrade -y
- apt install -y clang lld ninja-build cmake libpcap-dev git - apt install -y clang lld ninja-build cmake libpcap-dev git ca-certificates
- echo "$ICS_IPA_CA_CRT" >/usr/local/share/ca-certificates/ica-ipa-ca.crt
- update-ca-certificates --fresh
- CC=clang CXX=clang++ LDFLAGS=-fuse-ld=lld sh ci/build-posix.sh - CC=clang CXX=clang++ LDFLAGS=-fuse-ld=lld sh ci/build-posix.sh
artifacts: artifacts:
when: always when: always
@@ -175,7 +180,9 @@ unit_test linux/ubuntu/2404/amd64/clang:
- echo max_parallel_downloads=10 >>/etc/dnf/dnf.conf - echo max_parallel_downloads=10 >>/etc/dnf/dnf.conf
- echo fastestmirror=True >>/etc/dnf/dnf.conf - echo fastestmirror=True >>/etc/dnf/dnf.conf
- dnf upgrade -y - dnf upgrade -y
- dnf install -y g++ libpcap-devel cmake ninja-build git - dnf install -y g++ libpcap-devel cmake ninja-build git ca-certificates
- echo "$ICS_IPA_CA_CRT" >/etc/pki/ca-trust/source/anchors/ica-ipa-ca.crt
- update-ca-trust
- sh ci/build-posix.sh - sh ci/build-posix.sh
artifacts: artifacts:
when: always when: always
@@ -209,7 +216,9 @@ unit_test linux/ubuntu/2404/amd64/clang:
- echo max_parallel_downloads=10 >>/etc/dnf/dnf.conf - echo max_parallel_downloads=10 >>/etc/dnf/dnf.conf
- echo fastestmirror=True >>/etc/dnf/dnf.conf - echo fastestmirror=True >>/etc/dnf/dnf.conf
- dnf upgrade -y - dnf upgrade -y
- dnf install -y clang lld libpcap-devel cmake ninja-build git - dnf install -y clang lld libpcap-devel cmake ninja-build git ca-certificates
- echo "$ICS_IPA_CA_CRT" >/etc/pki/ca-trust/source/anchors/ica-ipa-ca.crt
- update-ca-trust
- CC=clang CXX=clang++ LDFLAGS=-fuse-ld=lld sh ci/build-posix.sh - CC=clang CXX=clang++ LDFLAGS=-fuse-ld=lld sh ci/build-posix.sh
artifacts: artifacts:
when: always when: always
@@ -234,30 +243,6 @@ unit_test linux/ubuntu/2404/amd64/clang:
- linux-build - linux-build
timeout: 5m timeout: 5m
build linux/fedora/41/amd64/gcc:
<<: *build_linux_fedora_gcc
image: fedora:41
unit_test linux/fedora/41/amd64/gcc:
<<: *test_linux_fedora_gcc
image: fedora:41
dependencies:
- build linux/fedora/41/amd64/gcc
needs:
- build linux/fedora/41/amd64/gcc
build linux/fedora/41/amd64/clang:
<<: *build_linux_fedora_clang
image: fedora:41
unit_test linux/fedora/41/amd64/clang:
<<: *test_linux_fedora_clang
image: fedora:41
dependencies:
- build linux/fedora/41/amd64/clang
needs:
- build linux/fedora/41/amd64/clang
build linux/fedora/42/amd64/gcc: build linux/fedora/42/amd64/gcc:
<<: *build_linux_fedora_gcc <<: *build_linux_fedora_gcc
image: fedora:42 image: fedora:42
@@ -282,6 +267,30 @@ unit_test linux/fedora/42/amd64/clang:
needs: needs:
- build linux/fedora/42/amd64/clang - build linux/fedora/42/amd64/clang
build linux/fedora/43/amd64/gcc:
<<: *build_linux_fedora_gcc
image: fedora:43
unit_test linux/fedora/43/amd64/gcc:
<<: *test_linux_fedora_gcc
image: fedora:43
dependencies:
- build linux/fedora/43/amd64/gcc
needs:
- build linux/fedora/43/amd64/gcc
build linux/fedora/43/amd64/clang:
<<: *build_linux_fedora_clang
image: fedora:43
unit_test linux/fedora/43/amd64/clang:
<<: *test_linux_fedora_clang
image: fedora:43
dependencies:
- build linux/fedora/43/amd64/clang
needs:
- build linux/fedora/43/amd64/clang
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
# Python Module # Python Module
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
@@ -289,22 +298,13 @@ unit_test linux/fedora/42/amd64/clang:
build python/linux/amd64: build python/linux/amd64:
stage: build stage: build
tags: tags:
- linux-build - linux-native-amd64
image: python:3.13
services:
- name: docker:dind
entrypoint: ["env", "-u", "DOCKER_HOST"]
command: ["dockerd-entrypoint.sh"]
variables: variables:
CIBW_BEFORE_ALL: yum install -y flex && sh ci/bootstrap-libpcap.sh CIBW_BEFORE_ALL: sh ci/bootstrap-cibuildwheel.sh && sh ci/bootstrap-libpcap.sh
CIBW_BUILD: "*manylinux*" # no musl CIBW_BUILD: "*manylinux*" # no musl
CIBW_ARCHS: x86_64 CIBW_ARCHS: x86_64
DOCKER_HOST: unix:///var/run/docker.sock
DOCKER_DRIVER: overlay2
DOCKER_TLS_CERTDIR: ""
CIBW_ENVIRONMENT: CMAKE_PREFIX_PATH=/project/libpcap/install CIBW_ENVIRONMENT: CMAKE_PREFIX_PATH=/project/libpcap/install
script: script:
- curl -sSL https://get.docker.com/ | sh
- sh ci/build-wheel-posix.sh - sh ci/build-wheel-posix.sh
artifacts: artifacts:
paths: paths:
@@ -315,7 +315,7 @@ build python/linux/arm64:
tags: tags:
- arm64-linux-build - arm64-linux-build
variables: variables:
CIBW_BEFORE_ALL: yum install -y flex && sh ci/bootstrap-libpcap.sh CIBW_BEFORE_ALL: sh ci/bootstrap-cibuildwheel.sh && sh ci/bootstrap-libpcap.sh
CIBW_BUILD: "*manylinux*" # no musl CIBW_BUILD: "*manylinux*" # no musl
CIBW_ARCHS: aarch64 CIBW_ARCHS: aarch64
CIBW_ENVIRONMENT: CMAKE_PREFIX_PATH=/project/libpcap/install CIBW_ENVIRONMENT: CMAKE_PREFIX_PATH=/project/libpcap/install
+5 -21
View File
@@ -3,24 +3,8 @@ SUBSYSTEM=="usb", ATTRS{idVendor}=="093c", GROUP="users", MODE="0666"
KERNEL=="ttyUSB?", ATTRS{idVendor}=="093c", GROUP="users", MODE="0666" KERNEL=="ttyUSB?", ATTRS{idVendor}=="093c", GROUP="users", MODE="0666"
KERNEL=="ttyACM?", ATTRS{idVendor}=="093c", GROUP="users", MODE="0666" KERNEL=="ttyACM?", ATTRS{idVendor}=="093c", GROUP="users", MODE="0666"
# neoVI ION/PLASMA PIDs are not in the latest ftdi_sio driver so lets make a ACTION=="add", SUBSYSTEMS=="usb", ATTRS{idVendor}=="093c", KERNEL=="ttyUSB*", \
# rule to add it when we see a new unclaimed device. RUN+="/bin/sh -c 'echo $id:1.0>/sys/bus/usb/drivers/ftdi_sio/unbind'"
# PLASMA = 0x0801, ION = 0x0901
ACTION=="add", SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_interface", \ ACTION=="add", SUBSYSTEMS=="usb", ATTRS{idVendor}=="093c", DRIVER=="usbhid", \
ATTRS{idVendor}=="093c", ATTRS{idProduct}=="0801", \ RUN+="/bin/sh -c 'echo $id:1.0>/sys/bus/usb/drivers/usbhid/unbind'"
DRIVER=="", \
RUN+="/sbin/modprobe -b ftdi_sio"
ACTION=="add", SUBSYSTEM=="drivers", \
ENV{DEVPATH}=="/bus/usb-serial/drivers/ftdi_sio", \
ATTR{new_id}="093c 0801"
ACTION=="add", SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_interface", \
ATTRS{idVendor}=="093c", ATTRS{idProduct}=="0901", \
DRIVER=="", \
RUN+="/sbin/modprobe -b ftdi_sio"
ACTION=="add", SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_interface", \
ATTRS{idVendor}=="093c", ATTRS{idProduct}=="1000", \
DRIVER=="", \
RUN+="/sbin/modprobe -b ftdi_sio"
ACTION=="add", SUBSYSTEM=="drivers", \
ENV{DEVPATH}=="/bus/usb-serial/drivers/ftdi_sio", \
ATTR{new_id}="093c 0901"
+42 -15
View File
@@ -27,9 +27,8 @@ option(LIBICSNEO_ENABLE_DXX "Enable devices which communicate over D2XX/D3XX via
option(LIBICSNEO_ENABLE_BINDINGS_PYTHON "Enable Python library" OFF) option(LIBICSNEO_ENABLE_BINDINGS_PYTHON "Enable Python library" OFF)
if(NOT CMAKE_CXX_STANDARD) set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD 17) set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded")
endif()
include(GNUInstallDirs) include(GNUInstallDirs)
@@ -37,17 +36,13 @@ set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
# Enable Warnings # Enable Warnings
if(MSVC) if(MSVC)
# Force to always compile with W4 set(LIBICSNEO_COMPILER_WARNINGS /W4)
if(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
endif()
# http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0618r0.html # http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0618r0.html
# Still supported until a suitable replacement is standardized # Still supported until a suitable replacement is standardized
add_definitions(-D_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING) add_definitions(-D_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING)
add_definitions(-D_ITERATOR_DEBUG_LEVEL=0)
else() #if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX) else() #if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-switch -Wno-unknown-pragmas") set(LIBICSNEO_COMPILER_WARNINGS -Wall -Wno-switch -Wno-unknown-pragmas)
endif() endif()
find_package(Threads REQUIRED) find_package(Threads REQUIRED)
@@ -200,10 +195,13 @@ set(SRC_FILES
communication/message/tc10statusmessage.cpp communication/message/tc10statusmessage.cpp
communication/message/gptpstatusmessage.cpp communication/message/gptpstatusmessage.cpp
communication/message/ethernetstatusmessage.cpp communication/message/ethernetstatusmessage.cpp
communication/message/macsecmessage.cpp communication/message/networkmutexmessage.cpp
communication/message/clientidmessage.cpp
communication/message/transmitmessage.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
communication/packet/spipacket.cpp
communication/packet/ethernetpacket.cpp communication/packet/ethernetpacket.cpp
communication/packet/versionpacket.cpp communication/packet/versionpacket.cpp
communication/packet/iso9141packet.cpp communication/packet/iso9141packet.cpp
@@ -227,8 +225,9 @@ set(SRC_FILES
communication/communication.cpp communication/communication.cpp
communication/driver.cpp communication/driver.cpp
communication/livedata.cpp communication/livedata.cpp
communication/ringbuffer.cpp core/ringbuffer.cpp
communication/crc32.cpp core/crc32.cpp
core/macseccfg.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
@@ -323,6 +322,7 @@ target_include_directories(icsneocpp
target_link_libraries(icsneocpp PUBLIC Threads::Threads $<$<BOOL:${WIN32}>:ws2_32 iphlpapi>) target_link_libraries(icsneocpp PUBLIC Threads::Threads $<$<BOOL:${WIN32}>:ws2_32 iphlpapi>)
set_property(TARGET icsneocpp PROPERTY POSITION_INDEPENDENT_CODE ON) set_property(TARGET icsneocpp PROPERTY POSITION_INDEPENDENT_CODE ON)
target_compile_features(icsneocpp PUBLIC cxx_auto_type cxx_constexpr cxx_lambdas cxx_nullptr cxx_range_for cxx_rvalue_references cxx_sizeof_member cxx_strong_enums) target_compile_features(icsneocpp PUBLIC cxx_auto_type cxx_constexpr cxx_lambdas cxx_nullptr cxx_range_for cxx_rvalue_references cxx_sizeof_member cxx_strong_enums)
target_compile_options(icsneocpp PRIVATE ${LIBICSNEO_COMPILER_WARNINGS})
message("Loaded extensions: " ${LIBICSNEO_EXTENSION_TARGETS}) message("Loaded extensions: " ${LIBICSNEO_EXTENSION_TARGETS})
target_link_libraries(icsneocpp PUBLIC ${LIBICSNEO_EXTENSION_TARGETS}) target_link_libraries(icsneocpp PUBLIC ${LIBICSNEO_EXTENSION_TARGETS})
if(LIBICSNEO_ENABLE_FIRMIO) if(LIBICSNEO_ENABLE_FIRMIO)
@@ -333,6 +333,11 @@ if(LIBICSNEO_ENABLE_RAW_ETHERNET)
endif() endif()
if(LIBICSNEO_ENABLE_CDCACM) if(LIBICSNEO_ENABLE_CDCACM)
target_compile_definitions(icsneocpp PRIVATE ICSNEO_ENABLE_CDCACM) target_compile_definitions(icsneocpp PRIVATE ICSNEO_ENABLE_CDCACM)
if(APPLE)
find_library(CORE_FOUNDATION_FRAMEWORK CoreFoundation REQUIRED)
find_library(IO_KIT_FRAMEWORK IOKit REQUIRED)
target_link_libraries(icsneocpp PRIVATE ${CORE_FOUNDATION_FRAMEWORK} ${IO_KIT_FRAMEWORK})
endif()
endif() endif()
if(LIBICSNEO_ENABLE_DXX) if(LIBICSNEO_ENABLE_DXX)
target_compile_definitions(icsneocpp PRIVATE ICSNEO_ENABLE_DXX) target_compile_definitions(icsneocpp PRIVATE ICSNEO_ENABLE_DXX)
@@ -355,8 +360,9 @@ if(LIBICSNEO_ENABLE_DXX)
include(FetchContent) include(FetchContent)
FetchContent_Declare(libredxx FetchContent_Declare(libredxx
GIT_REPOSITORY https://github.com/Zeranoe/libredxx.git GIT_REPOSITORY https://github.com/Zeranoe/libredxx.git
GIT_TAG 2b7932fe7f2fc006ef269c7a72595f3940178a10 GIT_TAG 267abf26a99fa69ed80a4180b155245a36fad101
) )
set(LIBREDXX_DISABLE_INSTALL ON)
FetchContent_MakeAvailable(libredxx) FetchContent_MakeAvailable(libredxx)
endif() endif()
@@ -376,6 +382,21 @@ if(LIBICSNEO_ENABLE_RAW_ETHERNET)
endif(WIN32) endif(WIN32)
endif(LIBICSNEO_ENABLE_RAW_ETHERNET) endif(LIBICSNEO_ENABLE_RAW_ETHERNET)
# protobuf
if(DEFINED ENV{LIBICSNEO_ICSPB_REPO})
set(LIBICSNEO_ICSPB_REPO "$ENV{LIBICSNEO_ICSPB_REPO}")
endif()
if(NOT LIBICSNEO_ICSPB_REPO)
set(LIBICSNEO_ICSPB_REPO https://github.com/intrepidcs/icspb.git)
endif()
include(FetchContent)
FetchContent_Declare(icspb
GIT_REPOSITORY ${LIBICSNEO_ICSPB_REPO}
GIT_TAG 3339fa6b83a6b3e7704d41f5c2f2175cfc761a1f
)
FetchContent_MakeAvailable(icspb)
target_link_libraries(icsneocpp PRIVATE icspb::icspb)
if(LIBICSNEO_BUILD_ICSNEOC) if(LIBICSNEO_BUILD_ICSNEOC)
add_library(icsneoc SHARED api/icsneoc/icsneoc.cpp ${CMAKE_CURRENT_BINARY_DIR}/generated/icsneoc/version.rc) add_library(icsneoc SHARED api/icsneoc/icsneoc.cpp ${CMAKE_CURRENT_BINARY_DIR}/generated/icsneoc/version.rc)
target_include_directories(icsneoc target_include_directories(icsneoc
@@ -387,6 +408,7 @@ if(LIBICSNEO_BUILD_ICSNEOC)
) )
target_link_libraries(icsneoc PRIVATE icsneocpp) target_link_libraries(icsneoc PRIVATE icsneocpp)
target_compile_features(icsneoc PRIVATE cxx_auto_type cxx_constexpr cxx_lambdas cxx_nullptr cxx_range_for cxx_rvalue_references cxx_sizeof_member cxx_strong_enums) target_compile_features(icsneoc PRIVATE cxx_auto_type cxx_constexpr cxx_lambdas cxx_nullptr cxx_range_for cxx_rvalue_references cxx_sizeof_member cxx_strong_enums)
target_compile_options(icsneoc PRIVATE ${LIBICSNEO_COMPILER_WARNINGS})
endif() endif()
if(LIBICSNEO_BUILD_ICSNEOC_STATIC) if(LIBICSNEO_BUILD_ICSNEOC_STATIC)
@@ -401,6 +423,7 @@ if(LIBICSNEO_BUILD_ICSNEOC_STATIC)
target_link_libraries(icsneoc-static PUBLIC icsneocpp) target_link_libraries(icsneoc-static PUBLIC icsneocpp)
target_compile_features(icsneoc-static PUBLIC cxx_auto_type cxx_constexpr cxx_lambdas cxx_nullptr cxx_range_for cxx_rvalue_references cxx_sizeof_member cxx_strong_enums) target_compile_features(icsneoc-static PUBLIC cxx_auto_type cxx_constexpr cxx_lambdas cxx_nullptr cxx_range_for cxx_rvalue_references cxx_sizeof_member cxx_strong_enums)
target_compile_definitions(icsneoc-static PUBLIC ICSNEOC_BUILD_STATIC) target_compile_definitions(icsneoc-static PUBLIC ICSNEOC_BUILD_STATIC)
target_compile_options(icsneoc-static PRIVATE ${LIBICSNEO_COMPILER_WARNINGS})
endif() endif()
if(LIBICSNEO_BUILD_ICSNEOLEGACY) if(LIBICSNEO_BUILD_ICSNEOLEGACY)
@@ -419,6 +442,7 @@ if(LIBICSNEO_BUILD_ICSNEOLEGACY)
) )
target_link_libraries(icsneolegacy PRIVATE icsneocpp) target_link_libraries(icsneolegacy PRIVATE icsneocpp)
target_compile_features(icsneolegacy PRIVATE cxx_auto_type cxx_constexpr cxx_lambdas cxx_nullptr cxx_range_for cxx_rvalue_references cxx_sizeof_member cxx_strong_enums) target_compile_features(icsneolegacy PRIVATE cxx_auto_type cxx_constexpr cxx_lambdas cxx_nullptr cxx_range_for cxx_rvalue_references cxx_sizeof_member cxx_strong_enums)
target_compile_options(icsneolegacy PRIVATE ${LIBICSNEO_COMPILER_WARNINGS})
endif() endif()
if(LIBICSNEO_BUILD_ICSNEOLEGACY_STATIC) if(LIBICSNEO_BUILD_ICSNEOLEGACY_STATIC)
@@ -438,6 +462,7 @@ if(LIBICSNEO_BUILD_ICSNEOLEGACY_STATIC)
target_link_libraries(icsneolegacy-static PUBLIC icsneocpp) target_link_libraries(icsneolegacy-static PUBLIC icsneocpp)
target_compile_features(icsneolegacy-static PUBLIC cxx_auto_type cxx_constexpr cxx_lambdas cxx_nullptr cxx_range_for cxx_rvalue_references cxx_sizeof_member cxx_strong_enums) target_compile_features(icsneolegacy-static PUBLIC cxx_auto_type cxx_constexpr cxx_lambdas cxx_nullptr cxx_range_for cxx_rvalue_references cxx_sizeof_member cxx_strong_enums)
target_compile_definitions(icsneolegacy-static PUBLIC ICSNEOC_BUILD_STATIC) target_compile_definitions(icsneolegacy-static PUBLIC ICSNEOC_BUILD_STATIC)
target_compile_options(icsneolegacy-static PRIVATE ${LIBICSNEO_COMPILER_WARNINGS})
endif() endif()
add_subdirectory(bindings) add_subdirectory(bindings)
@@ -468,6 +493,8 @@ if(LIBICSNEO_BUILD_UNIT_TESTS)
test/unit/periodictest.cpp test/unit/periodictest.cpp
) )
target_compile_options(libicsneo-unit-tests PRIVATE ${LIBICSNEO_COMPILER_WARNINGS})
target_link_libraries(libicsneo-unit-tests gtest gtest_main) target_link_libraries(libicsneo-unit-tests gtest gtest_main)
target_link_libraries(libicsneo-unit-tests icsneocpp) target_link_libraries(libicsneo-unit-tests icsneocpp)
@@ -480,4 +507,4 @@ 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)
+1
View File
@@ -27,6 +27,7 @@ each of the respective APIs.
- RAD-EpsilonXL - RAD-EpsilonXL
- RAD-Galaxy - RAD-Galaxy
- RAD-Galaxy 2 - RAD-Galaxy 2
- RAD-Gemini
- RAD-Gigastar - RAD-Gigastar
- RAD-Gigastar 2 - RAD-Gigastar 2
- RAD-Moon 2 - RAD-Moon 2
+29
View File
@@ -156,6 +156,16 @@ static constexpr const char* VSA_BYTE_PARSE_FAILURE = "Failure to parse record b
static constexpr const char* VSA_EXTENDED_MESSAGE_ERROR = "Failure to parse extended message record sequence"; static constexpr const char* VSA_EXTENDED_MESSAGE_ERROR = "Failure to parse extended message record sequence";
static constexpr const char* VSA_OTHER_ERROR = "Unknown error in VSA read API."; static constexpr const char* VSA_OTHER_ERROR = "Unknown error in VSA read API.";
// MACSEC
static constexpr const char* MACSEC_SECY_LIMIT = "Attempted to exceed the limit of SecY additions to this port";
static constexpr const char* MACSEC_RULE_LIMIT = "Attempted to exceed the limit of rule additions to this port";
static constexpr const char* MACSEC_SA_LIMIT = "Attempted to exceed the limit of SA additions to this port";
static constexpr const char* MACSEC_INVALID_SECY_INDEX = "Attempted to access an invalid SecY index";
static constexpr const char* MACSEC_INVALID_SA_INDEX = "Attempted to access an invalid SA index";
static constexpr const char* MACSEC_INVALID_RULE_INDEX = "Attempted to access an invalid rule index";
static constexpr const char* MACSEC_REKEY_NOT_ENABLED = "Attempted to set rekey SA when rekey was not enabled";
static constexpr const char* MACSEC_NOT_SUPPORTED = "MACsec is not supported on this device";
static constexpr const char* MACSEC_CONFIG_MISMATCH = "Attempted to configure device with a macsec configuration for a different device";
// Servd // Servd
static constexpr const char* SERVD_BIND_ERROR = "Error binding socket for Servd communication"; static constexpr const char* SERVD_BIND_ERROR = "Error binding socket for Servd communication";
static constexpr const char* SERVD_NONBLOCK_ERROR = "Error setting non-blocking mode for Servd socket"; static constexpr const char* SERVD_NONBLOCK_ERROR = "Error setting non-blocking mode for Servd socket";
@@ -371,6 +381,25 @@ const char* APIEvent::DescriptionForType(Type type) {
case Type::VSAOtherError: case Type::VSAOtherError:
return VSA_OTHER_ERROR; return VSA_OTHER_ERROR;
// MACSEC
case Type::MACsecSecYLimit:
return MACSEC_SECY_LIMIT;
case Type::MACsecSaLimit:
return MACSEC_SA_LIMIT;
case Type::MACsecRuleLimit:
return MACSEC_RULE_LIMIT;
case Type::MACsecInvalidSecYIndex:
return MACSEC_INVALID_SECY_INDEX;
case Type::MACsecInvalidSaIndex:
return MACSEC_INVALID_SA_INDEX;
case Type::MACsecInvalidRuleIndex:
return MACSEC_INVALID_RULE_INDEX;
case Type::MACsecRekeyNotEnabled:
return MACSEC_REKEY_NOT_ENABLED;
case Type::MACsecNotSupported:
return MACSEC_NOT_SUPPORTED;
case Type::MACsecConfigMismatch:
return MACSEC_CONFIG_MISMATCH;
// Servd // Servd
case Type::ServdBindError: case Type::ServdBindError:
return SERVD_BIND_ERROR; return SERVD_BIND_ERROR;
+4
View File
@@ -90,6 +90,7 @@ static bool NeoMessageToSpyMessage(const neodevice_t* device, const neomessage_t
copyFrameData(); copyFrameData();
break; break;
case Network::Type::Ethernet: case Network::Type::Ethernet:
case Network::Type::AutomotiveEthernet:
oldmsg.Protocol = SPY_PROTOCOL_ETHERNET; oldmsg.Protocol = SPY_PROTOCOL_ETHERNET;
oldmsg.NumberBytesData = static_cast<uint8_t>(frame.length & 0xFF); oldmsg.NumberBytesData = static_cast<uint8_t>(frame.length & 0xFF);
oldmsg.NumberBytesHeader = static_cast<uint8_t>(frame.length >> 8); oldmsg.NumberBytesHeader = static_cast<uint8_t>(frame.length >> 8);
@@ -1075,6 +1076,9 @@ int LegacyDLLExport icsneoGetDeviceSettingsType(void* hObject, EPlasmaIonVnetCha
case NEODEVICE_RADMOON3: case NEODEVICE_RADMOON3:
*pDeviceSettingsType = DeviceRADMoon3SettingsType; *pDeviceSettingsType = DeviceRADMoon3SettingsType;
break; break;
case NEODEVICE_RADGEMINI:
*pDeviceSettingsType = DeviceRADGeminiSettingsType;
break;
case NEODEVICE_RED2: case NEODEVICE_RED2:
*pDeviceSettingsType = DeviceRed2SettingsType; *pDeviceSettingsType = DeviceRed2SettingsType;
break; break;
+10 -3
View File
@@ -9,7 +9,7 @@ else()
FetchContent_Declare( FetchContent_Declare(
pybind11 pybind11
GIT_REPOSITORY https://github.com/pybind/pybind11.git GIT_REPOSITORY https://github.com/pybind/pybind11.git
GIT_TAG v2.13.6 GIT_TAG v3.0.1
) )
FetchContent_MakeAvailable(pybind11) FetchContent_MakeAvailable(pybind11)
endif() endif()
@@ -22,6 +22,7 @@ pybind11_add_module(icsneopy
icsneopy/device/devicetype.cpp icsneopy/device/devicetype.cpp
icsneopy/communication/network.cpp icsneopy/communication/network.cpp
icsneopy/communication/io.cpp icsneopy/communication/io.cpp
icsneopy/communication/livedata.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/canerrormessage.cpp
@@ -31,13 +32,19 @@ pybind11_add_module(icsneopy
icsneopy/communication/message/mdiomessage.cpp icsneopy/communication/message/mdiomessage.cpp
icsneopy/communication/message/gptpstatusmessage.cpp icsneopy/communication/message/gptpstatusmessage.cpp
icsneopy/communication/message/ethernetstatusmessage.cpp icsneopy/communication/message/ethernetstatusmessage.cpp
icsneopy/communication/message/macsecmessage.cpp icsneopy/communication/message/spimessage.cpp
icsneopy/communication/message/scriptstatusmessage.cpp icsneopy/communication/message/scriptstatusmessage.cpp
icsneopy/communication/message/ethphymessage.cpp
icsneopy/communication/message/livedatamessage.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/communication/message/flexray/flexraymessage.cpp icsneopy/core/macseccfg.cpp
icsneopy/flexray/flexray.cpp
icsneopy/disk/diskdriver.cpp icsneopy/disk/diskdriver.cpp
icsneopy/device/chipid.cpp
icsneopy/device/versionreport.cpp
icsneopy/device/device.cpp icsneopy/device/device.cpp
icsneopy/device/extensions/deviceextension.cpp
icsneopy/device/idevicesettings.cpp icsneopy/device/idevicesettings.cpp
icsneopy/icsneocpp.cpp icsneopy/icsneocpp.cpp
) )
+9 -6
View File
@@ -1,14 +1,15 @@
#include <pybind11/pybind11.h> #include <pybind11/pybind11.h>
#include <pybind11/stl.h> #include <pybind11/stl.h>
#include <pybind11/functional.h> #include <pybind11/functional.h>
#include <pybind11/native_enum.h>
#include "icsneo/api/event.h" #include "icsneo/api/event.h"
namespace icsneo { namespace icsneo {
void init_event(pybind11::module_& m) { void init_event(pybind11::module_& m) {
pybind11::class_<APIEvent, std::shared_ptr<APIEvent>> apiEvent(m, "APIEvent"); pybind11::classh<APIEvent> apiEvent(m, "APIEvent");
pybind11::enum_<APIEvent::Type>(apiEvent, "Type") pybind11::native_enum<APIEvent::Type>(apiEvent, "Type", "enum.IntEnum")
.value("Any", APIEvent::Type::Any) .value("Any", APIEvent::Type::Any)
.value("InvalidNeoDevice", APIEvent::Type::InvalidNeoDevice) .value("InvalidNeoDevice", APIEvent::Type::InvalidNeoDevice)
.value("RequiredParameterNull", APIEvent::Type::RequiredParameterNull) .value("RequiredParameterNull", APIEvent::Type::RequiredParameterNull)
@@ -132,13 +133,15 @@ void init_event(pybind11::module_& m) {
.value("DXXErrorArg", APIEvent::Type::DXXErrorArg) .value("DXXErrorArg", APIEvent::Type::DXXErrorArg)
.value("NoErrorFound", APIEvent::Type::NoErrorFound) .value("NoErrorFound", APIEvent::Type::NoErrorFound)
.value("TooManyEvents", APIEvent::Type::TooManyEvents) .value("TooManyEvents", APIEvent::Type::TooManyEvents)
.value("Unknown", APIEvent::Type::Unknown); .value("Unknown", APIEvent::Type::Unknown)
.finalize();
pybind11::enum_<APIEvent::Severity>(apiEvent, "Severity") pybind11::native_enum<APIEvent::Severity>(apiEvent, "Severity", "enum.IntEnum")
.value("Any", APIEvent::Severity::Any) .value("Any", APIEvent::Severity::Any)
.value("EventInfo", APIEvent::Severity::EventInfo) .value("EventInfo", APIEvent::Severity::EventInfo)
.value("EventWarning", APIEvent::Severity::EventWarning) .value("EventWarning", APIEvent::Severity::EventWarning)
.value("Error", APIEvent::Severity::Error); .value("Error", APIEvent::Severity::Error)
.finalize();
apiEvent apiEvent
.def("get_type", &APIEvent::getType) .def("get_type", &APIEvent::getType)
@@ -147,7 +150,7 @@ void init_event(pybind11::module_& m) {
.def("describe", &APIEvent::describe) .def("describe", &APIEvent::describe)
.def("__repr__", &APIEvent::describe); .def("__repr__", &APIEvent::describe);
pybind11::class_<EventFilter, std::shared_ptr<EventFilter>>(m, "EventFilter") pybind11::classh<EventFilter>(m, "EventFilter")
.def(pybind11::init()) .def(pybind11::init())
.def(pybind11::init<APIEvent::Type>()) .def(pybind11::init<APIEvent::Type>())
.def(pybind11::init<APIEvent::Severity>()) .def(pybind11::init<APIEvent::Severity>())
@@ -7,7 +7,7 @@
namespace icsneo { namespace icsneo {
void init_eventcallback(pybind11::module_& m) { void init_eventcallback(pybind11::module_& m) {
pybind11::class_<EventCallback>(m, "EventCallback") pybind11::classh<EventCallback>(m, "EventCallback")
.def(pybind11::init<EventCallback::fn_eventCallback, EventFilter>()) .def(pybind11::init<EventCallback::fn_eventCallback, EventFilter>())
.def(pybind11::init<EventCallback::fn_eventCallback>()); .def(pybind11::init<EventCallback::fn_eventCallback>());
} }
@@ -7,7 +7,7 @@
namespace icsneo { namespace icsneo {
void init_eventmanager(pybind11::module_& m) { void init_eventmanager(pybind11::module_& m) {
pybind11::class_<EventManager>(m, "EventManager") pybind11::classh<EventManager>(m, "EventManager")
.def_static("get_instance", &EventManager::GetInstance, pybind11::return_value_policy::reference) .def_static("get_instance", &EventManager::GetInstance, pybind11::return_value_policy::reference)
.def("add_event_callback", &EventManager::addEventCallback) .def("add_event_callback", &EventManager::addEventCallback)
.def("remove_event_callback", &EventManager::removeEventCallback) .def("remove_event_callback", &EventManager::removeEventCallback)
+1 -1
View File
@@ -9,7 +9,7 @@
namespace icsneo { namespace icsneo {
void init_version(pybind11::module_& m) { void init_version(pybind11::module_& m) {
pybind11::class_<neoversion_t>(m, "NeoVersion") pybind11::classh<neoversion_t>(m, "NeoVersion")
.def_readonly("major", &neoversion_t::major) .def_readonly("major", &neoversion_t::major)
.def_readonly("minor", &neoversion_t::minor) .def_readonly("minor", &neoversion_t::minor)
.def_readonly("patch", &neoversion_t::patch) .def_readonly("patch", &neoversion_t::patch)
@@ -0,0 +1,79 @@
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <pybind11/functional.h>
#include <pybind11/native_enum.h>
#include "icsneo/communication/livedata.h"
namespace icsneo {
void init_livedata(pybind11::module_& m) {
// LiveDataValue struct
pybind11::classh<LiveDataValue>(m, "LiveDataValue")
.def(pybind11::init<>())
.def_readwrite("value", &LiveDataValue::value);
// LiveDataArgument struct
pybind11::classh<LiveDataArgument>(m, "LiveDataArgument")
.def(pybind11::init<>())
.def_readwrite("object_type", &LiveDataArgument::objectType)
.def_readwrite("object_index", &LiveDataArgument::objectIndex)
.def_readwrite("signal_index", &LiveDataArgument::signalIndex)
.def_readwrite("value_type", &LiveDataArgument::valueType);
// LiveDataCommand enum
pybind11::native_enum<LiveDataCommand>(m, "LiveDataCommand", "enum.IntEnum")
.value("STATUS", LiveDataCommand::STATUS)
.value("SUBSCRIBE", LiveDataCommand::SUBSCRIBE)
.value("UNSUBSCRIBE", LiveDataCommand::UNSUBSCRIBE)
.value("RESPONSE", LiveDataCommand::RESPONSE)
.value("CLEAR_ALL", LiveDataCommand::CLEAR_ALL)
.value("SET_VALUE", LiveDataCommand::SET_VALUE)
.finalize();
// LiveDataStatus enum
pybind11::native_enum<LiveDataStatus>(m, "LiveDataStatus", "enum.IntEnum")
.value("SUCCESS", LiveDataStatus::SUCCESS)
.value("ERR_UNKNOWN_COMMAND", LiveDataStatus::ERR_UNKNOWN_COMMAND)
.value("ERR_HANDLE", LiveDataStatus::ERR_HANDLE)
.value("ERR_DUPLICATE", LiveDataStatus::ERR_DUPLICATE)
.value("ERR_FULL", LiveDataStatus::ERR_FULL)
.finalize();
// LiveDataObjectType enum
pybind11::enum_<LiveDataObjectType>(m, "LiveDataObjectType")
.value("MISC", LiveDataObjectType::MISC)
.value("SNA", LiveDataObjectType::SNA)
.export_values();
// LiveDataValueType enum
pybind11::native_enum<LiveDataValueType>(m, "LiveDataValueType", "enum.IntEnum")
.value("GPS_LATITUDE", LiveDataValueType::GPS_LATITUDE)
.value("GPS_LONGITUDE", LiveDataValueType::GPS_LONGITUDE)
.value("GPS_ALTITUDE", LiveDataValueType::GPS_ALTITUDE)
.value("GPS_SPEED", LiveDataValueType::GPS_SPEED)
.value("GPS_VALID", LiveDataValueType::GPS_VALID)
.value("GPS_ENABLE", LiveDataValueType::GPS_ENABLE)
.value("MANUAL_TRIGGER", LiveDataValueType::MANUAL_TRIGGER)
.value("TIME_SINCE_MSG", LiveDataValueType::TIME_SINCE_MSG)
.value("GPS_ACCURACY", LiveDataValueType::GPS_ACCURACY)
.value("GPS_BEARING", LiveDataValueType::GPS_BEARING)
.value("GPS_TIME", LiveDataValueType::GPS_TIME)
.value("GPS_TIME_VALID", LiveDataValueType::GPS_TIME_VALID)
.value("DAQ_ENABLE", LiveDataValueType::DAQ_ENABLE)
.finalize();
// LiveDataUtil namespace functions
m.def("get_new_handle", &LiveDataUtil::getNewHandle,
"Generate a new unique LiveData handle");
m.def("livedata_value_to_double", &LiveDataUtil::liveDataValueToDouble,
pybind11::arg("val"),
"Convert LiveDataValue to double (32.32 fixed-point to floating-point)");
m.def("livedata_double_to_value", &LiveDataUtil::liveDataDoubleToValue,
pybind11::arg("d"),
"Convert double to LiveDataValue (32.32 fixed-point format). Returns LiveDataValue or None on failure.");
}
} // namespace icsneo
@@ -7,7 +7,7 @@
namespace icsneo { namespace icsneo {
void init_messagecallback(pybind11::module_& m) { void init_messagecallback(pybind11::module_& m) {
pybind11::class_<MessageCallback, std::shared_ptr<MessageCallback>>(m, "MessageCallback") pybind11::classh<MessageCallback>(m, "MessageCallback")
.def(pybind11::init<MessageCallback::fn_messageCallback, std::shared_ptr<MessageFilter>>()); .def(pybind11::init<MessageCallback::fn_messageCallback, std::shared_ptr<MessageFilter>>());
} }
@@ -1,13 +1,14 @@
#include <pybind11/pybind11.h> #include <pybind11/pybind11.h>
#include <pybind11/stl.h> #include <pybind11/stl.h>
#include <pybind11/functional.h> #include <pybind11/functional.h>
#include <pybind11/native_enum.h>
#include "icsneo/communication/message/canerrormessage.h" #include "icsneo/communication/message/canerrormessage.h"
namespace icsneo { namespace icsneo {
void init_errorcodes(pybind11::module_& m) { void init_errorcodes(pybind11::module_& m) {
pybind11::enum_<CANErrorCode>(m, "CANErrorCode") pybind11::native_enum<CANErrorCode>(m, "CANErrorCode", "enum.IntEnum")
.value("NoError", CANErrorCode::NoError) .value("NoError", CANErrorCode::NoError)
.value("StuffError", CANErrorCode::StuffError) .value("StuffError", CANErrorCode::StuffError)
.value("FormError", CANErrorCode::FormError) .value("FormError", CANErrorCode::FormError)
@@ -15,12 +16,13 @@ void init_errorcodes(pybind11::module_& m) {
.value("Bit1Error", CANErrorCode::Bit1Error) .value("Bit1Error", CANErrorCode::Bit1Error)
.value("Bit0Error", CANErrorCode::Bit0Error) .value("Bit0Error", CANErrorCode::Bit0Error)
.value("CRCError", CANErrorCode::CRCError) .value("CRCError", CANErrorCode::CRCError)
.value("NoChange", CANErrorCode::NoChange); .value("NoChange", CANErrorCode::NoChange)
.finalize();
} }
void init_canerrormessage(pybind11::module_& m) { void init_canerrormessage(pybind11::module_& m) {
init_errorcodes(m); init_errorcodes(m);
pybind11::class_<CANErrorMessage, std::shared_ptr<CANErrorMessage>, Message>(m, "CANErrorMessage") pybind11::classh<CANErrorMessage, Message>(m, "CANErrorMessage")
.def_readonly("network", &CANErrorMessage::network) .def_readonly("network", &CANErrorMessage::network)
.def_readonly("transmitErrorCount", &CANErrorMessage::transmitErrorCount) .def_readonly("transmitErrorCount", &CANErrorMessage::transmitErrorCount)
.def_readonly("receiveErrorCount", &CANErrorMessage::receiveErrorCount) .def_readonly("receiveErrorCount", &CANErrorMessage::receiveErrorCount)
@@ -7,7 +7,7 @@
namespace icsneo { namespace icsneo {
void init_canmessage(pybind11::module_& m) { void init_canmessage(pybind11::module_& m) {
pybind11::class_<CANMessage, std::shared_ptr<CANMessage>, Frame>(m, "CANMessage") pybind11::classh<CANMessage, Frame>(m, "CANMessage")
.def(pybind11::init()) .def(pybind11::init())
.def_readwrite("arbid", &CANMessage::arbid) .def_readwrite("arbid", &CANMessage::arbid)
.def_readwrite("dlcOnWire", &CANMessage::dlcOnWire) .def_readwrite("dlcOnWire", &CANMessage::dlcOnWire)
@@ -7,17 +7,28 @@
namespace icsneo { namespace icsneo {
void init_ethernetmessage(pybind11::module_& m) { void init_ethernetmessage(pybind11::module_& m) {
pybind11::class_<MACAddress>(m, "MACAddress") pybind11::classh<MACAddress>(m, "MACAddress")
.def("to_string", &MACAddress::toString) .def("to_string", &MACAddress::toString)
.def("__repr__", &MACAddress::toString); .def("__repr__", &MACAddress::toString);
pybind11::class_<EthernetMessage, std::shared_ptr<EthernetMessage>, Frame>(m, "EthernetMessage") pybind11::classh<EthernetMessage, Frame>(m, "EthernetMessage")
.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("fcs", &EthernetMessage::fcs) .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_readwrite("fcsVerified", &EthernetMessage::fcsVerified)
.def_readwrite("txAborted", &EthernetMessage::txAborted)
.def_readwrite("crcError", &EthernetMessage::crcError)
.def_readwrite("isT1S", &EthernetMessage::isT1S)
.def_readwrite("isT1SSymbol", &EthernetMessage::isT1SSymbol)
.def_readwrite("isT1SBurst", &EthernetMessage::isT1SBurst)
.def_readwrite("txCollision", &EthernetMessage::txCollision)
.def_readwrite("isT1SWake", &EthernetMessage::isT1SWake)
.def_readwrite("t1sNodeId", &EthernetMessage::t1sNodeId)
.def_readwrite("t1sBurstCount", &EthernetMessage::t1sBurstCount)
.def_readwrite("t1sSymbolType", &EthernetMessage::t1sSymbolType)
.def("get_destination_mac", &EthernetMessage::getDestinationMAC, pybind11::return_value_policy::reference) .def("get_destination_mac", &EthernetMessage::getDestinationMAC, pybind11::return_value_policy::reference)
.def("get_source_mac", &EthernetMessage::getSourceMAC, pybind11::return_value_policy::reference) .def("get_source_mac", &EthernetMessage::getSourceMAC, pybind11::return_value_policy::reference)
.def("get_ether_type", &EthernetMessage::getEtherType); .def("get_ether_type", &EthernetMessage::getEtherType);
@@ -7,7 +7,7 @@
namespace icsneo { namespace icsneo {
void init_ethernetstatusmessage(pybind11::module_& m) { void init_ethernetstatusmessage(pybind11::module_& m) {
pybind11::class_<EthernetStatusMessage, std::shared_ptr<EthernetStatusMessage>, Message> ethernetStatusMessage(m, "EthernetStatusMessage"); pybind11::classh<EthernetStatusMessage, Message> ethernetStatusMessage(m, "EthernetStatusMessage");
pybind11::enum_<EthernetStatusMessage::LinkSpeed>(ethernetStatusMessage, "LinkSpeed") pybind11::enum_<EthernetStatusMessage::LinkSpeed>(ethernetStatusMessage, "LinkSpeed")
.value("LinkSpeedAuto", EthernetStatusMessage::LinkSpeed::LinkSpeedAuto) .value("LinkSpeedAuto", EthernetStatusMessage::LinkSpeed::LinkSpeedAuto)
@@ -22,7 +22,8 @@ void init_ethernetstatusmessage(pybind11::module_& m) {
.value("LinkModeAuto", EthernetStatusMessage::LinkMode::LinkModeAuto) .value("LinkModeAuto", EthernetStatusMessage::LinkMode::LinkModeAuto)
.value("LinkModeMaster", EthernetStatusMessage::LinkMode::LinkModeMaster) .value("LinkModeMaster", EthernetStatusMessage::LinkMode::LinkModeMaster)
.value("LinkModeSlave", EthernetStatusMessage::LinkMode::LinkModeSlave) .value("LinkModeSlave", EthernetStatusMessage::LinkMode::LinkModeSlave)
.value("LinkModeInvalid", EthernetStatusMessage::LinkMode::LinkModeInvalid); .value("LinkModeInvalid", EthernetStatusMessage::LinkMode::LinkModeInvalid)
.value("LinkModeNone", EthernetStatusMessage::LinkMode::LinkModeNone);
ethernetStatusMessage ethernetStatusMessage
.def_readonly("network", &EthernetStatusMessage::network) .def_readonly("network", &EthernetStatusMessage::network)
@@ -0,0 +1,34 @@
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <pybind11/functional.h>
#include "icsneo/communication/message/ethphymessage.h"
namespace icsneo {
void init_ethphymessage(pybind11::module_& m) {
pybind11::classh<Clause22Message>(m, "Clause22Message")
.def_readwrite("phyAddr", &Clause22Message::phyAddr)
.def_readwrite("page", &Clause22Message::page)
.def_readwrite("regAddr", &Clause22Message::regAddr)
.def_readwrite("regVal", &Clause22Message::regVal);
pybind11::classh<Clause45Message>(m, "Clause45Message")
.def_readwrite("port", &Clause45Message::port)
.def_readwrite("device", &Clause45Message::device)
.def_readwrite("regAddr", &Clause45Message::regAddr)
.def_readwrite("regVal", &Clause45Message::regVal);
pybind11::classh<PhyMessage>(m, "PhyMessage")
.def(pybind11::init())
.def_readwrite("Enabled", &PhyMessage::Enabled)
.def_readwrite("WriteEnable", &PhyMessage::WriteEnable)
.def_readwrite("Clause45Enable", &PhyMessage::Clause45Enable)
.def_readwrite("Version", &PhyMessage::Version)
.def_readwrite("BusIndex", &PhyMessage::BusIndex)
.def_readwrite("Clause22", &PhyMessage::Clause22)
.def_readwrite("Clause45", &PhyMessage::Clause45);
pybind11::classh<EthPhyMessage, Message>(m, "EthPhyMessage")
.def(pybind11::init())
.def_readwrite("messages", &EthPhyMessage::messages);
}
} // namespace icsneo
@@ -7,7 +7,7 @@
namespace icsneo { namespace icsneo {
void init_messagefilter(pybind11::module_& m) { void init_messagefilter(pybind11::module_& m) {
pybind11::class_<MessageFilter, std::shared_ptr<MessageFilter>>(m, "MessageFilter") pybind11::classh<MessageFilter>(m, "MessageFilter")
.def(pybind11::init()) .def(pybind11::init())
.def(pybind11::init<Message::Type>()) .def(pybind11::init<Message::Type>())
.def(pybind11::init<Network::NetID>()); .def(pybind11::init<Network::NetID>());
@@ -1,57 +0,0 @@
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <pybind11/functional.h>
#include "icsneo/communication/message/flexray/flexraymessage.h"
#include "icsneo/device/extensions/flexray/symbol.h"
#include "icsneo/device/extensions/flexray/channel.h"
#include "icsneo/device/extensions/flexray/crcstatus.h"
namespace icsneo {
struct FlexRayNamespace {
using Symbol = icsneo::FlexRay::Symbol;
using CRCStatus = icsneo::FlexRay::CRCStatus;
using Channel = icsneo::FlexRay::Channel;
};
void init_flexraymessage(pybind11::module_& m) {
// dummy class to hold the enums
pybind11::class_<FlexRayNamespace> flexray(m, "FlexRay");
// enumerations
pybind11::enum_<FlexRayNamespace::Symbol>(flexray, "Symbol")
.value("None", FlexRayNamespace::Symbol::None)
.value("Unknown", FlexRayNamespace::Symbol::Unknown)
.value("Wakeup", FlexRayNamespace::Symbol::Wakeup)
.value("CAS", FlexRayNamespace::Symbol::CAS);
pybind11::enum_<FlexRayNamespace::CRCStatus>(flexray, "CRCStatus")
.value("OK", FlexRayNamespace::CRCStatus::OK)
.value("Error", FlexRayNamespace::CRCStatus::Error)
.value("NoCRC", FlexRayNamespace::CRCStatus::NoCRC);
pybind11::enum_<FlexRayNamespace::Channel>(flexray, "Channel")
.value("None", FlexRayNamespace::Channel::None)
.value("A", FlexRayNamespace::Channel::A)
.value("B", FlexRayNamespace::Channel::B)
.value("AB", FlexRayNamespace::Channel::AB);
// read-only until transmit is supported
pybind11::class_<FlexRayMessage, std::shared_ptr<FlexRayMessage>, Frame>(m, "FlexRayMessage")
.def(pybind11::init())
.def_readonly("slotid", &FlexRayMessage::slotid)
.def_readonly("tsslen", &FlexRayMessage::tsslen)
.def_readonly("framelen", &FlexRayMessage::framelen)
.def_readonly("symbol", &FlexRayMessage::symbol)
.def_readonly("header_crc_status", &FlexRayMessage::headerCRCStatus)
.def_readonly("header_crc", &FlexRayMessage::headerCRC)
.def_readonly("frame_crc_status", &FlexRayMessage::crcStatus)
.def_readonly("frame_crc", &FlexRayMessage::frameCRC)
.def_readonly("channel", &FlexRayMessage::channel)
.def_readonly("null_frame", &FlexRayMessage::nullFrame)
.def_readonly("payload_preamble", &FlexRayMessage::payloadPreamble)
.def_readonly("sync_frame", &FlexRayMessage::sync)
.def_readonly("startup_frame", &FlexRayMessage::startup)
.def_readonly("dynamic_frame", &FlexRayMessage::dynamic)
.def_readonly("cycle", &FlexRayMessage::cycle);
}
} // namespace icsneo
@@ -7,72 +7,73 @@
namespace icsneo { namespace icsneo {
void init_gptpstatusmessage(pybind11::module_& m) { void init_gptpstatusmessage(pybind11::module_& m) {
pybind11::class_<GPTPStatus, std::shared_ptr<GPTPStatus>, Message> gptpStatus(m, "GPTPStatus"); pybind11::classh<GPTPStatus, Message> gptpStatus(m, "GPTPStatus");
pybind11::class_<GPTPStatus::Timestamp>(gptpStatus, "Timestamp") pybind11::classh<GPTPStatus::Timestamp>(gptpStatus, "Timestamp")
.def_readonly("seconds", &GPTPStatus::Timestamp::seconds) .def_readonly("seconds", &GPTPStatus::Timestamp::seconds)
.def_readonly("nanoseconds", &GPTPStatus::Timestamp::nanoseconds) .def_readonly("nanoseconds", &GPTPStatus::Timestamp::nanoseconds)
.def("to_seconds", &GPTPStatus::Timestamp::toSeconds, pybind11::call_guard<pybind11::gil_scoped_release>()); .def("to_seconds", &GPTPStatus::Timestamp::toSeconds, pybind11::call_guard<pybind11::gil_scoped_release>());
pybind11::class_<GPTPStatus::ScaledNanoSeconds>(gptpStatus, "ScaledNanoSeconds") pybind11::classh<GPTPStatus::ScaledNanoSeconds>(gptpStatus, "ScaledNanoSeconds")
.def_readonly("nanosecondsMSB", &GPTPStatus::ScaledNanoSeconds::nanosecondsMSB) .def_readonly("nanoseconds_msb", &GPTPStatus::ScaledNanoSeconds::nanosecondsMSB)
.def_readonly("nanosecondsLSB", &GPTPStatus::ScaledNanoSeconds::nanosecondsLSB) .def_readonly("nanoseconds_lsb", &GPTPStatus::ScaledNanoSeconds::nanosecondsLSB)
.def_readonly("fractionalNanoseconds", &GPTPStatus::ScaledNanoSeconds::fractionalNanoseconds); .def_readonly("fractional_nanoseconds", &GPTPStatus::ScaledNanoSeconds::fractionalNanoseconds);
pybind11::class_<GPTPStatus::PortID>(gptpStatus, "PortID") pybind11::classh<GPTPStatus::PortID>(gptpStatus, "PortID")
.def_readonly("clockIdentity", &GPTPStatus::PortID::clockIdentity) .def_readonly("clock_identity", &GPTPStatus::PortID::clockIdentity)
.def_readonly("portNumber", &GPTPStatus::PortID::portNumber); .def_readonly("port_number", &GPTPStatus::PortID::portNumber);
pybind11::class_<GPTPStatus::ClockQuality>(gptpStatus, "ClockQuality") pybind11::classh<GPTPStatus::ClockQuality>(gptpStatus, "ClockQuality")
.def_readonly("clockClass", &GPTPStatus::ClockQuality::clockClass) .def_readonly("clock_class", &GPTPStatus::ClockQuality::clockClass)
.def_readonly("clockAccuracy", &GPTPStatus::ClockQuality::clockAccuracy) .def_readonly("clock_accuracy", &GPTPStatus::ClockQuality::clockAccuracy)
.def_readonly("offsetScaledLogVariance", &GPTPStatus::ClockQuality::offsetScaledLogVariance); .def_readonly("offset_scaled_log_variance", &GPTPStatus::ClockQuality::offsetScaledLogVariance);
pybind11::class_<GPTPStatus::SystemID>(gptpStatus, "SystemID") pybind11::classh<GPTPStatus::SystemID>(gptpStatus, "SystemID")
.def_readonly("priority1", &GPTPStatus::SystemID::priority1) .def_readonly("priority1", &GPTPStatus::SystemID::priority1)
.def_readonly("clockQuality", &GPTPStatus::SystemID::clockQuality) .def_readonly("clock_quality", &GPTPStatus::SystemID::clockQuality)
.def_readonly("priority2", &GPTPStatus::SystemID::priority2) .def_readonly("priority2", &GPTPStatus::SystemID::priority2)
.def_readonly("clockID", &GPTPStatus::SystemID::clockID); .def_readonly("clock_id", &GPTPStatus::SystemID::clockID);
pybind11::class_<GPTPStatus::PriorityVector>(gptpStatus, "PriorityVector") pybind11::classh<GPTPStatus::PriorityVector>(gptpStatus, "PriorityVector")
.def_readonly("sysID", &GPTPStatus::PriorityVector::sysID) .def_readonly("sys_id", &GPTPStatus::PriorityVector::sysID)
.def_readonly("stepsRemoved", &GPTPStatus::PriorityVector::stepsRemoved) .def_readonly("steps_removed", &GPTPStatus::PriorityVector::stepsRemoved)
.def_readonly("portID", &GPTPStatus::PriorityVector::portID) .def_readonly("port_id", &GPTPStatus::PriorityVector::portID)
.def_readonly("portNumber", &GPTPStatus::PriorityVector::portNumber); .def_readonly("port_number", &GPTPStatus::PriorityVector::portNumber);
pybind11::class_<GPTPStatus::ParentDS>(gptpStatus, "ParentDS") pybind11::classh<GPTPStatus::ParentDS>(gptpStatus, "ParentDS")
.def_readonly("parentPortIdentity", &GPTPStatus::ParentDS::parentPortIdentity) .def_readonly("parent_port_identity", &GPTPStatus::ParentDS::parentPortIdentity)
.def_readonly("cumulativeRateRatio", &GPTPStatus::ParentDS::cumulativeRateRatio) .def_readonly("cumulative_rate_ratio", &GPTPStatus::ParentDS::cumulativeRateRatio)
.def_readonly("grandmasterIdentity", &GPTPStatus::ParentDS::grandmasterIdentity) .def_readonly("grandmaster_identity", &GPTPStatus::ParentDS::grandmasterIdentity)
.def_readonly("gmClockQualityClockClass", &GPTPStatus::ParentDS::gmClockQualityClockClass) .def_readonly("gm_clock_quality_clock_class", &GPTPStatus::ParentDS::gmClockQualityClockClass)
.def_readonly("gmClockQualityClockAccuracy", &GPTPStatus::ParentDS::gmClockQualityClockAccuracy) .def_readonly("gm_clock_quality_clock_accuracy", &GPTPStatus::ParentDS::gmClockQualityClockAccuracy)
.def_readonly("gmClockQualityOffsetScaledLogVariance", &GPTPStatus::ParentDS::gmClockQualityOffsetScaledLogVariance) .def_readonly("gm_clock_quality_offset_scaled_log_variance", &GPTPStatus::ParentDS::gmClockQualityOffsetScaledLogVariance)
.def_readonly("gmPriority1", &GPTPStatus::ParentDS::gmPriority1) .def_readonly("gm_priority1", &GPTPStatus::ParentDS::gmPriority1)
.def_readonly("gmPriority2", &GPTPStatus::ParentDS::gmPriority2); .def_readonly("gm_priority2", &GPTPStatus::ParentDS::gmPriority2);
pybind11::class_<GPTPStatus::CurrentDS>(gptpStatus, "CurrentDS") pybind11::classh<GPTPStatus::CurrentDS>(gptpStatus, "CurrentDS")
.def_readonly("stepsRemoved", &GPTPStatus::CurrentDS::stepsRemoved) .def_readonly("steps_removed", &GPTPStatus::CurrentDS::stepsRemoved)
.def_readonly("offsetFromMaster", &GPTPStatus::CurrentDS::offsetFromMaster) .def_readonly("offset_from_master", &GPTPStatus::CurrentDS::offsetFromMaster)
.def_readonly("lastgmPhaseChange", &GPTPStatus::CurrentDS::lastgmPhaseChange) .def_readonly("lastgm_phase_change", &GPTPStatus::CurrentDS::lastgmPhaseChange)
.def_readonly("lastgmFreqChange", &GPTPStatus::CurrentDS::lastgmFreqChange) .def_readonly("lastgm_freq_change", &GPTPStatus::CurrentDS::lastgmFreqChange)
.def_readonly("gmTimeBaseIndicator", &GPTPStatus::CurrentDS::gmTimeBaseIndicator) .def_readonly("gm_time_base_indicator", &GPTPStatus::CurrentDS::gmTimeBaseIndicator)
.def_readonly("gmChangeCount", &GPTPStatus::CurrentDS::gmChangeCount) .def_readonly("gm_change_count", &GPTPStatus::CurrentDS::gmChangeCount)
.def_readonly("timeOfLastgmChangeEvent", &GPTPStatus::CurrentDS::timeOfLastgmChangeEvent) .def_readonly("time_of_lastgm_change_event", &GPTPStatus::CurrentDS::timeOfLastgmChangeEvent)
.def_readonly("timeOfLastgmPhaseChangeEvent", &GPTPStatus::CurrentDS::timeOfLastgmPhaseChangeEvent) .def_readonly("time_of_lastgm_phase_change_event", &GPTPStatus::CurrentDS::timeOfLastgmPhaseChangeEvent)
.def_readonly("timeOfLastgmFreqChangeEvent", &GPTPStatus::CurrentDS::timeOfLastgmFreqChangeEvent); .def_readonly("time_of_lastgm_freq_change_event", &GPTPStatus::CurrentDS::timeOfLastgmFreqChangeEvent);
gptpStatus.def_readonly("currentTime", &GPTPStatus::currentTime) gptpStatus.def_readonly("current_time", &GPTPStatus::currentTime)
.def_readonly("gmPriority", &GPTPStatus::gmPriority) .def_readonly("gm_priority", &GPTPStatus::gmPriority)
.def_readonly("msOffsetNs", &GPTPStatus::msOffsetNs) .def_readonly("ms_offset_ns", &GPTPStatus::msOffsetNs)
.def_readonly("isSync", &GPTPStatus::isSync) .def_readonly("is_sync", &GPTPStatus::isSync)
.def_readonly("linkStatus", &GPTPStatus::linkStatus) .def_readonly("link_status", &GPTPStatus::linkStatus)
.def_readonly("linkDelayNS", &GPTPStatus::linkDelayNS) .def_readonly("link_delay_ns", &GPTPStatus::linkDelayNS)
.def_readonly("selectedRole", &GPTPStatus::selectedRole) .def_readonly("selected_role", &GPTPStatus::selectedRole)
.def_readonly("asCapable", &GPTPStatus::asCapable) .def_readonly("as_capable", &GPTPStatus::asCapable)
.def_readonly("isSyntonized", &GPTPStatus::isSyntonized) .def_readonly("is_syntonized", &GPTPStatus::isSyntonized)
.def_readonly("lastRXSyncTS", &GPTPStatus::lastRXSyncTS) .def_readonly("last_rx_sync_ts", &GPTPStatus::lastRXSyncTS)
.def_readonly("currentDS", &GPTPStatus::currentDS) .def_readonly("current_ds", &GPTPStatus::currentDS)
.def_readonly("parentDS", &GPTPStatus::parentDS); .def_readonly("parent_ds", &GPTPStatus::parentDS)
.def_readonly("short_format", &GPTPStatus::shortFormat);
} }
@@ -7,7 +7,7 @@
namespace icsneo { namespace icsneo {
void init_linmessage(pybind11::module_& m) { void init_linmessage(pybind11::module_& m) {
pybind11::class_<LINErrorFlags>(m, "LINErrorFlags") pybind11::classh<LINErrorFlags>(m, "LINErrorFlags")
.def_readwrite("ErrRxBreakOnly", &LINErrorFlags::ErrRxBreakOnly) .def_readwrite("ErrRxBreakOnly", &LINErrorFlags::ErrRxBreakOnly)
.def_readwrite("ErrRxBreakSyncOnly", &LINErrorFlags::ErrRxBreakSyncOnly) .def_readwrite("ErrRxBreakSyncOnly", &LINErrorFlags::ErrRxBreakSyncOnly)
.def_readwrite("ErrTxRxMismatch", &LINErrorFlags::ErrTxRxMismatch) .def_readwrite("ErrTxRxMismatch", &LINErrorFlags::ErrTxRxMismatch)
@@ -20,7 +20,7 @@ void init_linmessage(pybind11::module_& m) {
.def_readwrite("ErrFrameResponderData", &LINErrorFlags::ErrFrameResponderData) .def_readwrite("ErrFrameResponderData", &LINErrorFlags::ErrFrameResponderData)
.def_readwrite("ErrChecksumMatch", &LINErrorFlags::ErrChecksumMatch); .def_readwrite("ErrChecksumMatch", &LINErrorFlags::ErrChecksumMatch);
pybind11::class_<LINStatusFlags>(m, "LINStatusFlags") pybind11::classh<LINStatusFlags>(m, "LINStatusFlags")
.def_readwrite("TxChecksumEnhanced", &LINStatusFlags::TxChecksumEnhanced) .def_readwrite("TxChecksumEnhanced", &LINStatusFlags::TxChecksumEnhanced)
.def_readwrite("TxCommander", &LINStatusFlags::TxCommander) .def_readwrite("TxCommander", &LINStatusFlags::TxCommander)
.def_readwrite("TxResponder", &LINStatusFlags::TxResponder) .def_readwrite("TxResponder", &LINStatusFlags::TxResponder)
@@ -30,7 +30,7 @@ void init_linmessage(pybind11::module_& m) {
.def_readwrite("BusRecovered", &LINStatusFlags::BusRecovered) .def_readwrite("BusRecovered", &LINStatusFlags::BusRecovered)
.def_readwrite("BreakOnly", &LINStatusFlags::BreakOnly); .def_readwrite("BreakOnly", &LINStatusFlags::BreakOnly);
pybind11::class_<LINMessage, std::shared_ptr<LINMessage>, Frame> linMessage(m, "LINMessage"); pybind11::classh<LINMessage, Frame> linMessage(m, "LINMessage");
pybind11::enum_<LINMessage::Type>(linMessage, "Type") pybind11::enum_<LINMessage::Type>(linMessage, "Type")
.value("NOT_SET", LINMessage::Type::NOT_SET) .value("NOT_SET", LINMessage::Type::NOT_SET)
@@ -0,0 +1,50 @@
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <pybind11/functional.h>
#include <pybind11/chrono.h>
#include "icsneo/communication/message/livedatamessage.h"
namespace icsneo {
void init_livedatamessage(pybind11::module_& m) {
// LiveDataMessage base class
pybind11::classh<LiveDataMessage, RawMessage>(m, "LiveDataMessage")
.def(pybind11::init<>())
.def_readwrite("handle", &LiveDataMessage::handle)
.def_readwrite("cmd", &LiveDataMessage::cmd);
// LiveDataCommandMessage (for subscribe/unsubscribe)
pybind11::classh<LiveDataCommandMessage, LiveDataMessage>(m, "LiveDataCommandMessage")
.def(pybind11::init<>())
.def_readwrite("update_period", &LiveDataCommandMessage::updatePeriod)
.def_readwrite("expiration_time", &LiveDataCommandMessage::expirationTime)
.def_readwrite("args", &LiveDataCommandMessage::args)
.def("append_signal_arg", &LiveDataCommandMessage::appendSignalArg,
pybind11::arg("value_type"),
"Append a signal argument to the command message");
// LiveDataValueMessage (received values)
pybind11::classh<LiveDataValueMessage, LiveDataMessage>(m, "LiveDataValueMessage")
.def(pybind11::init<>())
.def_readwrite("num_args", &LiveDataValueMessage::numArgs)
.def_readwrite("values", &LiveDataValueMessage::values);
// LiveDataStatusMessage (status responses)
pybind11::classh<LiveDataStatusMessage, LiveDataMessage>(m, "LiveDataStatusMessage")
.def(pybind11::init<>())
.def_readwrite("requested_command", &LiveDataStatusMessage::requestedCommand)
.def_readwrite("status", &LiveDataStatusMessage::status);
// LiveDataSetValueMessage (for setting values)
pybind11::classh<LiveDataSetValueMessage, LiveDataMessage>(m, "LiveDataSetValueMessage")
.def(pybind11::init<>())
.def_readwrite("args", &LiveDataSetValueMessage::args)
.def_readwrite("values", &LiveDataSetValueMessage::values)
.def("append_set_value", &LiveDataSetValueMessage::appendSetValue,
pybind11::arg("value_type"),
pybind11::arg("value"),
"Append a value to set in the message");
}
} // namespace icsneo
@@ -1,160 +0,0 @@
#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
@@ -7,7 +7,7 @@
namespace icsneo { namespace icsneo {
void init_mdiomessage(pybind11::module_& m) { void init_mdiomessage(pybind11::module_& m) {
pybind11::class_<MDIOMessage, std::shared_ptr<MDIOMessage>, Frame> mdioMessage(m, "MDIOMessage"); pybind11::classh<MDIOMessage, Frame> mdioMessage(m, "MDIOMessage");
pybind11::enum_<MDIOMessage::Clause>(mdioMessage, "Clause") pybind11::enum_<MDIOMessage::Clause>(mdioMessage, "Clause")
.value("Clause45", MDIOMessage::Clause::Clause45) .value("Clause45", MDIOMessage::Clause::Clause45)
.value("Clause22", MDIOMessage::Clause::Clause22); .value("Clause22", MDIOMessage::Clause::Clause22);
@@ -1,14 +1,16 @@
#include <pybind11/pybind11.h> #include <pybind11/pybind11.h>
#include <pybind11/stl.h> #include <pybind11/stl.h>
#include <pybind11/functional.h> #include <pybind11/functional.h>
#include <pybind11/native_enum.h>
#include "icsneo/communication/message/message.h" #include "icsneo/communication/message/message.h"
namespace icsneo { namespace icsneo {
void init_message(pybind11::module_& m) { void init_message(pybind11::module_& m) {
pybind11::class_<Message, std::shared_ptr<Message>> message(m, "Message"); // Using py::smart_holder for safer lifetime management
pybind11::enum_<Message::Type>(message, "Type") pybind11::classh<Message> message(m, "Message");
pybind11::native_enum<Message::Type>(message, "Type", "enum.IntEnum")
.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("CANError", Message::Type::CANError)
@@ -34,17 +36,18 @@ void init_message(pybind11::module_& m) {
.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("GPTPStatus", Message::Type::GPTPStatus)
.value("EthernetStatus", Message::Type::EthernetStatus); .value("EthernetStatus", Message::Type::EthernetStatus)
.finalize();
message.def(pybind11::init<Message::Type>()); message.def(pybind11::init<Message::Type>());
message.def_readonly("type", &Message::type); message.def_readonly("type", &Message::type);
message.def_readwrite("timestamp", &Message::timestamp); message.def_readwrite("timestamp", &Message::timestamp);
pybind11::class_<RawMessage, std::shared_ptr<RawMessage>, Message>(m, "RawMessage") pybind11::classh<RawMessage, Message>(m, "RawMessage")
.def_readwrite("network", &RawMessage::network) .def_readwrite("network", &RawMessage::network)
.def_readwrite("data", &RawMessage::data); .def_readwrite("data", &RawMessage::data);
pybind11::class_<Frame, std::shared_ptr<Frame>, RawMessage>(m, "Frame") pybind11::classh<Frame, RawMessage>(m, "Frame")
.def_readwrite("description", &Frame::description) .def_readwrite("description", &Frame::description)
.def_readwrite("transmitted", &Frame::transmitted) .def_readwrite("transmitted", &Frame::transmitted)
.def_readwrite("error", &Frame::error); .def_readwrite("error", &Frame::error);
@@ -7,7 +7,7 @@
namespace icsneo { namespace icsneo {
void init_scriptstatusmessage(pybind11::module_& m) { void init_scriptstatusmessage(pybind11::module_& m) {
pybind11::class_<ScriptStatusMessage, std::shared_ptr<ScriptStatusMessage>, Message>(m, "ScriptStatusMessage") pybind11::classh<ScriptStatusMessage, Message>(m, "ScriptStatusMessage")
.def_readonly("isEncrypted", &ScriptStatusMessage::isEncrypted) .def_readonly("isEncrypted", &ScriptStatusMessage::isEncrypted)
.def_readonly("isCoreminiRunning", &ScriptStatusMessage::isCoreminiRunning) .def_readonly("isCoreminiRunning", &ScriptStatusMessage::isCoreminiRunning)
.def_readonly("sectorOverflows", &ScriptStatusMessage::sectorOverflows) .def_readonly("sectorOverflows", &ScriptStatusMessage::sectorOverflows)
@@ -0,0 +1,24 @@
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <pybind11/functional.h>
#include "icsneo/communication/message/spimessage.h"
namespace icsneo {
void init_spimessage(pybind11::module_& m) {
pybind11::classh<SPIMessage, Frame> spiMessage(m, "SPIMessage");
pybind11::enum_<SPIMessage::Direction>(spiMessage, "Direction")
.value("Write", SPIMessage::Direction::Write)
.value("Read", SPIMessage::Direction::Read);
spiMessage
.def(pybind11::init())
.def_readwrite("direction", &SPIMessage::direction)
.def_readwrite("address", &SPIMessage::address)
.def_readwrite("mms", &SPIMessage::mms)
.def_readwrite("stats", &SPIMessage::stats)
.def_readwrite("payload", &SPIMessage::payload);
}
} // namespace icsneo
@@ -17,7 +17,7 @@ void init_tc10statusmessage(pybind11::module_& m) {
.value("SleepFailed", TC10SleepStatus::SleepFailed) .value("SleepFailed", TC10SleepStatus::SleepFailed)
.value("SleepAborted", TC10SleepStatus::SleepAborted); .value("SleepAborted", TC10SleepStatus::SleepAborted);
pybind11::class_<TC10StatusMessage, std::shared_ptr<TC10StatusMessage>, Message>(m, "TC10StatusMessage") pybind11::classh<TC10StatusMessage, Message>(m, "TC10StatusMessage")
.def_readonly("wakeStatus", &TC10StatusMessage::wakeStatus) .def_readonly("wakeStatus", &TC10StatusMessage::wakeStatus)
.def_readonly("sleepStatus", &TC10StatusMessage::sleepStatus); .def_readonly("sleepStatus", &TC10StatusMessage::sleepStatus);
} }
@@ -1,15 +1,16 @@
#include <pybind11/pybind11.h> #include <pybind11/pybind11.h>
#include <pybind11/stl.h> #include <pybind11/stl.h>
#include <pybind11/functional.h> #include <pybind11/functional.h>
#include <pybind11/native_enum.h>
#include "icsneo/communication/network.h" #include "icsneo/communication/network.h"
namespace icsneo { namespace icsneo {
void init_network(pybind11::module_& m) { void init_network(pybind11::module_& m) {
pybind11::class_<Network> network(m, "Network"); pybind11::classh<Network> network(m, "Network");
pybind11::enum_<Network::NetID>(network, "NetID") pybind11::native_enum<Network::NetID>(network, "NetID", "enum.IntEnum")
.value("Device", Network::NetID::Device) .value("Device", Network::NetID::Device)
.value("DWCAN_01", Network::NetID::DWCAN_01) .value("DWCAN_01", Network::NetID::DWCAN_01)
.value("DWCAN_08", Network::NetID::DWCAN_08) .value("DWCAN_08", Network::NetID::DWCAN_08)
@@ -166,9 +167,10 @@ void init_network(pybind11::module_& m) {
.value("LIN_15", Network::NetID::LIN_15) .value("LIN_15", Network::NetID::LIN_15)
.value("LIN_16", Network::NetID::LIN_16) .value("LIN_16", Network::NetID::LIN_16)
.value("Any", Network::NetID::Any) .value("Any", Network::NetID::Any)
.value("Invalid", Network::NetID::Invalid); .value("Invalid", Network::NetID::Invalid)
.finalize();
pybind11::enum_<Network::Type>(network, "Type") pybind11::native_enum<Network::Type>(network, "Type", "enum.Enum")
.value("Invalid", Network::Type::Invalid) .value("Invalid", Network::Type::Invalid)
.value("Internal", Network::Type::Internal) .value("Internal", Network::Type::Internal)
.value("CAN", Network::Type::CAN) .value("CAN", Network::Type::CAN)
@@ -179,12 +181,14 @@ void init_network(pybind11::module_& m) {
.value("LSFTCAN", Network::Type::LSFTCAN) .value("LSFTCAN", Network::Type::LSFTCAN)
.value("SWCAN", Network::Type::SWCAN) .value("SWCAN", Network::Type::SWCAN)
.value("ISO9141", Network::Type::ISO9141) .value("ISO9141", Network::Type::ISO9141)
.value("I2C_01", Network::Type::I2C) .value("I2C", Network::Type::I2C)
.value("A2B", Network::Type::A2B) .value("A2B", Network::Type::A2B)
.value("SPI", Network::Type::SPI) .value("SPI", Network::Type::SPI)
.value("MDIO", Network::Type::MDIO) .value("MDIO", Network::Type::MDIO)
.value("AutomotiveEthernet", Network::Type::AutomotiveEthernet)
.value("Any", Network::Type::Any) .value("Any", Network::Type::Any)
.value("Other", Network::Type::Other); .value("Other", Network::Type::Other)
.finalize();
network network
.def(pybind11::init<Network::NetID>()) .def(pybind11::init<Network::NetID>())
+166
View File
@@ -0,0 +1,166 @@
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <pybind11/functional.h>
#include "icsneo/core/macseccfg.h"
namespace icsneo {
void init_macsecconfig(pybind11::module_ & m)
{
pybind11::enum_<MACsecPacketType>(m, "MACsecPacketType")
.value("DEFAULT", MACsecPacketType::Default)
.value("SINGLE_VLAN", MACsecPacketType::SingleVLAN)
.value("DUAL_VLAN", MACsecPacketType::DualVLAN)
.value("MPLS", MACsecPacketType::MPLS)
.value("SINGLE_VLAN_FOLLOWED_BY_MPLS", MACsecPacketType::SingleVLANFollowedByMPLS)
.value("DUAL_VLAN_FOLLOWED_BY_MPLS", MACsecPacketType::DualVLANFollowedByMPLS)
.value("UNSUPPORTED", MACsecPacketType::Unsupported);
pybind11::enum_<MACsecValidation>(m, "MACsecValidation")
.value("DISABLED", MACsecValidation::Disabled)
.value("CHECK", MACsecValidation::Check)
.value("STRICT", MACsecValidation::Strict)
.value("NA", MACsecValidation::NA);
pybind11::enum_<MACsecStrip>(m, "MACsecStrip")
.value("STRIP_SECTAG_AND_ICV", MACsecStrip::StripSecTagAndIcv)
.value("STRIP_SECTAG_PRESERVE_ICV", MACsecStrip::StripSecTagPreserveICV)
.value("PRESERVE_SECTAG_STRIP_ICV", MACsecStrip::PreserveSecTagStripICV)
.value("NO_STRIP", MACsecStrip::NoStrip);
pybind11::enum_<MACsecCipherSuite>(m, "MACsecCipherSuite")
.value("GCM_AES_128", MACsecCipherSuite::GcmAes128)
.value("GCM_AES_256", MACsecCipherSuite::GcmAes256)
.value("GCM_AES_128_XPN", MACsecCipherSuite::GcmAes128Xpn)
.value("GCM_AES_256_XPN", MACsecCipherSuite::GcmAes256Xpn);
pybind11::classh<MACsecVLANTag>(m, "MACsecVLANTag")
.def(pybind11::init())
.def_readwrite("vid", &MACsecVLANTag::vid)
.def_readwrite("pri_cfi", &MACsecVLANTag::priCfi);
pybind11::classh<MACsecMPLSOuter>(m, "MACsecMPLSOuter")
.def(pybind11::init())
.def_readwrite("mpls_label", &MACsecMPLSOuter::mplsLabel)
.def_readwrite("exp", &MACsecMPLSOuter::exp);
pybind11::classh<MACsecTci>(m, "MACsecTci")
.def(pybind11::init())
.def_readwrite("es", &MACsecTci::es)
.def_readwrite("sc", &MACsecTci::sc)
.def_readwrite("scb", &MACsecTci::scb)
.def_readwrite("e", &MACsecTci::e)
.def_readwrite("c", &MACsecTci::c);
pybind11::classh<MACsecRxRule>(m, "MACsecRxRule")
.def(pybind11::init())
.def_readwrite("key_mac_da", &MACsecRxRule::keyMacDa)
.def_readwrite("mask_mac_da", &MACsecRxRule::maskMacDa)
.def_readwrite("key_mask_sa", &MACsecRxRule::keyMacSa)
.def_readwrite("mask_mac_sa", &MACsecRxRule::maskMacSa)
.def_readwrite("key_ether_type", &MACsecRxRule::keyEthertype)
.def_readwrite("mask_ether_type", &MACsecRxRule::maskEthertype)
.def_readwrite("key_vlan_tag_outer1", &MACsecRxRule::keyVlanTagOuter1)
.def_readwrite("key_mpls_outer1", &MACsecRxRule::keyMplsOuter1)
.def_readwrite("mask_vlan_tag_outer1", &MACsecRxRule::maskVlanTagOuter1)
.def_readwrite("mask_mpls_outer1", &MACsecRxRule::maskMplsOuter1)
.def_readwrite("key_vlan_tag_outer2", &MACsecRxRule::keyVlanTagOuter2)
.def_readwrite("key_mpls_outer2", &MACsecRxRule::keyMplsOuter2)
.def_readwrite("mask_vlan_tag_outer2", &MACsecRxRule::maskVlanTagOuter2)
.def_readwrite("mask_mpls_outer2", &MACsecRxRule::maskMplsOuter2)
.def_readwrite("key_bonus_data", &MACsecRxRule::keyBonusData)
.def_readwrite("mask_bonus_data", &MACsecRxRule::maskBonusData)
.def_readwrite("key_tag_match_bitmap", &MACsecRxRule::keyTagMatchBitmap)
.def_readwrite("mask_tag_match_bitmap", &MACsecRxRule::maskTagMatchBitmap)
.def_readwrite("key_packet_type", &MACsecRxRule::keyPacketType)
.def_readwrite("mask_packet_type", &MACsecRxRule::maskPacketType)
.def_readwrite("key_inner_vlan_type", &MACsecRxRule::keyInnerVlanType)
.def_readwrite("mask_inner_vlan_type", &MACsecRxRule::maskInnerVlanType)
.def_readwrite("key_outer_vlan_type", &MACsecRxRule::keyOuterVlanType)
.def_readwrite("mask_outer_vlan_type", &MACsecRxRule::maskOuterVlanType)
.def_readwrite("key_num_tags", &MACsecRxRule::keyNumTags)
.def_readwrite("mask_num_tags", &MACsecRxRule::maskNumTags)
.def_readwrite("key_express", &MACsecRxRule::keyExpress)
.def_readwrite("mask_express", &MACsecRxRule::maskExpress)
.def_readwrite("is_mpls", &MACsecRxRule::isMpls);
pybind11::classh<MACsecTxSecY>(m, "MACsecTxSecY")
.def(pybind11::init())
.def_readwrite("enable_control_port", &MACsecTxSecY::enableControlPort)
.def_readwrite("cipher", &MACsecTxSecY::cipher)
.def_readwrite("confidentiality_offset", &MACsecTxSecY::confidentialityOffset)
.def_readwrite("icv_includes_da_sa", &MACsecTxSecY::icvIncludesDaSa)
.def_readwrite("protect_frames", &MACsecTxSecY::protectFrames)
.def_readwrite("sec_tag_offset", &MACsecTxSecY::secTagOffset)
.def_readwrite("sec_tag_tci", &MACsecTxSecY::tci)
.def_readwrite("mtu", &MACsecTxSecY::mtu)
.def_readwrite("is_control_packet", &MACsecTxSecY::isControlPacket)
.def_readwrite("auxiliary_policy", &MACsecTxSecY::auxiliaryPolicy)
.def_readwrite("sci", &MACsecTxSecY::sci);
pybind11::classh<MACsecRxSecY>(m, "MACsecRxSecY")
.def(pybind11::init())
.def_readwrite("enable_control_port", &MACsecRxSecY::enableControlPort)
.def_readwrite("frame_validation", &MACsecRxSecY::frameValidation)
.def_readwrite("frame_strip", &MACsecRxSecY::frameStrip)
.def_readwrite("cipher", &MACsecRxSecY::cipher)
.def_readwrite("confidentiality_offset", &MACsecRxSecY::confidentialityOffset)
.def_readwrite("icv_includes_da_sa", &MACsecRxSecY::icvIncludesDaSa)
.def_readwrite("replay_protect", &MACsecRxSecY::replayProtect)
.def_readwrite("replay_window", &MACsecRxSecY::replayWindow)
.def_readwrite("is_control_packet", &MACsecRxSecY::isControlPacket)
.def_readwrite("sci", &MACsecRxSecY::sci);
pybind11::classh<MACsecTxSa>(m, "MACsecTxSa")
.def(pybind11::init())
.def_readwrite("sak", &MACsecTxSa::sak)
.def_readwrite("hash_key", &MACsecTxSa::hashKey)
.def_readwrite("salt", &MACsecTxSa::salt)
.def_readwrite("ssci", &MACsecTxSa::ssci)
.def_readwrite("next_pn", &MACsecTxSa::nextPn)
.def_readwrite("an", &MACsecTxSa::an);
pybind11::classh<MACsecRxSa>(m, "MACsecRxSa")
.def(pybind11::init())
.def_readwrite("sak", &MACsecRxSa::sak)
.def_readwrite("hash_key", &MACsecRxSa::hashKey)
.def_readwrite("salt", &MACsecRxSa::salt)
.def_readwrite("ssci", &MACsecRxSa::ssci)
.def_readwrite("next_pn", &MACsecRxSa::nextPn);
pybind11::classh<MACsecConfig>(m, "MACsecConfig")
.def(pybind11::init<icsneo::DeviceType>())
.def("add_rx_secy", &MACsecConfig::addRxSecY, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("add_tx_secY", &MACsecConfig::addTxSecY, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("add_rx_rule", &MACsecConfig::addRxRule, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("add_rx_sa", &MACsecConfig::addRxSa, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("add_tx_sa", &MACsecConfig::addTxSa, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("get_rx_secy", [](MACsecConfig& cfg, uint8_t index) -> MACsecRxSecY& { return cfg.getRxSecY(index); }, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("get_tx_secy", [](MACsecConfig& cfg, uint8_t index) -> MACsecTxSecY& { return cfg.getTxSecY(index); }, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("get_rx_sa", [](MACsecConfig& cfg, uint8_t index) -> MACsecRxSa& { return cfg.getRxSa(index); }, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("get_tx_sa", [](MACsecConfig& cfg, uint8_t index) -> MACsecTxSa& { return cfg.getTxSa(index); }, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("get_rx_rule", [](MACsecConfig& cfg, uint8_t index) -> MACsecRxRule& { return cfg.getRxRule(index); }, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("set_tx_sa_index", &MACsecConfig::setTxSaIndex, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("enable_tx_rekey", &MACsecConfig::enableTxRekey, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("set_tx_sa_rekey_index", &MACsecConfig::setTxSaRekeyIndex, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("disable_tx_rekey", &MACsecConfig::disableTxRekey, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("set_rx_sa_index", &MACsecConfig::setRxSaIndex, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("enable_rx_rekey", &MACsecConfig::enableRxRekey, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("set_rx_sa_rekey_index", &MACsecConfig::setRxSaRekeyIndex, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("disable_rx_rekey", &MACsecConfig::disableRxRekey, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("set_rx_enable", &MACsecConfig::setRxEnable, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("set_tx_enable", &MACsecConfig::setTxEnable, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("set_storage", &MACsecConfig::setStorage, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("clear", &MACsecConfig::clear, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("serialize", &MACsecConfig::serialize, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("get_bin_index", &MACsecConfig::getBinIndex, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("get_type", &MACsecConfig::getType, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("get_max_num_rule", &MACsecConfig::getMaxNumRule, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("get_max_num_secy", &MACsecConfig::getMaxNumSecY, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("get_max_num_sa", &MACsecConfig::getMaxNumSa, pybind11::call_guard<pybind11::gil_scoped_release>());
}
} // namespace icsneo
+138
View File
@@ -0,0 +1,138 @@
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <pybind11/functional.h>
#include <pybind11/native_enum.h>
#include "icsneo/device/chipid.h"
namespace icsneo {
void init_chipid(pybind11::module_& m) {
pybind11::native_enum<ChipID>(m, "ChipID", "enum.IntEnum")
.value("neoVIFIRE_MCHIP", ChipID::neoVIFIRE_MCHIP)
.value("neoVIFIRE_LCHIP", ChipID::neoVIFIRE_LCHIP)
.value("neoVIFIRE_UCHIP", ChipID::neoVIFIRE_UCHIP)
.value("neoVIFIRE_JCHIP", ChipID::neoVIFIRE_JCHIP)
.value("ValueCAN3_MCHIP", ChipID::ValueCAN3_MCHIP)
.value("neoVIECU_MPIC", ChipID::neoVIECU_MPIC)
.value("neoVIIEVB_MPIC", ChipID::neoVIIEVB_MPIC)
.value("neoVIPENDANT_MPIC", ChipID::neoVIPENDANT_MPIC)
.value("neoVIFIRE_VNET_MCHIP", ChipID::neoVIFIRE_VNET_MCHIP)
.value("neoVIFIRE_VNET_LCHIP", ChipID::neoVIFIRE_VNET_LCHIP)
.value("neoVIPLASMA_Core", ChipID::neoVIPLASMA_Core)
.value("neoVIPLASMA_HID", ChipID::neoVIPLASMA_HID)
.value("neoVIANALOG_MPIC", ChipID::neoVIANALOG_MPIC)
.value("neoVIPLASMA_ANALOG_Core", ChipID::neoVIPLASMA_ANALOG_Core)
.value("neoVIPLASMA_FlexRay_Core", ChipID::neoVIPLASMA_FlexRay_Core)
.value("neoVIPLASMA_Core_1_12", ChipID::neoVIPLASMA_Core_1_12)
.value("neoVIFIRE_Slave_VNET_MCHIP", ChipID::neoVIFIRE_Slave_VNET_MCHIP)
.value("neoVIFIRE_Slave_VNET_LCHIP", ChipID::neoVIFIRE_Slave_VNET_LCHIP)
.value("neoVIION_Core", ChipID::neoVIION_Core)
.value("neoVIION_HID", ChipID::neoVIION_HID)
.value("neoVIION_Core_Loader", ChipID::neoVIION_Core_Loader)
.value("neoVIION_HID_Loader", ChipID::neoVIION_HID_Loader)
.value("neoVIION_FPGA_BIT", ChipID::neoVIION_FPGA_BIT)
.value("neoVIFIRE_VNET_EP_MCHIP", ChipID::neoVIFIRE_VNET_EP_MCHIP)
.value("neoVIFIRE_VNET_EP_LCHIP", ChipID::neoVIFIRE_VNET_EP_LCHIP)
.value("neoVIAnalogOut_MCHIP", ChipID::neoVIAnalogOut_MCHIP)
.value("neoVIMOST25_MCHIP", ChipID::neoVIMOST25_MCHIP)
.value("neoVIMOST50_MCHIP", ChipID::neoVIMOST50_MCHIP)
.value("neoVIMOST150_MCHIP", ChipID::neoVIMOST150_MCHIP)
.value("ValueCAN4_4_MCHIP", ChipID::ValueCAN4_4_MCHIP)
.value("ValueCAN4_4_SCHIP", ChipID::ValueCAN4_4_SCHIP)
.value("cmProbe_ZYNQ", ChipID::cmProbe_ZYNQ)
.value("EEVB_STM32", ChipID::EEVB_STM32)
.value("neoVIFIRE_Slave_VNET_EP_MCHIP", ChipID::neoVIFIRE_Slave_VNET_EP_MCHIP)
.value("neoVIFIRE_Slave_VNET_EP_LCHIP", ChipID::neoVIFIRE_Slave_VNET_EP_LCHIP)
.value("RADStar_MCHIP", ChipID::RADStar_MCHIP)
.value("ValueCANrf_MCHIP", ChipID::ValueCANrf_MCHIP)
.value("neoVIFIRE2_MCHIP", ChipID::neoVIFIRE2_MCHIP)
.value("neoVIFIRE2_CCHIP", ChipID::neoVIFIRE2_CCHIP)
.value("neoVIFIRE2_Core", ChipID::neoVIFIRE2_Core)
.value("neoVIFIRE2_BLECHIP", ChipID::neoVIFIRE2_BLECHIP)
.value("neoVIFIRE2_ZYNQ", ChipID::neoVIFIRE2_ZYNQ)
.value("neoVIFIRE2_SECURITYCHIP", ChipID::neoVIFIRE2_SECURITYCHIP)
.value("RADGalaxy_ZYNQ", ChipID::RADGalaxy_ZYNQ)
.value("neoVIFIRE2_VNET_MCHIP", ChipID::neoVIFIRE2_VNET_MCHIP)
.value("neoVIFIRE2_Slave_VNET_A_MCHIP", ChipID::neoVIFIRE2_Slave_VNET_A_MCHIP)
.value("neoVIFIRE2_Slave_VNET_A_CCHIP", ChipID::neoVIFIRE2_Slave_VNET_A_CCHIP)
.value("neoVIFIRE2_VNET_CCHIP", ChipID::neoVIFIRE2_VNET_CCHIP)
.value("neoVIFIRE2_VNET_Core", ChipID::neoVIFIRE2_VNET_Core)
.value("RADStar2_ZYNQ", ChipID::RADStar2_ZYNQ)
.value("VividCAN_MCHIP", ChipID::VividCAN_MCHIP)
.value("neoOBD2SIM_MCHIP", ChipID::neoOBD2SIM_MCHIP)
.value("neoVIFIRE2_VNETZ_MCHIP", ChipID::neoVIFIRE2_VNETZ_MCHIP)
.value("neoVIFIRE2_VNETZ_ZYNQ", ChipID::neoVIFIRE2_VNETZ_ZYNQ)
.value("neoVIFIRE2_Slave_VNETZ_A_MCHIP", ChipID::neoVIFIRE2_Slave_VNETZ_A_MCHIP)
.value("neoVIFIRE2_Slave_VNETZ_A_ZYNQ", ChipID::neoVIFIRE2_Slave_VNETZ_A_ZYNQ)
.value("VividCAN_EXT_FLASH", ChipID::VividCAN_EXT_FLASH)
.value("VividCAN_NRF52", ChipID::VividCAN_NRF52)
.value("cmProbe_ZYNQ_Unused", ChipID::cmProbe_ZYNQ_Unused)
.value("neoOBD2PRO_MCHIP", ChipID::neoOBD2PRO_MCHIP)
.value("ValueCAN4_1_MCHIP", ChipID::ValueCAN4_1_MCHIP)
.value("ValueCAN4_2_MCHIP", ChipID::ValueCAN4_2_MCHIP)
.value("ValueCAN4_4_2EL_Core", ChipID::ValueCAN4_4_2EL_Core)
.value("neoOBD2PRO_SCHIP", ChipID::neoOBD2PRO_SCHIP)
.value("ValueCAN4_2EL_MCHIP", ChipID::ValueCAN4_2EL_MCHIP)
.value("neoECUAVBTSN_MCHIP", ChipID::neoECUAVBTSN_MCHIP)
.value("neoOBD2PRO_Core", ChipID::neoOBD2PRO_Core)
.value("RADSupermoon_ZYNQ", ChipID::RADSupermoon_ZYNQ)
.value("RADMoon2_ZYNQ", ChipID::RADMoon2_ZYNQ)
.value("VividCANPRO_MCHIP", ChipID::VividCANPRO_MCHIP)
.value("VividCANPRO_EXT_FLASH", ChipID::VividCANPRO_EXT_FLASH)
.value("RADPluto_MCHIP", ChipID::RADPluto_MCHIP)
.value("RADMars_ZYNQ", ChipID::RADMars_ZYNQ)
.value("neoECU12_MCHIP", ChipID::neoECU12_MCHIP)
.value("RADIOCANHUB_MCHIP", ChipID::RADIOCANHUB_MCHIP)
.value("FlexRay_VNETZ_ZCHIP", ChipID::FlexRay_VNETZ_ZCHIP)
.value("neoOBD2_LCBADGE_MCHIP", ChipID::neoOBD2_LCBADGE_MCHIP)
.value("neoOBD2_LCBADGE_SCHIP", ChipID::neoOBD2_LCBADGE_SCHIP)
.value("RADMoonDuo_MCHIP", ChipID::RADMoonDuo_MCHIP)
.value("neoVIFIRE3_ZCHIP", ChipID::neoVIFIRE3_ZCHIP)
.value("FlexRay_VNETZ_FCHIP", ChipID::FlexRay_VNETZ_FCHIP)
.value("RADJupiter_MCHIP", ChipID::RADJupiter_MCHIP)
.value("ValueCAN4Industrial_MCHIP", ChipID::ValueCAN4Industrial_MCHIP)
.value("EtherBADGE_MCHIP", ChipID::EtherBADGE_MCHIP)
.value("RADMars_3_ZYNQ", ChipID::RADMars_3_ZYNQ)
.value("RADGigastar_USBZ_ZYNQ", ChipID::RADGigastar_USBZ_ZYNQ)
.value("RADGigastar_ZYNQ", ChipID::RADGigastar_ZYNQ)
.value("RAD4G_MCHIP", ChipID::RAD4G_MCHIP)
.value("neoVIFIRE3_SCHIP", ChipID::neoVIFIRE3_SCHIP)
.value("RADEpsilon_MCHIP", ChipID::RADEpsilon_MCHIP)
.value("RADA2B_ZCHIP", ChipID::RADA2B_ZCHIP)
.value("neoOBD2Dev_MCHIP", ChipID::neoOBD2Dev_MCHIP)
.value("neoOBD2Dev_SCHIP", ChipID::neoOBD2Dev_SCHIP)
.value("neoOBD2SIMDoIP_MCHIP", ChipID::neoOBD2SIMDoIP_MCHIP)
.value("SFPModule_MCHIP", ChipID::SFPModule_MCHIP)
.value("RADEpsilonT_MCHIP", ChipID::RADEpsilonT_MCHIP)
.value("RADEpsilonExpress_MCHIP", ChipID::RADEpsilonExpress_MCHIP)
.value("RADProxima_MCHIP", ChipID::RADProxima_MCHIP)
.value("NewDevice57_ZCHIP", ChipID::NewDevice57_ZCHIP)
.value("RAD_GALAXY_2_ZMPCHIP_ID", ChipID::RAD_GALAXY_2_ZMPCHIP_ID)
.value("NewDevice59_MCHIP", ChipID::NewDevice59_MCHIP)
.value("RADMoon2_Z7010_ZYNQ", ChipID::RADMoon2_Z7010_ZYNQ)
.value("neoVIFIRE2_Core_SG4", ChipID::neoVIFIRE2_Core_SG4)
.value("RADBMS_MCHIP", ChipID::RADBMS_MCHIP)
.value("RADMoon2_ZL_MCHIP", ChipID::RADMoon2_ZL_MCHIP)
.value("RADGigastar_USBZ_Z7010_ZYNQ", ChipID::RADGigastar_USBZ_Z7010_ZYNQ)
.value("neoVIFIRE3_LINUX", ChipID::neoVIFIRE3_LINUX)
.value("RADGigastar_USBZ_Z7007S_ZYNQ", ChipID::RADGigastar_USBZ_Z7007S_ZYNQ)
.value("VEM_01_8DW_ZCHIP", ChipID::VEM_01_8DW_ZCHIP)
.value("RADGalaxy_FFG_Zynq", ChipID::RADGalaxy_FFG_Zynq)
.value("RADMoon3_MCHIP", ChipID::RADMoon3_MCHIP)
.value("RADComet_ZYNQ", ChipID::RADComet_ZYNQ)
.value("VEM_02_FR_ZCHIP", ChipID::VEM_02_FR_ZCHIP)
.value("RADA2B_REVB_ZCHIP", ChipID::RADA2B_REVB_ZCHIP)
.value("RADGigastar_FFG_ZYNQ", ChipID::RADGigastar_FFG_ZYNQ)
.value("VEM_02_FR_FCHIP", ChipID::VEM_02_FR_FCHIP)
.value("Connect_ZCHIP", ChipID::Connect_ZCHIP)
.value("RADGALAXY2_SYSMON_CHIP", ChipID::RADGALAXY2_SYSMON_CHIP)
.value("RADCOMET3_ZCHIP", ChipID::RADCOMET3_ZCHIP)
.value("Connect_LINUX", ChipID::Connect_LINUX)
.value("RADGigastar2_ZYNQ", ChipID::RADGigastar2_ZYNQ)
.value("RADGemini_MCHIP", ChipID::RADGemini_MCHIP)
.value("Invalid", ChipID::Invalid)
.finalize();
}
} // namespace icsneo
+11 -1
View File
@@ -4,13 +4,14 @@
#include <pybind11/chrono.h> #include <pybind11/chrono.h>
#include "icsneo/device/device.h" #include "icsneo/device/device.h"
#include "icsneo/device/extensions/deviceextension.h"
#include <fstream> #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::classh<Device>(m, "Device")
.def("__repr__", &Device::describe) .def("__repr__", &Device::describe)
.def("add_message_callback", &Device::addMessageCallback, pybind11::call_guard<pybind11::gil_scoped_release>()) .def("add_message_callback", &Device::addMessageCallback, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("clear_script", &Device::clearScript, pybind11::call_guard<pybind11::gil_scoped_release>()) .def("clear_script", &Device::clearScript, pybind11::call_guard<pybind11::gil_scoped_release>())
@@ -20,6 +21,8 @@ void init_device(pybind11::module_& m) {
.def("enable_message_polling", &Device::enableMessagePolling, pybind11::arg("filter") = std::nullopt, pybind11::call_guard<pybind11::gil_scoped_release>()) .def("enable_message_polling", &Device::enableMessagePolling, pybind11::arg("filter") = std::nullopt, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("get_current_message_count", &Device::getCurrentMessageCount) .def("get_current_message_count", &Device::getCurrentMessageCount)
.def("get_digital_io", &Device::getDigitalIO, pybind11::arg("type"), pybind11::arg("number"), pybind11::call_guard<pybind11::gil_scoped_release>()) .def("get_digital_io", &Device::getDigitalIO, pybind11::arg("type"), pybind11::arg("number"), pybind11::call_guard<pybind11::gil_scoped_release>())
.def("get_extension", static_cast<std::shared_ptr<DeviceExtension>(Device::*)(const std::string&) const>(&Device::getExtension)) // This has to be static_casted rather than overload_casted because DeviceExtension is forward declared in device.h
.def("get_flexray_controllers", &Device::getFlexRayControllers)
.def("get_gptp_status", &Device::getGPTPStatus, pybind11::arg("timeout") = std::chrono::milliseconds(100), pybind11::call_guard<pybind11::gil_scoped_release>()) .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_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)
@@ -49,9 +52,16 @@ void init_device(pybind11::module_& m) {
.def("start_script", &Device::startScript, 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("stop_script", &Device::stopScript, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("supports_tc10", &Device::supportsTC10) .def("supports_tc10", &Device::supportsTC10)
.def("supports_live_data", &Device::supportsLiveData)
.def("subscribe_live_data", &Device::subscribeLiveData, pybind11::arg("message"), pybind11::call_guard<pybind11::gil_scoped_release>())
.def("unsubscribe_live_data", &Device::unsubscribeLiveData, pybind11::arg("handle"), pybind11::call_guard<pybind11::gil_scoped_release>())
.def("clear_all_live_data", &Device::clearAllLiveData, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("set_value_live_data", &Device::setValueLiveData, pybind11::arg("message"), pybind11::call_guard<pybind11::gil_scoped_release>())
.def("transmit", pybind11::overload_cast<std::shared_ptr<Frame>>(&Device::transmit), pybind11::call_guard<pybind11::gil_scoped_release>()) .def("transmit", pybind11::overload_cast<std::shared_ptr<Frame>>(&Device::transmit), pybind11::call_guard<pybind11::gil_scoped_release>())
.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("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("write_macsec_config", &Device::writeMACsecConfig, pybind11::call_guard<pybind11::gil_scoped_release>()) .def("write_macsec_config", &Device::writeMACsecConfig, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("send_eth_phy_msg", &Device::sendEthPhyMsg, pybind11::arg("message"), pybind11::arg("timeout") = std::chrono::milliseconds(50), pybind11::call_guard<pybind11::gil_scoped_release>())
.def("get_chip_versions", &Device::getChipVersions, pybind11::arg("refreshComponents") = true, pybind11::call_guard<pybind11::gil_scoped_release>())
.def_readonly("settings", &Device::settings); .def_readonly("settings", &Device::settings);
} }
@@ -1,14 +1,15 @@
#include <pybind11/pybind11.h> #include <pybind11/pybind11.h>
#include <pybind11/stl.h> #include <pybind11/stl.h>
#include <pybind11/functional.h> #include <pybind11/functional.h>
#include <pybind11/native_enum.h>
#include "icsneo/device/devicetype.h" #include "icsneo/device/devicetype.h"
namespace icsneo { namespace icsneo {
void init_devicetype(pybind11::module_& m) { void init_devicetype(pybind11::module_& m) {
pybind11::class_<DeviceType> deviceType(m, "DeviceType"); pybind11::classh<DeviceType> deviceType(m, "DeviceType");
pybind11::enum_<DeviceType::Enum>(deviceType, "Enum") pybind11::native_enum<DeviceType::Enum>(deviceType, "Enum", "enum.IntEnum")
.value("Unknown", DeviceType::Enum::Unknown) .value("Unknown", DeviceType::Enum::Unknown)
.value("BLUE", DeviceType::Enum::BLUE) .value("BLUE", DeviceType::Enum::BLUE)
.value("ECU_AVB", DeviceType::Enum::ECU_AVB) .value("ECU_AVB", DeviceType::Enum::ECU_AVB)
@@ -36,8 +37,11 @@ void init_devicetype(pybind11::module_& m) {
.value("RADEpsilonXL", DeviceType::Enum::RADEpsilonXL) .value("RADEpsilonXL", DeviceType::Enum::RADEpsilonXL)
.value("RADGalaxy2", DeviceType::Enum::RADGalaxy2) .value("RADGalaxy2", DeviceType::Enum::RADGalaxy2)
.value("RADMoon3", DeviceType::Enum::RADMoon3) .value("RADMoon3", DeviceType::Enum::RADMoon3)
.value("RADGemini", DeviceType::Enum::RADGemini)
.value("RADComet", DeviceType::Enum::RADComet) .value("RADComet", DeviceType::Enum::RADComet)
.value("FIRE3_FlexRay", DeviceType::Enum::FIRE3_FlexRay) .value("FIRE3_FlexRay", DeviceType::Enum::FIRE3_FlexRay)
.value("FIRE3_T1S_LIN", DeviceType::Enum::FIRE3_T1S_LIN)
.value("FIRE3_T1S_SENT", DeviceType::Enum::FIRE3_T1S_SENT)
.value("Connect", DeviceType::Enum::Connect) .value("Connect", DeviceType::Enum::Connect)
.value("RADComet3", DeviceType::Enum::RADComet3) .value("RADComet3", DeviceType::Enum::RADComet3)
.value("RADMoonT1S", DeviceType::Enum::RADMoonT1S) .value("RADMoonT1S", DeviceType::Enum::RADMoonT1S)
@@ -67,7 +71,8 @@ void init_devicetype(pybind11::module_& m) {
.value("RADGalaxy", DeviceType::Enum::RADGalaxy) .value("RADGalaxy", DeviceType::Enum::RADGalaxy)
.value("RADStar2", DeviceType::Enum::RADStar2) .value("RADStar2", DeviceType::Enum::RADStar2)
.value("VividCAN", DeviceType::Enum::VividCAN) .value("VividCAN", DeviceType::Enum::VividCAN)
.value("OBD2_SIM", DeviceType::Enum::OBD2_SIM); .value("OBD2_SIM", DeviceType::Enum::OBD2_SIM)
.finalize();
deviceType.def(pybind11::init<DeviceType::Enum>()); deviceType.def(pybind11::init<DeviceType::Enum>());
deviceType.def("get_device_type", &DeviceType::getDeviceType); deviceType.def("get_device_type", &DeviceType::getDeviceType);
deviceType.def("get_generic_product_name", &DeviceType::getGenericProductName); deviceType.def("get_generic_product_name", &DeviceType::getGenericProductName);
@@ -0,0 +1,14 @@
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <pybind11/functional.h>
#include "icsneo/device/extensions/deviceextension.h"
namespace icsneo {
void init_deviceextension(pybind11::module_& m) {
pybind11::classh<DeviceExtension>(m, "DeviceExtension")
.def("get_name", &DeviceExtension::getName);
}
} // namespace icsneo
@@ -12,35 +12,105 @@ namespace icsneo {
struct DeviceSettingsNamespace { struct DeviceSettingsNamespace {
using EthLinkMode = AELinkMode; using EthLinkMode = AELinkMode;
using LinkSpeed = EthLinkSpeed;
}; };
void init_idevicesettings(pybind11::module_& m) { void init_idevicesettings(pybind11::module_& m) {
pybind11::class_<DeviceSettingsNamespace> settings(m, "Settings"); pybind11::classh<DeviceSettingsNamespace> settings(m, "Settings");
pybind11::enum_<DeviceSettingsNamespace::EthLinkMode>(settings, "EthernetLinkMode") pybind11::enum_<DeviceSettingsNamespace::EthLinkMode>(settings, "EthernetLinkMode")
.value("Auto", DeviceSettingsNamespace::EthLinkMode::AE_LINK_AUTO) .value("Auto", DeviceSettingsNamespace::EthLinkMode::AE_LINK_AUTO)
.value("Slave", DeviceSettingsNamespace::EthLinkMode::AE_LINK_SLAVE) .value("Slave", DeviceSettingsNamespace::EthLinkMode::AE_LINK_SLAVE)
.value("Master", DeviceSettingsNamespace::EthLinkMode::AE_LINK_MASTER); .value("Master", DeviceSettingsNamespace::EthLinkMode::AE_LINK_MASTER);
pybind11::enum_<DeviceSettingsNamespace::LinkSpeed>(settings, "EthernetLinkSpeed") pybind11::enum_<EthPhyLinkMode>(settings, "PhyLinkMode")
.value("Speed10M", DeviceSettingsNamespace::LinkSpeed::ETH_SPEED_10) .value("ETH_LINK_MODE_AUTO_NEGOTIATION", ETH_LINK_MODE_AUTO_NEGOTIATION)
.value("Speed100M", DeviceSettingsNamespace::LinkSpeed::ETH_SPEED_100) .value("ETH_LINK_MODE_10MBPS_HALFDUPLEX", ETH_LINK_MODE_10MBPS_HALFDUPLEX)
.value("Speed1G", DeviceSettingsNamespace::LinkSpeed::ETH_SPEED_1000) .value("ETH_LINK_MODE_10MBPS_FULLDUPLEX", ETH_LINK_MODE_10MBPS_FULLDUPLEX)
.value("Speed2_5G", DeviceSettingsNamespace::LinkSpeed::ETH_SPEED_2500) .value("ETH_LINK_MODE_100MBPS_HALFDUPLEX", ETH_LINK_MODE_100MBPS_HALFDUPLEX)
.value("Speed5G", DeviceSettingsNamespace::LinkSpeed::ETH_SPEED_5000) .value("ETH_LINK_MODE_100MBPS_FULLDUPLEX", ETH_LINK_MODE_100MBPS_FULLDUPLEX)
.value("Speed10G", DeviceSettingsNamespace::LinkSpeed::ETH_SPEED_10000); .value("ETH_LINK_MODE_1GBPS_HALFDUPLEX", ETH_LINK_MODE_1GBPS_HALFDUPLEX)
.value("ETH_LINK_MODE_1GBPS_FULLDUPLEX", ETH_LINK_MODE_1GBPS_FULLDUPLEX)
.value("ETH_LINK_MODE_2_5GBPS_FULLDUPLEX", ETH_LINK_MODE_2_5GBPS_FULLDUPLEX)
.value("ETH_LINK_MODE_5GBPS_FULLDUPLEX", ETH_LINK_MODE_5GBPS_FULLDUPLEX)
.value("ETH_LINK_MODE_10GBPS_FULLDUPLEX", ETH_LINK_MODE_10GBPS_FULLDUPLEX);
pybind11::class_<IDeviceSettings, std::shared_ptr<IDeviceSettings>>(m, "IDeviceSettings") pybind11::enum_<LINMode>(settings, "LINMode")
.value("Sleep", LINMode::SLEEP_MODE)
.value("Slow", LINMode::SLOW_MODE)
.value("Normal", LINMode::NORMAL_MODE)
.value("Fast", LINMode::FAST_MODE);
pybind11::enum_<MiscIOAnalogVoltage>(settings, "MiscIOAnalogVoltage")
.value("V0", MiscIOAnalogVoltage::V0)
.value("V1", MiscIOAnalogVoltage::V1)
.value("V2", MiscIOAnalogVoltage::V2)
.value("V3", MiscIOAnalogVoltage::V3)
.value("V4", MiscIOAnalogVoltage::V4)
.value("V5", MiscIOAnalogVoltage::V5);
pybind11::classh<IDeviceSettings>(m, "IDeviceSettings")
.def("apply", &IDeviceSettings::apply, pybind11::arg("temporary") = 0, pybind11::call_guard<pybind11::gil_scoped_release>()) .def("apply", &IDeviceSettings::apply, pybind11::arg("temporary") = 0, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("apply_defaults", &IDeviceSettings::applyDefaults, pybind11::arg("temporary") = 0, pybind11::call_guard<pybind11::gil_scoped_release>()) .def("apply_defaults", &IDeviceSettings::applyDefaults, pybind11::arg("temporary") = 0, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("refresh", &IDeviceSettings::refresh, pybind11::call_guard<pybind11::gil_scoped_release>())
// Baudrate methods
.def("get_baudrate", &IDeviceSettings::getBaudrateFor, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("set_baudrate", &IDeviceSettings::setBaudrateFor, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("get_fd_baudrate", &IDeviceSettings::getFDBaudrateFor, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("set_fd_baudrate", &IDeviceSettings::setFDBaudrateFor, pybind11::call_guard<pybind11::gil_scoped_release>())
// Termination methods
.def("is_termination_supported", &IDeviceSettings::isTerminationSupportedFor, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("can_termination_be_enabled", &IDeviceSettings::canTerminationBeEnabledFor, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("is_termination_enabled", &IDeviceSettings::isTerminationEnabledFor, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("set_termination", &IDeviceSettings::setTerminationFor, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("get_termination_groups", &IDeviceSettings::getTerminationGroups, pybind11::call_guard<pybind11::gil_scoped_release>())
// LIN methods
.def("is_commander_resistor_enabled", &IDeviceSettings::isCommanderResistorEnabledFor, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("set_commander_resistor", &IDeviceSettings::setCommanderResistorFor, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("get_lin_mode", &IDeviceSettings::getLINModeFor, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("set_lin_mode", &IDeviceSettings::setLINModeFor, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("get_lin_commander_response_time", &IDeviceSettings::getLINCommanderResponseTimeFor, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("set_lin_commander_response_time", &IDeviceSettings::setLINCommanderResponseTimeFor, pybind11::call_guard<pybind11::gil_scoped_release>())
// Ethernet PHY methods (index-based for switch devices)
.def("get_phy_enable", &IDeviceSettings::getPhyEnable, pybind11::call_guard<pybind11::gil_scoped_release>()) .def("get_phy_enable", &IDeviceSettings::getPhyEnable, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("get_phy_mode", &IDeviceSettings::getPhyMode, pybind11::call_guard<pybind11::gil_scoped_release>()) .def("get_phy_mode", &IDeviceSettings::getPhyMode, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("get_phy_speed", &IDeviceSettings::getPhySpeed, pybind11::call_guard<pybind11::gil_scoped_release>()) .def("get_phy_speed", &IDeviceSettings::getPhySpeed, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("set_phy_enable", &IDeviceSettings::setPhyEnable, pybind11::call_guard<pybind11::gil_scoped_release>()) .def("set_phy_enable", &IDeviceSettings::setPhyEnable, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("set_phy_mode", &IDeviceSettings::setPhyMode, pybind11::call_guard<pybind11::gil_scoped_release>()) .def("set_phy_mode", &IDeviceSettings::setPhyMode, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("set_phy_speed", &IDeviceSettings::setPhySpeed, pybind11::call_guard<pybind11::gil_scoped_release>()) .def("set_phy_speed", &IDeviceSettings::setPhySpeed, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("refresh", &IDeviceSettings::refresh, pybind11::arg("ignoreChecksum") = 0, pybind11::call_guard<pybind11::gil_scoped_release>());
// Ethernet PHY methods (network-based for multi-interface devices)
.def("get_phy_enable_for", &IDeviceSettings::getPhyEnableFor, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("get_phy_role_for", &IDeviceSettings::getPhyRoleFor, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("get_phy_link_mode_for", &IDeviceSettings::getPhyLinkModeFor, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("set_phy_enable_for", &IDeviceSettings::setPhyEnableFor, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("set_phy_role_for", &IDeviceSettings::setPhyRoleFor, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("set_phy_link_mode_for", &IDeviceSettings::setPhyLinkModeFor, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("get_supported_phy_link_modes_for", &IDeviceSettings::getSupportedPhyLinkModesFor, pybind11::call_guard<pybind11::gil_scoped_release>())
// 10BASE-T1S methods
.def("is_t1s_plca_enabled", &IDeviceSettings::isT1SPLCAEnabledFor, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("set_t1s_plca", &IDeviceSettings::setT1SPLCAFor, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("get_t1s_local_id", &IDeviceSettings::getT1SLocalIDFor, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("set_t1s_local_id", &IDeviceSettings::setT1SLocalIDFor, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("get_t1s_max_nodes", &IDeviceSettings::getT1SMaxNodesFor, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("set_t1s_max_nodes", &IDeviceSettings::setT1SMaxNodesFor, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("get_t1s_tx_opp_timer", &IDeviceSettings::getT1STxOppTimerFor, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("set_t1s_tx_opp_timer", &IDeviceSettings::setT1STxOppTimerFor, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("get_t1s_max_burst", &IDeviceSettings::getT1SMaxBurstFor, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("set_t1s_max_burst", &IDeviceSettings::setT1SMaxBurstFor, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("get_t1s_burst_timer", &IDeviceSettings::getT1SBurstTimerFor, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("set_t1s_burst_timer", &IDeviceSettings::setT1SBurstTimerFor, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("set_misc_io_analog_output_enabled", &IDeviceSettings::setMiscIOAnalogOutputEnabled, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("set_misc_io_analog_output", &IDeviceSettings::setMiscIOAnalogOutput, pybind11::call_guard<pybind11::gil_scoped_release>())
// Status properties
.def_readonly("disabled", &IDeviceSettings::disabled)
.def_readonly("readonly", &IDeviceSettings::readonly);
} }
} // namespace icsneo } // namespace icsneo
@@ -0,0 +1,19 @@
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <pybind11/functional.h>
#include "icsneo/device/versionreport.h"
namespace icsneo {
void init_versionreport(pybind11::module_& m) {
pybind11::classh<VersionReport>(m, "VersionReport")
.def_readonly("id", &VersionReport::id)
.def_readonly("name", &VersionReport::name)
.def_readonly("major", &VersionReport::major)
.def_readonly("minor", &VersionReport::minor)
.def_readonly("maintenance", &VersionReport::maintenance)
.def_readonly("build", &VersionReport::build);
}
} // namespace icsneo
+1 -1
View File
@@ -13,7 +13,7 @@ struct DiskNamespace {
}; };
void init_diskdriver(pybind11::module_& m) { void init_diskdriver(pybind11::module_& m) {
pybind11::class_<DiskNamespace> disk(m, "Disk"); pybind11::classh<DiskNamespace> disk(m, "Disk");
pybind11::enum_<Disk::Access>(disk, "Access") pybind11::enum_<Disk::Access>(disk, "Access")
.value("None", Disk::Access::None) .value("None", Disk::Access::None)
.value("EntireCard", Disk::Access::EntireCard) .value("EntireCard", Disk::Access::EntireCard)
@@ -0,0 +1,195 @@
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <pybind11/functional.h>
#include "icsneo/communication/message/flexray/flexraymessage.h"
#include "icsneo/device/extensions/flexray/symbol.h"
#include "icsneo/device/extensions/flexray/channel.h"
#include "icsneo/device/extensions/flexray/crcstatus.h"
#include "icsneo/device/extensions/flexray/controller.h"
namespace icsneo {
struct FlexRayNamespace {
using Symbol = icsneo::FlexRay::Symbol;
using CRCStatus = icsneo::FlexRay::CRCStatus;
using Channel = icsneo::FlexRay::Channel;
};
namespace FlexRay {
struct ClusterNamespace {
using SpeedType = icsneo::FlexRay::Cluster::SpeedType;
using SPPType = icsneo::FlexRay::Cluster::SPPType;
};
void init_extension(pybind11::classh<FlexRayNamespace>& c) {
pybind11::classh<MessageBuffer>(c, "MessageBuffer")
.def(pybind11::init())
.def_readwrite("is_dynamic", &MessageBuffer::isDynamic)
.def_readwrite("is_sync", &MessageBuffer::isSync)
.def_readwrite("is_startup", &MessageBuffer::isStartup)
.def_readwrite("is_network_management_frame", &MessageBuffer::isNetworkManagementFrame)
.def_readwrite("is_transmit", &MessageBuffer::isTransmit)
.def_readwrite("frame_id", &MessageBuffer::frameID)
.def_readwrite("channel_a", &MessageBuffer::channelA)
.def_readwrite("channel_b", &MessageBuffer::channelB)
.def_readwrite("frame_length_bytes", &MessageBuffer::frameLengthBytes)
.def_readwrite("base_cycle", &MessageBuffer::baseCycle)
.def_readwrite("cycle_repetition", &MessageBuffer::cycleRepetition)
.def_readwrite("continuous_mode", &MessageBuffer::continuousMode);
auto controller = pybind11::classh<Controller>(c, "Controller")
.def("get_network", &Controller::getNetwork)
.def("get_configuration", &Controller::getConfiguration)
.def("set_configuration", &Controller::setConfiguration)
.def("get_start_when_going_online", &Controller::getStartWhenGoingOnline)
.def("set_start_when_going_online", &Controller::setStartWhenGoingOnline)
.def("get_allow_coldstart", &Controller::getAllowColdstart)
.def("set_allow_coldstart", &Controller::setAllowColdstart)
.def("get_wakeup_before_start", &Controller::getWakeupBeforeStart)
.def("set_wakeup_before_start", &Controller::setWakeupBeforeStart)
.def("add_message_buffer", &Controller::addMessageBuffer)
.def("clear_message_buffers", &Controller::clearMessageBuffers)
.def("wakeup", &Controller::wakeup)
.def("configure", &Controller::getReady)
.def("start", &Controller::start)
.def("transmit", &Controller::transmit)
.def("halt", &Controller::halt)
.def("freeze", &Controller::freeze)
.def("trigger_mts", &Controller::triggerMTS);
pybind11::classh<Controller::Configuration>(controller, "Configuration")
.def(pybind11::init())
.def_readwrite("accept_startup_range_microticks", &Controller::Configuration::AcceptStartupRangeMicroticks)
.def_readwrite("allow_passive_to_active_cycle_pairs", &Controller::Configuration::AllowPassiveToActiveCyclePairs)
.def_readwrite("cluster_drift_damping", &Controller::Configuration::ClusterDriftDamping)
.def_readwrite("allow_halt_due_to_clock", &Controller::Configuration::AllowHaltDueToClock)
.def_readwrite("channel_a", &Controller::Configuration::ChannelA)
.def_readwrite("channel_b", &Controller::Configuration::ChannelB)
.def_readwrite("decoding_correction_microticks", &Controller::Configuration::DecodingCorrectionMicroticks)
.def_readwrite("delay_compensation_a_microticks", &Controller::Configuration::DelayCompensationAMicroticks)
.def_readwrite("delay_compensation_b_microticks", &Controller::Configuration::DelayCompensationBMicroticks)
.def_readwrite("extern_offset_correction_control", &Controller::Configuration::ExternOffsetCorrectionControl)
.def_readwrite("extern_rate_correction_control", &Controller::Configuration::ExternRateCorrectionControl)
.def_readwrite("extern_offset_correction_microticks", &Controller::Configuration::ExternOffsetCorrectionMicroticks)
.def_readwrite("extern_rate_correction_microticks", &Controller::Configuration::ExternRateCorrectionMicroticks)
.def_readwrite("key_slot_id", &Controller::Configuration::KeySlotID)
.def_readwrite("key_slot_only_enabled", &Controller::Configuration::KeySlotOnlyEnabled)
.def_readwrite("key_slot_used_for_startup", &Controller::Configuration::KeySlotUsedForStartup)
.def_readwrite("key_slot_used_for_sync", &Controller::Configuration::KeySlotUsedForSync)
.def_readwrite("latest_tx_minislot", &Controller::Configuration::LatestTxMinislot)
.def_readwrite("listen_timeout", &Controller::Configuration::ListenTimeout)
.def_readwrite("macro_initial_offset_a", &Controller::Configuration::MacroInitialOffsetA)
.def_readwrite("macro_initial_offset_b", &Controller::Configuration::MacroInitialOffsetB)
.def_readwrite("micro_initial_offset_a", &Controller::Configuration::MicroInitialOffsetA)
.def_readwrite("micro_initial_offset_b", &Controller::Configuration::MicroInitialOffsetB)
.def_readwrite("micro_per_cycle", &Controller::Configuration::MicroPerCycle)
.def_readwrite("mts_on_a", &Controller::Configuration::MTSOnA)
.def_readwrite("mts_on_b", &Controller::Configuration::MTSOnB)
.def_readwrite("offset_correction_out_microticks", &Controller::Configuration::OffsetCorrectionOutMicroticks)
.def_readwrite("rate_correction_out_microticks", &Controller::Configuration::RateCorrectionOutMicroticks)
.def_readwrite("second_key_slot_id", &Controller::Configuration::SecondKeySlotID)
.def_readwrite("two_key_slot_mode", &Controller::Configuration::TwoKeySlotMode)
.def_readwrite("wakeup_pattern", &Controller::Configuration::WakeupPattern)
.def_readwrite("wakeup_on_channel_b", &Controller::Configuration::WakeupOnChannelB);
// Dummy class for cluster namespace
pybind11::classh<ClusterNamespace> cluster(c, "Cluster");
pybind11::enum_<Cluster::SpeedType>(cluster, "SpeedType")
.value("FLEXRAY_BAUDRATE_10M", Cluster::SpeedType::FLEXRAY_BAUDRATE_10M)
.value("FLEXRAY_BAUDRATE_5M", Cluster::SpeedType::FLEXRAY_BAUDRATE_5M)
.value("FLEXRAY_BAUDRATE_2M5", Cluster::SpeedType::FLEXRAY_BAUDRATE_2M5)
.value("FLEXRAY_BAUDRATE_2M5_ALT", Cluster::SpeedType::FLEXRAY_BAUDRATE_2M5_ALT);
pybind11::enum_<Cluster::SPPType>(cluster, "SPPType")
.value("FLEXRAY_SPP_5", Cluster::SPPType::FLEXRAY_SPP_5)
.value("FLEXRAY_SPP_4", Cluster::SPPType::FLEXRAY_SPP_4)
.value("FLEXRAY_SPP_6", Cluster::SPPType::FLEXRAY_SPP_6)
.value("FLEXRAY_SPP_5_ALT", Cluster::SPPType::FLEXRAY_SPP_5_ALT);
pybind11::classh<Cluster::Configuration>(cluster, "Configuration")
.def(pybind11::init())
.def_readwrite("speed", &Cluster::Configuration::Speed)
.def_readwrite("strobe_point_position", &Cluster::Configuration::StrobePointPosition)
.def_readwrite("action_point_offset", &Cluster::Configuration::ActionPointOffset)
.def_readwrite("casr_x_low_max", &Cluster::Configuration::CASRxLowMax)
.def_readwrite("cold_start_attempts", &Cluster::Configuration::ColdStartAttempts)
.def_readwrite("cycle_duration_micro_sec", &Cluster::Configuration::CycleDurationMicroSec)
.def_readwrite("dynamic_slot_idle_phase_minislots", &Cluster::Configuration::DynamicSlotIdlePhaseMinislots)
.def_readwrite("listen_noise_macroticks", &Cluster::Configuration::ListenNoiseMacroticks)
.def_readwrite("macroticks_per_cycle", &Cluster::Configuration::MacroticksPerCycle)
.def_readwrite("macrotick_duration_micro_sec", &Cluster::Configuration::MacrotickDurationMicroSec)
.def_readwrite("max_without_clock_correction_fatal", &Cluster::Configuration::MaxWithoutClockCorrectionFatal)
.def_readwrite("max_without_clock_correction_passive", &Cluster::Configuration::MaxWithoutClockCorrectionPassive)
.def_readwrite("minislot_action_point_offset_macroticks", &Cluster::Configuration::MinislotActionPointOffsetMacroticks)
.def_readwrite("minislot_duration_macroticks", &Cluster::Configuration::MinislotDurationMacroticks)
.def_readwrite("network_idle_time_macroticks", &Cluster::Configuration::NetworkIdleTimeMacroticks)
.def_readwrite("network_management_vector_length_bytes", &Cluster::Configuration::NetworkManagementVectorLengthBytes)
.def_readwrite("number_of_minislots", &Cluster::Configuration::NumberOfMinislots)
.def_readwrite("number_of_static_slots", &Cluster::Configuration::NumberOfStaticSlots)
.def_readwrite("offset_correction_start_macroticks", &Cluster::Configuration::OffsetCorrectionStartMacroticks)
.def_readwrite("payload_length_of_static_slot_in_words", &Cluster::Configuration::PayloadLengthOfStaticSlotInWords)
.def_readwrite("static_slot_macroticks", &Cluster::Configuration::StaticSlotMacroticks)
.def_readwrite("symbol_window_macroticks", &Cluster::Configuration::SymbolWindowMacroticks)
.def_readwrite("symbol_window_action_point_offset_macroticks", &Cluster::Configuration::SymbolWindowActionPointOffsetMacroticks)
.def_readwrite("sync_frame_id_count_max", &Cluster::Configuration::SyncFrameIDCountMax)
.def_readwrite("transmission_start_sequence_duration_bits", &Cluster::Configuration::TransmissionStartSequenceDurationBits)
.def_readwrite("wakeup_rx_idle_bits", &Cluster::Configuration::WakeupRxIdleBits)
.def_readwrite("wakeup_rx_low_bits", &Cluster::Configuration::WakeupRxLowBits)
.def_readwrite("wakeup_rx_window_bits", &Cluster::Configuration::WakeupRxWindowBits)
.def_readwrite("wakeup_tx_active_bits", &Cluster::Configuration::WakeupTxActiveBits)
.def_readwrite("wakeup_tx_idle_bits", &Cluster::Configuration::WakeupTxIdleBits);
}
} // namespace FlexRay
void init_flexraymessage(pybind11::module_& m) {
pybind11::classh<FlexRayMessage, Frame>(m, "FlexRayMessage")
.def(pybind11::init())
.def_readwrite("slotid", &FlexRayMessage::slotid)
.def_readwrite("tsslen", &FlexRayMessage::tsslen)
.def_readwrite("framelen", &FlexRayMessage::framelen)
.def_readwrite("symbol", &FlexRayMessage::symbol)
.def_readwrite("header_crc_status", &FlexRayMessage::headerCRCStatus)
.def_readwrite("header_crc", &FlexRayMessage::headerCRC)
.def_readwrite("frame_crc_status", &FlexRayMessage::crcStatus)
.def_readwrite("frame_crc", &FlexRayMessage::frameCRC)
.def_readwrite("channel", &FlexRayMessage::channel)
.def_readwrite("null_frame", &FlexRayMessage::nullFrame)
.def_readwrite("payload_preamble", &FlexRayMessage::payloadPreamble)
.def_readwrite("sync_frame", &FlexRayMessage::sync)
.def_readwrite("startup_frame", &FlexRayMessage::startup)
.def_readwrite("dynamic_frame", &FlexRayMessage::dynamic)
.def_readwrite("cycle", &FlexRayMessage::cycle)
.def_readwrite("cycle_repetition", &FlexRayMessage::cycleRepetition);
//// TODO: Eliminate FlexRayControlMessage class references in controller class and eliminate getStatus function in bindings
}
void init_flexray(pybind11::module_& m) {
// Dummy class to act as FlexRay namespace
pybind11::classh<FlexRayNamespace> flexray(m, "FlexRay");
pybind11::enum_<FlexRayNamespace::Symbol>(flexray, "Symbol")
.value("None", FlexRayNamespace::Symbol::None)
.value("Unknown", FlexRayNamespace::Symbol::Unknown)
.value("Wakeup", FlexRayNamespace::Symbol::Wakeup)
.value("CAS", FlexRayNamespace::Symbol::CAS);
pybind11::enum_<FlexRayNamespace::CRCStatus>(flexray, "CRCStatus")
.value("OK", FlexRayNamespace::CRCStatus::OK)
.value("Error", FlexRayNamespace::CRCStatus::Error)
.value("NoCRC", FlexRayNamespace::CRCStatus::NoCRC);
pybind11::enum_<FlexRayNamespace::Channel>(flexray, "Channel")
.value("None", FlexRayNamespace::Channel::None)
.value("A", FlexRayNamespace::Channel::A)
.value("B", FlexRayNamespace::Channel::B)
.value("AB", FlexRayNamespace::Channel::AB);
init_flexraymessage(m);
FlexRay::init_extension(flexray);
}
} // namespace icsneo
+18 -4
View File
@@ -20,16 +20,23 @@ void init_linmessage(pybind11::module_&);
void init_tc10statusmessage(pybind11::module_&); void init_tc10statusmessage(pybind11::module_&);
void init_gptpstatusmessage(pybind11::module_&); void init_gptpstatusmessage(pybind11::module_&);
void init_mdiomessage(pybind11::module_&); void init_mdiomessage(pybind11::module_&);
void init_spimessage(pybind11::module_&);
void init_ethernetstatusmessage(pybind11::module_&); void init_ethernetstatusmessage(pybind11::module_&);
void init_macsecmessage(pybind11::module_&); void init_macsecconfig(pybind11::module_&);
void init_scriptstatusmessage(pybind11::module_&); void init_scriptstatusmessage(pybind11::module_&);
void init_diskdriver(pybind11::module_&); void init_diskdriver(pybind11::module_&);
void init_deviceextension(pybind11::module_&);
void init_chipid(pybind11::module_&);
void init_versionreport(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_&);
void init_flexraymessage(pybind11::module_& m); void init_flexray(pybind11::module_& m);
void init_idevicesettings(pybind11::module_&); void init_idevicesettings(pybind11::module_&);
void init_ethphymessage(pybind11::module_&);
void init_livedata(pybind11::module_&);
void init_livedatamessage(pybind11::module_&);
PYBIND11_MODULE(icsneopy, m) { PYBIND11_MODULE(icsneopy, m) {
pybind11::options options; pybind11::options options;
@@ -43,6 +50,7 @@ PYBIND11_MODULE(icsneopy, m) {
init_devicetype(m); init_devicetype(m);
init_network(m); init_network(m);
init_io(m); init_io(m);
init_livedata(m);
init_message(m); init_message(m);
init_canmessage(m); init_canmessage(m);
init_canerrormessage(m); init_canerrormessage(m);
@@ -52,13 +60,19 @@ PYBIND11_MODULE(icsneopy, m) {
init_gptpstatusmessage(m); init_gptpstatusmessage(m);
init_mdiomessage(m); init_mdiomessage(m);
init_ethernetstatusmessage(m); init_ethernetstatusmessage(m);
init_macsecmessage(m); init_macsecconfig(m);
init_scriptstatusmessage(m); init_scriptstatusmessage(m);
init_spimessage(m);
init_livedatamessage(m);
init_messagefilter(m); init_messagefilter(m);
init_messagecallback(m); init_messagecallback(m);
init_diskdriver(m); init_diskdriver(m);
init_flexray(m);
init_ethphymessage(m);
init_chipid(m);
init_versionreport(m);
init_device(m); init_device(m);
init_flexraymessage(m); init_deviceextension(m);
init_idevicesettings(m); init_idevicesettings(m);
m.def("find_all_devices", &FindAllDevices); m.def("find_all_devices", &FindAllDevices);
+7
View File
@@ -0,0 +1,7 @@
#!/bin/sh
yum install -y flex ca-certificates || exit 1
echo "$ICS_IPA_CA_CRT" >/etc/pki/ca-trust/source/anchors/ica-ipa-ca.crt
update-ca-trust || exit 1
+1 -2
View File
@@ -1,6 +1,5 @@
#!/bin/sh #!/bin/sh
export CFLAGS="-Wall -Werror"
export CXXFLAGS="-Wall -Werror"
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_ENABLE_TCP=OFF || exit 1 -DLIBICSNEO_BUILD_UNIT_TESTS=ON -DLIBICSNEO_ENABLE_TCP=OFF || exit 1
+8 -11
View File
@@ -1,12 +1,9 @@
REM clean intermediate directories @setlocal
rmdir /s /q build @echo off
mkdir build
REM build mkdir build >nul 2>&1
cd build
set CFLAGS=/WX /W4 /wd4127 cmake -GNinja -Bbuild -DCMAKE_BUILD_TYPE=Release -DLIBICSNEO_BUILD_UNIT_TESTS=ON ^
set CXXFLAGS=/WX /W4 /wd4127 -DLIBICSNEO_ENABLE_TCP=ON || exit /b 1
cmake -GNinja -DCMAKE_BUILD_TYPE=RelWithDebInfo -DLIBICSNEO_BUILD_UNIT_TESTS=ON -DLIBICSNEO_ENABLE_TCP=ON ..
if %errorlevel% neq 0 exit /b %errorlevel% cmake --build build || exit /b 1
cmake --build .
if %errorlevel% neq 0 exit /b %errorlevel%
+35
View File
@@ -14,6 +14,12 @@
#include "icsneo/communication/message/readsettingsmessage.h" #include "icsneo/communication/message/readsettingsmessage.h"
#include "icsneo/communication/message/versionmessage.h" #include "icsneo/communication/message/versionmessage.h"
#include "icsneo/communication/message/componentversionsmessage.h" #include "icsneo/communication/message/componentversionsmessage.h"
#include "icsneo/communication/message/filter/extendedresponsefilter.h"
#include "icsneo/communication/message/clientidmessage.h"
#include "icsneo/communication/icspb.h"
#include <commands/generic/v1/client_id.pb.h>
#include <commands/network/v1/mutex.pb.h>
using namespace icsneo; using namespace icsneo;
@@ -313,3 +319,32 @@ std::optional< std::vector<ComponentVersion> > Communication::getComponentVersio
return std::make_optional< std::vector<ComponentVersion> >(std::move(ver->versions)); return std::make_optional< std::vector<ComponentVersion> >(std::move(ver->versions));
} }
std::optional<uint32_t> Communication::getClientIDSync() {
constexpr auto timeout = std::chrono::milliseconds(250);
commands::generic::v1::ClientId msg;
msg.Clear();
std::vector<uint8_t> payload = protoapi::getPayload(protoapi::Command::GET, msg);
std::shared_ptr<Message> response = waitForMessageSync(
[this, payload](){
return sendCommand(ExtendedCommand::ProtobufAPI, payload);
},
std::make_shared<MessageFilter>(Message::Type::ClientId),
timeout
);
if(!response) {
report(APIEvent::Type::NoDeviceResponse, APIEvent::Severity::Error);
return std::nullopt;
}
auto clientIdMessage = std::dynamic_pointer_cast<ClientIdMessage>(response);
if(!clientIdMessage) {
report(APIEvent::Type::UnexpectedResponse, APIEvent::Severity::Error);
return std::nullopt;
}
return clientIdMessage->clientId;
}
+41 -3
View File
@@ -23,6 +23,8 @@
#include "icsneo/communication/message/gptpstatusmessage.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/message/ethernetstatusmessage.h"
#include "icsneo/communication/message/networkmutexmessage.h"
#include "icsneo/communication/message/clientidmessage.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"
@@ -43,6 +45,9 @@
#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/communication/packet/hardwareinfopacket.h" #include "icsneo/communication/packet/hardwareinfopacket.h"
#include "icsneo/communication/packet/spipacket.h"
#include "icsneo/communication/icspb.h"
#include <iostream> #include <iostream>
@@ -57,8 +62,9 @@ uint64_t Decoder::GetUInt64FromLEBytes(const uint8_t* bytes) {
bool Decoder::decode(std::shared_ptr<Message>& result, const std::shared_ptr<Packet>& packet) { bool Decoder::decode(std::shared_ptr<Message>& result, const std::shared_ptr<Packet>& packet) {
switch(packet->network.getType()) { switch(packet->network.getType()) {
case Network::Type::Ethernet: { case Network::Type::Ethernet:
result = HardwareEthernetPacket::DecodeToMessage(packet->data, report); case Network::Type::AutomotiveEthernet: {
result = HardwareEthernetPacket::DecodeToMessage(packet->data);
if(!result) { 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 not long enough to decode return false; // A nullptr was returned, the packet was not long enough to decode
@@ -184,6 +190,19 @@ bool Decoder::decode(std::shared_ptr<Message>& result, const std::shared_ptr<Pac
msg.timestamp *= timestampResolution; msg.timestamp *= timestampResolution;
return true; return true;
} }
case Network::Type::SPI: {
result = HardwareSPIPacket::DecodeToMessage(packet->data);
if(!result) {
report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::Error);
return false; // A nullptr was returned, the packet was not long enough to decode
}
SPIMessage& msg = *static_cast<SPIMessage*>(result.get());
msg.network = packet->network;
msg.timestamp *= timestampResolution;
return true;
}
case Network::Type::MDIO: { case Network::Type::MDIO: {
result = HardwareMDIOPacket::DecodeToMessage(packet->data); result = HardwareMDIOPacket::DecodeToMessage(packet->data);
@@ -259,7 +278,7 @@ bool Decoder::decode(std::shared_ptr<Message>& result, const std::shared_ptr<Pac
result = can; result = can;
} }
result->timestamp *= timestampResolution; result->timestamp = can->timestamp * timestampResolution;
return true; return true;
} }
case Network::NetID::DeviceStatus: { case Network::NetID::DeviceStatus: {
@@ -324,6 +343,25 @@ bool Decoder::decode(std::shared_ptr<Message>& result, const std::shared_ptr<Pac
result = GPTPStatus::DecodeToMessage(packet->data, report); result = GPTPStatus::DecodeToMessage(packet->data, report);
return true; return true;
} }
case ExtendedCommand::ProtobufAPI: {
// get the proto id
std::vector<uint8_t> responseBody(
packet->data.begin() + sizeof(ExtendedResponseMessage::ResponseHeader),
packet->data.end()
);
protoapi::Id protoId = protoapi::getProtoId(responseBody.data(), responseBody.size());
switch(protoId) {
case protoapi::Id::NetworkMutex:
result = NetworkMutexMessage::DecodeToMessage(responseBody);
return true;
case protoapi::Id::ClientId:
result = ClientIdMessage::DecodeToMessage(responseBody);
return true;
default:
report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::Error);
return false;
}
}
case ExtendedCommand::GetDiskDetails: case ExtendedCommand::GetDiskDetails:
case ExtendedCommand::DiskFormatProgress: { case ExtendedCommand::DiskFormatProgress: {
std::vector<uint8_t> responseBody( std::vector<uint8_t> responseBody(
+7 -11
View File
@@ -38,18 +38,10 @@ bool Driver::waitForRx(std::function<bool()> predicate, std::chrono::millisecond
} }
bool Driver::readWait(std::vector<uint8_t>& bytes, std::chrono::milliseconds timeout, size_t limit) { bool Driver::readWait(std::vector<uint8_t>& bytes, std::chrono::milliseconds timeout, size_t limit) {
// A limit of zero indicates no limit // wait until we have enough data, or the timeout occurs
if(limit == 0)
limit = (size_t)-1;
if(limit > (readBuffer.size() + 4))
limit = (readBuffer.size() + 4);
// wait until we have enough data, or the timout occurs
waitForRx(limit, timeout); waitForRx(limit, timeout);
size_t actuallyRead = std::min(readBuffer.size(), limit); size_t actuallyRead = readBuffer.size();
bytes.resize(actuallyRead); bytes.resize(actuallyRead);
readBuffer.read(bytes.data(), 0, actuallyRead); readBuffer.read(bytes.data(), 0, actuallyRead);
@@ -79,8 +71,12 @@ bool Driver::write(const std::vector<uint8_t>& bytes) {
if(writeBlocks) { if(writeBlocks) {
if(writeQueueFull()) { if(writeQueueFull()) {
while(writeQueueAlmostFull()) // Wait until we have some decent amount of space while(writeQueueAlmostFull() && !isDisconnected() && !isClosing()) // Wait until we have some decent amount of space
std::this_thread::sleep_for(std::chrono::milliseconds(10)); std::this_thread::sleep_for(std::chrono::milliseconds(10));
if(isDisconnected() || isClosing()) {
return false;
}
} }
} else { } else {
if(writeQueueFull()) { if(writeQueueFull()) {
+16 -1
View File
@@ -13,6 +13,7 @@
#include "icsneo/communication/packet/a2bpacket.h" #include "icsneo/communication/packet/a2bpacket.h"
#include "icsneo/communication/packet/linpacket.h" #include "icsneo/communication/packet/linpacket.h"
#include "icsneo/communication/packet/mdiopacket.h" #include "icsneo/communication/packet/mdiopacket.h"
#include "icsneo/communication/packet/spipacket.h"
using namespace icsneo; using namespace icsneo;
@@ -31,7 +32,8 @@ bool Encoder::encode(const Packetizer& packetizer, std::vector<uint8_t>& result,
netid = uint16_t(frame->network.getNetID()); netid = uint16_t(frame->network.getNetID());
switch(frame->network.getType()) { switch(frame->network.getType()) {
case Network::Type::Ethernet: { case Network::Type::Ethernet:
case Network::Type::AutomotiveEthernet: {
auto ethmsg = std::dynamic_pointer_cast<EthernetMessage>(message); auto ethmsg = std::dynamic_pointer_cast<EthernetMessage>(message);
if(!ethmsg) { if(!ethmsg) {
report(APIEvent::Type::MessageFormattingError, APIEvent::Severity::Error); report(APIEvent::Type::MessageFormattingError, APIEvent::Severity::Error);
@@ -54,6 +56,7 @@ bool Encoder::encode(const Packetizer& packetizer, std::vector<uint8_t>& result,
break; break;
} }
case Network::Type::Internal:
case Network::Type::CAN: case Network::Type::CAN:
case Network::Type::SWCAN: case Network::Type::SWCAN:
case Network::Type::LSFTCAN: { case Network::Type::LSFTCAN: {
@@ -133,6 +136,17 @@ bool Encoder::encode(const Packetizer& packetizer, std::vector<uint8_t>& result,
} }
break; break;
} // End of Network::Type::MDIO } // End of Network::Type::MDIO
case Network::Type::SPI: {
auto msg = std::dynamic_pointer_cast<SPIMessage>(message);
if(!msg) {
report(APIEvent::Type::MessageFormattingError, APIEvent::Severity::Error);
return false; // The message was not a properly formed LiveDataMessage
}
if(!HardwareSPIPacket::EncodeFromMessage(*msg, result, report))
return false;
result = packetizer.packetWrap(result, false);
return true;
} // End of Network::Type::SPI
default: default:
report(APIEvent::Type::UnexpectedNetworkType, APIEvent::Severity::Error); report(APIEvent::Type::UnexpectedNetworkType, APIEvent::Severity::Error);
return false; return false;
@@ -271,6 +285,7 @@ bool Encoder::encode(const Packetizer& packetizer, std::vector<uint8_t>& result,
case Command::RequestSerialNumber: case Command::RequestSerialNumber:
case Command::EnableNetworkCommunication: case Command::EnableNetworkCommunication:
case Command::EnableNetworkCommunicationEx: case Command::EnableNetworkCommunicationEx:
case Command::KeepAlive:
case Command::GetMainVersion: case Command::GetMainVersion:
case Command::GetSecondaryVersions: case Command::GetSecondaryVersions:
case Command::NeoReadMemory: case Command::NeoReadMemory:
+6 -5
View File
@@ -19,7 +19,8 @@ double liveDataValueToDouble(const LiveDataValue& val) {
return val.value * liveDataFixedPointToDouble; return val.value * liveDataFixedPointToDouble;
} }
bool liveDataDoubleToValue(const double& dFloat, LiveDataValue& value) { std::optional<LiveDataValue> liveDataDoubleToValue(const double& dFloat) {
LiveDataValue value;
union { union {
struct struct
{ {
@@ -56,23 +57,23 @@ bool liveDataDoubleToValue(const double& dFloat, LiveDataValue& value) {
value.value = CminiFixedPt.ValueLarge; value.value = CminiFixedPt.ValueLarge;
if(dFloat == (double)0.0) if(dFloat == (double)0.0)
return true; return value;
//check if double can be stored as 32.32 //check if double can be stored as 32.32
// 0x1 0000 0000 0000 0000 * CM_FIXED_POINT_TO_DOUBLEVALUE = 0x1 0000 0000 // 0x1 0000 0000 0000 0000 * CM_FIXED_POINT_TO_DOUBLEVALUE = 0x1 0000 0000
if(dFloat > INT32_MAX_DOUBLE || dFloat < INT32_MIN_DOUBLE) { if(dFloat > INT32_MAX_DOUBLE || dFloat < INT32_MIN_DOUBLE) {
EventManager::GetInstance().add(APIEvent::Type::FixedPointOverflow, APIEvent::Severity::Error); EventManager::GetInstance().add(APIEvent::Type::FixedPointOverflow, APIEvent::Severity::Error);
return false; return std::nullopt;
} }
// Use absolute value for minimum fixed point check // Use absolute value for minimum fixed point check
double absFloat = (dFloat < 0.0) ? -dFloat : dFloat; double absFloat = (dFloat < 0.0) ? -dFloat : dFloat;
if(absFloat < MIN_FIXED_POINT_DOUBLE) { if(absFloat < MIN_FIXED_POINT_DOUBLE) {
EventManager::GetInstance().add(APIEvent::Type::FixedPointPrecision, APIEvent::Severity::Error); EventManager::GetInstance().add(APIEvent::Type::FixedPointPrecision, APIEvent::Severity::Error);
return false; return std::nullopt;
} }
return true; return value;
} }
} // namespace LiveDataUtil } // namespace LiveDataUtil
+21
View File
@@ -0,0 +1,21 @@
#include "icsneo/communication/message/clientidmessage.h"
#include "icsneo/communication/icspb.h"
#include "icsneo/communication/command.h"
#include "icsneo/communication/message/extendedresponsemessage.h"
using namespace icsneo;
std::shared_ptr<ClientIdMessage> ClientIdMessage::DecodeToMessage(const std::vector<uint8_t>& bytestream) {
ClientIdMessage decoded;
commands::generic::v1::ClientId msg;
if(!protoapi::processResponse(bytestream.data(), bytestream.size(), msg)) {
return nullptr;
}
if(msg.has_client_id()) {
decoded.clientId.emplace(msg.client_id());
}
return std::make_shared<ClientIdMessage>(decoded);
}
@@ -13,7 +13,15 @@ enum LinkSpeed {
ethSpeed10000, ethSpeed10000,
}; };
enum LinkMode { enum TLinkMode {
T_LINK_NONE,
T_LINK_MASTER,
T_LINK_SLAVE,
T_LINK_AUTO,
T_LINK_INVALID = 255,
};
enum AELinkMode {
AE_LINK_AUTO, AE_LINK_AUTO,
AE_LINK_MASTER, AE_LINK_MASTER,
AE_LINK_SLAVE, AE_LINK_SLAVE,
@@ -46,11 +54,26 @@ std::shared_ptr<Message> EthernetStatusMessage::DecodeToMessage(const std::vecto
default: return nullptr; default: return nullptr;
} }
LinkMode mode; LinkMode mode;
switch(packet->mode) { switch(Network::GetTypeOfNetID((Network::NetID)packet->network, false)) {
case AE_LINK_INVALID: mode = EthernetStatusMessage::LinkMode::LinkModeInvalid; break; case Network::Type::Ethernet:
case AE_LINK_AUTO: mode = EthernetStatusMessage::LinkMode::LinkModeAuto; break; switch(packet->mode) {
case AE_LINK_MASTER: mode = EthernetStatusMessage::LinkMode::LinkModeMaster; break; case T_LINK_NONE: mode = EthernetStatusMessage::LinkMode::LinkModeNone; break;
case AE_LINK_SLAVE: mode = EthernetStatusMessage::LinkMode::LinkModeSlave; break; case T_LINK_MASTER: mode = EthernetStatusMessage::LinkMode::LinkModeMaster; break;
case T_LINK_SLAVE: mode = EthernetStatusMessage::LinkMode::LinkModeSlave; break;
case T_LINK_AUTO: mode = EthernetStatusMessage::LinkMode::LinkModeAuto; break;
case T_LINK_INVALID: mode = EthernetStatusMessage::LinkMode::LinkModeInvalid; break;
default: return nullptr;
}
break;
case Network::Type::AutomotiveEthernet:
switch(packet->mode) {
case AE_LINK_AUTO: mode = EthernetStatusMessage::LinkMode::LinkModeAuto; break;
case AE_LINK_MASTER: mode = EthernetStatusMessage::LinkMode::LinkModeMaster; break;
case AE_LINK_SLAVE: mode = EthernetStatusMessage::LinkMode::LinkModeSlave; break;
case AE_LINK_INVALID: mode = EthernetStatusMessage::LinkMode::LinkModeInvalid; break;
default: return nullptr;
}
break;
default: return nullptr; default: return nullptr;
} }
return std::make_shared<EthernetStatusMessage>(packet->network, packet->state, speed, packet->duplex, mode); return std::make_shared<EthernetStatusMessage>(packet->network, packet->state, speed, packet->duplex, mode);
+9 -9
View File
@@ -8,7 +8,7 @@ bool EthPhyMessage::appendPhyMessage(bool writeEnable, bool clause45, uint8_t ph
msg->Clause45Enable = clause45; msg->Clause45Enable = clause45;
msg->Enabled = enabled; msg->Enabled = enabled;
msg->WriteEnable = writeEnable; msg->WriteEnable = writeEnable;
msg->version = 1u; msg->Version = 1u;
if( (FiveBits < phyAddrOrPort) || if( (FiveBits < phyAddrOrPort) ||
(clause45 && (FiveBits < pageOrDevice)) || (clause45 && (FiveBits < pageOrDevice)) ||
(!clause45 && (FiveBits < regAddr)) ) (!clause45 && (FiveBits < regAddr)) )
@@ -18,17 +18,17 @@ bool EthPhyMessage::appendPhyMessage(bool writeEnable, bool clause45, uint8_t ph
if(clause45) if(clause45)
{ {
msg->clause45.port = phyAddrOrPort; msg->Clause45.port = phyAddrOrPort;
msg->clause45.device = pageOrDevice; msg->Clause45.device = pageOrDevice;
msg->clause45.regAddr = regAddr; msg->Clause45.regAddr = regAddr;
msg->clause45.regVal = regVal; msg->Clause45.regVal = regVal;
} }
else else
{ {
msg->clause22.phyAddr = phyAddrOrPort; msg->Clause22.phyAddr = phyAddrOrPort;
msg->clause22.page = pageOrDevice; msg->Clause22.page = pageOrDevice;
msg->clause22.regAddr = regAddr; msg->Clause22.regAddr = regAddr;
msg->clause22.regVal = regVal; msg->Clause22.regVal = regVal;
} }
return appendPhyMessage(msg); return appendPhyMessage(msg);
} }
@@ -7,9 +7,9 @@
using namespace icsneo; using namespace icsneo;
std::vector<uint8_t> FlexRayControlMessage::BuildBaseControlArgs(uint8_t controller, FlexRay::Opcode op, const std::vector<uint8_t>& args) { std::vector<uint8_t> FlexRayControlMessage::BuildBaseControlArgs(uint8_t controller, FlexRay::Opcode op, const std::vector<uint8_t>& args) {
std::vector<uint8_t> ret(args.size() + 4); std::vector<uint8_t> ret;
ret.push_back(controller); ret.push_back(controller);
const uint16_t size = uint16_t((std::min)(args.size() + 1, size_t(std::numeric_limits<uint16_t>::max()))); // Add 1 for the opcode const uint16_t size = static_cast<uint16_t>(std::min(args.size() + 1, size_t(std::numeric_limits<uint16_t>::max()))); // Add 1 for the opcode
ret.push_back(uint8_t(size)); ret.push_back(uint8_t(size));
ret.push_back(uint8_t(size >> 8)); ret.push_back(uint8_t(size >> 8));
ret.push_back(uint8_t(op)); ret.push_back(uint8_t(op));
-531
View File
@@ -1,531 +0,0 @@
#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 */
typedef union _MACSecFlags
{
struct
{
uint32_t en : 1; // '1' = enable; '0' = disable
uint32_t reserved : 31;
};
uint32_t flags_32b;
} MACSecFlags_t;
#define MACSEC_SETTINGS_FLAGS_SIZE (4)
/* 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
+4 -2
View File
@@ -44,7 +44,8 @@ neomessage_t icsneo::CreateNeoMessage(const std::shared_ptr<Message> message) {
can.status.canfdESI = canmsg->errorStateIndicator; can.status.canfdESI = canmsg->errorStateIndicator;
break; break;
} }
case Network::Type::Ethernet: { case Network::Type::Ethernet:
case Network::Type::AutomotiveEthernet: {
neomessage_eth_t& eth = *(neomessage_eth_t*)&neomsg; neomessage_eth_t& eth = *(neomessage_eth_t*)&neomsg;
auto ethmsg = std::static_pointer_cast<EthernetMessage>(message); auto ethmsg = std::static_pointer_cast<EthernetMessage>(message);
eth.preemptionFlags = ethmsg->preemptionFlags; eth.preemptionFlags = ethmsg->preemptionFlags;
@@ -142,7 +143,8 @@ std::shared_ptr<Message> icsneo::CreateMessageFromNeoMessage(const neomessage_t*
canmsg->errorStateIndicator = can.status.canfdESI; canmsg->errorStateIndicator = can.status.canfdESI;
return canmsg; return canmsg;
} }
case Network::Type::Ethernet: { case Network::Type::Ethernet:
case Network::Type::AutomotiveEthernet: {
neomessage_eth_t& eth = *(neomessage_eth_t*)neomessage; neomessage_eth_t& eth = *(neomessage_eth_t*)neomessage;
auto ethmsg = std::make_shared<EthernetMessage>(); auto ethmsg = std::make_shared<EthernetMessage>();
ethmsg->network = network; ethmsg->network = network;
@@ -0,0 +1,89 @@
#include "icsneo/communication/message/networkmutexmessage.h"
#include "icsneo/communication/icspb.h"
#include "icsneo/communication/command.h"
#include "icsneo/communication/message/extendedresponsemessage.h"
using namespace icsneo;
std::shared_ptr<NetworkMutexMessage> NetworkMutexMessage::DecodeToMessage(const std::vector<uint8_t>& bytestream) {
NetworkMutexMessage decoded;
commands::network::v1::NetworkMutex msg;
if(!protoapi::processResponse(bytestream.data(), bytestream.size(), msg)) {
return nullptr;
}
if(msg.has_client_id()) {
decoded.owner_id.emplace(msg.client_id());
}
if(msg.has_type()) {
decoded.type.emplace(static_cast<NetworkMutexType>(msg.type()));
}
if(msg.has_priority()) {
decoded.priority.emplace(msg.priority());
}
if(msg.has_ttl()){
decoded.ttlMs.emplace(msg.ttl());
}
if(msg.has_event()){
decoded.event.emplace(static_cast<NetworkMutexEvent>(msg.event()));
}
for(int i = 0 ; i < msg.network_ids_size(); ++i){
decoded.networks.emplace(static_cast<Network::NetID>(msg.network_ids(i)));
}
return std::make_shared<NetworkMutexMessage>(decoded);
}
std::vector<uint8_t> NetworkMutexMessage::EncodeArgumentsForLock(uint32_t client_id, NetworkMutexType type, uint32_t priority, uint32_t ttlMs, const std::set<Network::NetID>& networks, const device_eventhandler_t& /* report */) {
commands::network::v1::NetworkMutex msg;
for(auto&& network_id : networks) {
msg.add_network_ids(static_cast<commands::network::v1::NetworkId>(network_id));
}
msg.set_client_id(client_id);
msg.set_priority(priority);
msg.set_ttl(ttlMs);
msg.set_type(static_cast<commands::network::v1::MutexType>(type));
return protoapi::getPayload(protoapi::Command::PUT, msg);
}
std::vector<uint8_t> NetworkMutexMessage::EncodeArgumentsForLockAll(uint32_t client_id, NetworkMutexType type, uint32_t priority, uint32_t ttlMs, const device_eventhandler_t& /* report */) {
commands::network::v1::NetworkMutex msg;
msg.set_client_id(client_id);
msg.set_priority(priority);
msg.set_ttl(ttlMs);
msg.set_type(static_cast<commands::network::v1::MutexType>(type));
msg.set_global(true);
return protoapi::getPayload(protoapi::Command::PUT, msg);
}
std::vector<uint8_t> NetworkMutexMessage::EncodeArgumentsForUnlock(uint32_t client_id, const std::set<Network::NetID>& networks, const device_eventhandler_t& /* report */) {
commands::network::v1::NetworkMutex msg;
msg.Clear();
for(auto&& network_id : networks)
{
msg.add_network_ids(static_cast<commands::network::v1::NetworkId>(network_id));
}
msg.set_client_id(client_id);
msg.set_release(true);
return protoapi::getPayload(protoapi::Command::PUT, msg);
}
std::vector<uint8_t> NetworkMutexMessage::EncodeArgumentsForUnlockAll(uint32_t client_id, const device_eventhandler_t& /* report */) {
commands::network::v1::NetworkMutex msg;
msg.Clear();
msg.set_client_id(client_id);
msg.set_release(true);
msg.set_global(true);
return protoapi::getPayload(protoapi::Command::PUT, msg);
}
std::vector<uint8_t> NetworkMutexMessage::EncodeArgumentsForStatus(Network::NetID network, const device_eventhandler_t& /* report */) {
commands::network::v1::NetworkMutex msg;
msg.add_network_ids(static_cast<commands::network::v1::NetworkId>(network));
return protoapi::getPayload(protoapi::Command::GET, msg);
}
+163
View File
@@ -0,0 +1,163 @@
#include "icsneo/communication/message/transmitmessage.h"
// packet defs
#include "icsneo/communication/packet/ethernetpacket.h"
#include "icsneo/communication/packet/canpacket.h"
#include "icsneo/communication/packet/linpacket.h"
using namespace icsneo;
// copied.. TODO
static std::optional<uint8_t> CAN_LengthToDLC(size_t dataLength, bool fd) {
if(dataLength <= 8)
return uint8_t(dataLength);
if(fd) {
if(dataLength <= 12)
return uint8_t(0x9);
if(dataLength <= 16)
return uint8_t(0xA);
if(dataLength <= 20)
return uint8_t(0xB);
if(dataLength <= 24)
return uint8_t(0xC);
if(dataLength <= 32)
return uint8_t(0xD);
if(dataLength <= 48)
return uint8_t(0xE);
if(dataLength <= 64)
return uint8_t(0xF);
}
return std::nullopt;
}
static std::vector<uint8_t> EncodeFromMessageEthernet(std::shared_ptr<Frame> frame, const device_eventhandler_t& report) {
auto ethmsg = std::dynamic_pointer_cast<EthernetMessage>(frame);
if(!ethmsg) {
report(APIEvent::Type::MessageFormattingError, APIEvent::Severity::Error);
return {};
}
std::vector<uint8_t> encoded;
size_t messageLen = ethmsg->data.size();
encoded.resize(sizeof(TransmitMessage) + messageLen);
TransmitMessage* const msg = (TransmitMessage*)encoded.data();
HardwareEthernetPacket* const ethpacket = (HardwareEthernetPacket*)(msg->commonHeader);
uint8_t* const payload = encoded.data() + sizeof(TransmitMessage);
ethpacket->header.ENABLE_PADDING = ethmsg->noPadding ? 0 : 1;
ethpacket->header.FCS_OVERRIDE = ethmsg->fcs ? 1 : 0;
ethpacket->eid.txlen = static_cast<uint16_t>(messageLen);
ethpacket->Length = static_cast<uint16_t>(messageLen);
ethpacket->stats = ethmsg->description;
ethpacket->NetworkID = static_cast<uint16_t>(ethmsg->network.getNetID());
std::copy(ethmsg->data.begin(), ethmsg->data.end(), payload);
return encoded;
}
static std::vector<uint8_t> EncodeFromMessageCAN(std::shared_ptr<Frame> frame, const device_eventhandler_t& report) {
auto canmsg = std::dynamic_pointer_cast<CANMessage>(frame);
if(!canmsg) {
report(APIEvent::Type::MessageFormattingError, APIEvent::Severity::Error);
return {};
}
if(canmsg->isCANFD && canmsg->isRemote) {
report(APIEvent::Type::RTRNotSupported, APIEvent::Severity::Error);
return {}; // RTR frames can not be used with CAN FD
}
std::vector<uint8_t> encoded;
size_t messageLen = canmsg->data.size();
size_t extraLen = 0;
if(messageLen > 8) {
extraLen = messageLen - 8;
}
encoded.resize(sizeof(TransmitMessage) + extraLen);
TransmitMessage* const msg = (TransmitMessage*)encoded.data();
HardwareCANPacket* const canpacket = (HardwareCANPacket*)(msg->commonHeader);
uint8_t* const extra_payload = encoded.data() + sizeof(TransmitMessage);
const size_t dataSize = canmsg->data.size();
std::optional<uint8_t> dlc = CAN_LengthToDLC(dataSize, canmsg->isCANFD);
if(!dlc.has_value()) {
report(APIEvent::Type::MessageMaxLengthExceeded, APIEvent::Severity::Error);
return {}; // Too much data for the protocol
}
// arb id
if(canmsg->isExtended) {
canpacket->header.IDE = 1;
canpacket->header.SID = (canmsg->arbid >> 18) & 0x7FF;
canpacket->eid.EID = (canmsg->arbid >> 6) & 0xfff;
canpacket->dlc.EID2 = canmsg->arbid & 0x3f;
} else {
canpacket->header.IDE = 0;
canpacket->header.SID = canmsg->arbid & 0x7FF;
}
// DLC
canpacket->dlc.DLC = dlc.value();
// FDF/BRS or remote frames
if(canmsg->isCANFD) {
canpacket->header.EDL = 1;
canpacket->header.BRS = canmsg->baudrateSwitch ? 1 : 0;
canpacket->header.ESI = canmsg->errorStateIndicator ? 1 : 0;
canpacket->dlc.RTR = 0;
canpacket->timestamp.IsExtended = 1;
} else {
canpacket->header.EDL = 0;
canpacket->header.BRS = 0;
canpacket->header.ESI = 0;
canpacket->dlc.RTR = canmsg->isRemote ? 1 : 0;
}
// network
canpacket->NetworkID = static_cast<uint16_t>(canmsg->network.getNetID());
canpacket->Length = static_cast<uint16_t>(extraLen);
// description id
canpacket->stats = canmsg->description;
// first 8 bytes
std::copy(canmsg->data.begin(), canmsg->data.begin() + (messageLen > 8 ? 8 : messageLen), canpacket->data);
// extra bytes
if(extraLen > 0) {
// copy extra data after the can packet
std::copy(canmsg->data.begin() + 8, canmsg->data.end(), extra_payload);
}
return encoded;
}
static std::vector<uint8_t> EncodeFromMessageLIN(std::shared_ptr<Frame> /* frame */, const device_eventhandler_t& report) {
// TODO
report(APIEvent::Type::UnsupportedTXNetwork, APIEvent::Severity::Error);
return {};
}
std::vector<uint8_t> TransmitMessage::EncodeFromMessage(std::shared_ptr<Frame> frame, uint32_t client_id, const device_eventhandler_t& report) {
std::vector<uint8_t> result;
switch(frame->network.getType()) {
case Network::Type::Ethernet:
case Network::Type::AutomotiveEthernet:
result = EncodeFromMessageEthernet(frame, report);
break;
case Network::Type::Internal:
case Network::Type::CAN:
result = EncodeFromMessageCAN(frame, report);
break;
case Network::Type::LIN:
result = EncodeFromMessageLIN(frame, report);
break;
default:
report(APIEvent::Type::UnexpectedNetworkType, APIEvent::Severity::Error);
return result;
}
// common fields
TransmitMessage* const msg = (TransmitMessage*)result.data();
msg->options.clientId = client_id;
msg->options.networkId = static_cast<uint32_t>(frame->network.getNetID());
msg->options.reserved[0] = 0;
msg->options.reserved[1] = 0;
msg->options.reserved[2] = 0;
return result;
}
+22 -13
View File
@@ -9,7 +9,7 @@ using namespace icsneo;
MultiChannelCommunication::MultiChannelCommunication(device_eventhandler_t err, std::unique_ptr<Driver> com, MultiChannelCommunication::MultiChannelCommunication(device_eventhandler_t err, std::unique_ptr<Driver> com,
std::function<std::unique_ptr<Packetizer>()> makeConfiguredPacketizer, std::unique_ptr<Encoder> e, std::function<std::unique_ptr<Packetizer>()> makeConfiguredPacketizer, std::unique_ptr<Encoder> e,
std::unique_ptr<Decoder> md, size_t vnetCount) : std::unique_ptr<Decoder> md, size_t vnetCount) :
Communication(err, std::move(com), makeConfiguredPacketizer, std::move(e), std::move(md)), numVnets(vnetCount) { Communication(err, std::move(com), makeConfiguredPacketizer, std::move(e), std::move(md)), numVnets(vnetCount), packetRB(2048) {
vnetThreads.resize(numVnets); vnetThreads.resize(numVnets);
vnetQueues.resize(numVnets); vnetQueues.resize(numVnets);
} }
@@ -24,6 +24,7 @@ void MultiChannelCommunication::spawnThreads() {
void MultiChannelCommunication::joinThreads() { void MultiChannelCommunication::joinThreads() {
closing = true; closing = true;
ringBufCV.notify_all();
if(hidReadThread.joinable()) if(hidReadThread.joinable())
hidReadThread.join(); hidReadThread.join();
for(auto& thread : vnetThreads) { for(auto& thread : vnetThreads) {
@@ -148,9 +149,13 @@ void MultiChannelCommunication::hidReadTask() {
break; break;
} }
if(!currentQueue->enqueue(std::move(payloadBytes)) && gotPacket) {
EventManager::GetInstance().add(APIEvent(APIEvent::Type::FailedToRead, APIEvent::Severity::Error)); std::unique_lock lk(ringBufMutex);
payloadBytes.clear(); if(!packetRB.write(std::move(payloadBytes)) && gotPacket)
EventManager::GetInstance().add(APIEvent(APIEvent::Type::FailedToRead, APIEvent::Severity::Error));
payloadBytes.clear();
}
ringBufCV.notify_all();
gotPacket = true; gotPacket = true;
state = PreprocessState::SearchForCommand; state = PreprocessState::SearchForCommand;
break; break;
@@ -160,7 +165,6 @@ void MultiChannelCommunication::hidReadTask() {
} }
void MultiChannelCommunication::vnetReadTask(size_t vnetIndex) { void MultiChannelCommunication::vnetReadTask(size_t vnetIndex) {
moodycamel::BlockingReaderWriterQueue< std::vector<uint8_t> >& queue = vnetQueues[vnetIndex];
std::vector<uint8_t> payloadBytes; std::vector<uint8_t> payloadBytes;
std::unique_ptr<Packetizer> packetizerLifetime; std::unique_ptr<Packetizer> packetizerLifetime;
Packetizer* vnetPacketizer; Packetizer* vnetPacketizer;
@@ -174,14 +178,19 @@ void MultiChannelCommunication::vnetReadTask(size_t vnetIndex) {
EventManager::GetInstance().downgradeErrorsOnCurrentThread(); EventManager::GetInstance().downgradeErrorsOnCurrentThread();
while(!closing) { while(!closing) {
if(queue.wait_dequeue_timed(payloadBytes, std::chrono::milliseconds(250))) { std::unique_lock lk(ringBufMutex);
if(closing) ringBufCV.wait(lk);
break; if(closing) {
break;
auto& ringBuffer = driver->getReadBuffer();
ringBuffer.write(payloadBytes);
handleInput(*vnetPacketizer);
} }
if(vnetPacketizer->input(packetRB)) {
for(const auto& packet : vnetPacketizer->output()) {
std::shared_ptr<Message> msg;
if(!decoder->decode(msg, packet))
continue;
dispatchMessage(msg);
}
}
} }
} }
+1 -1
View File
@@ -114,7 +114,7 @@ std::shared_ptr<Message> HardwareCANPacket::DecodeToMessage(const std::vector<ui
msg->data.insert(msg->data.end(), data->data, data->data + (length > 8 ? 8 : length)); msg->data.insert(msg->data.end(), data->data, data->data + (length > 8 ? 8 : length));
if(length > 8) { // If there are more than 8 bytes, they come at the end of the message if(length > 8) { // If there are more than 8 bytes, they come at the end of the message
// Messages with extra data are formatted as message, then uint16_t netid, then uint16_t length, then extra data // Messages with extra data are formatted as message, then uint16_t netid, then uint16_t length, then extra data
const auto extraDataStart = bytestream.begin() + sizeof(HardwareCANPacket) + 2 + 2; const auto extraDataStart = bytestream.begin() + sizeof(HardwareCANPacket);
msg->data.insert(msg->data.end(), extraDataStart, extraDataStart + (length - 8)); msg->data.insert(msg->data.end(), extraDataStart, extraDataStart + (length - 8));
} }
} }
+22 -8
View File
@@ -1,28 +1,26 @@
#include "icsneo/communication/packet/ethernetpacket.h" #include "icsneo/communication/packet/ethernetpacket.h"
#include <algorithm> // for std::copy #include <algorithm>
#include <iostream> #include <iostream>
using namespace icsneo; using namespace icsneo;
std::shared_ptr<EthernetMessage> HardwareEthernetPacket::DecodeToMessage(const std::vector<uint8_t>& bytestream, const device_eventhandler_t& report) { std::shared_ptr<EthernetMessage> HardwareEthernetPacket::DecodeToMessage(const std::vector<uint8_t>& bytestream) {
const HardwareEthernetPacket* packet = (const HardwareEthernetPacket*)((const void*)bytestream.data()); const HardwareEthernetPacket* packet = (const HardwareEthernetPacket*)((const void*)bytestream.data());
const uint16_t* rawWords = (const uint16_t*)bytestream.data(); const uint16_t* rawWords = (const uint16_t*)bytestream.data();
// Make sure we have enough to read the packet length first // Make sure we have enough to read the packet length first
if(bytestream.size() < sizeof(HardwareEthernetPacket)) if(bytestream.size() < sizeof(HardwareEthernetPacket))
return nullptr; return nullptr;
// packet->Length will also encompass the two uint16_t's at the end of the struct, make sure that at least they are here
if(packet->Length < 4)
return nullptr;
const size_t fcsSize = packet->header.FCS_AVAIL ? 4 : 0; const size_t fcsSize = packet->header.FCS_AVAIL ? 4 : 0;
// Ensure Length is sufficient for FCS extraction to avoid invalid iterator arithmetic
if(packet->Length < fcsSize)
return nullptr;
const size_t bytestreamExpectedSize = sizeof(HardwareEthernetPacket) + packet->Length; 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;
// Check for oversized packets, noting that some devices will send an extra byte to have an even number of bytes
if(bytestreamActualSize > bytestreamExpectedSize + 1)
report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::EventWarning);
auto messagePtr = std::make_shared<EthernetMessage>(); auto messagePtr = std::make_shared<EthernetMessage>();
EthernetMessage& message = *messagePtr; EthernetMessage& message = *messagePtr;
// Standard Ethernet fields
message.transmitted = packet->eid.TXMSG; message.transmitted = packet->eid.TXMSG;
if(message.transmitted) if(message.transmitted)
message.description = packet->stats; message.description = packet->stats;
@@ -30,12 +28,28 @@ 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.frameTooShort = packet->header.RUNT_FRAME; message.frameTooShort = packet->header.RUNT_FRAME;
message.noPadding = !packet->header.ENABLE_PADDING;
message.fcsVerified = packet->header.FCS_VERIFIED;
message.txAborted = packet->eid.TXAborted;
message.crcError = packet->header.CRC_ERROR;
if(message.frameTooShort) if(message.frameTooShort)
message.error = true; message.error = true;
// 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
message.timestamp = packet->timestamp.TS; message.timestamp = packet->timestamp.TS;
// Check if this is a T1S packet and populate T1S-specific fields
message.isT1S = packet->header.T1S_ETHERNET;
if(message.isT1S) {
message.isT1SSymbol = packet->eid.T1S_SYMBOL;
message.isT1SBurst = packet->eid.T1S_BURST;
message.txCollision = packet->t1s_status.TXCollision;
message.isT1SWake = packet->t1s_status.T1SWake;
message.t1sNodeId = packet->t1s_node.T1S_NODE_ID;
message.t1sBurstCount = packet->t1s_node.T1S_BURST_COUNT;
}
const std::vector<uint8_t>::const_iterator databegin = bytestream.begin() + sizeof(HardwareEthernetPacket); 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 dataend = databegin + packet->Length - fcsSize;
message.data.insert(message.data.begin(), databegin, dataend); message.data.insert(message.data.begin(), databegin, dataend);
+18 -16
View File
@@ -34,11 +34,12 @@ std::shared_ptr<EthPhyMessage> HardwareEthernetPhyRegisterPacket::DecodeToMessag
phyMessage->Enabled = (pEntry->Enabled != 0u); phyMessage->Enabled = (pEntry->Enabled != 0u);
phyMessage->WriteEnable = (pEntry->WriteEnable != 0u); phyMessage->WriteEnable = (pEntry->WriteEnable != 0u);
phyMessage->Clause45Enable = (pEntry->Clause45Enable != 0u); phyMessage->Clause45Enable = (pEntry->Clause45Enable != 0u);
phyMessage->version = static_cast<uint8_t>(pEntry->version); phyMessage->BusIndex = static_cast<uint8_t>(pEntry->BusIndex);
phyMessage->Version = static_cast<uint8_t>(pEntry->version);
if(phyMessage->Clause45Enable) if(phyMessage->Clause45Enable)
phyMessage->clause45 = pEntry->clause45; phyMessage->Clause45 = pEntry->clause45;
else else
phyMessage->clause22 = pEntry->clause22; phyMessage->Clause22 = pEntry->clause22;
msg->messages.push_back(phyMessage); msg->messages.push_back(phyMessage);
} }
} }
@@ -69,34 +70,35 @@ bool HardwareEthernetPhyRegisterPacket::EncodeFromMessage(const EthPhyMessage& m
PhyRegisterPacket_t tempPacket; PhyRegisterPacket_t tempPacket;
tempPacket.Enabled = phyMessage->Enabled ? 0x1u : 0x0u; tempPacket.Enabled = phyMessage->Enabled ? 0x1u : 0x0u;
tempPacket.WriteEnable = phyMessage->WriteEnable ? 0x1u : 0x0u; tempPacket.WriteEnable = phyMessage->WriteEnable ? 0x1u : 0x0u;
tempPacket.version = (phyMessage->version & 0xF); tempPacket.BusIndex = (phyMessage->BusIndex & 0xF);
tempPacket.version = (phyMessage->Version & 0xF);
if(phyMessage->Clause45Enable) if(phyMessage->Clause45Enable)
{ {
if( (FiveBits < phyMessage->clause45.port) || if( (FiveBits < phyMessage->Clause45.port) ||
(FiveBits < phyMessage->clause45.device) ) (FiveBits < phyMessage->Clause45.device) )
{ {
report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error); report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error);
return false; return false;
} }
tempPacket.Clause45Enable = 0x1u; tempPacket.Clause45Enable = 0x1u;
tempPacket.clause45.port = phyMessage->clause45.port; tempPacket.clause45.port = phyMessage->Clause45.port;
tempPacket.clause45.device = phyMessage->clause45.device; tempPacket.clause45.device = phyMessage->Clause45.device;
tempPacket.clause45.regAddr = phyMessage->clause45.regAddr; tempPacket.clause45.regAddr = phyMessage->Clause45.regAddr;
tempPacket.clause45.regVal = phyMessage->clause45.regVal; tempPacket.clause45.regVal = phyMessage->Clause45.regVal;
} }
else else
{ {
if( (FiveBits < phyMessage->clause22.phyAddr) || if( (FiveBits < phyMessage->Clause22.phyAddr) ||
(FiveBits < phyMessage->clause22.regAddr) ) (FiveBits < phyMessage->Clause22.regAddr) )
{ {
report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error); report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error);
return false; return false;
} }
tempPacket.Clause45Enable = 0x0u; tempPacket.Clause45Enable = 0x0u;
tempPacket.clause22.phyAddr = phyMessage->clause22.phyAddr; tempPacket.clause22.phyAddr = phyMessage->Clause22.phyAddr;
tempPacket.clause22.page = phyMessage->clause22.page; tempPacket.clause22.page = phyMessage->Clause22.page;
tempPacket.clause22.regAddr = phyMessage->clause22.regAddr; tempPacket.clause22.regAddr = phyMessage->Clause22.regAddr;
tempPacket.clause22.regVal = phyMessage->clause22.regVal; tempPacket.clause22.regVal = phyMessage->Clause22.regVal;
} }
uint8_t* pktPtr = reinterpret_cast<uint8_t*>(&tempPacket); uint8_t* pktPtr = reinterpret_cast<uint8_t*>(&tempPacket);
bytestream.insert(bytestream.end(), pktPtr, pktPtr + sizeof(PhyRegisterPacket_t)); bytestream.insert(bytestream.end(), pktPtr, pktPtr + sizeof(PhyRegisterPacket_t));
+1 -1
View File
@@ -49,7 +49,7 @@ namespace icsneo
report(APIEvent::Type::I2CMessageExceedsMaxLength, APIEvent::Severity::Error); report(APIEvent::Type::I2CMessageExceedsMaxLength, APIEvent::Severity::Error);
return false; return false;
} }
if(message.controlBytes.empty() || message.dataBytes.empty()) if(message.controlBytes.empty() && message.dataBytes.empty())
{ {
//You'll need to provide a target R/W register in controlBytes //You'll need to provide a target R/W register in controlBytes
//alternatively, you're expecting to read without providing a dataBytes payload //alternatively, you're expecting to read without providing a dataBytes payload
+1 -2
View File
@@ -9,7 +9,7 @@ std::shared_ptr<Message> HardwareLINPacket::DecodeToMessage(const std::vector<ui
size_t numDataBytes = packet->CoreMiniBitsLIN.len; size_t numDataBytes = packet->CoreMiniBitsLIN.len;
size_t numHeaderBytes = sizeof(HardwareLINPacket::CoreMiniBitsLIN); size_t numHeaderBytes = sizeof(HardwareLINPacket::CoreMiniBitsLIN);
if( (sizeof(HardwareLINPacket) != bytestream.size()) || if( (sizeof(HardwareLINPacket) > bytestream.size()) ||
((numDataBytes + numHeaderBytes) > bytestream.size()) ) ((numDataBytes + numHeaderBytes) > bytestream.size()) )
return nullptr; return nullptr;
@@ -17,7 +17,6 @@ std::shared_ptr<Message> HardwareLINPacket::DecodeToMessage(const std::vector<ui
--numDataBytes; //If data is present, there will be a checksum included --numDataBytes; //If data is present, there will be a checksum included
auto msg = std::make_shared<LINMessage>(static_cast<uint8_t>(packet->CoreMiniBitsLIN.ID)); auto msg = std::make_shared<LINMessage>(static_cast<uint8_t>(packet->CoreMiniBitsLIN.ID));
msg->network = Network::GetNetIDFromCoreMiniNetwork(static_cast<Network::CoreMini>(packet->networkID));
msg->isEnhancedChecksum = static_cast<bool>(packet->CoreMiniBitsLIN.TxChkSumEnhanced); msg->isEnhancedChecksum = static_cast<bool>(packet->CoreMiniBitsLIN.TxChkSumEnhanced);
/* Minimum one responder byte and one checksum byte. */ /* Minimum one responder byte and one checksum byte. */
+82
View File
@@ -0,0 +1,82 @@
#include "icsneo/communication/packet/spipacket.h"
#include "icsneo/communication/command.h"
#include <cstring>
#include <vector>
using namespace icsneo;
static size_t SPISubHeaderLength = 5u;
std::shared_ptr<Message> HardwareSPIPacket::DecodeToMessage(const std::vector<uint8_t>& bytestream) {
if(bytestream.size() < sizeof(HardwareSPIPacket)) {
return nullptr;
}
const HardwareSPIPacket* packet = (const HardwareSPIPacket*)bytestream.data();
size_t totalPackedLength = static_cast<size_t>(bytestream.size()) - sizeof(HardwareSPIPacket); // First 28 bytes are message header.
if(totalPackedLength < SPISubHeaderLength) {
return nullptr;
}
const uint8_t* bytes = bytestream.data() + sizeof(HardwareSPIPacket);
std::shared_ptr<SPIMessage> msg = std::make_shared<SPIMessage>();
msg->direction = static_cast<SPIMessage::Direction>(bytes[0]);
msg->address = *reinterpret_cast<const uint16_t*>(&bytes[1]);
msg->mms = bytes[3];
msg->stats = packet->stats;
msg->timestamp = packet->timestamp.TS;
size_t numWords = (totalPackedLength - SPISubHeaderLength) / 4;
msg->payload.reserve(numWords);
for(size_t offset = SPISubHeaderLength; offset < totalPackedLength; offset += 4) {
msg->payload.push_back(*reinterpret_cast<const uint32_t*>(bytes + offset));
}
return msg;
}
bool HardwareSPIPacket::EncodeFromMessage(const SPIMessage& message, std::vector<uint8_t>& bytestream, const device_eventhandler_t& /*report*/) {
// Payload length is everything excluding cmdHeader (note at the beginning there is an offset of 2)
uint16_t payloadLength = static_cast<uint16_t>(
2 +
sizeof(HardwareSPIPacket) +
SPISubHeaderLength +
message.payload.size() * sizeof(uint32_t)
);
if(payloadLength % 2) {
// Pad payload to even number
payloadLength++;
}
// +1 for AA, another +1 for firmware nuance
uint16_t fullSize = 1 + sizeof(ExtendedCommandHeader) + payloadLength + 1;
uint16_t unwrappedSize = sizeof(ExtendedCommandHeader) + payloadLength; // fullSize without AA and firmware nuance
bytestream.resize(unwrappedSize, 0);
uint32_t offset = 0;
auto* cmdHeader = reinterpret_cast<ExtendedCommandHeader*>(bytestream.data() + offset);
cmdHeader->netid = static_cast<uint8_t>(Network::NetID::Main51);
cmdHeader->fullLength = fullSize;
cmdHeader->command = static_cast<uint8_t>(Command::Extended);
cmdHeader->extendedCommand = static_cast<uint16_t>(ExtendedCommand::TransmitCoreminiMessage);
cmdHeader->payloadLength = payloadLength;
offset += sizeof(ExtendedCommandHeader) + 2; // Offset of 2 between header and packet
auto* packet = reinterpret_cast<HardwareSPIPacket*>(bytestream.data() + offset);
packet->header.frameLength = static_cast<uint16_t>(SPISubHeaderLength + message.payload.size() * sizeof(uint32_t));
packet->networkID = static_cast<uint16_t>(message.network.getNetID());
packet->length = packet->header.frameLength;
packet->timestamp.IsExtended = 1;
offset += sizeof(HardwareSPIPacket);
// Write the sub header details
bytestream[offset++] = static_cast<uint8_t>(message.direction);
bytestream[offset++] = static_cast<uint8_t>(message.address & 0xFF);
bytestream[offset++] = static_cast<uint8_t>((message.address >> 8) & 0xFF);
bytestream[offset++] = static_cast<uint8_t>(message.mms);
bytestream[offset++] = static_cast<uint8_t>(message.payload.size());
// Write the words
for(uint32_t word : message.payload) {
*reinterpret_cast<uint32_t*>(bytestream.data() + offset) = word;
offset += sizeof(uint32_t);
}
return true;
}
+41 -7
View File
@@ -31,24 +31,46 @@ std::shared_ptr<WiVI::ResponseMessage> WiVI::CommandPacket::DecodeToMessage(cons
break; break;
} }
case WiVI::Command::GetAll: { case WiVI::Command::GetAll: {
if(bytestream.size() < sizeof(WiVI::CommandPacket::GetAll)) if(bytestream.size() < sizeof(WiVI::CommandPacket::GetAllHeader))
return {}; return {};
const auto& getAll = *reinterpret_cast<const WiVI::CommandPacket::GetAll*>(bytestream.data()); const auto& getAll = *reinterpret_cast<const WiVI::CommandPacket::GetAllHeader*>(bytestream.data());
msg->responseTo = WiVI::Command::GetAll; msg->responseTo = WiVI::Command::GetAll;
msg->info.emplace(); msg->info.emplace();
msg->info->sleepRequest = getAll.sleepRequest; msg->info->sleepRequest = getAll.sleepRequest;
msg->info->connectionTimeoutMinutes = getAll.connectionTimeoutMinutes; msg->info->connectionTimeoutMinutes = getAll.connectionTimeoutMinutes;
// Check that we have enough data for the capture infos // Check that we have enough data for the capture infos
if(bytestream.size() < sizeof(WiVI::CommandPacket::GetAll) + (sizeof(WiVI::CaptureInfo) * getAll.numCaptureInfos)) size_t captureInfosSize = sizeof(WiVI::CaptureInfo) * getAll.numCaptureInfos;
if(bytestream.size() < sizeof(WiVI::CommandPacket::GetAllHeader) + captureInfosSize)
return {}; return {};
const WiVI::CaptureInfo* const captureInfos = (const WiVI::CaptureInfo*)(bytestream.data() + sizeof(WiVI::CommandPacket::GetAllHeader));
msg->info->captures.resize(getAll.numCaptureInfos); msg->info->captures.resize(getAll.numCaptureInfos);
for(uint16_t i = 0; i < getAll.numCaptureInfos; i++) for(uint16_t i = 0; i < getAll.numCaptureInfos; i++)
msg->info->captures[i] = getAll.captureInfos[i]; msg->info->captures[i] = captureInfos[i];
// New field vinAvail was added - check if it is present:
if(bytestream.size() >= sizeof(WiVI::CommandPacket::GetAllHeader) + captureInfosSize + 2) {
msg->info->vinAvailable = *(bytestream.data() + sizeof(WiVI::CommandPacket::GetAllHeader) + captureInfosSize);
} else {
msg->info->vinAvailable = 0;
}
break; break;
} }
case WiVI::Command::GetVIN: {
if (bytestream.size() < sizeof(WiVI::CommandPacket::GetVIN))
return {};
const auto& getVIN = *reinterpret_cast<const WiVI::CommandPacket::GetVIN*>(bytestream.data());
msg->responseTo = WiVI::Command::GetVIN;
msg->vin = getVIN.VIN;
break;
}
default: // Unknown command response default: // Unknown command response
return {}; return {};
} }
@@ -78,9 +100,9 @@ std::vector<uint8_t> WiVI::CommandPacket::SetSignal::Encode(WiVI::SignalType typ
return ret; return ret;
} }
std::vector<uint8_t> WiVI::CommandPacket::GetAll::Encode() { std::vector<uint8_t> WiVI::CommandPacket::GetAllHeader::Encode() {
std::vector<uint8_t> ret(sizeof(WiVI::CommandPacket::GetAll)); std::vector<uint8_t> ret(sizeof(WiVI::CommandPacket::GetAllHeader));
auto& frame = *reinterpret_cast<WiVI::CommandPacket::GetAll*>(ret.data()); auto& frame = *reinterpret_cast<WiVI::CommandPacket::GetAllHeader*>(ret.data());
frame.header.cmd = WiVI::Command::GetAll; frame.header.cmd = WiVI::Command::GetAll;
frame.header.length = sizeof(frame) - sizeof(frame.header); frame.header.length = sizeof(frame) - sizeof(frame.header);
@@ -98,3 +120,15 @@ std::vector<uint8_t> WiVI::CommandPacket::ClearUploads::Encode(const std::vector
return ret; return ret;
} }
std::vector<uint8_t> WiVI::CommandPacket::GetVIN::Encode()
{
std::vector<uint8_t> ret(sizeof(WiVI::CommandPacket::GetVIN));
auto& frame = *reinterpret_cast<WiVI::CommandPacket::GetVIN*>(ret.data());
frame.header.cmd = WiVI::Command::GetVIN;
frame.header.length = sizeof(frame) - sizeof(frame.header);
return ret;
}
-91
View File
@@ -1,91 +0,0 @@
#include "icsneo/communication/ringbuffer.h"
#include <stdexcept>
namespace icsneo {
RingBuffer::RingBuffer(size_t bufferSize) : readCursor(0), writeCursor(0) {
// round the buffer size to the nearest power of 2
bufferSize = RoundUp(bufferSize);
mask = bufferSize - 1;
buf = new uint8_t[bufferSize];
}
RingBuffer::~RingBuffer() {
delete[] buf;
buf = nullptr;
}
const uint8_t& RingBuffer::operator[](size_t offset) const {
return get(offset);
}
size_t RingBuffer::size() const {
// The values in the cursors are monotonic, i.e. they only ever increment. They can be considered to be the total number of elements ever written or read
auto currentWriteCursor = writeCursor.load(std::memory_order_relaxed);
auto currentReadCursor = readCursor.load(std::memory_order_relaxed);
// Using unmasked values, writeCursor is guaranteed to be >= readCursor. If they are equal that means the buffer is empty
return currentWriteCursor - currentReadCursor;
}
void RingBuffer::pop_front() {
pop(1);
}
void RingBuffer::pop(size_t count) {
if (size() < count) {
throw std::runtime_error("RingBuffer: Underflow");
}
readCursor.fetch_add(count, std::memory_order_release);
}
const uint8_t& RingBuffer::get(size_t offset) const {
if (offset >= size()) {
throw std::runtime_error("RingBuffer: Index out of range");
}
auto currentReadCursor = readCursor.load(std::memory_order_acquire);
return *resolve(currentReadCursor, offset);
}
bool RingBuffer::write(const uint8_t* addr, size_t length) {
const auto freeSpace = (capacity() - size());
if (length > freeSpace) {
return false;
}
auto currentWriteCursor = writeCursor.load(std::memory_order_relaxed);
auto spaceAtEnd = std::min(freeSpace, capacity() - (currentWriteCursor & mask)); // number of bytes from (masked) writeCursor to the end of the writable space (i.e. we reach the masked read cursor or the end of the buffer)
auto firstCopySize = std::min(spaceAtEnd, length);
(void)memcpy(resolve(currentWriteCursor, 0), addr, firstCopySize);
if (firstCopySize < length)
{
(void)memcpy(buf, &addr[firstCopySize], length - firstCopySize);
}
writeCursor.store(currentWriteCursor + length, std::memory_order_release);
return true;
}
bool RingBuffer::write(const std::vector<uint8_t>& source) {
return write(source.data(), source.size());
}
bool RingBuffer::read(uint8_t* dest, size_t startIndex, size_t length) const {
auto currentSize = size();
if ((startIndex >= currentSize) || ((startIndex + length) > size())) {
return false;
}
auto currentReadCursor = readCursor.load(std::memory_order_relaxed);
auto bytesAtEnd = std::min<size_t>(capacity() - ((currentReadCursor + startIndex) & mask), length);
const auto bytesAtStart = (length - bytesAtEnd);
(void)memcpy(dest, resolve(currentReadCursor, startIndex), bytesAtEnd);
if (bytesAtStart > 0) {
(void)memcpy(&dest[bytesAtEnd], buf, bytesAtStart);
}
return true;
}
void RingBuffer::clear() {
pop(size());
}
}
+5 -6
View File
@@ -4,8 +4,7 @@
* Created on: Jun 22, 2020 * Created on: Jun 22, 2020
* Author: BJones * Author: BJones
*/ */
#include "icsneo/communication/crc32.h" #include "icsneo/core/crc32.h"
#include <stddef.h>
static const unsigned long crc32_table[256] = { 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 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, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2,
@@ -32,7 +31,7 @@ static const unsigned long crc32_table[256] = { 0x00000000, 0x77073096, 0xEE0E61
0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E,
0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D }; 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D };
uint32_t crc32(uint32_t crc, const unsigned char* buf, uint32_t len) uint32_t icsneo::crc32(uint32_t crc, const unsigned char* buf, uint32_t len)
{ {
unsigned char octet; unsigned char octet;
const unsigned char* p = buf; const unsigned char* p = buf;
@@ -50,13 +49,13 @@ static unsigned char rev_crc32_table[256];
static void revgen(void) static void revgen(void)
{ {
size_t k; uint16_t k;
for (k = 0; k < 256; k++) for (k = 0; k < 256; k++)
rev_crc32_table[crc32_table[k] >> 24] = (uint8_t)k; rev_crc32_table[crc32_table[k] >> 24] = (unsigned char)k;
} }
uint32_t revcrc32(uint32_t crc, const unsigned char* buf, uint32_t len) uint32_t icsneo::revcrc32(uint32_t crc, const unsigned char* buf, uint32_t len)
{ {
unsigned char k; unsigned char k;
revgen(); revgen();
+776
View File
@@ -0,0 +1,776 @@
#include "icsneo/core/macseccfg.h"
#include "icsneo/api/eventmanager.h"
#include "icsneo/core/crc32.h"
#include <cstring>
namespace icsneo {
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 4201) // nameless struct/union
#endif
#pragma pack(push, 1)
typedef struct
{
uint16_t VID; /*!< 12 bits */
uint8_t PRI_CFI; /*!< PRI - 3 bits, CFI - 1bit */
} MACSEC_VLANTAG_t;
/**
* @brief Structure of MPLS
*
*/
typedef struct
{
uint32_t MPLS_label; /*!< 20 bits */
uint8_t exp; /*!< 3 bits */
} MACSEC_MPLS_OUTER_t;
#define MACSEC_SETTINGS_RULE_SIZE (88)
typedef union _MACSecRule
{
struct
{
uint8_t index;
uint8_t key_MAC_DA[6]; /*!< MAC DA field extracted from the packet */
uint8_t mask_MAC_DA[6]; /*!< Set bits to 1 to mask/exclude corresponding flowid_tcam_data bit from compare */
uint8_t key_MAC_SA[6]; /*!< MAC SA field extracted from the packet */
uint8_t mask_MAC_SA[6]; /*!< Set bits to 1 to mask/exclude corresponding flowid_tcam_data bit from compare */
uint16_t key_Ethertype; /*!< First E-Type found in the packet that doesn't match one of the preconfigured custom tag. */
uint16_t mask_Ethertype; /*!< Set bits to 1 to mask/exclude corresponding flowid_tcam_data bit from compare */
MACSEC_VLANTAG_t key_vlantag_outer1; /*!< outermost/1st VLAN ID {8'd0, VLAN_ID[11:0]}, or 20-bit MPLS label. */
MACSEC_MPLS_OUTER_t key_MPLS_outer1;
MACSEC_VLANTAG_t mask_vlantag_outer1; /*!< Set bits to 1 to mask/exclude corresponding flowid_tcam_data bit from compare */
MACSEC_MPLS_OUTER_t mask_MPLS_outer1;
MACSEC_VLANTAG_t key_vlantag_outer2; /*!< 2nd outermost VLAN ID {8'd0, VLAN_ID[11:0]}, or 20-bit MPLS label. */
MACSEC_MPLS_OUTER_t key_MPLS_outer2;
MACSEC_VLANTAG_t mask_vlantag_outer2; /*!< Set bits to 1 to mask/exclude corresponding flowid_tcam_data bit from compare */
MACSEC_MPLS_OUTER_t mask_MPLS_outer2;
uint16_t key_bonus_data; /*!< 2 bytes of additional bonus data extracted from one of the custom tags. */
uint16_t mask_bonus_data; /*!< Set bits to 1 to mask/exclude corresponding flowid_tcam_data bit from compare */
uint8_t
key_tag_match_bitmap; /*!< 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 mask_tag_match_bitmap; /*!< Set bits to 1 to mask/exclude corresponding flowid_tcam_data bit from compare */
MACsecPacketType key_packet_type; /*!< Encoded Packet Type, see MACSEC_PACKET_TYPE */
uint8_t mask_packet_type; /*!< Set bits to 1 to mask/exclude corresponding flowid_tcam_data bit from compare */
uint16_t
key_inner_vlan_type; /*!< 3 bits total. Encoded value indicating which VLAN TPID value matched for the second outermost VLAN Tag. */
uint16_t mask_inner_vlan_type; /*!< Set bits to 1 to mask/exclude corresponding flowid_tcam_data bit from compare */
uint16_t key_outer_vlan_type; /*!< 3 bits total. Encoded value indicating which VLAN TPID value matched for the outermost VLAN Tag. */
uint16_t mask_outer_vlan_type; /*!< Set bits to 1 to mask/exclude corresponding flowid_tcam_data bit from compare */
uint8_t
key_num_tags; /*!< 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 mask_num_tags; /*!< Set bits to 1 to mask/exclude corresponding flowid_tcam_data bit from compare */
uint8_t key_express; /*!< 1 bits. Express packet. */
uint8_t mask_express; /*!< 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 */
#define MACSEC_SETTINGS_MAP_SIZE (20)
typedef union _MACSecMap
{
struct
{
uint8_t index;
uint64_t sectag_sci; /*!< 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 auxiliary_plcy; /*!< 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 */
#define MACSEC_SETTINGS_SECY_SIZE (24)
typedef union _MACSecSecY
{
struct
{
uint8_t index; /*!< Identifies the SecY for this Flow. */
uint8_t controlled_port_enabled; /*!< Enable (or disable) operation of the Controlled port associated with this SecY */
MACsecValidation validate_frames; /*!< see MACSEC_VALIDATEFRAME */
MACsecStrip strip_sectag_icv; /*!< see MACSEC_STRIP_SECTAG_ICV */
MACsecCipherSuite cipher; /*!< Define the cipher suite to use for this SecY */
uint8_t confidential_offset; /*!< Define the number of bytes that are unencrypted following the SecTag. */
uint8_t icv_includes_da_sa; /*!< When set, the outer DA/SA bytes are included in the authentication GHASH calculation */
uint8_t replay_protect; /*!< Enables Anti-Replay protection */
uint32_t replay_window; /*!< Unsigned value indicating the size of the anti-replay window. */
uint8_t
protect_frames; /*!< 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
sectag_offset; /*!< Define the offset in bytes from either the start of the packet or a matching Etype depending on SecTag_Insertion_Mode. */
uint8_t sectag_tci; /*!< 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 */
#define 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 sa_index0; /*!< Define the 1st SA to use */
uint8_t sa_index1; /*!< Define the 2nd SA to use */
uint8_t sa_index0_in_use; /*!< Specifies whether 1st SA is in use or not. */
uint8_t sa_index1_in_use; /*!< Specifies whether 2nd SA is in use or not. */
uint8_t enable_auto_rekey; /*!< 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 */
#define 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 */
#define 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 */
#define MACSEC_NUM_FLAGS_PER_CONFIG (1)
#define MACSEC_NUM_RULES_PER_CONFIG (2)
#define MACSEC_NUM_MAPS_PER_CONFIG (2)
#define MACSEC_NUM_SECY_PER_CONFIG (2)
#define MACSEC_NUM_SC_PER_CONFIG (2)
#define MACSEC_NUM_SA_PER_CONFIG (4)
typedef struct MACSEC_CONFIG_t
{
MACSecFlags_t flags;
MACSecRule_t rule[MACSEC_NUM_RULES_PER_CONFIG];
MACSecMap_t map[MACSEC_NUM_MAPS_PER_CONFIG];
MACSecSecY_t secy[MACSEC_NUM_SECY_PER_CONFIG];
MACSecSc_t sc[MACSEC_NUM_SC_PER_CONFIG];
MACSecSa_t sa[MACSEC_NUM_SA_PER_CONFIG];
} 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
typedef struct MACSEC_SETTINGS_W_HDR
{
uint16_t version;
uint16_t len;
uint32_t crc32;
MACSEC_SETTINGS macsec;
} MACSEC_SETTINGS_W_HDR;
#define MACSEC_SETTINGS_W_HDR_SIZE (2048)
#pragma pack(pop)
#ifdef _MSC_VER
#pragma warning(pop)
#endif
static void ReportEvent(APIEvent::Type event, APIEvent::Severity severity) {
auto& em = EventManager::GetInstance();
em.add(APIEvent(event, severity));
}
MACsecConfig::MACsecConfig(const DeviceType& deviceType) : type(deviceType) {
switch(deviceType.getDeviceType()) {
case icsneo::DeviceType::Enum::RADMoon2:
case icsneo::DeviceType::Enum::RADMoon3:
case icsneo::DeviceType::Enum::RADEpsilon:
maxSecY = 2;
maxRule = 2;
maxSa = 4;
binIndex = 0;
break;
default:
maxSecY = 0;
maxSa = 0;
maxRule = 0;
binIndex = 0;
ReportEvent(APIEvent::Type::MACsecNotSupported, APIEvent::Severity::Error);
return;
}
}
int MACsecConfig::addRxSecY(const MACsecRxSecY& secY, uint8_t saIndex) {
if(rxSecY.size() >= maxSecY) {
ReportEvent(APIEvent::Type::MACsecSecYLimit, APIEvent::Severity::Error);
return -1;
}
if(saIndex >= rxSa.size()) {
ReportEvent(APIEvent::Type::MACsecInvalidSaIndex, APIEvent::Severity::Error);
return -1;
}
int ret = static_cast<int>(rxSecY.size());
rxSecY.emplace_back(secY);
rxSecYSaIndices.emplace_back(saIndex, saIndex + 1);
rxSecYRekey.emplace_back(false);
rxRuleIndices.emplace_back(0);
return ret;
}
int MACsecConfig::addTxSecY(const MACsecTxSecY& secY, uint8_t saIndex) {
if(txSecY.size() >= maxSecY) {
ReportEvent(APIEvent::Type::MACsecSecYLimit, APIEvent::Severity::Error);
return -1;
}
if(saIndex >= txSa.size()) {
ReportEvent(APIEvent::Type::MACsecInvalidSaIndex, APIEvent::Severity::Error);
return -1;
}
int ret = static_cast<int>(txSecY.size());
txSecY.emplace_back(secY);
txSecYSaIndices.emplace_back(saIndex, saIndex + 1);
txSecYRekey.emplace_back(false);
return ret;
}
int MACsecConfig::addRxSa(const MACsecRxSa& sa) {
if(rxSa.size() >= maxSa) {
ReportEvent(APIEvent::Type::MACsecSaLimit, APIEvent::Severity::Error);
return -1;
}
int ret = static_cast<int>(rxSa.size());
rxSa.emplace_back(sa);
return ret;
}
int MACsecConfig::addTxSa(const MACsecTxSa& sa) {
if(txSa.size() >= maxSa) {
ReportEvent(APIEvent::Type::MACsecSaLimit, APIEvent::Severity::Error);
return -1;
}
int ret = static_cast<int>(txSa.size());
txSa.emplace_back(sa);
return ret;
}
int MACsecConfig::addRxRule(const MACsecRxRule& rule, uint8_t secYIndex) {
if(rxRule.size() >= maxRule) {
ReportEvent(APIEvent::Type::MACsecSaLimit, APIEvent::Severity::Error);
return -1;
}
if(maxSecY >= rxRule.size()) {
ReportEvent(APIEvent::Type::MACsecSecYLimit, APIEvent::Severity::Error);
return -1;
}
int ret = static_cast<int>(rxRule.size());
rxRuleIndices[secYIndex] = static_cast<uint8_t>(rxRule.size());
rxRule.emplace_back(rule);
return ret;
}
MACsecRxRule& MACsecConfig::getRxRule(uint8_t ruleIndex) {
return rxRule[ruleIndex];
}
const MACsecRxRule& MACsecConfig::getRxRule(uint8_t ruleIndex) const {
return rxRule[ruleIndex];
}
MACsecRxSecY& MACsecConfig::getRxSecY(uint8_t secYIndex) {
return rxSecY[secYIndex];
}
const MACsecRxSecY& MACsecConfig::getRxSecY(uint8_t secYIndex) const {
return rxSecY[secYIndex];
}
MACsecTxSecY& MACsecConfig::getTxSecY(uint8_t secYIndex) {
return txSecY[secYIndex];
}
const MACsecTxSecY& MACsecConfig::getTxSecY(uint8_t secYIndex) const {
return txSecY[secYIndex];
}
MACsecRxSa& MACsecConfig::getRxSa(uint8_t saIndex) {
return rxSa[saIndex];
}
const MACsecRxSa& MACsecConfig::getRxSa(uint8_t saIndex) const {
return rxSa[saIndex];
}
MACsecTxSa& MACsecConfig::getTxSa(uint8_t saIndex) {
return txSa[saIndex];
}
const MACsecTxSa& MACsecConfig::getTxSa(uint8_t saIndex) const {
return txSa[saIndex];
}
bool MACsecConfig::setTxSaIndex(uint8_t secYIndex, uint8_t saIndex) {
if(secYIndex >= txSecY.size()) {
ReportEvent(APIEvent::Type::MACsecInvalidSecYIndex, APIEvent::Severity::Error);
return false;
}
if(saIndex >= txSa.size()) {
ReportEvent(APIEvent::Type::MACsecInvalidSaIndex, APIEvent::Severity::Error);
return false;
}
txSecYSaIndices[secYIndex].first = saIndex;
return true;
}
bool MACsecConfig::enableTxRekey(uint8_t secYIndex, uint8_t rekeySaIndex) {
if(secYIndex >= txSecY.size()) {
ReportEvent(APIEvent::Type::MACsecInvalidSecYIndex, APIEvent::Severity::Error);
return false;
}
if(rekeySaIndex >= txSa.size()) {
ReportEvent(APIEvent::Type::MACsecInvalidSaIndex, APIEvent::Severity::Error);
return false;
}
txSecYSaIndices[secYIndex].second = rekeySaIndex;
txSecYRekey[secYIndex] = true;
return true;
}
bool MACsecConfig::setTxSaRekeyIndex(uint8_t secYIndex, uint8_t saIndex) {
if(secYIndex >= txSecY.size()) {
ReportEvent(APIEvent::Type::MACsecInvalidSecYIndex, APIEvent::Severity::Error);
return false;
}
if(saIndex >= txSa.size()) {
ReportEvent(APIEvent::Type::MACsecInvalidSaIndex, APIEvent::Severity::Error);
return false;
}
txSecYSaIndices[secYIndex].second = saIndex;
return true;
}
void MACsecConfig::disableTxRekey(uint8_t secYIndex) {
if(secYIndex >= txSecY.size()) {
ReportEvent(APIEvent::Type::MACsecInvalidSecYIndex, APIEvent::Severity::EventWarning);
return;
}
txSecYRekey[secYIndex] = false;
}
bool MACsecConfig::setRxSaIndex(uint8_t secYIndex, uint8_t saIndex) {
if(secYIndex >= rxSecY.size()) {
ReportEvent(APIEvent::Type::MACsecInvalidSecYIndex, APIEvent::Severity::Error);
return false;
}
if(saIndex >= rxSa.size()) {
ReportEvent(APIEvent::Type::MACsecInvalidSaIndex, APIEvent::Severity::Error);
return false;
}
rxSecYSaIndices[secYIndex].first = saIndex;
return true;
}
bool MACsecConfig::enableRxRekey(uint8_t secYIndex, uint8_t rekeySaIndex) {
if(secYIndex >= rxSecY.size()) {
ReportEvent(APIEvent::Type::MACsecInvalidSecYIndex, APIEvent::Severity::Error);
return false;
}
if(rekeySaIndex >= rxSa.size()) {
ReportEvent(APIEvent::Type::MACsecInvalidSaIndex, APIEvent::Severity::Error);
return false;
}
rxSecYSaIndices[secYIndex].second = rekeySaIndex;
rxSecYRekey[secYIndex] = true;
return true;
}
bool MACsecConfig::setRxSaRekeyIndex(uint8_t secYIndex, uint8_t saIndex) {
if(secYIndex >= rxSecY.size()) {
ReportEvent(APIEvent::Type::MACsecInvalidSecYIndex, APIEvent::Severity::Error);
return false;
}
if(saIndex >= rxSa.size()) {
ReportEvent(APIEvent::Type::MACsecInvalidSaIndex, APIEvent::Severity::Error);
return false;
}
rxSecYSaIndices[secYIndex].second = saIndex;
return true;
}
void MACsecConfig::disableRxRekey(uint8_t secYIndex) {
if(secYIndex >= rxSecY.size()) {
ReportEvent(APIEvent::Type::MACsecInvalidSecYIndex, APIEvent::Severity::EventWarning);
return;
}
rxSecYRekey[secYIndex] = false;
}
void MACsecConfig::setRxEnable(bool newRxEnable) {
enableRx = newRxEnable;
}
void MACsecConfig::setTxEnable(bool newTxEnable) {
enableTx = newTxEnable;
}
void MACsecConfig::setStorage(bool temporary) {
nvm = !temporary;
}
void MACsecConfig::clear() {
// Set everything back to default, except device maximums
rxSecY.clear();
txSecY.clear();
rxSa.clear();
txSa.clear();
rxRule.clear();
rxSecYRekey.clear();
txSecYRekey.clear();
rxSecYSaIndices.clear();
txSecYSaIndices.clear();
rxRuleIndices.clear();
enableRx = false;
enableTx = false;
nvm = false;
}
MACsecConfig::operator bool() const {
return (maxSa != 0) || (maxSecY != 0) || (maxRule != 0);
}
uint16_t MACsecConfig::getBinIndex() const {
return binIndex;
}
DeviceType MACsecConfig::getType() const {
return type;
}
uint8_t MACsecConfig::getMaxNumRule() const {
return maxRule;
}
uint8_t MACsecConfig::getMaxNumSecY() const {
return maxSecY;
}
uint8_t MACsecConfig::getMaxNumSa() const {
return maxSa;
}
static uint8_t TCItoInt(const MACsecTci& tci) {
uint8_t res = 0;
res |= tci.c ? 0x01u : 0;
res |= tci.e ? 0x02u : 0;
res |= tci.scb ? 0x04u : 0;
res |= tci.sc ? 0x08u : 0;
res |= tci.es ? 0x10u : 0;
return res;
}
static void SetHardwareTxSecY(
MACSEC_SETTINGS_W_HDR* hwSettings,
const MACsecTxSecY& secY,
bool rekeyEnabled,
const std::pair<uint8_t, uint8_t>& saIndices,
uint8_t index
) {
MACSecSecY_t* hwSecY = &hwSettings->macsec.tx.secy[index];
MACSecSc_t* hwSc = &hwSettings->macsec.tx.sc[index];
MACSecMap_t* hwMap = &hwSettings->macsec.tx.map[index];
hwSecY->index = index;
hwSecY->enable = true;
hwSecY->controlled_port_enabled = secY.enableControlPort ? 0x1u : 0x0u;
hwSecY->cipher = secY.cipher;
hwSecY->confidential_offset = secY.confidentialityOffset;
hwSecY->icv_includes_da_sa = secY.icvIncludesDaSa ? 0x1u : 0x0u;
hwSecY->mtu = secY.mtu;
hwSecY->sectag_tci = TCItoInt(secY.tci);
hwSecY->sectag_offset = secY.secTagOffset;
hwSecY->protect_frames = secY.protectFrames;
hwSc->index = index;
hwSc->enable = true;
hwSc->secYIndex = index;
hwSc->enable_auto_rekey = rekeyEnabled ? 0x1u : 0x0u;
hwSc->sa_index0 = saIndices.first;
hwSc->sa_index1 = saIndices.second;
hwSc->sa_index0_in_use = true;
hwSc->sa_index1_in_use = rekeyEnabled ? true : false;
hwSc->isActiveSA1 = rekeyEnabled ? true : false;
hwSc->sci = secY.sci;
hwMap->index = index;
hwMap->enable = true;
hwMap->auxiliary_plcy = secY.auxiliaryPolicy;
hwMap->secYIndex = index;
hwMap->isControlPacket = secY.isControlPacket ? 0x1u : 0x0u;
hwMap->scIndex = index;
hwMap->sectag_sci = secY.sci;
}
static void SetHardwareRxSecY(
MACSEC_SETTINGS_W_HDR* hwSettings,
const MACsecRxSecY& secY,
bool rekeyEnabled,
uint8_t ruleIndex,
const std::pair<uint8_t, uint8_t>& saIndices,
uint8_t index
) {
MACSecSecY_t* hwSecY = &hwSettings->macsec.rx.secy[index];
MACSecSc_t* hwSc = &hwSettings->macsec.rx.sc[index];
MACSecMap_t* hwMap = &hwSettings->macsec.rx.map[index];
hwSecY->index = index;
hwSecY->enable = 0x1u;
hwSecY->controlled_port_enabled = secY.enableControlPort ? 0x1u : 0x0u;
hwSecY->cipher = secY.cipher;
hwSecY->confidential_offset = secY.confidentialityOffset;
hwSecY->icv_includes_da_sa = secY.icvIncludesDaSa ? 0x1u : 0x0u;
hwSecY->replay_protect = secY.replayProtect ? 0x1u : 0x0u;
hwSecY->replay_window = secY.replayWindow;
hwSecY->validate_frames = secY.frameValidation;
hwSecY->strip_sectag_icv = secY.frameStrip;
hwSecY->sectag_offset = 12;
hwSc->index = index;
hwSc->enable = 0x1u;
hwSc->secYIndex = index;
hwSc->enable_auto_rekey = rekeyEnabled ? 0x1u : 0x0u;
hwSc->sa_index0 = saIndices.first;
hwSc->sa_index1 = saIndices.second;
hwSc->sa_index0_in_use = 0x1u;
hwSc->sa_index1_in_use = rekeyEnabled ? 0x1u : 0x0u;
hwSc->isActiveSA1 = rekeyEnabled ? 0x1u : 0x0u;
hwSc->sci = secY.sci;
hwMap->index = index;
hwMap->enable = 0x1u;
hwMap->secYIndex = index;
hwMap->ruleId = ruleIndex;
hwMap->isControlPacket = secY.isControlPacket ? 0x1u : 0x0u;
hwMap->scIndex = index;
hwMap->sectag_sci = secY.sci;
}
static void SetHardwareTxSa(MACSEC_SETTINGS_W_HDR* hwSettings, const MACsecTxSa& sa, uint8_t index) {
MACSecSa_t* hwSa = &hwSettings->macsec.tx.sa[index];
hwSa->index = index;
hwSa->enable = 0x1u;
memcpy(hwSa->sak, sa.sak.data(), 32);
memcpy(hwSa->hashKey, sa.hashKey.data(), 16);
memcpy(hwSa->salt, sa.salt.data(), 12);
hwSa->ssci = sa.ssci;
hwSa->AN = sa.an;
hwSa->nextPN = sa.nextPn;
}
static void SetHardwareRxSa(MACSEC_SETTINGS_W_HDR* hwSettings, const MACsecRxSa& sa, uint8_t index) {
MACSecSa_t* hwSa = &hwSettings->macsec.rx.sa[index];
hwSa->index = index;
hwSa->enable = 0x1u;
memcpy(hwSa->sak, sa.sak.data(), 32);
memcpy(hwSa->hashKey, sa.hashKey.data(), 16);
memcpy(hwSa->salt, sa.salt.data(), 12);
hwSa->ssci = sa.ssci;
hwSa->nextPN = sa.nextPn;
}
static void SetHardwareRxRule(MACSecRule_t* hwRule, const MACsecRxRule& rule, uint8_t index) {
hwRule->enable = 0x1u;
hwRule->index = index;
memcpy(hwRule->key_MAC_DA, rule.keyMacDa.data(), 6);
memcpy(hwRule->mask_MAC_DA, rule.maskMacDa.data(), 6);
memcpy(hwRule->key_MAC_SA, rule.keyMacSa.data(), 6);
memcpy(hwRule->mask_MAC_SA, rule.maskMacSa.data(), 6);
hwRule->key_Ethertype = rule.keyEthertype;
hwRule->mask_Ethertype = rule.maskEthertype;
hwRule->key_vlantag_outer1.PRI_CFI = rule.keyVlanTagOuter1.priCfi;
hwRule->key_vlantag_outer1.VID = rule.keyVlanTagOuter1.vid;
hwRule->key_MPLS_outer1.exp = rule.keyMplsOuter1.exp;
hwRule->key_MPLS_outer1.MPLS_label = rule.keyMplsOuter1.mplsLabel;
hwRule->mask_vlantag_outer1.PRI_CFI = rule.maskVlanTagOuter1.priCfi;
hwRule->mask_vlantag_outer1.VID = rule.maskVlanTagOuter1.vid;
hwRule->mask_MPLS_outer1.exp = rule.maskMplsOuter1.exp;
hwRule->mask_MPLS_outer1.MPLS_label = rule.maskMplsOuter1.mplsLabel;
hwRule->key_vlantag_outer2.PRI_CFI = rule.keyVlanTagOuter2.priCfi;
hwRule->key_vlantag_outer2.VID = rule.keyVlanTagOuter2.vid;
hwRule->key_MPLS_outer2.exp = rule.keyMplsOuter2.exp;
hwRule->key_MPLS_outer2.MPLS_label = rule.keyMplsOuter2.mplsLabel;
hwRule->mask_vlantag_outer2.PRI_CFI = rule.maskVlanTagOuter2.priCfi;
hwRule->mask_vlantag_outer2.VID = rule.maskVlanTagOuter2.vid;
hwRule->mask_MPLS_outer2.exp = rule.maskMplsOuter2.exp;
hwRule->mask_MPLS_outer2.MPLS_label = rule.maskMplsOuter2.mplsLabel;
hwRule->key_bonus_data = rule.keyBonusData;
hwRule->mask_bonus_data = rule.maskBonusData;
hwRule->key_tag_match_bitmap = rule.keyTagMatchBitmap;
hwRule->mask_tag_match_bitmap = rule.maskTagMatchBitmap;
hwRule->key_packet_type = rule.keyPacketType;
hwRule->mask_packet_type = rule.maskPacketType;
hwRule->key_inner_vlan_type = rule.keyInnerVlanType;
hwRule->mask_inner_vlan_type = rule.maskInnerVlanType;
hwRule->key_outer_vlan_type = rule.keyOuterVlanType;
hwRule->mask_outer_vlan_type = rule.maskOuterVlanType;
hwRule->key_num_tags = rule.keyNumTags;
hwRule->mask_num_tags = rule.maskNumTags;
hwRule->key_express = rule.keyExpress ? 0x1u : 0x0u;
hwRule->mask_express = rule.maskExpress ? 0x1u : 0x0u;
hwRule->isMPLS = rule.isMpls ? 0x1u : 0x0u;
}
std::vector<uint8_t> MACsecConfig::serialize() const {
std::vector<uint8_t> res(sizeof(MACSEC_SETTINGS_W_HDR), 0);
MACSEC_SETTINGS_W_HDR* hwSettings = (MACSEC_SETTINGS_W_HDR*)(res.data());
for(uint8_t i = 0; i < maxSecY; i++) {
if(i < rxSecY.size()) {
SetHardwareRxSecY(
hwSettings,
rxSecY[i],
rxSecYRekey[i],
rxRuleIndices[i],
rxSecYSaIndices[i],
i
);
} else {
hwSettings->macsec.rx.secy[i].enable = false;
hwSettings->macsec.rx.map[i].enable = false;
hwSettings->macsec.rx.sc[i].enable = false;
}
if(i < txSecY.size()) {
SetHardwareTxSecY(
hwSettings,
txSecY[i],
txSecYRekey[i],
txSecYSaIndices[i],
i
);
} else {
hwSettings->macsec.tx.secy[i].enable = false;
hwSettings->macsec.tx.map[i].enable = false;
hwSettings->macsec.tx.sc[i].enable = false;
}
}
for(uint8_t i = 0; i < maxSa; i++) {
if(i < rxSa.size()) {
SetHardwareRxSa(hwSettings, rxSa[i], i);
} else {
hwSettings->macsec.rx.sa[i].enable = false;
}
if(i < txSa.size()) {
SetHardwareTxSa(hwSettings, txSa[i], i);
} else {
hwSettings->macsec.tx.sa[i].enable = false;
}
}
if(rxRule.size() == 0) {
MACsecRxRule defaultRule;
MACSecRule_t* hwRxRule = &hwSettings->macsec.rx.rule[0];
MACSecRule_t* hwTxRule = &hwSettings->macsec.tx.rule[0];
SetHardwareRxRule(hwRxRule, defaultRule, 0);
SetHardwareRxRule(hwTxRule, defaultRule, 0);
//hwSettings->macsec.tx.rule[0].enable = false;
for(uint8_t i = 1; i < maxRule; i++) {
hwSettings->macsec.rx.rule[i].enable = false;
hwSettings->macsec.tx.rule[i].enable = false;
}
} else {
for(uint8_t i = 0; i < maxRule; i++) {
if(i < rxRule.size()) {
auto* hwRxRule = &hwSettings->macsec.rx.rule[i];
SetHardwareRxRule(hwRxRule, rxRule[i], i);
} else {
hwSettings->macsec.rx.rule[i].enable = false;
hwSettings->macsec.tx.rule[i].enable = false;
}
}
}
hwSettings->len = sizeof(MACSEC_SETTINGS_W_HDR);
hwSettings->version = MACSEC_SETTINGS_VERSION;
hwSettings->macsec.flags.en = (enableRx || enableTx) ? 1u : 0u;
hwSettings->macsec.flags.nvm = nvm ? 1u : 0u;
hwSettings->macsec.rx.flags.en = enableRx ? 1u : 0u;
hwSettings->macsec.tx.flags.en = enableTx ? 1u : 0u;
hwSettings->crc32 = crc32(0, (uint8_t*)&hwSettings->macsec, sizeof(MACSEC_SETTINGS));
return res;
}
}
+91
View File
@@ -0,0 +1,91 @@
#include "icsneo/core/ringbuffer.h"
#include <stdexcept>
namespace icsneo {
RingBuffer::RingBuffer(size_t bufferSize) : readCursor(0), writeCursor(0) {
// round the buffer size to the nearest power of 2
bufferSize = RoundUp(bufferSize);
mask = bufferSize - 1;
buf = new uint8_t[bufferSize];
}
RingBuffer::~RingBuffer() {
delete[] buf;
buf = nullptr;
}
const uint8_t& RingBuffer::operator[](size_t offset) const {
return get(offset);
}
size_t RingBuffer::size() const {
// The values in the cursors are monotonic, i.e. they only ever increment. They can be considered to be the total number of elements ever written or read
auto currentWriteCursor = writeCursor.load(std::memory_order_relaxed);
auto currentReadCursor = readCursor.load(std::memory_order_relaxed);
// Using unmasked values, writeCursor is guaranteed to be >= readCursor. If they are equal that means the buffer is empty
return currentWriteCursor - currentReadCursor;
}
void RingBuffer::pop_front() {
pop(1);
}
void RingBuffer::pop(size_t count) {
if (size() < count) {
throw std::runtime_error("RingBuffer: Underflow");
}
readCursor.fetch_add(count, std::memory_order_release);
}
const uint8_t& RingBuffer::get(size_t offset) const {
if (offset >= size()) {
throw std::runtime_error("RingBuffer: Index out of range");
}
auto currentReadCursor = readCursor.load(std::memory_order_acquire);
return *resolve(currentReadCursor, offset);
}
bool RingBuffer::write(const uint8_t* addr, size_t length) {
const auto freeSpace = (capacity() - size());
if (length > freeSpace) {
return false;
}
auto currentWriteCursor = writeCursor.load(std::memory_order_relaxed);
auto spaceAtEnd = std::min(freeSpace, capacity() - (currentWriteCursor & mask)); // number of bytes from (masked) writeCursor to the end of the writable space (i.e. we reach the masked read cursor or the end of the buffer)
auto firstCopySize = std::min(spaceAtEnd, length);
(void)memcpy(resolve(currentWriteCursor, 0), addr, firstCopySize);
if (firstCopySize < length)
{
(void)memcpy(buf, &addr[firstCopySize], length - firstCopySize);
}
writeCursor.store(currentWriteCursor + length, std::memory_order_release);
return true;
}
bool RingBuffer::write(const std::vector<uint8_t>& source) {
return write(source.data(), source.size());
}
bool RingBuffer::read(uint8_t* dest, size_t startIndex, size_t length) const {
auto currentSize = size();
if ((startIndex >= currentSize) || ((startIndex + length) > size())) {
return false;
}
auto currentReadCursor = readCursor.load(std::memory_order_relaxed);
auto bytesAtEnd = std::min<size_t>(capacity() - ((currentReadCursor + startIndex) & mask), length);
const auto bytesAtStart = (length - bytesAtEnd);
(void)memcpy(dest, resolve(currentReadCursor, startIndex), bytesAtEnd);
if (bytesAtStart > 0) {
(void)memcpy(&dest[bytesAtEnd], buf, bytesAtStart);
}
return true;
}
void RingBuffer::clear() {
pop(size());
}
}
+502 -25
View File
@@ -6,6 +6,8 @@
#include "icsneo/device/extensions/deviceextension.h" #include "icsneo/device/extensions/deviceextension.h"
#include "icsneo/disk/fat.h" #include "icsneo/disk/fat.h"
#include "icsneo/communication/message/filter/extendedresponsefilter.h" #include "icsneo/communication/message/filter/extendedresponsefilter.h"
#include "icsneo/communication/message/networkmutexmessage.h"
#include "icsneo/communication/message/transmitmessage.h"
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(disable : 4996) // STL time functions #pragma warning(disable : 4996) // STL time functions
@@ -207,6 +209,75 @@ bool Device::refreshComponentVersions() {
return false; return false;
} }
std::vector<VersionReport> Device::getChipVersions(bool refreshComponents) {
if(refreshComponents) {
refreshComponentVersions();
}
std::vector<VersionReport> chipVersions;
if (supportsComponentVersions()) {
const auto& compVersions = getComponentVersions();
auto disectVersion = [](uint32_t dotVersion) {
std::array<uint8_t, 4> result = {0,0,0,0};
size_t i = 0;
if(dotVersion & 0xFF000000ul) {
result[i++] = (uint8_t)((dotVersion & 0xFF000000ul) >> 24);
result[i++] = (uint8_t)((dotVersion & 0x00FF0000ul) >> 16);
} else if(dotVersion & 0x00FF0000ul) {
result[i++] = (uint8_t)((dotVersion & 0x00FF0000ul) >> 16);
}
result[i++] = (uint8_t)((dotVersion & 0x0000FF00ul) >> 8);
result[i] = (uint8_t)((dotVersion & 0x000000FFul) >> 0);
return result;
};
for(const auto& chipInfo : getChipInfo()) {
for(const auto& component : compVersions) {
if(!component.valid) {
continue;
}
if(component.identifier == (uint32_t)chipInfo.id) {
chipVersions.emplace_back();
auto& version = chipVersions.back();
auto disectedVersion = disectVersion(component.dotVersion);
version.id = chipInfo.id;
version.name = chipInfo.name;
version.major = disectedVersion[0];
version.minor = disectedVersion[1];
version.maintenance = disectedVersion[2];
version.build = disectedVersion[3];
}
}
}
} else {
const auto& appVersions = getVersions();
for(const auto& chipInfo : getChipInfo()) {
if(!chipInfo.defaultEnabled) {
continue;
}
if(appVersions.size() <= chipInfo.versionIndex) {
continue;
}
const auto& appVer = appVersions[chipInfo.versionIndex];
if(!appVer) {
continue;
}
chipVersions.emplace_back();
auto& version = chipVersions.back();
version.id = chipInfo.id;
version.name = chipInfo.name;
version.major = appVer->major;
version.minor = appVer->minor;
version.maintenance = 0;
version.build = 0;
}
}
return chipVersions;
}
bool Device::open(OpenFlags flags, OpenStatusHandler handler) { bool Device::open(OpenFlags flags, OpenStatusHandler handler) {
if(!com) { if(!com) {
report(APIEvent::Type::Unknown, APIEvent::Severity::Error); report(APIEvent::Type::Unknown, APIEvent::Severity::Error);
@@ -342,6 +413,44 @@ bool Device::open(OpenFlags flags, OpenStatusHandler handler) {
return true; return true;
} }
bool Device::reconnect(std::chrono::milliseconds timeout, std::chrono::milliseconds interval) {
if(isOnline()) {
goOffline();
}
bool readsArePaused = com->readsArePaused();
if(!com->close()) {
return false;
}
std::vector<FoundDevice> foundDevices;
auto findAll = com->driver->getFinder();
auto start = std::chrono::system_clock::now();
while((std::chrono::system_clock::now() - start) < timeout) {
foundDevices.clear();
findAll(foundDevices);
for(auto& fd : foundDevices) {
if(!memcmp(fd.serial, data.serial, 6)) {
com->driver = fd.makeDriver(report, getWritableNeoDevice());
if(readsArePaused) {
// Pause reads again
com->pauseReads();
}
if(com->open()) {
return true;
} else {
if(readsArePaused) {
com->resumeReads();
}
}
}
}
std::this_thread::sleep_for(interval);
}
return false;
}
APIEvent::Type Device::attemptToBeginCommunication() { APIEvent::Type Device::attemptToBeginCommunication() {
versions.clear(); versions.clear();
@@ -451,8 +560,38 @@ bool Device::goOnline() {
return false; return false;
} }
if(supportsNetworkMutex()) {
assignedClientId = com->getClientIDSync();
if(assignedClientId) {
std::set<Network::NetID> nets;
for(auto&& net : getSupportedTXNetworks()) {
nets.insert(net.getNetID());
}
// firmware supports clientid/mutex
networkMutexCallbackHandle = lockNetworks(nets, std::numeric_limits<uint32_t>::max(), std::numeric_limits<uint32_t>::max(), NetworkMutexType::Shared, [this](std::shared_ptr<Message> message) {
auto netMutexMsg = std::static_pointer_cast<NetworkMutexMessage>(message);
if(netMutexMsg->networks.size() && netMutexMsg->event.has_value()) {
switch(*netMutexMsg->event) {
case NetworkMutexEvent::Acquired:
lockedNetworks.emplace(*netMutexMsg->networks.begin());
break;
case NetworkMutexEvent::Released: {
auto it = lockedNetworks.find(*netMutexMsg->networks.begin());
if (it != lockedNetworks.end())
lockedNetworks.erase(it);
break;
}
}
}
});
}
}
// (re)start the keeponline // (re)start the keeponline
keeponline = std::make_unique<Periodic>([this] { return enableNetworkCommunication(true, onlineTimeoutMs); }, std::chrono::milliseconds(onlineTimeoutMs / 4)); keeponline = std::make_unique<Periodic>([this] {
static std::vector<uint8_t> timeoutBytes = std::vector<uint8_t>((uint8_t*)&onlineTimeoutMs, (uint8_t*)&onlineTimeoutMs + sizeof(onlineTimeoutMs));
return com->sendCommand(Command::KeepAlive, timeoutBytes);
}, std::chrono::milliseconds(onlineTimeoutMs / 4));
online = true; online = true;
@@ -464,6 +603,9 @@ bool Device::goOnline() {
bool Device::goOffline() { bool Device::goOffline() {
keeponline.reset(); keeponline.reset();
if(networkMutexCallbackHandle)
removeMessageCallback(*networkMutexCallbackHandle);
forEachExtension([](const std::shared_ptr<DeviceExtension>& ext) { ext->onGoOffline(); return true; }); forEachExtension([](const std::shared_ptr<DeviceExtension>& ext) { ext->onGoOffline(); return true; });
if(isDisconnected()) { if(isDisconnected()) {
@@ -471,6 +613,11 @@ bool Device::goOffline() {
return true; return true;
} }
if(assignedClientId.has_value()) {
unlockAllNetworks();
assignedClientId.reset();
}
if(!enableNetworkCommunication(false)) if(!enableNetworkCommunication(false))
return false; return false;
@@ -794,9 +941,12 @@ bool Device::transmit(std::shared_ptr<Frame> frame) {
return transmitStatusFromExtension; return transmitStatusFromExtension;
std::vector<uint8_t> packet; std::vector<uint8_t> packet;
if(assignedClientId.has_value()) {
packet = TransmitMessage::EncodeFromMessage(frame, *assignedClientId, report);
return packet.size() && com->sendCommand(ExtendedCommand::TransmitMessage, packet);
}
if(!com->encoder->encode(*com->packetizer, packet, frame)) if(!com->encoder->encode(*com->packetizer, packet, frame))
return false; return false;
return com->sendPacket(packet); return com->sendPacket(packet);
} }
@@ -1178,7 +1328,7 @@ void Device::wiviThreadBody() {
// Use the command GetAll to get a WiVI::Info structure from the device // Use the command GetAll to get a WiVI::Info structure from the device
const auto generic = com->waitForMessageSync([this]() { const auto generic = com->waitForMessageSync([this]() {
return com->sendCommand(Command::WiVICommand, WiVI::CommandPacket::GetAll::Encode()); return com->sendCommand(Command::WiVICommand, WiVI::CommandPacket::GetAllHeader::Encode());
}, filter, std::chrono::milliseconds(1000)); }, filter, std::chrono::milliseconds(1000));
if(!generic || generic->type != Message::Type::WiVICommandResponse) { if(!generic || generic->type != Message::Type::WiVICommandResponse) {
@@ -1290,6 +1440,22 @@ void Device::wiviThreadBody() {
for(auto& cb : sleepRequestedCallbacks) for(auto& cb : sleepRequestedCallbacks)
cb.second = false; cb.second = false;
} }
// Process vin available callbacks
if (resp->info->vinAvailable & 1) {
for (auto& cb : vinAvailableCallbacks) {
if (!cb.second && cb.first) {
cb.second = true;
lk.unlock();
try {
cb.first();
} catch(...) {
report(APIEvent::Type::Unknown, APIEvent::Severity::Error);
}
lk.lock();
}
}
}
} }
} }
@@ -1464,6 +1630,110 @@ bool Device::allowSleep(bool remoteWakeup) {
return true; return true;
} }
Lifetime Device::addVINAvailableCallback(VINAvailableCallback cb)
{
if(!isOpen()) {
report(APIEvent::Type::DeviceCurrentlyClosed, APIEvent::Severity::Error);
return {};
}
if(!supportsWiVI()) {
report(APIEvent::Type::WiVINotSupported, APIEvent::Severity::Error);
return {};
}
std::lock_guard<std::mutex> lk(wiviMutex);
if(!wiviThread.joinable()) {
// Start the thread
stopWiVIThread = false;
wiviThread = std::thread([this]() { wiviThreadBody(); });
}
size_t idx = 0;
for(; idx < vinAvailableCallbacks.size(); idx++) {
if(!vinAvailableCallbacks[idx].first) // Empty space (previously erased callback)
break;
}
if(idx == vinAvailableCallbacks.size()) // Create a new space
vinAvailableCallbacks.emplace_back(std::move(cb), false);
else
vinAvailableCallbacks[idx] = { std::move(cb), false };
// Cleanup function to remove this sleep requested callback
return Lifetime([this, idx]() {
// TODO: Hold a weak ptr to the `this` instead of relying on the user to keep `this` valid
std::unique_lock<std::mutex> lk2(wiviMutex);
vinAvailableCallbacks[idx].first = VINAvailableCallback();
stopWiVIThreadIfNecessary(std::move(lk2));
});
}
std::optional<bool> Device::isVINEnabled() const
{
if(!isOpen()) {
report(APIEvent::Type::DeviceCurrentlyClosed, APIEvent::Severity::Error);
return std::nullopt;
}
if(!supportsWiVI()) {
report(APIEvent::Type::WiVINotSupported, APIEvent::Severity::Error);
return std::nullopt;
}
static std::shared_ptr<MessageFilter> filter = std::make_shared<MessageFilter>(Message::Type::WiVICommandResponse);
// Hold this lock so the WiVI stack doesn't issue a WiVICommand at the same time as us
std::lock_guard<std::mutex> lk(wiviMutex);
const auto generic = com->waitForMessageSync([this]() {
return com->sendCommand(Command::WiVICommand, WiVI::CommandPacket::GetSignal::Encode(WiVI::SignalType::VINEnabled));
}, filter, std::chrono::milliseconds(1000));
if(!generic || generic->type != Message::Type::WiVICommandResponse) {
report(APIEvent::Type::NoDeviceResponse, APIEvent::Severity::Error);
return std::nullopt;
}
const auto resp = std::static_pointer_cast<WiVI::ResponseMessage>(generic);
if(!resp->success || !resp->value.has_value()) {
report(APIEvent::Type::ValueNotYetPresent, APIEvent::Severity::Error);
return std::nullopt;
}
return *resp->value;
}
std::optional<std::string> Device::getVIN() const
{
if(!isOpen()) {
report(APIEvent::Type::DeviceCurrentlyClosed, APIEvent::Severity::Error);
return std::nullopt;
}
if(!supportsWiVI()) {
report(APIEvent::Type::WiVINotSupported, APIEvent::Severity::Error);
return std::nullopt;
}
static std::shared_ptr<MessageFilter> filter = std::make_shared<MessageFilter>(Message::Type::WiVICommandResponse);
std::lock_guard<std::mutex> lk(wiviMutex);
const auto generic = com->waitForMessageSync([this]() {
return com->sendCommand(Command::WiVICommand, WiVI::CommandPacket::GetVIN::Encode());
}, filter, std::chrono::milliseconds(1000));
if(!generic || generic->type != Message::Type::WiVICommandResponse) {
report(APIEvent::Type::NoDeviceResponse, APIEvent::Severity::Error);
return std::nullopt;
}
const auto resp = std::static_pointer_cast<WiVI::ResponseMessage>(generic);
if(!resp->success || !resp->vin.has_value()) {
report(APIEvent::Type::ValueNotYetPresent, APIEvent::Severity::Error);
return std::nullopt;
}
return *resp->vin;
}
void Device::scriptStatusThreadBody() void Device::scriptStatusThreadBody()
{ {
std::unique_lock<std::mutex> lk(scriptStatusMutex); std::unique_lock<std::mutex> lk(scriptStatusMutex);
@@ -1750,6 +2020,15 @@ 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);
@@ -1759,15 +2038,6 @@ 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) {
@@ -1837,16 +2107,12 @@ std::optional<EthPhyMessage> Device::sendEthPhyMsg(const EthPhyMessage& message,
report(APIEvent::Type::EthPhyRegisterControlNotAvailable, APIEvent::Severity::Error); report(APIEvent::Type::EthPhyRegisterControlNotAvailable, APIEvent::Severity::Error);
return std::nullopt; return std::nullopt;
} }
if(!isOnline()) {
report(APIEvent::Type::DeviceCurrentlyOffline, APIEvent::Severity::Error);
return std::nullopt;
}
std::vector<uint8_t> bytes; std::vector<uint8_t> bytes;
HardwareEthernetPhyRegisterPacket::EncodeFromMessage(message, bytes, report); HardwareEthernetPhyRegisterPacket::EncodeFromMessage(message, bytes, report);
std::shared_ptr<Message> response = com->waitForMessageSync( std::shared_ptr<Message> response = com->waitForMessageSync(
[this, bytes](){ return com->sendCommand(Command::PHYControlRegisters, bytes); }, [this, bytes](){ return com->sendCommand(Command::PHYControlRegisters, bytes); },
std::make_shared<MessageFilter>(Network::NetID::EthPHYControl), timeout); std::make_shared<MessageFilter>(Message::Type::EthernetPhyRegister), timeout);
if(!response) { if(!response) {
report(APIEvent::Type::NoDeviceResponse, APIEvent::Severity::Error); report(APIEvent::Type::NoDeviceResponse, APIEvent::Severity::Error);
@@ -2800,7 +3066,6 @@ std::optional<bool> Device::isVSAOverlapped(std::optional<VSAMetadata> optMetada
lastSectorRecord->getTimestamp() > metadata.coreMiniTimestamp; lastSectorRecord->getTimestamp() > metadata.coreMiniTimestamp;
} else if(lastSectorStatus == VSAParser::RecordParseStatus::NotARecordStart) { } else if(lastSectorStatus == VSAParser::RecordParseStatus::NotARecordStart) {
// The vsa record buffer is not full // The vsa record buffer is not full
report(APIEvent::Type::VSAOtherError, APIEvent::Severity::Error);
return false; return false;
} }
report(APIEvent::Type::VSABufferFormatError, APIEvent::Severity::Error); report(APIEvent::Type::VSABufferFormatError, APIEvent::Severity::Error);
@@ -3315,10 +3580,18 @@ std::optional<uint64_t> Device::vsaReadLogicalDisk(uint64_t pos, uint8_t* into,
return readLogicalDisk(pos, into, amount); return readLogicalDisk(pos, into, amount);
} }
uint64_t firstReadAmount = diskSize - pos; uint64_t firstReadAmount = diskSize - pos;
if(!readLogicalDisk(pos, into, firstReadAmount)) { uint64_t bytesRead = 0;
if(auto optBytesReadFirst = readLogicalDisk(pos, into, firstReadAmount)) {
bytesRead = *optBytesReadFirst;
} else {
return std::nullopt; return std::nullopt;
} }
return readLogicalDisk(VSA::RecordStartOffset, into + firstReadAmount, amount - firstReadAmount); if(auto optBytesReadSecond = readLogicalDisk(VSA::RecordStartOffset, into + firstReadAmount, amount - firstReadAmount)) {
bytesRead += *optBytesReadSecond;
} else {
return std::nullopt;
}
return bytesRead;
} }
bool Device::dispatchVSAMessages(VSAParser& parser) { bool Device::dispatchVSAMessages(VSAParser& parser) {
@@ -3480,13 +3753,19 @@ std::optional<GPTPStatus> Device::getGPTPStatus(std::chrono::milliseconds timeou
return *retMsg; return *retMsg;
} }
bool Device::writeMACsecConfig(const MACsecMessage& message, uint16_t binaryIndex) bool Device::writeMACsecConfig(const MACsecConfig& cfg) {
{ if(!cfg) {
std::vector<uint8_t> raw; report(APIEvent::Type::MACsecNotSupported, APIEvent::Severity::Error);
return false;
}
message.EncodeFromMessage(raw, report); if(getType() != cfg.getType()) {
report(APIEvent::Type::MACsecConfigMismatch, APIEvent::Severity::Error);
return false;
}
return writeBinaryFile(raw, binaryIndex); std::vector<uint8_t> raw = cfg.serialize();
return writeBinaryFile(raw, cfg.getBinIndex());
} }
bool Device::enableNetworkCommunication(bool enable, uint32_t timeout) { bool Device::enableNetworkCommunication(bool enable, uint32_t timeout) {
@@ -3628,3 +3907,201 @@ std::shared_ptr<DiskDetails> Device::getDiskDetails(std::chrono::milliseconds ti
return DiskDetails::Decode(extResponse->data, getDiskCount(), report); return DiskDetails::Decode(extResponse->data, getDiskCount(), report);
} }
[[nodiscard]] std::optional<int> Device::lockNetworks(const std::set<Network::NetID>& networks, uint32_t priority, uint32_t ttlMs, NetworkMutexType type, std::function<void(std::shared_ptr<Message>)>&& on_event)
{
if(!supportsNetworkMutex()) {
report(APIEvent::Type::NotSupported, APIEvent::Severity::Error);
return std::nullopt;
}
if(!assignedClientId.has_value()) {
report(APIEvent::Type::RequiredParameterNull, APIEvent::Severity::Error);
return std::nullopt;
}
constexpr auto timeout = std::chrono::milliseconds(250);
std::vector<uint8_t> payload = NetworkMutexMessage::EncodeArgumentsForLock(*assignedClientId, type, priority, ttlMs, networks, report);
std::optional<int> handle = std::nullopt;
if(on_event) {
handle.emplace(addMessageCallback(
std::make_shared<MessageCallback>(
on_event,
std::make_shared<MessageFilter>(Message::Type::NetworkMutex)
)
));
}
std::shared_ptr<Message> response = com->waitForMessageSync(
[this, payload](){
return com->sendCommand(ExtendedCommand::ProtobufAPI, payload);
},
std::make_shared<ExtendedResponseFilter>(ExtendedCommand::ProtobufAPI),
timeout
);
if(!response) {
report(APIEvent::Type::NoDeviceResponse, APIEvent::Severity::Error);
return std::nullopt;
}
auto extResponse = std::dynamic_pointer_cast<ExtendedResponseMessage>(response);
if(!extResponse) {
report(APIEvent::Type::UnexpectedResponse, APIEvent::Severity::Error);
return std::nullopt;
}
if(extResponse->response != ExtendedResponse::OK && extResponse->response != ExtendedResponse::OperationPending) {
return std::nullopt;
}
return handle;
}
bool Device::unlockNetworks(const std::set<Network::NetID>& networks)
{
if(!supportsNetworkMutex()) {
report(APIEvent::Type::NotSupported, APIEvent::Severity::Error);
return false;
}
if(!assignedClientId.has_value()) {
report(APIEvent::Type::RequiredParameterNull, APIEvent::Severity::Error);
return false;
}
constexpr auto timeout = std::chrono::milliseconds(250);
std::vector<uint8_t> payload = NetworkMutexMessage::EncodeArgumentsForUnlock(*assignedClientId, networks, report);
std::shared_ptr<Message> response = com->waitForMessageSync(
[this, payload](){
return com->sendCommand(ExtendedCommand::ProtobufAPI, payload);
},
std::make_shared<ExtendedResponseFilter>(ExtendedCommand::ProtobufAPI),
timeout
);
if(!response) {
report(APIEvent::Type::NoDeviceResponse, APIEvent::Severity::Error);
return false;
}
auto extResponse = std::dynamic_pointer_cast<ExtendedResponseMessage>(response);
if(!extResponse) {
report(APIEvent::Type::UnexpectedResponse, APIEvent::Severity::Error);
return false;
}
if(extResponse->response != ExtendedResponse::OK) {
return false;
}
return true;
}
std::shared_ptr<NetworkMutexMessage> Device::getNetworkMutexStatus(Network::NetID network)
{
if(!supportsNetworkMutex()) {
report(APIEvent::Type::NotSupported, APIEvent::Severity::Error);
return nullptr;
}
constexpr auto timeout = std::chrono::milliseconds(1000);
std::vector<uint8_t> payload = NetworkMutexMessage::EncodeArgumentsForStatus(network, report);
std::shared_ptr<Message> response = com->waitForMessageSync(
[this, payload](){
return com->sendCommand(ExtendedCommand::ProtobufAPI, payload);
},
std::make_shared<MessageFilter>(Message::Type::NetworkMutex),
timeout
);
return std::dynamic_pointer_cast<NetworkMutexMessage>(response);
}
[[nodiscard]] std::optional<int> Device::lockAllNetworks(uint32_t priority, uint32_t ttlMs, NetworkMutexType type, std::function<void(std::shared_ptr<Message>)>&& on_event)
{
if(!supportsNetworkMutex()) {
report(APIEvent::Type::NotSupported, APIEvent::Severity::Error);
return std::nullopt;
}
if(!assignedClientId.has_value()) {
report(APIEvent::Type::RequiredParameterNull, APIEvent::Severity::Error);
return std::nullopt;
}
constexpr auto timeout = std::chrono::milliseconds(1000);
std::vector<uint8_t> payload = NetworkMutexMessage::EncodeArgumentsForLockAll(*assignedClientId, type, priority, ttlMs, report);
int handle = addMessageCallback(
std::make_shared<MessageCallback>(
on_event,
std::make_shared<MessageFilter>(Message::Type::NetworkMutex)
)
);
std::shared_ptr<Message> response = com->waitForMessageSync(
[this, payload](){
return com->sendCommand(ExtendedCommand::ProtobufAPI, payload);
},
std::make_shared<ExtendedResponseFilter>(ExtendedCommand::ProtobufAPI),
timeout
);
if(!response) {
report(APIEvent::Type::NoDeviceResponse, APIEvent::Severity::Error);
return std::nullopt;
}
auto extResponse = std::dynamic_pointer_cast<ExtendedResponseMessage>(response);
if(!extResponse) {
report(APIEvent::Type::UnexpectedResponse, APIEvent::Severity::Error);
return std::nullopt;
}
if(extResponse->response != ExtendedResponse::OK && extResponse->response != ExtendedResponse::OperationPending) {
return std::nullopt;
}
return std::make_optional(handle);
}
bool Device::unlockAllNetworks()
{
if(!supportsNetworkMutex()) {
report(APIEvent::Type::NotSupported, APIEvent::Severity::Error);
return false;
}
if(!assignedClientId.has_value()) {
report(APIEvent::Type::RequiredParameterNull, APIEvent::Severity::Error);
return false;
}
constexpr auto timeout = std::chrono::milliseconds(1000);
std::vector<uint8_t> payload = NetworkMutexMessage::EncodeArgumentsForUnlockAll(*assignedClientId, report);
std::shared_ptr<Message> response = com->waitForMessageSync(
[this, payload](){
return com->sendCommand(ExtendedCommand::ProtobufAPI, payload);
},
std::make_shared<ExtendedResponseFilter>(ExtendedCommand::ProtobufAPI),
timeout
);
if(!response) {
report(APIEvent::Type::NoDeviceResponse, APIEvent::Severity::Error);
return false;
}
auto extResponse = std::dynamic_pointer_cast<ExtendedResponseMessage>(response);
if(!extResponse) {
report(APIEvent::Type::UnexpectedResponse, APIEvent::Severity::Error);
return false;
}
if(extResponse->response != ExtendedResponse::OK) {
return false;
}
return true;
}
+20 -13
View File
@@ -35,15 +35,6 @@ static void makeIfSerialMatches(const FoundDevice& dev, std::vector<std::shared_
into.push_back(std::make_shared<T>(dev)); into.push_back(std::make_shared<T>(dev));
} }
template<typename T>
static void makeIfPIDMatches(const FoundDevice& dev, std::vector<std::shared_ptr<Device>>& into) {
// Relies on the subclass to have a `static constexpr uint16_t PRODUCT_ID = 0x1111`
// and also a public constructor `T(const FoundDevice& dev)`
// Use macro ICSNEO_FINDABLE_DEVICE_BY_PID() to create these
if(dev.productId == T::PRODUCT_ID)
into.push_back(std::make_shared<T>(dev));
}
template<typename T> template<typename T>
static void makeIfSerialRangeMatches(const FoundDevice& dev, std::vector<std::shared_ptr<Device>>& into) { static void makeIfSerialRangeMatches(const FoundDevice& dev, std::vector<std::shared_ptr<Device>>& into) {
// Relies on the subclass to have // Relies on the subclass to have
@@ -139,7 +130,7 @@ std::vector<std::shared_ptr<Device>> DeviceFinder::FindAll() {
#endif #endif
#ifdef __NEOVIFIRE_H_ #ifdef __NEOVIFIRE_H_
makeIfPIDMatches<NeoVIFIRE>(dev, newFoundDevices); makeIfSerialRangeMatches<NeoVIFIRE>(dev, newFoundDevices);
#endif #endif
#ifdef __NEOVIFIRE2_H_ #ifdef __NEOVIFIRE2_H_
@@ -154,16 +145,20 @@ std::vector<std::shared_ptr<Device>> DeviceFinder::FindAll() {
makeIfSerialMatches<NeoVIFIRE3FlexRay>(dev, newFoundDevices); makeIfSerialMatches<NeoVIFIRE3FlexRay>(dev, newFoundDevices);
#endif #endif
#ifdef __NEOVIFIRE3T1SLIN_H_
makeIfSerialMatches<NeoVIFIRE3T1SLIN>(dev, newFoundDevices);
#endif
#ifdef __NEOVIRED2_H_ #ifdef __NEOVIRED2_H_
makeIfSerialMatches<NeoVIRED2>(dev, newFoundDevices); makeIfSerialMatches<NeoVIRED2>(dev, newFoundDevices);
#endif #endif
#ifdef __NEOVIION_H_ #ifdef __NEOVIION_H_
makeIfPIDMatches<NeoVIION>(dev, newFoundDevices); makeIfSerialMatches<NeoVIION>(dev, newFoundDevices);
#endif #endif
#ifdef __NEOVIPLASMA_H_ #ifdef __NEOVIPLASMA_H_
makeIfPIDMatches<NeoVIPLASMA>(dev, newFoundDevices); makeIfSerialMatches<NeoVIPLASMA>(dev, newFoundDevices);
#endif #endif
#ifdef __RADA2B_H_ #ifdef __RADA2B_H_
@@ -230,6 +225,10 @@ std::vector<std::shared_ptr<Device>> DeviceFinder::FindAll() {
makeIfSerialMatches<RADMoon3>(dev, newFoundDevices); makeIfSerialMatches<RADMoon3>(dev, newFoundDevices);
#endif #endif
#ifdef __RADGEMINI_H_
makeIfSerialMatches<RADGemini>(dev, newFoundDevices);
#endif
#ifdef __RADMOONDUO_H_ #ifdef __RADMOONDUO_H_
makeIfSerialMatches<RADMoonDuo>(dev, newFoundDevices); makeIfSerialMatches<RADMoonDuo>(dev, newFoundDevices);
#endif #endif
@@ -247,7 +246,7 @@ std::vector<std::shared_ptr<Device>> DeviceFinder::FindAll() {
#endif #endif
#ifdef __VALUECAN3_H_ #ifdef __VALUECAN3_H_
makeIfPIDMatches<ValueCAN3>(dev, newFoundDevices); makeIfSerialRangeMatches<ValueCAN3>(dev, newFoundDevices);
#endif #endif
#ifdef __VALUECAN4_1_H_ #ifdef __VALUECAN4_1_H_
@@ -325,6 +324,10 @@ const std::vector<DeviceType>& DeviceFinder::GetSupportedDevices() {
NeoVIFIRE3FlexRay::DEVICE_TYPE, NeoVIFIRE3FlexRay::DEVICE_TYPE,
#endif #endif
#ifdef __NEOVIFIRE3T1SLIN_H_
NeoVIFIRE3T1SLIN::DEVICE_TYPE,
#endif
#ifdef __NEOVIION_H_ #ifdef __NEOVIION_H_
NeoVIION::DEVICE_TYPE, NeoVIION::DEVICE_TYPE,
#endif #endif
@@ -385,6 +388,10 @@ const std::vector<DeviceType>& DeviceFinder::GetSupportedDevices() {
RADMoon3::DEVICE_TYPE, RADMoon3::DEVICE_TYPE,
#endif #endif
#ifdef __RADGEMINI_H_
RADGemini::DEVICE_TYPE,
#endif
#ifdef __RADMOONDUO_H_ #ifdef __RADMOONDUO_H_
RADMoonDuo::DEVICE_TYPE, RADMoonDuo::DEVICE_TYPE,
#endif #endif
+45 -53
View File
@@ -3,16 +3,6 @@
using namespace icsneo; using namespace icsneo;
void FlexRay::Controller::_setStatus(std::shared_ptr<FlexRayControlMessage> msg) {
std::lock_guard<std::mutex> lk(statusLock);
status = msg;
}
std::shared_ptr<FlexRayControlMessage> FlexRay::Controller::getStatus() const {
std::lock_guard<std::mutex> lk(statusLock);
return status;
}
std::pair<const FlexRay::Cluster::Configuration&, const FlexRay::Controller::Configuration&> FlexRay::Controller::getConfiguration() const { std::pair<const FlexRay::Cluster::Configuration&, const FlexRay::Controller::Configuration&> FlexRay::Controller::getConfiguration() const {
return { clusterConfig, controllerConfig }; return { clusterConfig, controllerConfig };
} }
@@ -74,7 +64,7 @@ bool FlexRay::Controller::configure(std::chrono::milliseconds timeout) {
((controllerConfig.KeySlotUsedForStartup & 0x1) << 8) | // TXST ((controllerConfig.KeySlotUsedForStartup & 0x1) << 8) | // TXST
((controllerConfig.KeySlotUsedForSync & 0x1) << 9) | // TXSY ((controllerConfig.KeySlotUsedForSync & 0x1) << 9) | // TXSY
((clusterConfig.ColdStartAttempts & 0x1f) << 11) | // CSA ((clusterConfig.ColdStartAttempts & 0x1f) << 11) | // CSA
((controllerConfig.AllowPassiveToActiveCyclePairs & 0x1f) << 16) | // PTA ((controllerConfig.AllowPassiveToActiveCyclePairs & 0x1F) << 16) | // PTA
((controllerConfig.WakeupOnChannelB & 0x1) << 21) | // WUCS ((controllerConfig.WakeupOnChannelB & 0x1) << 21) | // WUCS
((controllerConfig.KeySlotOnlyEnabled & 0x1) << 22) | // TSM ((controllerConfig.KeySlotOnlyEnabled & 0x1) << 22) | // TSM
((controllerConfig.AllowHaltDueToClock & 0x1) << 23) | // HCSE ((controllerConfig.AllowHaltDueToClock & 0x1) << 23) | // HCSE
@@ -85,99 +75,100 @@ bool FlexRay::Controller::configure(std::chrono::milliseconds timeout) {
}); });
registerWrites.push_back({ ERAYRegister::SUCC2, registerWrites.push_back({ ERAYRegister::SUCC2,
((controllerConfig.ListenTimeout & 0x1fffff)) | ((controllerConfig.ListenTimeout & 0x1FFFFF)) |
((clusterConfig.ListenNoiseMacroticks - 1) << 24) (((clusterConfig.ListenNoiseMacroticks - 1) & 0xF) << 24)
}); });
registerWrites.push_back({ ERAYRegister::SUCC3, registerWrites.push_back({ ERAYRegister::SUCC3,
(clusterConfig.MaxWithoutClockCorrectionPassive & 0xF) | (clusterConfig.MaxWithoutClockCorrectionPassive & 0xF) |
((clusterConfig.MaxWithoutClockCorrectionFatal) << 4) ((clusterConfig.MaxWithoutClockCorrectionFatal & 0xF) << 4)
}); });
registerWrites.push_back({ ERAYRegister::NEMC, registerWrites.push_back({ ERAYRegister::NEMC,
clusterConfig.NetworkManagementVectorLengthBytes clusterConfig.NetworkManagementVectorLengthBytes & 0xF
}); });
registerWrites.push_back({ ERAYRegister::PRTC1, registerWrites.push_back({ ERAYRegister::PRTC1,
(clusterConfig.TransmissionStartSequenceDurationBits & 0xF) | (clusterConfig.TransmissionStartSequenceDurationBits & 0xF) |
((clusterConfig.CASRxLowMax & 0x3F) << 4) | ((clusterConfig.CASRxLowMax & 0x1F) << 4) |
(0x1 << 10) | // Most significant bit of CASRxLowMax. Hardwired to 1 and cannot be modified
((clusterConfig.StrobePointPosition & 0x3) << 12) | ((clusterConfig.StrobePointPosition & 0x3) << 12) |
((clusterConfig.Speed & 0x3) << 14) | ((clusterConfig.Speed & 0x3) << 14) |
((clusterConfig.WakeupRxWindowBits & 0x1ff) << 16) | ((clusterConfig.WakeupRxWindowBits & 0x1FF) << 16) |
((controllerConfig.WakeupPattern) << 26) ((controllerConfig.WakeupPattern & 0x3F) << 26)
}); });
registerWrites.push_back({ ERAYRegister::PRTC2, registerWrites.push_back({ ERAYRegister::PRTC2,
(clusterConfig.WakeupRxIdleBits) | (clusterConfig.WakeupRxIdleBits & 0x3F) |
((clusterConfig.WakeupRxLowBits) << 8) | ((clusterConfig.WakeupRxLowBits & 0x3F) << 8) |
((clusterConfig.WakeupTxIdleBits) << 16) | ((clusterConfig.WakeupTxIdleBits) << 16) |
((clusterConfig.WakeupTxActiveBits) << 24) ((clusterConfig.WakeupTxActiveBits & 0x3F) << 24)
}); });
registerWrites.push_back({ ERAYRegister::MHDC, registerWrites.push_back({ ERAYRegister::MHDC,
(clusterConfig.PayloadLengthOfStaticSlotInWords) | (clusterConfig.PayloadLengthOfStaticSlotInWords & 0x7F) |
((controllerConfig.LatestTxMinislot) << 16) ((controllerConfig.LatestTxMinislot & 0x1FFF) << 16)
}); });
registerWrites.push_back({ ERAYRegister::GTUC1, registerWrites.push_back({ ERAYRegister::GTUC1,
controllerConfig.MicroPerCycle controllerConfig.MicroPerCycle & 0xFFFFF
}); });
registerWrites.push_back({ ERAYRegister::GTUC2, registerWrites.push_back({ ERAYRegister::GTUC2,
(clusterConfig.SyncFrameIDCountMax << 16) | (clusterConfig.SyncFrameIDCountMax << 16) |
clusterConfig.MacroticksPerCycle (clusterConfig.MacroticksPerCycle & 0x3FFF)
}); });
registerWrites.push_back({ ERAYRegister::GTUC3, registerWrites.push_back({ ERAYRegister::GTUC3,
(controllerConfig.MicroInitialOffsetA) | (controllerConfig.MicroInitialOffsetA) |
((controllerConfig.MicroInitialOffsetB) << 8) | ((controllerConfig.MicroInitialOffsetB) << 8) |
((controllerConfig.MacroInitialOffsetA) << 16) | ((controllerConfig.MacroInitialOffsetA & 0x7F) << 16) |
((controllerConfig.MacroInitialOffsetB) << 24) ((controllerConfig.MacroInitialOffsetB & 0x7F) << 24)
}); });
registerWrites.push_back({ ERAYRegister::GTUC4, registerWrites.push_back({ ERAYRegister::GTUC4,
((clusterConfig.MacroticksPerCycle - clusterConfig.NetworkIdleTimeMacroticks - 1) & 0xFFFF) | ((clusterConfig.MacroticksPerCycle - clusterConfig.NetworkIdleTimeMacroticks - 1) & 0x3FFF) |
((clusterConfig.OffsetCorrectionStartMacroticks - 1) << 16) (((clusterConfig.OffsetCorrectionStartMacroticks - 1) & 0x3FFF) << 16)
}); });
registerWrites.push_back({ ERAYRegister::GTUC5, registerWrites.push_back({ ERAYRegister::GTUC5,
controllerConfig.DelayCompensationAMicroticks | controllerConfig.DelayCompensationAMicroticks |
(controllerConfig.DelayCompensationBMicroticks << 8) | (controllerConfig.DelayCompensationBMicroticks << 8) |
(controllerConfig.ClusterDriftDamping << 16) | ((controllerConfig.ClusterDriftDamping & 0x1F) << 16) |
(controllerConfig.DecodingCorrectionMicroticks << 24) (controllerConfig.DecodingCorrectionMicroticks << 24)
}); });
registerWrites.push_back({ ERAYRegister::GTUC6, registerWrites.push_back({ ERAYRegister::GTUC6,
controllerConfig.AcceptStartupRangeMicroticks | (controllerConfig.AcceptStartupRangeMicroticks & 0x7FF) |
(controllerConfig.RateCorrectionOutMicroticks << 16) ((controllerConfig.RateCorrectionOutMicroticks & 0x7FF) << 16)
}); });
registerWrites.push_back({ ERAYRegister::GTUC7, registerWrites.push_back({ ERAYRegister::GTUC7,
(clusterConfig.StaticSlotMacroticks) | (clusterConfig.StaticSlotMacroticks & 0x3FF) |
(clusterConfig.NumberOfStaticSlots << 16) ((clusterConfig.NumberOfStaticSlots & 0x3FF) << 16)
}); });
registerWrites.push_back({ ERAYRegister::GTUC8, registerWrites.push_back({ ERAYRegister::GTUC8,
clusterConfig.MinislotDurationMacroticks | (clusterConfig.MinislotDurationMacroticks & 0x3F) |
(clusterConfig.NumberOfMinislots << 16) ((clusterConfig.NumberOfMinislots & 0x1FFF) << 16)
}); });
registerWrites.push_back({ ERAYRegister::GTUC9, registerWrites.push_back({ ERAYRegister::GTUC9,
clusterConfig.ActionPointOffset | (clusterConfig.ActionPointOffset & 0x3F) |
(clusterConfig.MinislotActionPointOffsetMacroticks << 8) | ((clusterConfig.MinislotActionPointOffsetMacroticks & 0x1F) << 8) |
(clusterConfig.DynamicSlotIdlePhaseMinislots << 16) ((clusterConfig.DynamicSlotIdlePhaseMinislots & 0x03) << 16)
}); });
registerWrites.push_back({ ERAYRegister::GTUC10, registerWrites.push_back({ ERAYRegister::GTUC10,
controllerConfig.OffsetCorrectionOutMicroticks | (controllerConfig.OffsetCorrectionOutMicroticks & 0x3FFF) |
(controllerConfig.RateCorrectionOutMicroticks << 16) ((controllerConfig.RateCorrectionOutMicroticks & 0x7FF) << 16)
}); });
registerWrites.push_back({ ERAYRegister::GTUC11, registerWrites.push_back({ ERAYRegister::GTUC11,
controllerConfig.ExternOffsetCorrectionControl | (controllerConfig.ExternOffsetCorrectionControl & 0x3) |
(controllerConfig.ExternRateCorrectionControl << 8) | ((controllerConfig.ExternRateCorrectionControl & 0x3) << 8) |
(controllerConfig.ExternOffsetCorrectionMicroticks << 16) | ((controllerConfig.ExternOffsetCorrectionMicroticks & 0x7) << 16) |
(controllerConfig.ExternRateCorrectionMicroticks << 24) ((controllerConfig.ExternRateCorrectionMicroticks & 0x7) << 24)
}); });
std::vector<std::shared_ptr<MessageBuffer>> staticTx; std::vector<std::shared_ptr<MessageBuffer>> staticTx;
@@ -210,7 +201,7 @@ bool FlexRay::Controller::configure(std::chrono::milliseconds timeout) {
second->isStartup = controllerConfig.KeySlotUsedForStartup; second->isStartup = controllerConfig.KeySlotUsedForStartup;
second->isSync = controllerConfig.KeySlotUsedForSync; second->isSync = controllerConfig.KeySlotUsedForSync;
second->isTransmit = true; second->isTransmit = true;
second->channelB =true; second->channelB = true;
second->frameID = controllerConfig.SecondKeySlotID; second->frameID = controllerConfig.SecondKeySlotID;
second->frameLengthBytes = clusterConfig.PayloadLengthOfStaticSlotInWords * 2; second->frameLengthBytes = clusterConfig.PayloadLengthOfStaticSlotInWords * 2;
second->baseCycle = 0; second->baseCycle = 0;
@@ -266,7 +257,7 @@ bool FlexRay::Controller::configure(std::chrono::milliseconds timeout) {
totalBuffers = 128; totalBuffers = 128;
registerWrites.push_back({ ERAYRegister::MRC, registerWrites.push_back({ ERAYRegister::MRC,
(uint8_t(staticTx.size())) | // FDB[7:0] message buffers exclusively for the static segment (static_cast<uint8_t>(staticTx.size())) | // FDB[7:0] message buffers exclusively for the static segment
// FFB[7:0] set to 0x80, No message buffer assigned to the FIFO // FFB[7:0] set to 0x80, No message buffer assigned to the FIFO
(0x80 << 8) | (0x80 << 8) |
(uint8_t(totalBuffers - 1) << 16) | (uint8_t(totalBuffers - 1) << 16) |
@@ -287,12 +278,12 @@ bool FlexRay::Controller::configure(std::chrono::milliseconds timeout) {
buf.frameID = static_cast<uint16_t>(i | (1 << 10)); buf.frameID = static_cast<uint16_t>(i | (1 << 10));
uint32_t hs1 = ( uint32_t hs1 = (
(buf.frameID) | (buf.frameID) | // FID
(CalculateCycleFilter(buf.baseCycle, buf.cycleRepetition) << 16) | (CalculateCycleFilter(buf.baseCycle, buf.cycleRepetition) << 16) | // CYA
((buf.channelA & 0x1) << 24) | ((buf.channelA & 0x1) << 24) | // CHA
((buf.channelB & 0x1) << 25) | ((buf.channelB & 0x1) << 25) | // CHB
((buf.isTransmit & 0x1) << 26) | // CFG ((buf.isTransmit & 0x1) << 26) | // CFG
((buf.isNMFrame & 0x1) << 27) | // PPIT ((buf.isNetworkManagementFrame & 0x1) << 27) | // PPIT
((!buf.continuousMode & 0x1) << 28) | // TXM ((!buf.continuousMode & 0x1) << 28) | // TXM
((0 & 0x1) << 29) // MBI, disabled for now but we might want confirmations in the future ((0 & 0x1) << 29) // MBI, disabled for now but we might want confirmations in the future
); );
@@ -610,7 +601,8 @@ uint16_t FlexRay::Controller::CalculateCycleFilter(uint8_t baseCycle, uint8_t cy
} }
std::pair<bool, uint32_t> FlexRay::Controller::readRegister(ERAYRegister reg, std::chrono::milliseconds timeout) const { std::pair<bool, uint32_t> FlexRay::Controller::readRegister(ERAYRegister reg, std::chrono::milliseconds timeout) const {
static const std::shared_ptr<MessageFilter> filter = std::make_shared<MessageFilter>(icsneo::Network::NetID::FlexRayControl); static const std::shared_ptr<MessageFilter> filter = std::make_shared<MessageFilter>();
filter->includeInternalInAny = true;
if(timeout.count() <= 20) if(timeout.count() <= 20)
return {false, 0}; // Out of time! return {false, 0}; // Out of time!
-20
View File
@@ -25,26 +25,6 @@ void FlexRay::Extension::onGoOffline() {
controller->halt(); controller->halt();
} }
void FlexRay::Extension::handleMessage(const std::shared_ptr<Message>& message) {
switch(message->type) {
case Message::Type::FlexRayControl: {
auto msg = std::dynamic_pointer_cast<FlexRayControlMessage>(message);
if(!msg || !msg->decoded)
return;
switch(msg->opcode) {
case FlexRay::Opcode::ReadCCStatus:
if(msg->controller >= controllers.size())
return; // TODO error
controllers[msg->controller]->_setStatus(msg);
break;
}
break;
}
default:
break;
}
}
bool FlexRay::Extension::transmitHook(const std::shared_ptr<Frame>& frame, bool& success) { bool FlexRay::Extension::transmitHook(const std::shared_ptr<Frame>& frame, bool& success) {
if(!frame || frame->network.getType() != Network::Type::FlexRay) if(!frame || frame->network.getType() != Network::Type::FlexRay)
return true; // Don't hook non-FlexRay messages return true; // Don't hook non-FlexRay messages
+23 -35
View File
@@ -4,9 +4,9 @@
using namespace icsneo; using namespace icsneo;
std::optional<uint16_t> IDeviceSettings::CalculateGSChecksum(const std::vector<uint8_t>& settings, std::optional<size_t> knownSize) { std::optional<uint16_t> IDeviceSettings::CalculateGSChecksum(const std::vector<uint8_t>& settings) {
const uint16_t* p = reinterpret_cast<const uint16_t*>(settings.data()); const uint16_t* p = reinterpret_cast<const uint16_t*>(settings.data());
size_t words = std::min(knownSize.value_or(0), settings.size()); size_t words = settings.size();
if(words % 2 == 1) if(words % 2 == 1)
return std::nullopt; // Somehow settings is not word aligned return std::nullopt; // Somehow settings is not word aligned
words /= 2; words /= 2;
@@ -159,15 +159,12 @@ bool IDeviceSettings::ValidateLINBaudrate(int64_t baudrate) {
} }
} }
bool IDeviceSettings::refresh(bool ignoreChecksum) { bool IDeviceSettings::refresh() {
if(disabled) { if(disabled) {
report(APIEvent::Type::SettingsNotAvailable, APIEvent::Severity::Error); report(APIEvent::Type::SettingsNotAvailable, APIEvent::Severity::Error);
return false; return false;
} }
if(disableGSChecksumming)
ignoreChecksum = true;
std::vector<uint8_t> rxSettings; std::vector<uint8_t> rxSettings;
bool ret = com->getSettingsSync(rxSettings); bool ret = com->getSettingsSync(rxSettings);
if(!ret) { if(!ret) {
@@ -175,24 +172,14 @@ bool IDeviceSettings::refresh(bool ignoreChecksum) {
return false; return false;
} }
constexpr size_t GsSize = 3 * sizeof(uint16_t); constexpr size_t GsSize = 3 * sizeof(uint16_t); // <version> <length> <checksum>
if(rxSettings.size() < GsSize) { // We need to at least have the header of GLOBAL_SETTINGS if(rxSettings.size() < GsSize) { // We need to at least have the header of GLOBAL_SETTINGS
report(APIEvent::Type::SettingsReadError, APIEvent::Severity::Error); report(APIEvent::Type::SettingsReadError, APIEvent::Severity::Error);
return false; return false;
} }
// The length of the settings structure sent to us
// This is the length the firmware thinks the current version of the structure is
const size_t rxLen = rxSettings.size() - GsSize;
const uint16_t gsVersion = rxSettings[0] | (rxSettings[1] << 8); const uint16_t gsVersion = rxSettings[0] | (rxSettings[1] << 8);
// The length of the settings last saved
// If the firmware is updated, it will have either extended (with zeros) or truncated
// the structure, but this value will continue to be set to the last saved value
const uint16_t gsLen = rxSettings[2] | (rxSettings[3] << 8);
const uint16_t gsChecksum = rxSettings[4] | (rxSettings[5] << 8);
rxSettings.erase(rxSettings.begin(), rxSettings.begin() + GsSize); rxSettings.erase(rxSettings.begin(), rxSettings.begin() + GsSize);
if(gsVersion != GS_VERSION) { if(gsVersion != GS_VERSION) {
@@ -200,19 +187,6 @@ bool IDeviceSettings::refresh(bool ignoreChecksum) {
return false; return false;
} }
if(rxLen < gsLen) {
// We got less data, i.e. the firmware thinks the strucure is smaller than what
// was last saved. Usually this is due to a firmware downgrade. We'll ignore the
// checksum for now, because it will definitely be wrong.
ignoreChecksum = true;
}
// We check the checksum against the data last saved
if(!ignoreChecksum && gsChecksum != CalculateGSChecksum(rxSettings, gsLen)) {
report(APIEvent::Type::SettingsChecksumError, APIEvent::Severity::Error);
return false;
}
settings = std::move(rxSettings); settings = std::move(rxSettings);
settingsInDeviceRAM = settings; settingsInDeviceRAM = settings;
settingsLoaded = true; settingsLoaded = true;
@@ -261,7 +235,7 @@ bool IDeviceSettings::apply(bool temporary) {
std::shared_ptr<Main51Message> msg = std::dynamic_pointer_cast<Main51Message>(com->waitForMessageSync([this, &bytestream]() { std::shared_ptr<Main51Message> msg = std::dynamic_pointer_cast<Main51Message>(com->waitForMessageSync([this, &bytestream]() {
return com->sendCommand(Command::SetSettings, bytestream); return com->sendCommand(Command::SetSettings, bytestream);
}, std::make_shared<Main51MessageFilter>(Command::SetSettings), std::chrono::milliseconds(1000))); }, std::make_shared<Main51MessageFilter>(Command::SetSettings), std::chrono::milliseconds(2000)));
if(!msg || msg->data[0] != 1) { // We did not receive a response if(!msg || msg->data[0] != 1) { // We did not receive a response
// Attempt to get the settings from the device so we're up to date if possible // Attempt to get the settings from the device so we're up to date if possible
@@ -272,7 +246,7 @@ bool IDeviceSettings::apply(bool temporary) {
return false; return false;
} }
refresh(true); // Refresh ignoring checksum refresh();
// The device might modify the settings once they are applied, however in this case it does not update the checksum // The device might modify the settings once they are applied, however in this case it does not update the checksum
// We refresh to get these updates, update the checksum, and send it back so it's all in sync // We refresh to get these updates, update the checksum, and send it back so it's all in sync
gsChecksum = CalculateGSChecksum(settings); gsChecksum = CalculateGSChecksum(settings);
@@ -287,7 +261,7 @@ bool IDeviceSettings::apply(bool temporary) {
msg = std::dynamic_pointer_cast<Main51Message>(com->waitForMessageSync([this, &bytestream]() { msg = std::dynamic_pointer_cast<Main51Message>(com->waitForMessageSync([this, &bytestream]() {
return com->sendCommand(Command::SetSettings, bytestream); return com->sendCommand(Command::SetSettings, bytestream);
}, std::make_shared<Main51MessageFilter>(Command::SetSettings), std::chrono::milliseconds(1000))); }, std::make_shared<Main51MessageFilter>(Command::SetSettings), std::chrono::milliseconds(2000)));
if(!msg || msg->data[0] != 1) { if(!msg || msg->data[0] != 1) {
// Attempt to get the settings from the device so we're up to date if possible // Attempt to get the settings from the device so we're up to date if possible
if(refresh()) { if(refresh()) {
@@ -342,7 +316,7 @@ bool IDeviceSettings::applyDefaults(bool temporary) {
// This short wait helps on FIRE devices, otherwise the checksum might be wrong! // This short wait helps on FIRE devices, otherwise the checksum might be wrong!
std::this_thread::sleep_for(std::chrono::milliseconds(3)); std::this_thread::sleep_for(std::chrono::milliseconds(3));
refresh(true); // Refresh ignoring checksum refresh();
// The device might modify the settings once they are applied, however in this case it does not update the checksum // The device might modify the settings once they are applied, however in this case it does not update the checksum
// We refresh to get these updates, update the checksum, and send it back so it's all in sync // We refresh to get these updates, update the checksum, and send it back so it's all in sync
std::vector<uint8_t> bytestream; std::vector<uint8_t> bytestream;
@@ -364,7 +338,7 @@ bool IDeviceSettings::applyDefaults(bool temporary) {
msg = std::dynamic_pointer_cast<Main51Message>(com->waitForMessageSync([this, &bytestream]() { msg = std::dynamic_pointer_cast<Main51Message>(com->waitForMessageSync([this, &bytestream]() {
return com->sendCommand(Command::SetSettings, bytestream); return com->sendCommand(Command::SetSettings, bytestream);
}, std::make_shared<Main51MessageFilter>(Command::SetSettings), std::chrono::milliseconds(1000))); }, std::make_shared<Main51MessageFilter>(Command::SetSettings), std::chrono::milliseconds(2000)));
if(!msg || msg->data[0] != 1) { if(!msg || msg->data[0] != 1) {
// Attempt to get the settings from the device so we're up to date if possible // Attempt to get the settings from the device so we're up to date if possible
if(refresh()) { if(refresh()) {
@@ -971,4 +945,18 @@ template<typename T> bool IDeviceSettings::applyStructure(const T& newStructure)
memcpy(settings.data(), &newStructure, structSize); memcpy(settings.data(), &newStructure, structSize);
return apply(); return apply();
}
bool IDeviceSettings::setMiscIOAnalogOutputEnabled(uint8_t pin, bool enabled) {
(void)pin;
(void)enabled;
report(APIEvent::Type::SettingNotAvaiableDevice, APIEvent::Severity::Error);
return false;
}
bool IDeviceSettings::setMiscIOAnalogOutput(uint8_t pin, MiscIOAnalogVoltage voltage) {
(void)pin;
(void)voltage;
report(APIEvent::Type::SettingNotAvaiableDevice, APIEvent::Severity::Error);
return false;
} }
-15
View File
@@ -25,19 +25,4 @@ void VSAExtendedMessage::appendPacket(std::shared_ptr<Packet> packet) const
if(packet->network.getNetID() == Network::NetID::Invalid) { if(packet->network.getNetID() == Network::NetID::Invalid) {
packet->network = network; packet->network = network;
} }
}
void VSAExtendedMessage::truncatePacket(std::shared_ptr<Packet> packet)
{
static constexpr auto EthernetLengthOffset = 26u;
switch(packet->network.getType()) {
case Network::Type::Ethernet:
{
const auto& packetLength = *reinterpret_cast<uint16_t*>(packet->data.data() + EthernetLengthOffset);
const size_t ethernetFrameSize = packetLength - (sizeof(uint16_t) * 2);
const size_t bytestreamExpectedSize = sizeof(HardwareEthernetPacket) + ethernetFrameSize;
packet->data.resize(bytestreamExpectedSize);
}
break;
}
} }
+1 -1
View File
@@ -9,7 +9,7 @@ VSA02::VSA02(uint8_t* const recordBytes)
constantIndex = *reinterpret_cast<uint16_t*>(recordBytes + 2); constantIndex = *reinterpret_cast<uint16_t*>(recordBytes + 2);
flags = *reinterpret_cast<Flags*>(recordBytes + 4); flags = *reinterpret_cast<Flags*>(recordBytes + 4);
pieceCount = recordBytes[5]; pieceCount = recordBytes[5];
timestamp = *reinterpret_cast<uint64_t*>(recordBytes + 6) & UINT63_MAX; timestamp = *reinterpret_cast<uint64_t*>(recordBytes + 6);
samples.insert(samples.end(), recordBytes + 14, recordBytes + 30); samples.insert(samples.end(), recordBytes + 14, recordBytes + 30);
checksum = *reinterpret_cast<uint16_t*>(recordBytes + 30); checksum = *reinterpret_cast<uint16_t*>(recordBytes + 30);
doChecksum(recordBytes); doChecksum(recordBytes);
+1 -1
View File
@@ -8,7 +8,7 @@ VSA03::VSA03(uint8_t* const recordBytes)
setType(VSA::Type::AA03); setType(VSA::Type::AA03);
eventType = static_cast<EventType>(*reinterpret_cast<uint16_t*>(recordBytes + 2)); eventType = static_cast<EventType>(*reinterpret_cast<uint16_t*>(recordBytes + 2));
eventData = *reinterpret_cast<uint16_t*>(recordBytes + 4); eventData = *reinterpret_cast<uint16_t*>(recordBytes + 4);
timestamp = *reinterpret_cast<uint64_t*>(recordBytes + 6) & UINT63_MAX; timestamp = *reinterpret_cast<uint64_t*>(recordBytes + 6);
checksum = *reinterpret_cast<uint16_t*>(recordBytes + 14); checksum = *reinterpret_cast<uint16_t*>(recordBytes + 14);
doChecksum(recordBytes); doChecksum(recordBytes);
} }
+1 -1
View File
@@ -8,7 +8,7 @@ VSA04::VSA04(uint8_t* const recordBytes)
setType(VSA::Type::AA04); setType(VSA::Type::AA04);
flags = *reinterpret_cast<Flags*>(recordBytes + 2); flags = *reinterpret_cast<Flags*>(recordBytes + 2);
partitionIndex = *reinterpret_cast<uint16_t*>(recordBytes + 4); partitionIndex = *reinterpret_cast<uint16_t*>(recordBytes + 4);
timestamp = *reinterpret_cast<uint64_t*>(recordBytes + 6) & UINT63_MAX; timestamp = *reinterpret_cast<uint64_t*>(recordBytes + 6);
checksum = *reinterpret_cast<uint16_t*>(recordBytes + 14); checksum = *reinterpret_cast<uint16_t*>(recordBytes + 14);
doChecksum(recordBytes); doChecksum(recordBytes);
} }
+1 -1
View File
@@ -8,7 +8,7 @@ VSA05::VSA05(uint8_t* const recordBytes)
setType(VSA::Type::AA05); setType(VSA::Type::AA05);
errorType = static_cast<ErrorType>(*reinterpret_cast<uint16_t*>(recordBytes + 2)); errorType = static_cast<ErrorType>(*reinterpret_cast<uint16_t*>(recordBytes + 2));
errorNetwork = *reinterpret_cast<uint16_t*>(recordBytes + 4); errorNetwork = *reinterpret_cast<uint16_t*>(recordBytes + 4);
timestamp = *reinterpret_cast<uint64_t*>(recordBytes + 6) & UINT63_MAX; timestamp = *reinterpret_cast<uint64_t*>(recordBytes + 6);
checksum = *reinterpret_cast<uint16_t*>(recordBytes + 14); checksum = *reinterpret_cast<uint16_t*>(recordBytes + 14);
} }
+1 -1
View File
@@ -9,7 +9,7 @@ VSA06::VSA06(uint8_t* const recordBytes)
savedSectors.insert(savedSectors.end(), reinterpret_cast<uint32_t*>(recordBytes + 2), reinterpret_cast<uint32_t*>(recordBytes + 18)); savedSectors.insert(savedSectors.end(), reinterpret_cast<uint32_t*>(recordBytes + 2), reinterpret_cast<uint32_t*>(recordBytes + 18));
error = *reinterpret_cast<uint16_t*>(recordBytes + 18); error = *reinterpret_cast<uint16_t*>(recordBytes + 18);
savedSectorsHigh = *reinterpret_cast<uint16_t*>(recordBytes + 20); savedSectorsHigh = *reinterpret_cast<uint16_t*>(recordBytes + 20);
timestamp = *reinterpret_cast<uint64_t*>(recordBytes + 22) & UINT63_MAX; timestamp = *reinterpret_cast<uint64_t*>(recordBytes + 22);
checksum = *reinterpret_cast<uint16_t*>(recordBytes + 30); checksum = *reinterpret_cast<uint16_t*>(recordBytes + 30);
doChecksum(recordBytes); doChecksum(recordBytes);
} }
+1 -1
View File
@@ -9,7 +9,7 @@ VSA07::VSA07(uint8_t* const recordBytes)
lastSector = *reinterpret_cast<uint32_t*>(recordBytes + 2); lastSector = *reinterpret_cast<uint32_t*>(recordBytes + 2);
currentSector = *reinterpret_cast<uint32_t*>(recordBytes + 6); currentSector = *reinterpret_cast<uint32_t*>(recordBytes + 6);
reserved.insert(reserved.end(), recordBytes + 10, recordBytes + 22); reserved.insert(reserved.end(), recordBytes + 10, recordBytes + 22);
timestamp = *reinterpret_cast<uint64_t*>(recordBytes + 22) & UINT63_MAX; timestamp = *reinterpret_cast<uint64_t*>(recordBytes + 22);
checksum = *reinterpret_cast<uint16_t*>(recordBytes + 30); checksum = *reinterpret_cast<uint16_t*>(recordBytes + 30);
doChecksum(recordBytes); doChecksum(recordBytes);
} }
+1 -1
View File
@@ -8,7 +8,7 @@ VSA08::VSA08(uint8_t* const recordBytes)
setType(VSA::Type::AA08); setType(VSA::Type::AA08);
troubleSramCount.insert(troubleSramCount.end(), recordBytes + 2, recordBytes + 6); troubleSramCount.insert(troubleSramCount.end(), recordBytes + 2, recordBytes + 6);
troubleSectors.insert(troubleSectors.end(), reinterpret_cast<uint32_t*>(recordBytes + 6), reinterpret_cast<uint32_t*>(recordBytes + 22)); troubleSectors.insert(troubleSectors.end(), reinterpret_cast<uint32_t*>(recordBytes + 6), reinterpret_cast<uint32_t*>(recordBytes + 22));
timestamp = *reinterpret_cast<uint64_t*>(recordBytes + 22) & UINT63_MAX; timestamp = *reinterpret_cast<uint64_t*>(recordBytes + 22);
checksum = *reinterpret_cast<uint16_t*>(recordBytes + 30); checksum = *reinterpret_cast<uint16_t*>(recordBytes + 30);
doChecksum(recordBytes); doChecksum(recordBytes);
} }
+1 -1
View File
@@ -16,7 +16,7 @@ VSA09::VSA09(uint8_t* const recordBytes)
reserved0.insert(reserved0.end(), recordBytes + 12, recordBytes + 18); reserved0.insert(reserved0.end(), recordBytes + 12, recordBytes + 18);
hardwareID = static_cast<HardwareID>(recordBytes[18]); hardwareID = static_cast<HardwareID>(recordBytes[18]);
reserved1.insert(reserved1.end(), recordBytes + 19, recordBytes + 22); reserved1.insert(reserved1.end(), recordBytes + 19, recordBytes + 22);
timestamp = *reinterpret_cast<uint64_t*>(recordBytes + 22) & UINT63_MAX; timestamp = *reinterpret_cast<uint64_t*>(recordBytes + 22);
checksum = *reinterpret_cast<uint16_t*>(recordBytes + 30); checksum = *reinterpret_cast<uint16_t*>(recordBytes + 30);
doChecksum(recordBytes); doChecksum(recordBytes);
} }
+3 -3
View File
@@ -11,7 +11,7 @@ VSA0B::VSA0B(uint8_t* const recordBytes)
{ {
setType(VSA::Type::AA0B); setType(VSA::Type::AA0B);
captureBitfield = reinterpret_cast<uint16_t*>(recordBytes)[1]; captureBitfield = reinterpret_cast<uint16_t*>(recordBytes)[1];
timestamp = *reinterpret_cast<uint64_t*>(recordBytes + 20) & UINT63_MAX; timestamp = *reinterpret_cast<uint64_t*>(recordBytes + 20);
reserved = recordBytes[28]; reserved = recordBytes[28];
checksum = reinterpret_cast<uint16_t*>(recordBytes)[15]; checksum = reinterpret_cast<uint16_t*>(recordBytes)[15];
doChecksum(recordBytes); doChecksum(recordBytes);
@@ -30,8 +30,8 @@ void VSA0B::doChecksum(uint8_t* recordBytes)
bool VSA0B::filter(const std::shared_ptr<VSAMessageReadFilter> filter) bool VSA0B::filter(const std::shared_ptr<VSAMessageReadFilter> filter)
{ {
if((filter->captureBitfield != captureBitfield && filter->captureBitfield != UINT16_MAX) || if((filter->captureBitfield != captureBitfield && filter->captureBitfield != UINT16_MAX) ||
getICSTimestampFromTimepoint(filter->readRange.first) > timestamp || getICSTimestampFromTimepoint(filter->readRange.first) > getTimestamp() ||
getICSTimestampFromTimepoint(filter->readRange.second) < timestamp) { getICSTimestampFromTimepoint(filter->readRange.second) < getTimestamp()) {
return false; return false;
} }
return true; return true;
+1 -1
View File
@@ -10,7 +10,7 @@ VSA0C::VSA0C(uint8_t* const recordBytes)
audioPreamble = recordBytes[4]; audioPreamble = recordBytes[4];
audioHeader = recordBytes[5]; audioHeader = recordBytes[5];
pcmData.insert(pcmData.end(), recordBytes + 6, recordBytes + 20); pcmData.insert(pcmData.end(), recordBytes + 6, recordBytes + 20);
timestamp = *reinterpret_cast<uint64_t*>(recordBytes + 20) & UINT63_MAX; timestamp = *reinterpret_cast<uint64_t*>(recordBytes + 20);
vNetBitfield = *reinterpret_cast<VSA0C::VNet*>(recordBytes + 28); vNetBitfield = *reinterpret_cast<VSA0C::VNet*>(recordBytes + 28);
checksum = *reinterpret_cast<uint16_t*>(recordBytes + 30); checksum = *reinterpret_cast<uint16_t*>(recordBytes + 30);
doChecksum(recordBytes); doChecksum(recordBytes);
+2 -2
View File
@@ -76,8 +76,8 @@ void VSA0DFirst::reorderPayload(std::vector<uint8_t>& secondPayload)
bool VSA0DFirst::filter(const std::shared_ptr<VSAMessageReadFilter> filter) bool VSA0DFirst::filter(const std::shared_ptr<VSAMessageReadFilter> filter)
{ {
if((filter->captureBitfield != captureBitfield && filter->captureBitfield != UINT16_MAX) || if((filter->captureBitfield != captureBitfield && filter->captureBitfield != UINT16_MAX) ||
getICSTimestampFromTimepoint(filter->readRange.first) > timestamp || getICSTimestampFromTimepoint(filter->readRange.first) > getTimestamp() ||
getICSTimestampFromTimepoint(filter->readRange.second) < timestamp) { getICSTimestampFromTimepoint(filter->readRange.second) < getTimestamp()) {
return false; return false;
} }
return true; return true;
+2 -2
View File
@@ -66,8 +66,8 @@ void VSA0EFirst::reservePacketData(std::shared_ptr<Packet>& packet) const
bool VSA0EFirst::filter(const std::shared_ptr<VSAMessageReadFilter> filter) bool VSA0EFirst::filter(const std::shared_ptr<VSAMessageReadFilter> filter)
{ {
if((filter->captureBitfield != captureBitfield && filter->captureBitfield != UINT16_MAX) || if((filter->captureBitfield != captureBitfield && filter->captureBitfield != UINT16_MAX) ||
getICSTimestampFromTimepoint(filter->readRange.first) > timestamp || getICSTimestampFromTimepoint(filter->readRange.first) > getTimestamp() ||
getICSTimestampFromTimepoint(filter->readRange.second) < timestamp) { getICSTimestampFromTimepoint(filter->readRange.second) < getTimestamp()) {
return false; return false;
} }
return true; return true;
+2 -2
View File
@@ -78,8 +78,8 @@ void VSA0FFirst::reservePacketData(std::shared_ptr<Packet>& packet) const
bool VSA0FFirst::filter(const std::shared_ptr<VSAMessageReadFilter> filter) bool VSA0FFirst::filter(const std::shared_ptr<VSAMessageReadFilter> filter)
{ {
if(filter->captureBitfield != captureBitfield || if(filter->captureBitfield != captureBitfield ||
getICSTimestampFromTimepoint(filter->readRange.first) > timestamp || getICSTimestampFromTimepoint(filter->readRange.first) > getTimestamp() ||
getICSTimestampFromTimepoint(filter->readRange.second) < timestamp) { getICSTimestampFromTimepoint(filter->readRange.second) < getTimestamp()) {
return false; return false;
} }
return true; return true;
+1 -1
View File
@@ -16,7 +16,7 @@ VSA6A::VSA6A(uint8_t* const recordBytes)
sequenceNum = *reinterpret_cast<uint32_t*>(recordBytes + 34); sequenceNum = *reinterpret_cast<uint32_t*>(recordBytes + 34);
totalSectors = *reinterpret_cast<uint32_t*>(recordBytes + 38); totalSectors = *reinterpret_cast<uint32_t*>(recordBytes + 38);
reserved = *reinterpret_cast<uint32_t*>(recordBytes + 42); reserved = *reinterpret_cast<uint32_t*>(recordBytes + 42);
timestamp = *reinterpret_cast<uint64_t*>(recordBytes + 46) & UINT63_MAX; timestamp = *reinterpret_cast<uint64_t*>(recordBytes + 46);
timestampSum = *reinterpret_cast<uint16_t*>(recordBytes + 54); timestampSum = *reinterpret_cast<uint16_t*>(recordBytes + 54);
data.insert(data.end(), recordBytes + 56, recordBytes + 508); data.insert(data.end(), recordBytes + 56, recordBytes + 508);
checksum = *reinterpret_cast<uint32_t*>(recordBytes + 508); checksum = *reinterpret_cast<uint32_t*>(recordBytes + 508);
-1
View File
@@ -430,7 +430,6 @@ bool VSAParser::extractMessagePackets(std::vector<std::shared_ptr<Packet>>& pack
extendedMessageRecord->appendPacket(packet); extendedMessageRecord->appendPacket(packet);
if(extendedMessageRecord->getRecordCount() == static_cast<uint32_t>(extendedMessageRecord->getIndex() + 1)) { // Last record in sequence if(extendedMessageRecord->getRecordCount() == static_cast<uint32_t>(extendedMessageRecord->getIndex() + 1)) { // Last record in sequence
if(!settings.messageFilter || extendedMessageRecord->filter(settings.messageFilter)) { if(!settings.messageFilter || extendedMessageRecord->filter(settings.messageFilter)) {
VSAExtendedMessage::truncatePacket(packet);
packets.push_back(packet); packets.push_back(packet);
} }
activeExtendedMessage = false; activeExtendedMessage = false;
+56
View File
@@ -0,0 +1,56 @@
===================
CAN Getting Started
===================
Prerequisites
=============
- Python 3.8 or higher
- icsneopy library installed
- CAN hardware device connected
:download:`Download complete example <../../examples/python/can/can_complete_example.py>`
Basic Setup
===========
1. Import the library and discover devices:
.. literalinclude:: ../../examples/python/can/can_complete_example.py
:language: python
:lines: 11-19
2. Configure and open the device:
.. literalinclude:: ../../examples/python/can/can_complete_example.py
:language: python
:lines: 22-37
Transmitting CAN Frames
========================
.. literalinclude:: ../../examples/python/can/can_complete_example.py
:language: python
:lines: 40-53
Receiving CAN Frames
=====================
.. literalinclude:: ../../examples/python/can/can_complete_example.py
:language: python
:lines: 56-72
Cleanup and Resource Management
===============================
.. literalinclude:: ../../examples/python/can/can_complete_example.py
:language: python
:lines: 75-79
Complete Example with Error Handling
====================================
.. literalinclude:: ../../examples/python/can/can_complete_example.py
:language: python
:lines: 82-125
@@ -0,0 +1,70 @@
=========================
Ethernet Getting Started
=========================
This guide provides basic instructions for working with Ethernet devices using the icsneopy library.
Prerequisites
=============
- Python 3.8 or higher
- icsneopy library installed
- Intrepid Control Systems Device
:download:`Download complete example <../../examples/python/ethernet/ethernet_complete_example.py>`
Opening the Device
==================
To begin working with an Ethernet device, you must first discover, open, and bring it online:
.. literalinclude:: ../../examples/python/ethernet/ethernet_complete_example.py
:language: python
:lines: 11-37
Transmitting Ethernet Frames
=============================
Transmit Ethernet frames using the EthernetMessage class:
.. literalinclude:: ../../examples/python/ethernet/ethernet_complete_example.py
:language: python
:lines: 61-78
Monitoring Ethernet Status
==========================
Monitor Ethernet link status changes using message callbacks:
.. literalinclude:: ../../examples/python/ethernet/ethernet_complete_example.py
:language: python
:lines: 39-40
DoIP Ethernet Activation Control
================================
Diagnostics over Internet Protocol (DoIP) can be controlled through digital I/O pins:
:download:`Download DoIP example <../../examples/python/doip/doip_activation_control.py>`
.. literalinclude:: ../../examples/python/doip/doip_activation_control.py
:language: python
:lines: 28-44
Network Configuration Reference
===============================
Standard Ethernet network identifiers:
- ``icsneopy.Network.NetID.ETHERNET_01`` - Standard Ethernet Port 1
Automotive Ethernet network identifiers:
- ``icsneopy.Network.NetID.AE_01`` - Automotive Ethernet Port 1
Complete Example with Resource Management
=========================================
.. literalinclude:: ../../examples/python/ethernet/ethernet_complete_example.py
:language: python
:lines: 86-127
+57 -86
View File
@@ -3,128 +3,99 @@ Python Examples
=============== ===============
Transmit CAN frames on DW CAN 01 Transmit CAN frames on DW CAN 01
============================ =================================
.. code-block:: python :download:`Download example <../../examples/python/can/can_transmit_basic.py>`
import icsneopy .. literalinclude:: ../../examples/python/can/can_transmit_basic.py
:language: python
devices: list[icsneopy.Device] = icsneopy.find_all_devices()
# grab the first/only device found
device: icsneopy.Device = devices[0]
message = icsneopy.CANMessage()
message.network = icsneopy.Network(icsneopy.Network.NetID.DWCAN_01)
message.arbid = 0x56
message.data = (0x11, 0x22, 0x33)
device.open()
device.go_online()
device.transmit(message)
Receive CAN frames on DW CAN 01 Receive CAN frames on DW CAN 01
=========================== ================================
.. code-block:: python :download:`Download example <../../examples/python/can/can_receive_basic.py>`
import icsneopy .. literalinclude:: ../../examples/python/can/can_receive_basic.py
import time :language: python
devices: list[icsneopy.Device] = icsneopy.find_all_devices() Complete CAN Example
====================
# grab the first/only device found :download:`Download example <../../examples/python/can/can_complete_example.py>`
device: icsneopy.Device = devices[0]
def on_message(message: icsneopy.CANMessage): .. literalinclude:: ../../examples/python/can/can_complete_example.py
print(message.arbid, message.data) :language: python
message_filter = icsneopy.MessageFilter(icsneopy.Network.NetID.DWCAN_01)
callback = icsneopy.MessageCallback(on_message, message_filter)
device.add_message_callback(callback)
device.open() LiveData Subscription and Monitoring
device.go_online() =====================================
# rx for 10s :download:`Download example <../../examples/python/livedata/livedata_example.py>`
time.sleep(10)
.. literalinclude:: ../../examples/python/livedata/livedata_example.py
:language: python
Transmit Ethernet frames on Ethernet 01
========================================
:download:`Download example <../../examples/python/ethernet/ethernet_transmit_basic.py>`
.. literalinclude:: ../../examples/python/ethernet/ethernet_transmit_basic.py
:language: python
Monitor Ethernet Status Monitor Ethernet Status
======================= =======================
.. code-block:: python :download:`Download example <../../examples/python/ethernet/ethernet_monitor_status.py>`
import icsneopy .. literalinclude:: ../../examples/python/ethernet/ethernet_monitor_status.py
import time :language: python
def main(): TC10 Power Management
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()
TC10
====
:download:`Download example <../../examples/python/tc10/tc10.py>` :download:`Download example <../../examples/python/tc10/tc10.py>`
.. literalinclude:: ../../examples/python/tc10/tc10.py .. literalinclude:: ../../examples/python/tc10/tc10.py
:language: python
DoIP Ethernet Activation DoIP Ethernet Activation
======================== ========================
.. code-block:: python :download:`Download example <../../examples/python/doip/doip_activation_control.py>`
import icsneopy .. literalinclude:: ../../examples/python/doip/doip_activation_control.py
import time :language: python
devs = icsneopy.find_all_devices() Complete Ethernet Example
=========================
dev = devs[0] :download:`Download example <../../examples/python/ethernet/ethernet_complete_example.py>`
dev.open() .. literalinclude:: ../../examples/python/ethernet/ethernet_complete_example.py
:language: python
# the device must be online for digital I/O Device Firmware/Chip Versions
dev.go_online() =============================
print(f"initial state: {dev.get_digital_io(icsneopy.IO.EthernetActivation, 1)}") :download:`Download example <../../examples/python/device/chip_versions.py>`
dev.set_digital_io(icsneopy.IO.EthernetActivation, 1, True) .. literalinclude:: ../../examples/python/device/chip_versions.py
:language: python
print(f"after setting to true: {dev.get_digital_io(icsneopy.IO.EthernetActivation, 1)}") SPI Example for 10BASE-T1S
=============================
# allow for observing the change :download:`Download example <../../examples/python/spi/spi_example.py>`
time.sleep(2)
dev.set_digital_io(icsneopy.IO.EthernetActivation, 1, False) .. literalinclude:: ../../examples/python/spi/spi_example.py
:language: python
print(f"after setting to false: {dev.get_digital_io(icsneopy.IO.EthernetActivation, 1)}") Analog Output Control
=====================
# allow for observing the change :download:`Download example <../../examples/python/analog_out/analog_out_basic.py>`
time.sleep(2)
.. literalinclude:: ../../examples/python/analog_out/analog_out_basic.py
:language: python
+191
View File
@@ -0,0 +1,191 @@
=======================
FlexRay Getting Started
=======================
Prerequisites
=============
- icsneopy library installed
- FlexRay hardware device connected (e.g., Fire3 Flexray)
- Proper FlexRay bus termination (100Ω on each channel end)
Physical Hardware Setup for Two-Node Testing
---------------------------------------------
For testing the basic transmit and receive examples with a single device:
- Hardware: Device with dual FlexRay controllers (e.g., neoVI FIRE 3 Flexray)
- Connection: FLEXRAY_01 Channel A looped to FLEXRAY_02 Channel A
- Termination: 100Ω termination resistors on both ends of the loopback
- Cable: Use proper FlexRay twisted pair cable (impedance matched)
.. note::
The basic transmit/receive examples are configured for this loopback setup
where both controllers act as coldstart nodes. For use on an existing
FlexRay network, see the passive monitoring configuration notes in the
receive example.
FlexRay Coldstart
-----------------
FlexRay networks require at least one "coldstart node" to initialize the network timing.
The coldstart node is responsible for starting the FlexRay communication cycle.
For a complete standalone coldstart example, see the Additional Examples section below.
Basic Setup
===========
1. Import the library and find FlexRay device:
.. code-block:: python
import icsneopy
devices = icsneopy.find_all_devices()
# Find a device with FlexRay support
device = None
for dev in devices:
if dev.get_extension("FlexRay"):
device = dev
break
if not device:
raise RuntimeError("No FlexRay-capable device found")
2. Configure FlexRay controller:
.. literalinclude:: ../../examples/python/flexray/flexray_transmit_basic.py
:language: python
:lines: 12-111
3. Open device and go online:
.. code-block:: python
if not device.open():
raise RuntimeError("Failed to open device")
if not device.go_online():
raise RuntimeError("Failed to go online")
Transmitting FlexRay Frames
============================
This example demonstrates a coldstart node that initiates a FlexRay network
and transmits simulated sensor data continuously in slot 1.
**Hardware Setup**: FLEXRAY_01 looped to FLEXRAY_02
**Usage**:
1. Start the receive example first
2. Start this transmit example second
3. Network will initialize and frames will be transmitted
.. literalinclude:: ../../examples/python/flexray/flexray_transmit_basic.py
:language: python
:lines: 113-170
Key Configuration Parameters:
- **slotid**: The FlexRay slot ID for transmission (1-2047 for static segment)
- **cycle**: The FlexRay cycle number (0-63)
- **cycle_repetition**: How often the frame repeats (1 = every cycle, 2 = every other cycle)
- **channel**: Transmission channel (A, B, or AB for both)
- **key_slot_id**: Must be unique per node on the network
- **key_slot_used_for_startup**: True for coldstart nodes
- **key_slot_used_for_sync**: True to provide synchronization frames
Receiving FlexRay Frames
=========================
This example demonstrates receiving FlexRay frames on FLEXRAY_02 Channel A.
**Hardware Setup**: FLEXRAY_01 looped to FLEXRAY_02
**Configuration Note**: This example is configured with coldstart capability
for two-node loopback testing. For passive monitoring on an existing FlexRay
network:
1. Set ``key_slot_used_for_startup = False`` in the controller configuration
2. Remove the ``controller.set_allow_coldstart(True)`` call
3. Ensure all cluster parameters match the existing network
4. The node will sync and receive without transmitting
**Usage**:
1. Start this receive example first
2. Start the transmit example second
3. Frames from slot 1 will be displayed with hex and decimal payload views
.. literalinclude:: ../../examples/python/flexray/flexray_receive_basic.py
:language: python
:lines: 103-170
FlexRay Coldstart Configuration
================================
To use the Coldstart example, ensure the following:
Set the Flexray network in neoVI Explorer to Coldstart.
No other nodes should be present on the network during testing.
Nothing connected to Fire3 FlexRay bus.
Critical Coldstart Settings
----------------------------
.. literalinclude:: ../../examples/python/flexray/flexray_coldstart.py
:language: python
:lines: 40-48
Configuration Example:
.. literalinclude:: ../../examples/python/flexray/flexray_coldstart.py
:language: python
:lines: 20-64
Setting Coldstart on Controller:
.. code-block:: python
controller.set_allow_coldstart(True)
controller.set_start_when_going_online(True)
Cleanup and Resource Management
================================
Always close the device when finished:
.. code-block:: python
try:
# Your FlexRay operations here
pass
finally:
device.close()
See the basic transmit and receive examples for complete implementations.
Additional Examples
===================
Transmit Basic
--------------
Complete working example with coldstart node transmitting simulated sensor data.
All example files are available for download:
**Transmit Basic** - Coldstart node transmitting simulated sensor data
:download:`flexray_transmit_basic.py <../../examples/python/flexray/flexray_transmit_basic.py>`
**Receive Basic** - Receiving and displaying FlexRay frames with formatted output
:download:`flexray_receive_basic.py <../../examples/python/flexray/flexray_receive_basic.py>`
**Coldstart** - Standalone coldstart example demonstrating network initialization
:download:`flexray_coldstart.py <../../examples/python/flexray/flexray_coldstart.py>`
+3
View File
@@ -5,6 +5,9 @@ icsneopy
.. toctree:: .. toctree::
:maxdepth: 2 :maxdepth: 2
can_getting_started
ethernet_getting_started
flexray_getting_started
examples examples
api api
radepsilon radepsilon
+27
View File
@@ -10,6 +10,13 @@ option(LIBICSNEO_BUILD_CPP_COREMINI_EXAMPLE "Build the Coremini example." ON)
option(LIBICSNEO_BUILD_CPP_MDIO_EXAMPLE "Build the MDIO example." ON) option(LIBICSNEO_BUILD_CPP_MDIO_EXAMPLE "Build the MDIO example." ON)
option(LIBICSNEO_BUILD_CPP_VSA_EXAMPLE "Build the VSA example." ON) option(LIBICSNEO_BUILD_CPP_VSA_EXAMPLE "Build the VSA example." ON)
option(LIBICSNEO_BUILD_CPP_APP_ERROR_EXAMPLE "Build the app error example." ON) option(LIBICSNEO_BUILD_CPP_APP_ERROR_EXAMPLE "Build the app error example." ON)
option(LIBICSNEO_BUILD_CPP_APP_ERROR_EXAMPLE "Build the macsec example" ON)
option(LIBICSNEO_BUILD_CPP_FLEXRAY_EXAMPLE "Build the FlexRay example." ON)
option(LIBICSNEO_BUILD_CPP_SPI_EXAMPLE "Build the SPI example." ON)
option(LIBICSNEO_BUILD_CPP_MUTEX_EXAMPLE "Build the NetworkMutex example." ON)
option(LIBICSNEO_BUILD_CPP_ANALOG_OUT_EXAMPLE "Build the analog output example." ON)
add_compile_options(${LIBICSNEO_COMPILER_WARNINGS})
if(LIBICSNEO_BUILD_C_INTERACTIVE_EXAMPLE) if(LIBICSNEO_BUILD_C_INTERACTIVE_EXAMPLE)
add_subdirectory(c/interactive) add_subdirectory(c/interactive)
@@ -58,3 +65,23 @@ endif()
if(LIBICSNEO_BUILD_CPP_APP_ERROR_EXAMPLE) if(LIBICSNEO_BUILD_CPP_APP_ERROR_EXAMPLE)
add_subdirectory(cpp/apperror) add_subdirectory(cpp/apperror)
endif() endif()
if(LIBICSNEO_BUILD_CPP_APP_ERROR_EXAMPLE)
add_subdirectory(cpp/macsec)
endif()
if(LIBICSNEO_BUILD_CPP_FLEXRAY_EXAMPLE)
add_subdirectory(cpp/flexray)
endif()
if(LIBICSNEO_BUILD_CPP_SPI_EXAMPLE)
add_subdirectory(cpp/spi)
endif()
if(LIBICSNEO_BUILD_CPP_MUTEX_EXAMPLE)
add_subdirectory(cpp/mutex)
endif()
if(LIBICSNEO_BUILD_CPP_ANALOG_OUT_EXAMPLE)
add_subdirectory(cpp/analog_out)
endif()
+2
View File
@@ -0,0 +1,2 @@
add_executable(libicsneocpp-analog-out src/analog_out.cpp)
target_link_libraries(libicsneocpp-analog-out icsneocpp)
+157
View File
@@ -0,0 +1,157 @@
/**
* libicsneo Analog Output example
*
* Demonstrates how to configure and control analog outputs on supported devices
*
* Usage: libicsneo-analog-out <pin> <voltage> [deviceSerial] [--yes]
*
* Arguments:
* pin: Pin number (1-3 for RAD Galaxy)
* voltage: Voltage level (0-5)
* deviceSerial: 6 character string for device serial (optional)
* --yes: Skip confirmation prompt
*/
#include <iostream>
#include <thread>
#include <chrono>
#include <string_view>
#include <cstdlib>
#include "icsneo/icsneocpp.h"
static const std::string usage = "Usage: libicsneo-analog-out <pin> <voltage> [deviceSerial] [--yes]\n\n"
"Arguments:\n"
"pin: Pin number (1-3 for RAD Galaxy)\n"
"voltage: Voltage level (0-5)\n"
"deviceSerial: 6 character string for device serial (optional)\n"
"--yes: Skip confirmation prompt\n";
int main(int argc, const char** argv) {
std::vector<std::string_view> args(argv, argv + argc);
// Parse arguments
if(args.size() < 3) {
std::cerr << "Error: Missing required arguments\n" << std::endl;
std::cerr << usage;
return -1;
}
char* endPtr;
long pinNum = std::strtol(args[1].data(), &endPtr, 10);
if(endPtr != args[1].data() + args[1].size() || pinNum < 1 || pinNum > 3) {
std::cerr << "Error: Invalid pin number (must be 1-3)" << std::endl;
return -1;
}
long voltageLevel = std::strtol(args[2].data(), &endPtr, 10);
if(endPtr != args[2].data() + args[2].size() || voltageLevel < 0 || voltageLevel > 5) {
std::cerr << "Error: Invalid voltage level (must be 0-5)" << std::endl;
return -1;
}
icsneo::MiscIOAnalogVoltage voltage = static_cast<icsneo::MiscIOAnalogVoltage>(voltageLevel);
uint8_t pin = static_cast<uint8_t>(pinNum);
// Check for optional arguments
bool skipConfirm = false;
std::string_view serial;
for(size_t i = 3; i < args.size(); i++) {
if(args[i] == "--yes") {
skipConfirm = true;
} else if(serial.empty() && args[i].size() == 6) {
serial = args[i];
}
}
// Confirmation prompt
if(!skipConfirm) {
std::cout << "WARNING: This will set analog output pin " << static_cast<int>(pin)
<< " to " << voltageLevel << "V" << std::endl;
std::cout << "Make sure nothing sensitive is connected to this pin." << std::endl;
std::cout << "Continue? (yes/no): ";
std::string response;
std::getline(std::cin, response);
if(response != "yes") {
std::cout << "Aborted." << std::endl;
return 0;
}
}
std::shared_ptr<icsneo::Device> device = nullptr;
if(!serial.empty()) {
// Find device by serial
auto devices = icsneo::FindAllDevices();
for(auto& dev : devices) {
if(dev->getSerial() == serial) {
device = dev;
break;
}
}
if(!device) {
std::cerr << "Device with serial " << serial << " not found" << std::endl;
return -1;
}
} else {
// Use first available device
auto devices = icsneo::FindAllDevices();
if(devices.empty()) {
std::cerr << "No devices found" << std::endl;
return -1;
}
device = devices[0];
}
std::cout << "Using device: " << device->describe() << std::endl;
if(!device->open()) {
std::cerr << "Failed to open device" << std::endl;
return -1;
}
auto settings = device->settings;
if(!settings) {
std::cerr << "Device settings not available" << std::endl;
device->close();
return -1;
}
std::cout << "Refreshing device settings..." << std::endl;
if(!settings->refresh()) {
std::cerr << "Failed to refresh settings" << std::endl;
device->close();
return -1;
}
// Enable analog output on specified pin
std::cout << "Enabling analog output on pin " << static_cast<int>(pin) << "..." << std::endl;
if(!settings->setMiscIOAnalogOutputEnabled(pin, true)) {
std::cerr << "Failed to enable analog output on pin " << static_cast<int>(pin) << std::endl;
device->close();
return -1;
}
// Set pin to specified voltage
std::cout << "Setting pin " << static_cast<int>(pin) << " to " << voltageLevel << "V..." << std::endl;
if(!settings->setMiscIOAnalogOutput(pin, voltage)) {
std::cerr << "Failed to set voltage on pin " << static_cast<int>(pin) << std::endl;
device->close();
return -1;
}
// Apply settings
std::cout << "Applying settings..." << std::endl;
if(!settings->apply()) {
std::cerr << "Failed to apply settings" << std::endl;
device->close();
return -1;
}
std::cout << "Analog output configured successfully!" << std::endl;
std::cout << "Pin " << static_cast<int>(pin) << ": Enabled at " << voltageLevel << "V" << std::endl;
device->close();
return 0;
}
-7
View File
@@ -44,12 +44,6 @@ int main(int argc, char** argv) {
return EXIT_FAILURE; return EXIT_FAILURE;
} }
if(!device->goOnline()) {
std::cout << "Failed to go online." << std::endl;
std::cout << icsneo::GetLastError() << std::endl;
return EXIT_FAILURE;
}
std::string memTypeString = arguments[3]; std::string memTypeString = arguments[3];
icsneo::Disk::MemoryType type; icsneo::Disk::MemoryType type;
@@ -75,7 +69,6 @@ int main(int argc, char** argv) {
std::cout << icsneo::GetLastError() << std::endl; std::cout << icsneo::GetLastError() << std::endl;
} }
device->goOffline();
device->close(); device->close();
return 0; return 0;
} }
+2
View File
@@ -0,0 +1,2 @@
add_executable(libicsneocpp-flexray-example src/FlexRayExample.cpp)
target_link_libraries(libicsneocpp-flexray-example icsneocpp)
+204
View File
@@ -0,0 +1,204 @@
#include <iostream>
#include <random>
#include "icsneo/icsneocpp.h"
#include "icsneo/device/extensions/flexray/cluster.h"
/* Modifiable Configuration Variables*/
static size_t NumMessages = 300;
static size_t FramePayloadSize = 134;
static uint16_t SlotOne = 1;
static uint16_t SlotTwo = 3;
static bool SuppressRxTxDebugMessages = true;
static const icsneo::FlexRay::Controller::Configuration DefaultControllerConfig {
160, // uint16_t AcceptStartupRangeMicroticks INIT(0); // pdAcceptedStartupRange
true, // bool AllowHaltDueToClock INIT(false); // pAllowHaltDueToClock
15, // uint8_t AllowPassiveToActiveCyclePairs INIT(0); // pAllowPassiveToActive
2, // uint8_t ClusterDriftDamping INIT(0); // pClusterDriftDamping
true, // bool ChannelA INIT(false); // pChannels
true, // bool ChannelB INIT(false); // pChannels
56, // uint8_t DecodingCorrectionMicroticks INIT(0); // pDecodingCorrection
28, // uint8_t DelayCompensationAMicroticks INIT(0); // pDelayCompensation[A]
28, // uint8_t DelayCompensationBMicroticks INIT(0); // pDelayCompensation[B]
0, // uint8_t ExternOffsetCorrectionControl INIT(0); // pExternOffsetControl
0, // uint8_t ExternRateCorrectionControl INIT(0); // pExternRateControl
0, // uint8_t ExternOffsetCorrectionMicroticks INIT(0); // pExternOffsetCorrection
0, // uint8_t ExternRateCorrectionMicroticks INIT(0); // pExternRateCorrection
0, // uint16_t KeySlotID INIT(0);
false, // bool KeySlotOnlyEnabled INIT(false); // pSingleSlotEnabled (TSM)
true, // bool KeySlotUsedForStartup INIT(false); // pKeySlotUsedForStartup (TXST)
true, // bool KeySlotUsedForSync INIT(false); // pKeySlotUsedForSync (TXSY)
226, // uint16_t LatestTxMinislot INIT(0); // pLatestTx
401202, // uint32_t ListenTimeout INIT(0); // pdListenTimeout
7, // uint8_t MacroInitialOffsetA INIT(0); // pMacroInitialOffset[A], Valid 2..72
7, // uint8_t MacroInitialOffsetB INIT(0); // pMacroInitialOffset[B], Valid 2..72
36, // uint8_t MicroInitialOffsetA INIT(0); // pMicroInitialOffset[A], Valid 0..240
36, // uint8_t MicroInitialOffsetB INIT(0); // pMicroInitialOffset[B], Valid 0..240
200000, // uint32_t MicroPerCycle INIT(0); // pMicroPerCycle
false, // bool MTSOnA INIT(false);
false, // bool MTSOnB INIT(false);
189, // uint16_t OffsetCorrectionOutMicroticks INIT(0); // pOffsetCorrectionOut
601, // uint16_t RateCorrectionOutMicroticks INIT(0); // pdMaxDrift and pRateCorrectionOut
0, // uint16_t SecondKeySlotID INIT(0);
false, // bool TwoKeySlotMode INIT(false);
55, // uint8_t WakeupPattern INIT(0);
false, // bool WakeupOnChannelB INIT(false); // pWakeupChannel
};
namespace Cluster = icsneo::FlexRay::Cluster;
static const Cluster::Configuration DefaultClusterConfig {
Cluster::SpeedType::FLEXRAY_BAUDRATE_10M, // neoflexray_speed_t Speed INIT(FLEXRAY_BAUDRATE_10M /* = 0 */); // gdSampleClockPeriod, pSamplesPerMicrotick, Baud Rate Prescaler
Cluster::SPPType::FLEXRAY_SPP_5, // neoflexray_spp_t StrobePointPosition INIT(FLEXRAY_SPP_5 /* = 0 */);
4, // uint8_t ActionPointOffset INIT(0); // gdActionPointOffset
64, // uint8_t CASRxLowMax INIT(0); // gdCASRxLowMax
8, // uint8_t ColdStartAttempts INIT(0); // gColdStartAttempts
5000, // uint16_t CycleDurationMicroSec INIT(0); // gdCycle
1, // uint8_t DynamicSlotIdlePhaseMinislots INIT(0); // gdDynamicSlotIdlePhase, In Minislot increments [0..2]
4, // uint8_t ListenNoiseMacroticks INIT(0); // gListenNoise
5000, // uint16_t MacroticksPerCycle INIT(0); // gMacroPerCycle
1, // uint8_t MacrotickDurationMicroSec INIT(0); // gdMacroTick
2, // uint8_t MaxWithoutClockCorrectionFatal INIT(0); // gMaxWithoutClockCorrectionFatal
2, // uint8_t MaxWithoutClockCorrectionPassive INIT(0); // gMaxWithoutClockCorrectionPassive
4, // uint8_t MinislotActionPointOffsetMacroticks INIT(0); // gdMinislotActionPointOffset
10, // uint32_t MinislotDurationMacroticks INIT(0); // gdMinislot
40, // uint32_t NetworkIdleTimeMacroticks INIT(0); // gdNIT
1, // uint8_t NetworkManagementVectorLengthBytes INIT(0); // gNetworkManagementVectorLength
0, // uint32_t NumberOfMinislots INIT(0); // gNumberOfMinislots
32, // uint16_t NumberOfStaticSlots INIT(0); // gdNumberOfStaticSlots
4991, // uint32_t OffsetCorrectionStartMacroticks INIT(0); // gOffsetCorrectionStart
67, // uint8_t PayloadLengthOfStaticSlotInWords INIT(0); // gPayloadLengthStatic
155, // uint16_t StaticSlotMacroticks INIT(0); // gdStaticSlot
0, // uint32_t SymbolWindowMacroticks INIT(0); // gdSymbolWindow
0, // uint32_t SymbolWindowActionPointOffsetMacroticks INIT(0);
15, // uint16_t SyncFrameIDCountMax INIT(0); // gSyncNodeMax
11, // uint8_t TransmissionStartSequenceDurationBits INIT(0); // gdTSSTransmitter
40, // uint8_t WakeupRxIdleBits INIT(0); // gdWakeupSymbolRxIdle
40, // uint8_t WakeupRxLowBits INIT(0); // gdWakeupSymbolRxLow
301, // uint16_t WakeupRxWindowBits INIT(0); // gdWakeupSymbolRxWindow
60, // uint8_t WakeupTxActiveBits INIT(0); // gdWakeupSymbolTxLow (active = low here)
180, // uint8_t WakeupTxIdleBits INIT(0); // gdWakeupSymbolTxIdle
};
static std::condition_variable cv;
static std::mutex msgRcvdMutex;
void configureFlexRayDevice(std::shared_ptr<icsneo::Device> device) {
auto controllers = device->getFlexRayControllers();
for (uint16_t i = 0; i < controllers.size(); i++) {
auto controller = controllers[i];
icsneo::FlexRay::Cluster::Configuration clusterConfig = DefaultClusterConfig;
icsneo::FlexRay::Controller::Configuration controllerConfig = DefaultControllerConfig;
controller->setAllowColdstart(true);
controllerConfig.KeySlotID = (i == 0) ? SlotOne : SlotTwo;
controller->setConfiguration(clusterConfig, controllerConfig);
controller->setStartWhenGoingOnline(true);
}
}
std::vector<std::shared_ptr<icsneo::FlexRayMessage>> makeDummyFlexRayMessages(size_t msgCount, size_t msgLen) {
std::vector<std::shared_ptr<icsneo::FlexRayMessage>> messages;
messages.reserve(msgCount);
std::random_device rd;
std::mt19937 engine(rd());
std::uniform_int_distribution<unsigned short> dist(0, 255);
for (size_t i = 0; i < msgCount; i++) {
auto msg = std::make_shared<icsneo::FlexRayMessage>();
msg->network = icsneo::Network::NetID::FLEXRAY_01;
msg->cycleRepetition = 1;
msg->channel = icsneo::FlexRay::Channel::AB;
msg->data.reserve(msgLen);
for (size_t j = 0; j < msgLen; j++) {
msg->data.push_back(static_cast<uint8_t>(dist(engine)));
}
msg->slotid = (i % 2 == 0) ? SlotOne : SlotTwo;
messages.push_back(msg);
}
return messages;
}
int main() {
auto devices = icsneo::FindAllDevices();
std::shared_ptr<icsneo::Device> flexrayDevice = nullptr;
for (auto&& device : devices) {
if (device->getExtension("FlexRay")) {
flexrayDevice = device;
}
}
if (flexrayDevice) {
std::cout << "Found device " << flexrayDevice->getProductName() << " " << flexrayDevice->getSerial() << " which supports FlexRay." << std::endl;
auto&& controllers = flexrayDevice->getFlexRayControllers();
if (controllers.size() > 0) {
std::vector<std::shared_ptr<icsneo::FlexRayMessage>> messages;
size_t currentMessage = 0;
auto filter = std::make_shared<icsneo::MessageFilter>(icsneo::Network::NetID::FLEXRAY_01);
auto rxCallback = [&messages, &currentMessage](std::shared_ptr<icsneo::Message> message) -> void {
std::unique_lock lk(msgRcvdMutex);
auto frmsg = std::static_pointer_cast<icsneo::FlexRayMessage>(message);
if (currentMessage < messages.size() && frmsg->data.size() > 1 && frmsg->data == messages[currentMessage]->data) {
if (!SuppressRxTxDebugMessages) {
std::cout << "Message Number " << currentMessage + 1 << " received." << std::endl;
}
currentMessage++;
lk.unlock();
cv.notify_all();
}
};
auto cb = std::make_shared<icsneo::MessageCallback>(rxCallback, filter);
auto cbId = flexrayDevice->addMessageCallback(cb);
messages = makeDummyFlexRayMessages(NumMessages, FramePayloadSize);
configureFlexRayDevice(flexrayDevice);
if (!flexrayDevice->open()) {
std::cerr << "Device open failed." << std::endl;
return -1;
}
if (!flexrayDevice->goOnline()) {
std::cerr << "Device go online failed." << std::endl;
return -1;
}
std::cout << "Transmitting " << NumMessages << " FlexRay frames." << std::endl;
for (auto msg : messages) {
std::unique_lock lk(msgRcvdMutex);
if (!flexrayDevice->transmit(msg)) {
std::cerr << "Failed to transmit message." << std::endl;
return -1;
} else if (!SuppressRxTxDebugMessages) {
std::cout << "Message Number " << currentMessage + 1 << " transmitted." << std::endl;
}
cv.wait(lk);
lk.unlock();
}
std::cout << "All transmitted frames received." << std::endl;
flexrayDevice->removeMessageCallback(cbId);
}
} else {
std::cerr << "Unable to find a device which supports FlexRay." << std::endl;
return -1;
}
std::cout << "Finished." << std::endl;
return 0;
}

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