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>
242 lines
5.9 KiB
C++
242 lines
5.9 KiB
C++
// SPDX-License-Identifier: LGPL-2.1-or-later
|
|
// SPDX-FileCopyrightText: 2021-2022 Bartosz Golaszewski <brgl@bgdev.pl>
|
|
|
|
#include <iterator>
|
|
#include <ostream>
|
|
#include <utility>
|
|
|
|
#include "internal.hpp"
|
|
|
|
namespace gpiod {
|
|
|
|
void line_request::impl::throw_if_released() const
|
|
{
|
|
if (!this->request)
|
|
throw request_released("GPIO lines have been released");
|
|
}
|
|
|
|
void line_request::impl::set_request_ptr(line_request_ptr& ptr)
|
|
{
|
|
this->request = ::std::move(ptr);
|
|
this->offset_buf.resize(::gpiod_line_request_get_num_requested_lines(this->request.get()));
|
|
}
|
|
|
|
void line_request::impl::fill_offset_buf(const line::offsets& offsets)
|
|
{
|
|
for (unsigned int i = 0; i < offsets.size(); i++)
|
|
this->offset_buf[i] = offsets[i];
|
|
}
|
|
|
|
line_request::line_request()
|
|
: _m_priv(new impl)
|
|
{
|
|
|
|
}
|
|
|
|
GPIOD_CXX_API line_request::line_request(line_request&& other) noexcept
|
|
: _m_priv(::std::move(other._m_priv))
|
|
{
|
|
|
|
}
|
|
|
|
GPIOD_CXX_API line_request::~line_request()
|
|
{
|
|
|
|
}
|
|
|
|
GPIOD_CXX_API line_request& line_request::operator=(line_request&& other) noexcept
|
|
{
|
|
this->_m_priv = ::std::move(other._m_priv);
|
|
|
|
return *this;
|
|
}
|
|
|
|
GPIOD_CXX_API line_request::operator bool() const noexcept
|
|
{
|
|
return this->_m_priv->request.get() != nullptr;
|
|
}
|
|
|
|
GPIOD_CXX_API void line_request::release()
|
|
{
|
|
this->_m_priv->throw_if_released();
|
|
|
|
this->_m_priv->request.reset();
|
|
}
|
|
|
|
GPIOD_CXX_API ::std::string line_request::chip_name() const
|
|
{
|
|
this->_m_priv->throw_if_released();
|
|
|
|
return ::gpiod_line_request_get_chip_name(this->_m_priv->request.get());
|
|
}
|
|
|
|
GPIOD_CXX_API ::std::size_t line_request::num_lines() const
|
|
{
|
|
this->_m_priv->throw_if_released();
|
|
|
|
return ::gpiod_line_request_get_num_requested_lines(this->_m_priv->request.get());
|
|
}
|
|
|
|
GPIOD_CXX_API line::offsets line_request::offsets() const
|
|
{
|
|
this->_m_priv->throw_if_released();
|
|
|
|
auto num_lines = this->num_lines();
|
|
::std::vector<unsigned int> buf(num_lines);
|
|
line::offsets offsets(num_lines);
|
|
|
|
::gpiod_line_request_get_requested_offsets(this->_m_priv->request.get(), buf.data(), buf.size());
|
|
|
|
for (unsigned int i = 0; i < num_lines; i++)
|
|
offsets[i] = buf[i];
|
|
|
|
return offsets;
|
|
}
|
|
|
|
GPIOD_CXX_API line::value line_request::get_value(line::offset offset)
|
|
{
|
|
return this->get_values({ offset }).front();
|
|
}
|
|
|
|
GPIOD_CXX_API line::values
|
|
line_request::get_values(const line::offsets& offsets)
|
|
{
|
|
line::values vals(offsets.size());
|
|
|
|
this->get_values(offsets, vals);
|
|
|
|
return vals;
|
|
}
|
|
|
|
GPIOD_CXX_API line::values line_request::get_values()
|
|
{
|
|
return this->get_values(this->offsets());
|
|
}
|
|
|
|
GPIOD_CXX_API void line_request::get_values(const line::offsets& offsets, line::values& values)
|
|
{
|
|
this->_m_priv->throw_if_released();
|
|
|
|
if (offsets.size() != values.size())
|
|
throw ::std::invalid_argument("values must have the same size as the offsets");
|
|
|
|
this->_m_priv->fill_offset_buf(offsets);
|
|
|
|
int ret = ::gpiod_line_request_get_values_subset(
|
|
this->_m_priv->request.get(),
|
|
offsets.size(), this->_m_priv->offset_buf.data(),
|
|
reinterpret_cast<::gpiod_line_value*>(values.data()));
|
|
if (ret)
|
|
throw_from_errno("unable to retrieve line values");
|
|
}
|
|
|
|
GPIOD_CXX_API void line_request::get_values(line::values& values)
|
|
{
|
|
this->get_values(this->offsets(), values);
|
|
}
|
|
|
|
GPIOD_CXX_API line_request&
|
|
line_request::line_request::set_value(line::offset offset, line::value value)
|
|
{
|
|
return this->set_values({ offset }, { value });
|
|
}
|
|
|
|
GPIOD_CXX_API line_request&
|
|
line_request::set_values(const line::value_mappings& values)
|
|
{
|
|
line::offsets offsets(values.size());
|
|
line::values vals(values.size());
|
|
|
|
for (unsigned int i = 0; i < values.size(); i++) {
|
|
offsets[i] = values[i].first;
|
|
vals[i] = values[i].second;
|
|
}
|
|
|
|
return this->set_values(offsets, vals);
|
|
}
|
|
|
|
GPIOD_CXX_API line_request& line_request::set_values(const line::offsets& offsets,
|
|
const line::values& values)
|
|
{
|
|
this->_m_priv->throw_if_released();
|
|
|
|
if (offsets.size() != values.size())
|
|
throw ::std::invalid_argument("values must have the same size as the offsets");
|
|
|
|
this->_m_priv->fill_offset_buf(offsets);
|
|
|
|
int ret = ::gpiod_line_request_set_values_subset(
|
|
this->_m_priv->request.get(),
|
|
offsets.size(), this->_m_priv->offset_buf.data(),
|
|
reinterpret_cast<const ::gpiod_line_value*>(values.data()));
|
|
if (ret)
|
|
throw_from_errno("unable to set line values");
|
|
|
|
return *this;
|
|
}
|
|
|
|
GPIOD_CXX_API line_request& line_request::set_values(const line::values& values)
|
|
{
|
|
return this->set_values(this->offsets(), values);
|
|
}
|
|
|
|
GPIOD_CXX_API line_request& line_request::reconfigure_lines(const line_config& config)
|
|
{
|
|
this->_m_priv->throw_if_released();
|
|
|
|
int ret = ::gpiod_line_request_reconfigure_lines(this->_m_priv->request.get(),
|
|
config._m_priv->config.get());
|
|
if (ret)
|
|
throw_from_errno("unable to reconfigure GPIO lines");
|
|
|
|
return *this;
|
|
}
|
|
|
|
GPIOD_CXX_API int line_request::fd() const
|
|
{
|
|
this->_m_priv->throw_if_released();
|
|
|
|
return ::gpiod_line_request_get_fd(this->_m_priv->request.get());
|
|
}
|
|
|
|
GPIOD_CXX_API bool line_request::wait_edge_events(const ::std::chrono::nanoseconds& timeout) const
|
|
{
|
|
this->_m_priv->throw_if_released();
|
|
|
|
int ret = ::gpiod_line_request_wait_edge_events(this->_m_priv->request.get(),
|
|
timeout.count());
|
|
if (ret < 0)
|
|
throw_from_errno("error waiting for edge events");
|
|
|
|
return ret;
|
|
}
|
|
|
|
GPIOD_CXX_API ::std::size_t line_request::read_edge_events(edge_event_buffer& buffer)
|
|
{
|
|
return this->read_edge_events(buffer, buffer.capacity());
|
|
}
|
|
|
|
GPIOD_CXX_API ::std::size_t
|
|
line_request::read_edge_events(edge_event_buffer& buffer, ::std::size_t max_events)
|
|
{
|
|
this->_m_priv->throw_if_released();
|
|
|
|
return buffer._m_priv->read_events(this->_m_priv->request, max_events);
|
|
}
|
|
|
|
GPIOD_CXX_API ::std::ostream& operator<<(::std::ostream& out, const line_request& request)
|
|
{
|
|
if (!request)
|
|
out << "gpiod::line_request(released)";
|
|
else
|
|
out << "gpiod::line_request(chip=\"" << request.chip_name() <<
|
|
"\", num_lines=" << request.num_lines() <<
|
|
", line_offsets=" << request.offsets() <<
|
|
", fd=" << request.fd() <<
|
|
")";
|
|
|
|
return out;
|
|
}
|
|
|
|
} /* namespace gpiod */
|