├── .clang-format ├── LICENSE.md ├── README.md ├── include ├── pnal.h └── pnet_api.h ├── pnet_options.h.in ├── pnet_version.h.in ├── src ├── common │ ├── pf_alarm.c │ ├── pf_alarm.h │ ├── pf_bg_worker.c │ ├── pf_bg_worker.h │ ├── pf_cpm.c │ ├── pf_cpm.h │ ├── pf_cpm_driver_sw.c │ ├── pf_cpm_driver_sw.h │ ├── pf_dcp.c │ ├── pf_dcp.h │ ├── pf_eth.c │ ├── pf_eth.h │ ├── pf_file.c │ ├── pf_file.h │ ├── pf_lldp.c │ ├── pf_lldp.h │ ├── pf_ppm.c │ ├── pf_ppm.h │ ├── pf_ppm_driver_sw.c │ ├── pf_ppm_driver_sw.h │ ├── pf_ptcp.c │ ├── pf_ptcp.h │ ├── pf_scheduler.c │ ├── pf_scheduler.h │ ├── pf_snmp.c │ ├── pf_snmp.h │ ├── pf_udp.c │ └── pf_udp.h ├── device │ ├── pf_block_reader.c │ ├── pf_block_reader.h │ ├── pf_block_writer.c │ ├── pf_block_writer.h │ ├── pf_cmdev.c │ ├── pf_cmdev.h │ ├── pf_cmdmc.c │ ├── pf_cmdmc.h │ ├── pf_cmina.c │ ├── pf_cmina.h │ ├── pf_cmio.c │ ├── pf_cmio.h │ ├── pf_cmpbe.c │ ├── pf_cmpbe.h │ ├── pf_cmrdr.c │ ├── pf_cmrdr.h │ ├── pf_cmrpc.c │ ├── pf_cmrpc.h │ ├── pf_cmrpc_epm.c │ ├── pf_cmrpc_epm.h │ ├── pf_cmrpc_helpers.c │ ├── pf_cmrpc_helpers.h │ ├── pf_cmrs.c │ ├── pf_cmrs.h │ ├── pf_cmsm.c │ ├── pf_cmsm.h │ ├── pf_cmsu.c │ ├── pf_cmsu.h │ ├── pf_cmwrr.c │ ├── pf_cmwrr.h │ ├── pf_diag.c │ ├── pf_diag.h │ ├── pf_fspm.c │ ├── pf_fspm.h │ ├── pf_pdport.c │ ├── pf_pdport.h │ ├── pf_plugsm.c │ ├── pf_plugsm.h │ ├── pf_port.c │ ├── pf_port.h │ └── pnet_api.c ├── drivers │ └── lan9662 │ │ ├── add_inbound_vcap_rule.sh │ │ ├── add_outbound_vcap_rule.sh │ │ ├── del_vcap_rule.sh │ │ ├── include │ │ ├── driver_config.h │ │ └── pnet_lan9662_api.h │ │ ├── pnet_driver_options.h.in │ │ ├── set_profinet_leds │ │ └── src │ │ ├── pf_cpm_driver_lan9662.c │ │ ├── pf_lan9662_mera.c │ │ ├── pf_lan9662_mera.h │ │ ├── pf_mera_trace.c │ │ ├── pf_mera_trace.h │ │ ├── pf_ppm_driver_lan9662.c │ │ ├── pf_rte_uio.c │ │ ├── pf_rte_uio.h │ │ ├── pf_sram_uio.c │ │ └── pf_sram_uio.h ├── pf_driver.h ├── pf_includes.h └── pf_types.h ├── test ├── mocks.cpp ├── mocks.h ├── pf_test.cpp ├── test_alarm.cpp ├── test_block_reader.cpp ├── test_cmdev.cpp ├── test_cmdmc.cpp ├── test_cmina.cpp ├── test_cmio.cpp ├── test_cmpbe.cpp ├── test_cmrdr.cpp ├── test_cmrpc.cpp ├── test_cmrs.cpp ├── test_cmsm.cpp ├── test_cmsu.cpp ├── test_cmwdr.cpp ├── test_cpm.cpp ├── test_dcp.cpp ├── test_diag.cpp ├── test_eth.cpp ├── test_file.cpp ├── test_fspm.cpp ├── test_lldp.cpp ├── test_pnetapi.cpp ├── test_port.cpp ├── test_ppm.cpp ├── test_ptcp.cpp ├── test_scheduler.cpp ├── test_snmp.cpp ├── utils_for_testing.cpp └── utils_for_testing.h └── tools └── clean_no_alarm.sh /.clang-format: -------------------------------------------------------------------------------- 1 | AlignAfterOpenBracket: AlwaysBreak 2 | AlignConsecutiveAssignments: false 3 | AlignConsecutiveMacros: true 4 | AllowAllArgumentsOnNextLine: false 5 | AllowAllParametersOfDeclarationOnNextLine: false 6 | AllowShortCaseLabelsOnASingleLine: false 7 | AllowShortFunctionsOnASingleLine: None 8 | AllowShortIfStatementsOnASingleLine: Never 9 | BinPackArguments: false 10 | BinPackParameters: false 11 | BreakBeforeBraces: Custom 12 | BraceWrapping: 13 | AfterCaseLabel: true 14 | AfterClass: true 15 | AfterControlStatement: true 16 | AfterEnum: true 17 | AfterFunction: true 18 | AfterNamespace: true 19 | AfterStruct: true 20 | AfterUnion: true 21 | BeforeCatch: true 22 | BeforeElse: true 23 | IndentBraces: false 24 | SplitEmptyFunction: true 25 | SplitEmptyRecord: true 26 | SplitEmptyNamespace: false 27 | AfterExternBlock: false 28 | ColumnLimit: 80 29 | ContinuationIndentWidth: 3 30 | IndentCaseLabels: false 31 | IndentWidth: 3 32 | PenaltyBreakAssignment: 10 33 | PenaltyBreakBeforeFirstCallParameter: 30 34 | PenaltyBreakComment: 10 35 | PenaltyBreakString: 100 36 | PenaltyExcessCharacter: 100 37 | PenaltyReturnTypeOnItsOwnLine: 100000 38 | PointerAlignment: Middle 39 | SortIncludes: false 40 | SpaceBeforeParens: NonEmptyParentheses 41 | UseTab: Never 42 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # License 2 | 3 | This software is dual-licensed. 4 | 5 | ## GPL version 3 6 | 7 | This software is distributed under GPLv3. You are allowed to use this 8 | software for an open-source project with a compatible license. 9 | 10 | Use of IPC interface(s) provided by the project is understood to be 11 | ordinary use, not within the meaning of "covered work" as defined in 12 | the GPLv3 license. 13 | 14 | [GNU GPL license v3](https://www.gnu.org/licenses/gpl-3.0.html) 15 | 16 | ## Commercial license 17 | 18 | This software is also available under a commercial license with 19 | options for support and maintenance. Please contact sales@rt-labs.com 20 | for further details. 21 | 22 | If you intend to use this stack in a commercial product, you likely need to 23 | buy a license. 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # P-Net 2 | 3 | Profinet device stack for embedded systems 4 | 5 | ## Web resources 6 | 7 | - Source repository: [https://github.com/rtlabs-com/p-net](https://github.com/rtlabs-com/p-net) 8 | - Documentation: [https://rt-labs.com/docs/p-net](https://rt-labs.com/docs/p-net) 9 | - Continuous integration: [https://github.com/rtlabs-com/p-net/actions](https://github.com/rtlabs-com/p-net/actions) 10 | - RT-Labs (stack integration, certification services and training): [https://rt-labs.com](https://rt-labs.com) 11 | 12 | [![Build Status](https://github.com/rtlabs-com/p-net/workflows/Build/badge.svg?branch=master)](https://github.com/rtlabs-com/p-net/actions?workflow=Build) 13 | [![CodeQL](https://github.com/rtlabs-com/p-net/workflows/CodeQL/badge.svg?branch=master)](https://github.com/rtlabs-com/p-net/actions?workflow=CodeQL) 14 | 15 | ## Key features 16 | 17 | - Profinet v2.43 18 | - Conformance Class A and B 19 | - Real Time Class 1 20 | - Multiple Ethernet ports 21 | 22 | 23 | - Easy to use 24 | - Extensive documentation and instructions on how to get started. 25 | - Build and run sample application on Raspberry Pi in 30 minutes. 26 | - Portable 27 | - Written in C. 28 | - Linux, RTOS or bare metal. 29 | - Sources for supported port layers provided. 30 | 31 | The RT-Labs Profinet stack p-net is used for Profinet device 32 | implementations. It is easy to use and provides a small footprint. It 33 | is especially well suited for embedded systems where resources are 34 | limited and efficiency is crucial. 35 | The stack is supplied with full sources including porting 36 | layers and a sample application. 37 | 38 | Also C++ (any version) is supported for application development. 39 | 40 | The main requirement on the platform 41 | is that it can send and receive raw Ethernet Layer 2 frames. 42 | 43 | This software is dual-licensed, with GPL version 3 and a commercial license. 44 | If you intend to use this stack in a commercial product, you likely need to 45 | buy a license. See LICENSE.md for more details. 46 | 47 | ## Getting started 48 | 49 | See the tutorial in the documentation: [https://docs.rt-labs.com/p-net/running_sample_app.html](https://docs.rt-labs.com/p-net/running_sample_app.html) 50 | 51 | Note that you need to include submodules when cloning: 52 | 53 | ``` 54 | git clone --recurse-submodules https://github.com/rtlabs-com/p-net.git 55 | ``` 56 | 57 | ## Features 58 | 59 | - Multiple Ethernet ports (for Linux only, so far) 60 | - TCP/IP 61 | - LLDP 62 | - SNMP 63 | - RT (real-time) 64 | - Address resolution 65 | - Parameterization 66 | - Process IO data exchange 67 | - Alarm handling 68 | - Configurable number of modules and sub-modules 69 | - Bare-metal or OS 70 | - Porting layer provided 71 | - Supports I&M0 - I&M4. The I&M data is supported for the device, but not for 72 | individual modules. 73 | - Shared device (connection to multiple controllers) 74 | 75 | ## Limitations 76 | 77 | - This is a device stack, which means that the IO-controller/master/PLC side is 78 | not supported. 79 | - No media redundancy (No MRP support) 80 | - Legacy startup mode is not fully implemented 81 | - No support for RT_CLASS_UDP 82 | - No support for DHCP 83 | - No fast start-up 84 | - No MC multicast device-to-device 85 | - No support for shared inputs 86 | - Supports only full connections, not the limited "DeviceAccess" connection type. 87 | - No iPar (parameter server) support 88 | - No support for time synchronization 89 | - No UDP frames at alarm (just the default alarm mechanism is implemented) 90 | - No ProfiDrive or ProfiSafe profiles. 91 | 92 | ## Requirements 93 | 94 | The platform must be able to send and receive raw Ethernet Layer 2 frames, 95 | and the Ethernet driver must be able to handle full size frames. It 96 | should also avoid copying data, for performance reasons. 97 | 98 | - cmake 3.14 or later 99 | 100 | For Linux: 101 | 102 | - gcc 4.6 or later 103 | - See the "Real-time properties of Linux" page in the documentation on how to 104 | improve Linux timing 105 | 106 | For rt-kernel: 107 | 108 | - Workbench 2020.1 or later 109 | 110 | An example of microcontroller we have been using is the Infineon XMC4800, 111 | which has an ARM Cortex-M4 running at 144 MHz, with 2 MB Flash and 352 kB RAM. 112 | It runs rt-kernel, and we have tested it with 9 Profinet slots each 113 | having 8 digital inputs and 8 digital outputs (one bit each). The values are 114 | sent and received each millisecond (PLC watchdog setting 3 ms). 115 | 116 | ## Dependencies 117 | 118 | Some of the platform-dependent parts are located in the OSAL repository and the 119 | cmake-tools repository. 120 | 121 | - [https://github.com/rtlabs-com/osal](https://github.com/rtlabs-com/osal) 122 | - [https://github.com/rtlabs-com/cmake-tools](https://github.com/rtlabs-com/cmake-tools) 123 | 124 | Those are downloaded automatically during install. 125 | 126 | The p-net stack contains no third party components. Its external dependencies are: 127 | 128 | - C-library 129 | - An operating system (if used) 130 | - For conformance class B you need an SNMP implementation. On Linux is 131 | net-snmp (BSD License) used [http://www.net-snmp.org](http://www.net-snmp.org) 132 | 133 | Tools used for building, testing and documentation (not shipped in the resulting binaries): 134 | 135 | - cmake (BSD 3-clause License) [https://cmake.org](https://cmake.org) 136 | - gtest (BSD-3-Clause License) [https://github.com/google/googletest](https://github.com/google/googletest) 137 | - Sphinx (BSD license) [https://www.sphinx-doc.org](https://www.sphinx-doc.org) 138 | - Doxygen (GPL v2) [https://www.doxygen.nl](https://www.doxygen.nl/index.html) 139 | - clang-format (Apache License 2.0) [https://clang.llvm.org](https://clang.llvm.org/docs/ClangFormat.html) 140 | 141 | ## Contributions 142 | 143 | Contributions are welcome. If you want to contribute you will need to 144 | sign a Contributor License Agreement and send it to us either by 145 | e-mail or by physical mail. More information is available 146 | on [https://rt-labs.com/contribution](https://rt-labs.com/contribution). 147 | -------------------------------------------------------------------------------- /pnet_options.h.in: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * _ _ _ 3 | * _ __ | |_ _ | | __ _ | |__ ___ 4 | * | '__|| __|(_)| | / _` || '_ \ / __| 5 | * | | | |_ _ | || (_| || |_) |\__ \ 6 | * |_| \__|(_)|_| \__,_||_.__/ |___/ 7 | * 8 | * www.rt-labs.com 9 | * Copyright 2018 rt-labs AB, Sweden. 10 | * 11 | * This software is dual-licensed under GPLv3 and a commercial 12 | * license. See the file LICENSE.md distributed with this software for 13 | * full license information. 14 | ********************************************************************/ 15 | 16 | #ifndef PNET_OPTIONS_H 17 | #define PNET_OPTIONS_H 18 | 19 | /** 20 | * # Profinet Stack Options 21 | * 22 | * The defines named `PNET_OPTION_*` may be used to extend or reduce 23 | * the functionality of the stack. Setting these values to 0 excludes 24 | * the specific function and may also reduce the memory usage of the 25 | * Profinet stack. 26 | * 27 | * Note that none of these options are currently supported (even if 28 | * enabled by setting the value to 1), except for parsing the RPC 29 | * Connect request message and generating the connect RPC Connect 30 | * response message. 31 | */ 32 | 33 | #cmakedefine01 PNET_OPTION_FAST_STARTUP 34 | 35 | #cmakedefine01 PNET_OPTION_PARAMETER_SERVER 36 | 37 | #cmakedefine01 PNET_OPTION_IR 38 | 39 | #cmakedefine01 PNET_OPTION_SR 40 | 41 | #cmakedefine01 PNET_OPTION_REDUNDANCY 42 | 43 | #cmakedefine01 PNET_OPTION_AR_VENDOR_BLOCKS 44 | 45 | #cmakedefine01 PNET_OPTION_RS 46 | 47 | #cmakedefine01 PNET_OPTION_MC_CR 48 | 49 | #cmakedefine01 PNET_OPTION_SRL 50 | 51 | #cmakedefine01 PNET_OPTION_SNMP 52 | 53 | #cmakedefine01 PNET_OPTION_DRIVER_ENABLE 54 | 55 | /** 56 | * Disable use of atomic operations (stdatomic.h). 57 | * If the compiler supports it then set this define to 1. 58 | */ 59 | /* TODO: compiler abstraction should be handled by cc.h */ 60 | #cmakedefine01 PNET_USE_ATOMICS 61 | 62 | /** 63 | * # Memory Usage 64 | * 65 | * Memory usage is controlled by the `PNET_MAX_*` defines. Define the 66 | * required number of supported items. 67 | * 68 | * These values directly affect the memory usage of the 69 | * implementation. Sometimes in complicated ways. 70 | * 71 | * Please note that some defines have minimum requirements. 72 | * Only a few of the defines are validated. 73 | */ 74 | 75 | /** Number of connections. Must be > 0. "Automated RT Tester" uses 2 */ 76 | #define PNET_MAX_AR @PNET_MAX_AR@ 77 | 78 | /** Number of Application Processes. Must be > 0. */ 79 | #define PNET_MAX_API @PNET_MAX_API@ 80 | 81 | /** Per AR. 1 input and 1 output. */ 82 | #define PNET_MAX_CR @PNET_MAX_CR@ 83 | 84 | /** Per API. Should be > 1 to allow at least one I/O module. */ 85 | #define PNET_MAX_SLOTS @PNET_MAX_SLOTS@ 86 | 87 | /** Per slot (3 needed for DAP). */ 88 | #define PNET_MAX_SUBSLOTS @PNET_MAX_SUBSLOTS@ 89 | 90 | /** Allowed values are 0 (zero) or 2. */ 91 | #define PNET_MAX_DFP_IOCR @PNET_MAX_DFP_IOCR@ 92 | 93 | /** Max number of physical ports */ 94 | #define PNET_MAX_PHYSICAL_PORTS @PNET_MAX_PHYSICAL_PORTS@ 95 | 96 | #define PNET_MAX_LOG_BOOK_ENTRIES @PNET_MAX_LOG_BOOK_ENTRIES@ 97 | 98 | /** Per AR and queue. One queue for hi and one for lo alarms. */ 99 | #define PNET_MAX_ALARMS @PNET_MAX_ALARMS@ 100 | 101 | /** Max size of alarm payload */ 102 | #define PNET_MAX_ALARM_PAYLOAD_DATA_SIZE @PNET_MAX_ALARM_PAYLOAD_DATA_SIZE@ 103 | 104 | /** Total, per device. Max is 65534 items. */ 105 | #define PNET_MAX_DIAG_ITEMS @PNET_MAX_DIAG_ITEMS@ 106 | 107 | /** Max size of manufacturer specific diagnosis data */ 108 | #define PNET_MAX_DIAG_MANUF_DATA_SIZE @PNET_MAX_DIAG_MANUF_DATA_SIZE@ 109 | 110 | #if PNET_OPTION_MC_CR 111 | 112 | /**< Per AR. */ 113 | #define PNET_MAX_MC_CR @PNET_MAX_MC_CR@ 114 | 115 | #endif /* PNET_OPTION_MC_CR */ 116 | 117 | #if PNET_OPTION_AR_VENDOR_BLOCKS 118 | 119 | /**< Must be > 0 */ 120 | #define PNET_MAX_AR_VENDOR_BLOCKS @PNET_MAX_AR_VENDOR_BLOCKS@ 121 | 122 | #define PNET_MAX_AR_VENDOR_BLOCK_DATA_LENGTH @PNET_MAX_AR_VENDOR_BLOCK_DATA_LENGTH@ 123 | 124 | #endif /* PNET_OPTION_AR_VENDOR_BLOCKS */ 125 | 126 | /** or 512 (bytes) */ 127 | #define PNET_MAX_MAN_SPECIFIC_FAST_STARTUP_DATA_LENGTH @PNET_MAX_MAN_SPECIFIC_FAST_STARTUP_DATA_LENGTH@ 128 | 129 | /** Max fragmented RPC request/response length */ 130 | #define PNET_MAX_SESSION_BUFFER_SIZE @PNET_MAX_SESSION_BUFFER_SIZE@ 131 | 132 | /** Max directory path size, including termination */ 133 | #define PNET_MAX_DIRECTORYPATH_SIZE @PNET_MAX_DIRECTORYPATH_SIZE@ 134 | 135 | /** Max filename size, including termination */ 136 | #define PNET_MAX_FILENAME_SIZE @PNET_MAX_FILENAME_SIZE@ 137 | 138 | /** Max port description size, including termination */ 139 | #define PNET_MAX_PORT_DESCRIPTION_SIZE @PNET_MAX_PORT_DESCRIPTION_SIZE@ 140 | 141 | 142 | /** 143 | * # Logging 144 | * 145 | * The following options controlling logging. 146 | */ 147 | 148 | #ifndef LOG_LEVEL 149 | #define LOG_LEVEL (LOG_LEVEL_@LOG_LEVEL@) 150 | #endif 151 | 152 | #ifndef PF_ETH_LOG 153 | #define PF_ETH_LOG (LOG_STATE_@PF_ETH_LOG@) 154 | #endif 155 | 156 | #ifndef PF_LLDP_LOG 157 | #define PF_LLDP_LOG (LOG_STATE_@PF_LLDP_LOG@) 158 | #endif 159 | 160 | #ifndef PF_SNMP_LOG 161 | #define PF_SNMP_LOG (LOG_STATE_@PF_SNMP_LOG@) 162 | #endif 163 | 164 | #ifndef PF_CPM_LOG 165 | #define PF_CPM_LOG (LOG_STATE_@PF_CPM_LOG@) 166 | #endif 167 | 168 | #ifndef PF_PPM_LOG 169 | #define PF_PPM_LOG (LOG_STATE_@PF_PPM_LOG@) 170 | #endif 171 | 172 | #ifndef PF_DCP_LOG 173 | #define PF_DCP_LOG (LOG_STATE_@PF_DCP_LOG@) 174 | #endif 175 | 176 | #ifndef PF_RPC_LOG 177 | #define PF_RPC_LOG (LOG_STATE_@PF_RPC_LOG@) 178 | #endif 179 | 180 | #ifndef PF_ALARM_LOG 181 | #define PF_ALARM_LOG (LOG_STATE_@PF_ALARM_LOG@) 182 | #endif 183 | 184 | #ifndef PF_AL_BUF_LOG 185 | #define PF_AL_BUF_LOG (LOG_STATE_@PF_AL_BUF_LOG@) 186 | #endif 187 | 188 | #ifndef PF_PNAL_LOG 189 | #define PF_PNAL_LOG (LOG_STATE_@PF_PNAL_LOG@) 190 | #endif 191 | 192 | #ifndef PNET_LOG 193 | #define PNET_LOG (LOG_STATE_@PNET_LOG@) 194 | #endif 195 | 196 | #endif /* PNET_OPTIONS_H */ 197 | -------------------------------------------------------------------------------- /pnet_version.h.in: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * _ _ _ 3 | * _ __ | |_ _ | | __ _ | |__ ___ 4 | * | '__|| __|(_)| | / _` || '_ \ / __| 5 | * | | | |_ _ | || (_| || |_) |\__ \ 6 | * |_| \__|(_)|_| \__,_||_.__/ |___/ 7 | * 8 | * www.rt-labs.com 9 | * Copyright 2018 rt-labs AB, Sweden. 10 | * 11 | * This software is dual-licensed under GPLv3 and a commercial 12 | * license. See the file LICENSE.md distributed with this software for 13 | * full license information. 14 | ********************************************************************/ 15 | 16 | #ifndef PNET_VERSION_H 17 | #define PNET_VERSION_H 18 | 19 | #cmakedefine PNET_GIT_REVISION "@PNET_GIT_REVISION@" 20 | 21 | #if !defined(PNET_VERSION_BUILD) && defined(PNET_GIT_REVISION) 22 | #define PNET_VERSION_BUILD PNET_GIT_REVISION 23 | #endif 24 | 25 | /* clang-format-off */ 26 | 27 | #define PNET_VERSION_MAJOR @PNET_VERSION_MAJOR@ 28 | #define PNET_VERSION_MINOR @PNET_VERSION_MINOR@ 29 | #define PNET_VERSION_PATCH @PNET_VERSION_PATCH@ 30 | 31 | #if defined(PNET_VERSION_BUILD) 32 | #define PNET_VERSION \ 33 | "@PNET_VERSION_MAJOR@.@PNET_VERSION_MINOR@.@PNET_VERSION_PATCH@+" PNET_VERSION_BUILD 34 | #else 35 | #define PNET_VERSION \ 36 | "@PNET_VERSION_MAJOR@.@PNET_VERSION_MINOR@.@PNET_VERSION_PATCH@" 37 | #endif 38 | 39 | /* clang-format-on */ 40 | 41 | #endif /* PNET_VERSION_H */ 42 | -------------------------------------------------------------------------------- /src/common/pf_bg_worker.h: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * _ _ _ 3 | * _ __ | |_ _ | | __ _ | |__ ___ 4 | * | '__|| __|(_)| | / _` || '_ \ / __| 5 | * | | | |_ _ | || (_| || |_) |\__ \ 6 | * |_| \__|(_)|_| \__,_||_.__/ |___/ 7 | * 8 | * www.rt-labs.com 9 | * Copyright 2021 rt-labs AB, Sweden. 10 | * 11 | * This software is dual-licensed under GPLv3 and a commercial 12 | * license. See the file LICENSE.md distributed with this software for 13 | * full license information. 14 | ********************************************************************/ 15 | 16 | #ifndef PF_BG_WORKER_H 17 | #define PF_BG_WORKER_H 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | /** 24 | * Background worker jobs 25 | */ 26 | typedef enum pf_bg_job 27 | { 28 | /** Update status for all ports */ 29 | PF_BGJOB_UPDATE_PORTS_STATUS = 0, 30 | 31 | /** Save non volatile ASE data to file */ 32 | PF_BGJOB_SAVE_ASE_NVM_DATA, 33 | 34 | /** Save non volatile IM data to file */ 35 | PF_BGJOB_SAVE_IM_NVM_DATA, 36 | 37 | /** Save non volatile PDPort data to file */ 38 | PF_BGJOB_SAVE_PDPORT_NVM_DATA, 39 | 40 | /** Save non volatile SNMP data to file */ 41 | PF_BGJOB_SAVE_SNMP_SYSTEM_CONTACT_NVM_DATA, 42 | PF_BGJOB_SAVE_SNMP_SYSTEM_NAME_NVM_DATA, 43 | PF_BGJOB_SAVE_SNMP_SYSTEM_LOCATION_NVM_DATA, 44 | PF_BGJOB_CLEAR_SNMP_SYSTEM_LOCATION_NVM_DATA, 45 | 46 | /** Clear ip setting file */ 47 | PF_BGJOB_CLEAR_IP_SETTINGS_FILE, 48 | 49 | /** Clear diagnostics file */ 50 | PF_BGJOB_CLEAR_DIAGNOSTICS_FILE, 51 | 52 | } pf_bg_job_t; 53 | 54 | /** 55 | * Initialize the background worker. 56 | * 57 | * @param net InOut: The p-net stack instance 58 | */ 59 | void pf_bg_worker_init (pnet_t * net); 60 | 61 | /** 62 | * Start a background job. 63 | * This function is non-blocking and sends the job request 64 | * to the background worker task. 65 | * @param net InOut: The p-net stack instance 66 | * @param job_id In: Job to run 67 | * @return 0 if operation is successfully initiated 68 | * -1 if an error occurred. 69 | */ 70 | int pf_bg_worker_start_job (pnet_t * net, pf_bg_job_t job_id); 71 | 72 | #ifdef __cplusplus 73 | } 74 | #endif 75 | 76 | #endif /* PF_BG_WORKER_H */ 77 | -------------------------------------------------------------------------------- /src/common/pf_cpm.h: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * _ _ _ 3 | * _ __ | |_ _ | | __ _ | |__ ___ 4 | * | '__|| __|(_)| | / _` || '_ \ / __| 5 | * | | | |_ _ | || (_| || |_) |\__ \ 6 | * |_| \__|(_)|_| \__,_||_.__/ |___/ 7 | * 8 | * www.rt-labs.com 9 | * Copyright 2018 rt-labs AB, Sweden. 10 | * 11 | * This software is dual-licensed under GPLv3 and a commercial 12 | * license. See the file LICENSE.md distributed with this software for 13 | * full license information. 14 | ********************************************************************/ 15 | 16 | #ifndef PF_CPM_H 17 | #define PF_CPM_H 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | /** 24 | * Initialize the CPM component. 25 | * @param net InOut: The p-net stack instance 26 | */ 27 | void pf_cpm_init (pnet_t * net); 28 | 29 | /** 30 | * Create a CPM for a specific IOCR instance. 31 | * 32 | * This function creates a CPM instance for the specified IOCR instance. 33 | * Set the CPM state to W_START. 34 | * Allocate the buffer mutex on first call. 35 | * 36 | * @param net InOut: The p-net stack instance 37 | * @param p_ar InOut: The AR instance. 38 | * @param crep In: The IOCR index. 39 | * @return 0 if the CPM instance was created. 40 | * -1 if an error occurred. 41 | */ 42 | int pf_cpm_create (pnet_t * net, pf_ar_t * p_ar, uint32_t crep); 43 | 44 | /** 45 | * Close a CPM instance. 46 | * 47 | * This function terminates the specified CPM instance. 48 | * De-registers a frame handler for incoming Ethernet frames. 49 | * The buffer mutex is destroyed on the last call. 50 | * 51 | * @param net InOut: The p-net stack instance 52 | * @param p_ar InOut: The AR instance. 53 | * @param crep In: The IOCR index. 54 | * @return 0 if the CPM instance was closed. 55 | * -1 if an error occurred. 56 | */ 57 | int pf_cpm_close_req (pnet_t * net, pf_ar_t * p_ar, uint32_t crep); 58 | 59 | /** 60 | * Activate a CPM instance and of the specified CR instance. 61 | * 62 | * Registers a frame handler for incoming Ethernet frames. 63 | * 64 | * @param net InOut: The p-net stack instance 65 | * @param p_ar InOut: The AR instance. 66 | * @param crep In: The IOCR index. 67 | * @return 0 if the CPM instance could be activated. 68 | * -1 if an error occurred. 69 | */ 70 | int pf_cpm_activate_req (pnet_t * net, pf_ar_t * p_ar, uint32_t crep); 71 | 72 | /** 73 | * Retrieve the specified sub-slot IOCS sent from the controller. 74 | * User must supply a buffer large enough to hold the received IOCS. 75 | * Maximum buffer size is 256 bytes. 76 | * @param net InOut: The p-net stack instance 77 | * @param api_id In: The API identifier. 78 | * @param slot_nbr In: The slot number. 79 | * @param subslot_nbr In: The sub-slot number. 80 | * @param p_iocs Out: Copy of the received IOCS. 81 | * @param p_iocs_len In: Size of buffer at p_iocs. 82 | * Out: The length of the received IOCS. 83 | * @return 84 | */ 85 | int pf_cpm_get_iocs ( 86 | pnet_t * net, 87 | uint32_t api_id, 88 | uint16_t slot_nbr, 89 | uint16_t subslot_nbr, 90 | uint8_t * p_iocs, 91 | uint8_t * p_iocs_len); 92 | 93 | /** 94 | * Retrieve the specified sub-slot data and IOPS received from the controller. 95 | * User must supply a buffer large enough to hold the received data. 96 | * Maximum buffer size is PF_FRAME_BUFFER_SIZE (1500) bytes. 97 | * User must supply a buffer large enough to hold the received IOPS. 98 | * Maximum buffer size is 256 bytes. 99 | * 100 | * @param net InOut: The p-net stack instance 101 | * @param api_id In: The API identifier. 102 | * @param slot_nbr In: The slot number. 103 | * @param subslot_nbr In: The sub-slot number. 104 | * @param p_new_flag Out: true means new valid data (and IOPS) frame 105 | * available since last call. 106 | * @param p_data Out: Copy of the received data. 107 | * @param p_data_len In: Buffer size. 108 | * Out: Length of received data. 109 | * @param p_iops Out: The received IOPS. 110 | * @param p_iops_len In: Size of buffer at p_iops. 111 | * Out: The length of the received IOPS. 112 | * @return 0 if the data and IOPS could be retrieved. 113 | * -1 if an error occurred. 114 | */ 115 | int pf_cpm_get_data_and_iops ( 116 | pnet_t * net, 117 | uint32_t api_id, 118 | uint16_t slot_nbr, 119 | uint16_t subslot_nbr, 120 | bool * p_new_flag, 121 | uint8_t * p_data, 122 | uint16_t * p_data_len, 123 | uint8_t * p_iops, 124 | uint8_t * p_iops_len); 125 | 126 | /** 127 | * Get the data status of the CPM connection. 128 | * @param p_cpm In: The CPM instance. 129 | * @param p_data_status Out: The CPM data status. 130 | * @return 131 | */ 132 | int pf_cpm_get_data_status (const pf_cpm_t * p_cpm, uint8_t * p_data_status); 133 | 134 | /** 135 | * Show information about a CPM instance. 136 | * @param net In: The p-net stack instance 137 | * @param p_cpm In: The CPM instance. 138 | */ 139 | void pf_cpm_show (const pnet_t * net, const pf_cpm_t * p_cpm); 140 | 141 | /* Functions used by cpm driver */ 142 | 143 | /** 144 | * Change the CPM state. 145 | * @param p_spm InOut: The CPM instance. 146 | * @param state In: The new CPM state. 147 | */ 148 | void pf_cpm_set_state (pf_cpm_t * p_cpm, pf_cpm_state_values_t state); 149 | 150 | /** 151 | * Notify other components about CPM events. 152 | * @param net InOut: The p-net stack instance 153 | * @param p_ar InOut: The AR instance. 154 | * @param crep In: The IOCR index 155 | * @param start In: Start/Stop indicator. True if CPM is starting. 156 | */ 157 | void pf_cpm_state_ind (pnet_t * net, pf_ar_t * p_ar, uint32_t crep, bool start); 158 | 159 | /** 160 | * Perform a check of the source address of the received frame. 161 | * @param p_cpm In: The CPM instance. 162 | * @param p_buf In: The frame buffer. 163 | * @return 0 if the source address is OK. 164 | * -1 if the source address is wrong. 165 | */ 166 | int pf_cpm_check_src_addr (const pf_cpm_t * p_cpm, const pnal_buf_t * p_buf); 167 | 168 | /************ Internal functions, made available for unit testing ************/ 169 | 170 | /** 171 | * Perform the cycle counter check of the received frame. 172 | * 173 | * Profinet 2.4, section 4.7.2.1.2 174 | * 175 | * In general, the current counter value should be larger than the 176 | * previous counter value. 177 | * 178 | * However as we use cyclic counters, also allow it to be a lot less (not the 179 | * same or slightly less). 180 | * 181 | * @param prev In: The previous cycle counter. 182 | * @param now In: The current cycle counter. 183 | * @return 0 If the cycle check is OK. 184 | * -1 if the cycle check fails. 185 | */ 186 | int pf_cpm_check_cycle (int32_t prev, uint16_t now); 187 | 188 | #ifdef __cplusplus 189 | } 190 | #endif 191 | 192 | #endif /* PF_CPM_H */ 193 | -------------------------------------------------------------------------------- /src/common/pf_cpm_driver_sw.h: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * _ _ _ 3 | * _ __ | |_ _ | | __ _ | |__ ___ 4 | * | '__|| __|(_)| | / _` || '_ \ / __| 5 | * | | | |_ _ | || (_| || |_) |\__ \ 6 | * |_| \__|(_)|_| \__,_||_.__/ |___/ 7 | * 8 | * www.rt-labs.com 9 | * Copyright 2018 rt-labs AB, Sweden. 10 | * 11 | * This software is dual-licensed under GPLv3 and a commercial 12 | * license. See the file LICENSE.md distributed with this software for 13 | * full license information. 14 | ********************************************************************/ 15 | 16 | #ifndef PF_CPM_DRIVER_SW_H 17 | #define PF_CPM_DRIVER_SW_H 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | /** 24 | * Initialize p-net default cpm driver. 25 | * @param net InOut: The p-net stack instance 26 | */ 27 | void pf_cpm_driver_sw_init (pnet_t * net); 28 | 29 | #ifdef __cplusplus 30 | } 31 | #endif 32 | 33 | #endif /* PF_CPM_DRIVER_SW_H */ 34 | -------------------------------------------------------------------------------- /src/common/pf_dcp.h: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * _ _ _ 3 | * _ __ | |_ _ | | __ _ | |__ ___ 4 | * | '__|| __|(_)| | / _` || '_ \ / __| 5 | * | | | |_ _ | || (_| || |_) |\__ \ 6 | * |_| \__|(_)|_| \__,_||_.__/ |___/ 7 | * 8 | * www.rt-labs.com 9 | * Copyright 2018 rt-labs AB, Sweden. 10 | * 11 | * This software is dual-licensed under GPLv3 and a commercial 12 | * license. See the file LICENSE.md distributed with this software for 13 | * full license information. 14 | ********************************************************************/ 15 | 16 | #ifndef PF_DCP_H 17 | #define PF_DCP_H 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | /* 24 | * The option and sub-option values are used by DCP and also by CMINA. 25 | */ 26 | typedef enum pf_dcp_opt_values 27 | { 28 | PF_DCP_OPT_RESERVED_0 = 0, 29 | PF_DCP_OPT_IP, 30 | PF_DCP_OPT_DEVICE_PROPERTIES, 31 | PF_DCP_OPT_DHCP, 32 | PF_DCP_OPT_RESERVED_4, 33 | PF_DCP_OPT_CONTROL, 34 | PF_DCP_OPT_DEVICE_INITIATIVE, 35 | /* 36 | * Reserved 0x07 .. 0x7f 37 | * Manufacturer specific 0x80 .. 0xfe 38 | */ 39 | PF_DCP_OPT_ALL = 0xff 40 | } pf_dcp_opt_values_t; 41 | 42 | typedef enum pf_dcp_sub_all_values 43 | { 44 | PF_DCP_SUB_ALL = 0xff 45 | } pf_dcp_sub_all_values_t; 46 | 47 | typedef enum pf_dcp_sub_ip_values 48 | { 49 | PF_DCP_SUB_IP_MAC = 0x01, /* Read */ 50 | PF_DCP_SUB_IP_PAR, /* Read/Write */ 51 | PF_DCP_SUB_IP_SUITE /* Read/(optional Write) */ 52 | } pf_dcp_sub_ip_values_t; 53 | 54 | typedef enum pf_dcp_sub_dev_prop 55 | { 56 | PF_DCP_SUB_DEV_PROP_VENDOR = 0x01, /* Read */ 57 | PF_DCP_SUB_DEV_PROP_NAME, /* Read/Write */ 58 | PF_DCP_SUB_DEV_PROP_ID, /* Read */ 59 | PF_DCP_SUB_DEV_PROP_ROLE, /* Read */ 60 | PF_DCP_SUB_DEV_PROP_OPTIONS, /* Read */ 61 | PF_DCP_SUB_DEV_PROP_ALIAS, /* Used as filter only */ 62 | PF_DCP_SUB_DEV_PROP_INSTANCE, /* Read, optional */ 63 | PF_DCP_SUB_DEV_PROP_OEM_ID, /* Read, optional */ 64 | PF_DCP_SUB_DEV_PROP_GATEWAY /* Read, optional */ 65 | } pf_dcp_sub_dev_prop_t; 66 | 67 | typedef enum pf_dcp_sub_dhcp 68 | { 69 | PF_DCP_SUB_DHCP_HOSTNAME = 12, 70 | PF_DCP_SUB_DHCP_VENDOR_SPEC = 43, 71 | PF_DCP_SUB_DHCP_SERVER_ID = 54, 72 | PF_DCP_SUB_DHCP_PAR_REQ_LIST = 55, 73 | PF_DCP_SUB_DHCP_CLASS_ID = 60, 74 | PF_DCP_SUB_DHCP_CLIENT_ID = 61, 75 | PF_DCP_SUB_DHCP_FQDN = 81, 76 | PF_DCP_SUB_DHCP_UUID_CLIENT_ID = 97, 77 | PF_DCP_SUB_DHCP_CONTROL = 255 /* Defined as END in the DHCP spec */ 78 | } pf_dcp_sub_dhcp_t; 79 | 80 | typedef enum pf_dcp_sub_control 81 | { 82 | PF_DCP_SUB_CONTROL_START = 0x01, /* Write */ 83 | PF_DCP_SUB_CONTROL_STOP, /* Write */ 84 | PF_DCP_SUB_CONTROL_SIGNAL, /* Write */ 85 | PF_DCP_SUB_CONTROL_RESPONSE, 86 | PF_DCP_SUB_CONTROL_FACTORY_RESET, /* Optional, Write */ 87 | PF_DCP_SUB_CONTROL_RESET_TO_FACTORY, /* Write */ 88 | } pf_dcp_sub_control_t; 89 | 90 | typedef enum pf_dcp_sub_dev_initiative 91 | { 92 | PF_DCP_SUB_DEV_INITIATIVE_SUPPORT = 0x01 /* Read */ 93 | } pf_dcp_sub_dev_initiative_t; 94 | 95 | typedef enum pf_dcp_block_error_values 96 | { 97 | PF_DCP_BLOCK_ERROR_NO_ERROR, 98 | PF_DCP_BLOCK_ERROR_OPTION_NOT_SUPPORTED, 99 | PF_DCP_BLOCK_ERROR_SUBOPTION_NOT_SUPPORTED, 100 | PF_DCP_BLOCK_ERROR_SUBOPTION_NOT_SET, 101 | PF_DCP_BLOCK_ERROR_RESOURCE_ERROR, 102 | PF_DCP_BLOCK_ERROR_SET_NOT_POSSIBLE 103 | } pf_dcp_block_error_values_t; 104 | 105 | /** 106 | * Initialize the DCP component. 107 | * 108 | * Registers incoming frame IDs with the frame handler. 109 | * 110 | * @param net InOut: The p-net stack instance 111 | */ 112 | void pf_dcp_init (pnet_t * net); 113 | 114 | /** 115 | * Stop the DCP component. 116 | * 117 | * Unregisters frame IDs from the frame handler. 118 | * 119 | * @param net InOut: The p-net stack instance 120 | */ 121 | void pf_dcp_exit (pnet_t * net); 122 | 123 | /** 124 | * Send a DCP HELLO message. 125 | * @param net InOut: The p-net stack instance 126 | * @return 0 if a HELLO message was sent. 127 | * -1 if an error occurred. 128 | */ 129 | int pf_dcp_hello_req (pnet_t * net); 130 | 131 | /************ Internal functions, made available for unit testing ************/ 132 | 133 | uint32_t pf_dcp_calculate_response_delay ( 134 | const pnet_ethaddr_t * mac_address, 135 | uint16_t response_delay_factor); 136 | 137 | bool pf_dcp_check_destination_address ( 138 | const pnet_ethaddr_t * local_mac, 139 | const pnet_ethaddr_t * destination_mac); 140 | 141 | #ifdef __cplusplus 142 | } 143 | #endif 144 | 145 | #endif /* PF_DCP_H */ 146 | -------------------------------------------------------------------------------- /src/common/pf_eth.h: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * _ _ _ 3 | * _ __ | |_ _ | | __ _ | |__ ___ 4 | * | '__|| __|(_)| | / _` || '_ \ / __| 5 | * | | | |_ _ | || (_| || |_) |\__ \ 6 | * |_| \__|(_)|_| \__,_||_.__/ |___/ 7 | * 8 | * www.rt-labs.com 9 | * Copyright 2018 rt-labs AB, Sweden. 10 | * 11 | * This software is dual-licensed under GPLv3 and a commercial 12 | * license. See the file LICENSE.md distributed with this software for 13 | * full license information. 14 | ********************************************************************/ 15 | 16 | #ifndef PF_ETH_H 17 | #define PF_ETH_H 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | /** 24 | * Initialize ETH component and network interfaces according to configuration 25 | * If device is configured with one network interface 26 | * (num_physical_ports==1), the management port and physical port 1 27 | * refers to same network interface. In a multi port configuration, the 28 | * management port and physical ports are different network interfaces. 29 | * @param net InOut: The p-net stack instance 30 | * @param p_cfg In: Configuration 31 | * @return 0 on success 32 | * -1 on error 33 | */ 34 | int pf_eth_init (pnet_t * net, const pnet_cfg_t * p_cfg); 35 | 36 | /** 37 | * Send raw Ethernet frame on a specific physical port. 38 | * 39 | * Not for use with management port. 40 | * 41 | * @param net InOut: The p-net stack instance 42 | * @param loc_port_num In: Local port number. 43 | * Valid range: 1 .. num_physical_ports 44 | * @param buf In: Buffer with data to be sent 45 | * @return The number of bytes sent, or -1 if an error occurred. 46 | */ 47 | int pf_eth_send_on_physical_port ( 48 | pnet_t * net, 49 | int loc_port_num, 50 | pnal_buf_t * buf); 51 | 52 | /** 53 | * Send raw Ethernet frame on management port. 54 | * 55 | * @param net InOut: The p-net stack instance 56 | * @param buf In: Buffer with data to be sent 57 | * @return The number of bytes sent, or -1 if an error occurred. 58 | */ 59 | int pf_eth_send_on_management_port (pnet_t * net, pnal_buf_t * buf); 60 | 61 | /** 62 | * Add a frame_id entry to the frame id filter map. 63 | * 64 | * This function adds an entry to the frame id table. 65 | * This table is used to map incoming frames to the right handler functions, 66 | * based on the frame id. 67 | * 68 | * Used only for incoming frames with Ethtype = Profinet. 69 | * 70 | * @param net InOut: The p-net stack instance 71 | * @param frame_id In: The frame ID to look for. 72 | * @param frame_handler In: The handler function to call. 73 | * @param p_arg In: Argument to handler function. 74 | */ 75 | void pf_eth_frame_id_map_add ( 76 | pnet_t * net, 77 | uint16_t frame_id, 78 | pf_eth_frame_handler_t frame_handler, 79 | void * p_arg); 80 | 81 | /** 82 | * Remove an entry from the frame id filter map (if it exists). 83 | * 84 | * @param net InOut: The p-net stack instance 85 | * @param frame_id In: The frame ID to remove. 86 | */ 87 | void pf_eth_frame_id_map_remove (pnet_t * net, uint16_t frame_id); 88 | 89 | /** 90 | * Inspect and possibly handle a raw Ethernet frame 91 | * 92 | * Find the packet type. If it is for Profinet then send it to the right 93 | * handler, depending on the frame_id within the packet. The frame_id is located 94 | * right after the packet type. Take care of handling the VLAN tag. 95 | * 96 | * Note also that this function is a callback and will be passed as an argument 97 | * to pnal_eth_init(). 98 | * 99 | * @param eth_handle InOut: Network interface the frame was received on. 100 | * @param arg InOut: User argument, will be converted to pnet_t 101 | * @param p_buf InOut: The Ethernet frame. Might be freed. 102 | * @return 0 If the frame was NOT handled by this function. 103 | * 1 If the frame was handled and the buffer freed. 104 | */ 105 | int pf_eth_recv (pnal_eth_handle_t * eth_handle, void * arg, pnal_buf_t * p_buf); 106 | 107 | #ifdef __cplusplus 108 | } 109 | #endif 110 | 111 | #endif /* PF_DCPMCS_H */ 112 | -------------------------------------------------------------------------------- /src/common/pf_file.h: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * _ _ _ 3 | * _ __ | |_ _ | | __ _ | |__ ___ 4 | * | '__|| __|(_)| | / _` || '_ \ / __| 5 | * | | | |_ _ | || (_| || |_) |\__ \ 6 | * |_| \__|(_)|_| \__,_||_.__/ |___/ 7 | * 8 | * www.rt-labs.com 9 | * Copyright 2018 rt-labs AB, Sweden. 10 | * 11 | * This software is dual-licensed under GPLv3 and a commercial 12 | * license. See the file LICENSE.md distributed with this software for 13 | * full license information. 14 | ********************************************************************/ 15 | 16 | #ifndef PF_FILE_H 17 | #define PF_FILE_H 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | #include 24 | 25 | /* Filenames used by p-net stack. A filename may not be longer than 26 | * PNET_MAX_FILENAME_SIZE (termination included). 27 | */ 28 | #define PF_FILENAME_IP "pnet_data_ip.bin" 29 | #define PF_FILENAME_IM "pnet_data_im.bin" 30 | #define PF_FILENAME_DIAGNOSTICS "pnet_data_diagnostics.bin" 31 | #define PF_FILENAME_PDPORT_1 "pnet_data_pdport_1.bin" 32 | #define PF_FILENAME_PDPORT_2 "pnet_data_pdport_2.bin" 33 | #define PF_FILENAME_PDPORT_3 "pnet_data_pdport_3.bin" 34 | #define PF_FILENAME_PDPORT_4 "pnet_data_pdport_4.bin" 35 | 36 | /** 37 | * Load a binary file, and verify the file version. 38 | * 39 | * @param directory In: Directory for files. Terminated string. NULL 40 | * or empty string is interpreted as current 41 | * directory. 42 | * @param filename In: File name. Terminated string. 43 | * @param p_object Out: Struct to load 44 | * @param size In: Size of struct to load 45 | * @return 0 if the operation succeeded. 46 | * -1 if not found or an error occurred (for example wrong version). 47 | */ 48 | int pf_file_load ( 49 | const char * directory, 50 | const char * filename, 51 | void * p_object, 52 | size_t size); 53 | 54 | /** 55 | * Save a binary file, and include version information. 56 | * 57 | * @param directory In: Directory for files. Terminated string. NULL 58 | * or empty string is interpreted as current 59 | * directory. 60 | * @param filename In: File name. Terminated string. 61 | * @param p_object In: Struct to save 62 | * @param size In: Size of struct to save 63 | * @return 0 if the operation succeeded. 64 | * -1 if an error occurred. 65 | */ 66 | int pf_file_save ( 67 | const char * directory, 68 | const char * filename, 69 | const void * p_object, 70 | size_t size); 71 | 72 | /** 73 | * Save a binary file if modified, and include version information. 74 | * 75 | * No saving is done if the content would be the same. This reduces the flash 76 | * memory wear. 77 | * 78 | * @param directory In: Directory for files. Terminated string. NULL 79 | * or empty string is interpreted as current 80 | * directory. 81 | * @param filename In: File name. Terminated string. 82 | * @param p_object In: Struct to save 83 | * @param p_tempobject Temp: Temporary buffer (of same size as object) for 84 | * loading existing file. 85 | * @param size In: Size of struct to save 86 | * @return 2 First saving of file (no previous file with correct version found) 87 | * 1 Updated file 88 | * 0 No storing required (no changes) 89 | * -1 if an error occurred. 90 | */ 91 | int pf_file_save_if_modified ( 92 | const char * directory, 93 | const char * filename, 94 | const void * p_object, 95 | void * p_tempobject, 96 | size_t size); 97 | 98 | /** 99 | * Clear a binary file. 100 | * 101 | * @param directory In: Directory for files. Terminated string. NULL 102 | * or empty string is interpreted as current 103 | * directory. 104 | * @param filename In: File name. Terminated string. 105 | */ 106 | void pf_file_clear (const char * directory, const char * filename); 107 | 108 | /************ Internal functions, made available for unit testing ************/ 109 | 110 | int pf_file_join_directory_filename ( 111 | const char * directory, 112 | const char * filename, 113 | char * fullpath, 114 | size_t size); 115 | 116 | #ifdef __cplusplus 117 | } 118 | #endif 119 | 120 | #endif /* PF_FILE_H */ -------------------------------------------------------------------------------- /src/common/pf_ppm_driver_sw.c: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * _ _ _ 3 | * _ __ | |_ _ | | __ _ | |__ ___ 4 | * | '__|| __|(_)| | / _` || '_ \ / __| 5 | * | | | |_ _ | || (_| || |_) |\__ \ 6 | * |_| \__|(_)|_| \__,_||_.__/ |___/ 7 | * 8 | * www.rt-labs.com 9 | * Copyright 2018 rt-labs AB, Sweden. 10 | * 11 | * This software is dual-licensed under GPLv3 and a commercial 12 | * license. See the file LICENSE.md distributed with this software for 13 | * full license information. 14 | ********************************************************************/ 15 | 16 | #include "pf_includes.h" 17 | 18 | #include 19 | #include 20 | 21 | /** 22 | * @internal 23 | * Send the process data frame. 24 | * 25 | * This is a callback for the scheduler. Arguments should fulfill 26 | * pf_scheduler_timeout_ftn_t 27 | * 28 | * If the PPM has not been stopped during the wait, then a data message 29 | * is sent and the function is rescheduled. 30 | * 31 | * @param net InOut: The p-net stack instance 32 | * @param arg In: The IOCR instance. 33 | * @param current_time In: The current system time, in microseconds, 34 | * when the scheduler is started to execute 35 | * stored tasks. 36 | */ 37 | static void pf_ppm_drv_sw_send (pnet_t * net, void * arg, uint32_t current_time) 38 | { 39 | pf_iocr_t * p_arg = (pf_iocr_t *)arg; 40 | uint32_t delay = 0; 41 | 42 | pf_scheduler_reset_handle (&p_arg->ppm.ci_timeout); 43 | if (p_arg->ppm.ci_running == true) 44 | { 45 | /* Insert data, status etc. The in_length is the size of input to the 46 | * controller */ 47 | pf_ppm_finish_buffer (net, &p_arg->ppm, p_arg->in_length); 48 | 49 | /* Now send it */ 50 | if (pf_eth_send_on_management_port (net, p_arg->ppm.p_send_buffer) > 0) 51 | { 52 | /* Schedule next execution */ 53 | p_arg->ppm.next_exec += p_arg->ppm.control_interval; 54 | delay = p_arg->ppm.next_exec - current_time; 55 | if ( 56 | pf_scheduler_add ( 57 | net, 58 | delay, 59 | pf_ppm_drv_sw_send, 60 | arg, 61 | &p_arg->ppm.ci_timeout) == 0) 62 | { 63 | p_arg->ppm.trx_cnt++; 64 | if (p_arg->ppm.first_transmit == false) 65 | { 66 | pf_ppm_state_ind (net, p_arg->p_ar, &p_arg->ppm, false); 67 | p_arg->ppm.first_transmit = true; 68 | } 69 | } 70 | else 71 | { 72 | /* Indidate error */ 73 | pf_ppm_state_ind (net, p_arg->p_ar, &p_arg->ppm, true); 74 | } 75 | } 76 | } 77 | } 78 | 79 | int pf_ppm_drv_sw_create (pnet_t * net, pf_ar_t * p_ar, uint32_t crep) 80 | { 81 | return 0; 82 | } 83 | 84 | int pf_ppm_drv_sw_activate_req (pnet_t * net, pf_ar_t * p_ar, uint32_t crep) 85 | { 86 | int ret = -1; 87 | pf_iocr_t * p_iocr = &p_ar->iocrs[crep]; 88 | pf_ppm_t * p_ppm = &p_ar->iocrs[crep].ppm; 89 | 90 | LOG_DEBUG ( 91 | PF_PPM_LOG, 92 | "PPM(%d): Start scheduling of process data frames for AREP %u CREP " 93 | "%" PRIu32 "\n", 94 | __LINE__, 95 | p_ar->arep, 96 | crep); 97 | 98 | pf_scheduler_init_handle (&p_ppm->ci_timeout, "ppm"); 99 | ret = pf_scheduler_add ( 100 | net, 101 | p_ppm->control_interval, 102 | pf_ppm_drv_sw_send, 103 | p_iocr, 104 | &p_ppm->ci_timeout); 105 | 106 | return ret; 107 | } 108 | 109 | int pf_ppm_drv_sw_close_req (pnet_t * net, pf_ar_t * p_ar, uint32_t crep) 110 | { 111 | pf_ppm_t * p_ppm = &p_ar->iocrs[crep].ppm; 112 | 113 | LOG_DEBUG ( 114 | PF_PPM_LOG, 115 | "PPM(%d): Stop scheduling of process data frames for AREP %u CREP " 116 | "%" PRIu32 "\n", 117 | __LINE__, 118 | p_ar->arep, 119 | crep); 120 | 121 | pf_scheduler_remove_if_running (net, &p_ppm->ci_timeout); 122 | 123 | return 0; 124 | } 125 | 126 | static int pf_ppm_drv_sw_write_frame_buffer ( 127 | pnet_t * net, 128 | pf_iocr_t * iocr, 129 | uint32_t offset, 130 | const uint8_t * data, 131 | uint16_t len) 132 | { 133 | memcpy (&iocr->ppm.buffer_data[offset], data, len); 134 | return 0; 135 | } 136 | 137 | static int pf_ppm_drv_sw_read_frame_buffer ( 138 | pnet_t * net, 139 | pf_iocr_t * iocr, 140 | uint32_t offset, 141 | uint8_t * data, 142 | uint16_t len) 143 | { 144 | memcpy (data, &iocr->ppm.buffer_data[offset], len); 145 | return 0; 146 | } 147 | 148 | int pf_ppm_drv_sw_write_data_and_iops ( 149 | pnet_t * net, 150 | pf_iocr_t * iocr, 151 | const pf_iodata_object_t * p_iodata, 152 | const uint8_t * data, 153 | uint16_t len, 154 | const uint8_t * iops, 155 | uint8_t iops_len) 156 | { 157 | int ret = 0; 158 | os_mutex_lock (net->ppm_buf_lock); 159 | 160 | if (data != NULL) 161 | { 162 | ret = pf_ppm_drv_sw_write_frame_buffer ( 163 | net, 164 | iocr, 165 | p_iodata->data_offset, 166 | data, 167 | len); 168 | } 169 | 170 | if (ret == 0) 171 | { 172 | ret = pf_ppm_drv_sw_write_frame_buffer ( 173 | net, 174 | iocr, 175 | p_iodata->iops_offset, 176 | iops, 177 | iops_len); 178 | } 179 | os_mutex_unlock (net->ppm_buf_lock); 180 | 181 | return ret; 182 | } 183 | 184 | int pf_ppm_drv_sw_read_data_and_iops ( 185 | pnet_t * net, 186 | pf_iocr_t * iocr, 187 | const pf_iodata_object_t * p_iodata, 188 | uint8_t * data, 189 | uint16_t data_len, 190 | uint8_t * iops, 191 | uint8_t iops_len) 192 | { 193 | int ret; 194 | 195 | os_mutex_lock (net->ppm_buf_lock); 196 | 197 | ret = pf_ppm_drv_sw_read_frame_buffer ( 198 | net, 199 | iocr, 200 | p_iodata->data_offset, 201 | data, 202 | data_len); 203 | if (ret == 0) 204 | { 205 | ret = pf_ppm_drv_sw_read_frame_buffer ( 206 | net, 207 | iocr, 208 | p_iodata->iops_offset, 209 | iops, 210 | iops_len); 211 | } 212 | 213 | os_mutex_unlock (net->ppm_buf_lock); 214 | 215 | return ret; 216 | } 217 | 218 | int pf_ppm_drv_sw_write_iocs ( 219 | pnet_t * net, 220 | pf_iocr_t * iocr, 221 | const pf_iodata_object_t * p_iodata, 222 | const uint8_t * iocs, 223 | uint8_t len) 224 | { 225 | int ret; 226 | 227 | os_mutex_lock (net->ppm_buf_lock); 228 | ret = pf_ppm_drv_sw_write_frame_buffer ( 229 | net, 230 | iocr, 231 | p_iodata->iocs_offset, 232 | iocs, 233 | len); 234 | os_mutex_unlock (net->ppm_buf_lock); 235 | 236 | return ret; 237 | } 238 | 239 | int pf_ppm_drv_sw_read_iocs ( 240 | pnet_t * net, 241 | pf_iocr_t * iocr, 242 | const pf_iodata_object_t * p_iodata, 243 | uint8_t * iocs, 244 | uint8_t iocs_len) 245 | { 246 | int ret; 247 | 248 | os_mutex_lock (net->ppm_buf_lock); 249 | ret = pf_ppm_drv_sw_read_frame_buffer ( 250 | net, 251 | iocr, 252 | p_iodata->iocs_offset, 253 | iocs, 254 | iocs_len); 255 | os_mutex_unlock (net->ppm_buf_lock); 256 | 257 | return ret; 258 | } 259 | 260 | int pf_ppm_drv_sw_write_data_status ( 261 | pnet_t * net, 262 | pf_iocr_t * iocr, 263 | uint8_t data_status) 264 | { 265 | return 0; 266 | } 267 | 268 | void pf_ppm_drv_sw_show (const pf_ppm_t * p_ppm) 269 | { 270 | printf ("pf_ppm_drv_sw_show not implemented\n"); 271 | } 272 | 273 | void pf_ppm_driver_sw_init (pnet_t * net) 274 | { 275 | static const pf_ppm_driver_t drv = { 276 | .create = pf_ppm_drv_sw_create, 277 | .activate_req = pf_ppm_drv_sw_activate_req, 278 | .close_req = pf_ppm_drv_sw_close_req, 279 | .write_data_and_iops = pf_ppm_drv_sw_write_data_and_iops, 280 | .read_data_and_iops = pf_ppm_drv_sw_read_data_and_iops, 281 | .write_iocs = pf_ppm_drv_sw_write_iocs, 282 | .read_iocs = pf_ppm_drv_sw_read_iocs, 283 | .write_data_status = pf_ppm_drv_sw_write_data_status, 284 | /*.read_data_status = pf_ppm_drv_sw_read_data_status, */ 285 | .show = pf_ppm_drv_sw_show}; 286 | 287 | net->ppm_drv = &drv; 288 | 289 | LOG_INFO ( 290 | PF_PPM_LOG, 291 | "PPM_DRIVER_SW(%d): Default PPM driver installed\n", 292 | __LINE__); 293 | } 294 | -------------------------------------------------------------------------------- /src/common/pf_ppm_driver_sw.h: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * _ _ _ 3 | * _ __ | |_ _ | | __ _ | |__ ___ 4 | * | '__|| __|(_)| | / _` || '_ \ / __| 5 | * | | | |_ _ | || (_| || |_) |\__ \ 6 | * |_| \__|(_)|_| \__,_||_.__/ |___/ 7 | * 8 | * www.rt-labs.com 9 | * Copyright 2018 rt-labs AB, Sweden. 10 | * 11 | * This software is dual-licensed under GPLv3 and a commercial 12 | * license. See the file LICENSE.md distributed with this software for 13 | * full license information. 14 | ********************************************************************/ 15 | 16 | #ifndef PF_PPM_DRIVER_SW_H 17 | #define PF_PPM_DRIVER_SW_H 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | void pf_ppm_driver_sw_init (pnet_t * net); 24 | 25 | #ifdef __cplusplus 26 | } 27 | #endif 28 | 29 | #endif /* PF_DRIVER_SW_H */ 30 | -------------------------------------------------------------------------------- /src/common/pf_ptcp.c: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * _ _ _ 3 | * _ __ | |_ _ | | __ _ | |__ ___ 4 | * | '__|| __|(_)| | / _` || '_ \ / __| 5 | * | | | |_ _ | || (_| || |_) |\__ \ 6 | * |_| \__|(_)|_| \__,_||_.__/ |___/ 7 | * 8 | * www.rt-labs.com 9 | * Copyright 2018 rt-labs AB, Sweden. 10 | * 11 | * This software is dual-licensed under GPLv3 and a commercial 12 | * license. See the file LICENSE.md distributed with this software for 13 | * full license information. 14 | ********************************************************************/ 15 | 16 | #ifdef UNIT_TEST 17 | 18 | #endif 19 | 20 | #include "pf_includes.h" 21 | -------------------------------------------------------------------------------- /src/common/pf_ptcp.h: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * _ _ _ 3 | * _ __ | |_ _ | | __ _ | |__ ___ 4 | * | '__|| __|(_)| | / _` || '_ \ / __| 5 | * | | | |_ _ | || (_| || |_) |\__ \ 6 | * |_| \__|(_)|_| \__,_||_.__/ |___/ 7 | * 8 | * www.rt-labs.com 9 | * Copyright 2018 rt-labs AB, Sweden. 10 | * 11 | * This software is dual-licensed under GPLv3 and a commercial 12 | * license. See the file LICENSE.md distributed with this software for 13 | * full license information. 14 | ********************************************************************/ 15 | 16 | #ifndef PF_PTCP_H 17 | #define PF_PTCP_H 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | #ifdef __cplusplus 24 | } 25 | #endif 26 | 27 | #endif /* PF_PTCP_H */ 28 | -------------------------------------------------------------------------------- /src/common/pf_scheduler.h: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * _ _ _ 3 | * _ __ | |_ _ | | __ _ | |__ ___ 4 | * | '__|| __|(_)| | / _` || '_ \ / __| 5 | * | | | |_ _ | || (_| || |_) |\__ \ 6 | * |_| \__|(_)|_| \__,_||_.__/ |___/ 7 | * 8 | * www.rt-labs.com 9 | * Copyright 2018 rt-labs AB, Sweden. 10 | * 11 | * This software is dual-licensed under GPLv3 and a commercial 12 | * license. See the file LICENSE.md distributed with this software for 13 | * full license information. 14 | ********************************************************************/ 15 | 16 | #ifndef PF_SCHEDULER_H 17 | #define PF_SCHEDULER_H 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | #define PF_SCHEDULER_MAX_DELAY_US 100000000U /* 100 seconds */ 24 | 25 | /** 26 | * Initialize the scheduler. 27 | * @param net InOut: The p-net stack instance 28 | * @param tick_interval In: System calls the tick function at these 29 | * intervals, in microseconds. Must be 30 | * larger than 0. 31 | */ 32 | void pf_scheduler_init (pnet_t * net, uint32_t tick_interval); 33 | 34 | /** 35 | * Initialize a timeout handle. 36 | * @param handle Out: Timeout handle. 37 | * @param name In: Descriptive name for debugging. Not NULL. 38 | */ 39 | void pf_scheduler_init_handle ( 40 | pf_scheduler_handle_t * handle, 41 | const char * name); 42 | 43 | /** 44 | * Reset the value inside the timeout handle to indicate that it's not running. 45 | * 46 | * May be used inside the callback (which is executed by the scheduler). 47 | * 48 | * To unschedule a callback, use \a pf_scheduler_remove() or 49 | * \a pf_scheduler_remove_if_running() instead. 50 | * 51 | * @param handle Out: Timeout handle. 52 | */ 53 | void pf_scheduler_reset_handle (pf_scheduler_handle_t * handle); 54 | 55 | /** 56 | * Report whether the timeout is running (=scheduled) 57 | * 58 | * @param handle InOut: Timeout handle. 59 | * @return true if it is running 60 | * false otherwise 61 | */ 62 | bool pf_scheduler_is_running (const pf_scheduler_handle_t * handle); 63 | 64 | /** 65 | * Report the internal value of a timeout handle. 66 | * 67 | * Intended for debugging and testing. 68 | * 69 | * The value is an index into the timers, and is 0 < x <= PF_MAX_TIMEOUTS when 70 | * the timer is running. The value is UINT32_MAX when it is stopped. 71 | * 72 | * @param handle InOut: Timeout handle. 73 | * @return the internal value (related to index in array of timeouts) 74 | */ 75 | uint32_t pf_scheduler_get_value (const pf_scheduler_handle_t * handle); 76 | 77 | /** 78 | * Report the name of a timeout handle. 79 | * 80 | * Intended for debugging and testing. 81 | * 82 | * @param handle InOut: Timeout handle. 83 | * @return the name given at initialization. 84 | */ 85 | const char * pf_scheduler_get_name (const pf_scheduler_handle_t * handle); 86 | 87 | /** 88 | * Schedule a call-back at a specific time. 89 | * 90 | * The callback must update the internal state stored in the handle. That is 91 | * done by calling \a pf_scheduler_reset_handle() or again calling 92 | * \ pf_scheduler_add(). 93 | * 94 | * @param net InOut: The p-net stack instance 95 | * @param delay In: The delay until the function shall be called, 96 | * in microseconds. Max 97 | * PF_SCHEDULER_MAX_DELAY_US. 98 | * @param cb In: The call-back. 99 | * @param arg In: Argument to the call-back. 100 | * @param handle InOut: Timeout handle. 101 | * @return 0 if the call-back was scheduled. 102 | * -1 if an error occurred. 103 | */ 104 | int pf_scheduler_add ( 105 | pnet_t * net, 106 | uint32_t delay, 107 | pf_scheduler_timeout_ftn_t cb, 108 | void * arg, 109 | pf_scheduler_handle_t * handle); 110 | 111 | /** 112 | * Re-schedule a call-back at a specific time. 113 | * 114 | * Removes the already scheduled instance, if existing. 115 | * 116 | * Do not use in a scheduler callback. 117 | * 118 | * @param net InOut: The p-net stack instance 119 | * @param delay In: The delay until the function shall be called, 120 | * in microseconds. Max 121 | * PF_SCHEDULER_MAX_DELAY_US. 122 | * @param cb In: The call-back. 123 | * @param arg In: Argument to the call-back. 124 | * @param handle InOut: Timeout handle. 125 | * @return 0 if the call-back was scheduled. 126 | * -1 if an error occurred. 127 | */ 128 | int pf_scheduler_restart ( 129 | pnet_t * net, 130 | uint32_t delay, 131 | pf_scheduler_timeout_ftn_t cb, 132 | void * arg, 133 | pf_scheduler_handle_t * handle); 134 | 135 | /** 136 | * Stop a timeout, if it is running. 137 | * 138 | * Silently ignoring the timeout if not running. 139 | * 140 | * @param net InOut: The p-net stack instance 141 | * @param handle InOut: Timeout handle. 142 | */ 143 | void pf_scheduler_remove_if_running ( 144 | pnet_t * net, 145 | pf_scheduler_handle_t * handle); 146 | 147 | /** 148 | * Stop a timeout. 149 | * @param net InOut: The p-net stack instance 150 | * @param handle InOut: Timeout handle. 151 | */ 152 | void pf_scheduler_remove (pnet_t * net, pf_scheduler_handle_t * handle); 153 | 154 | /** 155 | * Check if it is time to call a scheduled call-back. 156 | * Run scheduled call-backs - if any. 157 | * @param net InOut: The p-net stack instance 158 | */ 159 | void pf_scheduler_tick (pnet_t * net); 160 | 161 | /** 162 | * Show scheduler (busy and free) instances. 163 | * 164 | * Locks the mutex temporarily. 165 | * 166 | * @param net InOut: The p-net stack instance 167 | */ 168 | void pf_scheduler_show (pnet_t * net); 169 | 170 | /************ Internal functions, made available for unit testing ************/ 171 | 172 | uint32_t pf_scheduler_sanitize_delay ( 173 | uint32_t wanted_delay, 174 | uint32_t stack_cycle_time, 175 | bool schedule_half_tick_in_advance); 176 | 177 | #ifdef __cplusplus 178 | } 179 | #endif 180 | 181 | #endif /* PF_SCHEDULER_H */ 182 | -------------------------------------------------------------------------------- /src/common/pf_udp.c: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * _ _ _ 3 | * _ __ | |_ _ | | __ _ | |__ ___ 4 | * | '__|| __|(_)| | / _` || '_ \ / __| 5 | * | | | |_ _ | || (_| || |_) |\__ \ 6 | * |_| \__|(_)|_| \__,_||_.__/ |___/ 7 | * 8 | * www.rt-labs.com 9 | * Copyright 2018 rt-labs AB, Sweden. 10 | * 11 | * This software is dual-licensed under GPLv3 and a commercial 12 | * license. See the file LICENSE.md distributed with this software for 13 | * full license information. 14 | ********************************************************************/ 15 | 16 | /** 17 | * @file 18 | * @brief UDP communications 19 | */ 20 | 21 | #ifdef UNIT_TEST 22 | #define pnal_udp_close mock_pnal_udp_close 23 | #define pnal_udp_open mock_pnal_udp_open 24 | #define pnal_udp_recvfrom mock_pnal_udp_recvfrom 25 | #define pnal_udp_sendto mock_pnal_udp_sendto 26 | #endif 27 | 28 | #include 29 | #include "pf_includes.h" 30 | 31 | int pf_udp_open (pnet_t * net, pnal_ipport_t port) 32 | { 33 | return pnal_udp_open (PNAL_IPADDR_ANY, port); 34 | } 35 | 36 | int pf_udp_sendto ( 37 | pnet_t * net, 38 | uint32_t id, 39 | pnal_ipaddr_t dst_addr, 40 | pnal_ipport_t dst_port, 41 | const uint8_t * data, 42 | int size) 43 | { 44 | int sent_len = 0; 45 | 46 | sent_len = pnal_udp_sendto (id, dst_addr, dst_port, data, size); 47 | 48 | if (sent_len != size) 49 | { 50 | LOG_ERROR ( 51 | PNET_LOG, 52 | "UDP(%d): Failed to send %u UDP bytes payload on the socket.\n", 53 | __LINE__, 54 | size); 55 | } 56 | 57 | return sent_len; 58 | } 59 | 60 | int pf_udp_recvfrom ( 61 | pnet_t * net, 62 | uint32_t id, 63 | pnal_ipaddr_t * src_addr, 64 | pnal_ipport_t * src_port, 65 | uint8_t * data, 66 | int size) 67 | { 68 | return pnal_udp_recvfrom (id, src_addr, src_port, data, size); 69 | } 70 | 71 | void pf_udp_close (pnet_t * net, uint32_t id) 72 | { 73 | pnal_udp_close (id); 74 | } 75 | -------------------------------------------------------------------------------- /src/common/pf_udp.h: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * _ _ _ 3 | * _ __ | |_ _ | | __ _ | |__ ___ 4 | * | '__|| __|(_)| | / _` || '_ \ / __| 5 | * | | | |_ _ | || (_| || |_) |\__ \ 6 | * |_| \__|(_)|_| \__,_||_.__/ |___/ 7 | * 8 | * www.rt-labs.com 9 | * Copyright 2018 rt-labs AB, Sweden. 10 | * 11 | * This software is dual-licensed under GPLv3 and a commercial 12 | * license. See the file LICENSE.md distributed with this software for 13 | * full license information. 14 | ********************************************************************/ 15 | 16 | #ifndef PF_UDP_H 17 | #define PF_UDP_H 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | /** 24 | * Open an UDP socket. Listens to all IP addresses (PNAL_IPADDR_ANY). 25 | * 26 | * @param net InOut: The p-net stack instance 27 | * @param port In: UDP port to listen to. 28 | * @return Socket ID, or -1 if an error occurred. Note that socket ID 0 29 | * is valid. 30 | */ 31 | int pf_udp_open (pnet_t * net, pnal_ipport_t port); 32 | 33 | /** 34 | * Send UDP data 35 | * 36 | * @param net InOut: The p-net stack instance 37 | * @param id In: Socket ID 38 | * @param dst_addr In: Destination IP address 39 | * @param dst_port In: Destination UDP port 40 | * @param data In: Data to be sent 41 | * @param size In: Size of data 42 | * @return The number of bytes sent, or -1 if an error occurred. 43 | */ 44 | int pf_udp_sendto ( 45 | pnet_t * net, 46 | uint32_t id, 47 | pnal_ipaddr_t dst_addr, 48 | pnal_ipport_t dst_port, 49 | const uint8_t * data, 50 | int size); 51 | 52 | /** 53 | * Receive UDP data. 54 | * 55 | * This is a nonblocking function, and it 56 | * returns 0 immediately if no data is available. 57 | * 58 | * @param net InOut: The p-net stack instance 59 | * @param id In: Socket ID 60 | * @param dst_addr Out: Source IP address 61 | * @param dst_port Out: Source UDP port 62 | * @param data Out: Received data 63 | * @param size In: Size of buffer for received data 64 | * @return The number of bytes received, or -1 if an error occurred. 65 | */ 66 | int pf_udp_recvfrom ( 67 | pnet_t * net, 68 | uint32_t id, 69 | pnal_ipaddr_t * src_addr, 70 | pnal_ipport_t * src_port, 71 | uint8_t * data, 72 | int size); 73 | 74 | /** 75 | * Close an UDP socket. 76 | * 77 | * @param net InOut: The p-net stack instance 78 | * @param id In: Socket ID 79 | */ 80 | void pf_udp_close (pnet_t * net, uint32_t id); 81 | 82 | #ifdef __cplusplus 83 | } 84 | #endif 85 | 86 | #endif /* PF_UDP_H */ 87 | -------------------------------------------------------------------------------- /src/device/pf_cmdmc.c: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * _ _ _ 3 | * _ __ | |_ _ | | __ _ | |__ ___ 4 | * | '__|| __|(_)| | / _` || '_ \ / __| 5 | * | | | |_ _ | || (_| || |_) |\__ \ 6 | * |_| \__|(_)|_| \__,_||_.__/ |___/ 7 | * 8 | * www.rt-labs.com 9 | * Copyright 2018 rt-labs AB, Sweden. 10 | * 11 | * This software is dual-licensed under GPLv3 and a commercial 12 | * license. See the file LICENSE.md distributed with this software for 13 | * full license information. 14 | ********************************************************************/ 15 | 16 | #ifdef UNIT_TEST 17 | 18 | #endif 19 | 20 | #include "pf_includes.h" 21 | 22 | int pf_cmdmc_activate_req (pf_ar_t * p_ar) 23 | { 24 | return 0; 25 | } 26 | 27 | int pf_cmdmc_close_req (pf_ar_t * p_ar) 28 | { 29 | return 0; 30 | } 31 | 32 | int pf_cmdmc_cpm_state_ind (pf_ar_t * p_ar, uint16_t ix, bool start) 33 | { 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /src/device/pf_cmdmc.h: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * _ _ _ 3 | * _ __ | |_ _ | | __ _ | |__ ___ 4 | * | '__|| __|(_)| | / _` || '_ \ / __| 5 | * | | | |_ _ | || (_| || |_) |\__ \ 6 | * |_| \__|(_)|_| \__,_||_.__/ |___/ 7 | * 8 | * www.rt-labs.com 9 | * Copyright 2018 rt-labs AB, Sweden. 10 | * 11 | * This software is dual-licensed under GPLv3 and a commercial 12 | * license. See the file LICENSE.md distributed with this software for 13 | * full license information. 14 | ********************************************************************/ 15 | 16 | #ifndef PF_CMDMC_H 17 | #define PF_CMDMC_H 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | /** 24 | * ? 25 | * @param p_ar InOut: The AR instance. 26 | * @return 0 if operation succeeded. 27 | * -1 if an error occurred. 28 | */ 29 | int pf_cmdmc_activate_req (pf_ar_t * p_ar); 30 | 31 | /** 32 | * ? 33 | * @param p_ar InOut: The AR instance. 34 | * @return 0 if operation succeeded. 35 | * -1 if an error occurred. 36 | */ 37 | int pf_cmdmc_close_req (pf_ar_t * p_ar); 38 | 39 | /** 40 | * ? 41 | * @param p_ar InOut: The AR instance. 42 | * @param ix In: ? 43 | * @param start In: ? 44 | * @return 0 if operation succeeded. 45 | * -1 if an error occurred. 46 | */ 47 | int pf_cmdmc_cpm_state_ind (pf_ar_t * p_ar, uint16_t ix, bool start); 48 | 49 | #ifdef __cplusplus 50 | } 51 | #endif 52 | 53 | #endif /* PF_CMDMC_H */ 54 | -------------------------------------------------------------------------------- /src/device/pf_cmina.h: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * _ _ _ 3 | * _ __ | |_ _ | | __ _ | |__ ___ 4 | * | '__|| __|(_)| | / _` || '_ \ / __| 5 | * | | | |_ _ | || (_| || |_) |\__ \ 6 | * |_| \__|(_)|_| \__,_||_.__/ |___/ 7 | * 8 | * www.rt-labs.com 9 | * Copyright 2018 rt-labs AB, Sweden. 10 | * 11 | * This software is dual-licensed under GPLv3 and a commercial 12 | * license. See the file LICENSE.md distributed with this software for 13 | * full license information. 14 | ********************************************************************/ 15 | 16 | #ifndef PF_CMINA_H 17 | #define PF_CMINA_H 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | /** 24 | * Initialize the CMINA component. 25 | * 26 | * Sets the IP address if necessary. 27 | * 28 | * Schedules sending HELLO frames. 29 | * 30 | * @param net InOut: The p-net stack instance 31 | * @return 0 if the operation succeeded. 32 | * -1 if an error occurred. 33 | */ 34 | int pf_cmina_init (pnet_t * net); 35 | 36 | /** 37 | * Remove the stack's data files. 38 | * 39 | * @param file_directory In: File directory 40 | * @return 0 if the operation succeeded. 41 | * -1 if an error occurred. 42 | */ 43 | int pf_cmina_remove_all_data_files (const char * file_directory); 44 | 45 | /** 46 | * Show port statistics 47 | * 48 | * @param net InOut: The p-net stack instance 49 | */ 50 | void pf_cmina_port_statistics_show (pnet_t * net); 51 | 52 | /** 53 | * Show the CMINA status. 54 | * @param net InOut: The p-net stack instance 55 | */ 56 | void pf_cmina_show (pnet_t * net); 57 | 58 | /** 59 | * Convert IPv4 address to string 60 | * @param ip In: IP address 61 | * @param outputstring Out: Buffer with resulting string. Should have 62 | * size PNAL_INET_ADDRSTR_SIZE. 63 | */ 64 | void pf_cmina_ip_to_string (pnal_ipaddr_t ip, char * outputstring); 65 | 66 | /** 67 | * Retrieve the path to the directory for saving files. 68 | * @param net In: The p-net stack instance 69 | * @return the absolute path to the file directory. 70 | * Terminated string or NULL. 71 | */ 72 | const char * pf_cmina_get_file_directory (const pnet_t * net); 73 | 74 | /** 75 | * Retrieve the current station name of the device. 76 | * 77 | * TODO: Not yet thread safe. Fix this, e.g. using a mutex. 78 | * 79 | * @param net In: The p-net stack instance 80 | * @param station_name Out: Resulting string buffer with a terminated 81 | * string. Should have size 82 | * PNET_STATION_NAME_MAX_SIZE. 83 | */ 84 | void pf_cmina_get_station_name (const pnet_t * net, char * station_name); 85 | 86 | /** 87 | * Retrieve the current IP address of the device. 88 | * @param net In: The p-net stack instance 89 | * @return the ip_address. 90 | */ 91 | pnal_ipaddr_t pf_cmina_get_ipaddr (const pnet_t * net); 92 | 93 | /** 94 | * Retrieve the current netmask for the device. 95 | * @param net In: The p-net stack instance 96 | * @return the netmask 97 | */ 98 | pnal_ipaddr_t pf_cmina_get_netmask (const pnet_t * net); 99 | 100 | /** 101 | * Retrieve the gateway address. 102 | * @param net In: The p-net stack instance 103 | * @return the gateway address. 104 | */ 105 | pnal_ipaddr_t pf_cmina_get_gateway (const pnet_t * net); 106 | 107 | /** 108 | * Retrieve the device MAC address. 109 | * @param net In: The p-net stack instance 110 | * @return the MAC address 111 | */ 112 | const pnet_ethaddr_t * pf_cmina_get_device_macaddr (const pnet_t * net); 113 | 114 | /** 115 | * Save one block of data for incoming DCP set command. 116 | * 117 | * Triggers the \a pnet_reset_ind() callback for some incoming DCP set commands. 118 | * 119 | * @param net InOut: The p-net stack instance 120 | * @param opt In: The option key. 121 | * @param sub In: The sub-option key. 122 | * @param block_qualifier In: The block qualifier. 123 | * @param value_length In: The length of the data to set. 124 | * @param p_value In: The data to set. 125 | * @param p_block_error Out: The block error code, if any. 126 | * @return 0 if the operation succeeded. 127 | * -1 if an error occurred. 128 | */ 129 | int pf_cmina_dcp_set_ind ( 130 | pnet_t * net, 131 | uint8_t opt, 132 | uint8_t sub, 133 | uint16_t block_qualifier, 134 | uint16_t value_length, 135 | const uint8_t * p_value, 136 | uint8_t * p_block_error); 137 | 138 | /** 139 | * Reset the configuration to default values. 140 | * 141 | * Triggers the application callback \a pnet_reset_ind() for some \a reset_mode 142 | * values. 143 | * 144 | * Reset modes: 145 | * 146 | * 0: Power-on reset 147 | * 1: Reset application parameters 148 | * 2: Reset communication parameters 149 | * 99: Reset application and communication parameters. 150 | * 151 | * Populates net->cmina_nonvolatile_dcp_ase from file (and/or from default 152 | * configuration), and copies the resulting values to net->cmina_current_dcp_ase 153 | * 154 | * In order to actually change IP etc, the function pf_cmina_dcp_set_commit() 155 | * must be called afterwards. 156 | * 157 | * @param net InOut: The p-net stack instance 158 | * @param reset_mode In: Reset mode. 159 | * @return 0 if the operation succeeded. 160 | * -1 if an error occurred. 161 | */ 162 | int pf_cmina_set_default_cfg (pnet_t * net, uint16_t reset_mode); 163 | 164 | /** 165 | * Commit changes to the IP-suite. 166 | * 167 | * This shall be done _after_ the answer to DCP set has been sent. 168 | * @param net InOut: The p-net stack instance 169 | */ 170 | void pf_cmina_dcp_set_commit (pnet_t * net); 171 | 172 | /** 173 | * Find data and its size for use in one block in response to a DCP get command. 174 | * 175 | * Also used in DCP Hello and DCP Identify. 176 | * 177 | * @param net InOut: The p-net stack instance 178 | * @param opt In: The option key. 179 | * @param sub In: The sub-option key. 180 | * @param value_length In: The length of the pp_value buffer. 181 | * Out: The length of the read data. 182 | * @param pp_value Out: The retrieved data. 183 | * @param p_block_error Out: The block error code, if any. 184 | * @return 0 if the operation succeeded. 185 | * -1 if an error occurred. 186 | */ 187 | int pf_cmina_dcp_get_req ( 188 | pnet_t * net, 189 | uint8_t opt, 190 | uint8_t sub, 191 | uint16_t * p_value_length, 192 | uint8_t ** pp_value, 193 | uint8_t * p_block_error); 194 | 195 | /** 196 | * Check if a time interval has passed 197 | * 198 | * @param now_us In: Interval end in microseconds 199 | * @param previous_us In: Interval start in microseconds 200 | * @param period In: Time interval length in 1/32 of millisecond. 201 | * For 1 millisecond use 32 202 | * 2 milliseconds use 64 etc 203 | * @param factor In: Multiplication factor for the timeout. 204 | * Use 1 if the given time interval length should 205 | * be used, or 3 if we should return true after 206 | * 3 time interval lengths etc 207 | * @return true if the measured time interval is longer than period*factor 208 | * false if it not has passed 209 | */ 210 | bool pf_cmina_has_timed_out ( 211 | uint32_t now_us, 212 | uint32_t previous_us, 213 | uint16_t period, 214 | uint16_t factor); 215 | 216 | /** 217 | * Save the IP settings (and station name) to nonvolatile memory if necessary. 218 | * This is a blocking call intended to be executed by the background worker. 219 | * 220 | * Compares with the content of already stored settings (in order not to 221 | * wear out the flash chip) 222 | * 223 | * @param net InOut: The p-net stack instance 224 | * @param p_ase In: Settings to be saved 225 | */ 226 | void pf_cmina_save_ase (pnet_t * net, pf_cmina_dcp_ase_t * p_ase); 227 | 228 | /************ Internal functions, made available for unit testing ************/ 229 | 230 | bool pf_cmina_is_stationname_valid (const char * station_name, uint16_t len); 231 | 232 | bool pf_cmina_is_netmask_valid (pnal_ipaddr_t netmask); 233 | 234 | bool pf_cmina_is_ipaddress_valid (pnal_ipaddr_t netmask, pnal_ipaddr_t ip); 235 | 236 | bool pf_cmina_is_gateway_valid ( 237 | pnal_ipaddr_t ip, 238 | pnal_ipaddr_t netmask, 239 | pnal_ipaddr_t gateway); 240 | 241 | bool pf_cmina_is_ipsuite_valid (const pf_ip_suite_t * p_ipsuite); 242 | 243 | bool pf_cmina_is_full_ipsuite_valid (const pf_full_ip_suite_t * p_full_ipsuite); 244 | 245 | #ifdef __cplusplus 246 | } 247 | #endif 248 | 249 | #endif /* PF_CMINA_H */ 250 | -------------------------------------------------------------------------------- /src/device/pf_cmio.h: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * _ _ _ 3 | * _ __ | |_ _ | | __ _ | |__ ___ 4 | * | '__|| __|(_)| | / _` || '_ \ / __| 5 | * | | | |_ _ | || (_| || |_) |\__ \ 6 | * |_| \__|(_)|_| \__,_||_.__/ |___/ 7 | * 8 | * www.rt-labs.com 9 | * Copyright 2018 rt-labs AB, Sweden. 10 | * 11 | * This software is dual-licensed under GPLv3 and a commercial 12 | * license. See the file LICENSE.md distributed with this software for 13 | * full license information. 14 | ********************************************************************/ 15 | 16 | #ifndef PF_CMIO_H 17 | #define PF_CMIO_H 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | /** 24 | * Show CMIO information about an AR. 25 | * @param p_ar In: The AR instance. 26 | */ 27 | void pf_cmio_show (const pf_ar_t * p_ar); 28 | 29 | /** 30 | * Handle CMDEV events. 31 | * @param net InOut: The p-net stack instance 32 | * @param p_ar InOut: The AR instance. 33 | * @param event In: The new CMDEV state. Use PNET_EVENT_xxx, not 34 | * PF_CMDEV_STATE_xxx 35 | * @return 0 if the operation succeeded. 36 | * -1 if an error occurred. 37 | */ 38 | int pf_cmio_cmdev_state_ind ( 39 | pnet_t * net, 40 | pf_ar_t * p_ar, 41 | pnet_event_values_t event); 42 | 43 | /** 44 | * Handle CPM start/stop events of a specific AR. 45 | * @param net InOut: The p-net stack instance 46 | * @param p_ar InOut: The AR instance. 47 | * @param crep In: The IOCR instance. 48 | * @param start In: Start or Stop information. True if CPM is 49 | * starting. 50 | * @return 0 if the operation succeeded. 51 | * -1 if an error occurred. 52 | */ 53 | int pf_cmio_cpm_state_ind ( 54 | pnet_t * net, 55 | pf_ar_t * p_ar, 56 | uint16_t crep, 57 | bool start); 58 | 59 | /** 60 | * Handle CPM new data events of a specific AR. 61 | * @param p_ar InOut: The AR instance. 62 | * @param crep In: The IOCR instance. 63 | * @param new_data In: true => Data, false => NoData. 64 | * @return 0 if the operation succeeded. 65 | * -1 if an error occurred. 66 | */ 67 | int pf_cmio_cpm_new_data_ind (pf_ar_t * p_ar, uint16_t crep, bool new_data); 68 | 69 | #ifdef __cplusplus 70 | } 71 | #endif 72 | 73 | #endif /* PF_CMIO_H */ 74 | -------------------------------------------------------------------------------- /src/device/pf_cmpbe.c: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * _ _ _ 3 | * _ __ | |_ _ | | __ _ | |__ ___ 4 | * | '__|| __|(_)| | / _` || '_ \ / __| 5 | * | | | |_ _ | || (_| || |_) |\__ \ 6 | * |_| \__|(_)|_| \__,_||_.__/ |___/ 7 | * 8 | * www.rt-labs.com 9 | * Copyright 2018 rt-labs AB, Sweden. 10 | * 11 | * This software is dual-licensed under GPLv3 and a commercial 12 | * license. See the file LICENSE.md distributed with this software for 13 | * full license information. 14 | ********************************************************************/ 15 | 16 | /** 17 | * @file 18 | * @brief Implements the Parameter Begin End Protocol Machine (PBE) 19 | * 20 | * Disables and enables alarm sending. 21 | */ 22 | 23 | #ifdef UNIT_TEST 24 | 25 | #endif 26 | 27 | #include "pf_includes.h" 28 | 29 | /*************** Diagnostic strings *****************************************/ 30 | 31 | /** 32 | * @internal 33 | * Return a string representation of the CMPBE state. 34 | * @param state In: The state. 35 | * @return A string representation of the CMPBE state. 36 | */ 37 | static const char * pf_cmpbe_state_to_string (pf_cmpbe_state_values_t state) 38 | { 39 | const char * s = ""; 40 | switch (state) 41 | { 42 | case PF_CMPBE_STATE_IDLE: 43 | s = "PF_CMPBE_STATE_IDLE"; 44 | break; 45 | case PF_CMPBE_STATE_WFIND: 46 | s = "PF_CMPBE_STATE_WFIND"; 47 | break; 48 | case PF_CMPBE_STATE_WFRSP: 49 | s = "PF_CMPBE_STATE_WFRSP"; 50 | break; 51 | case PF_CMPBE_STATE_WFPEI: 52 | s = "PF_CMPBE_STATE_WFPEI"; 53 | break; 54 | case PF_CMPBE_STATE_WFPER: 55 | s = "PF_CMPBE_STATE_WFPER"; 56 | break; 57 | case PF_CMPBE_STATE_WFREQ: 58 | s = "PF_CMPBE_STATE_WFREQ"; 59 | break; 60 | case PF_CMPBE_STATE_WFCNF: 61 | s = "PF_CMPBE_STATE_WFCNF"; 62 | break; 63 | } 64 | 65 | return s; 66 | } 67 | 68 | void pf_cmpbe_show (const pf_ar_t * p_ar) 69 | { 70 | const char * s = pf_cmpbe_state_to_string (p_ar->cmpbe_state); 71 | 72 | printf ("CMPBE state = %s\n", s); 73 | printf (" stored command = %#x\n", p_ar->cmpbe_stored_command); 74 | } 75 | 76 | /****************************************************************************/ 77 | 78 | /** 79 | * @internal 80 | * Handle state changes in the CMPBE component. 81 | * @param p_ar InOut: The AR instance. 82 | * @param state In: The new state. 83 | */ 84 | static void pf_cmpbe_set_state (pf_ar_t * p_ar, pf_cmpbe_state_values_t state) 85 | { 86 | if (state != p_ar->cmpbe_state) 87 | { 88 | LOG_DEBUG ( 89 | PNET_LOG, 90 | "CMPBE(%d): New state %s for AREP %u (was %s)\n", 91 | __LINE__, 92 | pf_cmpbe_state_to_string (state), 93 | p_ar->arep, 94 | pf_cmpbe_state_to_string (p_ar->cmpbe_state)); 95 | } 96 | p_ar->cmpbe_state = state; 97 | } 98 | 99 | int pf_cmpbe_cmdev_state_ind (pf_ar_t * p_ar, pnet_event_values_t event) 100 | { 101 | LOG_DEBUG ( 102 | PNET_LOG, 103 | "CMPBE(%d): Received event %s from CMDEV. Initial state %s for AREP " 104 | "%u.\n", 105 | __LINE__, 106 | pf_cmdev_event_to_string (event), 107 | pf_cmpbe_state_to_string (p_ar->cmpbe_state), 108 | p_ar->arep); 109 | switch (p_ar->cmpbe_state) 110 | { 111 | case PF_CMPBE_STATE_IDLE: 112 | if (event == PNET_EVENT_DATA) 113 | { 114 | pf_cmpbe_set_state (p_ar, PF_CMPBE_STATE_WFIND); 115 | } 116 | else 117 | { 118 | /* Ignore and stay in state */ 119 | } 120 | break; 121 | case PF_CMPBE_STATE_WFRSP: 122 | case PF_CMPBE_STATE_WFIND: 123 | case PF_CMPBE_STATE_WFPEI: 124 | case PF_CMPBE_STATE_WFPER: 125 | case PF_CMPBE_STATE_WFREQ: 126 | case PF_CMPBE_STATE_WFCNF: 127 | if (event == PNET_EVENT_ABORT) 128 | { 129 | pf_cmpbe_set_state (p_ar, PF_CMPBE_STATE_IDLE); 130 | } 131 | break; 132 | } 133 | 134 | return 0; 135 | } 136 | 137 | int pf_cmpbe_rm_dcontrol_ind ( 138 | pnet_t * net, 139 | pf_ar_t * p_ar, 140 | pf_control_block_t * p_control_io, 141 | pnet_result_t * p_result) 142 | { 143 | int ret = -1; 144 | uint16_t temp_control_command; 145 | 146 | LOG_DEBUG ( 147 | PNET_LOG, 148 | "CMPBE(%d): Received DControl command bitfield 0x%04x for AREP %u. " 149 | "Initial state %s\n", 150 | __LINE__, 151 | p_control_io->control_command, 152 | p_ar->arep, 153 | pf_cmpbe_state_to_string (p_ar->cmpbe_state)); 154 | switch (p_ar->cmpbe_state) 155 | { 156 | case PF_CMPBE_STATE_IDLE: 157 | ret = 0; /* Ignore */ 158 | break; 159 | case PF_CMPBE_STATE_WFRSP: 160 | /* Is virtual state - see below! */ 161 | break; 162 | case PF_CMPBE_STATE_WFIND: 163 | if (p_ar->cmpbe_stored_command != 0) 164 | { 165 | /* Save */ 166 | temp_control_command = p_control_io->control_command; 167 | 168 | /* Issue stored control command */ 169 | p_control_io->control_command = p_ar->cmpbe_stored_command; 170 | p_ar->cmpbe_stored_command = 0; 171 | 172 | /* Only stored command is PNET_CONTROL_COMMAND_PRM_BEGIN */ 173 | if ( 174 | pf_fspm_cm_dcontrol_ind ( 175 | net, 176 | p_ar, 177 | PNET_CONTROL_COMMAND_PRM_BEGIN, 178 | p_result) == 0) 179 | { 180 | pf_cmpbe_set_state (p_ar, PF_CMPBE_STATE_WFRSP); 181 | /* cm_dcontrol_rsp() */ 182 | ret = 0; 183 | pf_cmpbe_set_state (p_ar, PF_CMPBE_STATE_WFPEI); 184 | } 185 | /* Restore */ 186 | p_control_io->control_command = temp_control_command; 187 | } 188 | else if ( 189 | p_control_io->control_command == 190 | BIT (PF_CONTROL_COMMAND_BIT_PRM_BEGIN)) 191 | { 192 | pf_alarm_disable (p_ar); 193 | ret = pf_fspm_cm_dcontrol_ind ( 194 | net, 195 | p_ar, 196 | PNET_CONTROL_COMMAND_PRM_BEGIN, 197 | p_result); 198 | pf_cmpbe_set_state (p_ar, PF_CMPBE_STATE_WFRSP); 199 | } 200 | break; 201 | case PF_CMPBE_STATE_WFPEI: 202 | if (p_control_io->control_command == BIT (PF_CONTROL_COMMAND_BIT_PRM_END)) 203 | { 204 | pf_fspm_cm_dcontrol_ind ( 205 | net, 206 | p_ar, 207 | PNET_CONTROL_COMMAND_PRM_END, 208 | p_result); 209 | pf_cmpbe_set_state (p_ar, PF_CMPBE_STATE_WFPER); 210 | /* cm_dcontrol_rsp() */ 211 | ret = 0; 212 | pf_cmpbe_set_state (p_ar, PF_CMPBE_STATE_WFREQ); 213 | } 214 | break; 215 | case PF_CMPBE_STATE_WFPER: 216 | if (p_control_io->control_command == BIT (PF_CONTROL_COMMAND_BIT_PRM_END)) 217 | { 218 | pf_cmpbe_set_state (p_ar, PF_CMPBE_STATE_WFREQ); 219 | ret = 0; 220 | } 221 | break; 222 | case PF_CMPBE_STATE_WFREQ: 223 | if (p_control_io->control_command == BIT (PF_CONTROL_COMMAND_BIT_PRM_BEGIN)) 224 | { 225 | /* Note: PrmEnd is handled by CMRPC as re-run. */ 226 | (void)pf_cmdev_state_ind (net, p_ar, PNET_EVENT_ABORT); 227 | pf_cmpbe_set_state (p_ar, PF_CMPBE_STATE_IDLE); 228 | } 229 | break; 230 | case PF_CMPBE_STATE_WFCNF: 231 | if (p_control_io->control_command == BIT (PF_CONTROL_COMMAND_BIT_PRM_BEGIN)) 232 | { 233 | p_ar->cmpbe_stored_command = p_control_io->control_command; 234 | } 235 | break; 236 | } 237 | 238 | return ret; 239 | } 240 | 241 | int pf_cmpbe_rm_ccontrol_cnf ( 242 | pf_ar_t * p_ar, 243 | const pf_control_block_t * p_control_io, 244 | pnet_result_t * p_result) 245 | { 246 | int ret = -1; 247 | 248 | if (p_ar->cmpbe_state == PF_CMPBE_STATE_WFCNF) 249 | { 250 | /* 251 | * The only expected bit is the DONE bit. 252 | * Assume it is the confirmation to the APPL_RDY ccontrol_req. 253 | */ 254 | if (p_control_io->control_command == BIT (PF_CONTROL_COMMAND_BIT_DONE)) 255 | { 256 | pf_alarm_enable (p_ar); 257 | pf_cmpbe_set_state (p_ar, PF_CMPBE_STATE_WFIND); 258 | ret = 0; 259 | } 260 | } 261 | else 262 | { 263 | ret = 0; /* Ignore */ 264 | } 265 | 266 | return ret; 267 | } 268 | 269 | /* Not used */ 270 | int pf_cmpbe_cm_ccontrol_req (pnet_t * net, pf_ar_t * p_ar) 271 | { 272 | int ret = -1; 273 | 274 | LOG_DEBUG ( 275 | PNET_LOG, 276 | "CMPBE(%d): ccontrol_req in state: %s\n", 277 | __LINE__, 278 | pf_cmpbe_state_to_string (p_ar->cmpbe_state)); 279 | 280 | if (p_ar->cmpbe_state == PF_CMPBE_STATE_WFREQ) 281 | { 282 | /* Control block is always APPLRDY here */ 283 | if (pf_alarm_pending (p_ar) == false) 284 | { 285 | ret = pf_cmrpc_rm_ccontrol_req (net, p_ar, PF_BT_APPRDY_REQ); 286 | pf_cmpbe_set_state (p_ar, PF_CMPBE_STATE_WFCNF); 287 | } 288 | } 289 | 290 | return ret; 291 | } 292 | -------------------------------------------------------------------------------- /src/device/pf_cmpbe.h: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * _ _ _ 3 | * _ __ | |_ _ | | __ _ | |__ ___ 4 | * | '__|| __|(_)| | / _` || '_ \ / __| 5 | * | | | |_ _ | || (_| || |_) |\__ \ 6 | * |_| \__|(_)|_| \__,_||_.__/ |___/ 7 | * 8 | * www.rt-labs.com 9 | * Copyright 2018 rt-labs AB, Sweden. 10 | * 11 | * This software is dual-licensed under GPLv3 and a commercial 12 | * license. See the file LICENSE.md distributed with this software for 13 | * full license information. 14 | ********************************************************************/ 15 | 16 | #ifndef PF_CMPBE_H 17 | #define PF_CMPBE_H 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | /** 24 | * Show CMPBE instance information about an AR. 25 | * @param p_ar In: The AR instance. 26 | */ 27 | void pf_cmpbe_show (const pf_ar_t * p_ar); 28 | 29 | /** 30 | * Handle CMDEV events. 31 | * @param p_ar InOut: The AR instance. 32 | * @param event In: The new CMDEV state. Use PNET_EVENT_xxx, not 33 | * PF_CMDEV_STATE_xxx 34 | * @return 0 if the operation succeeded. 35 | * -1 if an error occurred. 36 | */ 37 | int pf_cmpbe_cmdev_state_ind (pf_ar_t * p_ar, pnet_event_values_t event); 38 | 39 | /** 40 | * Handle a CControl request for a specific AR. 41 | * @param net InOut: The p-net stack instance 42 | * @param p_ar InOut: The AR instance. 43 | * @return 0 if the operation succeeded. 44 | * -1 if an error occurred. 45 | */ 46 | int pf_cmpbe_cm_ccontrol_req (pnet_t * net, pf_ar_t * p_ar); 47 | 48 | /** 49 | * Handle a CControl confirmation for a specific AR. 50 | * @param p_ar InOut: The AR instance. 51 | * @param p_control_io In: The CControl block. 52 | * @param p_result Out: The result information. Not used. 53 | * @return 0 if the operation succeeded. 54 | * -1 if an error occurred. 55 | */ 56 | int pf_cmpbe_rm_ccontrol_cnf ( 57 | pf_ar_t * p_ar, 58 | const pf_control_block_t * p_control_io, 59 | pnet_result_t * p_result); 60 | 61 | /** 62 | * Handle a DControl indication for a specific AR. 63 | * @param net InOut: The p-net stack instance 64 | * @param p_ar InOut: The AR instance. 65 | * @param p_control_io InOut: The DControl block. 66 | * @param p_result Out: The result information. 67 | * @return 0 if the operation succeeded. 68 | * -1 if an error occurred. 69 | */ 70 | int pf_cmpbe_rm_dcontrol_ind ( 71 | pnet_t * net, 72 | pf_ar_t * p_ar, 73 | pf_control_block_t * p_control_io, 74 | pnet_result_t * p_result); 75 | 76 | #ifdef __cplusplus 77 | } 78 | #endif 79 | 80 | #endif /* PF_CMPBE_H */ 81 | -------------------------------------------------------------------------------- /src/device/pf_cmrdr.h: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * _ _ _ 3 | * _ __ | |_ _ | | __ _ | |__ ___ 4 | * | '__|| __|(_)| | / _` || '_ \ / __| 5 | * | | | |_ _ | || (_| || |_) |\__ \ 6 | * |_| \__|(_)|_| \__,_||_.__/ |___/ 7 | * 8 | * www.rt-labs.com 9 | * Copyright 2018 rt-labs AB, Sweden. 10 | * 11 | * This software is dual-licensed under GPLv3 and a commercial 12 | * license. See the file LICENSE.md distributed with this software for 13 | * full license information. 14 | ********************************************************************/ 15 | 16 | #ifndef PF_CMRDR_H 17 | #define PF_CMRDR_H 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | /** 24 | * Handle a RPC read request. 25 | * Triggers the \a pnet_read_ind() user callback for some values. 26 | * 27 | * @param net InOut: The p-net stack instance 28 | * @param p_ar InOut: The AR instance. 29 | * @param p_read_request In: The read request. 30 | * @param p_read_status Out: The result information. 31 | * @param res_size In: The size of the output buffer. 32 | * @param p_res Out: The output buffer. 33 | * @param p_pos InOut: Position in the output buffer. 34 | * @return 0 if operation succeeded. 35 | * -1 if an error occurred. 36 | */ 37 | int pf_cmrdr_rm_read_ind ( 38 | pnet_t * net, 39 | pf_ar_t * p_ar, 40 | const pf_iod_read_request_t * p_read_request, 41 | pnet_result_t * p_read_status, 42 | uint16_t res_size, 43 | uint8_t * p_res, 44 | uint16_t * p_pos); 45 | 46 | /** 47 | * Describe an index on a subslot. 48 | * 49 | * @param index In: The index 50 | * @return a descriptive string. 51 | */ 52 | const char * pf_index_to_logstring (uint16_t index); 53 | 54 | #ifdef __cplusplus 55 | } 56 | #endif 57 | 58 | #endif /* PF_CMRDR_H */ 59 | -------------------------------------------------------------------------------- /src/device/pf_cmrpc.h: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * _ _ _ 3 | * _ __ | |_ _ | | __ _ | |__ ___ 4 | * | '__|| __|(_)| | / _` || '_ \ / __| 5 | * | | | |_ _ | || (_| || |_) |\__ \ 6 | * |_| \__|(_)|_| \__,_||_.__/ |___/ 7 | * 8 | * www.rt-labs.com 9 | * Copyright 2018 rt-labs AB, Sweden. 10 | * 11 | * This software is dual-licensed under GPLv3 and a commercial 12 | * license. See the file LICENSE.md distributed with this software for 13 | * full license information. 14 | ********************************************************************/ 15 | 16 | #ifndef PF_CMRPC_H 17 | #define PF_CMRPC_H 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | /* ================================================ 24 | * Local primitives 25 | */ 26 | 27 | /** 28 | * Initialize the CMRPC component. 29 | * 30 | * Opens the UDP socket for incoming RPC requests. 31 | * 32 | * @param net InOut: The p-net stack instance 33 | */ 34 | void pf_cmrpc_init (pnet_t * net); 35 | 36 | /** 37 | * Cleanup the CMRPC component. 38 | * @param net InOut: The p-net stack instance 39 | */ 40 | void pf_cmrpc_exit (pnet_t * net); 41 | 42 | /** 43 | * Handle periodic RPC tasks. 44 | * Check for DCE RPC requests. 45 | * Check for DCE RPC confirmations. 46 | * @param net InOut: The p-net stack instance 47 | */ 48 | void pf_cmrpc_periodic (pnet_t * net); 49 | 50 | /** 51 | * Find an AR by its AREP. 52 | * @param net InOut: The p-net stack instance 53 | * @param arep In: The AREP. 54 | * @param pp_ar Out: The AR (or NULL). 55 | * @return 0 if AR is found and valid. 56 | * -1 if AREP is invalid. 57 | */ 58 | int pf_ar_find_by_arep (pnet_t * net, uint32_t arep, pf_ar_t ** pp_ar); 59 | 60 | /** 61 | * Return pointer to specific AR. 62 | * @param net InOut: The p-net stack instance 63 | * @param ix In: The AR array index. 64 | * @return The AR instance. 65 | */ 66 | pf_ar_t * pf_ar_find_by_index (pnet_t * net, uint16_t ix); 67 | 68 | /** 69 | * Insert detailed error information into the result structure (of a session). 70 | * 71 | * If you need to set error information after some function has returned an 72 | * error (and possibly already has updated the error information), use 73 | * \a pf_set_error_if_not_already_set() instead. 74 | * 75 | * @param p_stat Out: The result structure. 76 | * @param code In: The error_code. 77 | * @param decode In: The error_decode. 78 | * @param code_1 In: The error_code_1. 79 | * @param code_2 In: The error_code_2. 80 | */ 81 | void pf_set_error ( 82 | pnet_result_t * p_stat, 83 | uint8_t code, 84 | uint8_t decode, 85 | uint8_t code_1, 86 | uint8_t code_2); 87 | 88 | /** 89 | * Insert detailed error information into the result structure (of a session). 90 | * Does not overwrite existing error information. 91 | * 92 | * This function is typically called after some other function has returned an 93 | * error and possibly have set an error code. 94 | * For other usecases, use pf_set_error() instead. 95 | * 96 | * @param p_stat Out: The result structure. 97 | * @param code In: The error_code. 98 | * @param decode In: The error_decode. 99 | * @param code_1 In: The error_code_1. 100 | * @param code_2 In: The error_code_2. 101 | */ 102 | void pf_set_error_if_not_already_set ( 103 | pnet_result_t * p_stat, 104 | uint8_t code, 105 | uint8_t decode, 106 | uint8_t code_1, 107 | uint8_t code_2); 108 | 109 | /** 110 | * Handle CMDEV events. 111 | * 112 | * For an ABORT event (given some conditions) the related sessions and the AR 113 | * are released, and the global RPC socket is re-opened. 114 | * 115 | * @param net InOut: The p-net stack instance 116 | * @param p_ar InOut: The AR instance. 117 | * @param event In: The new CMDEV state. Use PNET_EVENT_xxx, not 118 | * PF_CMDEV_STATE_xxx 119 | * @return 0 if operation succeeded. 120 | * -1 if an error occurred. 121 | */ 122 | int pf_cmrpc_cmdev_state_ind ( 123 | pnet_t * net, 124 | pf_ar_t * p_ar, 125 | pnet_event_values_t event); 126 | 127 | /** 128 | * Send a DCE RPC request to the controller. 129 | * The only request handled is the CControl (APPL_RDY) request. 130 | * 131 | * Opens a new UDP socket for the session. 132 | * 133 | * @param net InOut: The p-net stack instance 134 | * @param p_ar InOut: The AR instance. 135 | * @param block_type In: The block type, depending on 136 | * the parameterisation sequence. 137 | * @return 0 if operation succeeded. 138 | * -1 if an error occurred. 139 | */ 140 | int pf_cmrpc_rm_ccontrol_req ( 141 | pnet_t * net, 142 | pf_ar_t * p_ar, 143 | pf_block_type_values_t block_type); 144 | 145 | /** 146 | * Show AR and session information. 147 | * 148 | * Use level 0xFFFF to show everything. 149 | * 150 | * @param net InOut: The p-net stack instance 151 | * @param level In: Level of detail. 152 | */ 153 | void pf_cmrpc_show (pnet_t * net, unsigned level); 154 | 155 | /************************* Utilities ******************************************/ 156 | 157 | /** 158 | * Display buffer contents 159 | * 160 | * For example: 161 | * 162 | * uint8_t mybuffer[18] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 163 | * 'K', 'L', 0, 1, 2, 3, 4, 5}; pf_memory_contents_show(mybuffer, 18); 164 | * 165 | * will be displayed as: 166 | * 167 | * 41 42 43 44 45 46 47 48 49 4a 4b 4c 00 01 02 03 |ABCDEFGHIJKL....| 168 | * 04 05 |..| 169 | * 170 | * @param data In: Buffer contents to be displayed 171 | * @param size In: Buffer size (or smaller, to only display the 172 | * beginning) 173 | */ 174 | void pf_memory_contents_show (const uint8_t * data, int size); 175 | 176 | /* Exported for testing only */ 177 | int pf_cmrpc_dce_packet ( 178 | pnet_t * net, 179 | uint32_t ip_addr, 180 | uint16_t port, 181 | const uint8_t * p_req, 182 | uint32_t req_len, 183 | uint8_t * p_res, 184 | uint16_t * p_res_len, 185 | bool * p_close_socket); 186 | 187 | #ifdef __cplusplus 188 | } 189 | #endif 190 | 191 | #endif /* PF_CMRPC_H */ 192 | -------------------------------------------------------------------------------- /src/device/pf_cmrpc_epm.h: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * _ _ _ 3 | * _ __ | |_ _ | | __ _ | |__ ___ 4 | * | '__|| __|(_)| | / _` || '_ \ / __| 5 | * | | | |_ _ | || (_| || |_) |\__ \ 6 | * |_| \__|(_)|_| \__,_||_.__/ |___/ 7 | * 8 | * www.rt-labs.com 9 | * Copyright 2018 rt-labs AB, Sweden. 10 | * 11 | * This software is dual-licensed under GPLv3 and a commercial 12 | * license. See the file LICENSE.md distributed with this software for 13 | * full license information. 14 | ********************************************************************/ 15 | 16 | #ifndef PF_CMRPC_EPM_H 17 | #define PF_CMRPC_EPM_H 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | /** 24 | * Handle rpc lookup request 25 | * @param net InOut: The p-net stack instance 26 | * @param p_sess InOut: Rpc session handle 27 | * @param p_rpc_req In: Rpc header. 28 | * @param p_lookup_req In: Lookup request. 29 | * @param p_read_status Out: Read pnio status 30 | * @param res_size In: The size of the output buffer. 31 | * @param p_res Out: The output buffer. 32 | * @param p_pos InOut: Position in the output buffer. 33 | * @return 0 if operation succeeded. 34 | * -1 if an error occurred. 35 | */ 36 | int pf_cmrpc_lookup_request ( 37 | pnet_t * net, 38 | pf_session_info_t * p_sess, 39 | const pf_rpc_header_t * p_rpc_req, 40 | const pf_rpc_lookup_req_t * p_lookup_req, 41 | pnet_result_t * p_read_status, 42 | uint16_t res_size, 43 | uint8_t * p_res, 44 | uint16_t * p_pos); 45 | 46 | #ifdef __cplusplus 47 | } 48 | #endif 49 | 50 | #endif /* PF_CMRPC_HELPERS_H */ 51 | -------------------------------------------------------------------------------- /src/device/pf_cmrpc_helpers.c: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * _ _ _ 3 | * _ __ | |_ _ | | __ _ | |__ ___ 4 | * | '__|| __|(_)| | / _` || '_ \ / __| 5 | * | | | |_ _ | || (_| || |_) |\__ \ 6 | * |_| \__|(_)|_| \__,_||_.__/ |___/ 7 | * 8 | * www.rt-labs.com 9 | * Copyright 2018 rt-labs AB, Sweden. 10 | * 11 | * This software is dual-licensed under GPLv3 and a commercial 12 | * license. See the file LICENSE.md distributed with this software for 13 | * full license information. 14 | ********************************************************************/ 15 | 16 | /** 17 | * @file 18 | * @brief Helper functions for CMRPC 19 | * 20 | * Located in a separate file to enabling mocking during tests. 21 | * 22 | */ 23 | 24 | #include "pf_includes.h" 25 | 26 | /** 27 | * @internal 28 | * Generate an UUID, inspired by version 1, variant 1 29 | * 30 | * See RFC 4122 31 | * 32 | * @param timestamp In: Some kind of timestamp 33 | * @param session_number In: Session number 34 | * @param mac_address In: MAC address 35 | * @param p_uuid Out: The generated UUID 36 | */ 37 | void pf_generate_uuid ( 38 | uint32_t timestamp, 39 | uint32_t session_number, 40 | pnet_ethaddr_t mac_address, 41 | pf_uuid_t * p_uuid) 42 | { 43 | /* TODO Maybe we should take pointer to mac address instead, to avoid 44 | copying? */ 45 | p_uuid->data1 = timestamp; 46 | p_uuid->data2 = session_number >> 16; 47 | p_uuid->data3 = (session_number >> 8) & 0x00ff; 48 | p_uuid->data3 |= 1 << 12; /* UUID version 1 */ 49 | p_uuid->data4[0] = 0x80; /* UUID variant 1 */ 50 | p_uuid->data4[1] = session_number & 0xff; 51 | p_uuid->data4[2] = mac_address.addr[0]; 52 | p_uuid->data4[3] = mac_address.addr[1]; 53 | p_uuid->data4[4] = mac_address.addr[2]; 54 | p_uuid->data4[5] = mac_address.addr[3]; 55 | p_uuid->data4[6] = mac_address.addr[4]; 56 | p_uuid->data4[7] = mac_address.addr[5]; 57 | } 58 | -------------------------------------------------------------------------------- /src/device/pf_cmrpc_helpers.h: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * _ _ _ 3 | * _ __ | |_ _ | | __ _ | |__ ___ 4 | * | '__|| __|(_)| | / _` || '_ \ / __| 5 | * | | | |_ _ | || (_| || |_) |\__ \ 6 | * |_| \__|(_)|_| \__,_||_.__/ |___/ 7 | * 8 | * www.rt-labs.com 9 | * Copyright 2018 rt-labs AB, Sweden. 10 | * 11 | * This software is dual-licensed under GPLv3 and a commercial 12 | * license. See the file LICENSE.md distributed with this software for 13 | * full license information. 14 | ********************************************************************/ 15 | 16 | #ifndef PF_CMRPC_HELPERS_H 17 | #define PF_CMRPC_HELPERS_H 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | /************ Internal functions, made available for unit testing ************/ 24 | 25 | void pf_generate_uuid ( 26 | uint32_t timestamp, 27 | uint32_t session_number, 28 | pnet_ethaddr_t mac_address, 29 | pf_uuid_t * p_uuid); 30 | 31 | #ifdef __cplusplus 32 | } 33 | #endif 34 | 35 | #endif /* PF_CMRPC_HELPERS_H */ 36 | -------------------------------------------------------------------------------- /src/device/pf_cmrs.c: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * _ _ _ 3 | * _ __ | |_ _ | | __ _ | |__ ___ 4 | * | '__|| __|(_)| | / _` || '_ \ / __| 5 | * | | | |_ _ | || (_| || |_) |\__ \ 6 | * |_| \__|(_)|_| \__,_||_.__/ |___/ 7 | * 8 | * www.rt-labs.com 9 | * Copyright 2018 rt-labs AB, Sweden. 10 | * 11 | * This software is dual-licensed under GPLv3 and a commercial 12 | * license. See the file LICENSE.md distributed with this software for 13 | * full license information. 14 | ********************************************************************/ 15 | 16 | #ifdef UNIT_TEST 17 | 18 | #endif 19 | 20 | #include "pf_includes.h" 21 | -------------------------------------------------------------------------------- /src/device/pf_cmrs.h: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * _ _ _ 3 | * _ __ | |_ _ | | __ _ | |__ ___ 4 | * | '__|| __|(_)| | / _` || '_ \ / __| 5 | * | | | |_ _ | || (_| || |_) |\__ \ 6 | * |_| \__|(_)|_| \__,_||_.__/ |___/ 7 | * 8 | * www.rt-labs.com 9 | * Copyright 2018 rt-labs AB, Sweden. 10 | * 11 | * This software is dual-licensed under GPLv3 and a commercial 12 | * license. See the file LICENSE.md distributed with this software for 13 | * full license information. 14 | ********************************************************************/ 15 | 16 | #ifndef PF_CMRS_H 17 | #define PF_CMRS_H 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | #ifdef __cplusplus 24 | } 25 | #endif 26 | 27 | #endif /* PF_CMRS_H */ 28 | -------------------------------------------------------------------------------- /src/device/pf_cmsm.h: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * _ _ _ 3 | * _ __ | |_ _ | | __ _ | |__ ___ 4 | * | '__|| __|(_)| | / _` || '_ \ / __| 5 | * | | | |_ _ | || (_| || |_) |\__ \ 6 | * |_| \__|(_)|_| \__,_||_.__/ |___/ 7 | * 8 | * www.rt-labs.com 9 | * Copyright 2018 rt-labs AB, Sweden. 10 | * 11 | * This software is dual-licensed under GPLv3 and a commercial 12 | * license. See the file LICENSE.md distributed with this software for 13 | * full license information. 14 | ********************************************************************/ 15 | 16 | #ifndef PF_CMSM_H 17 | #define PF_CMSM_H 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | /** 24 | * Initialize the CMSM-specific parts of an AR 25 | * @param p_ar In: The AR instance (not NULL) 26 | * @return 0 if the operation succeeded. 27 | * -1 if an error occurred. 28 | */ 29 | int pf_cmsm_activate (pf_ar_t * p_ar); 30 | 31 | /** 32 | * Handle incoming CMDEV events. 33 | * @param net InOut: The p-net stack instance 34 | * @param p_ar InOut: The AR instance, or NULL. 35 | * @param event In: The new CMDEV state. Use PNET_EVENT_xxx, not 36 | * PF_CMDEV_STATE_xxx 37 | * @return 0 if the operation succeeded. 38 | * -1 if an error occurred. 39 | */ 40 | int pf_cmsm_cmdev_state_ind ( 41 | pnet_t * net, 42 | pf_ar_t * p_ar, 43 | pnet_event_values_t event); 44 | 45 | /** 46 | * Handle incoming RPC read requests, by restarting the timer if running. 47 | * Only if index is PF_IDX_DEV_CONN_MON_TRIGGER 48 | * 49 | * @param net InOut: The p-net stack instance 50 | * @param p_ar InOut: The AR instance, or NULL. 51 | * @param p_read_request In: The read request. 52 | * @return 0 if the operation succeeded. 53 | * -1 if an error occurred. 54 | */ 55 | int pf_cmsm_rm_read_ind ( 56 | pnet_t * net, 57 | pf_ar_t * p_ar, 58 | pf_iod_read_request_t * p_read_request); 59 | 60 | /** 61 | * Handle incoming RPC read requests, by restarting the timer if running. 62 | * @param net InOut: The p-net stack instance 63 | * @param p_ar InOut: The AR instance, or NULL. 64 | * @param p_read_request In: The read request. not used. 65 | * @return 0 if the operation succeeded. 66 | * -1 if an error occurred. 67 | */ 68 | int pf_cmsm_cm_read_ind ( 69 | pnet_t * net, 70 | pf_ar_t * p_ar, 71 | const pf_iod_read_request_t * p_read_request); 72 | 73 | /** 74 | * Handle incoming RPC write requests, by restarting the timer if running. 75 | * @param net InOut: The p-net stack instance 76 | * @param p_ar InOut: The AR instance, or NULL. 77 | * @param p_write_request In: The write request. Not used. 78 | * @return 0 if the operation succeeded. 79 | * -1 if an error occurred. 80 | */ 81 | int pf_cmsm_cm_write_ind ( 82 | pnet_t * net, 83 | pf_ar_t * p_ar, 84 | const pf_iod_write_request_t * p_write_request); 85 | 86 | /** 87 | * Print information about CMSM for the specified AR. 88 | * @param p_ar In: The AR instance, or NULL. 89 | */ 90 | void pf_cmsm_show (const pf_ar_t * p_ar); 91 | 92 | #ifdef __cplusplus 93 | } 94 | #endif 95 | 96 | #endif /* PF_CMSM_H */ 97 | -------------------------------------------------------------------------------- /src/device/pf_cmsu.h: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * _ _ _ 3 | * _ __ | |_ _ | | __ _ | |__ ___ 4 | * | '__|| __|(_)| | / _` || '_ \ / __| 5 | * | | | |_ _ | || (_| || |_) |\__ \ 6 | * |_| \__|(_)|_| \__,_||_.__/ |___/ 7 | * 8 | * www.rt-labs.com 9 | * Copyright 2018 rt-labs AB, Sweden. 10 | * 11 | * This software is dual-licensed under GPLv3 and a commercial 12 | * license. See the file LICENSE.md distributed with this software for 13 | * full license information. 14 | ********************************************************************/ 15 | 16 | #ifndef PF_CMSU_H 17 | #define PF_CMSU_H 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | /** 24 | * Initialize the CMSU component. 25 | * @param net InOut: The p-net stack instance 26 | * @param p_ar InOut: The AR instance. 27 | */ 28 | void pf_cmsu_init (pnet_t * net, pf_ar_t * p_ar); 29 | 30 | /** 31 | * Handle CMDEV events. 32 | * 33 | * Can close CPM and PPM instances. Closes alarm instance, which triggers an 34 | * alarm. 35 | * 36 | * @param net InOut: The p-net stack instance 37 | * @param p_ar InOut: The AR instance. 38 | * @param event In: The new CMDEV state. Use PNET_EVENT_xxx, not 39 | * PF_CMDEV_STATE_xxx 40 | * @return 0 if the operation succeeded. 41 | * -1 if an error occurred. 42 | */ 43 | int pf_cmsu_cmdev_state_ind ( 44 | pnet_t * net, 45 | pf_ar_t * p_ar, 46 | pnet_event_values_t event); 47 | 48 | /** 49 | * Start all state machines for a specific AR. 50 | * @param net InOut: The p-net stack instance 51 | * @param p_ar InOut: The AR instance. 52 | * @param p_stat Out: Detailed error info if returning != 0 53 | * Note that only the fields error_code_1 and 54 | * error_code_2 are set. 55 | * @return 0 if the operation succeeded. 56 | * -1 if an error occurred. 57 | */ 58 | int pf_cmsu_start_req (pnet_t * net, pf_ar_t * p_ar, pnet_result_t * p_stat); 59 | 60 | /** 61 | * Handle CPM error indications for a specific AR. 62 | * 63 | * Closes the AR with PNET_EVENT_ABORT 64 | * 65 | * @param net InOut: The p-net stack instance 66 | * @param p_ar InOut: The AR instance. 67 | * @param err_cls In: ERR_CLS. ErrorCode1. 68 | * @param err_code In: ERR_CODE. ErrorCode2. 69 | * @return 0 if the operation succeeded. 70 | * -1 if an error occurred. 71 | */ 72 | int pf_cmsu_cpm_error_ind ( 73 | pnet_t * net, 74 | pf_ar_t * p_ar, 75 | uint8_t err_cls, 76 | uint8_t err_code); 77 | 78 | /** 79 | * Handle PPM error indications for a specific AR. 80 | * 81 | * Closes the AR with PNET_EVENT_ABORT 82 | * 83 | * @param net InOut: The p-net stack instance 84 | * @param p_ar InOut: The AR instance. 85 | * @param err_cls In: ERR_CLS. ErrorCode1. 86 | * @param err_code In: ERR_CODE. ErrorCode2. 87 | * @return 0 if the operation succeeded. 88 | * -1 if an error occurred. 89 | */ 90 | int pf_cmsu_ppm_error_ind ( 91 | pnet_t * net, 92 | pf_ar_t * p_ar, 93 | uint8_t err_cls, 94 | uint8_t err_code); 95 | 96 | /** 97 | * Handle alarm error indications for a specific AR. 98 | * 99 | * Closes the AR with PNET_EVENT_ABORT 100 | * 101 | * @param net InOut: The p-net stack instance 102 | * @param p_ar InOut: The AR instance. 103 | * @param err_cls In: ERR_CLS. ErrorCode1. 104 | * @param err_code In: ERR_CODE. ErrorCode2. 105 | * @return 0 if the operation succeeded. 106 | * -1 if an error occurred. 107 | */ 108 | int pf_cmsu_alarm_error_ind ( 109 | pnet_t * net, 110 | pf_ar_t * p_ar, 111 | uint8_t err_cls, 112 | uint8_t err_code); 113 | 114 | /* Not used */ 115 | /** 116 | * Handle DMC error indications for a specific AR. 117 | * 118 | * Closes the AR with PNET_EVENT_ABORT 119 | * 120 | * @param net InOut: The p-net stack instance 121 | * @param p_ar InOut: The AR instance. 122 | * @param err_cls In: ERR_CLS. ErrorCode1. 123 | * @param err_code In: ERR_CODE. ErrorCode2. 124 | * @return 0 if the operation succeeded. 125 | * -1 if an error occurred. 126 | */ 127 | int pf_cmsu_cmdmc_error_ind ( 128 | pnet_t * net, 129 | pf_ar_t * p_ar, 130 | uint8_t err_cls, 131 | uint8_t err_code); 132 | 133 | #ifdef __cplusplus 134 | } 135 | #endif 136 | 137 | #endif /* PF_CMSU_H */ 138 | -------------------------------------------------------------------------------- /src/device/pf_cmwrr.h: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * _ _ _ 3 | * _ __ | |_ _ | | __ _ | |__ ___ 4 | * | '__|| __|(_)| | / _` || '_ \ / __| 5 | * | | | |_ _ | || (_| || |_) |\__ \ 6 | * |_| \__|(_)|_| \__,_||_.__/ |___/ 7 | * 8 | * www.rt-labs.com 9 | * Copyright 2018 rt-labs AB, Sweden. 10 | * 11 | * This software is dual-licensed under GPLv3 and a commercial 12 | * license. See the file LICENSE.md distributed with this software for 13 | * full license information. 14 | ********************************************************************/ 15 | 16 | #ifndef PF_CMWRR_H 17 | #define PF_CMWRR_H 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | /** 24 | * Initialize the CMWRR component. 25 | * @param net InOut: The p-net stack instance 26 | */ 27 | void pf_cmwrr_init (pnet_t * net, pf_ar_t * p_ar); 28 | 29 | /** 30 | * Show the CMWRR part of the specified AR. 31 | * @param net InOut: The p-net stack instance 32 | * @param p_ar In: The AR instance. 33 | */ 34 | void pf_cmwrr_show (const pnet_t * net, const pf_ar_t * p_ar); 35 | 36 | /** 37 | * Handle CMDEV events. 38 | * @param net InOut: The p-net stack instance 39 | * @param p_ar In: The AR instance. Not used, 40 | * @param event In: The new CMDEV state. Use PNET_EVENT_xxx, not 41 | * PF_CMDEV_STATE_xxx 42 | * @return 0 if operation succeeded. 43 | * -1 if an error occurred. 44 | */ 45 | int pf_cmwrr_cmdev_state_ind ( 46 | pnet_t * net, 47 | pf_ar_t * p_ar, 48 | pnet_event_values_t event); 49 | 50 | /** 51 | * Handle RPC write requests. 52 | * 53 | * If the state is correct, it will trigger pf_cmwrr_write() 54 | * 55 | * Triggers the \a pnet_write_ind() user callback for some values. 56 | * 57 | * @param net InOut: The p-net stack instance 58 | * @param p_ar InOut: The AR instance. 59 | * @param p_write_request In: The write request block. 60 | * @param p_write_result Out: The write result block. 61 | * @param p_result Out: Detailed error information if returning != 0 62 | * @param p_req_buf In: The RPC request buffer. 63 | * @param data_length In: The length of the data to write. 64 | * @param p_req_pos In: Position in p_req_buf. 65 | * @return 0 if operation succeeded. 66 | * -1 if an error occurred. 67 | */ 68 | int pf_cmwrr_rm_write_ind ( 69 | pnet_t * net, 70 | pf_ar_t * p_ar, 71 | const pf_iod_write_request_t * p_write_request, 72 | pf_iod_write_result_t * p_write_result, 73 | pnet_result_t * p_result, 74 | const uint8_t * p_req_buf, 75 | uint16_t data_length, 76 | uint16_t * p_req_pos); 77 | 78 | #ifdef __cplusplus 79 | } 80 | #endif 81 | 82 | #endif /* PF_CMWRR_H */ 83 | -------------------------------------------------------------------------------- /src/device/pf_pdport.h: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * _ _ _ 3 | * _ __ | |_ _ | | __ _ | |__ ___ 4 | * | '__|| __|(_)| | / _` || '_ \ / __| 5 | * | | | |_ _ | || (_| || |_) |\__ \ 6 | * |_| \__|(_)|_| \__,_||_.__/ |___/ 7 | * 8 | * www.rt-labs.com 9 | * Copyright 2018 rt-labs AB, Sweden. 10 | * 11 | * This software is dual-licensed under GPLv3 and a commercial 12 | * license. See the file LICENSE.md distributed with this software for 13 | * full license information. 14 | ********************************************************************/ 15 | 16 | #ifndef PF_PDPORT_H 17 | #define PF_PDPORT_H 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | #include 24 | 25 | /** 26 | * Initialize PDPort. 27 | * Load PDPortport configuration from nvm. 28 | * 29 | * @param net InOut: The p-net stack instance 30 | * @return 0 if the operation succeeded. 31 | * -1 if not found or an error occurred 32 | */ 33 | int pf_pdport_init (pnet_t * net); 34 | 35 | /** 36 | * Reset PDPort configuration data for all ports. 37 | * Clear PDPort configuration in nvm. 38 | * Remove all active diagnostics items related to PDPort. 39 | * 40 | * @param net InOut: The p-net stack instance 41 | * @return 0 if the operation succeeded. 42 | * -1 if not found or an error occurred 43 | */ 44 | int pf_pdport_reset_all (pnet_t * net); 45 | 46 | /** 47 | * Remove configuration files for all ports. 48 | * 49 | * @param * @param file_directory In: File directory 50 | */ 51 | void pf_pdport_remove_data_files (const char * file_directory); 52 | 53 | /** 54 | * Notify PDPort that a new AR has been set up. 55 | * @param net InOut: The p-net stack instance 56 | * @param p_ar In: The AR instance. 57 | */ 58 | void pf_pdport_ar_connect_ind (pnet_t * net, const pf_ar_t * p_ar); 59 | 60 | /** 61 | * Restart LLDP transmission 62 | * 63 | * The current PDPort port adjustments is checked. 64 | * @param net InOut: The p-net stack instance 65 | */ 66 | void pf_pdport_lldp_restart_transmission (pnet_t * net); 67 | 68 | /** 69 | * Read a PDPort data record/index 70 | * Record to read defined by index in request 71 | * Parse request and write response to output buffer. 72 | * The following indexes are supported: 73 | * - PF_IDX_SUB_PDPORT_DATA_REAL 74 | * - PF_IDX_SUB_PDPORT_DATA_ADJ 75 | * - PF_IDX_SUB_PDPORT_DATA_CHECK 76 | * - PF_IDX_DEV_PDREAL_DATA 77 | * - PF_IDX_DEV_PDEXP_DATA 78 | * - PF_IDX_SUB_PDPORT_STATISTIC 79 | * 80 | * @param net InOut: The p-net stack instance 81 | * @param p_ar InOut: The AR instance. 82 | * @param p_read_req In: The read request. 83 | * @param p_read_res In: The result information. 84 | * @param res_size In: The size of the output buffer. 85 | * @param p_res Out: The output buffer. 86 | * @param p_pos InOut: Position in the output buffer. 87 | * @return 0 if operation succeeded. 88 | * -1 if an error occurred. 89 | */ 90 | int pf_pdport_read_ind ( 91 | pnet_t * net, 92 | pf_ar_t * p_ar, 93 | const pf_iod_read_request_t * p_read_req, 94 | const pf_iod_read_result_t * p_read_res, 95 | uint16_t res_size, 96 | uint8_t * p_res, 97 | uint16_t * p_pos); 98 | 99 | /** 100 | * Write a PDPort data record/index 101 | * Record to write defined by index in request 102 | * The following indexes are supported: 103 | * - PF_IDX_SUB_PDPORT_DATA_REAL 104 | * - PF_IDX_SUB_PDPORT_DATA_ADJ 105 | * - PF_IDX_SUB_PDPORT_DATA_CHECK 106 | * - PF_IDX_DEV_PDREAL_DATA 107 | * - PF_IDX_DEV_PDEXP_DATA 108 | * - PF_IDX_SUB_PDPORT_STATISTIC 109 | * 110 | * @param net InOut: The p-net stack instance 111 | * @param p_ar In: The AR instance. 112 | * @param p_write_req In: The IODWrite request. 113 | * @param p_req_buf In: The request buffer. 114 | * @param data_length In: Size of the data to write. 115 | * @param p_result Out: Detailed error information. 116 | * @return 0 if operation succeeded. 117 | * -1 if an error occurred. 118 | */ 119 | int pf_pdport_write_req ( 120 | pnet_t * net, 121 | const pf_ar_t * p_ar, 122 | const pf_iod_write_request_t * p_write_req, 123 | const uint8_t * p_req_buf, 124 | uint16_t data_length, 125 | pnet_result_t * p_result); 126 | 127 | /** 128 | * Notify PDPort that the LLDP peer information has changed. 129 | * 130 | * PDPort will later verify that correct peer is connected to the port. 131 | * 132 | * @param net InOut: The p-net stack instance 133 | * @param loc_port_num In: Local port number. 134 | * Valid range: 1 .. num_physical_ports 135 | */ 136 | void pf_pdport_peer_indication (pnet_t * net, int loc_port_num); 137 | 138 | /** 139 | * Start Ethernet link monitoring 140 | * 141 | * @param net InOut: The p-net stack instance 142 | */ 143 | void pf_pdport_start_linkmonitor (pnet_t * net); 144 | 145 | /** 146 | * Run PDPort observers. 147 | * Run enabled checks and set diagnoses. 148 | * 149 | * @param net InOut: The p-net stack instance 150 | */ 151 | void pf_pdport_periodic (pnet_t * net); 152 | 153 | /** 154 | * Save PDPort configuration to NVM for all ports. 155 | * This function is intended to be executed in the background task, 156 | * as the system calls to save files may be blocking. 157 | * 158 | * @param net InOut: The p-net stack instance 159 | * @return 0 if operation succeeded. 160 | * -1 if an error occurred. 161 | */ 162 | int pf_pdport_save_all (pnet_t * net); 163 | 164 | /** 165 | * Verify that at least one operational port has a speed of at 166 | * least 100 MBit/s, full duplex. 167 | * 168 | * Otherwise we should refuse to make a connection. 169 | * 170 | * To support the special case of devices with 10 Mbit/s, this function must be 171 | * modified. 172 | * 173 | * See PdevCheckFailed() in Profinet 2.4 Protocol 5.6.3.2.1.4 CMDEV state table 174 | * 175 | * @param net InOut: The p-net stack instance 176 | * @return true if at least one port has the required speed, else false. 177 | */ 178 | bool pf_pdport_is_a_fast_port_in_use (pnet_t * net); 179 | 180 | /** 181 | * Update the ethernet status for all ports. 182 | * This function is intended to be executed in a background task, 183 | * as the system calls to read the ethernet status may be blocking. 184 | * 185 | * @param net InOut: The p-net stack instance 186 | */ 187 | void pf_pdport_update_eth_status (pnet_t * net); 188 | 189 | /** 190 | * Get current ethernet status for local port. 191 | * This is a non-blocking function reading from mutex-protected memory. 192 | * The status values are updated by the background worker task 193 | * in a periodic job executing the pf_pdport_update_eth_status() function. 194 | * 195 | * @param net InOut: The p-net stack instance 196 | * @param loc_port_num In: Local port number. 197 | * Valid range: 1 .. num_physical_ports 198 | * @return The ethernet status for local port 199 | */ 200 | pnal_eth_status_t pf_pdport_get_eth_status (pnet_t * net, int loc_port_num); 201 | 202 | /** 203 | * Get current ethernet status for local port. 204 | * This is a non-blocking function reading from mutex-protected memory. 205 | * The status values are updated by the background worker task 206 | * in a periodic job executing the pf_pdport_update_eth_status() function. 207 | * 208 | * The MAU type value in the resulting \a pnal_eth_status_t struct 209 | * will be replaced by the default MAU type from the configuration 210 | * when the link is down (and the actual MAU type not can be read from 211 | * hardware). 212 | * 213 | * @param net InOut: The p-net stack instance 214 | * @param loc_port_num In: Local port number. 215 | * Valid range: 1 .. num_physical_ports 216 | * @return The ethernet status for local port 217 | */ 218 | pnal_eth_status_t pf_pdport_get_eth_status_filtered_mau ( 219 | pnet_t * net, 220 | int loc_port_num); 221 | 222 | #ifdef __cplusplus 223 | } 224 | #endif 225 | 226 | #endif /* PF_PDPORT_H */ 227 | -------------------------------------------------------------------------------- /src/device/pf_plugsm.c: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * _ _ _ 3 | * _ __ | |_ _ | | __ _ | |__ ___ 4 | * | '__|| __|(_)| | / _` || '_ \ / __| 5 | * | | | |_ _ | || (_| || |_) |\__ \ 6 | * |_| \__|(_)|_| \__,_||_.__/ |___/ 7 | * 8 | * www.rt-labs.com 9 | * Copyright 2023 rt-labs AB, Sweden. 10 | * 11 | * This software is dual-licensed under GPLv3 and a commercial 12 | * license. See the file LICENSE.md distributed with this software for 13 | * full license information. 14 | ********************************************************************/ 15 | 16 | /** 17 | * @file 18 | * @brief Implements the Plug State Machine (PLUGSM) 19 | * 20 | * This is a partial implementation of PLUGSM, to handle the release of 21 | * submodules when more than one AR is allowed, i.e. when shared device is 22 | * supported. 23 | */ 24 | 25 | #include "pf_includes.h" 26 | #include 27 | 28 | void pf_plugsm_released_alarm_req ( 29 | pnet_t * net, 30 | pf_ar_t * ar, 31 | uint32_t api, 32 | uint16_t slot_number, 33 | uint16_t subslot_number, 34 | uint32_t module_ident, 35 | uint32_t submodule_ident) 36 | { 37 | pf_ar_plug_t * plug; 38 | uint16_t i; 39 | 40 | plug = &ar->plug_info; 41 | if (plug->count >= PF_AR_PLUG_MAX_QUEUE) 42 | { 43 | LOG_ERROR ( 44 | PNET_LOG, 45 | "PLUGSM(%d): Queue is full for AREP %d\n", 46 | __LINE__, 47 | ar->arep); 48 | } 49 | else 50 | { 51 | i = plug->current + plug->count; 52 | if (i >= PF_AR_PLUG_MAX_QUEUE) 53 | { 54 | i -= PF_AR_PLUG_MAX_QUEUE; 55 | } 56 | plug->queue[i].api = api; 57 | plug->queue[i].slot_number = slot_number; 58 | plug->queue[i].subslot_number = subslot_number; 59 | plug->queue[i].module_ident = module_ident; 60 | plug->queue[i].submodule_ident = submodule_ident; 61 | ++plug->count; 62 | 63 | LOG_DEBUG ( 64 | PNET_LOG, 65 | "PLUGSM(%d): Queued released alarm.\n" 66 | " AREP: %" PRIu16 ", API: %" PRIu32 ", Slot: 0x%" PRIx16 67 | ", Subslot: 0x%" PRIx16 "\n", 68 | __LINE__, 69 | ar->arep, 70 | api, 71 | slot_number, 72 | subslot_number); 73 | } 74 | if (plug->state == PF_PLUGSM_STATE_IDLE) 75 | { 76 | plug->state = PF_PLUGSM_STATE_WFPRMIND; 77 | 78 | LOG_DEBUG ( 79 | PNET_LOG, 80 | "PLUGSM(%d): Sending released alarm to controller.\n" 81 | " AREP: %" PRIu16 ", API: %" PRIu32 ", Slot: 0x%" PRIx16 82 | ", Subslot: 0x%" PRIx16 "\n", 83 | __LINE__, 84 | ar->arep, 85 | plug->queue[plug->current].api, 86 | plug->queue[plug->current].slot_number, 87 | plug->queue[plug->current].subslot_number); 88 | 89 | pf_alarm_send_released ( 90 | net, 91 | ar, 92 | plug->queue[plug->current].api, 93 | plug->queue[plug->current].slot_number, 94 | plug->queue[plug->current].subslot_number, 95 | plug->queue[plug->current].module_ident, 96 | plug->queue[plug->current].submodule_ident); 97 | } 98 | } 99 | 100 | int pf_plugsm_prmend_ind (pnet_t * net, pf_ar_t * ar, pnet_result_t * result) 101 | { 102 | int ret; 103 | pf_ar_plug_t * plug; 104 | 105 | ret = 0; 106 | plug = &ar->plug_info; 107 | if (plug->state == PF_PLUGSM_STATE_WFPRMIND) 108 | { 109 | if (net->fspm_cfg.sm_released_cb != NULL) 110 | { 111 | LOG_DEBUG ( 112 | PNET_LOG, 113 | "PLUGSM(%d): Triggering sm_released callback for AREP %u\n", 114 | __LINE__, 115 | ar->arep); 116 | 117 | ret = net->fspm_cfg.sm_released_cb ( 118 | net, 119 | net->fspm_cfg.cb_arg, 120 | ar->arep, 121 | plug->queue[plug->current].api, 122 | plug->queue[plug->current].slot_number, 123 | plug->queue[plug->current].subslot_number, 124 | result); 125 | } 126 | else 127 | { 128 | LOG_DEBUG ( 129 | PNET_LOG, 130 | "FSPM(%d): No user callback for sm_released implemented.\n", 131 | __LINE__); 132 | } 133 | 134 | if (ret == 0) 135 | { 136 | plug->state = PF_PLUGSM_STATE_WFDATAUPDATE; 137 | } 138 | else 139 | { 140 | plug->state = PF_PLUGSM_STATE_WFAPLRDYCNF; 141 | pf_plugsm_application_ready_cnf (net, ar); 142 | } 143 | } 144 | 145 | return ret; 146 | } 147 | 148 | void pf_plugsm_application_ready_req (pnet_t * net, pf_ar_t * ar) 149 | { 150 | pf_ar_plug_t * plug; 151 | 152 | plug = &ar->plug_info; 153 | if (plug->state == PF_PLUGSM_STATE_WFDATAUPDATE) 154 | { 155 | plug->state = PF_PLUGSM_STATE_WFAPLRDYCNF; 156 | 157 | LOG_DEBUG ( 158 | PNET_LOG, 159 | "PLUGSM(%d): Sending application ready to controller.\n" 160 | " AREP: %" PRIu16 ", API: %" PRIu32 ", Slot: 0x%" PRIx16 161 | ", Subslot: 0x%" PRIx16 "\n", 162 | __LINE__, 163 | ar->arep, 164 | plug->queue[plug->current].api, 165 | plug->queue[plug->current].slot_number, 166 | plug->queue[plug->current].subslot_number); 167 | 168 | pf_cmdev_generate_submodule_diff ( 169 | net, 170 | ar, 171 | plug->queue[plug->current].api, 172 | plug->queue[plug->current].slot_number, 173 | plug->queue[plug->current].subslot_number); 174 | 175 | pf_cmrpc_rm_ccontrol_req (net, ar, PF_BT_APPRDY_PLUG_ALARM_REQ); 176 | } 177 | } 178 | 179 | int pf_plugsm_application_ready_cnf (pnet_t * net, pf_ar_t * ar) 180 | { 181 | pf_ar_plug_t * plug; 182 | 183 | plug = &ar->plug_info; 184 | if (plug->state == PF_PLUGSM_STATE_WFAPLRDYCNF) 185 | { 186 | LOG_DEBUG ( 187 | PNET_LOG, 188 | "PLUGSM(%d): Application ready confirmed by controller.\n" 189 | " AREP: %" PRIu16 ", API: %" PRIu32 ", Slot: 0x%" PRIx16 190 | ", Subslot: 0x%" PRIx16 "\n", 191 | __LINE__, 192 | ar->arep, 193 | plug->queue[plug->current].api, 194 | plug->queue[plug->current].slot_number, 195 | plug->queue[plug->current].subslot_number); 196 | 197 | --plug->count; 198 | ++plug->current; 199 | if (plug->current >= PF_AR_PLUG_MAX_QUEUE) 200 | { 201 | plug->current = 0; 202 | } 203 | if (plug->count > 0) 204 | { 205 | plug->state = PF_PLUGSM_STATE_WFPRMIND; 206 | 207 | LOG_DEBUG ( 208 | PNET_LOG, 209 | "PLUGSM(%d): Sending released alarm to controller.\n" 210 | " AREP: %" PRIu16 ", API: %" PRIu32 ", Slot: 0x%" PRIx16 211 | ", Subslot: 0x%" PRIx16 "\n", 212 | __LINE__, 213 | ar->arep, 214 | plug->queue[plug->current].api, 215 | plug->queue[plug->current].slot_number, 216 | plug->queue[plug->current].subslot_number); 217 | 218 | pf_alarm_send_released ( 219 | net, 220 | ar, 221 | plug->queue[plug->current].api, 222 | plug->queue[plug->current].slot_number, 223 | plug->queue[plug->current].subslot_number, 224 | plug->queue[plug->current].module_ident, 225 | plug->queue[plug->current].submodule_ident); 226 | } 227 | else 228 | { 229 | plug->state = PF_PLUGSM_STATE_IDLE; 230 | } 231 | } 232 | return 0; 233 | } 234 | -------------------------------------------------------------------------------- /src/device/pf_plugsm.h: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * _ _ _ 3 | * _ __ | |_ _ | | __ _ | |__ ___ 4 | * | '__|| __|(_)| | / _` || '_ \ / __| 5 | * | | | |_ _ | || (_| || |_) |\__ \ 6 | * |_| \__|(_)|_| \__,_||_.__/ |___/ 7 | * 8 | * www.rt-labs.com 9 | * Copyright 2023 rt-labs AB, Sweden. 10 | * 11 | * This software is dual-licensed under GPLv3 and a commercial 12 | * license. See the file LICENSE.md distributed with this software for 13 | * full license information. 14 | ********************************************************************/ 15 | 16 | /** 17 | * @file 18 | * @brief Partial implementation of the Plug State Machine (PLUGSM) 19 | * 20 | * These functions implement the subset of the PLUGSM state machine (see 21 | * Profinet 2.4 services, section 7.3.2.2.6.2.4) that deals with submodules 22 | * being released by an AR, when it is released. A released submodule may get 23 | * a new owning AR, the controller side of which is expected to go through a 24 | * parameterisation sequence, before the ownership is finalised. 25 | */ 26 | 27 | #ifndef PF_PLUGSM_H 28 | #define PF_PLUGSM_H 29 | 30 | #ifdef __cplusplus 31 | extern "C" { 32 | #endif 33 | 34 | /** 35 | * Request a Released alarm to be sent for a submodule to a controller through 36 | * a specific AR. 37 | * 38 | * The request is queued up for the AR in question. If the queue is empty at 39 | * the time of calling this function, the request is acted upon immediately. 40 | * 41 | * @param net InOut: The p-net stack instance. 42 | * @param ar InOut: The AR instance. 43 | * @param api In: The API containing the submodule. 44 | * @param slot_number In: The slot containing the submodule. 45 | * @param subslot_number In: The subslot containing the submodule. 46 | * @param module_ident In: The identification of the module. 47 | * @param submodule_ident In: The identification of the submodule. 48 | */ 49 | void pf_plugsm_released_alarm_req ( 50 | pnet_t * net, 51 | pf_ar_t * ar, 52 | uint32_t api, 53 | uint16_t slot_number, 54 | uint16_t subslot_number, 55 | uint32_t module_ident, 56 | uint32_t submodule_ident); 57 | 58 | /** 59 | * Handle the PrmEnd request sent by a controller as a result of a submodule 60 | * being released. 61 | * 62 | * This will call the \a pnet_sm_released_ind() callback registered by the 63 | * application, and act according to its return value: either record that the 64 | * application is expected to call \a pnet_sm_released_cnf(), or activate the 65 | * next request for a Released alarm from the same AR. 66 | * 67 | * @param net InOut: The p-net stack instance. 68 | * @param ar InOut: The AR instance. 69 | * @param result Out: Detailed error information if return != 0; 70 | * @return 0 on success. 71 | * -1 on failure. 72 | */ 73 | int pf_plugsm_prmend_ind ( 74 | pnet_t * net, 75 | pf_ar_t * ar, 76 | pnet_result_t * result); 77 | 78 | /** 79 | * Send an Application Ready request to the controller, after an AR to it has 80 | * become the new owner of a released submodule. 81 | * 82 | * This will be called indirectly by the application, when it calls \a 83 | * pnet_sm_released_cnf() to confirm that it has handled a released submodule. 84 | * 85 | * @param net InOut: The p-net stack instance. 86 | * @param ar InOut: The AR instance. 87 | */ 88 | void pf_plugsm_application_ready_req (pnet_t * net, pf_ar_t * ar); 89 | 90 | /** 91 | * Handle the Application Ready confirmation sent by a controller, after an AR 92 | * to it has become the new owner of a released submodule. 93 | * 94 | * This will check the queue of Released alarm requests, and act on the first 95 | * request in the queue, if there is one. 96 | * 97 | * @param net InOut: The p-net stack instance. 98 | * @param ar InOut: The AR instance. 99 | * @return 0 on success. 100 | * -1 on failure. 101 | */ 102 | int pf_plugsm_application_ready_cnf (pnet_t * net, pf_ar_t * ar); 103 | 104 | #ifdef __cplusplus 105 | } 106 | #endif 107 | 108 | #endif /* PF_PLUGSM_H */ 109 | -------------------------------------------------------------------------------- /src/device/pf_port.h: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * _ _ _ 3 | * _ __ | |_ _ | | __ _ | |__ ___ 4 | * | '__|| __|(_)| | / _` || '_ \ / __| 5 | * | | | |_ _ | || (_| || |_) |\__ \ 6 | * |_| \__|(_)|_| \__,_||_.__/ |___/ 7 | * 8 | * www.rt-labs.com 9 | * Copyright 2020 rt-labs AB, Sweden. 10 | * 11 | * This software is dual-licensed under GPLv3 and a commercial 12 | * license. See the file LICENSE.md distributed with this software for 13 | * full license information. 14 | ********************************************************************/ 15 | 16 | #ifndef PF_PORT_H 17 | #define PF_PORT_H 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | /** 24 | * Init port data 25 | * 26 | * @param net In: The p-net stack instance. 27 | */ 28 | void pf_port_init (pnet_t * net); 29 | 30 | /** 31 | * Init main interface data, and schedule Ethernet link monitoring 32 | * 33 | * @param net In: The p-net stack instance. 34 | */ 35 | void pf_port_main_interface_init (pnet_t * net); 36 | 37 | /** 38 | * Get number of physical ports. 39 | * 40 | * @param net In: The p-net stack instance. 41 | * @return the number of physical ports. 42 | */ 43 | uint8_t pf_port_get_number_of_ports (const pnet_t * net); 44 | 45 | /** 46 | * Get list of local ports. 47 | * 48 | * This is the list of physical ports on the local interface. 49 | * The management port is not included. 50 | * 51 | * @param net In: The p-net stack instance. 52 | * @param p_list Out: List of local ports. 53 | */ 54 | void pf_port_get_list_of_ports ( 55 | const pnet_t * net, 56 | pf_lldp_port_list_t * p_list); 57 | 58 | /** 59 | * Initialise iterator for iterating over local ports. 60 | * 61 | * This iterator may be used for iterating over all physical ports 62 | * on the local interface. The management port is not included. 63 | * See pf_port_get_next(). 64 | * 65 | * @param net In: The p-net stack instance. 66 | * @param p_iterator Out: Port iterator. 67 | */ 68 | void pf_port_init_iterator_over_ports ( 69 | const pnet_t * net, 70 | pf_port_iterator_t * p_iterator); 71 | 72 | /** 73 | * Get next local port. 74 | * 75 | * If no more ports are available, 0 is returned. 76 | * 77 | * Will return: 1 2 3 ... num_physical_ports 0 0 0 78 | * 79 | * @param p_iterator InOut: Port iterator. 80 | * @return Local port number for next port on local interface. 81 | * If no more ports are available, 0 is returned. 82 | */ 83 | int pf_port_get_next (pf_port_iterator_t * p_iterator); 84 | 85 | /** 86 | * Get next local port, over and over again. 87 | * 88 | * After highest port number has been returned, next time 1 will be returned 89 | * (and then 2 etc) 90 | * 91 | * Will return: 1 2 3 ... num_physical_ports 1 2 3 ... etc 92 | * 93 | * @param p_iterator InOut: Port iterator. 94 | * @return Local port number for next port on local interface. 95 | */ 96 | int pf_port_get_next_repeat_cyclic (pf_port_iterator_t * p_iterator); 97 | 98 | /** 99 | * Get DAP port subslot using local port number 100 | * 101 | * If the local port number is out of range this operation will assert. 102 | * 103 | * @param net In: The p-net stack instance 104 | * @param loc_port_num In: Local port number. 105 | * Valid range: 1 .. num_physical_ports 106 | * @return DAP subslot number for port identity 107 | */ 108 | uint16_t pf_port_loc_port_num_to_dap_subslot ( 109 | const pnet_t * net, 110 | int loc_port_num); 111 | 112 | /** 113 | * Check if a DAP port subslot is mapped to a local port 114 | * 115 | * @param net In: The p-net stack instance 116 | * @param subslot In: Subslot number 117 | * @return true if the subslot is mapped to a local port. 118 | * false if the subslot is not supported. 119 | */ 120 | bool pf_port_subslot_is_dap_port_id (const pnet_t * net, uint16_t subslot); 121 | 122 | /** 123 | * Get local port from DAP port subslot 124 | * 125 | * @param net In: The p-net stack instance 126 | * @param subslot In: Subslot number 127 | * @return The port number mapping to the subslot. 128 | * 0 if the subslot is not supported. 129 | */ 130 | int pf_port_dap_subslot_to_local_port (const pnet_t * net, uint16_t subslot); 131 | 132 | /** 133 | * Get port runtime data. 134 | * 135 | * If the local port number is out of range this operation will assert. 136 | * NULL will never be returned. 137 | * 138 | * See also \a pf_port_get_config() for configuration of the port. 139 | * 140 | * @param net In: The p-net stack instance 141 | * @param loc_port_num In: Local port number. 142 | * Valid range: 1 .. num_physical_ports 143 | * @return port runtime data 144 | */ 145 | pf_port_t * pf_port_get_state (pnet_t * net, int loc_port_num); 146 | 147 | /** 148 | * Get port configuration. 149 | * 150 | * If the local port number is out of range this operation will assert. 151 | * NULL will never be returned. 152 | * 153 | * See also \a pf_port_get_state() for port runtime data. 154 | * 155 | * @param net In: The p-net stack instance 156 | * @param loc_port_num In: Local port number. 157 | * Valid range: 1 .. num_physical_ports 158 | * @return port configuration 159 | */ 160 | const pnet_port_cfg_t * pf_port_get_config (pnet_t * net, int loc_port_num); 161 | 162 | /** 163 | * Check if port number corresponds to a valid physical port. 164 | * 165 | * @param net In: The p-net stack instance 166 | * @param loc_port_num In: Local port number. 167 | * Valid range: 1 .. num_physical_ports 168 | * @return true if port number is valid, 169 | * false if not 170 | */ 171 | bool pf_port_is_valid (const pnet_t * net, int loc_port_num); 172 | 173 | /** 174 | * Get port number for network interface. If network interface 175 | * is not a physical port, zero is returned. 176 | * 177 | * @param net In: The p-net stack instance. 178 | * @param eth_handle In: Network interface handle. 179 | * @return local port number 180 | * 0 if no local port matches the network interface handle 181 | */ 182 | int pf_port_get_port_number (const pnet_t * net, pnal_eth_handle_t * eth_handle); 183 | 184 | /** 185 | * Decode media type from Ethernet MAU type. 186 | * Media types listed in PN-AL-protocol (Mar20) Table 727. 187 | * 188 | * The MAU type 0 represents "unknown" when the link is down. 189 | * When the link is up a MAU type 0 represents "Radio". 190 | * 191 | * This function assumes that the link is up. Make sure you use 192 | * some default MAU type if the link is down, before using this function. 193 | * 194 | * @param mau_type In: Ethernet MAU type 195 | * @return media type 196 | */ 197 | pf_mediatype_values_t pf_port_get_media_type (pnal_eth_mau_t mau_type); 198 | 199 | /** 200 | * Show port details 201 | * 202 | * @param net InOut: The p-net stack instance 203 | */ 204 | void pf_port_show (pnet_t * net); 205 | 206 | #ifdef __cplusplus 207 | } 208 | #endif 209 | 210 | #endif /* PF_PORT_H */ 211 | -------------------------------------------------------------------------------- /src/drivers/lan9662/add_inbound_vcap_rule.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ############################################# 3 | # Add vcap rule for inbound data / outgoing cyclic frames 4 | # 5 | # Definitions: 6 | # VLAN_ID :== VLAN ID 7 | # DMAC :== xx:xx:xx:xx:xx:xx 8 | # RT_VLAN_IDX :== 0..7 9 | # PRIORITY :== 0..0xffff 10 | # VCAM_HANDLE :== 0..0xffffffff 11 | # RT_FRMID :== 0..0xffff 12 | # RTP_ID :== 0..0x1f 13 | # RTP_SUBID :== 0..1 14 | # RTE_INB_UPD :== 1 for inbound RTE processing, 0 otherwise 15 | 16 | #set -x 17 | 18 | PRIORITY=10 19 | VCAM_HANDLE=$1 20 | VLAN_ID=$2 21 | DMAC=$3 22 | RT_VLAN_IDX=$4 23 | 24 | RT_FRMID=$5 25 | RTP_ID=$6 26 | RTP_SUBID=0 27 | RTE_INB_UPD=1 28 | 29 | COMMAND="vcap add $VCAM_HANDLE is1 $PRIORITY 0 \ 30 | VCAP_KFS_RT L2_MAC $DMAC ff:ff:ff:ff:ff:ff \ 31 | RT_VLAN_IDX $RT_VLAN_IDX 0x7 RT_FRMID $RT_FRMID 0xffff \ 32 | VCAP_AFS_S1_RT RTP_ID $RTP_ID RTP_SUBID $RTP_SUBID \ 33 | RTE_INB_UPD $RTE_INB_UPD FWD_ENA 1 FWD_MASK 0x10" 34 | 35 | echo "$COMMAND" 36 | if ! $COMMAND; then 37 | echo "Failed adding vcap rule for inbound data" 38 | exit 1 39 | fi 40 | 41 | exit 0 42 | -------------------------------------------------------------------------------- /src/drivers/lan9662/add_outbound_vcap_rule.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ############################################ 4 | # Add vcap rule for outbound data / incoming cyclic frames 5 | # 6 | # Definitions: 7 | # VLAN_ID :== VLAN ID 8 | # RT_VLAN_IDX :== 0..7 9 | # PRIORITY :== 0..0xffff 10 | # VCAM_HANDLE :== 0..0xffffffff 11 | # RT_FRMID :== 0..0xffff 12 | # RTP_ID :== 0..0x1f 13 | # RTP_SUBID :== 0..1 14 | # RTE_INB_UPD :== 1 for inbound RTE processing, 0 otherwise 15 | 16 | # set -x 17 | 18 | PRIORITY=10 19 | VCAM_HANDLE=$1 20 | VLAN_ID=$2 21 | RT_VLAN_IDX=$3 22 | 23 | RT_FRMID=$4 24 | RTP_ID=$5 25 | DMAC=$6 26 | 27 | # Enable untagged RTP processing 28 | symreg ana_rt_vlan_pcp[$RT_VLAN_IDX].pcp_mask 0xff # Wildcard on pcp value 29 | symreg ana_rt_vlan_pcp[$RT_VLAN_IDX].vlan_id $VLAN_ID # Actual vid 30 | symreg ana_rt_vlan_pcp[$RT_VLAN_IDX].vlan_pcp_ena 1 # Enable entry 31 | 32 | COMMAND="vcap add $VCAM_HANDLE is1 $PRIORITY 0 \ 33 | VCAP_KFS_RT \ 34 | RT_VLAN_IDX $RT_VLAN_IDX 0x7 \ 35 | L2_MAC $DMAC ff:ff:ff:ff:ff:ff \ 36 | RT_TYPE 1 0x3 \ 37 | RT_FRMID $RT_FRMID 0xffff \ 38 | VCAP_AFS_S1_RT RTP_ID $RTP_ID \ 39 | FWD_ENA 1 FWD_MASK 0x10" 40 | 41 | echo "$COMMAND" 42 | if ! $COMMAND; then 43 | echo "Failed adding vcam rule for inbound data" 44 | exit 1 45 | fi 46 | 47 | exit 0 48 | -------------------------------------------------------------------------------- /src/drivers/lan9662/del_vcap_rule.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ############################################ 4 | # Delete vcap rule 5 | # 6 | 7 | #set -x 8 | 9 | PRIORITY=10 10 | VCAM_HANDLE=$1 11 | 12 | COMMAND="vcap del $VCAM_HANDLE" 13 | 14 | echo "$COMMAND" 15 | if ! $COMMAND; then 16 | echo "Failed to delete vcap rule" 17 | exit 1 18 | fi 19 | 20 | exit 0 21 | -------------------------------------------------------------------------------- /src/drivers/lan9662/include/driver_config.h: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * _ _ _ 3 | * _ __ | |_ _ | | __ _ | |__ ___ 4 | * | '__|| __|(_)| | / _` || '_ \ / __| 5 | * | | | |_ _ | || (_| || |_) |\__ \ 6 | * |_| \__|(_)|_| \__,_||_.__/ |___/ 7 | * 8 | * www.rt-labs.com 9 | * Copyright 2022 rt-labs AB, Sweden. 10 | * 11 | * This software is dual-licensed under GPLv3 and a commercial 12 | * license. See the file LICENSE.md distributed with this software for 13 | * full license information. 14 | ********************************************************************/ 15 | 16 | /** 17 | * @file 18 | * @brief LAN9662-specific configuration 19 | * 20 | * This file contains definitions of configuration settings for the 21 | * LAN9662 driver. 22 | */ 23 | 24 | #ifndef DRIVER_CONFIG_H 25 | #define DRIVER_CONFIG_H 26 | 27 | #ifdef __cplusplus 28 | extern "C" { 29 | #endif 30 | 31 | #include "pnet_driver_options.h" 32 | 33 | typedef struct pnet_driver_config 34 | { 35 | struct 36 | { 37 | uint16_t vcam_base_id; 38 | uint16_t rtp_base_id; 39 | uint16_t wal_base_id; 40 | uint16_t ral_base_id; 41 | } mera; 42 | 43 | } pnet_driver_config_t; 44 | 45 | #ifdef __cplusplus 46 | } 47 | #endif 48 | 49 | #endif /* DRIVER_CONFIG_H */ -------------------------------------------------------------------------------- /src/drivers/lan9662/include/pnet_lan9662_api.h: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * _ _ _ 3 | * _ __ | |_ _ | | __ _ | |__ ___ 4 | * | '__|| __|(_)| | / _` || '_ \ / __| 5 | * | | | |_ _ | || (_| || |_) |\__ \ 6 | * |_| \__|(_)|_| \__,_||_.__/ |___/ 7 | * 8 | * www.rt-labs.com 9 | * Copyright 2021 rt-labs AB, Sweden. 10 | * 11 | * This software is dual-licensed under GPLv3 and a commercial 12 | * license. See the file LICENSE.md distributed with this software for 13 | * full license information. 14 | ********************************************************************/ 15 | 16 | #ifndef PF_LAN9662_API_H 17 | #define PF_LAN9662_API_H 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | #include 24 | 25 | typedef enum 26 | { 27 | PNET_MERA_DATA_TYPE_SRAM, 28 | PNET_MERA_DATA_TYPE_QSPI 29 | } pnet_mera_rte_data_type_t; 30 | 31 | /** 32 | * Submodule RTE data configuration. 33 | * Used for both inputs and outputs configuration. 34 | * The default value is used if the IOXS is bad. 35 | */ 36 | typedef struct pnet_mera_rte_data_cfg 37 | { 38 | pnet_mera_rte_data_type_t type; 39 | uint16_t address; 40 | const uint8_t * default_data; 41 | } pnet_mera_rte_data_cfg_t; 42 | 43 | /** 44 | * Configure RTE input for a single subslot. 45 | * This operation is used to configure a QSPI data source. 46 | * Called during the AR establishment. 47 | * 48 | * @param net InOut: The p-net stack instance 49 | * @param api In: The API. 50 | * @param slot In: The slot. 51 | * @param subslot In: The sub-slot. 52 | * @param rte_data_cfg In: RTE configuration 53 | * @return 0 if the RTE is successfully configured. 54 | * -1 if an error occurred. For example if HW resources are not 55 | * available. 56 | */ 57 | PNET_EXPORT int pnet_mera_input_set_rte_config ( 58 | pnet_t * net, 59 | uint32_t api, 60 | uint16_t slot, 61 | uint16_t subslot, 62 | const pnet_mera_rte_data_cfg_t * rte_data_cfg); 63 | 64 | /** 65 | * Configure RTE output for a single subslot. 66 | * This operation is used to configure a QSPI data sink. 67 | * Called during the AR establishment. 68 | * 69 | * @param net InOut: The p-net stack instance 70 | * @param api In: The API. 71 | * @param slot In: The slot. 72 | * @param subslot In: The sub-slot. 73 | * @param rte_data_cfg In: RTE configuration 74 | * @return 0 if the RTE is successfully configured. 75 | * -1 if an error occurred. For example if HW resources are not 76 | * available. 77 | */ 78 | PNET_EXPORT int pnet_mera_output_set_rte_config ( 79 | pnet_t * net, 80 | uint32_t api, 81 | uint16_t slot, 82 | uint16_t subslot, 83 | const pnet_mera_rte_data_cfg_t * rte_data_cfg); 84 | 85 | #ifdef __cplusplus 86 | } 87 | #endif 88 | 89 | #endif /* PF_LAN9662_API_H */ 90 | -------------------------------------------------------------------------------- /src/drivers/lan9662/pnet_driver_options.h.in: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * _ _ _ 3 | * _ __ | |_ _ | | __ _ | |__ ___ 4 | * | '__|| __|(_)| | / _` || '_ \ / __| 5 | * | | | |_ _ | || (_| || |_) |\__ \ 6 | * |_| \__|(_)|_| \__,_||_.__/ |___/ 7 | * 8 | * www.rt-labs.com 9 | * Copyright 2022 rt-labs AB, Sweden. 10 | * 11 | * This software is dual-licensed under GPLv3 and a commercial 12 | * license. See the file LICENSE.md distributed with this software for 13 | * full license information. 14 | ********************************************************************/ 15 | 16 | #ifndef PNET_DRIVER_OPTIONS_H 17 | #define PNET_DRIVER_OPTIONS_H 18 | 19 | 20 | #if !defined (PNET_OPTION_DRIVER_LAN9662) 21 | #cmakedefine01 PNET_OPTION_DRIVER_LAN9662 22 | #endif 23 | 24 | #if !defined (PNET_OPTION_LAN9662_SHOW_RTE_INFO) 25 | #cmakedefine01 PNET_OPTION_LAN9662_SHOW_RTE_INFO 26 | #endif 27 | 28 | #if !defined (PNET_LAN9662_MAX_FRAMES) 29 | #define PNET_LAN9662_MAX_FRAMES @PNET_LAN9662_MAX_FRAMES@ 30 | #endif 31 | 32 | #if !defined (PNET_LAN9662_MAX_IDS) 33 | #define PNET_LAN9662_MAX_IDS @PNET_LAN9662_MAX_IDS@ 34 | #endif 35 | 36 | #if !defined (PNET_LAN9662_VCAM_BASE) 37 | #define PNET_LAN9662_VCAM_BASE @PNET_LAN9662_VCAM_BASE@ 38 | #endif 39 | 40 | #if !defined (PNET_LAN9662_RTP_BASE) 41 | #define PNET_LAN9662_RTP_BASE @PNET_LAN9662_RTP_BASE@ 42 | #endif 43 | 44 | #if !defined (PNET_LAN9662_WAL_BASE) 45 | #define PNET_LAN9662_WAL_BASE @PNET_LAN9662_WAL_BASE@ 46 | #endif 47 | 48 | #if !defined (PNET_LAN9662_RAL_BASE) 49 | #define PNET_LAN9662_RAL_BASE @PNET_LAN9662_RAL_BASE@ 50 | #endif 51 | 52 | #endif /* PNET_DRIVER_OPTIONS_H */ 53 | -------------------------------------------------------------------------------- /src/drivers/lan9662/set_profinet_leds: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ############################################# 4 | # Script for setting Profinet LEDs on Linux # 5 | ############################################# 6 | # 7 | # This writes the output to files instead of real LEDs. 8 | # It can be useful when running on for example Ubuntu or some other 9 | # desktop Linux variant. 10 | # 11 | # Modify this script to fit your setup, by for example changing output path. 12 | 13 | if [ $# -ne 2 ]; then 14 | echo "Usage: ${0} led_number led_state" 15 | echo " where:" 16 | echo " led_number: LED number. Number 1 for sample app data LED" 17 | echo " Number 2 for mandatory Profinet signal LED" 18 | echo " led_state: 1 for on, 0 for off" 19 | echo " Exit code: 0 on success, 1 on error" 20 | exit 1 21 | fi 22 | 23 | LED_NUMBER=$1 24 | LED_STATE=$2 25 | 26 | # Uncomment next line for debugging 27 | #echo "Script for setting Profinet LED state in dummy file. LED number ${LED_NUMBER}, new state ${LED_STATE}" 28 | 29 | if ! [ ${LED_STATE} == "0" -o ${LED_STATE} == "1" ]; then 30 | echo "Wrong LED state: ${LED_STATE}" 31 | exit 1 32 | fi 33 | 34 | # Todo - map to GPIOs 35 | echo "LED ${LED_NUMBER} new state ${LED_STATE}" 36 | 37 | exit 0 38 | -------------------------------------------------------------------------------- /src/drivers/lan9662/src/pf_mera_trace.c: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2004-2020 Microchip Technology Inc. and its subsidiaries. 2 | // SPDX-License-Identifier: MIT 3 | 4 | /********************************************************************* 5 | * _ _ _ 6 | * _ __ | |_ _ | | __ _ | |__ ___ 7 | * | '__|| __|(_)| | / _` || '_ \ / __| 8 | * | | | |_ _ | || (_| || |_) |\__ \ 9 | * |_| \__|(_)|_| \__,_||_.__/ |___/ 10 | * 11 | * www.rt-labs.com 12 | * 13 | ********************************************************************/ 14 | 15 | /** 16 | * Mera lib log callbacks adapted for P-Net. 17 | * Based on code in mera demo. 18 | */ 19 | 20 | #include "pf_includes.h" 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include 29 | #include 30 | #include "microchip/ethernet/rte/api.h" 31 | 32 | #define TRACE_GROUP_DEFAULT 0 33 | #define TRACE_GROUP_CNT 1 34 | 35 | typedef struct 36 | { 37 | const char * name; 38 | mera_trace_level_t level; 39 | } trace_group_t; 40 | 41 | static trace_group_t trace_groups[] = { 42 | {.name = "default", .level = MERA_TRACE_LEVEL_NOISE}, 43 | {.name = "ib", .level = MERA_TRACE_LEVEL_NOISE}, 44 | {.name = "ob", .level = MERA_TRACE_LEVEL_NOISE}, 45 | }; 46 | 47 | static void printf_trace_head ( 48 | const char * mname, 49 | const char * gname, 50 | const mera_trace_level_t level, 51 | const char * file, 52 | const int line, 53 | const char * function, 54 | const char * lcont) 55 | { 56 | struct timeval tv; 57 | int h, m, s; 58 | const char *p, *base_name = file; 59 | 60 | for (p = file; *p != 0; p++) 61 | { 62 | if (*p == '/' || *p == '\\') 63 | { 64 | base_name = (p + 1); 65 | } 66 | } 67 | 68 | (void)gettimeofday (&tv, NULL); 69 | h = (tv.tv_sec / 3600 % 24); 70 | m = (tv.tv_sec / 60 % 60); 71 | s = (tv.tv_sec % 60); 72 | printf ( 73 | "%u:%02u:%02u:%05lu %s/%s/%s %s(%u) %s%s", 74 | h, 75 | m, 76 | s, 77 | tv.tv_usec, 78 | mname, 79 | gname, 80 | level == MERA_TRACE_LEVEL_ERROR 81 | ? "error" 82 | : level == MERA_TRACE_LEVEL_INFO 83 | ? "info" 84 | : level == MERA_TRACE_LEVEL_DEBUG 85 | ? "debug" 86 | : level == MERA_TRACE_LEVEL_NOISE ? "noise" : "?", 87 | base_name, 88 | line, 89 | function, 90 | lcont); 91 | } 92 | 93 | static void mera_printf_trace_head ( 94 | const mera_trace_group_t group, 95 | const mera_trace_level_t level, 96 | const char * file, 97 | const int line, 98 | const char * function, 99 | const char * lcont) 100 | { 101 | printf_trace_head ( 102 | "p-net", 103 | (int)group < (int)NELEMENTS (trace_groups) ? trace_groups[group].name 104 | : "?", 105 | level, 106 | file, 107 | line, 108 | function, 109 | lcont); 110 | } 111 | 112 | void pf_mera_callout_trace_printf ( 113 | const mera_trace_group_t group, 114 | const mera_trace_level_t level, 115 | const char * file, 116 | const int line, 117 | const char * function, 118 | const char * format, 119 | ...) 120 | { 121 | va_list args; 122 | 123 | mera_printf_trace_head (group, level, file, line, function, ": "); 124 | va_start (args, format); 125 | vprintf (format, args); 126 | va_end (args); 127 | printf ("\n"); 128 | fflush (stdout); 129 | } 130 | -------------------------------------------------------------------------------- /src/drivers/lan9662/src/pf_mera_trace.h: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * _ _ _ 3 | * _ __ | |_ _ | | __ _ | |__ ___ 4 | * | '__|| __|(_)| | / _` || '_ \ / __| 5 | * | | | |_ _ | || (_| || |_) |\__ \ 6 | * |_| \__|(_)|_| \__,_||_.__/ |___/ 7 | * 8 | * www.rt-labs.com 9 | * Copyright 2021 rt-labs AB, Sweden. 10 | * 11 | * This software is dual-licensed under GPLv3 and a commercial 12 | * license. See the file LICENSE.md distributed with this software for 13 | * full license information. 14 | ********************************************************************/ 15 | 16 | #ifndef PF_MERA_TRACE_H 17 | #define PF_MERA_TRACE_H 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | #include "microchip/ethernet/rte/api.h" 24 | 25 | void pf_mera_callout_trace_printf ( 26 | const mera_trace_group_t group, 27 | const mera_trace_level_t level, 28 | const char * file, 29 | const int line, 30 | const char * function, 31 | const char * format, 32 | ...); 33 | 34 | #ifdef __cplusplus 35 | } 36 | #endif 37 | 38 | #endif /* PF_MERA_TRACE_H */ 39 | -------------------------------------------------------------------------------- /src/drivers/lan9662/src/pf_rte_uio.c: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2004-2020 Microchip Technology Inc. and its subsidiaries. 2 | // SPDX-License-Identifier: MIT 3 | 4 | /********************************************************************* 5 | * _ _ _ 6 | * _ __ | |_ _ | | __ _ | |__ ___ 7 | * | '__|| __|(_)| | / _` || '_ \ / __| 8 | * | | | |_ _ | || (_| || |_) |\__ \ 9 | * |_| \__|(_)|_| \__,_||_.__/ |___/ 10 | * 11 | * www.rt-labs.com 12 | * 13 | ********************************************************************/ 14 | 15 | /** 16 | * RTE UIO driver adapted for P-Net. 17 | * Implements register read and write operations. 18 | * Based on code in mera demo. 19 | */ 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include /* I2C support */ 26 | #include /* I2C support */ 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | #include "microchip/ethernet/rte/api.h" 36 | #include "pf_includes.h" 37 | 38 | #define T_D(...) LOG_DEBUG (PNET_LOG, __VA_ARGS__) 39 | #define T_I(...) LOG_INFO (PNET_LOG, __VA_ARGS__) 40 | #define T_E(...) LOG_ERROR (PNET_LOG, __VA_ARGS__) 41 | 42 | #if (__BYTE_ORDER == __BIG_ENDIAN) 43 | #define PCIE_HOST_CVT(x) \ 44 | __builtin_bswap32 ((x)) /* PCIe is LE - we're BE, so swap */ 45 | #else 46 | #define PCIE_HOST_CVT(x) (x) /* We're LE already */ 47 | #endif 48 | 49 | volatile uint32_t * base_mem = NULL; 50 | 51 | int pf_rte_uio_reg_read ( 52 | struct mera_inst * inst, 53 | const uintptr_t addr, 54 | uint32_t * data) 55 | { 56 | if (base_mem != NULL) 57 | { 58 | *data = PCIE_HOST_CVT (base_mem[addr]); 59 | return 0; 60 | } 61 | return -1; 62 | } 63 | 64 | int pf_rte_uio_reg_write ( 65 | struct mera_inst * inst, 66 | const uintptr_t addr, 67 | const uint32_t data) 68 | { 69 | if (base_mem != NULL) 70 | { 71 | base_mem[addr] = PCIE_HOST_CVT (data); 72 | return 0; 73 | } 74 | return -1; 75 | } 76 | 77 | int pf_rte_uio_init (void) 78 | { 79 | const char * driver = "mscc_switch"; 80 | const char * top = "/sys/class/uio"; 81 | DIR * dir; 82 | struct dirent * dent; 83 | char fn[PATH_MAX], devname[128]; 84 | FILE * fp; 85 | char iodev[512]; 86 | size_t mapsize; 87 | int dev_fd, len, rc = -1; 88 | 89 | if (!(dir = opendir (top))) 90 | { 91 | T_E ("operdir(%s) failed\n", top); 92 | return rc; 93 | } 94 | 95 | while ((dent = readdir (dir)) != NULL) 96 | { 97 | if (dent->d_name[0] == '.') 98 | { 99 | continue; 100 | } 101 | 102 | snprintf (fn, sizeof (fn), "%s/%s/name", top, dent->d_name); 103 | fp = fopen (fn, "r"); 104 | if (!fp) 105 | { 106 | T_E ("UIO: Failed to open: %s\n", fn); 107 | continue; 108 | } 109 | 110 | const char * rrd = fgets (devname, sizeof (devname), fp); 111 | fclose (fp); 112 | 113 | if (!rrd) 114 | { 115 | T_E ("UIO: Failed to read: %s\n", fn); 116 | continue; 117 | } 118 | 119 | len = strlen (devname); 120 | if (len > 0 && devname[len - 1] == '\n') 121 | { 122 | devname[len - 1] = '\0'; 123 | } 124 | T_D ("UIO: %s -> %s\n", fn, devname); 125 | if ( 126 | !strstr (devname, "mscc_switch") && 127 | !strstr (devname, "vcoreiii_switch") && 128 | !strstr (devname, "lan966x_uio")) 129 | { 130 | continue; 131 | } 132 | 133 | snprintf (iodev, sizeof (iodev), "/dev/%s", dent->d_name); 134 | snprintf (fn, sizeof (fn), "%s/%s/maps/map0/size", top, dent->d_name); 135 | fp = fopen (fn, "r"); 136 | if (!fp) 137 | { 138 | continue; 139 | } 140 | 141 | if (fscanf (fp, "%zi", &mapsize)) 142 | { 143 | fclose (fp); 144 | rc = 0; 145 | T_I ("Using UIO device: %s\n", devname); 146 | break; 147 | } 148 | fclose (fp); 149 | } 150 | closedir (dir); 151 | 152 | if (rc < 0) 153 | { 154 | T_E ("No suitable UIO device found!\n"); 155 | return rc; 156 | } 157 | 158 | /* Open the UIO device file */ 159 | T_D ("Using UIO, found '%s' driver at %s\n", driver, iodev); 160 | dev_fd = open (iodev, O_RDWR); 161 | if (dev_fd < 1) 162 | { 163 | T_E ("open(%s) failed\n", iodev); 164 | rc = -1; 165 | } 166 | else 167 | { 168 | /* mmap the UIO device */ 169 | base_mem = 170 | mmap (NULL, mapsize, PROT_READ | PROT_WRITE, MAP_SHARED, dev_fd, 0); 171 | if (base_mem != MAP_FAILED) 172 | { 173 | T_D ("Mapped register memory @ %p\n", base_mem); 174 | } 175 | else 176 | { 177 | T_E ("mmap failed\n"); 178 | rc = -1; 179 | } 180 | } 181 | return rc; 182 | } 183 | -------------------------------------------------------------------------------- /src/drivers/lan9662/src/pf_rte_uio.h: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * _ _ _ 3 | * _ __ | |_ _ | | __ _ | |__ ___ 4 | * | '__|| __|(_)| | / _` || '_ \ / __| 5 | * | | | |_ _ | || (_| || |_) |\__ \ 6 | * |_| \__|(_)|_| \__,_||_.__/ |___/ 7 | * 8 | * www.rt-labs.com 9 | * Copyright 2020 rt-labs AB, Sweden. 10 | * 11 | * This software is dual-licensed under GPLv3 and a commercial 12 | * license. See the file LICENSE.md distributed with this software for 13 | * full license information. 14 | ********************************************************************/ 15 | 16 | #ifndef PF_UIO_H 17 | #define PF_UIO_H 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | /** 24 | * Init RTE UIO driver 25 | * The RTE driver provides access to RTE registers from user space. 26 | * The register read and write operations are used by the MERA library. 27 | * @return 0 on success, - 1 on error error 28 | */ 29 | int pf_rte_uio_init (void); 30 | 31 | /** 32 | * Read RTE register 33 | * @param inst In: MERA library instance 34 | * @param addr In: Register address 35 | * @param data In: Register value 36 | * @return 0 on success, - 1 on error error 37 | */ 38 | int pf_rte_uio_reg_read ( 39 | struct mera_inst * inst, 40 | const uintptr_t addr, 41 | uint32_t * data); 42 | 43 | /** 44 | * Write RTE register 45 | * @param inst In: MERA library instance 46 | * @param addr In: Register address 47 | * @param data InOut: Register value 48 | * @return 0 on success, - 1 on error error 49 | */ 50 | int pf_rte_uio_reg_write ( 51 | struct mera_inst * inst, 52 | const uintptr_t addr, 53 | const uint32_t data); 54 | 55 | #ifdef __cplusplus 56 | } 57 | #endif 58 | 59 | #endif /* PF_RTE_UIO_H */ 60 | -------------------------------------------------------------------------------- /src/drivers/lan9662/src/pf_sram_uio.c: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2004-2020 Microchip Technology Inc. and its subsidiaries. 2 | // SPDX-License-Identifier: MIT 3 | 4 | /********************************************************************* 5 | * _ _ _ 6 | * _ __ | |_ _ | | __ _ | |__ ___ 7 | * | '__|| __|(_)| | / _` || '_ \ / __| 8 | * | | | |_ _ | || (_| || |_) |\__ \ 9 | * |_| \__|(_)|_| \__,_||_.__/ |___/ 10 | * 11 | * www.rt-labs.com 12 | * 13 | ********************************************************************/ 14 | 15 | /** 16 | * SRAM UIO driver adapted for P-Net. 17 | * Implements read and write operations as well as 18 | * a allocation/frame concept. 19 | * Based on code in mera demo. 20 | */ 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | #include "microchip/ethernet/rte/api.h" 35 | #include "pf_includes.h" 36 | 37 | #include "pf_sram_uio.h" 38 | 39 | #if (__BYTE_ORDER == __BIG_ENDIAN) 40 | #define HOST_CVT(x) (x) 41 | #else 42 | #define HOST_CVT(x) __builtin_bswap32 ((x)) /* PCIe is LE, so swap */ 43 | #endif 44 | 45 | /* Do not start on address 0 - 0 is used "NULL"*/ 46 | #define PF_SRAM_AREA_START_ADDRESS 100 47 | #define PF_SRAM_FRAME_SIZE 1600 48 | #define PF_SRAM_MAX_FRAMES 4 49 | #define PF_SRAM_MAX_ADDRESS 0x1FFFF 50 | 51 | typedef union pf_uio_reg 52 | { 53 | uint32_t val; 54 | uint8_t data[4]; 55 | } pf_uio_reg_t; 56 | 57 | typedef struct pf_sram_frame 58 | { 59 | bool used; 60 | uint16_t start_address; 61 | } pf_sram_frame_t; 62 | 63 | typedef struct pf_sram_uio 64 | { 65 | int dev_fd; 66 | volatile uint32_t * base_mem; 67 | pf_sram_frame_t frames[PF_SRAM_MAX_FRAMES]; 68 | } pf_sram_uio_t; 69 | 70 | pf_sram_uio_t sram_uio = {0}; 71 | 72 | static int uio_init (pf_sram_uio_t * handle) 73 | { 74 | const char * driver = "mscc_sram"; 75 | const char * top = "/sys/class/uio"; 76 | DIR * dir; 77 | struct dirent * dent; 78 | char fn[PATH_MAX], devname[128]; 79 | FILE * fp; 80 | char iodev[512]; 81 | size_t mapsize; 82 | int len, rc = -1; 83 | 84 | handle->dev_fd = -1; 85 | 86 | if (!(dir = opendir (top))) 87 | { 88 | LOG_ERROR (PF_PPM_LOG, "SRAM UIO - opendir(%s) failed", top); 89 | return rc; 90 | } 91 | 92 | while ((dent = readdir (dir)) != NULL) 93 | { 94 | if (dent->d_name[0] == '.') 95 | { 96 | continue; 97 | } 98 | 99 | snprintf (fn, sizeof (fn), "%s/%s/name", top, dent->d_name); 100 | fp = fopen (fn, "r"); 101 | if (!fp) 102 | { 103 | LOG_ERROR (PF_PPM_LOG, "SRAM UIO - Failed to open: %s", fn); 104 | continue; 105 | } 106 | 107 | const char * rrd = fgets (devname, sizeof (devname), fp); 108 | fclose (fp); 109 | 110 | if (!rrd) 111 | { 112 | LOG_ERROR (PF_PPM_LOG, "SRAM UIO - Failed to read: %s", fn); 113 | continue; 114 | } 115 | 116 | len = strlen (devname); 117 | if (len > 0 && devname[len - 1] == '\n') 118 | { 119 | devname[len - 1] = '\0'; 120 | } 121 | 122 | if (!strstr (devname, driver)) 123 | { 124 | continue; 125 | } 126 | 127 | snprintf (iodev, sizeof (iodev), "/dev/%s", dent->d_name); 128 | snprintf (fn, sizeof (fn), "%s/%s/maps/map0/size", top, dent->d_name); 129 | fp = fopen (fn, "r"); 130 | if (!fp) 131 | { 132 | continue; 133 | } 134 | 135 | if (fscanf (fp, "%zi", &mapsize)) 136 | { 137 | fclose (fp); 138 | rc = 0; 139 | LOG_DEBUG (PF_PPM_LOG, "SRAM UIO - Using device: %s\n", devname); 140 | break; 141 | } 142 | fclose (fp); 143 | } 144 | closedir (dir); 145 | 146 | if (rc < 0) 147 | { 148 | LOG_ERROR (PF_PPM_LOG, "SRAM UIO - No suitable UIO device found!\n"); 149 | return rc; 150 | } 151 | 152 | /* Open the UIO device file */ 153 | LOG_INFO ( 154 | PF_PPM_LOG, 155 | "SRAM UIO - found '%s' driver at %s, size: %zu\n", 156 | driver, 157 | iodev, 158 | mapsize); 159 | handle->dev_fd = open (iodev, O_RDWR); 160 | if (handle->dev_fd < 1) 161 | { 162 | LOG_INFO (PF_PPM_LOG, "SRAM UIO - open(%s) failed\n", iodev); 163 | rc = -1; 164 | } 165 | else 166 | { 167 | /* mmap the UIO device */ 168 | handle->base_mem = mmap ( 169 | NULL, 170 | mapsize, 171 | PROT_READ | PROT_WRITE, 172 | MAP_SHARED, 173 | handle->dev_fd, 174 | 0); 175 | if (handle->base_mem != MAP_FAILED) 176 | { 177 | LOG_DEBUG ( 178 | PF_PPM_LOG, 179 | "SRAM UIO - Mapped register memory @ %p\n", 180 | handle->base_mem); 181 | } 182 | else 183 | { 184 | LOG_ERROR (PF_PPM_LOG, "SRAM UIO - mmap failed\n"); 185 | rc = -1; 186 | } 187 | } 188 | return rc; 189 | } 190 | 191 | int pf_sram_init (void) 192 | { 193 | uint16_t i; 194 | 195 | for (i = 0; i < PF_SRAM_MAX_FRAMES; i++) 196 | { 197 | sram_uio.frames[i].used = false; 198 | sram_uio.frames[i].start_address = 199 | PF_SRAM_AREA_START_ADDRESS + i * PF_SRAM_FRAME_SIZE; 200 | } 201 | 202 | if (uio_init (&sram_uio) != 0) 203 | { 204 | return -1; 205 | } 206 | 207 | return 0; 208 | } 209 | 210 | uint16_t pf_sram_frame_alloc (void) 211 | { 212 | uint16_t i; 213 | 214 | for (i = 0; i < PF_SRAM_MAX_FRAMES; i++) 215 | { 216 | if (sram_uio.frames[i].used == false) 217 | { 218 | sram_uio.frames[i].used = true; 219 | return sram_uio.frames[i].start_address; 220 | } 221 | } 222 | 223 | return PF_SRAM_INVALID_ADDRESS; 224 | } 225 | 226 | void pf_sram_frame_free (uint16_t frame_start_address) 227 | { 228 | uint16_t i; 229 | 230 | for (i = 0; i < PF_SRAM_MAX_FRAMES; i++) 231 | { 232 | if (sram_uio.frames[i].start_address == frame_start_address) 233 | { 234 | sram_uio.frames[i].used = false; 235 | return; 236 | } 237 | } 238 | 239 | LOG_ERROR ( 240 | PF_PPM_LOG, 241 | "SRAM UIO - failed to free frame at address 0x%x\n", 242 | frame_start_address); 243 | } 244 | 245 | static int reg_check (uint32_t addr) 246 | { 247 | if (addr >= PF_SRAM_MAX_ADDRESS) 248 | { 249 | LOG_ERROR (PF_PPM_LOG, "SRAM UIO - address range is 17 bits\n"); 250 | return -1; 251 | } 252 | if (addr & 3) 253 | { 254 | LOG_ERROR (PF_PPM_LOG, "SRAM UIO - address must be 32-bit word aligned\n"); 255 | return -1; 256 | } 257 | return 0; 258 | } 259 | 260 | static int reg_read (uint32_t addr, uint32_t * val) 261 | { 262 | if (reg_check (addr) < 0) 263 | { 264 | return -1; 265 | } 266 | *val = HOST_CVT (sram_uio.base_mem[addr / 4]); 267 | return 0; 268 | } 269 | 270 | static int reg_write (uint32_t addr, uint32_t val) 271 | { 272 | if (reg_check (addr) < 0) 273 | { 274 | return -1; 275 | } 276 | sram_uio.base_mem[addr / 4] = HOST_CVT (val); 277 | return 0; 278 | } 279 | 280 | int pf_sram_write (uint16_t address, const uint8_t * data, uint16_t length) 281 | { 282 | pf_uio_reg_t tmp; 283 | uint32_t uio_reg_addr = address & 0xFFFFFFFC; 284 | uint32_t offset; 285 | uint32_t index = 0; 286 | uint32_t i = 0; 287 | 288 | offset = address - uio_reg_addr; 289 | while (index < length) 290 | { 291 | if (reg_read (uio_reg_addr, &tmp.val) != 0) 292 | { 293 | return -1; 294 | } 295 | 296 | for (i = offset; i <= 3; i++) 297 | { 298 | if (index < length) 299 | { 300 | tmp.data[3 - i] = data[index++]; 301 | } 302 | } 303 | 304 | if (reg_write (uio_reg_addr, tmp.val) != 0) 305 | { 306 | return -1; 307 | } 308 | 309 | uio_reg_addr += 4; 310 | offset = 0; 311 | } 312 | return 0; 313 | } 314 | 315 | int pf_sram_read (uint16_t address, uint8_t * data, uint16_t length) 316 | { 317 | pf_uio_reg_t tmp; 318 | uint32_t uio_reg_addr = address & 0xFFFFFFFC; 319 | uint32_t offset; 320 | uint32_t index = 0; 321 | uint32_t i = 0; 322 | 323 | offset = address - uio_reg_addr; 324 | while (index < length) 325 | { 326 | if (reg_read (uio_reg_addr, &tmp.val) != 0) 327 | { 328 | return -1; 329 | } 330 | 331 | for (i = offset; i <= 3; i++) 332 | { 333 | if (index < length) 334 | { 335 | data[index++] = tmp.data[3 - i]; 336 | } 337 | } 338 | 339 | uio_reg_addr += 4; 340 | offset = 0; 341 | } 342 | return 0; 343 | } -------------------------------------------------------------------------------- /src/drivers/lan9662/src/pf_sram_uio.h: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * _ _ _ 3 | * _ __ | |_ _ | | __ _ | |__ ___ 4 | * | '__|| __|(_)| | / _` || '_ \ / __| 5 | * | | | |_ _ | || (_| || |_) |\__ \ 6 | * |_| \__|(_)|_| \__,_||_.__/ |___/ 7 | * 8 | * www.rt-labs.com 9 | * Copyright 2020 rt-labs AB, Sweden. 10 | * 11 | * This software is dual-licensed under GPLv3 and a commercial 12 | * license. See the file LICENSE.md distributed with this software for 13 | * full license information. 14 | ********************************************************************/ 15 | 16 | #ifndef PF_SRAM_UIO_H 17 | #define PF_SRAM_UIO_H 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | #define PF_SRAM_INVALID_ADDRESS 0 24 | 25 | /** 26 | * Init SRAM UIO driver. 27 | * The SRAM driver provides access to LAN9662 SRAM used by the RTE. 28 | * The driver implements a frame concept for managing the SRAM 29 | * as frames mapping to a inbound or outbound RTE configurations. 30 | * @return 0 on success, - 1 on error error 31 | */ 32 | int pf_sram_init (void); 33 | 34 | /** 35 | * Allocate SRAM frame 36 | * @return Frame start address, PF_SRAM_INVALID_ADDRESS on error 37 | */ 38 | uint16_t pf_sram_frame_alloc (void); 39 | 40 | /** 41 | * Free SRAM frame 42 | * @param Frame start address 43 | */ 44 | void pf_sram_frame_free (uint16_t frame_start_address); 45 | 46 | /** 47 | * Write SRAM 48 | * @param address In: SRAM address to write 49 | * @param data In: Data 50 | * @param length In: Length of data 51 | * @return 0 on success, -1 on error 52 | */ 53 | int pf_sram_write (uint16_t address, const uint8_t * data, uint16_t length); 54 | 55 | /** 56 | * Read SRAM 57 | * @param address In: SRAM address to read 58 | * @param data Out: Data 59 | * @param length In: Length of data 60 | * @return 0 on success, -1 on error 61 | */ 62 | int pf_sram_read (uint16_t address, uint8_t * data, uint16_t length); 63 | 64 | #ifdef __cplusplus 65 | } 66 | #endif 67 | 68 | #endif /* PF_PORT_H */ 69 | -------------------------------------------------------------------------------- /src/pf_driver.h: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * _ _ _ 3 | * _ __ | |_ _ | | __ _ | |__ ___ 4 | * | '__|| __|(_)| | / _` || '_ \ / __| 5 | * | | | |_ _ | || (_| || |_) |\__ \ 6 | * |_| \__|(_)|_| \__,_||_.__/ |___/ 7 | * 8 | * www.rt-labs.com 9 | * Copyright 2018 rt-labs AB, Sweden. 10 | * 11 | * This software is dual-licensed under GPLv3 and a commercial 12 | * license. See the file LICENSE.md distributed with this software for 13 | * full license information. 14 | ********************************************************************/ 15 | 16 | /** 17 | * @file 18 | * @brief Driver interface 19 | */ 20 | 21 | #ifndef PF_DRIVER_H 22 | #define PF_DRIVER_H 23 | 24 | #ifdef __cplusplus 25 | extern "C" { 26 | #endif 27 | 28 | #include "pf_includes.h" 29 | 30 | /** 31 | * Initialize hardware offload driver 32 | * Called during P-Net initialization if option 33 | * PNET_OPTION_DRIVER_ENABLE is enabled. 34 | * @param net InOut: The p-net stack instance 35 | * @return 0 on success 36 | * -1 on error 37 | */ 38 | int pf_driver_init (pnet_t * net); 39 | 40 | /** 41 | * Install hardware offload ppm driver 42 | * Called during P-Net initialization if option 43 | * PNET_OPTION_DRIVER_ENABLE is enabled. 44 | * 45 | * @return 0 on success 46 | * -1 on error 47 | */ 48 | int pf_driver_ppm_init (pnet_t * net); 49 | 50 | /** 51 | * Install hardware offload cpm driver 52 | * Called during P-Net initialization if option 53 | * PNET_OPTION_DRIVER_ENABLE is enabled. 54 | * 55 | * @return 0 on success 56 | * -1 on error 57 | */ 58 | int pf_driver_cpm_init (pnet_t * net); 59 | 60 | #ifdef __cplusplus 61 | } 62 | #endif 63 | 64 | #endif /* PF_DRIVER_H*/ 65 | -------------------------------------------------------------------------------- /src/pf_includes.h: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * _ _ _ 3 | * _ __ | |_ _ | | __ _ | |__ ___ 4 | * | '__|| __|(_)| | / _` || '_ \ / __| 5 | * | | | |_ _ | || (_| || |_) |\__ \ 6 | * |_| \__|(_)|_| \__,_||_.__/ |___/ 7 | * 8 | * www.rt-labs.com 9 | * Copyright 2018 rt-labs AB, Sweden. 10 | * 11 | * This software is dual-licensed under GPLv3 and a commercial 12 | * license. See the file LICENSE.md distributed with this software for 13 | * full license information. 14 | ********************************************************************/ 15 | 16 | /** 17 | * @file 18 | * @brief describe purpose of this file 19 | */ 20 | 21 | #ifndef PF_INCLUDES_H 22 | #define PF_INCLUDES_H 23 | 24 | #ifdef __cplusplus 25 | extern "C" { 26 | #endif 27 | 28 | #include "pnet_options.h" 29 | #include "osal.h" 30 | #include "osal_log.h" 31 | #include "pnal.h" 32 | 33 | #include "pnet_api.h" 34 | #include "pf_driver.h" 35 | #include "pf_types.h" 36 | 37 | /* common */ 38 | #include "pf_alarm.h" 39 | #include "pf_bg_worker.h" 40 | #include "pf_cpm.h" 41 | #include "pf_cpm_driver_sw.h" 42 | #include "pf_dcp.h" 43 | #include "pf_eth.h" 44 | #include "pf_file.h" 45 | #include "pf_lldp.h" 46 | #include "pf_ppm.h" 47 | #include "pf_ppm_driver_sw.h" 48 | #include "pf_ptcp.h" 49 | #include "pf_scheduler.h" 50 | #include "pf_snmp.h" 51 | #include "pf_udp.h" 52 | 53 | /* device */ 54 | #include "pf_cmdev.h" 55 | #include "pf_cmdmc.h" 56 | #include "pf_cmina.h" 57 | #include "pf_cmio.h" 58 | #include "pf_cmpbe.h" 59 | #include "pf_cmrdr.h" 60 | #include "pf_cmrpc.h" 61 | #include "pf_cmrpc_helpers.h" 62 | #include "pf_cmrs.h" 63 | #include "pf_cmsm.h" 64 | #include "pf_cmsu.h" 65 | #include "pf_cmwrr.h" 66 | #include "pf_diag.h" 67 | #include "pf_fspm.h" 68 | #include "pf_pdport.h" 69 | #include "pf_port.h" 70 | #include "pf_plugsm.h" 71 | 72 | #ifdef __cplusplus 73 | } 74 | #endif 75 | 76 | #endif /* PF_INCLUDES_H */ 77 | -------------------------------------------------------------------------------- /test/mocks.h: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * _ _ _ 3 | * _ __ | |_ _ | | __ _ | |__ ___ 4 | * | '__|| __|(_)| | / _` || '_ \ / __| 5 | * | | | |_ _ | || (_| || |_) |\__ \ 6 | * |_| \__|(_)|_| \__,_||_.__/ |___/ 7 | * 8 | * www.rt-labs.com 9 | * Copyright 2018 rt-labs AB, Sweden. 10 | * 11 | * This software is dual-licensed under GPLv3 and a commercial 12 | * license. See the file LICENSE.md distributed with this software for 13 | * full license information. 14 | ********************************************************************/ 15 | 16 | #ifndef MOCKS_H 17 | #define MOCKS_H 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | #include 24 | 25 | #include "pnet_options.h" 26 | #include "pnet_api.h" 27 | #include "pf_includes.h" 28 | #include "osal.h" 29 | 30 | typedef struct mock_os_data_obj 31 | { 32 | uint8_t eth_send_copy[PF_FRAME_BUFFER_SIZE]; 33 | uint16_t eth_send_len; 34 | uint16_t eth_send_count; 35 | 36 | /* Per port Ethernet link status. 37 | * Note that port numbers start at 1. To simplify test cases, we add a 38 | * dummy array element at index 0. 39 | */ 40 | pnal_eth_status_t eth_status[PNET_MAX_PHYSICAL_PORTS + 1]; 41 | pnal_port_stats_t port_statistics[PNET_MAX_PHYSICAL_PORTS + 1]; 42 | 43 | uint16_t udp_sendto_len; 44 | uint16_t udp_sendto_count; 45 | 46 | uint8_t udp_recvfrom_buffer[PF_FRAME_BUFFER_SIZE]; 47 | uint16_t udp_recvfrom_length; 48 | uint16_t udp_recvfrom_count; 49 | 50 | uint16_t set_ip_suite_count; 51 | 52 | uint32_t current_time_us; 53 | uint32_t system_uptime_10ms; 54 | 55 | int interface_index; 56 | pnal_eth_handle_t * eth_if_handle; 57 | 58 | char file_fullpath[100]; /* Full file path at latest save operation */ 59 | uint16_t file_size; 60 | uint8_t file_content[2000]; 61 | 62 | } mock_os_data_t; 63 | 64 | typedef struct mock_lldp_data 65 | { 66 | pf_lldp_management_address_t management_address; 67 | pf_lldp_management_address_t peer_management_address; 68 | pf_lldp_link_status_t link_status; 69 | pf_lldp_link_status_t peer_link_status; 70 | int error; 71 | 72 | } mock_lldp_data_t; 73 | 74 | typedef struct mock_file_data 75 | { 76 | char filename[PNET_MAX_FILENAME_SIZE]; 77 | uint8_t object[300]; 78 | size_t size; 79 | bool is_save_failing; /* Used for injecting error */ 80 | bool is_load_failing; /* Used for injecting error */ 81 | 82 | } mock_file_data_t; 83 | 84 | typedef struct mock_fspm_data 85 | { 86 | char im_location[PNET_LOCATION_MAX_SIZE]; 87 | } mock_fspm_data_t; 88 | 89 | extern mock_os_data_t mock_os_data; 90 | extern mock_lldp_data_t mock_lldp_data; 91 | extern mock_file_data_t mock_file_data; 92 | extern mock_fspm_data_t mock_fspm_data; 93 | 94 | uint32_t mock_os_get_current_time_us (void); 95 | uint32_t mock_pnal_get_system_uptime_10ms (void); 96 | 97 | void mock_init (void); 98 | void mock_clear (void); 99 | void mock_set_pnal_udp_recvfrom_buffer (uint8_t * p_src, uint16_t len); 100 | 101 | pnal_eth_handle_t * mock_pnal_eth_init ( 102 | const char * if_name, 103 | const pnal_cfg_t * pnal_cfg, 104 | pnal_eth_callback_t * callback, 105 | void * arg); 106 | int mock_pnal_eth_send (pnal_eth_handle_t * handle, pnal_buf_t * buf); 107 | int mock_pnal_get_macaddress ( 108 | const char * interface_name, 109 | pnal_ethaddr_t * p_mac); 110 | int mock_pnal_eth_get_status ( 111 | const char * interface_name, 112 | pnal_eth_status_t * status); 113 | int mock_pnal_get_port_statistics ( 114 | const char * interface_name, 115 | pnal_port_stats_t * port_stats); 116 | int mock_pnal_get_hostname (char * hostname); 117 | void mock_os_cpy_mac_addr (uint8_t * mac_addr); 118 | int mock_pnal_udp_open (pnal_ipaddr_t addr, pnal_ipport_t port); 119 | int mock_pnal_udp_sendto ( 120 | uint32_t id, 121 | pnal_ipaddr_t dst_addr, 122 | pnal_ipport_t dst_port, 123 | const uint8_t * data, 124 | int size); 125 | int mock_pnal_udp_recvfrom ( 126 | uint32_t id, 127 | pnal_ipaddr_t * dst_addr, 128 | pnal_ipport_t * dst_port, 129 | uint8_t * data, 130 | int size); 131 | void mock_pnal_udp_close (uint32_t id); 132 | int mock_pnal_set_ip_suite ( 133 | const char * interface_name, 134 | const pnal_ipaddr_t * p_ipaddr, 135 | const pnal_ipaddr_t * p_netmask, 136 | const pnal_ipaddr_t * p_gw, 137 | const char * hostname, 138 | bool permanent); 139 | int mock_pnal_get_interface_index (const char * interface_name); 140 | 141 | int mock_pnal_save_file ( 142 | const char * fullpath, 143 | const void * object_1, 144 | size_t size_1, 145 | const void * object_2, 146 | size_t size_2); 147 | 148 | void mock_pnal_clear_file (const char * fullpath); 149 | 150 | int mock_pnal_load_file ( 151 | const char * fullpath, 152 | void * object_1, 153 | size_t size_1, 154 | void * object_2, 155 | size_t size_2); 156 | 157 | int mock_pf_alarm_send_diagnosis ( 158 | pf_ar_t * p_ar, 159 | uint32_t api_id, 160 | uint16_t slot_nbr, 161 | uint16_t subslot_nbr, 162 | pf_diag_item_t * p_item); 163 | 164 | void mock_pf_generate_uuid ( 165 | uint32_t timestamp, 166 | uint32_t session_number, 167 | pnet_ethaddr_t mac_address, 168 | pf_uuid_t * p_uuid); 169 | 170 | void mock_pf_lldp_get_management_address ( 171 | pnet_t * net, 172 | pf_lldp_management_address_t * p_man_address); 173 | 174 | int mock_pf_lldp_get_peer_management_address ( 175 | pnet_t * net, 176 | int loc_port_num, 177 | pf_lldp_management_address_t * p_man_address); 178 | 179 | void mock_pf_lldp_get_link_status ( 180 | pnet_t * net, 181 | int loc_port_num, 182 | pf_lldp_link_status_t * p_link_status); 183 | 184 | int mock_pf_lldp_get_peer_link_status ( 185 | pnet_t * net, 186 | int loc_port_num, 187 | pf_lldp_link_status_t * p_link_status); 188 | 189 | int mock_pnal_snmp_init (pnet_t * pnet, const pnal_cfg_t * pnal_cfg); 190 | 191 | int mock_pf_file_save_if_modified ( 192 | const char * directory, 193 | const char * filename, 194 | const void * p_object, 195 | void * p_tempobject, 196 | size_t size); 197 | 198 | int mock_pf_file_save ( 199 | const char * directory, 200 | const char * filename, 201 | const void * p_object, 202 | size_t size); 203 | 204 | void mock_pf_file_clear (const char * directory, const char * filename); 205 | 206 | int mock_pf_file_load ( 207 | const char * directory, 208 | const char * filename, 209 | void * p_object, 210 | size_t size); 211 | 212 | void mock_pf_fspm_get_im_location (pnet_t * net, char * location); 213 | 214 | void mock_pf_fspm_save_im_location (pnet_t * net, const char * location); 215 | 216 | void mock_pf_bg_worker_init (pnet_t * net); 217 | 218 | int mock_pf_bg_worker_start_job (pnet_t * net, pf_bg_job_t job_id); 219 | 220 | #ifdef __cplusplus 221 | } 222 | #endif 223 | 224 | #endif /* MOCKS_H */ 225 | -------------------------------------------------------------------------------- /test/pf_test.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * _ _ _ 3 | * _ __ | |_ _ | | __ _ | |__ ___ 4 | * | '__|| __|(_)| | / _` || '_ \ / __| 5 | * | | | |_ _ | || (_| || |_) |\__ \ 6 | * |_| \__|(_)|_| \__,_||_.__/ |___/ 7 | * 8 | * www.rt-labs.com 9 | * Copyright 2018 rt-labs AB, Sweden. 10 | * 11 | * This software is dual-licensed under GPLv3 and a commercial 12 | * license. See the file LICENSE.md distributed with this software for 13 | * full license information. 14 | ********************************************************************/ 15 | 16 | #include 17 | #include "osal.h" 18 | 19 | OS_MAIN (int argc, char * argv[]) 20 | { 21 | if (argc > 0) 22 | ::testing::InitGoogleTest (&argc, argv); 23 | else 24 | ::testing::InitGoogleTest(); 25 | 26 | int result = RUN_ALL_TESTS(); 27 | return result; 28 | } 29 | -------------------------------------------------------------------------------- /test/test_block_reader.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * _ _ _ 3 | * _ __ | |_ _ | | __ _ | |__ ___ 4 | * | '__|| __|(_)| | / _` || '_ \ / __| 5 | * | | | |_ _ | || (_| || |_) |\__ \ 6 | * |_| \__|(_)|_| \__,_||_.__/ |___/ 7 | * 8 | * www.rt-labs.com 9 | * Copyright 2018 rt-labs AB, Sweden. 10 | * 11 | * This software is dual-licensed under GPLv3 and a commercial 12 | * license. See the file LICENSE.md distributed with this software for 13 | * full license information. 14 | ********************************************************************/ 15 | 16 | #include "utils_for_testing.h" 17 | #include "mocks.h" 18 | 19 | #include "pf_block_reader.h" 20 | #include "pf_includes.h" 21 | 22 | #include 23 | 24 | class BlockReaderUnitTest : public PnetUnitTest 25 | { 26 | }; 27 | 28 | TEST_F (BlockReaderUnitTest, BlockReaderTestGetBits) 29 | { 30 | 31 | /* 11111111 11111111 11111111 11111111 */ 32 | EXPECT_EQ (0x00000000ul, pf_get_bits (0xFFFFFFFF, 0, 0)); 33 | EXPECT_EQ (0x00000001ul, pf_get_bits (0xFFFFFFFF, 0, 1)); 34 | EXPECT_EQ (0x00000003ul, pf_get_bits (0xFFFFFFFF, 0, 2)); 35 | EXPECT_EQ (0x00000007ul, pf_get_bits (0xFFFFFFFF, 0, 3)); 36 | EXPECT_EQ (0x0000000Ful, pf_get_bits (0xFFFFFFFF, 0, 4)); 37 | EXPECT_EQ (0x0000001Ful, pf_get_bits (0xFFFFFFFF, 0, 5)); 38 | EXPECT_EQ (0x0000003Ful, pf_get_bits (0xFFFFFFFF, 0, 6)); 39 | EXPECT_EQ (0x0000007Ful, pf_get_bits (0xFFFFFFFF, 0, 7)); 40 | EXPECT_EQ (0x000000FFul, pf_get_bits (0xFFFFFFFF, 0, 8)); 41 | EXPECT_EQ (0x7FFFFFFFul, pf_get_bits (0xFFFFFFFF, 0, 31)); 42 | EXPECT_EQ (0xFFFFFFFFul, pf_get_bits (0xFFFFFFFF, 0, 32)); 43 | EXPECT_EQ (0ul, pf_get_bits (0xFFFFFFFF, 0, 33)); /* Illegal length */ 44 | 45 | EXPECT_EQ (0x00000000ul, pf_get_bits (0xFFFFFFFF, 1, 0)); 46 | EXPECT_EQ (0x00000001ul, pf_get_bits (0xFFFFFFFF, 1, 1)); 47 | EXPECT_EQ (0x00000003ul, pf_get_bits (0xFFFFFFFF, 1, 2)); 48 | EXPECT_EQ (0x00000007ul, pf_get_bits (0xFFFFFFFF, 1, 3)); 49 | EXPECT_EQ (0x000000FFul, pf_get_bits (0xFFFFFFFF, 1, 8)); 50 | EXPECT_EQ (0x7FFFFFFFul, pf_get_bits (0xFFFFFFFF, 1, 31)); 51 | EXPECT_EQ (0ul, pf_get_bits (0xFFFFFFFF, 1, 32)); /* Illegal length and 52 | position combination*/ 53 | EXPECT_EQ (0ul, pf_get_bits (0xFFFFFFFF, 1, 33)); /* Illegal length */ 54 | 55 | EXPECT_EQ (0x00000000ul, pf_get_bits (0xFFFFFFFF, 31, 0)); 56 | EXPECT_EQ (0x00000001ul, pf_get_bits (0xFFFFFFFF, 31, 1)); 57 | EXPECT_EQ (0ul, pf_get_bits (0xFFFFFFFF, 31, 2)); /* Illegal length and 58 | position combination*/ 59 | EXPECT_EQ (0ul, pf_get_bits (0xFFFFFFFF, 31, 32)); /* Illegal length and 60 | position combination*/ 61 | EXPECT_EQ (0ul, pf_get_bits (0xFFFFFFFF, 31, 33)); /* Illegal length */ 62 | 63 | EXPECT_EQ (0ul, pf_get_bits (0xFFFFFFFF, 32, 0)); /* Illegal position */ 64 | EXPECT_EQ (0ul, pf_get_bits (0xFFFFFFFF, 32, 1)); /* Illegal position */ 65 | EXPECT_EQ (0ul, pf_get_bits (0xFFFFFFFF, 32, 32)); /* Illegal position */ 66 | EXPECT_EQ (0ul, pf_get_bits (0xFFFFFFFF, 32, 33)); /* Illegal position and 67 | illegal length */ 68 | 69 | EXPECT_EQ (0ul, pf_get_bits (0xFFFFFFFF, 0xFF, 0xFF)); /* Illegal position 70 | and illegal length 71 | */ 72 | 73 | /* 00000000 00000000 00000000 00010000 */ 74 | EXPECT_EQ (0x00000000ul, pf_get_bits (0x00000010, 0, 3)); 75 | EXPECT_EQ (0x00000000ul, pf_get_bits (0x00000010, 1, 3)); 76 | EXPECT_EQ (0x00000004ul, pf_get_bits (0x00000010, 2, 3)); 77 | EXPECT_EQ (0x00000002ul, pf_get_bits (0x00000010, 3, 3)); 78 | EXPECT_EQ (0x00000001ul, pf_get_bits (0x00000010, 4, 3)); 79 | EXPECT_EQ (0x00000000ul, pf_get_bits (0x00000010, 5, 3)); 80 | EXPECT_EQ (0x00000000ul, pf_get_bits (0x00000010, 28, 3)); 81 | EXPECT_EQ (0x00000000ul, pf_get_bits (0x00000010, 29, 3)); 82 | EXPECT_EQ (0ul, pf_get_bits (0x00000010, 30, 3)); /* Illegal length and 83 | position combination*/ 84 | EXPECT_EQ (0ul, pf_get_bits (0x00000010, 31, 3)); /* Illegal length and 85 | position combination*/ 86 | EXPECT_EQ (0ul, pf_get_bits (0x00000010, 32, 3)); /* Illegal position */ 87 | EXPECT_EQ (0ul, pf_get_bits (0x00000010, 33, 3)); /* Illegal position */ 88 | 89 | /* 00000000 00000000 00000000 00000001 */ 90 | EXPECT_EQ (0x00000001ul, pf_get_bits (0x00000001, 0, 3)); 91 | EXPECT_EQ (0x00000000ul, pf_get_bits (0x00000001, 1, 3)); 92 | EXPECT_EQ (0x00000000ul, pf_get_bits (0x00000001, 2, 3)); 93 | EXPECT_EQ (0x00000000ul, pf_get_bits (0x00000001, 3, 3)); 94 | EXPECT_EQ (0x00000000ul, pf_get_bits (0x00000001, 4, 3)); 95 | EXPECT_EQ (0ul, pf_get_bits (0x00000010, 30, 3)); /* Illegal length and 96 | position combination*/ 97 | EXPECT_EQ (0ul, pf_get_bits (0x00000010, 31, 3)); /* Illegal length and 98 | position combination*/ 99 | EXPECT_EQ (0ul, pf_get_bits (0x00000010, 32, 3)); /* Illegal position */ 100 | EXPECT_EQ (0ul, pf_get_bits (0x00000010, 33, 3)); /* Illegal position */ 101 | 102 | /* 10000000 00000000 00000000 00000000 */ 103 | EXPECT_EQ (0x00000000ul, pf_get_bits (0x80000000, 0, 3)); 104 | EXPECT_EQ (0x00000000ul, pf_get_bits (0x80000000, 1, 3)); 105 | EXPECT_EQ (0x00000000ul, pf_get_bits (0x80000000, 28, 3)); 106 | EXPECT_EQ (0x00000004ul, pf_get_bits (0x80000000, 29, 3)); 107 | EXPECT_EQ (0ul, pf_get_bits (0x80000000, 30, 3)); /* Illegal length and 108 | position combination*/ 109 | EXPECT_EQ (0ul, pf_get_bits (0x80000000, 31, 3)); /* Illegal length and 110 | position combination*/ 111 | EXPECT_EQ (0ul, pf_get_bits (0x80000000, 32, 3)); /* Illegal position */ 112 | EXPECT_EQ (0ul, pf_get_bits (0x80000000, 33, 3)); /* Illegal position */ 113 | } 114 | -------------------------------------------------------------------------------- /test/test_cmdmc.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * _ _ _ 3 | * _ __ | |_ _ | | __ _ | |__ ___ 4 | * | '__|| __|(_)| | / _` || '_ \ / __| 5 | * | | | |_ _ | || (_| || |_) |\__ \ 6 | * |_| \__|(_)|_| \__,_||_.__/ |___/ 7 | * 8 | * www.rt-labs.com 9 | * Copyright 2018 rt-labs AB, Sweden. 10 | * 11 | * This software is dual-licensed under GPLv3 and a commercial 12 | * license. See the file LICENSE.md distributed with this software for 13 | * full license information. 14 | ********************************************************************/ 15 | 16 | #include "utils_for_testing.h" 17 | #include "mocks.h" 18 | 19 | #include "pf_includes.h" 20 | 21 | #include 22 | 23 | class CmdmcTest : public PnetIntegrationTest 24 | { 25 | }; 26 | 27 | TEST_F (CmdmcTest, CmdmcRunTest) 28 | { 29 | } 30 | -------------------------------------------------------------------------------- /test/test_cmio.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * _ _ _ 3 | * _ __ | |_ _ | | __ _ | |__ ___ 4 | * | '__|| __|(_)| | / _` || '_ \ / __| 5 | * | | | |_ _ | || (_| || |_) |\__ \ 6 | * |_| \__|(_)|_| \__,_||_.__/ |___/ 7 | * 8 | * www.rt-labs.com 9 | * Copyright 2018 rt-labs AB, Sweden. 10 | * 11 | * This software is dual-licensed under GPLv3 and a commercial 12 | * license. See the file LICENSE.md distributed with this software for 13 | * full license information. 14 | ********************************************************************/ 15 | 16 | #include "utils_for_testing.h" 17 | #include "mocks.h" 18 | 19 | #include "pf_includes.h" 20 | 21 | #include 22 | 23 | class CmioTest : public PnetIntegrationTest 24 | { 25 | }; 26 | 27 | TEST_F (CmioTest, CmioRunTest) 28 | { 29 | } 30 | -------------------------------------------------------------------------------- /test/test_cmpbe.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * _ _ _ 3 | * _ __ | |_ _ | | __ _ | |__ ___ 4 | * | '__|| __|(_)| | / _` || '_ \ / __| 5 | * | | | |_ _ | || (_| || |_) |\__ \ 6 | * |_| \__|(_)|_| \__,_||_.__/ |___/ 7 | * 8 | * www.rt-labs.com 9 | * Copyright 2018 rt-labs AB, Sweden. 10 | * 11 | * This software is dual-licensed under GPLv3 and a commercial 12 | * license. See the file LICENSE.md distributed with this software for 13 | * full license information. 14 | ********************************************************************/ 15 | 16 | #include "utils_for_testing.h" 17 | #include "mocks.h" 18 | 19 | #include "pf_includes.h" 20 | 21 | #include 22 | 23 | class CmpbeTest : public PnetIntegrationTest 24 | { 25 | }; 26 | 27 | TEST_F (CmpbeTest, CmpbeRunTest) 28 | { 29 | } 30 | -------------------------------------------------------------------------------- /test/test_cmrs.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * _ _ _ 3 | * _ __ | |_ _ | | __ _ | |__ ___ 4 | * | '__|| __|(_)| | / _` || '_ \ / __| 5 | * | | | |_ _ | || (_| || |_) |\__ \ 6 | * |_| \__|(_)|_| \__,_||_.__/ |___/ 7 | * 8 | * www.rt-labs.com 9 | * Copyright 2018 rt-labs AB, Sweden. 10 | * 11 | * This software is dual-licensed under GPLv3 and a commercial 12 | * license. See the file LICENSE.md distributed with this software for 13 | * full license information. 14 | ********************************************************************/ 15 | 16 | #include "utils_for_testing.h" 17 | #include "mocks.h" 18 | 19 | #include "pf_includes.h" 20 | 21 | #include 22 | 23 | class CmrsTest : public PnetIntegrationTest 24 | { 25 | }; 26 | 27 | TEST_F (CmrsTest, CmrsRunTest) 28 | { 29 | } 30 | -------------------------------------------------------------------------------- /test/test_cmsm.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * _ _ _ 3 | * _ __ | |_ _ | | __ _ | |__ ___ 4 | * | '__|| __|(_)| | / _` || '_ \ / __| 5 | * | | | |_ _ | || (_| || |_) |\__ \ 6 | * |_| \__|(_)|_| \__,_||_.__/ |___/ 7 | * 8 | * www.rt-labs.com 9 | * Copyright 2018 rt-labs AB, Sweden. 10 | * 11 | * This software is dual-licensed under GPLv3 and a commercial 12 | * license. See the file LICENSE.md distributed with this software for 13 | * full license information. 14 | ********************************************************************/ 15 | 16 | #include "utils_for_testing.h" 17 | #include "mocks.h" 18 | 19 | #include "pf_includes.h" 20 | 21 | #include 22 | 23 | class CmsmTest : public PnetIntegrationTest 24 | { 25 | }; 26 | 27 | TEST_F (CmsmTest, CmsmRunTest) 28 | { 29 | } 30 | -------------------------------------------------------------------------------- /test/test_cmsu.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * _ _ _ 3 | * _ __ | |_ _ | | __ _ | |__ ___ 4 | * | '__|| __|(_)| | / _` || '_ \ / __| 5 | * | | | |_ _ | || (_| || |_) |\__ \ 6 | * |_| \__|(_)|_| \__,_||_.__/ |___/ 7 | * 8 | * www.rt-labs.com 9 | * Copyright 2018 rt-labs AB, Sweden. 10 | * 11 | * This software is dual-licensed under GPLv3 and a commercial 12 | * license. See the file LICENSE.md distributed with this software for 13 | * full license information. 14 | ********************************************************************/ 15 | 16 | #include "utils_for_testing.h" 17 | #include "mocks.h" 18 | 19 | #include "pf_includes.h" 20 | 21 | #include 22 | 23 | class CmsuTest : public PnetIntegrationTest 24 | { 25 | }; 26 | 27 | TEST_F (CmsuTest, CmsuRunTest) 28 | { 29 | } 30 | -------------------------------------------------------------------------------- /test/test_cmwdr.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * _ _ _ 3 | * _ __ | |_ _ | | __ _ | |__ ___ 4 | * | '__|| __|(_)| | / _` || '_ \ / __| 5 | * | | | |_ _ | || (_| || |_) |\__ \ 6 | * |_| \__|(_)|_| \__,_||_.__/ |___/ 7 | * 8 | * www.rt-labs.com 9 | * Copyright 2018 rt-labs AB, Sweden. 10 | * 11 | * This software is dual-licensed under GPLv3 and a commercial 12 | * license. See the file LICENSE.md distributed with this software for 13 | * full license information. 14 | ********************************************************************/ 15 | 16 | #include "utils_for_testing.h" 17 | #include "mocks.h" 18 | 19 | #include "pf_includes.h" 20 | 21 | #include 22 | 23 | class CmwdrTest : public PnetIntegrationTest 24 | { 25 | }; 26 | 27 | TEST_F (CmwdrTest, CmwdrRunTest) 28 | { 29 | } 30 | -------------------------------------------------------------------------------- /test/test_cpm.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * _ _ _ 3 | * _ __ | |_ _ | | __ _ | |__ ___ 4 | * | '__|| __|(_)| | / _` || '_ \ / __| 5 | * | | | |_ _ | || (_| || |_) |\__ \ 6 | * |_| \__|(_)|_| \__,_||_.__/ |___/ 7 | * 8 | * www.rt-labs.com 9 | * Copyright 2018 rt-labs AB, Sweden. 10 | * 11 | * This software is dual-licensed under GPLv3 and a commercial 12 | * license. See the file LICENSE.md distributed with this software for 13 | * full license information. 14 | ********************************************************************/ 15 | 16 | #include "utils_for_testing.h" 17 | #include "mocks.h" 18 | 19 | #include "pf_includes.h" 20 | 21 | #include 22 | 23 | class CpmUnitTest : public PnetUnitTest 24 | { 25 | }; 26 | 27 | TEST_F (CpmUnitTest, CpmCheckCycle) 28 | { 29 | EXPECT_EQ (-1, pf_cpm_check_cycle (1, 0xFFFF)); 30 | EXPECT_EQ (-1, pf_cpm_check_cycle (1, 0)); 31 | EXPECT_EQ (-1, pf_cpm_check_cycle (1, 1)); 32 | EXPECT_EQ (0, pf_cpm_check_cycle (1, 2)); 33 | EXPECT_EQ (0, pf_cpm_check_cycle (1, 3)); 34 | 35 | /* Previous counter value was 0x4000 */ 36 | EXPECT_EQ (0, pf_cpm_check_cycle (0x4000, 0x0000)); 37 | EXPECT_EQ (0, pf_cpm_check_cycle (0x4000, 0x0001)); 38 | EXPECT_EQ (0, pf_cpm_check_cycle (0x4000, 0x2FFE)); 39 | EXPECT_EQ (0, pf_cpm_check_cycle (0x4000, 0x2FFF)); 40 | EXPECT_EQ (0, pf_cpm_check_cycle (0x4000, 0x3000)); 41 | EXPECT_EQ (-1, pf_cpm_check_cycle (0x4000, 0x3001)); 42 | EXPECT_EQ (-1, pf_cpm_check_cycle (0x4000, 0x3002)); 43 | EXPECT_EQ (-1, pf_cpm_check_cycle (0x4000, 0x3FFD)); 44 | EXPECT_EQ (-1, pf_cpm_check_cycle (0x4000, 0x3FFE)); 45 | EXPECT_EQ (-1, pf_cpm_check_cycle (0x4000, 0x3FFF)); 46 | EXPECT_EQ (-1, pf_cpm_check_cycle (0x4000, 0x4000)); 47 | EXPECT_EQ (0, pf_cpm_check_cycle (0x4000, 0x4001)); 48 | EXPECT_EQ (0, pf_cpm_check_cycle (0x4000, 0x4002)); 49 | EXPECT_EQ (0, pf_cpm_check_cycle (0x4000, 0xFFFF)); 50 | 51 | /* Previous counter value was 0xFFFF (Forbidden zone ends at 0xFFFF) */ 52 | EXPECT_EQ (0, pf_cpm_check_cycle (0xFFFF, 0xEFFE)); 53 | EXPECT_EQ (0, pf_cpm_check_cycle (0xFFFF, 0xEFFF)); 54 | EXPECT_EQ (-1, pf_cpm_check_cycle (0xFFFF, 0xF000)); 55 | EXPECT_EQ (-1, pf_cpm_check_cycle (0xFFFF, 0xF001)); 56 | EXPECT_EQ (-1, pf_cpm_check_cycle (0xFFFF, 0xFFFE)); 57 | EXPECT_EQ (-1, pf_cpm_check_cycle (0xFFFF, 0xFFFF)); 58 | EXPECT_EQ (0, pf_cpm_check_cycle (0xFFFF, 0x0000)); 59 | EXPECT_EQ (0, pf_cpm_check_cycle (0xFFFF, 0x0001)); 60 | EXPECT_EQ (0, pf_cpm_check_cycle (0xFFFF, 0x0002)); 61 | 62 | /* Previous counter value was 0x0000 (Forbidden zone ends at 0x0000) */ 63 | EXPECT_EQ (0, pf_cpm_check_cycle (0x0000, 0xEFFE)); 64 | EXPECT_EQ (0, pf_cpm_check_cycle (0x0000, 0xEFFF)); 65 | EXPECT_EQ (0, pf_cpm_check_cycle (0x0000, 0xF000)); 66 | EXPECT_EQ (-1, pf_cpm_check_cycle (0x0000, 0xF001)); 67 | EXPECT_EQ (-1, pf_cpm_check_cycle (0x0000, 0xFFFE)); 68 | EXPECT_EQ (-1, pf_cpm_check_cycle (0x0000, 0xFFFF)); 69 | EXPECT_EQ (-1, pf_cpm_check_cycle (0x0000, 0x0000)); 70 | EXPECT_EQ (0, pf_cpm_check_cycle (0x0000, 0x0001)); 71 | EXPECT_EQ (0, pf_cpm_check_cycle (0x0000, 0x0002)); 72 | 73 | /* Previous counter value was 0x0FFE (Forbidden zone starts at 0xFFFF) */ 74 | EXPECT_EQ (0, pf_cpm_check_cycle (0x0FFE, 0xFFFE)); 75 | EXPECT_EQ (-1, pf_cpm_check_cycle (0x0FFE, 0xFFFF)); 76 | EXPECT_EQ (-1, pf_cpm_check_cycle (0x0FFE, 0x0000)); 77 | EXPECT_EQ (-1, pf_cpm_check_cycle (0x0FFE, 0x0001)); 78 | EXPECT_EQ (-1, pf_cpm_check_cycle (0x0FFE, 0x0FFE)); 79 | EXPECT_EQ (0, pf_cpm_check_cycle (0x0FFE, 0x0FFF)); 80 | EXPECT_EQ (0, pf_cpm_check_cycle (0x0FFE, 0x1000)); 81 | EXPECT_EQ (0, pf_cpm_check_cycle (0x0FFE, 0x1001)); 82 | 83 | /* Previous counter value was 0x0FFF (Forbidden zone starts at zero) */ 84 | EXPECT_EQ (0, pf_cpm_check_cycle (0x0FFF, 0xFFFE)); 85 | EXPECT_EQ (0, pf_cpm_check_cycle (0x0FFF, 0xFFFF)); 86 | EXPECT_EQ (-1, pf_cpm_check_cycle (0x0FFF, 0x0000)); 87 | EXPECT_EQ (-1, pf_cpm_check_cycle (0x0FFF, 0x0001)); 88 | EXPECT_EQ (-1, pf_cpm_check_cycle (0x0FFF, 0x0FFE)); 89 | EXPECT_EQ (-1, pf_cpm_check_cycle (0x0FFF, 0x0FFF)); 90 | EXPECT_EQ (0, pf_cpm_check_cycle (0x0FFF, 0x1000)); 91 | EXPECT_EQ (0, pf_cpm_check_cycle (0x0FFF, 0x1001)); 92 | 93 | /* Previous counter value was 0x0010 (Forbidden zone overlaps zero) */ 94 | EXPECT_EQ (0, pf_cpm_check_cycle (0x0010, 0xF00F)); 95 | EXPECT_EQ (0, pf_cpm_check_cycle (0x0010, 0xF010)); 96 | EXPECT_EQ (-1, pf_cpm_check_cycle (0x0010, 0xF011)); 97 | EXPECT_EQ (-1, pf_cpm_check_cycle (0x0010, 0xFFFE)); 98 | EXPECT_EQ (-1, pf_cpm_check_cycle (0x0010, 0xFFFF)); 99 | EXPECT_EQ (-1, pf_cpm_check_cycle (0x0010, 0x0000)); 100 | EXPECT_EQ (-1, pf_cpm_check_cycle (0x0010, 0x0001)); 101 | EXPECT_EQ (-1, pf_cpm_check_cycle (0x0010, 0x000E)); 102 | EXPECT_EQ (-1, pf_cpm_check_cycle (0x0010, 0x000F)); 103 | EXPECT_EQ (-1, pf_cpm_check_cycle (0x0010, 0x0010)); 104 | EXPECT_EQ (0, pf_cpm_check_cycle (0x0010, 0x0011)); 105 | EXPECT_EQ (0, pf_cpm_check_cycle (0x0010, 0x0012)); 106 | } 107 | -------------------------------------------------------------------------------- /test/test_eth.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * _ _ _ 3 | * _ __ | |_ _ | | __ _ | |__ ___ 4 | * | '__|| __|(_)| | / _` || '_ \ / __| 5 | * | | | |_ _ | || (_| || |_) |\__ \ 6 | * |_| \__|(_)|_| \__,_||_.__/ |___/ 7 | * 8 | * www.rt-labs.com 9 | * Copyright 2018 rt-labs AB, Sweden. 10 | * 11 | * This software is dual-licensed under GPLv3 and a commercial 12 | * license. See the file LICENSE.md distributed with this software for 13 | * full license information. 14 | ********************************************************************/ 15 | 16 | #include "utils_for_testing.h" 17 | #include "mocks.h" 18 | 19 | #include "pf_includes.h" 20 | 21 | #include 22 | 23 | class EthTest : public PnetIntegrationTest 24 | { 25 | }; 26 | 27 | TEST_F (EthTest, EthRunTest) 28 | { 29 | } 30 | -------------------------------------------------------------------------------- /test/test_fspm.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * _ _ _ 3 | * _ __ | |_ _ | | __ _ | |__ ___ 4 | * | '__|| __|(_)| | / _` || '_ \ / __| 5 | * | | | |_ _ | || (_| || |_) |\__ \ 6 | * |_| \__|(_)|_| \__,_||_.__/ |___/ 7 | * 8 | * www.rt-labs.com 9 | * Copyright 2018 rt-labs AB, Sweden. 10 | * 11 | * This software is dual-licensed under GPLv3 and a commercial 12 | * license. See the file LICENSE.md distributed with this software for 13 | * full license information. 14 | ********************************************************************/ 15 | 16 | #include "utils_for_testing.h" 17 | #include "mocks.h" 18 | 19 | #include "pf_includes.h" 20 | 21 | #include 22 | 23 | class FspmTest : public PnetIntegrationTest 24 | { 25 | }; 26 | 27 | class FspmUnitTest : public PnetUnitTest 28 | { 29 | }; 30 | 31 | TEST_F (FspmUnitTest, FspmCheckValidateConfiguration) 32 | { 33 | pnet_cfg_t cfg; 34 | 35 | /* Known good values */ 36 | memset (&cfg, 0, sizeof (pnet_cfg_t)); 37 | cfg.tick_us = 1000; 38 | cfg.min_device_interval = 1; 39 | cfg.im_0_data.im_supported = 0; 40 | cfg.if_cfg.main_netif_name = "eth0"; 41 | cfg.num_physical_ports = PNET_MAX_PHYSICAL_PORTS; 42 | 43 | EXPECT_EQ (pf_fspm_validate_configuration (&cfg), 0); 44 | 45 | /* Check pointer validity */ 46 | EXPECT_EQ (pf_fspm_validate_configuration (NULL), -1); 47 | 48 | /* Check number of ports */ 49 | cfg.num_physical_ports = PNET_MAX_PHYSICAL_PORTS + 1; 50 | EXPECT_EQ (pf_fspm_validate_configuration (&cfg), -1); 51 | 52 | cfg.num_physical_ports = 0; 53 | EXPECT_EQ (pf_fspm_validate_configuration (&cfg), -1); 54 | 55 | cfg.num_physical_ports = 1; 56 | EXPECT_EQ (pf_fspm_validate_configuration (&cfg), 0); 57 | 58 | cfg.num_physical_ports = PNET_MAX_PHYSICAL_PORTS; 59 | EXPECT_EQ (pf_fspm_validate_configuration (&cfg), 0); 60 | 61 | /* Check minimum stack update interval */ 62 | cfg.min_device_interval = 0; 63 | EXPECT_EQ (pf_fspm_validate_configuration (&cfg), -1); 64 | 65 | cfg.min_device_interval = 0x1000; 66 | EXPECT_EQ (pf_fspm_validate_configuration (&cfg), 0); 67 | 68 | cfg.min_device_interval = 0x1001; 69 | EXPECT_EQ (pf_fspm_validate_configuration (&cfg), -1); 70 | 71 | cfg.min_device_interval = 0xFFFF; 72 | EXPECT_EQ (pf_fspm_validate_configuration (&cfg), -1); 73 | cfg.min_device_interval = 1; 74 | 75 | /* Check supported I&M fields */ 76 | cfg.im_0_data.im_supported = PNET_SUPPORTED_IM1; 77 | EXPECT_EQ (pf_fspm_validate_configuration (&cfg), 0); 78 | 79 | cfg.im_0_data.im_supported = PNET_SUPPORTED_IM1 | PNET_SUPPORTED_IM2; 80 | EXPECT_EQ (pf_fspm_validate_configuration (&cfg), 0); 81 | 82 | cfg.im_0_data.im_supported = PNET_SUPPORTED_IM1 | PNET_SUPPORTED_IM2 | 83 | PNET_SUPPORTED_IM3 | PNET_SUPPORTED_IM4; 84 | EXPECT_EQ (pf_fspm_validate_configuration (&cfg), 0); 85 | 86 | cfg.im_0_data.im_supported = PNET_SUPPORTED_IM4; 87 | EXPECT_EQ (pf_fspm_validate_configuration (&cfg), 0); 88 | 89 | cfg.im_0_data.im_supported = 1; 90 | EXPECT_EQ (pf_fspm_validate_configuration (&cfg), -1); 91 | 92 | cfg.im_0_data.im_supported = 0x0020; 93 | EXPECT_EQ (pf_fspm_validate_configuration (&cfg), -1); 94 | 95 | cfg.im_0_data.im_supported = 0x8000; 96 | EXPECT_EQ (pf_fspm_validate_configuration (&cfg), -1); 97 | 98 | cfg.im_0_data.im_supported = 0xFFFF; 99 | EXPECT_EQ (pf_fspm_validate_configuration (&cfg), -1); 100 | cfg.im_0_data.im_supported = 0; 101 | } 102 | 103 | TEST_F (FspmTest, FspmGetImLocation) 104 | { 105 | const char expected[PNET_LOCATION_MAX_SIZE] = " "; 106 | char actual[PNET_LOCATION_MAX_SIZE]; 107 | 108 | memset (actual, 0xff, sizeof (actual)); 109 | 110 | /* Note that as loading from file failed in pf_fspm_init(), location was set 111 | * to its default value, which is all spaces. 112 | */ 113 | pf_fspm_get_im_location (net, actual); 114 | EXPECT_STREQ (actual, expected); 115 | EXPECT_EQ (strlen (actual), 22u); 116 | } 117 | 118 | TEST_F (FspmTest, FspmSaveImLocation) 119 | { 120 | const char written[PNET_LOCATION_MAX_SIZE] = "location of device"; 121 | const char expected[PNET_LOCATION_MAX_SIZE] = "location of device "; 122 | char actual[PNET_LOCATION_MAX_SIZE]; 123 | 124 | memset (actual, 0xff, sizeof (actual)); 125 | 126 | /* Note that extra spaces are added at the end */ 127 | pf_fspm_save_im_location (net, written); 128 | 129 | /* The file save operation below is performed by the background worker 130 | * during normal execution of the stack. 131 | */ 132 | pf_fspm_save_im (net); 133 | 134 | pf_fspm_get_im_location (net, actual); 135 | EXPECT_STREQ (actual, expected); 136 | EXPECT_EQ (strlen (actual), 22u); 137 | EXPECT_STREQ (mock_file_data.filename, PF_FILENAME_IM); 138 | } 139 | 140 | TEST_F (FspmTest, FspmSaveImLocationShouldAddTermination) 141 | { 142 | char not_terminated[PNET_LOCATION_MAX_SIZE]; 143 | char actual[PNET_LOCATION_MAX_SIZE]; 144 | 145 | memset (actual, 0xff, sizeof (actual)); 146 | memset (not_terminated, 'n', sizeof (not_terminated)); 147 | 148 | pf_fspm_save_im_location (net, not_terminated); 149 | 150 | /* The file save operation below is performed by the background worker 151 | * during normal execution of the stack. 152 | */ 153 | pf_fspm_save_im (net); 154 | 155 | pf_fspm_get_im_location (net, actual); 156 | EXPECT_EQ (actual[sizeof (actual) - 1], '\0'); 157 | EXPECT_EQ (strlen (actual), 22u); 158 | EXPECT_STREQ (mock_file_data.filename, PF_FILENAME_IM); 159 | } 160 | 161 | TEST_F (FspmTest, FspmSaveImLocationShouldTruncateLargeStrings) 162 | { 163 | const char large[] = "123456789012345678901234567890"; 164 | const char expected[] = "1234567890123456789012"; 165 | char actual[PNET_LOCATION_MAX_SIZE]; 166 | 167 | memset (actual, 0xff, sizeof (actual)); 168 | 169 | pf_fspm_save_im_location (net, large); 170 | 171 | /* The file save operation below is performed by the background worker 172 | * during normal execution of the stack. 173 | */ 174 | pf_fspm_save_im (net); 175 | 176 | pf_fspm_get_im_location (net, actual); 177 | EXPECT_STREQ (actual, expected); 178 | EXPECT_EQ (strlen (actual), 22u); 179 | EXPECT_STREQ (mock_file_data.filename, PF_FILENAME_IM); 180 | } 181 | -------------------------------------------------------------------------------- /test/test_ppm.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * _ _ _ 3 | * _ __ | |_ _ | | __ _ | |__ ___ 4 | * | '__|| __|(_)| | / _` || '_ \ / __| 5 | * | | | |_ _ | || (_| || |_) |\__ \ 6 | * |_| \__|(_)|_| \__,_||_.__/ |___/ 7 | * 8 | * www.rt-labs.com 9 | * Copyright 2018 rt-labs AB, Sweden. 10 | * 11 | * This software is dual-licensed under GPLv3 and a commercial 12 | * license. See the file LICENSE.md distributed with this software for 13 | * full license information. 14 | ********************************************************************/ 15 | 16 | #include "utils_for_testing.h" 17 | #include "mocks.h" 18 | 19 | #include "pf_includes.h" 20 | 21 | #include 22 | 23 | class PpmTest : public PnetIntegrationTest 24 | { 25 | }; 26 | 27 | class PpmUnitTest : public PnetUnitTest 28 | { 29 | }; 30 | 31 | TEST_F (PpmTest, PpmTestCalculateCycle) 32 | { 33 | /* Cycle length 31.25 us, transmission period 31.25 us */ 34 | EXPECT_EQ (pf_ppm_calculate_cyclecounter (0, 1, 1), 0); 35 | EXPECT_EQ (pf_ppm_calculate_cyclecounter (20, 1, 1), 0); 36 | EXPECT_EQ (pf_ppm_calculate_cyclecounter (40, 1, 1), 1); 37 | EXPECT_EQ (pf_ppm_calculate_cyclecounter (70, 1, 1), 2); 38 | 39 | /* Cycle length 62.5 us, transmission period 62.5 us */ 40 | EXPECT_EQ (pf_ppm_calculate_cyclecounter (0, 2, 1), 0); 41 | EXPECT_EQ (pf_ppm_calculate_cyclecounter (10, 2, 1), 0); 42 | EXPECT_EQ (pf_ppm_calculate_cyclecounter (50, 2, 1), 0); 43 | EXPECT_EQ (pf_ppm_calculate_cyclecounter (80, 2, 1), 2); 44 | EXPECT_EQ (pf_ppm_calculate_cyclecounter (100, 2, 1), 2); 45 | EXPECT_EQ (pf_ppm_calculate_cyclecounter (140, 2, 1), 4); 46 | EXPECT_EQ (pf_ppm_calculate_cyclecounter (160, 2, 1), 4); 47 | 48 | /* Cycle length 62.5 us, transmission period 500 us */ 49 | EXPECT_EQ (pf_ppm_calculate_cyclecounter (0, 2, 8), 0); 50 | EXPECT_EQ (pf_ppm_calculate_cyclecounter (250, 2, 8), 0); 51 | EXPECT_EQ (pf_ppm_calculate_cyclecounter (750, 2, 8), 16); 52 | EXPECT_EQ (pf_ppm_calculate_cyclecounter (1250, 2, 8), 32); 53 | 54 | /* Cycle length 125 us, transmission period 500 us */ 55 | EXPECT_EQ (pf_ppm_calculate_cyclecounter (0, 4, 4), 0); 56 | EXPECT_EQ (pf_ppm_calculate_cyclecounter (250, 4, 4), 0); 57 | EXPECT_EQ (pf_ppm_calculate_cyclecounter (750, 4, 4), 16); 58 | EXPECT_EQ (pf_ppm_calculate_cyclecounter (1250, 4, 4), 32); 59 | 60 | /* Cycle length 1 ms, transmission period 4 ms */ 61 | EXPECT_EQ (pf_ppm_calculate_cyclecounter (0, 32, 4), 0); 62 | EXPECT_EQ (pf_ppm_calculate_cyclecounter (3000, 32, 4), 0); 63 | EXPECT_EQ (pf_ppm_calculate_cyclecounter (5000, 32, 4), 128); 64 | EXPECT_EQ (pf_ppm_calculate_cyclecounter (7000, 32, 4), 128); 65 | EXPECT_EQ (pf_ppm_calculate_cyclecounter (9000, 32, 4), 256); 66 | } 67 | 68 | TEST_F (PpmTest, PpmTestCalculateNextCycle) 69 | { 70 | /* Cycle length 31.25 us, transmission period 31.25 us */ 71 | EXPECT_EQ (pf_ppm_calculate_next_cyclecounter (0, 1, 1), 1); 72 | EXPECT_EQ (pf_ppm_calculate_next_cyclecounter (1, 1, 1), 2); 73 | EXPECT_EQ (pf_ppm_calculate_next_cyclecounter (2, 1, 1), 3); 74 | EXPECT_EQ (pf_ppm_calculate_next_cyclecounter (3, 1, 1), 4); 75 | EXPECT_EQ (pf_ppm_calculate_next_cyclecounter (4, 1, 1), 5); 76 | EXPECT_EQ (pf_ppm_calculate_next_cyclecounter (5, 1, 1), 6); 77 | EXPECT_EQ (pf_ppm_calculate_next_cyclecounter (6, 1, 1), 7); 78 | EXPECT_EQ (pf_ppm_calculate_next_cyclecounter (0xFFFF, 1, 1), 0); 79 | 80 | /* Cycle length 62.5 us, transmission period 62.5 us */ 81 | EXPECT_EQ (pf_ppm_calculate_next_cyclecounter (0, 2, 1), 2); 82 | EXPECT_EQ (pf_ppm_calculate_next_cyclecounter (1, 2, 1), 2); 83 | EXPECT_EQ (pf_ppm_calculate_next_cyclecounter (2, 2, 1), 4); 84 | EXPECT_EQ (pf_ppm_calculate_next_cyclecounter (3, 2, 1), 4); 85 | EXPECT_EQ (pf_ppm_calculate_next_cyclecounter (4, 2, 1), 6); 86 | EXPECT_EQ (pf_ppm_calculate_next_cyclecounter (5, 2, 1), 6); 87 | EXPECT_EQ (pf_ppm_calculate_next_cyclecounter (6, 2, 1), 8); 88 | EXPECT_EQ (pf_ppm_calculate_next_cyclecounter (7, 2, 1), 8); 89 | EXPECT_EQ (pf_ppm_calculate_next_cyclecounter (8, 2, 1), 10); 90 | EXPECT_EQ (pf_ppm_calculate_next_cyclecounter (9, 2, 1), 10); 91 | EXPECT_EQ (pf_ppm_calculate_next_cyclecounter (10, 2, 1), 12); 92 | EXPECT_EQ (pf_ppm_calculate_next_cyclecounter (0xFFFD, 2, 1), 0xFFFE); 93 | EXPECT_EQ (pf_ppm_calculate_next_cyclecounter (0xFFFE, 2, 1), 0); 94 | EXPECT_EQ (pf_ppm_calculate_next_cyclecounter (0xFFFF, 2, 1), 0); 95 | 96 | /* Cycle length 62.5 us, transmission period 250 us */ 97 | EXPECT_EQ (pf_ppm_calculate_next_cyclecounter (0, 2, 4), 8); 98 | EXPECT_EQ (pf_ppm_calculate_next_cyclecounter (7, 2, 4), 8); 99 | EXPECT_EQ (pf_ppm_calculate_next_cyclecounter (8, 2, 4), 16); 100 | EXPECT_EQ (pf_ppm_calculate_next_cyclecounter (9, 2, 4), 16); 101 | EXPECT_EQ (pf_ppm_calculate_next_cyclecounter (0xFFFE, 2, 4), 0); 102 | EXPECT_EQ (pf_ppm_calculate_next_cyclecounter (0xFFFF, 2, 4), 0); 103 | 104 | /* Cycle length 1 ms, transmission period 4 ms */ 105 | EXPECT_EQ (pf_ppm_calculate_next_cyclecounter (0, 32, 4), 128); 106 | EXPECT_EQ (pf_ppm_calculate_next_cyclecounter (1, 32, 4), 128); 107 | EXPECT_EQ (pf_ppm_calculate_next_cyclecounter (2, 32, 4), 128); 108 | EXPECT_EQ (pf_ppm_calculate_next_cyclecounter (3, 32, 4), 128); 109 | EXPECT_EQ (pf_ppm_calculate_next_cyclecounter (127, 32, 4), 128); 110 | EXPECT_EQ (pf_ppm_calculate_next_cyclecounter (128, 32, 4), 256); 111 | EXPECT_EQ (pf_ppm_calculate_next_cyclecounter (129, 32, 4), 256); 112 | 113 | EXPECT_EQ (pf_ppm_calculate_next_cyclecounter (0x00, 32, 4), 0x080); 114 | EXPECT_EQ (pf_ppm_calculate_next_cyclecounter (0x7F, 32, 4), 0x080); 115 | EXPECT_EQ (pf_ppm_calculate_next_cyclecounter (0x80, 32, 4), 0x100); 116 | EXPECT_EQ (pf_ppm_calculate_next_cyclecounter (0x81, 32, 4), 0x100); 117 | EXPECT_EQ (pf_ppm_calculate_next_cyclecounter (0xFE, 32, 4), 0x100); 118 | EXPECT_EQ (pf_ppm_calculate_next_cyclecounter (0xFF, 32, 4), 0x100); 119 | EXPECT_EQ (pf_ppm_calculate_next_cyclecounter (0x100, 32, 4), 0x180); 120 | EXPECT_EQ (pf_ppm_calculate_next_cyclecounter (0x101, 32, 4), 0x180); 121 | EXPECT_EQ (pf_ppm_calculate_next_cyclecounter (0xFEFF, 32, 4), 0xFF00); 122 | EXPECT_EQ (pf_ppm_calculate_next_cyclecounter (0xFF00, 32, 4), 0xFF80); 123 | EXPECT_EQ (pf_ppm_calculate_next_cyclecounter (0xFF01, 32, 4), 0xFF80); 124 | EXPECT_EQ (pf_ppm_calculate_next_cyclecounter (0xFF7E, 32, 4), 0xFF80); 125 | EXPECT_EQ (pf_ppm_calculate_next_cyclecounter (0xFF7F, 32, 4), 0xFF80); 126 | EXPECT_EQ (pf_ppm_calculate_next_cyclecounter (0xFF80, 32, 4), 0); 127 | EXPECT_EQ (pf_ppm_calculate_next_cyclecounter (0xFF81, 32, 4), 0); 128 | EXPECT_EQ (pf_ppm_calculate_next_cyclecounter (0xFFFE, 32, 4), 0); 129 | EXPECT_EQ (pf_ppm_calculate_next_cyclecounter (0xFFFF, 32, 4), 0); 130 | 131 | /* Cycle length 4 ms, transmission period 2.048 s */ 132 | EXPECT_EQ (pf_ppm_calculate_next_cyclecounter (0, 128, 512), 0); 133 | EXPECT_EQ (pf_ppm_calculate_next_cyclecounter (1, 128, 512), 0); 134 | EXPECT_EQ (pf_ppm_calculate_next_cyclecounter (2, 128, 512), 0); 135 | EXPECT_EQ (pf_ppm_calculate_next_cyclecounter (0xFFFE, 128, 512), 0); 136 | EXPECT_EQ (pf_ppm_calculate_next_cyclecounter (0xFFFF, 128, 512), 0); 137 | } 138 | -------------------------------------------------------------------------------- /test/test_ptcp.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * _ _ _ 3 | * _ __ | |_ _ | | __ _ | |__ ___ 4 | * | '__|| __|(_)| | / _` || '_ \ / __| 5 | * | | | |_ _ | || (_| || |_) |\__ \ 6 | * |_| \__|(_)|_| \__,_||_.__/ |___/ 7 | * 8 | * www.rt-labs.com 9 | * Copyright 2018 rt-labs AB, Sweden. 10 | * 11 | * This software is dual-licensed under GPLv3 and a commercial 12 | * license. See the file LICENSE.md distributed with this software for 13 | * full license information. 14 | ********************************************************************/ 15 | 16 | #include "utils_for_testing.h" 17 | #include "mocks.h" 18 | 19 | #include "pf_includes.h" 20 | 21 | #include 22 | 23 | class PtcpTest : public PnetIntegrationTest 24 | { 25 | }; 26 | 27 | TEST_F (PtcpTest, PtcpRunTest) 28 | { 29 | } 30 | -------------------------------------------------------------------------------- /tools/clean_no_alarm.sh: -------------------------------------------------------------------------------- 1 | number_of_arguments=$# 2 | directory=$1 3 | mode_argument=$2 4 | 5 | if [ "$number_of_arguments" -eq 0 ] || [ "$number_of_arguments" -gt 2 ]; then 6 | echo "Usage: clean_no_alarm.sh directory [-a]" 7 | echo 8 | echo "Remove wireshark files that don't contain Profinet alarm frames." 9 | echo 10 | echo "By default this script will examine the next-newest file in the directory." 11 | echo "Give the -a argument to scan all files in the directory." 12 | echo 13 | echo "Use the watch command to run this repeatedly:" 14 | echo " watch -n 10 ./clean_no_alarm.sh DIRECTORYNAME" 15 | echo 16 | echo "where the -n argument specifies the number of seconds between each invocation." 17 | echo 18 | echo "This tool uses the tshark program, which must be installed." 19 | echo 20 | echo "To record the files it is recommended to use the tcpdump utility to continuously" 21 | echo "save data into 10 MByte files:" 22 | echo " sudo tcpdump -i INTERFACENAME -C 10 -w recordingfile -K -n" 23 | echo "The directory that the files are saved into must have write permission for all:" 24 | echo " chmod o+w DIRECTORYNAME" 25 | 26 | # Handling both sourced and executed script 27 | return 1 2>/dev/null 28 | exit 1 29 | fi 30 | 31 | # Delete a wireshark pcap file if it doesn't contain any Profinet alarm frames 32 | examine_file () { 33 | full_path=$1 34 | echo "Examining the file: ${full_path}" 35 | 36 | file_description=`file ${full_path}` 37 | case "$file_description" in 38 | *capture*) ;; 39 | * ) echo " Not a wireshark file"; return ;; 40 | esac 41 | 42 | # Check if the file contains the Profinet frame ID for ALARM_PRIO_LOW 43 | number_of_alarm_frames=`tshark -r ${full_path} -T fields -e frame.number -Y "pn_rt.frame_id == 65025" | wc -l` 44 | if [ "$number_of_alarm_frames" -eq 0 ]; then 45 | echo " Deleting ${full_path} as it has no alarms" 46 | rm "$full_path" 47 | fi 48 | } 49 | 50 | if [ "$mode_argument" = "-a" ] 51 | then 52 | # Examine all files in directory 53 | for file in $directory/* 54 | do 55 | examine_file "$file" 56 | done 57 | else 58 | # Examine second newest file 59 | filename=`ls -1t $directory | sed -n '2p'` 60 | examine_file ${directory}/${filename} 61 | fi 62 | --------------------------------------------------------------------------------