mirror of
https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git
synced 2026-10-24 00:48:53 +03:00
Commit ea84f882d5 ("licensing: relicense C++ library code under
LGPL-3.0-or-later") changed the license of C++ bindings in order to
solve potential issues with code generated from templates[1], default
implementations, etc. However this change makes the bindings less
attractive to projects that have strict licensing restrictions and avoid
GPL-3.0 code[2].
After talking to Grant Likely I decided that the best approach is to
make the bindings available under LGPL-v2.1-or-later and simply let the
end user decide which version's text to apply.
While at it: tweak the README to also mention that examples are provided
under GPL-2.0-or-later.
Link: [1] https://www.spinics.net/lists/linux-gpio/msg46605.html
Link: [2] https://github.com/brgl/libgpiod/issues/72
Suggested-by: Walter Lozano <walter.lozano@collabora.com>
Suggested-by: Grant Likely <grant.likely@linaro.org>
Acked-by: Kent Gibson <warthog618@gmail.com>
Acked-by: Kevin Hilman <khilman@baylibre.com>
Acked-by: Grant Likely <grant.likely@linaro.org>
Link: https://lore.kernel.org/r/20240416212141.6683-2-brgl@bgdev.pl
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
331 lines
9.3 KiB
C++
331 lines
9.3 KiB
C++
// SPDX-License-Identifier: LGPL-2.1-or-later
|
|
// SPDX-FileCopyrightText: 2022 Bartosz Golaszewski <brgl@bgdev.pl>
|
|
|
|
#include <map>
|
|
#include <ostream>
|
|
|
|
#include "internal.hpp"
|
|
|
|
namespace gpiod {
|
|
|
|
namespace {
|
|
|
|
template<class cxx_enum_type, class c_enum_type>
|
|
::std::map<c_enum_type, cxx_enum_type>
|
|
make_reverse_maping(const ::std::map<cxx_enum_type, c_enum_type>& mapping)
|
|
{
|
|
::std::map<c_enum_type, cxx_enum_type> ret;
|
|
|
|
for (const auto &item: mapping)
|
|
ret[item.second] = item.first;
|
|
|
|
return ret;
|
|
}
|
|
|
|
const ::std::map<line::direction, ::gpiod_line_direction> direction_mapping = {
|
|
{ line::direction::AS_IS, GPIOD_LINE_DIRECTION_AS_IS },
|
|
{ line::direction::INPUT, GPIOD_LINE_DIRECTION_INPUT },
|
|
{ line::direction::OUTPUT, GPIOD_LINE_DIRECTION_OUTPUT },
|
|
};
|
|
|
|
const ::std::map<::gpiod_line_direction, line::direction>
|
|
reverse_direction_mapping = make_reverse_maping(direction_mapping);
|
|
|
|
const ::std::map<line::edge, ::gpiod_line_edge> edge_mapping = {
|
|
{ line::edge::NONE, GPIOD_LINE_EDGE_NONE },
|
|
{ line::edge::FALLING, GPIOD_LINE_EDGE_FALLING },
|
|
{ line::edge::RISING, GPIOD_LINE_EDGE_RISING },
|
|
{ line::edge::BOTH, GPIOD_LINE_EDGE_BOTH },
|
|
};
|
|
|
|
const ::std::map<::gpiod_line_edge, line::edge>
|
|
reverse_edge_mapping = make_reverse_maping(edge_mapping);
|
|
|
|
const ::std::map<line::bias, ::gpiod_line_bias> bias_mapping = {
|
|
{ line::bias::AS_IS, GPIOD_LINE_BIAS_AS_IS },
|
|
{ line::bias::DISABLED, GPIOD_LINE_BIAS_DISABLED },
|
|
{ line::bias::PULL_UP, GPIOD_LINE_BIAS_PULL_UP },
|
|
{ line::bias::PULL_DOWN, GPIOD_LINE_BIAS_PULL_DOWN },
|
|
};
|
|
|
|
const ::std::map<::gpiod_line_bias, line::bias>
|
|
reverse_bias_mapping = make_reverse_maping(bias_mapping);
|
|
|
|
const ::std::map<line::drive, ::gpiod_line_drive> drive_mapping = {
|
|
{ line::drive::PUSH_PULL, GPIOD_LINE_DRIVE_PUSH_PULL },
|
|
{ line::drive::OPEN_DRAIN, GPIOD_LINE_DRIVE_OPEN_DRAIN },
|
|
{ line::drive::OPEN_SOURCE, GPIOD_LINE_DRIVE_OPEN_SOURCE },
|
|
};
|
|
|
|
const ::std::map<::gpiod_line_drive, line::drive>
|
|
reverse_drive_mapping = make_reverse_maping(drive_mapping);
|
|
|
|
const ::std::map<line::clock, ::gpiod_line_clock> clock_mapping = {
|
|
{ line::clock::MONOTONIC, GPIOD_LINE_CLOCK_MONOTONIC },
|
|
{ line::clock::REALTIME, GPIOD_LINE_CLOCK_REALTIME },
|
|
{ line::clock::HTE, GPIOD_LINE_CLOCK_HTE },
|
|
};
|
|
|
|
const ::std::map<::gpiod_line_clock, line::clock>
|
|
reverse_clock_mapping = make_reverse_maping(clock_mapping);
|
|
|
|
const ::std::map<line::value, ::gpiod_line_value> value_mapping = {
|
|
{ line::value::INACTIVE, GPIOD_LINE_VALUE_INACTIVE },
|
|
{ line::value::ACTIVE, GPIOD_LINE_VALUE_ACTIVE },
|
|
};
|
|
|
|
const ::std::map<::gpiod_line_value, line::value>
|
|
reverse_value_mapping = make_reverse_maping(value_mapping);
|
|
|
|
line_settings_ptr make_line_settings()
|
|
{
|
|
line_settings_ptr settings(::gpiod_line_settings_new());
|
|
if (!settings)
|
|
throw_from_errno("Unable to allocate the line settings object");
|
|
|
|
return settings;
|
|
}
|
|
|
|
line_settings_ptr copy_line_settings(const line_settings_ptr& ptr)
|
|
{
|
|
line_settings_ptr settings(::gpiod_line_settings_copy(ptr.get()));
|
|
if (!settings)
|
|
throw_from_errno("Unable to copy the line settings object");
|
|
|
|
return settings;
|
|
}
|
|
|
|
template<class cxx_enum_type, class c_enum_type>
|
|
c_enum_type do_map_value(cxx_enum_type value, const ::std::map<cxx_enum_type, c_enum_type>& mapping)
|
|
try {
|
|
return get_mapped_value(value, mapping);
|
|
} catch (const bad_mapping& ex) {
|
|
throw ::std::invalid_argument(ex.what());
|
|
}
|
|
|
|
template<class cxx_enum_type, class c_enum_type, int set_func(::gpiod_line_settings*, c_enum_type)>
|
|
void set_mapped_prop(::gpiod_line_settings* settings, cxx_enum_type value,
|
|
const ::std::map<cxx_enum_type, c_enum_type>& mapping)
|
|
{
|
|
c_enum_type mapped_val = do_map_value(value, mapping);
|
|
|
|
auto ret = set_func(settings, mapped_val);
|
|
if (ret)
|
|
throw_from_errno("unable to set property");
|
|
}
|
|
|
|
template<class cxx_enum_type, class c_enum_type, c_enum_type get_func(::gpiod_line_settings*)>
|
|
cxx_enum_type get_mapped_prop(::gpiod_line_settings* settings,
|
|
const ::std::map<c_enum_type, cxx_enum_type>& mapping)
|
|
{
|
|
auto mapped_val = get_func(settings);
|
|
|
|
return get_mapped_value(mapped_val, mapping);
|
|
}
|
|
|
|
} /* namespace */
|
|
|
|
::gpiod_line_value map_output_value(line::value value)
|
|
{
|
|
return do_map_value(value, value_mapping);
|
|
}
|
|
|
|
line_settings::impl::impl()
|
|
: settings(make_line_settings())
|
|
{
|
|
|
|
}
|
|
|
|
line_settings::impl::impl(const impl& other)
|
|
: settings(copy_line_settings(other.settings))
|
|
{
|
|
|
|
}
|
|
|
|
GPIOD_CXX_API line_settings::line_settings()
|
|
: _m_priv(new impl)
|
|
{
|
|
|
|
}
|
|
|
|
GPIOD_CXX_API line_settings::line_settings(const line_settings& other)
|
|
: _m_priv(new impl(*other._m_priv))
|
|
{
|
|
|
|
}
|
|
|
|
GPIOD_CXX_API line_settings::line_settings(line_settings&& other) noexcept
|
|
: _m_priv(::std::move(other._m_priv))
|
|
{
|
|
|
|
}
|
|
|
|
GPIOD_CXX_API line_settings::~line_settings()
|
|
{
|
|
|
|
}
|
|
|
|
GPIOD_CXX_API line_settings& line_settings::operator=(const line_settings& other)
|
|
{
|
|
this->_m_priv.reset(new impl(*other._m_priv));
|
|
|
|
return *this;
|
|
}
|
|
|
|
GPIOD_CXX_API line_settings& line_settings::operator=(line_settings&& other)
|
|
{
|
|
this->_m_priv = ::std::move(other._m_priv);
|
|
|
|
return *this;
|
|
}
|
|
|
|
GPIOD_CXX_API line_settings& line_settings::reset() noexcept
|
|
{
|
|
::gpiod_line_settings_reset(this->_m_priv->settings.get());
|
|
|
|
return *this;
|
|
}
|
|
|
|
GPIOD_CXX_API line_settings& line_settings::set_direction(line::direction direction)
|
|
{
|
|
set_mapped_prop<line::direction, ::gpiod_line_direction,
|
|
::gpiod_line_settings_set_direction>(this->_m_priv->settings.get(),
|
|
direction, direction_mapping);
|
|
|
|
return *this;
|
|
}
|
|
|
|
GPIOD_CXX_API line::direction line_settings::direction() const
|
|
{
|
|
return get_mapped_prop<line::direction, ::gpiod_line_direction,
|
|
::gpiod_line_settings_get_direction>(
|
|
this->_m_priv->settings.get(),
|
|
reverse_direction_mapping);
|
|
}
|
|
|
|
GPIOD_CXX_API line_settings& line_settings::set_edge_detection(line::edge edge)
|
|
{
|
|
set_mapped_prop<line::edge, ::gpiod_line_edge,
|
|
::gpiod_line_settings_set_edge_detection>(this->_m_priv->settings.get(),
|
|
edge, edge_mapping);
|
|
|
|
return *this;
|
|
}
|
|
|
|
GPIOD_CXX_API line::edge line_settings::edge_detection() const
|
|
{
|
|
return get_mapped_prop<line::edge, ::gpiod_line_edge,
|
|
::gpiod_line_settings_get_edge_detection>(
|
|
this->_m_priv->settings.get(),
|
|
reverse_edge_mapping);
|
|
}
|
|
|
|
GPIOD_CXX_API line_settings& line_settings::set_bias(line::bias bias)
|
|
{
|
|
set_mapped_prop<line::bias, ::gpiod_line_bias,
|
|
::gpiod_line_settings_set_bias>(this->_m_priv->settings.get(),
|
|
bias, bias_mapping);
|
|
|
|
return *this;
|
|
}
|
|
|
|
GPIOD_CXX_API line::bias line_settings::bias() const
|
|
{
|
|
return get_mapped_prop<line::bias, ::gpiod_line_bias,
|
|
::gpiod_line_settings_get_bias>(this->_m_priv->settings.get(),
|
|
reverse_bias_mapping);
|
|
}
|
|
|
|
GPIOD_CXX_API line_settings& line_settings::set_drive(line::drive drive)
|
|
{
|
|
set_mapped_prop<line::drive, ::gpiod_line_drive,
|
|
::gpiod_line_settings_set_drive>(this->_m_priv->settings.get(),
|
|
drive, drive_mapping);
|
|
|
|
return *this;
|
|
}
|
|
|
|
GPIOD_CXX_API line::drive line_settings::drive() const
|
|
{
|
|
return get_mapped_prop<line::drive, ::gpiod_line_drive,
|
|
::gpiod_line_settings_get_drive>(this->_m_priv->settings.get(),
|
|
reverse_drive_mapping);
|
|
}
|
|
|
|
GPIOD_CXX_API line_settings& line_settings::set_active_low(bool active_low)
|
|
{
|
|
::gpiod_line_settings_set_active_low(this->_m_priv->settings.get(), active_low);
|
|
|
|
return *this;
|
|
}
|
|
|
|
GPIOD_CXX_API bool line_settings::active_low() const noexcept
|
|
{
|
|
return ::gpiod_line_settings_get_active_low(this->_m_priv->settings.get());
|
|
}
|
|
|
|
GPIOD_CXX_API line_settings&
|
|
line_settings::set_debounce_period(const ::std::chrono::microseconds& period)
|
|
{
|
|
::gpiod_line_settings_set_debounce_period_us(this->_m_priv->settings.get(), period.count());
|
|
|
|
return *this;
|
|
}
|
|
|
|
GPIOD_CXX_API ::std::chrono::microseconds line_settings::debounce_period() const noexcept
|
|
{
|
|
return ::std::chrono::microseconds(
|
|
::gpiod_line_settings_get_debounce_period_us(this->_m_priv->settings.get()));
|
|
}
|
|
|
|
GPIOD_CXX_API line_settings& line_settings::set_event_clock(line::clock event_clock)
|
|
{
|
|
set_mapped_prop<line::clock, ::gpiod_line_clock,
|
|
::gpiod_line_settings_set_event_clock>(this->_m_priv->settings.get(),
|
|
event_clock, clock_mapping);
|
|
|
|
return *this;
|
|
}
|
|
|
|
GPIOD_CXX_API line::clock line_settings::event_clock() const
|
|
{
|
|
return get_mapped_prop<line::clock, ::gpiod_line_clock,
|
|
::gpiod_line_settings_get_event_clock>(
|
|
this->_m_priv->settings.get(),
|
|
reverse_clock_mapping);
|
|
}
|
|
|
|
GPIOD_CXX_API line_settings& line_settings::set_output_value(line::value value)
|
|
{
|
|
set_mapped_prop<line::value, ::gpiod_line_value,
|
|
::gpiod_line_settings_set_output_value>(this->_m_priv->settings.get(),
|
|
value, value_mapping);
|
|
|
|
return *this;
|
|
}
|
|
|
|
GPIOD_CXX_API line::value line_settings::output_value() const
|
|
{
|
|
return get_mapped_prop<line::value, ::gpiod_line_value,
|
|
::gpiod_line_settings_get_output_value>(
|
|
this->_m_priv->settings.get(),
|
|
reverse_value_mapping);
|
|
}
|
|
|
|
GPIOD_CXX_API ::std::ostream& operator<<(::std::ostream& out, const line_settings& settings)
|
|
{
|
|
out << "gpiod::line_settings(direction=" << settings.direction() <<
|
|
", edge_detection=" << settings.edge_detection() <<
|
|
", bias=" << settings.bias() <<
|
|
", drive=" << settings.drive() <<
|
|
", " << (settings.active_low() ? "active-low" : "active-high") <<
|
|
", debounce_period=" << settings.debounce_period().count() <<
|
|
", event_clock=" << settings.event_clock() <<
|
|
", output_value=" << settings.output_value() <<
|
|
")";
|
|
|
|
return out;
|
|
}
|
|
|
|
} /* namespace gpiod */
|