}
+chip::chip(const ::std::weak_ptr<::gpiod_chip>& chip_ptr)
+ : _m_chip(chip_ptr)
+{
+
+}
+
void chip::open(const ::std::string& device, int how)
{
auto func = open_funcs.at(how);
return EXIT_FAILURE;
}
- ::gpiod::line line = ::gpiod::find_line(argv[1]);
- if (!line)
+ auto ret = ::gpiod::find_line(argv[1]);
+ if (!ret.first)
return EXIT_FAILURE;
- ::std::cout << line.get_chip().name() << " " << line.offset() << ::std::endl;
+ ::std::cout << ret.second.name() << " " << ret.first.offset() << ::std::endl;
return EXIT_SUCCESS;
}
private:
chip(::gpiod_chip* chip);
+ chip(const ::std::weak_ptr<::gpiod_chip>& chip_ptr);
void throw_if_noref(void) const;
::std::shared_ptr<::gpiod_chip> _m_chip;
+ friend line;
friend chip_iter;
friend line_iter;
};
GPIOD_API int event_get_fd(void) const;
/**
- * @brief Get the reference to the parent chip.
- * @return Reference to the parent chip object.
+ * @brief Get the parent chip.
+ * @return Parent chip of this line.
*/
- GPIOD_API const chip& get_chip(void) const;
+ GPIOD_API const chip get_chip(void) const;
/**
* @brief Re-read the line info from the kernel.
line_event make_line_event(const ::gpiod_line_event& event) const noexcept;
::gpiod_line* _m_line;
- chip _m_chip;
+ ::std::weak_ptr<::gpiod_chip> _m_owner;
+
+ class chip_guard
+ {
+ public:
+ chip_guard(const line& line);
+ ~chip_guard(void) = default;
+
+ chip_guard(const chip_guard& other) = delete;
+ chip_guard(chip_guard&& other) = delete;
+ chip_guard& operator=(const chip_guard&& other) = delete;
+ chip_guard& operator=(chip_guard&& other) = delete;
+
+ private:
+ ::std::shared_ptr<::gpiod_chip> _m_chip;
+ };
friend chip;
friend line_bulk;
/**
* @brief Find a GPIO line by name. Search all GPIO chips present on the system.
* @param name Name of the line.
- * @return Returns a line object - empty if the line was not found.
+ * @return Returns a <line, chip> pair where line is the line with given name
+ * and chip is the line's owner. Both objects are empty if the line was
+ * not found.
*/
-GPIOD_API line find_line(const ::std::string& name);
+GPIOD_API ::std::pair<line, chip> find_line(const ::std::string& name);
/**
* @brief Describes a single GPIO line event.
{
::gpiod_line* next = ::gpiod_line_iter_next(this->_m_iter.get());
- this->_m_current = next ? line(next, this->_m_current._m_chip) : line();
+ this->_m_current = next ? line(next, this->_m_current._m_owner) : line();
return *this;
}
line::line(void)
: _m_line(nullptr),
- _m_chip()
+ _m_owner()
{
}
line::line(::gpiod_line* line, const chip& owner)
: _m_line(line),
- _m_chip(owner)
+ _m_owner(owner._m_chip)
{
}
unsigned int line::offset(void) const
{
this->throw_if_null();
+ line::chip_guard lock_chip(*this);
return ::gpiod_line_offset(this->_m_line);
}
::std::string line::name(void) const
{
this->throw_if_null();
+ line::chip_guard lock_chip(*this);
const char* name = ::gpiod_line_name(this->_m_line);
::std::string line::consumer(void) const
{
this->throw_if_null();
+ line::chip_guard lock_chip(*this);
const char* consumer = ::gpiod_line_consumer(this->_m_line);
int line::direction(void) const
{
this->throw_if_null();
+ line::chip_guard lock_chip(*this);
int dir = ::gpiod_line_direction(this->_m_line);
int line::active_state(void) const
{
this->throw_if_null();
+ line::chip_guard lock_chip(*this);
int active = ::gpiod_line_active_state(this->_m_line);
int line::bias(void) const
{
this->throw_if_null();
+ line::chip_guard lock_chip(*this);
return bias_mapping.at(::gpiod_line_bias(this->_m_line));
}
bool line::is_used(void) const
{
this->throw_if_null();
+ line::chip_guard lock_chip(*this);
return ::gpiod_line_is_used(this->_m_line);
}
bool line::is_open_drain(void) const
{
this->throw_if_null();
+ line::chip_guard lock_chip(*this);
return ::gpiod_line_is_open_drain(this->_m_line);
}
bool line::is_open_source(void) const
{
this->throw_if_null();
+ line::chip_guard lock_chip(*this);
return ::gpiod_line_is_open_source(this->_m_line);
}
bool line::is_requested(void) const
{
this->throw_if_null();
+ line::chip_guard lock_chip(*this);
return ::gpiod_line_is_requested(this->_m_line);
}
line_event line::event_read(void) const
{
this->throw_if_null();
+ line::chip_guard lock_chip(*this);
::gpiod_line_event event_buf;
line_event event;
::std::vector<line_event> line::event_read_multiple(void) const
{
this->throw_if_null();
+ line::chip_guard lock_chip(*this);
/* 16 is the maximum number of events stored in the kernel FIFO. */
::std::array<::gpiod_line_event, 16> event_buf;
int line::event_get_fd(void) const
{
this->throw_if_null();
+ line::chip_guard lock_chip(*this);
int ret = ::gpiod_line_event_get_fd(this->_m_line);
return ret;
}
-const chip& line::get_chip(void) const
+const chip line::get_chip(void) const
{
- return this->_m_chip;
+ return chip(this->_m_owner);
}
void line::update(void) const
{
this->throw_if_null();
+ line::chip_guard lock_chip(*this);
int ret = ::gpiod_line_update(this->_m_line);
void line::reset(void)
{
this->_m_line = nullptr;
- this->_m_chip.reset();
+ this->_m_owner.reset();
}
bool line::operator==(const line& rhs) const noexcept
throw ::std::logic_error("object not holding a GPIO line handle");
}
-line find_line(const ::std::string& name)
+line::chip_guard::chip_guard(const line& line)
+ : _m_chip(line._m_owner)
{
- line ret;
+
+}
+
+::std::pair<line, chip> find_line(const ::std::string& name)
+{
+ ::std::pair<line, chip> ret;
for (auto& it: make_chip_iter()) {
- ret = it.find_line(name);
- if (ret)
+ ret.first = it.find_line(name);
+ if (ret.first) {
+ ret.second = it;
break;
+ }
}
return ret;
void line_bulk::request(const line_request& config, const ::std::vector<int> default_vals) const
{
this->throw_if_empty();
+ line::chip_guard lock_chip(this->_m_bulk.front());
if (!default_vals.empty() && this->size() != default_vals.size())
throw ::std::invalid_argument("the number of default values must correspond with the number of lines");
void line_bulk::release(void) const
{
this->throw_if_empty();
+ line::chip_guard lock_chip(this->_m_bulk.front());
::gpiod_line_bulk bulk;
::std::vector<int> line_bulk::get_values(void) const
{
this->throw_if_empty();
+ line::chip_guard lock_chip(this->_m_bulk.front());
::std::vector<int> values;
::gpiod_line_bulk bulk;
void line_bulk::set_values(const ::std::vector<int>& values) const
{
this->throw_if_empty();
+ line::chip_guard lock_chip(this->_m_bulk.front());
if (values.size() != this->_m_bulk.size())
throw ::std::invalid_argument("the size of values array must correspond with the number of lines");
const ::std::vector<int> values) const
{
this->throw_if_empty();
+ line::chip_guard lock_chip(this->_m_bulk.front());
if (!values.empty() && this->_m_bulk.size() != values.size())
throw ::std::invalid_argument("the number of default values must correspond with the number of lines");
void line_bulk::set_flags(::std::bitset<32> flags) const
{
this->throw_if_empty();
+ line::chip_guard lock_chip(this->_m_bulk.front());
::gpiod_line_bulk bulk;
int rv, gflags;
void line_bulk::set_direction_input() const
{
this->throw_if_empty();
+ line::chip_guard lock_chip(this->_m_bulk.front());
::gpiod_line_bulk bulk;
int rv;
void line_bulk::set_direction_output(const ::std::vector<int>& values) const
{
this->throw_if_empty();
+ line::chip_guard lock_chip(this->_m_bulk.front());
if (values.size() != this->_m_bulk.size())
throw ::std::invalid_argument("the size of values array must correspond with the number of lines");
line_bulk line_bulk::event_wait(const ::std::chrono::nanoseconds& timeout) const
{
this->throw_if_empty();
+ line::chip_guard lock_chip(this->_m_bulk.front());
::gpiod_line_bulk bulk, event_bulk;
::timespec ts;
SECTION("line found")
{
- auto line = ::gpiod::find_line("gpio-mockup-C-5");
- REQUIRE(line.offset() == 5);
- REQUIRE(line.name() == "gpio-mockup-C-5");
- REQUIRE(line.get_chip().label() == "gpio-mockup-C");
+ auto ret = ::gpiod::find_line("gpio-mockup-C-5");
+ REQUIRE(ret.first.offset() == 5);
+ REQUIRE(ret.first.name() == "gpio-mockup-C-5");
+ REQUIRE(ret.second.label() == "gpio-mockup-C");
}
SECTION("line not found")
{
- auto line = ::gpiod::find_line("nonexistent-line");
- REQUIRE_FALSE(line);
+ auto ret = ::gpiod::find_line("nonexistent-line");
+ REQUIRE_FALSE(ret.first);
}
}