1
0
mirror of https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git synced 2026-10-24 00:48:53 +03:00
Files
libgpiod/bindings/cxx/line-settings.cpp
Bartosz Golaszewski 76ecc337c5 licensing: relicense C++ bindings under LGPL-2.1-or-later
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>
2024-04-22 14:04:19 +02:00

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 */