35#ifndef _OPENLCB_CONFIGREPRESENTATION_HXX_
36#define _OPENLCB_CONFIGREPRESENTATION_HXX_
49 static constexpr unsigned size()
53 constexpr unsigned end_offset()
const
80 constexpr unsigned end_offset()
const
84 static constexpr unsigned size()
100 using Name = AtomConfigOptions::Name;
101 using Description = AtomConfigOptions::Description;
102 using MapValues = AtomConfigOptions::MapValues;
103 using Hints = AtomConfigOptions::Hints;
104 using SkipInit = AtomConfigOptions::SkipInit;
105 using Min = NumericConfigOptions::Min;
106 using Max = NumericConfigOptions::Max;
107 using Default = NumericConfigOptions::Default;
108 using Segment = GroupConfigOptions::Segment;
109 using Offset = GroupConfigOptions::Offset;
110 using RepName = GroupConfigOptions::RepName;
111 using FixedSize = GroupConfigOptions::FixedSize;
112 using Hidden = GroupConfigOptions::Hidden;
113 using LinkRef = GroupConfigOptions::LinkRef;
114 using LinkText = GroupConfigOptions::LinkText;
115 using Manufacturer = IdentificationConfigOptions::Manufacturer;
116 using Model = IdentificationConfigOptions::Model;
117 using HwVersion = IdentificationConfigOptions::HwVersion;
118 using SwVersion = IdentificationConfigOptions::SwVersion;
119 static constexpr Segment MainCdi()
134#define CDI_GROUP_HELPER(START_LINE, GroupName, ARGS...) \
135 struct GroupName : public openlcb::GroupBase \
137 INHERIT_CONSTEXPR_CONSTRUCTOR(GroupName, GroupBase); \
138 constexpr openlcb::GroupBaseEntry entry( \
139 const openlcb::EntryMarker<START_LINE> &) const \
141 return openlcb::GroupBaseEntry(offset_); \
143 template <typename... Args> \
144 static constexpr openlcb::GroupConfigOptions group_opts(Args... args) \
146 return openlcb::GroupConfigOptions(args..., ##ARGS); \
148 static constexpr unsigned size() \
150 return GroupName(0).end_offset(); \
152 static constexpr GroupName zero_offset_this() \
154 return GroupName(0); \
156 template <int LINE> \
157 constexpr openlcb::NoopGroupEntry entry( \
158 const openlcb::EntryMarker<LINE> &) const \
160 return openlcb::NoopGroupEntry( \
161 entry(openlcb::EntryMarker<LINE - 1>()).end_offset()); \
163 template <int LINE> \
164 static void render_content_cdi( \
165 const openlcb::EntryMarker<LINE> &, std::string *s) \
167 render_content_cdi(openlcb::EntryMarker<LINE - 1>(), s); \
169 static void render_content_cdi( \
170 const openlcb::EntryMarker<START_LINE> &, std::string *s) \
173 template <int LINE> \
174 void __attribute__((always_inline)) \
175 recursive_handle_events(const openlcb::EntryMarker<LINE> &, \
176 const openlcb::EventOffsetCallback &fn) \
178 recursive_handle_events(openlcb::EntryMarker<LINE - 1>(), fn); \
180 void __attribute__((always_inline)) \
181 recursive_handle_events(const openlcb::EntryMarker<START_LINE> &, \
182 const openlcb::EventOffsetCallback &fn) \
186 static constexpr openlcb::GroupConfigRenderer<GroupName> \
189 return openlcb::GroupConfigRenderer<GroupName>(1, GroupName(0)); \
195#define CDI_GROUP_ENTRY_HELPER(LINE, NAME, TYPE, ...) \
196 constexpr TYPE entry(const openlcb::EntryMarker<LINE> &) const \
198 static_assert(!group_opts().is_cdi() || \
199 TYPE(0).group_opts(__VA_ARGS__).is_segment(), \
200 "May only have segments inside CDI."); \
201 return TYPE(group_opts().is_cdi() \
202 ? TYPE(0).group_opts(__VA_ARGS__).get_segment_offset() \
203 : entry(openlcb::EntryMarker<LINE - 1>()).end_offset() + \
204 NAME##_options().offset()); \
206 constexpr TYPE NAME() const \
208 return entry(openlcb::EntryMarker<LINE>()); \
210 static constexpr typename decltype(TYPE::config_renderer())::OptionsType \
213 using SelfType = TYPE; \
214 using OptionsType = \
215 typename decltype(SelfType::config_renderer())::OptionsType; \
216 return OptionsType(__VA_ARGS__); \
218 static void render_content_cdi( \
219 const openlcb::EntryMarker<LINE> &, std::string *s) \
221 render_content_cdi(openlcb::EntryMarker<LINE - 1>(), s); \
222 TYPE::config_renderer().render_cdi(s, ##__VA_ARGS__); \
224 void __attribute__((always_inline)) \
225 recursive_handle_events(const openlcb::EntryMarker<LINE> &e, \
226 const openlcb::EventOffsetCallback &fn) \
228 recursive_handle_events(openlcb::EntryMarker<LINE - 1>(), fn); \
229 if ((!TYPE(0).group_opts(__VA_ARGS__).is_segment() || \
230 TYPE(0).group_opts(__VA_ARGS__).segment() == \
231 openlcb::MemoryConfigDefs::SPACE_CONFIG) && \
232 NAME##_options().skip_init() == 0) \
234 entry(e).handle_events(fn); \
242#define CDI_GROUP_END_HELPER(LINE) \
243 constexpr unsigned end_offset() const \
245 static_assert((group_opts().fixed_size() == 0) || \
246 (zero_offset_this() \
247 .entry(openlcb::EntryMarker<LINE>()) \
248 .end_offset() <= (unsigned)group_opts().fixed_size()), \
249 "FixedSize group contents too large"); \
250 return (group_opts().fixed_size() == 0) \
251 ? entry(openlcb::EntryMarker<LINE>()).end_offset() \
252 : offset_ + group_opts().fixed_size(); \
254 constexpr unsigned end_buffer_length() const \
256 return group_opts().fixed_size() - \
257 (entry(openlcb::EntryMarker<LINE>()).end_offset() - offset()); \
259 static void render_content_cdi(std::string *s) \
261 return render_content_cdi(openlcb::EntryMarker<LINE>(), s); \
263 void __attribute__((always_inline)) \
264 handle_events(const openlcb::EventOffsetCallback &fn) \
266 recursive_handle_events(openlcb::EntryMarker<LINE>(), fn); \
275#define CDI_GROUP(GroupName, ARGS...) \
276 CDI_GROUP_HELPER(__LINE__, GroupName, ##ARGS)
286#define CDI_GROUP_ENTRY(NAME, TYPE, ARGS...) \
287 CDI_GROUP_ENTRY_HELPER(__LINE__, NAME, TYPE, ##ARGS)
290#define CDI_GROUP_END() CDI_GROUP_END_HELPER(__LINE__)
301#define CDI_FACTORY_RESET(PATH) \
302 PATH().write(fd, PATH##_options().defaultvalue())
311#define CDI_READ_TRIMMED(PATH, fd) \
312 PATH().read_or_write_trimmed( \
313 fd, PATH##_options().minvalue(), PATH##_options().maxvalue())
322#define CDI_READ_TRIM_DEFAULT(PATH, fd) \
323 PATH().read_or_write_default(fd, PATH##_options().minvalue(), \
324 PATH##_options().maxvalue(), PATH##_options().defaultvalue())
338 static constexpr unsigned size()
340 return Group::size() * N;
342 constexpr unsigned end_offset()
const
344 return offset() + size();
346 static constexpr unsigned num_repeats()
350 template <
int K>
constexpr Group entry()
const
352 static_assert(K < N,
"Tried to fetch an entry of a repeated "
353 "group that does not exist!");
354 return Group(
offset_ + (K * Group::size()));
357 Group entry(
unsigned k)
360 return Group(
offset_ + (k * Group::size()));
371 for (
unsigned i = 0; i < N; ++i)
373 entry(i).handle_events(fn);
387 static constexpr int size()
391 constexpr unsigned end_offset()
const
393 return offset() + size();
411 template<
typename... Args>
416 static constexpr unsigned size()
420 constexpr unsigned end_offset()
const
422 return offset() + size();
462 "This name will appear in network browsers for this device."));
465 Name(
"User Description"),
466 Description(
"This description will appear in network browsers for "
475 Description(
"Do not change these settings."));
487template <
typename CdiType>
515#define RENDER_CDI(NS, TYPE, NAME, N) \
516 template <> inline void render_all_cdi<2 * N>() \
519 render_cdi_helper(def, #NS, NAME); \
520 render_all_cdi<2 * N - 1>(); \
void render_cdi_helper(const CdiType &t, string ns, string name)
Helper function defined in CompileCdiMain.cxx.
void render_all_cdi< 0 >()
End-of-recursion template instantiation for CDI rendering.
void render_all_cdi()
Forward declaration of the recursive helper template for adding multiple CDIs to a single binary imag...
#define CDI_GROUP(GroupName, ARGS...)
Starts a CDI group.
#define CDI_GROUP_ENTRY(NAME, TYPE, ARGS...)
Adds an entry to a CDI group.
Helper class for rendering the "<acdi>" tag.
Renders an "<acdi>" tag in the CDI group.
Base class for individual configuration entries.
Class representing a particular location in the configuration space.
unsigned offset_
zero-based offset from the beginning of the configuration file.
Helper class for rendering an empty group of a given size into the cdi.xml.
Defines an empty group with no members, but blocking a certain amount of space in the rendered config...
Helper class for partial template specialization.
Constexpr base class for all group like structures.
Base class for all CDI Group structures (including segment, and the whole CDI entry).
Implementation class for the condifuration options of a CDI group element.
Helper class for rendering the cdi.xml of groups, segments and the toplevel CDI node.
Helper class for rendering the "<identification>" tag.
Add this entry to the beginning of the CDI group to render an "<identification>" tag at the beginning...
Empty group entry that can be used for structuring the CDI configs.
Implementation class for numeric configuration entries, templated by the integer type.
Defines a repeated group of a given type and a given number of repeats.
static constexpr GroupConfigRenderer< Group > config_renderer()
Implementation class for string configuration entries.
Base class for all entries that can appear in the MainCdi group.
#define HASSERT(x)
Checks that the value of expression x is true, else terminates the current process.
#define INHERIT_CONSTEXPR_CONSTRUCTOR(CURRENT_CLASS, BASE_CLASS)
Adds a constexpr constructor to the current class that proxies every argument to the base constructor...
CDI_GROUP_END()
Signals termination of the group.
std::function< void(unsigned)> EventOffsetCallback
Function declaration that will be called with all event offsets that exist in the configuration space...
@ SPACE_ACDI_USR
read-write ACDI space