GCC Code Coverage Report


Directory: ./
File: src/devices/Infra.cpp
Date: 2026-09-03 16:05:57
Exec Total Coverage
Lines: 29 42 69.0%
Branches: 11 62 17.7%

Line Branch Exec Source
1 /*****************************************************************************
2 *
3 * This file is part of the ecapp library (EtherCAT application devices).
4 *
5 * Copyright (C) 2026 Florian Pose <fp@igh.de>
6 *
7 * The ecapp library is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public License
9 * as published by the Free Software Foundation, version 3 of the
10 * License.
11 *
12 * The ecapp library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with the ecapp library. If not, see
19 * <https://www.gnu.org/licenses/>.
20 *
21 ****************************************************************************/
22
23 #include "devices/Infra.h"
24
25 #include "SlaveContext.h"
26 #include "ecapp/Exceptions.h"
27 #include "ecapp/Factory.h"
28 #include "ecapp/Master.h"
29
30 #include <memory>
31 #include <sstream>
32 #include <stdexcept>
33
34 /****************************************************************************/
35
36 using std::make_unique;
37 using std::runtime_error;
38 using std::size_t;
39 using std::stringstream;
40 using std::unique_ptr;
41
42 namespace EcApp {
43
44 struct InfraType
45 {
46 const char *name;
47 uint32_t vendor_id;
48 uint32_t product_code;
49 };
50
51 const static InfraType infraType[Infra<Mode::Control>::NumTypes] = {
52 {"EK1100", 0x00000002, 0x044c2c52},
53 {"EK1110", 0x00000002, 0x04562c52},
54 {"EK1122", 0x00000002, 0x04622c52},
55 {"EPP1332-0001", 0x00000002, 0x64761949},
56 {"EPP9001-0060", 0x00000002, 0x6477f899},
57 };
58
59 /****************************************************************************/
60
61 template <Mode mode>
62 2 Infra<mode>::Infra(
63 Master *master,
64 uint16_t alias,
65 uint16_t position,
66 Type typeIdx) :
67 2 type(infraType[typeIdx]), sc(NULL)
68 {
69
1/4
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 if (!master) {
70 2 return;
71 }
72
73 sc = ecrt_master_slave_config(
74 master->getMaster(), alias, position, type.vendor_id,
75 type.product_code);
76 if (!sc) {
77 stringstream err;
78 err << "Failed to get slave configuration.";
79 throw runtime_error(err.str());
80 }
81 }
82
83 /****************************************************************************/
84
85 template class Infra<Mode::Control>;
86 template class Infra<Mode::Simulation>;
87
88 /****************************************************************************/
89 // Generic SubDevice adapter: no inputs, no outputs -- Infra slaves only
90 // need a place in the bus topology. Application code never names
91 // Infra, only e.g. "EK1100" -- the factory resolves it.
92 /****************************************************************************/
93
94 template <Mode mode>
95 4 class InfraAdapter : public SubDevice
96 {
97 public:
98 2 InfraAdapter(const SlaveContext &ctx, typename Infra<mode>::Type t) :
99
1/4
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 9 taken 2 times.
✗ Branch 10 not taken.
2 device(ctx.master, ctx.alias, ctx.position, t)
100 2 {}
101
102 1 void updateInputs() override {}
103 1 void updateOutputs() override {}
104
105 3 const std::vector<ChannelKind> &inputKinds() const override
106 {
107 3 return inputKinds_;
108 }
109 2 const std::vector<ChannelKind> &outputKinds() const override
110 {
111 2 return outputKinds_;
112 }
113
114 protected:
115 ChannelValue getInputAt(size_t) const override
116 {
117 throw UnknownChannel("Infra has no input channels.");
118 }
119 void setOutputAt(size_t, const ChannelValue &) override
120 {
121 throw UnknownChannel("Infra has no output channels.");
122 }
123
124 private:
125 Infra<mode> device;
126 std::vector<ChannelKind> inputKinds_;
127 std::vector<ChannelKind> outputKinds_;
128 };
129
130 /****************************************************************************/
131
132 namespace {
133
134 40 DeviceFactoryFn makeInfraFactory(unsigned int typeIdx)
135 {
136 4 return [typeIdx](const SlaveContext &ctx) -> unique_ptr<SubDevice> {
137
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (ctx.mode == Mode::Control) {
138
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
4 return make_unique<InfraAdapter<Mode::Control>>(
139 6 ctx, static_cast<Infra<Mode::Control>::Type>(typeIdx));
140 }
141 else {
142 return make_unique<InfraAdapter<Mode::Simulation>>(
143 ctx, static_cast<Infra<Mode::Simulation>::Type>(typeIdx));
144 }
145 40 };
146 }
147
148 struct InfraRegistrations
149 {
150 8 InfraRegistrations()
151 {
152
2/2
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 8 times.
48 for (unsigned int i = 0; i < Infra<Mode::Control>::NumTypes; i++) {
153 40 const auto &t = infraType[i];
154
4/8
✓ Branch 3 taken 40 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 40 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 40 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 40 times.
✗ Branch 14 not taken.
240 Registry::instance().add(
155 120 {t.name, __FILE__, t.vendor_id, t.product_code,
156
1/2
✓ Branch 1 taken 40 times.
✗ Branch 2 not taken.
80 AnyRevision, wrapFactory(makeInfraFactory(i))});
157 }
158 8 }
159 8 } infraRegistrations;
160
161 } // namespace
162
163 24 } // namespace EcApp
164
165 /****************************************************************************/
166