diff --git a/bindings/cxx/Makefile.am b/bindings/cxx/Makefile.am
deleted file mode 100644
index d9fa577..0000000
--- a/bindings/cxx/Makefile.am
+++ /dev/null
@@ -1,28 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-or-later
-# SPDX-FileCopyrightText: 2017-2021 Bartosz Golaszewski <bartekgola@gmail.com>
-
-lib_LTLIBRARIES = libgpiodcxx.la
-libgpiodcxx_la_SOURCES = chip.cpp internal.h iter.cpp line.cpp line_bulk.cpp
-libgpiodcxx_la_CPPFLAGS = -Wall -Wextra -g -std=gnu++11
-libgpiodcxx_la_CPPFLAGS += -fvisibility=hidden -I$(top_srcdir)/include/
-libgpiodcxx_la_LDFLAGS = -version-info $(subst .,:,$(ABI_CXX_VERSION))
-libgpiodcxx_la_LDFLAGS += -lgpiod -L$(top_builddir)/lib
-
-include_HEADERS = gpiod.hpp
-
-pkgconfigdir = $(libdir)/pkgconfig
-pkgconfig_DATA = libgpiodcxx.pc
-
-SUBDIRS = .
-
-if WITH_TESTS
-
-SUBDIRS += tests
-
-endif
-
-if WITH_EXAMPLES
-
-SUBDIRS += examples
-
-endif
diff --git a/bindings/cxx/chip.cpp b/bindings/cxx/chip.cpp
deleted file mode 100644
index ee6ab6f..0000000
--- a/bindings/cxx/chip.cpp
+++ /dev/null
@@ -1,157 +0,0 @@
-// SPDX-License-Identifier: LGPL-3.0-or-later
-// SPDX-FileCopyrightText: 2017-2021 Bartosz Golaszewski <bartekgola@gmail.com>
-
-#include <functional>
-#include <gpiod.hpp>
-#include <map>
-#include <system_error>
-#include <utility>
-
-#include "internal.hpp"
-
-namespace gpiod {
-
-namespace {
-
-GPIOD_CXX_API void chip_deleter(::gpiod_chip* chip)
-{
-	::gpiod_chip_unref(chip);
-}
-
-} /* namespace */
-
-GPIOD_CXX_API bool is_gpiochip_device(const ::std::string& path)
-{
-	return ::gpiod_is_gpiochip_device(path.c_str());
-}
-
-GPIOD_CXX_API chip::chip(const ::std::string& path)
-	: _m_chip()
-{
-	this->open(path);
-}
-
-GPIOD_CXX_API chip::chip(::gpiod_chip* chip)
-	: _m_chip(chip, chip_deleter)
-{
-
-}
-
-GPIOD_CXX_API chip::chip(const ::std::weak_ptr<::gpiod_chip>& chip_ptr)
-	: _m_chip(chip_ptr)
-{
-
-}
-
-GPIOD_CXX_API void chip::open(const ::std::string& path)
-{
-	::gpiod_chip *chip = ::gpiod_chip_open(path.c_str());
-	if (!chip)
-		throw ::std::system_error(errno, ::std::system_category(),
-					  "cannot open GPIO device " + path);
-
-	this->_m_chip.reset(chip, chip_deleter);
-}
-
-GPIOD_CXX_API void chip::reset(void) noexcept
-{
-	this->_m_chip.reset();
-}
-
-GPIOD_CXX_API ::std::string chip::name(void) const
-{
-	this->throw_if_noref();
-
-	return ::std::string(::gpiod_chip_get_name(this->_m_chip.get()));
-}
-
-GPIOD_CXX_API ::std::string chip::label(void) const
-{
-	this->throw_if_noref();
-
-	return ::std::string(::gpiod_chip_get_label(this->_m_chip.get()));
-}
-
-GPIOD_CXX_API unsigned int chip::num_lines(void) const
-{
-	this->throw_if_noref();
-
-	return ::gpiod_chip_get_num_lines(this->_m_chip.get());
-}
-
-GPIOD_CXX_API line chip::get_line(unsigned int offset) const
-{
-	this->throw_if_noref();
-
-	if (offset >= this->num_lines())
-		throw ::std::out_of_range("line offset greater than the number of lines");
-
-	::gpiod_line* line_handle = ::gpiod_chip_get_line(this->_m_chip.get(), offset);
-	if (!line_handle)
-		throw ::std::system_error(errno, ::std::system_category(),
-					  "error getting GPIO line from chip");
-
-	return line(line_handle, *this);
-}
-
-GPIOD_CXX_API int chip::find_line(const ::std::string& name) const
-{
-	this->throw_if_noref();
-
-	for (unsigned int offset = 0; offset < this->num_lines(); offset++) {
-		auto line = this->get_line(offset);
-
-		if (line.name() == name)
-			return offset;
-	}
-
-	return -1;
-}
-
-GPIOD_CXX_API line_bulk chip::get_lines(const ::std::vector<unsigned int>& offsets) const
-{
-	line_bulk lines;
-
-	for (auto& it: offsets)
-		lines.append(this->get_line(it));
-
-	return lines;
-}
-
-GPIOD_CXX_API line_bulk chip::get_all_lines(void) const
-{
-	line_bulk lines;
-
-	for (unsigned int i = 0; i < this->num_lines(); i++)
-		lines.append(this->get_line(i));
-
-	return lines;
-}
-
-GPIOD_CXX_API bool chip::operator==(const chip& rhs) const noexcept
-{
-	return this->_m_chip.get() == rhs._m_chip.get();
-}
-
-GPIOD_CXX_API bool chip::operator!=(const chip& rhs) const noexcept
-{
-	return this->_m_chip.get() != rhs._m_chip.get();
-}
-
-GPIOD_CXX_API chip::operator bool(void) const noexcept
-{
-	return this->_m_chip.get() != nullptr;
-}
-
-GPIOD_CXX_API bool chip::operator!(void) const noexcept
-{
-	return this->_m_chip.get() == nullptr;
-}
-
-GPIOD_CXX_API void chip::throw_if_noref(void) const
-{
-	if (!this->_m_chip.get())
-		throw ::std::logic_error("object not associated with an open GPIO chip");
-}
-
-} /* namespace gpiod */
diff --git a/bindings/cxx/examples/.gitignore b/bindings/cxx/examples/.gitignore
deleted file mode 100644
index 54bda46..0000000
--- a/bindings/cxx/examples/.gitignore
+++ /dev/null
@@ -1,9 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-or-later
-# SPDX-FileCopyrightText: 2017-2021 Bartosz Golaszewski <bartekgola@gmail.com>
-
-gpiodetectcxx
-gpiofindcxx
-gpiogetcxx
-gpioinfocxx
-gpiomoncxx
-gpiosetcxx
diff --git a/bindings/cxx/examples/Makefile.am b/bindings/cxx/examples/Makefile.am
deleted file mode 100644
index 748b581..0000000
--- a/bindings/cxx/examples/Makefile.am
+++ /dev/null
@@ -1,26 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-or-later
-# SPDX-FileCopyrightText: 2017-2021 Bartosz Golaszewski <bartekgola@gmail.com>
-
-AM_CPPFLAGS = -I$(top_srcdir)/bindings/cxx/ -I$(top_srcdir)/include
-AM_CPPFLAGS += -Wall -Wextra -g -std=gnu++17
-AM_LDFLAGS = -lgpiodcxx -L$(top_builddir)/bindings/cxx/ -lstdc++fs
-
-noinst_PROGRAMS =				\
-		gpiodetectcxx			\
-		gpiofindcxx			\
-		gpiogetcxx			\
-		gpioinfocxx			\
-		gpiomoncxx			\
-		gpiosetcxx
-
-gpiodetectcxx_SOURCES = gpiodetectcxx.cpp
-
-gpiofindcxx_SOURCES = gpiofindcxx.cpp
-
-gpiogetcxx_SOURCES = gpiogetcxx.cpp
-
-gpioinfocxx_SOURCES = gpioinfocxx.cpp
-
-gpiomoncxx_SOURCES = gpiomoncxx.cpp
-
-gpiosetcxx_SOURCES = gpiosetcxx.cpp
diff --git a/bindings/cxx/examples/gpiodetectcxx.cpp b/bindings/cxx/examples/gpiodetectcxx.cpp
deleted file mode 100644
index 872cd96..0000000
--- a/bindings/cxx/examples/gpiodetectcxx.cpp
+++ /dev/null
@@ -1,30 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-// SPDX-FileCopyrightText: 2017-2021 Bartosz Golaszewski <bartekgola@gmail.com>
-
-/* C++ reimplementation of the gpiodetect tool. */
-
-#include <gpiod.hpp>
-
-#include <cstdlib>
-#include <filesystem>
-#include <iostream>
-
-int main(int argc, char **argv)
-{
-	if (argc != 1) {
-		::std::cerr << "usage: " << argv[0] << ::std::endl;
-		return EXIT_FAILURE;
-	}
-
-	for (const auto& entry: ::std::filesystem::directory_iterator("/dev/")) {
-		if (::gpiod::is_gpiochip_device(entry.path())) {
-			::gpiod::chip chip(entry.path());
-
-			::std::cout << chip.name() << " ["
-				    << chip.label() << "] ("
-				    << chip.num_lines() << " lines)" << ::std::endl;
-		}
-	}
-
-	return EXIT_SUCCESS;
-}
diff --git a/bindings/cxx/examples/gpiofindcxx.cpp b/bindings/cxx/examples/gpiofindcxx.cpp
deleted file mode 100644
index ec4d79b..0000000
--- a/bindings/cxx/examples/gpiofindcxx.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-// SPDX-FileCopyrightText: 2017-2021 Bartosz Golaszewski <bartekgola@gmail.com>
-
-/* C++ reimplementation of the gpiofind tool. */
-
-#include <gpiod.hpp>
-
-#include <cstdlib>
-#include <filesystem>
-#include <iostream>
-
-int main(int argc, char **argv)
-{
-	if (argc != 2) {
-		::std::cerr << "usage: " << argv[0] << " <line name>" << ::std::endl;
-		return EXIT_FAILURE;
-	}
-
-	for (const auto& entry: ::std::filesystem::directory_iterator("/dev/")) {
-		if (::gpiod::is_gpiochip_device(entry.path())) {
-			::gpiod::chip chip(entry.path());
-
-			auto offset = chip.find_line(argv[1]);
-			if (offset >= 0) {
-				::std::cout << chip.name() << " " << offset << ::std::endl;
-				return EXIT_SUCCESS;
-			}
-		}
-	}
-
-	return EXIT_FAILURE;
-}
diff --git a/bindings/cxx/examples/gpiogetcxx.cpp b/bindings/cxx/examples/gpiogetcxx.cpp
deleted file mode 100644
index 94b3dac..0000000
--- a/bindings/cxx/examples/gpiogetcxx.cpp
+++ /dev/null
@@ -1,39 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-// SPDX-FileCopyrightText: 2017-2021 Bartosz Golaszewski <bartekgola@gmail.com>
-
-/* Simplified C++ reimplementation of the gpioget tool. */
-
-#include <gpiod.hpp>
-
-#include <cstdlib>
-#include <iostream>
-
-int main(int argc, char **argv)
-{
-	if (argc < 3) {
-		::std::cerr << "usage: " << argv[0] << " <chip> <line_offset0> ..." << ::std::endl;
-		return EXIT_FAILURE;
-	}
-
-	::std::vector<unsigned int> offsets;
-
-	for (int i = 2; i < argc; i++)
-		offsets.push_back(::std::stoul(argv[i]));
-
-	::gpiod::chip chip(argv[1]);
-	auto lines = chip.get_lines(offsets);
-
-	lines.request({
-		argv[0],
-		::gpiod::line_request::DIRECTION_INPUT,
-		0
-	});
-
-	auto vals = lines.get_values();
-
-	for (auto& it: vals)
-		::std::cout << it << ' ';
-	::std::cout << ::std::endl;
-
-	return EXIT_SUCCESS;
-}
diff --git a/bindings/cxx/examples/gpioinfocxx.cpp b/bindings/cxx/examples/gpioinfocxx.cpp
deleted file mode 100644
index 2175adc..0000000
--- a/bindings/cxx/examples/gpioinfocxx.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-// SPDX-FileCopyrightText: 2017-2021 Bartosz Golaszewski <bartekgola@gmail.com>
-
-/* Simplified C++ reimplementation of the gpioinfo tool. */
-
-#include <gpiod.hpp>
-
-#include <cstdlib>
-#include <filesystem>
-#include <iostream>
-
-int main(int argc, char **argv)
-{
-	if (argc != 1) {
-		::std::cerr << "usage: " << argv[0] << ::std::endl;
-		return EXIT_FAILURE;
-	}
-
-	for (const auto& entry: ::std::filesystem::directory_iterator("/dev/")) {
-		if (::gpiod::is_gpiochip_device(entry.path())) {
-			::gpiod::chip chip(entry.path());
-
-			::std::cout << chip.name() << " - " << chip.num_lines() << " lines:" << ::std::endl;
-
-			for (auto& lit: ::gpiod::line_iter(chip)) {
-				::std::cout << "\tline ";
-				::std::cout.width(3);
-				::std::cout << lit.offset() << ": ";
-
-				::std::cout.width(12);
-				::std::cout << (lit.name().empty() ? "unnamed" : lit.name());
-				::std::cout << " ";
-
-				::std::cout.width(12);
-				::std::cout << (lit.consumer().empty() ? "unused" : lit.consumer());
-				::std::cout << " ";
-
-				::std::cout.width(8);
-				::std::cout << (lit.direction() == ::gpiod::line::DIRECTION_INPUT ? "input" : "output");
-				::std::cout << " ";
-
-				::std::cout.width(10);
-				::std::cout << (lit.is_active_low() ? "active-low" : "active-high");
-
-				::std::cout << ::std::endl;
-			}
-		}
-	}
-
-	return EXIT_SUCCESS;
-}
diff --git a/bindings/cxx/examples/gpiomoncxx.cpp b/bindings/cxx/examples/gpiomoncxx.cpp
deleted file mode 100644
index 4d6ac6e..0000000
--- a/bindings/cxx/examples/gpiomoncxx.cpp
+++ /dev/null
@@ -1,65 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-// SPDX-FileCopyrightText: 2017-2021 Bartosz Golaszewski <bartekgola@gmail.com>
-
-/* Simplified C++ reimplementation of the gpiomon tool. */
-
-#include <gpiod.hpp>
-
-#include <cstdlib>
-#include <iostream>
-
-namespace {
-
-void print_event(const ::gpiod::line_event& event)
-{
-	if (event.event_type == ::gpiod::line_event::RISING_EDGE)
-		::std::cout << " RISING EDGE";
-	else if (event.event_type == ::gpiod::line_event::FALLING_EDGE)
-		::std::cout << "FALLING EDGE";
-	else
-		throw ::std::logic_error("invalid event type");
-
-	::std::cout << " ";
-
-	::std::cout << ::std::chrono::duration_cast<::std::chrono::seconds>(event.timestamp).count();
-	::std::cout << ".";
-	::std::cout << event.timestamp.count() % 1000000000;
-
-	::std::cout << " line: " << event.source.offset();
-
-	::std::cout << ::std::endl;
-}
-
-} /* namespace */
-
-int main(int argc, char **argv)
-{
-	if (argc < 3) {
-		::std::cout << "usage: " << argv[0] << " <chip> <offset0> ..." << ::std::endl;
-		return EXIT_FAILURE;
-	}
-
-	::std::vector<unsigned int> offsets;
-	offsets.reserve(argc);
-	for (int i = 2; i < argc; i++)
-		offsets.push_back(::std::stoul(argv[i]));
-
-	::gpiod::chip chip(argv[1]);
-	auto lines = chip.get_lines(offsets);
-
-	lines.request({
-		argv[0],
-		::gpiod::line_request::EVENT_BOTH_EDGES,
-		0,
-	});
-
-	for (;;) {
-		auto events = lines.event_wait(::std::chrono::seconds(1));
-		if (events) {
-			for (auto& it: events)
-				print_event(it.event_read());
-		}
-	}
-
-	return EXIT_SUCCESS;
-}
diff --git a/bindings/cxx/examples/gpiosetcxx.cpp b/bindings/cxx/examples/gpiosetcxx.cpp
deleted file mode 100644
index 71b27a9..0000000
--- a/bindings/cxx/examples/gpiosetcxx.cpp
+++ /dev/null
@@ -1,48 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-// SPDX-FileCopyrightText: 2017-2021 Bartosz Golaszewski <bartekgola@gmail.com>
-
-/* Simplified C++ reimplementation of the gpioset tool. */
-
-#include <gpiod.hpp>
-
-#include <cstdlib>
-#include <iostream>
-
-int main(int argc, char **argv)
-{
-	if (argc < 3) {
-		::std::cerr << "usage: " << argv[0] << " <chip> <line_offset0>=<value0> ..." << ::std::endl;
-		return EXIT_FAILURE;
-	}
-
-	::std::vector<unsigned int> offsets;
-	::std::vector<int> values;
-
-	for (int i = 2; i < argc; i++) {
-		::std::string arg(argv[i]);
-
-		size_t pos = arg.find('=');
-
-		::std::string offset(arg.substr(0, pos));
-		::std::string value(arg.substr(pos + 1, ::std::string::npos));
-
-		if (offset.empty() || value.empty())
-			throw ::std::invalid_argument("invalid argument: " + ::std::string(argv[i]));
-
-		offsets.push_back(::std::stoul(offset));
-		values.push_back(::std::stoul(value));
-	}
-
-	::gpiod::chip chip(argv[1]);
-	auto lines = chip.get_lines(offsets);
-
-	lines.request({
-		argv[0],
-		::gpiod::line_request::DIRECTION_OUTPUT,
-		0
-	}, values);
-
-	::std::cin.get();
-
-	return EXIT_SUCCESS;
-}
diff --git a/bindings/cxx/gpiod.hpp b/bindings/cxx/gpiod.hpp
deleted file mode 100644
index e3ce2fc..0000000
--- a/bindings/cxx/gpiod.hpp
+++ /dev/null
@@ -1,940 +0,0 @@
-/* SPDX-License-Identifier: LGPL-3.0-or-later */
-/* SPDX-FileCopyrightText: 2017-2021 Bartosz Golaszewski <bartekgola@gmail.com> */
-
-#ifndef __LIBGPIOD_GPIOD_CXX_HPP__
-#define __LIBGPIOD_GPIOD_CXX_HPP__
-
-#include <bitset>
-#include <chrono>
-#include <gpiod.h>
-#include <memory>
-#include <string>
-#include <vector>
-
-namespace gpiod {
-
-class line;
-class line_bulk;
-class line_iter;
-class chip_iter;
-struct line_event;
-
-/**
- * @file gpiod.hpp
- */
-
-/**
- * @defgroup gpiod_cxx C++ bindings
- * @{
- */
-
-/**
- * @brief Check if the file pointed to by path is a GPIO chip character device.
- * @param path Path to check.
- * @return True if the file exists and is a GPIO chip character device or a
- *         symbolic link to it.
- */
-bool is_gpiochip_device(const ::std::string& path);
-
-/**
- * @brief Represents a GPIO chip.
- *
- * Internally this class holds a smart pointer to an open GPIO chip descriptor.
- * Multiple objects of this class can reference the same chip. The chip is
- * closed and all resources freed when the last reference is dropped.
- */
-class chip
-{
-public:
-
-	/**
-	 * @brief Default constructor. Creates an empty GPIO chip object.
-	 */
-	chip(void) = default;
-
-	/**
-	 * @brief Constructor. Opens the chip using chip::open.
-	 * @param path Path to the GPIO chip device.
-	 */
-	chip(const ::std::string& path);
-
-	/**
-	 * @brief Copy constructor. References the object held by other.
-	 * @param other Other chip object.
-	 */
-	chip(const chip& other) = default;
-
-	/**
-	 * @brief Move constructor. References the object held by other.
-	 * @param other Other chip object.
-	 */
-	chip(chip&& other) = default;
-
-	/**
-	 * @brief Assignment operator. References the object held by other.
-	 * @param other Other chip object.
-	 * @return Reference to this object.
-	 */
-	chip& operator=(const chip& other) = default;
-
-	/**
-	 * @brief Move assignment operator. References the object held by other.
-	 * @param other Other chip object.
-	 * @return Reference to this object.
-	 */
-	chip& operator=(chip&& other) = default;
-
-	/**
-	 * @brief Destructor. Unreferences the internal chip object.
-	 */
-	~chip(void) = default;
-
-	/**
-	 * @brief Open a GPIO chip.
-	 * @param path Path to the GPIO chip device.
-	 *
-	 * If the object already holds a reference to an open chip, it will be
-	 * closed and the reference reset.
-	 */
-	void open(const ::std::string &path);
-
-	/**
-	 * @brief Reset the internal smart pointer owned by this object.
-	 */
-	void reset(void) noexcept;
-
-	/**
-	 * @brief Return the name of the chip held by this object.
-	 * @return Name of the GPIO chip.
-	 */
-	::std::string name(void) const;
-
-	/**
-	 * @brief Return the label of the chip held by this object.
-	 * @return Label of the GPIO chip.
-	 */
-	::std::string label(void) const;
-
-	/**
-	 * @brief Return the number of lines exposed by this chip.
-	 * @return Number of lines.
-	 */
-	unsigned int num_lines(void) const;
-
-	/**
-	 * @brief Get the line exposed by this chip at given offset.
-	 * @param offset Offset of the line.
-	 * @return Line object.
-	 */
-	line get_line(unsigned int offset) const;
-
-	/**
-	 * @brief Map a GPIO line's name to its offset within the chip.
-	 * @param name Name of the GPIO line to map.
-	 * @return Offset of the line within the chip or -1 if a line with
-	 *         given name is not exposed by the chip.
-	 */
-	int find_line(const ::std::string& name) const;
-
-	/**
-	 * @brief Get a set of lines exposed by this chip at given offsets.
-	 * @param offsets Vector of line offsets.
-	 * @return Set of lines held by a line_bulk object.
-	 */
-	line_bulk get_lines(const ::std::vector<unsigned int>& offsets) const;
-
-	/**
-	 * @brief Get all lines exposed by this chip.
-	 * @return All lines exposed by this chip held by a line_bulk object.
-	 */
-	line_bulk get_all_lines(void) const;
-
-	/**
-	 * @brief Equality operator.
-	 * @param rhs Right-hand side of the equation.
-	 * @return True if rhs references the same chip. False otherwise.
-	 */
-	bool operator==(const chip& rhs) const noexcept;
-
-	/**
-	 * @brief Inequality operator.
-	 * @param rhs Right-hand side of the equation.
-	 * @return False if rhs references the same chip. True otherwise.
-	 */
-	bool operator!=(const chip& rhs) const noexcept;
-
-	/**
-	 * @brief Check if this object holds a reference to a GPIO chip.
-	 * @return True if this object references a GPIO chip, false otherwise.
-	 */
-	explicit operator bool(void) const noexcept;
-
-	/**
-	 * @brief Check if this object doesn't hold a reference to a GPIO chip.
-	 * @return False if this object references a GPIO chip, true otherwise.
-	 */
-	bool operator!(void) const noexcept;
-
-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;
-};
-
-/**
- * @brief Stores the configuration for line requests.
- */
-struct line_request
-{
-	/**
-	 * @brief Request types.
-	 */
-	enum : int {
-		DIRECTION_AS_IS = 1,
-		/**< Request for values, don't change the direction. */
-		DIRECTION_INPUT,
-		/**< Request for reading line values. */
-		DIRECTION_OUTPUT,
-		/**< Request for driving the GPIO lines. */
-		EVENT_FALLING_EDGE,
-		/**< Listen for falling edge events. */
-		EVENT_RISING_EDGE,
-		/**< Listen for rising edge events. */
-		EVENT_BOTH_EDGES,
-		/**< Listen for all types of events. */
-	};
-
-	static const ::std::bitset<32> FLAG_ACTIVE_LOW;
-	/**< Set the active state to 'low' (high is the default). */
-	static const ::std::bitset<32> FLAG_OPEN_SOURCE;
-	/**< The line is an open-source port. */
-	static const ::std::bitset<32> FLAG_OPEN_DRAIN;
-	/**< The line is an open-drain port. */
-	static const ::std::bitset<32> FLAG_BIAS_DISABLED;
-	/**< The line has neither pull-up nor pull-down resistor enabled. */
-	static const ::std::bitset<32> FLAG_BIAS_PULL_DOWN;
-	/**< The line has a configurable pull-down resistor enabled. */
-	static const ::std::bitset<32> FLAG_BIAS_PULL_UP;
-	/**< The line has a configurable pull-up resistor enabled. */
-
-	::std::string consumer;
-	/**< Consumer name to pass to the request. */
-	int request_type;
-	/**< Type of the request. */
-	::std::bitset<32> flags;
-	/**< Additional request flags. */
-};
-
-/**
- * @brief Represents a single GPIO line.
- *
- * Internally this class holds a raw pointer to a GPIO line descriptor and a
- * reference to the parent chip. All line resources are freed when the last
- * reference to the parent chip is dropped.
- */
-class line
-{
-public:
-
-	/**
-	 * @brief Default constructor. Creates an empty line object.
-	 */
-	line(void);
-
-	/**
-	 * @brief Copy constructor.
-	 * @param other Other line object.
-	 */
-	line(const line& other) = default;
-
-	/**
-	 * @brief Move constructor.
-	 * @param other Other line object.
-	 */
-	line(line&& other) = default;
-
-	/**
-	 * @brief Assignment operator.
-	 * @param other Other line object.
-	 * @return Reference to this object.
-	 */
-	line& operator=(const line& other) = default;
-
-	/**
-	 * @brief Move assignment operator.
-	 * @param other Other line object.
-	 * @return Reference to this object.
-	 */
-	line& operator=(line&& other) = default;
-
-	/**
-	 * @brief Destructor.
-	 */
-	~line(void) = default;
-
-	/**
-	 * @brief Get the offset of this line.
-	 * @return Offet of this line.
-	 */
-	unsigned int offset(void) const;
-
-	/**
-	 * @brief Get the name of this line (if any).
-	 * @return Name of this line or an empty string if it is unnamed.
-	 */
-	::std::string name(void) const;
-
-	/**
-	 * @brief Get the consumer of this line (if any).
-	 * @return Name of the consumer of this line or an empty string if it
-	 *         is unused.
-	 */
-	::std::string consumer(void) const;
-
-	/**
-	 * @brief Get current direction of this line.
-	 * @return Current direction setting.
-	 */
-	int direction(void) const;
-
-	/**
-	 * @brief Check if this line's signal is inverted.
-	 * @return True if this line is "active-low", false otherwise.
-	 */
-	bool is_active_low(void) const;
-
-	/**
-	 * @brief Get current bias of this line.
-	 * @return Current bias setting.
-	 */
-	int bias(void) const;
-
-	/**
-	 * @brief Check if this line is used by the kernel or other user space
-	 *        process.
-	 * @return True if this line is in use, false otherwise.
-	 */
-	bool is_used(void) const;
-
-	/**
-	 * @brief Get current drive setting of this line.
-	 * @return Current drive setting.
-	 */
-	int drive(void) const;
-
-	/**
-	 * @brief Request this line.
-	 * @param config Request config (see gpiod::line_request).
-	 * @param default_val Default value - only matters for OUTPUT direction.
-	 */
-	void request(const line_request& config, int default_val = 0) const;
-
-	/**
-	 * @brief Release the line if it was previously requested.
-	 */
-	void release(void) const;
-
-	/**
-	 * @brief Read the line value.
-	 * @return Current value (0 or 1).
-	 */
-	int get_value(void) const;
-
-	/**
-	 * @brief Set the value of this line.
-	 * @param val New value (0 or 1).
-	 */
-	void set_value(int val) const;
-
-	/**
-	 * @brief Set configuration of this line.
-	 * @param direction New direction.
-	 * @param flags Replacement flags.
-	 * @param value New value (0 or 1) - only matters for OUTPUT direction.
-	 */
-	void set_config(int direction, ::std::bitset<32> flags, int value = 0) const;
-
-	/**
-	 * @brief Set configuration flags of this line.
-	 * @param flags Replacement flags.
-	 */
-	void set_flags(::std::bitset<32> flags) const;
-
-	/**
-	 * @brief Change the direction this line to input.
-	 */
-	void set_direction_input() const;
-
-	/**
-	 * @brief Change the direction this lines to output.
-	 * @param value New value (0 or 1).
-	 */
-	void set_direction_output(int value = 0) const;
-
-	/**
-	 * @brief Wait for an event on this line.
-	 * @param timeout Time to wait before returning if no event occurred.
-	 * @return True if an event occurred and can be read, false if the wait
-	 *         timed out.
-	 */
-	bool event_wait(const ::std::chrono::nanoseconds& timeout) const;
-
-	/**
-	 * @brief Read a line event.
-	 * @return Line event object.
-	 */
-	line_event event_read(void) const;
-
-	/**
-	 * @brief Read multiple line events.
-	 * @return Vector of line event objects.
-	 */
-	::std::vector<line_event> event_read_multiple(void) const;
-
-	/**
-	 * @brief Get the event file descriptor associated with this line.
-	 * @return File descriptor number.
-	 */
-	int event_get_fd(void) const;
-
-	/**
-	 * @brief Get the parent chip.
-	 * @return Parent chip of this line.
-	 */
-	const chip get_chip(void) const;
-
-	/**
-	 * @brief Reset the state of this object.
-	 *
-	 * This is useful when the user needs to e.g. keep the line_event object
-	 * but wants to drop the reference to the GPIO chip indirectly held by
-	 * the line being the source of the event.
-	 */
-	void reset(void);
-
-	/**
-	 * @brief Check if two line objects reference the same GPIO line.
-	 * @param rhs Right-hand side of the equation.
-	 * @return True if both objects reference the same line, fale otherwise.
-	 */
-	bool operator==(const line& rhs) const noexcept;
-
-	/**
-	 * @brief Check if two line objects reference different GPIO lines.
-	 * @param rhs Right-hand side of the equation.
-	 * @return False if both objects reference the same line, true otherwise.
-	 */
-	bool operator!=(const line& rhs) const noexcept;
-
-	/**
-	 * @brief Check if this object holds a reference to any GPIO line.
-	 * @return True if this object references a GPIO line, false otherwise.
-	 */
-	explicit operator bool(void) const noexcept;
-
-	/**
-	 * @brief Check if this object doesn't reference any GPIO line.
-	 * @return True if this object doesn't reference any GPIO line, true
-	 *         otherwise.
-	 */
-	bool operator!(void) const noexcept;
-
-	/**
-	 * @brief Possible direction settings.
-	 */
-	enum : int {
-		DIRECTION_INPUT = 1,
-		/**< Line's direction setting is input. */
-		DIRECTION_OUTPUT,
-		/**< Line's direction setting is output. */
-	};
-
-	/**
-	 * @brief Possible drive settings.
-	 */
-	enum : int {
-		DRIVE_PUSH_PULL = 1,
-		/**< Drive setting is unknown. */
-		DRIVE_OPEN_DRAIN,
-		/**< Line output is open-drain. */
-		DRIVE_OPEN_SOURCE,
-		/**< Line output is open-source. */
-	};
-
-	/**
-	 * @brief Possible bias settings.
-	 */
-	enum : int {
-		BIAS_UNKNOWN = 1,
-		/**< Line's bias state is unknown. */
-		BIAS_DISABLED,
-		/**< Line's internal bias is disabled. */
-		BIAS_PULL_UP,
-		/**< Line's internal pull-up bias is enabled. */
-		BIAS_PULL_DOWN,
-		/**< Line's internal pull-down bias is enabled. */
-	};
-
-private:
-
-	line(::gpiod_line* line, const chip& owner);
-
-	void throw_if_null(void) const;
-	line_event make_line_event(const ::gpiod_line_event& event) const noexcept;
-
-	::gpiod_line* _m_line;
-	::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;
-	friend line_iter;
-};
-
-/**
- * @brief Describes a single GPIO line event.
- */
-struct line_event
-{
-	/**
-	 * @brief Possible event types.
-	 */
-	enum : int {
-		RISING_EDGE = 1,
-		/**< Rising edge event. */
-		FALLING_EDGE,
-		/**< Falling edge event. */
-	};
-
-	::std::chrono::nanoseconds timestamp;
-	/**< Best estimate of time of event occurrence in nanoseconds. */
-	int event_type;
-	/**< Type of the event that occurred. */
-	line source;
-	/**< Line object referencing the GPIO line on which the event occurred. */
-};
-
-/**
- * @brief Represents a set of GPIO lines.
- *
- * Internally an object of this class stores an array of line objects
- * owned by a single chip.
- */
-class line_bulk
-{
-public:
-
-	/**
-	 * @brief Default constructor. Creates an empty line_bulk object.
-	 */
-	line_bulk(void) = default;
-
-	/**
-	 * @brief Construct a line_bulk from a vector of lines.
-	 * @param lines Vector of gpiod::line objects.
-	 * @note All lines must be owned by the same GPIO chip.
-	 */
-	line_bulk(const ::std::vector<line>& lines);
-
-	/**
-	 * @brief Copy constructor.
-	 * @param other Other line_bulk object.
-	 */
-	line_bulk(const line_bulk& other) = default;
-
-	/**
-	 * @brief Move constructor.
-	 * @param other Other line_bulk object.
-	 */
-	line_bulk(line_bulk&& other) = default;
-
-	/**
-	 * @brief Assignment operator.
-	 * @param other Other line_bulk object.
-	 * @return Reference to this object.
-	 */
-	line_bulk& operator=(const line_bulk& other) = default;
-
-	/**
-	 * @brief Move assignment operator.
-	 * @param other Other line_bulk object.
-	 * @return Reference to this object.
-	 */
-	line_bulk& operator=(line_bulk&& other) = default;
-
-	/**
-	 * @brief Destructor.
-	 */
-	~line_bulk(void) = default;
-
-	/**
-	 * @brief Add a line to this line_bulk object.
-	 * @param new_line Line to add.
-	 * @note The new line must be owned by the same chip as all the other
-	 *       lines already held by this line_bulk object.
-	 */
-	void append(const line& new_line);
-
-	/**
-	 * @brief Get the line at given offset.
-	 * @param index Index of the line to get.
-	 * @return Reference to the line object.
-	 * @note This method will throw if index is equal or greater than the
-	 *       number of lines currently held by this bulk.
-	 */
-	line& get(unsigned int index);
-
-	/**
-	 * @brief Get the line at given offset without bounds checking.
-	 * @param index Offset of the line to get.
-	 * @return Reference to the line object.
-	 * @note No bounds checking is performed.
-	 */
-	line& operator[](unsigned int index);
-
-	/**
-	 * @brief Get the number of lines currently held by this object.
-	 * @return Number of elements in this line_bulk.
-	 */
-	unsigned int size(void) const noexcept;
-
-	/**
-	 * @brief Check if this line_bulk doesn't hold any lines.
-	 * @return True if this object is empty, false otherwise.
-	 */
-	bool empty(void) const noexcept;
-
-	/**
-	 * @brief Remove all lines from this object.
-	 */
-	void clear(void);
-
-	/**
-	 * @brief Request all lines held by this object.
-	 * @param config Request config (see gpiod::line_request).
-	 * @param default_vals Vector of default values. Only relevant for
-	 *                     output direction requests.
-	 */
-	void request(const line_request& config,
-		     const ::std::vector<int> default_vals = ::std::vector<int>()) const;
-
-	/**
-	 * @brief Release all lines held by this object.
-	 */
-	void release(void) const;
-
-	/**
-	 * @brief Read values from all lines held by this object.
-	 * @return Vector containing line values the order of which corresponds
-	 *         with the order of lines in the internal array.
-	 */
-	::std::vector<int> get_values(void) const;
-
-	/**
-	 * @brief Set values of all lines held by this object.
-	 * @param values Vector of values to set. Must be the same size as the
-	 *               number of lines held by this line_bulk.
-	 */
-	void set_values(const ::std::vector<int>& values) const;
-
-	/**
-	 * @brief Set configuration of all lines held by this object.
-	 * @param direction New direction.
-	 * @param flags Replacement flags.
-	 * @param values Vector of values to set. Must be the same size as the
-	 *               number of lines held by this line_bulk.
-	 *               Only relevant for output direction requests.
-	 */
-	void set_config(int direction, ::std::bitset<32> flags,
-			const ::std::vector<int> values = ::std::vector<int>()) const;
-
-	/**
-	 * @brief Set configuration flags of all lines held by this object.
-	 * @param flags Replacement flags.
-	 */
-	void set_flags(::std::bitset<32> flags) const;
-
-	/**
-	 * @brief Change the direction all lines held by this object to input.
-	 */
-	void set_direction_input() const;
-
-	/**
-	 * @brief Change the direction all lines held by this object to output.
-	 * @param values Vector of values to set. Must be the same size as the
-	 *               number of lines held by this line_bulk.
-	 */
-	void set_direction_output(const ::std::vector<int>& values) const;
-
-	/**
-	 * @brief Poll the set of lines for line events.
-	 * @param timeout Number of nanoseconds to wait before returning an
-	 *                empty line_bulk.
-	 * @return Returns a line_bulk object containing lines on which events
-	 *         occurred.
-	 */
-	line_bulk event_wait(const ::std::chrono::nanoseconds& timeout) const;
-
-	/**
-	 * @brief Check if this object holds any lines.
-	 * @return True if this line_bulk holds at least one line, false otherwise.
-	 */
-	explicit operator bool(void) const noexcept;
-
-	/**
-	 * @brief Check if this object doesn't hold any lines.
-	 * @return True if this line_bulk is empty, false otherwise.
-	 */
-	bool operator!(void) const noexcept;
-
-	/**
-	 * @brief Max number of lines that this object can hold.
-	 */
-	static const unsigned int MAX_LINES;
-
-	/**
-	 * @brief Iterator for iterating over lines held by line_bulk.
-	 */
-	class iterator
-	{
-	public:
-
-		/**
-		 * @brief Default constructor. Builds an empty iterator object.
-		 */
-		iterator(void) = default;
-
-		/**
-		 * @brief Copy constructor.
-		 * @param other Other line_bulk iterator.
-		 */
-		iterator(const iterator& other) = default;
-
-		/**
-		 * @brief Move constructor.
-		 * @param other Other line_bulk iterator.
-		 */
-		iterator(iterator&& other) = default;
-
-		/**
-		 * @brief Assignment operator.
-		 * @param other Other line_bulk iterator.
-		 * @return Reference to this iterator.
-		 */
-		iterator& operator=(const iterator& other) = default;
-
-		/**
-		 * @brief Move assignment operator.
-		 * @param other Other line_bulk iterator.
-		 * @return Reference to this iterator.
-		 */
-		iterator& operator=(iterator&& other) = default;
-
-		/**
-		 * @brief Destructor.
-		 */
-		~iterator(void) = default;
-
-		/**
-		 * @brief Advance the iterator by one element.
-		 * @return Reference to this iterator.
-		 */
-		iterator& operator++(void);
-
-		/**
-		 * @brief Dereference current element.
-		 * @return Current GPIO line by reference.
-		 */
-		const line& operator*(void) const;
-
-		/**
-		 * @brief Member access operator.
-		 * @return Current GPIO line by pointer.
-		 */
-		const line* operator->(void) const;
-
-		/**
-		 * @brief Check if this operator points to the same element.
-		 * @param rhs Right-hand side of the equation.
-		 * @return True if this iterator points to the same GPIO line,
-		 *         false otherwise.
-		 */
-		bool operator==(const iterator& rhs) const noexcept;
-
-		/**
-		 * @brief Check if this operator doesn't point to the same element.
-		 * @param rhs Right-hand side of the equation.
-		 * @return True if this iterator doesn't point to the same GPIO
-		 *         line, false otherwise.
-		 */
-		bool operator!=(const iterator& rhs) const noexcept;
-
-	private:
-
-		iterator(const ::std::vector<line>::iterator& it);
-
-		::std::vector<line>::iterator _m_iter;
-
-		friend line_bulk;
-	};
-
-	/**
-	 * @brief Returns an iterator to the first line.
-	 * @return A line_bulk iterator.
-	 */
-	iterator begin(void) noexcept;
-
-	/**
-	 * @brief Returns an iterator to the element following the last line.
-	 * @return A line_bulk iterator.
-	 */
-	iterator end(void) noexcept;
-
-private:
-
-	struct line_bulk_deleter
-	{
-		void operator()(::gpiod_line_bulk *bulk);
-	};
-
-	void throw_if_empty(void) const;
-
-	using line_bulk_ptr = ::std::unique_ptr<::gpiod_line_bulk, line_bulk_deleter>;
-
-	line_bulk_ptr make_line_bulk_ptr(void) const;
-	line_bulk_ptr to_line_bulk(void) const;
-
-	::std::vector<line> _m_bulk;
-};
-
-/**
- * @brief Support for range-based loops for line iterators.
- * @param iter A line iterator.
- * @return Iterator unchanged.
- */
-line_iter begin(line_iter iter) noexcept;
-
-/**
- * @brief Support for range-based loops for line iterators.
- * @param iter A line iterator.
- * @return New end iterator.
- */
-line_iter end(const line_iter& iter) noexcept;
-
-/**
- * @brief Allows to iterate over all lines owned by a GPIO chip.
- */
-class line_iter
-{
-public:
-
-	/**
-	 * @brief Default constructor. Creates the end iterator.
-	 */
-	line_iter(void) = default;
-
-	/**
-	 * @brief Constructor. Creates the begin iterator.
-	 * @param owner Chip owning the GPIO lines over which we want to iterate.
-	 */
-	line_iter(const chip& owner);
-
-	/**
-	 * @brief Copy constructor.
-	 * @param other Other line iterator.
-	 */
-	line_iter(const line_iter& other) = default;
-
-	/**
-	 * @brief Move constructor.
-	 * @param other Other line iterator.
-	 */
-	line_iter(line_iter&& other) = default;
-
-	/**
-	 * @brief Assignment operator.
-	 * @param other Other line iterator.
-	 * @return Reference to this line_iter.
-	 */
-	line_iter& operator=(const line_iter& other) = default;
-
-	/**
-	 * @brief Move assignment operator.
-	 * @param other Other line iterator.
-	 * @return Reference to this line_iter.
-	 */
-	line_iter& operator=(line_iter&& other) = default;
-
-	/**
-	 * @brief Destructor.
-	 */
-	~line_iter(void) = default;
-
-	/**
-	 * @brief Advance the iterator by one element.
-	 * @return Reference to this iterator.
-	 */
-	line_iter& operator++(void);
-
-	/**
-	 * @brief Dereference current element.
-	 * @return Current GPIO line by reference.
-	 */
-	const line& operator*(void) const;
-
-	/**
-	 * @brief Member access operator.
-	 * @return Current GPIO line by pointer.
-	 */
-	const line* operator->(void) const;
-
-	/**
-	 * @brief Check if this operator points to the same element.
-	 * @param rhs Right-hand side of the equation.
-	 * @return True if this iterator points to the same line_iter,
-	 *         false otherwise.
-	 */
-	bool operator==(const line_iter& rhs) const noexcept;
-
-	/**
-	 * @brief Check if this operator doesn't point to the same element.
-	 * @param rhs Right-hand side of the equation.
-	 * @return True if this iterator doesn't point to the same line_iter,
-	 *         false otherwise.
-	 */
-	bool operator!=(const line_iter& rhs) const noexcept;
-
-private:
-
-	line _m_current;
-};
-
-/**
- * @}
- */
-
-} /* namespace gpiod */
-
-#endif /* __LIBGPIOD_GPIOD_CXX_HPP__ */
diff --git a/bindings/cxx/internal.hpp b/bindings/cxx/internal.hpp
deleted file mode 100644
index 9406d30..0000000
--- a/bindings/cxx/internal.hpp
+++ /dev/null
@@ -1,9 +0,0 @@
-/* SPDX-License-Identifier: LGPL-3.0-or-later */
-/* SPDX-FileCopyrightText: 2021 Bartosz Golaszewski <bgolaszewski@baylibre.com> */
-
-#ifndef __LIBGPIOD_GPIOD_CXX_INTERNAL_HPP__
-#define __LIBGPIOD_GPIOD_CXX_INTERNAL_HPP__
-
-#define GPIOD_CXX_API __attribute__((visibility("default")))
-
-#endif /* __LIBGPIOD_GPIOD_CXX_INTERNAL_HPP__ */
diff --git a/bindings/cxx/iter.cpp b/bindings/cxx/iter.cpp
deleted file mode 100644
index 09d46f3..0000000
--- a/bindings/cxx/iter.cpp
+++ /dev/null
@@ -1,60 +0,0 @@
-// SPDX-License-Identifier: LGPL-3.0-or-later
-// SPDX-FileCopyrightText: 2017-2021 Bartosz Golaszewski <bartekgola@gmail.com>
-
-#include <gpiod.hpp>
-#include <system_error>
-
-#include "internal.hpp"
-
-namespace gpiod {
-
-GPIOD_CXX_API line_iter begin(line_iter iter) noexcept
-{
-	return iter;
-}
-
-GPIOD_CXX_API line_iter end(const line_iter&) noexcept
-{
-	return line_iter();
-}
-
-GPIOD_CXX_API line_iter::line_iter(const chip& owner)
-	: _m_current(owner.get_line(0))
-{
-
-}
-
-GPIOD_CXX_API line_iter& line_iter::operator++(void)
-{
-	unsigned int offset = this->_m_current.offset() + 1;
-	chip owner = this->_m_current.get_chip();
-
-	if (offset == owner.num_lines())
-		this->_m_current = line(); /* Last element */
-	else
-		this->_m_current = owner.get_line(offset);
-
-	return *this;
-}
-
-GPIOD_CXX_API const line& line_iter::operator*(void) const
-{
-	return this->_m_current;
-}
-
-GPIOD_CXX_API const line* line_iter::operator->(void) const
-{
-	return ::std::addressof(this->_m_current);
-}
-
-GPIOD_CXX_API bool line_iter::operator==(const line_iter& rhs) const noexcept
-{
-	return this->_m_current._m_line == rhs._m_current._m_line;
-}
-
-GPIOD_CXX_API bool line_iter::operator!=(const line_iter& rhs) const noexcept
-{
-	return this->_m_current._m_line != rhs._m_current._m_line;
-}
-
-} /* namespace gpiod */
diff --git a/bindings/cxx/libgpiodcxx.pc.in b/bindings/cxx/libgpiodcxx.pc.in
deleted file mode 100644
index 731227c..0000000
--- a/bindings/cxx/libgpiodcxx.pc.in
+++ /dev/null
@@ -1,14 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-or-later
-# SPDX-FileCopyrightText: 2017-2021 Bartosz Golaszewski <bartekgola@gmail.com>
-
-prefix=@prefix@
-exec_prefix=@exec_prefix@
-libdir=@libdir@
-includedir=@includedir@
-
-Name: libgpiodcxx
-Description: C++ bindings for libgpiod
-URL: @PACKAGE_URL@
-Version: @PACKAGE_VERSION@
-Libs: -L${libdir} -lgpiodcxx
-Cflags: -I${includedir}
diff --git a/bindings/cxx/line.cpp b/bindings/cxx/line.cpp
deleted file mode 100644
index cfcf2fb..0000000
--- a/bindings/cxx/line.cpp
+++ /dev/null
@@ -1,321 +0,0 @@
-// SPDX-License-Identifier: LGPL-3.0-or-later
-// SPDX-FileCopyrightText: 2017-2021 Bartosz Golaszewski <bartekgola@gmail.com>
-
-#include <gpiod.hpp>
-#include <array>
-#include <map>
-#include <system_error>
-
-#include "internal.hpp"
-
-namespace gpiod {
-
-namespace {
-
-const ::std::map<int, int> drive_mapping = {
-	{ GPIOD_LINE_DRIVE_PUSH_PULL,	line::DRIVE_PUSH_PULL, },
-	{ GPIOD_LINE_DRIVE_OPEN_DRAIN,	line::DRIVE_OPEN_DRAIN, },
-	{ GPIOD_LINE_DRIVE_OPEN_SOURCE,	line::DRIVE_OPEN_SOURCE, },
-};
-
-const ::std::map<int, int> bias_mapping = {
-	{ GPIOD_LINE_BIAS_UNKNOWN,	line::BIAS_UNKNOWN, },
-	{ GPIOD_LINE_BIAS_DISABLED,	line::BIAS_DISABLED, },
-	{ GPIOD_LINE_BIAS_PULL_UP,	line::BIAS_PULL_UP, },
-	{ GPIOD_LINE_BIAS_PULL_DOWN,	line::BIAS_PULL_DOWN, },
-};
-
-} /* namespace */
-
-GPIOD_CXX_API line::line(void)
-	: _m_line(nullptr),
-	  _m_owner()
-{
-
-}
-
-GPIOD_CXX_API line::line(::gpiod_line* line, const chip& owner)
-	: _m_line(line),
-	  _m_owner(owner._m_chip)
-{
-
-}
-
-GPIOD_CXX_API unsigned int line::offset(void) const
-{
-	this->throw_if_null();
-	line::chip_guard lock_chip(*this);
-
-	return ::gpiod_line_offset(this->_m_line);
-}
-
-GPIOD_CXX_API ::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);
-
-	return name ? ::std::string(name) : ::std::string();
-}
-
-GPIOD_CXX_API ::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);
-
-	return consumer ? ::std::string(consumer) : ::std::string();
-}
-
-GPIOD_CXX_API int line::direction(void) const
-{
-	this->throw_if_null();
-	line::chip_guard lock_chip(*this);
-
-	int dir = ::gpiod_line_direction(this->_m_line);
-
-	return dir == GPIOD_LINE_DIRECTION_INPUT ? DIRECTION_INPUT : DIRECTION_OUTPUT;
-}
-
-GPIOD_CXX_API bool line::is_active_low(void) const
-{
-	this->throw_if_null();
-	line::chip_guard lock_chip(*this);
-
-	return ::gpiod_line_is_active_low(this->_m_line);
-}
-
-GPIOD_CXX_API 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));
-}
-
-GPIOD_CXX_API bool line::is_used(void) const
-{
-	this->throw_if_null();
-	line::chip_guard lock_chip(*this);
-
-	return ::gpiod_line_is_used(this->_m_line);
-}
-
-GPIOD_CXX_API int line::drive(void) const
-{
-	this->throw_if_null();
-	line::chip_guard lock_chip(*this);
-
-	return drive_mapping.at(::gpiod_line_drive(this->_m_line));
-}
-
-GPIOD_CXX_API void line::request(const line_request& config, int default_val) const
-{
-	this->throw_if_null();
-
-	line_bulk bulk({ *this });
-
-	bulk.request(config, { default_val });
-}
-
-GPIOD_CXX_API void line::release(void) const
-{
-	this->throw_if_null();
-
-	line_bulk bulk({ *this });
-
-	bulk.release();
-}
-
-/*
- * REVISIT: Check the performance of get/set_value & event_wait compared to
- * the C API. Creating a line_bulk object involves a memory allocation every
- * time this method if called. If the performance is significantly lower,
- * switch to calling the C functions for setting/getting line values and
- * polling for events on single lines directly.
- */
-
-GPIOD_CXX_API int line::get_value(void) const
-{
-	this->throw_if_null();
-
-	line_bulk bulk({ *this });
-
-	return bulk.get_values()[0];
-}
-
-GPIOD_CXX_API void line::set_value(int val) const
-{
-	this->throw_if_null();
-
-	line_bulk bulk({ *this });
-
-	bulk.set_values({ val });
-}
-
-GPIOD_CXX_API void line::set_config(int direction, ::std::bitset<32> flags,
-				    int value) const
-{
-	this->throw_if_null();
-
-	line_bulk bulk({ *this });
-
-	bulk.set_config(direction, flags, { value });
-}
-
-GPIOD_CXX_API void line::set_flags(::std::bitset<32> flags) const
-{
-	this->throw_if_null();
-
-	line_bulk bulk({ *this });
-
-	bulk.set_flags(flags);
-}
-
-GPIOD_CXX_API void line::set_direction_input() const
-{
-	this->throw_if_null();
-
-	line_bulk bulk({ *this });
-
-	bulk.set_direction_input();
-}
-
-GPIOD_CXX_API void line::set_direction_output(int value) const
-{
-	this->throw_if_null();
-
-	line_bulk bulk({ *this });
-
-	bulk.set_direction_output({ value });
-}
-
-GPIOD_CXX_API bool line::event_wait(const ::std::chrono::nanoseconds& timeout) const
-{
-	this->throw_if_null();
-
-	line_bulk bulk({ *this });
-
-	line_bulk event_bulk = bulk.event_wait(timeout);
-
-	return !!event_bulk;
-}
-
-GPIOD_CXX_API line_event line::make_line_event(const ::gpiod_line_event& event) const noexcept
-{
-	line_event ret;
-
-	if (event.event_type == GPIOD_LINE_EVENT_RISING_EDGE)
-		ret.event_type = line_event::RISING_EDGE;
-	else if (event.event_type == GPIOD_LINE_EVENT_FALLING_EDGE)
-		ret.event_type = line_event::FALLING_EDGE;
-
-	ret.timestamp = ::std::chrono::duration_cast<::std::chrono::nanoseconds>(
-				::std::chrono::seconds(event.ts.tv_sec)) +
-				::std::chrono::nanoseconds(event.ts.tv_nsec);
-
-	ret.source = *this;
-
-	return ret;
-}
-
-GPIOD_CXX_API 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;
-	int rv;
-
-	rv = ::gpiod_line_event_read(this->_m_line, ::std::addressof(event_buf));
-	if (rv < 0)
-		throw ::std::system_error(errno, ::std::system_category(),
-					  "error reading line event");
-
-	return this->make_line_event(event_buf);
-}
-
-GPIOD_CXX_API ::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;
-	::std::vector<line_event> events;
-	int rv;
-
-	rv = ::gpiod_line_event_read_multiple(this->_m_line,
-					      event_buf.data(), event_buf.size());
-	if (rv < 0)
-		throw ::std::system_error(errno, ::std::system_category(),
-					  "error reading multiple line events");
-
-	events.reserve(rv);
-	for (int i = 0; i < rv; i++)
-		events.push_back(this->make_line_event(event_buf[i]));
-
-	return events;
-}
-
-GPIOD_CXX_API 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);
-
-	if (ret < 0)
-		throw ::std::system_error(errno, ::std::system_category(),
-					  "unable to get the line event file descriptor");
-
-	return ret;
-}
-
-GPIOD_CXX_API const chip line::get_chip(void) const
-{
-	return chip(this->_m_owner);
-}
-
-GPIOD_CXX_API void line::reset(void)
-{
-	this->_m_line = nullptr;
-	this->_m_owner.reset();
-}
-
-GPIOD_CXX_API bool line::operator==(const line& rhs) const noexcept
-{
-	return this->_m_line == rhs._m_line;
-}
-
-GPIOD_CXX_API bool line::operator!=(const line& rhs) const noexcept
-{
-	return this->_m_line != rhs._m_line;
-}
-
-GPIOD_CXX_API line::operator bool(void) const noexcept
-{
-	return this->_m_line != nullptr;
-}
-
-GPIOD_CXX_API bool line::operator!(void) const noexcept
-{
-	return this->_m_line == nullptr;
-}
-
-GPIOD_CXX_API void line::throw_if_null(void) const
-{
-	if (!this->_m_line)
-		throw ::std::logic_error("object not holding a GPIO line handle");
-}
-
-GPIOD_CXX_API line::chip_guard::chip_guard(const line& line)
-	: _m_chip(line._m_owner)
-{
-
-}
-
-} /* namespace gpiod */
diff --git a/bindings/cxx/line_bulk.cpp b/bindings/cxx/line_bulk.cpp
deleted file mode 100644
index a9261c0..0000000
--- a/bindings/cxx/line_bulk.cpp
+++ /dev/null
@@ -1,366 +0,0 @@
-// SPDX-License-Identifier: LGPL-3.0-or-later
-// SPDX-FileCopyrightText: 2017-2021 Bartosz Golaszewski <bartekgola@gmail.com>
-
-#include <gpiod.hpp>
-#include <map>
-#include <system_error>
-
-#include "internal.hpp"
-
-namespace gpiod {
-
-GPIOD_CXX_API const ::std::bitset<32> line_request::FLAG_ACTIVE_LOW(GPIOD_BIT(0));
-GPIOD_CXX_API const ::std::bitset<32> line_request::FLAG_OPEN_SOURCE(GPIOD_BIT(1));
-GPIOD_CXX_API const ::std::bitset<32> line_request::FLAG_OPEN_DRAIN(GPIOD_BIT(2));
-GPIOD_CXX_API const ::std::bitset<32> line_request::FLAG_BIAS_DISABLED(GPIOD_BIT(3));
-GPIOD_CXX_API const ::std::bitset<32> line_request::FLAG_BIAS_PULL_DOWN(GPIOD_BIT(4));
-GPIOD_CXX_API const ::std::bitset<32> line_request::FLAG_BIAS_PULL_UP(GPIOD_BIT(5));
-
-namespace {
-
-const ::std::map<int, int> reqtype_mapping = {
-	{ line_request::DIRECTION_AS_IS,	GPIOD_LINE_REQUEST_DIRECTION_AS_IS, },
-	{ line_request::DIRECTION_INPUT,	GPIOD_LINE_REQUEST_DIRECTION_INPUT, },
-	{ line_request::DIRECTION_OUTPUT,	GPIOD_LINE_REQUEST_DIRECTION_OUTPUT, },
-	{ line_request::EVENT_FALLING_EDGE,	GPIOD_LINE_REQUEST_EVENT_FALLING_EDGE, },
-	{ line_request::EVENT_RISING_EDGE,	GPIOD_LINE_REQUEST_EVENT_RISING_EDGE, },
-	{ line_request::EVENT_BOTH_EDGES,	GPIOD_LINE_REQUEST_EVENT_BOTH_EDGES, },
-};
-
-struct bitset_cmp
-{
-	bool operator()(const ::std::bitset<32>& lhs, const ::std::bitset<32>& rhs) const
-	{
-		return lhs.to_ulong() < rhs.to_ulong();
-	}
-};
-
-const ::std::map<::std::bitset<32>, int, bitset_cmp> reqflag_mapping = {
-	{ line_request::FLAG_ACTIVE_LOW,	GPIOD_LINE_REQUEST_FLAG_ACTIVE_LOW, },
-	{ line_request::FLAG_OPEN_DRAIN,	GPIOD_LINE_REQUEST_FLAG_OPEN_DRAIN, },
-	{ line_request::FLAG_OPEN_SOURCE,	GPIOD_LINE_REQUEST_FLAG_OPEN_SOURCE, },
-	{ line_request::FLAG_BIAS_DISABLED,	GPIOD_LINE_REQUEST_FLAG_BIAS_DISABLED, },
-	{ line_request::FLAG_BIAS_PULL_DOWN,	GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_DOWN, },
-	{ line_request::FLAG_BIAS_PULL_UP,	GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_UP, },
-};
-
-} /* namespace */
-
-GPIOD_CXX_API const unsigned int line_bulk::MAX_LINES = 64;
-
-GPIOD_CXX_API line_bulk::line_bulk(const ::std::vector<line>& lines)
-	: _m_bulk()
-{
-	this->_m_bulk.reserve(lines.size());
-
-	for (auto& it: lines)
-		this->append(it);
-}
-
-GPIOD_CXX_API void line_bulk::append(const line& new_line)
-{
-	if (!new_line)
-		throw ::std::logic_error("line_bulk cannot hold empty line objects");
-
-	if (this->_m_bulk.size() >= MAX_LINES)
-		throw ::std::logic_error("maximum number of lines reached");
-
-	if (this->_m_bulk.size() >= 1 && this->_m_bulk.begin()->get_chip() != new_line.get_chip())
-		throw ::std::logic_error("line_bulk cannot hold GPIO lines from different chips");
-
-	this->_m_bulk.push_back(new_line);
-}
-
-GPIOD_CXX_API line& line_bulk::get(unsigned int index)
-{
-	return this->_m_bulk.at(index);
-}
-
-GPIOD_CXX_API line& line_bulk::operator[](unsigned int index)
-{
-	return this->_m_bulk[index];
-}
-
-GPIOD_CXX_API unsigned int line_bulk::size(void) const noexcept
-{
-	return this->_m_bulk.size();
-}
-
-GPIOD_CXX_API bool line_bulk::empty(void) const noexcept
-{
-	return this->_m_bulk.empty();
-}
-
-GPIOD_CXX_API void line_bulk::clear(void)
-{
-	this->_m_bulk.clear();
-}
-
-GPIOD_CXX_API 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");
-
-	::gpiod_line_request_config conf;
-	auto bulk = this->to_line_bulk();
-	int rv;
-
-	conf.consumer = config.consumer.c_str();
-	conf.request_type = reqtype_mapping.at(config.request_type);
-	conf.flags = 0;
-
-	for (auto& it: reqflag_mapping) {
-		if ((it.first & config.flags).to_ulong())
-			conf.flags |= it.second;
-	}
-
-	rv = ::gpiod_line_request_bulk(bulk.get(),
-				       ::std::addressof(conf),
-				       default_vals.empty() ? NULL : default_vals.data());
-	if (rv)
-		throw ::std::system_error(errno, ::std::system_category(),
-					  "error requesting GPIO lines");
-}
-
-GPIOD_CXX_API void line_bulk::release(void) const
-{
-	this->throw_if_empty();
-	line::chip_guard lock_chip(this->_m_bulk.front());
-
-	auto bulk = this->to_line_bulk();
-
-	::gpiod_line_release_bulk(bulk.get());
-}
-
-GPIOD_CXX_API ::std::vector<int> line_bulk::get_values(void) const
-{
-	this->throw_if_empty();
-	line::chip_guard lock_chip(this->_m_bulk.front());
-
-	auto bulk = this->to_line_bulk();
-	::std::vector<int> values;
-	int rv;
-
-	values.resize(this->_m_bulk.size());
-
-	rv = ::gpiod_line_get_value_bulk(bulk.get(), values.data());
-	if (rv)
-		throw ::std::system_error(errno, ::std::system_category(),
-					  "error reading GPIO line values");
-
-	return values;
-}
-
-GPIOD_CXX_API 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");
-
-	auto bulk = this->to_line_bulk();
-	int rv;
-
-	rv = ::gpiod_line_set_value_bulk(bulk.get(), values.data());
-	if (rv)
-		throw ::std::system_error(errno, ::std::system_category(),
-					  "error setting GPIO line values");
-}
-
-GPIOD_CXX_API void line_bulk::set_config(int direction, ::std::bitset<32> flags,
-					 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");
-
-	auto bulk = this->to_line_bulk();
-	int rv, gflags;
-
-	gflags = 0;
-
-	for (auto& it: reqflag_mapping) {
-		if ((it.first & flags).to_ulong())
-			gflags |= it.second;
-	}
-
-	rv = ::gpiod_line_set_config_bulk(bulk.get(), direction,
-					  gflags, values.data());
-	if (rv)
-		throw ::std::system_error(errno, ::std::system_category(),
-					  "error setting GPIO line config");
-}
-
-GPIOD_CXX_API void line_bulk::set_flags(::std::bitset<32> flags) const
-{
-	this->throw_if_empty();
-	line::chip_guard lock_chip(this->_m_bulk.front());
-
-	auto bulk = this->to_line_bulk();
-	int rv, gflags;
-
-	gflags = 0;
-
-	for (auto& it: reqflag_mapping) {
-		if ((it.first & flags).to_ulong())
-			gflags |= it.second;
-	}
-
-	rv = ::gpiod_line_set_flags_bulk(bulk.get(), gflags);
-	if (rv)
-		throw ::std::system_error(errno, ::std::system_category(),
-					  "error setting GPIO line flags");
-}
-
-GPIOD_CXX_API void line_bulk::set_direction_input() const
-{
-	this->throw_if_empty();
-	line::chip_guard lock_chip(this->_m_bulk.front());
-
-	auto bulk = this->to_line_bulk();
-	int rv;
-
-	rv = ::gpiod_line_set_direction_input_bulk(bulk.get());
-	if (rv)
-		throw ::std::system_error(errno, ::std::system_category(),
-			"error setting GPIO line direction to input");
-}
-
-GPIOD_CXX_API 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");
-
-	auto bulk = this->to_line_bulk();
-	int rv;
-
-	rv = ::gpiod_line_set_direction_output_bulk(bulk.get(), values.data());
-	if (rv)
-		throw ::std::system_error(errno, ::std::system_category(),
-			"error setting GPIO line direction to output");
-}
-
-GPIOD_CXX_API 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());
-
-	auto ev_bulk = this->make_line_bulk_ptr();
-	auto bulk = this->to_line_bulk();
-	::timespec ts;
-	line_bulk ret;
-	int rv;
-
-	ts.tv_sec = timeout.count() / 1000000000ULL;
-	ts.tv_nsec = timeout.count() % 1000000000ULL;
-
-	rv = ::gpiod_line_event_wait_bulk(bulk.get(), ::std::addressof(ts), ev_bulk.get());
-	if (rv < 0) {
-		throw ::std::system_error(errno, ::std::system_category(),
-					  "error polling for events");
-	} else if (rv > 0) {
-		auto chip = this->_m_bulk[0].get_chip();
-		auto num_lines = ::gpiod_line_bulk_num_lines(ev_bulk.get());
-
-		for (unsigned int i = 0; i < num_lines; i++)
-			ret.append(line(::gpiod_line_bulk_get_line(ev_bulk.get(), i), chip));
-	}
-
-	return ret;
-}
-
-GPIOD_CXX_API line_bulk::operator bool(void) const noexcept
-{
-	return !this->_m_bulk.empty();
-}
-
-GPIOD_CXX_API bool line_bulk::operator!(void) const noexcept
-{
-	return this->_m_bulk.empty();
-}
-
-GPIOD_CXX_API line_bulk::iterator::iterator(const ::std::vector<line>::iterator& it)
-	: _m_iter(it)
-{
-
-}
-
-GPIOD_CXX_API line_bulk::iterator& line_bulk::iterator::operator++(void)
-{
-	this->_m_iter++;
-
-	return *this;
-}
-
-GPIOD_CXX_API const line& line_bulk::iterator::operator*(void) const
-{
-	return *this->_m_iter;
-}
-
-GPIOD_CXX_API const line* line_bulk::iterator::operator->(void) const
-{
-	return this->_m_iter.operator->();
-}
-
-GPIOD_CXX_API bool line_bulk::iterator::operator==(const iterator& rhs) const noexcept
-{
-	return this->_m_iter == rhs._m_iter;
-}
-
-GPIOD_CXX_API bool line_bulk::iterator::operator!=(const iterator& rhs) const noexcept
-{
-	return this->_m_iter != rhs._m_iter;
-}
-
-GPIOD_CXX_API line_bulk::iterator line_bulk::begin(void) noexcept
-{
-	return line_bulk::iterator(this->_m_bulk.begin());
-}
-
-GPIOD_CXX_API line_bulk::iterator line_bulk::end(void) noexcept
-{
-	return line_bulk::iterator(this->_m_bulk.end());
-}
-
-GPIOD_CXX_API void line_bulk::throw_if_empty(void) const
-{
-	if (this->_m_bulk.empty())
-		throw ::std::logic_error("line_bulk not holding any GPIO lines");
-}
-
-GPIOD_CXX_API line_bulk::line_bulk_ptr line_bulk::make_line_bulk_ptr(void) const
-{
-	line_bulk_ptr bulk(::gpiod_line_bulk_new(this->size()));
-
-	if (!bulk)
-		throw ::std::system_error(errno, ::std::system_category(),
-					  "unable to allocate new bulk object");
-
-	return bulk;
-}
-
-GPIOD_CXX_API line_bulk::line_bulk_ptr line_bulk::to_line_bulk(void) const
-{
-	line_bulk_ptr bulk = this->make_line_bulk_ptr();
-
-	for (auto& it: this->_m_bulk)
-		::gpiod_line_bulk_add_line(bulk.get(), it._m_line);
-
-	return bulk;
-}
-
-GPIOD_CXX_API void line_bulk::line_bulk_deleter::operator()(::gpiod_line_bulk *bulk)
-{
-	::gpiod_line_bulk_free(bulk);
-}
-
-} /* namespace gpiod */
diff --git a/bindings/cxx/tests/.gitignore b/bindings/cxx/tests/.gitignore
deleted file mode 100644
index 7990193..0000000
--- a/bindings/cxx/tests/.gitignore
+++ /dev/null
@@ -1,4 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-or-later
-# SPDX-FileCopyrightText: 2017-2021 Bartosz Golaszewski <bartekgola@gmail.com>
-
-gpiod-cxx-test
diff --git a/bindings/cxx/tests/Makefile.am b/bindings/cxx/tests/Makefile.am
deleted file mode 100644
index cbdecdc..0000000
--- a/bindings/cxx/tests/Makefile.am
+++ /dev/null
@@ -1,21 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-or-later
-# SPDX-FileCopyrightText: 2017-2021 Bartosz Golaszewski <bartekgola@gmail.com>
-
-AM_CPPFLAGS = -I$(top_srcdir)/bindings/cxx/ -I$(top_srcdir)/include
-AM_CPPFLAGS += -I$(top_srcdir)/tests/mockup/
-AM_CPPFLAGS += -Wall -Wextra -g -std=gnu++11 $(CATCH2_CFLAGS)
-AM_LDFLAGS = -lgpiodcxx -L$(top_builddir)/bindings/cxx/
-AM_LDFLAGS += -lgpiomockup -L$(top_builddir)/tests/mockup/
-AM_LDFLAGS += -pthread
-
-bin_PROGRAMS = gpiod-cxx-test
-
-gpiod_cxx_test_SOURCES =			\
-		gpiod-cxx-test-main.cpp		\
-		gpiod-cxx-test.cpp		\
-		gpio-mockup.cpp			\
-		gpio-mockup.hpp			\
-		tests-chip.cpp			\
-		tests-event.cpp			\
-		tests-iter.cpp			\
-		tests-line.cpp
diff --git a/bindings/cxx/tests/gpio-mockup.cpp b/bindings/cxx/tests/gpio-mockup.cpp
deleted file mode 100644
index 2e99dd4..0000000
--- a/bindings/cxx/tests/gpio-mockup.cpp
+++ /dev/null
@@ -1,153 +0,0 @@
-// SPDX-License-Identifier: LGPL-3.0-or-later
-// SPDX-FileCopyrightText: 2017-2021 Bartosz Golaszewski <bartekgola@gmail.com>
-
-#include <system_error>
-
-#include "gpio-mockup.hpp"
-
-namespace gpiod {
-namespace test {
-
-const ::std::bitset<32> mockup::FLAG_NAMED_LINES("1");
-
-mockup& mockup::instance(void)
-{
-	static mockup mockup;
-
-	return mockup;
-}
-
-mockup::mockup(void) : _m_mockup(::gpio_mockup_new())
-{
-	if (!this->_m_mockup)
-		throw ::std::system_error(errno, ::std::system_category(),
-					  "unable to create the gpio-mockup context");
-}
-
-mockup::~mockup(void)
-{
-	::gpio_mockup_unref(this->_m_mockup);
-}
-
-void mockup::probe(const ::std::vector<unsigned int>& chip_sizes,
-		   const ::std::bitset<32>& flags)
-{
-	int ret, probe_flags = 0;
-
-	if (flags.to_ulong() & FLAG_NAMED_LINES.to_ulong())
-		probe_flags |= GPIO_MOCKUP_FLAG_NAMED_LINES;
-
-	ret = ::gpio_mockup_probe(this->_m_mockup, chip_sizes.size(),
-				  chip_sizes.data(), probe_flags);
-	if (ret)
-		throw ::std::system_error(errno, ::std::system_category(),
-					  "unable to probe gpio-mockup module");
-}
-
-void mockup::remove(void)
-{
-	int ret = ::gpio_mockup_remove(this->_m_mockup);
-	if (ret)
-		throw ::std::system_error(errno, ::std::system_category(),
-					  "unable to remove gpio-mockup module");
-}
-
-::std::string mockup::chip_name(unsigned int idx) const
-{
-	const char *name = ::gpio_mockup_chip_name(this->_m_mockup, idx);
-	if (!name)
-		throw ::std::system_error(errno, ::std::system_category(),
-					  "unable to retrieve the chip name");
-
-	return ::std::string(name);
-}
-
-::std::string mockup::chip_path(unsigned int idx) const
-{
-	const char *path = ::gpio_mockup_chip_path(this->_m_mockup, idx);
-	if (!path)
-		throw ::std::system_error(errno, ::std::system_category(),
-					  "unable to retrieve the chip path");
-
-	return ::std::string(path);
-}
-
-unsigned int mockup::chip_num(unsigned int idx) const
-{
-	int num = ::gpio_mockup_chip_num(this->_m_mockup, idx);
-	if (num < 0)
-		throw ::std::system_error(errno, ::std::system_category(),
-					  "unable to retrieve the chip number");
-
-	return num;
-}
-
-int mockup::chip_get_value(unsigned int chip_idx, unsigned int line_offset)
-{
-	int val = ::gpio_mockup_get_value(this->_m_mockup, chip_idx, line_offset);
-	if (val < 0)
-		throw ::std::system_error(errno, ::std::system_category(),
-					  "error reading the line value");
-
-	return val;
-}
-
-void mockup::chip_set_pull(unsigned int chip_idx, unsigned int line_offset, int pull)
-{
-	int ret = ::gpio_mockup_set_pull(this->_m_mockup, chip_idx, line_offset, pull);
-	if (ret)
-		throw ::std::system_error(errno, ::std::system_category(),
-					  "error setting line pull");
-}
-
-mockup::probe_guard::probe_guard(const ::std::vector<unsigned int>& chip_sizes,
-				 const ::std::bitset<32>& flags)
-{
-	mockup::instance().probe(chip_sizes, flags);
-}
-
-mockup::probe_guard::~probe_guard(void)
-{
-	mockup::instance().remove();
-}
-
-mockup::event_thread::event_thread(unsigned int chip_index,
-				   unsigned int line_offset, unsigned int period_ms)
-	: _m_chip_index(chip_index),
-	  _m_line_offset(line_offset),
-	  _m_period_ms(period_ms),
-	  _m_stop(false),
-	  _m_mutex(),
-	  _m_cond(),
-	  _m_thread(&event_thread::event_worker, this)
-{
-
-}
-
-mockup::event_thread::~event_thread(void)
-{
-	::std::unique_lock<::std::mutex> lock(this->_m_mutex);
-	this->_m_stop = true;
-	this->_m_cond.notify_all();
-	lock.unlock();
-	this->_m_thread.join();
-}
-
-void mockup::event_thread::event_worker(void)
-{
-	for (unsigned int i = 0;; i++) {
-		::std::unique_lock<::std::mutex> lock(this->_m_mutex);
-
-		if (this->_m_stop)
-			break;
-
-		::std::cv_status status = this->_m_cond.wait_for(lock,
-						std::chrono::milliseconds(this->_m_period_ms));
-		if (status == ::std::cv_status::timeout)
-			mockup::instance().chip_set_pull(this->_m_chip_index,
-							 this->_m_line_offset, i % 2);
-	}
-}
-
-} /* namespace test */
-} /* namespace gpiod */
diff --git a/bindings/cxx/tests/gpio-mockup.hpp b/bindings/cxx/tests/gpio-mockup.hpp
deleted file mode 100644
index 9ca27bd..0000000
--- a/bindings/cxx/tests/gpio-mockup.hpp
+++ /dev/null
@@ -1,94 +0,0 @@
-/* SPDX-License-Identifier: LGPL-3.0-or-later */
-/* SPDX-FileCopyrightText: 2017-2021 Bartosz Golaszewski <bartekgola@gmail.com> */
-
-#ifndef __GPIOD_CXX_TEST_HPP__
-#define __GPIOD_CXX_TEST_HPP__
-
-#include <bitset>
-#include <condition_variable>
-#include <gpio-mockup.h>
-#include <mutex>
-#include <string>
-#include <vector>
-#include <thread>
-
-namespace gpiod {
-namespace test {
-
-class mockup
-{
-public:
-
-	static mockup& instance(void);
-
-	mockup(const mockup& other) = delete;
-	mockup(mockup&& other) = delete;
-	mockup& operator=(const mockup& other) = delete;
-	mockup& operator=(mockup&& other) = delete;
-
-	void probe(const ::std::vector<unsigned int>& chip_sizes,
-		   const ::std::bitset<32>& flags = 0);
-	void remove(void);
-
-	std::string chip_name(unsigned int idx) const;
-	std::string chip_path(unsigned int idx) const;
-	unsigned int chip_num(unsigned int idx) const;
-
-	int chip_get_value(unsigned int chip_idx, unsigned int line_offset);
-	void chip_set_pull(unsigned int chip_idx, unsigned int line_offset, int pull);
-
-	static const ::std::bitset<32> FLAG_NAMED_LINES;
-
-	class probe_guard
-	{
-	public:
-
-		probe_guard(const ::std::vector<unsigned int>& chip_sizes,
-			    const ::std::bitset<32>& flags = 0);
-		~probe_guard(void);
-
-		probe_guard(const probe_guard& other) = delete;
-		probe_guard(probe_guard&& other) = delete;
-		probe_guard& operator=(const probe_guard& other) = delete;
-		probe_guard& operator=(probe_guard&& other) = delete;
-	};
-
-	class event_thread
-	{
-	public:
-
-		event_thread(unsigned int chip_index, unsigned int line_offset, unsigned int period_ms);
-		~event_thread(void);
-
-		event_thread(const event_thread& other) = delete;
-		event_thread(event_thread&& other) = delete;
-		event_thread& operator=(const event_thread& other) = delete;
-		event_thread& operator=(event_thread&& other) = delete;
-
-	private:
-
-		void event_worker(void);
-
-		unsigned int _m_chip_index;
-		unsigned int _m_line_offset;
-		unsigned int _m_period_ms;
-
-		bool _m_stop;
-
-		::std::mutex _m_mutex;
-		::std::condition_variable _m_cond;
-		::std::thread _m_thread;
-	};
-
-private:
-
-	mockup(void);
-	~mockup(void);
-
-	::gpio_mockup *_m_mockup;
-};
-
-} /* namespace test */
-} /* namespace gpiod */
-
-#endif /* __GPIOD_CXX_TEST_HPP__ */
diff --git a/bindings/cxx/tests/gpiod-cxx-test-main.cpp b/bindings/cxx/tests/gpiod-cxx-test-main.cpp
deleted file mode 100644
index 11bf8e5..0000000
--- a/bindings/cxx/tests/gpiod-cxx-test-main.cpp
+++ /dev/null
@@ -1,5 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-// SPDX-FileCopyrightText: 2017-2021 Bartosz Golaszewski <bartekgola@gmail.com>
-
-#define CATCH_CONFIG_MAIN
-#include <catch2/catch.hpp>
diff --git a/bindings/cxx/tests/gpiod-cxx-test.cpp b/bindings/cxx/tests/gpiod-cxx-test.cpp
deleted file mode 100644
index 834f372..0000000
--- a/bindings/cxx/tests/gpiod-cxx-test.cpp
+++ /dev/null
@@ -1,55 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-// SPDX-FileCopyrightText: 2017-2021 Bartosz Golaszewski <bartekgola@gmail.com>
-
-#include <linux/version.h>
-#include <sys/utsname.h>
-#include <system_error>
-#include <sstream>
-
-namespace {
-
-class kernel_checker
-{
-public:
-
-	kernel_checker(unsigned int major, unsigned int minor, unsigned int release)
-	{
-		unsigned long curr_major, curr_minor, curr_release, curr_ver, req_ver;
-		::std::string major_str, minor_str, release_str;
-		::utsname un;
-		int ret;
-
-		ret = ::uname(::std::addressof(un));
-		if (ret)
-			throw ::std::system_error(errno, ::std::system_category(),
-						  "unable to read the kernel version");
-
-		::std::stringstream ver_stream(::std::string(un.release));
-		::std::getline(ver_stream, major_str, '.');
-		::std::getline(ver_stream, minor_str, '.');
-		::std::getline(ver_stream, release_str, '.');
-
-		curr_major = ::std::stoul(major_str, nullptr, 0);
-		curr_minor = ::std::stoul(minor_str, nullptr, 0);
-		curr_release = ::std::stoul(release_str, nullptr, 0);
-
-		curr_ver = KERNEL_VERSION(curr_major, curr_minor, curr_release);
-		req_ver = KERNEL_VERSION(major, minor, release);
-
-		if (curr_ver < req_ver)
-			throw ::std::system_error(EOPNOTSUPP, ::std::system_category(),
-						  "kernel release must be at least: " +
-						  ::std::to_string(major) + "." +
-						  ::std::to_string(minor) + "." +
-						  ::std::to_string(release));
-	}
-
-	kernel_checker(const kernel_checker& other) = delete;
-	kernel_checker(kernel_checker&& other) = delete;
-	kernel_checker& operator=(const kernel_checker& other) = delete;
-	kernel_checker& operator=(kernel_checker&& other) = delete;
-};
-
-kernel_checker require_kernel(5, 10, 0);
-
-} /* namespace */
diff --git a/bindings/cxx/tests/tests-chip.cpp b/bindings/cxx/tests/tests-chip.cpp
deleted file mode 100644
index aea00fa..0000000
--- a/bindings/cxx/tests/tests-chip.cpp
+++ /dev/null
@@ -1,173 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-// SPDX-FileCopyrightText: 2017-2021 Bartosz Golaszewski <bartekgola@gmail.com>
-
-#include <catch2/catch.hpp>
-#include <gpiod.hpp>
-
-#include "gpio-mockup.hpp"
-
-using ::gpiod::test::mockup;
-
-TEST_CASE("GPIO chip device can be verified with is_gpiochip_device()", "[chip]")
-{
-	mockup::probe_guard mockup_chips({ 8 });
-
-	SECTION("good chip")
-	{
-		REQUIRE(::gpiod::is_gpiochip_device(mockup::instance().chip_path(0)));
-	}
-
-	SECTION("not a chip")
-	{
-		REQUIRE_FALSE(::gpiod::is_gpiochip_device("/dev/null"));
-	}
-
-	SECTION("nonexistent file")
-	{
-		REQUIRE_FALSE(::gpiod::is_gpiochip_device("/dev/nonexistent_device"));
-	}
-}
-
-TEST_CASE("GPIO chip device can be opened", "[chip]")
-{
-	mockup::probe_guard mockup_chips({ 8, 8, 8 });
-
-	SECTION("open from constructor")
-	{
-		REQUIRE_NOTHROW(::gpiod::chip(mockup::instance().chip_path(1)));
-	}
-
-	SECTION("open from open() method")
-	{
-		::gpiod::chip chip;
-
-		REQUIRE_FALSE(!!chip);
-
-		REQUIRE_NOTHROW(chip.open(mockup::instance().chip_path(1)));
-	}
-}
-
-TEST_CASE("Uninitialized GPIO chip behaves correctly", "[chip]")
-{
-	::gpiod::chip chip;
-
-	SECTION("uninitialized chip is 'false'")
-	{
-		REQUIRE_FALSE(!!chip);
-	}
-
-	SECTION("using uninitialized chip throws logic_error")
-	{
-		REQUIRE_THROWS_AS(chip.name(), ::std::logic_error);
-	}
-}
-
-TEST_CASE("Trying to open a nonexistent chip throws system_error", "[chip]")
-{
-	REQUIRE_THROWS_AS(::gpiod::chip("nonexistent-chip"), ::std::system_error);
-}
-
-TEST_CASE("Chip object can be reset", "[chip]")
-{
-	mockup::probe_guard mockup_chips({ 8 });
-
-	::gpiod::chip chip(mockup::instance().chip_path(0));
-	REQUIRE(chip);
-	chip.reset();
-	REQUIRE_FALSE(!!chip);
-}
-
-TEST_CASE("Chip info can be correctly retrieved", "[chip]")
-{
-	mockup::probe_guard mockup_chips({ 8, 16, 8 });
-
-	::gpiod::chip chip(mockup::instance().chip_path(1));
-	REQUIRE(chip.name() == mockup::instance().chip_name(1));
-	REQUIRE(chip.label() == "gpio-mockup-B");
-	REQUIRE(chip.num_lines() == 16);
-}
-
-TEST_CASE("Chip object can be copied and compared", "[chip]")
-{
-	mockup::probe_guard mockup_chips({ 8, 8 });
-
-	::gpiod::chip chip1(mockup::instance().chip_path(0));
-	auto chip2 = chip1;
-	REQUIRE(chip1 == chip2);
-	REQUIRE_FALSE(chip1 != chip2);
-	::gpiod::chip chip3(mockup::instance().chip_path(1));
-	REQUIRE(chip1 != chip3);
-	REQUIRE_FALSE(chip2 == chip3);
-}
-
-TEST_CASE("Lines can be retrieved from chip objects", "[chip]")
-{
-	mockup::probe_guard mockup_chips({ 8, 8, 8 }, mockup::FLAG_NAMED_LINES);
-	::gpiod::chip chip(mockup::instance().chip_path(1));
-
-	SECTION("get single line by offset")
-	{
-		auto line = chip.get_line(3);
-		REQUIRE(line.name() == "gpio-mockup-B-3");
-	}
-
-	SECTION("find single line by name")
-	{
-		auto offset = chip.find_line("gpio-mockup-B-3");
-		REQUIRE(offset == 3);
-	}
-
-	SECTION("get multiple lines by offsets")
-	{
-		auto lines = chip.get_lines({ 1, 3, 4, 7});
-		REQUIRE(lines.size() == 4);
-		REQUIRE(lines.get(0).name() == "gpio-mockup-B-1");
-		REQUIRE(lines.get(1).name() == "gpio-mockup-B-3");
-		REQUIRE(lines.get(2).name() == "gpio-mockup-B-4");
-		REQUIRE(lines.get(3).name() == "gpio-mockup-B-7");
-	}
-
-	SECTION("get multiple lines by offsets in mixed order")
-	{
-		auto lines = chip.get_lines({ 5, 1, 3, 2});
-		REQUIRE(lines.size() == 4);
-		REQUIRE(lines.get(0).name() == "gpio-mockup-B-5");
-		REQUIRE(lines.get(1).name() == "gpio-mockup-B-1");
-		REQUIRE(lines.get(2).name() == "gpio-mockup-B-3");
-		REQUIRE(lines.get(3).name() == "gpio-mockup-B-2");
-	}
-}
-
-TEST_CASE("All lines can be retrieved from a chip at once", "[chip]")
-{
-	mockup::probe_guard mockup_chips({ 4 });
-	::gpiod::chip chip(mockup::instance().chip_path(0));
-
-	auto lines = chip.get_all_lines();
-	REQUIRE(lines.size() == 4);
-	REQUIRE(lines.get(0).offset() == 0);
-	REQUIRE(lines.get(1).offset() == 1);
-	REQUIRE(lines.get(2).offset() == 2);
-	REQUIRE(lines.get(3).offset() == 3);
-}
-
-TEST_CASE("Errors occurring when retrieving lines are correctly reported", "[chip]")
-{
-	mockup::probe_guard mockup_chips({ 8 }, mockup::FLAG_NAMED_LINES);
-	::gpiod::chip chip(mockup::instance().chip_path(0));
-
-	SECTION("invalid offset (single line)")
-	{
-		REQUIRE_THROWS_AS(chip.get_line(9), ::std::out_of_range);
-	}
-
-	SECTION("invalid offset (multiple lines)")
-	{
-		REQUIRE_THROWS_AS(chip.get_lines({ 1, 19, 4, 7 }), ::std::out_of_range);
-	}
-
-	SECTION("line not found by name")
-	{
-		REQUIRE(chip.find_line("nonexistent-line") == -1);
-	}
-}
diff --git a/bindings/cxx/tests/tests-event.cpp b/bindings/cxx/tests/tests-event.cpp
deleted file mode 100644
index aeb50dd..0000000
--- a/bindings/cxx/tests/tests-event.cpp
+++ /dev/null
@@ -1,280 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-// SPDX-FileCopyrightText: 2017-2021 Bartosz Golaszewski <bartekgola@gmail.com>
-
-#include <catch2/catch.hpp>
-#include <gpiod.hpp>
-#include <poll.h>
-#include <thread>
-
-#include "gpio-mockup.hpp"
-
-using ::gpiod::test::mockup;
-
-namespace {
-
-const ::std::string consumer = "event-test";
-
-} /* namespace */
-
-TEST_CASE("Line events can be detected", "[event][line]")
-{
-	mockup::probe_guard mockup_chips({ 8 });
-	mockup::event_thread events(0, 4, 200);
-	::gpiod::chip chip(mockup::instance().chip_path(0));
-	auto line = chip.get_line(4);
-	::gpiod::line_request config;
-
-	config.consumer = consumer.c_str();
-
-	SECTION("rising edge")
-	{
-		config.request_type = ::gpiod::line_request::EVENT_RISING_EDGE;
-		line.request(config);
-
-		auto got_event = line.event_wait(::std::chrono::seconds(1));
-		REQUIRE(got_event);
-
-		auto event = line.event_read();
-		REQUIRE(event.source == line);
-		REQUIRE(event.event_type == ::gpiod::line_event::RISING_EDGE);
-	}
-
-	SECTION("falling edge")
-	{
-		config.request_type = ::gpiod::line_request::EVENT_FALLING_EDGE;
-
-		line.request(config);
-
-		auto got_event = line.event_wait(::std::chrono::seconds(1));
-		REQUIRE(got_event);
-
-		auto event = line.event_read();
-		REQUIRE(event.source == line);
-		REQUIRE(event.event_type == ::gpiod::line_event::FALLING_EDGE);
-	}
-
-	SECTION("both edges")
-	{
-		config.request_type = ::gpiod::line_request::EVENT_BOTH_EDGES;
-
-		line.request(config);
-
-		auto got_event = line.event_wait(::std::chrono::seconds(1));
-		REQUIRE(got_event);
-
-		auto event = line.event_read();
-		REQUIRE(event.source == line);
-		REQUIRE(event.event_type == ::gpiod::line_event::RISING_EDGE);
-
-		got_event = line.event_wait(::std::chrono::seconds(1));
-		REQUIRE(got_event);
-
-		event = line.event_read();
-		REQUIRE(event.source == line);
-		REQUIRE(event.event_type == ::gpiod::line_event::FALLING_EDGE);
-	}
-
-	SECTION("active-low")
-	{
-		config.request_type = ::gpiod::line_request::EVENT_BOTH_EDGES;
-		config.flags = ::gpiod::line_request::FLAG_ACTIVE_LOW;
-
-		line.request(config);
-
-		auto got_event = line.event_wait(::std::chrono::seconds(1));
-		REQUIRE(got_event);
-
-		auto event = line.event_read();
-		REQUIRE(event.source == line);
-		REQUIRE(event.event_type == ::gpiod::line_event::FALLING_EDGE);
-
-		got_event = line.event_wait(::std::chrono::seconds(1));
-		REQUIRE(got_event);
-
-		event = line.event_read();
-		REQUIRE(event.source == line);
-		REQUIRE(event.event_type == ::gpiod::line_event::RISING_EDGE);
-	}
-}
-
-TEST_CASE("Watching line_bulk objects for events works", "[event][bulk]")
-{
-	mockup::probe_guard mockup_chips({ 8 });
-	mockup::event_thread events(0, 2, 200);
-	::gpiod::chip chip(mockup::instance().chip_path(0));
-	auto lines = chip.get_lines({ 0, 1, 2, 3 });
-	::gpiod::line_request config;
-
-	config.consumer = consumer.c_str();
-	config.request_type = ::gpiod::line_request::EVENT_BOTH_EDGES;
-	lines.request(config);
-
-	auto event_lines = lines.event_wait(::std::chrono::seconds(1));
-	REQUIRE(event_lines);
-	REQUIRE(event_lines.size() == 1);
-
-	auto event = event_lines.get(0).event_read();
-	REQUIRE(event.source == event_lines.get(0));
-	REQUIRE(event.event_type == ::gpiod::line_event::RISING_EDGE);
-
-	event_lines = lines.event_wait(::std::chrono::seconds(1));
-	REQUIRE(event_lines);
-	REQUIRE(event_lines.size() == 1);
-
-	event = event_lines.get(0).event_read();
-	REQUIRE(event.source == event_lines.get(0));
-	REQUIRE(event.event_type == ::gpiod::line_event::FALLING_EDGE);
-}
-
-TEST_CASE("It's possible to retrieve the event file descriptor", "[event][line]")
-{
-	mockup::probe_guard mockup_chips({ 8 });
-	::gpiod::chip chip(mockup::instance().chip_path(0));
-	auto line = chip.get_line(4);
-	::gpiod::line_request config;
-
-	config.consumer = consumer.c_str();
-
-	SECTION("get the fd")
-	{
-		config.request_type = ::gpiod::line_request::EVENT_BOTH_EDGES;
-
-		line.request(config);
-		REQUIRE(line.event_get_fd() >= 0);
-	}
-
-	SECTION("error if not requested")
-	{
-		REQUIRE_THROWS_AS(line.event_get_fd(), ::std::system_error);
-	}
-
-	SECTION("error if requested for values")
-	{
-		config.request_type = ::gpiod::line_request::DIRECTION_INPUT;
-
-		line.request(config);
-		REQUIRE_THROWS_AS(line.event_get_fd(), ::std::system_error);
-	}
-}
-
-TEST_CASE("Event file descriptors can be used for polling", "[event]")
-{
-	mockup::probe_guard mockup_chips({ 8 });
-	mockup::event_thread events(0, 3, 200);
-	::gpiod::chip chip(mockup::instance().chip_path(0));
-	auto lines = chip.get_lines({ 0, 1, 2, 3, 4, 5 });
-
-	::gpiod::line_request config;
-	config.consumer = consumer.c_str();
-	config.request_type = ::gpiod::line_request::EVENT_BOTH_EDGES;
-
-	lines.request(config);
-
-	::std::vector<::pollfd> fds(3);
-	fds[0].fd = lines[1].event_get_fd();
-	fds[1].fd = lines[3].event_get_fd();
-	fds[2].fd = lines[5].event_get_fd();
-
-	fds[0].events = fds[1].events = fds[2].events = POLLIN | POLLPRI;
-
-	int ret = ::poll(fds.data(), 3, 1000);
-	REQUIRE(ret == 1);
-
-	for (int i = 0; i < 3; i++) {
-		if (fds[i].revents) {
-			auto event = lines[3].event_read();
-			REQUIRE(event.source == lines[3]);
-			REQUIRE(event.event_type == ::gpiod::line_event::RISING_EDGE);
-		}
-	}
-}
-
-TEST_CASE("It's possible to read a value from a line requested for events", "[event][line]")
-{
-	mockup::probe_guard mockup_chips({ 8 });
-	::gpiod::chip chip(mockup::instance().chip_path(0));
-	auto line = chip.get_line(4);
-	::gpiod::line_request config;
-
-	config.consumer = consumer.c_str();
-	config.request_type = ::gpiod::line_request::EVENT_BOTH_EDGES;
-
-	mockup::instance().chip_set_pull(0, 4, 1);
-
-	SECTION("active-high (default)")
-	{
-		line.request(config);
-		REQUIRE(line.get_value() == 1);
-	}
-
-	SECTION("active-low")
-	{
-		config.flags = ::gpiod::line_request::FLAG_ACTIVE_LOW;
-		line.request(config);
-		REQUIRE(line.get_value() == 0);
-	}
-}
-
-TEST_CASE("It's possible to read values from lines requested for events", "[event][bulk]")
-{
-	mockup::probe_guard mockup_chips({ 8 });
-	::gpiod::chip chip(mockup::instance().chip_path(0));
-	auto lines = chip.get_lines({ 0, 1, 2, 3, 4 });
-	::gpiod::line_request config;
-
-	config.consumer = consumer.c_str();
-	config.request_type = ::gpiod::line_request::EVENT_BOTH_EDGES;
-
-	mockup::instance().chip_set_pull(0, 5, 1);
-
-	SECTION("active-high (default)")
-	{
-		lines.request(config);
-		REQUIRE(lines.get_values() == ::std::vector<int>({ 0, 0, 0, 0, 0 }));
-		mockup::instance().chip_set_pull(0, 1, 1);
-		mockup::instance().chip_set_pull(0, 3, 1);
-		mockup::instance().chip_set_pull(0, 4, 1);
-		REQUIRE(lines.get_values() == ::std::vector<int>({ 0, 1, 0, 1, 1 }));
-	}
-
-	SECTION("active-low")
-	{
-		config.flags = ::gpiod::line_request::FLAG_ACTIVE_LOW;
-		lines.request(config);
-		REQUIRE(lines.get_values() == ::std::vector<int>({ 1, 1, 1, 1, 1 }));
-		mockup::instance().chip_set_pull(0, 1, 1);
-		mockup::instance().chip_set_pull(0, 3, 1);
-		mockup::instance().chip_set_pull(0, 4, 1);
-		REQUIRE(lines.get_values() == ::std::vector<int>({ 1, 0, 1, 0, 0 }));
-	}
-}
-
-TEST_CASE("It's possible to read more than one line event", "[event][line]")
-{
-	mockup::probe_guard mockup_chips({ 8 });
-	::gpiod::chip chip(mockup::instance().chip_path(0));
-	auto line = chip.get_line(4);
-	::gpiod::line_request config;
-
-	config.consumer = consumer.c_str();
-	config.request_type = ::gpiod::line_request::EVENT_BOTH_EDGES;
-
-	line.request(config);
-
-	mockup::instance().chip_set_pull(0, 4, 1);
-	::std::this_thread::sleep_for(::std::chrono::milliseconds(10));
-	mockup::instance().chip_set_pull(0, 4, 0);
-	::std::this_thread::sleep_for(::std::chrono::milliseconds(10));
-	mockup::instance().chip_set_pull(0, 4, 1);
-	::std::this_thread::sleep_for(::std::chrono::milliseconds(10));
-
-	auto events = line.event_read_multiple();
-
-	REQUIRE(events.size() == 3);
-	REQUIRE(events.at(0).event_type == ::gpiod::line_event::RISING_EDGE);
-	REQUIRE(events.at(1).event_type == ::gpiod::line_event::FALLING_EDGE);
-	REQUIRE(events.at(2).event_type == ::gpiod::line_event::RISING_EDGE);
-	REQUIRE(events.at(0).source == line);
-	REQUIRE(events.at(1).source == line);
-	REQUIRE(events.at(2).source == line);
-}
diff --git a/bindings/cxx/tests/tests-iter.cpp b/bindings/cxx/tests/tests-iter.cpp
deleted file mode 100644
index 848889b..0000000
--- a/bindings/cxx/tests/tests-iter.cpp
+++ /dev/null
@@ -1,21 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-// SPDX-FileCopyrightText: 2017-2021 Bartosz Golaszewski <bartekgola@gmail.com>
-
-#include <catch2/catch.hpp>
-#include <gpiod.hpp>
-
-#include "gpio-mockup.hpp"
-
-using ::gpiod::test::mockup;
-
-TEST_CASE("Line iterator works", "[iter][line]")
-{
-	mockup::probe_guard mockup_chips({ 4 });
-	::gpiod::chip chip(mockup::instance().chip_path(0));
-	unsigned int count = 0;
-
-	for (auto& it: ::gpiod::line_iter(chip))
-		REQUIRE(it.offset() == count++);
-
-	REQUIRE(count == chip.num_lines());
-}
diff --git a/bindings/cxx/tests/tests-line.cpp b/bindings/cxx/tests/tests-line.cpp
deleted file mode 100644
index ababf8b..0000000
--- a/bindings/cxx/tests/tests-line.cpp
+++ /dev/null
@@ -1,467 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-// SPDX-FileCopyrightText: 2017-2021 Bartosz Golaszewski <bartekgola@gmail.com>
-
-#include <catch2/catch.hpp>
-#include <gpiod.hpp>
-
-#include "gpio-mockup.hpp"
-
-using ::gpiod::test::mockup;
-
-namespace {
-
-const ::std::string consumer = "line-test";
-
-} /* namespace */
-
-TEST_CASE("Line information can be correctly retrieved", "[line]")
-{
-	mockup::probe_guard mockup_chips({ 8 }, mockup::FLAG_NAMED_LINES);
-	::gpiod::chip chip(mockup::instance().chip_path(0));
-	auto line = chip.get_line(4);
-
-	SECTION("unexported line")
-	{
-		REQUIRE(line.offset() == 4);
-		REQUIRE(line.name() == "gpio-mockup-A-4");
-		REQUIRE(line.direction() == ::gpiod::line::DIRECTION_INPUT);
-		REQUIRE_FALSE(line.is_active_low());
-		REQUIRE(line.consumer().empty());
-		REQUIRE_FALSE(line.is_used());
-		REQUIRE(line.drive() == ::gpiod::line::DRIVE_PUSH_PULL);
-		REQUIRE(line.bias() == ::gpiod::line::BIAS_UNKNOWN);
-	}
-
-	SECTION("exported line")
-	{
-		::gpiod::line_request config;
-
-		config.consumer = consumer.c_str();
-		config.request_type = ::gpiod::line_request::DIRECTION_OUTPUT;
-		line.request(config);
-
-		REQUIRE(line.offset() == 4);
-		REQUIRE(line.name() == "gpio-mockup-A-4");
-		REQUIRE(line.direction() == ::gpiod::line::DIRECTION_OUTPUT);
-		REQUIRE_FALSE(line.is_active_low());
-		REQUIRE(line.is_used());
-		REQUIRE(line.drive() == ::gpiod::line::DRIVE_PUSH_PULL);
-		REQUIRE(line.bias() == ::gpiod::line::BIAS_UNKNOWN);
-	}
-
-	SECTION("exported line with flags")
-	{
-		::gpiod::line_request config;
-
-		config.consumer = consumer.c_str();
-		config.request_type = ::gpiod::line_request::DIRECTION_OUTPUT;
-		config.flags = ::gpiod::line_request::FLAG_ACTIVE_LOW |
-			       ::gpiod::line_request::FLAG_OPEN_DRAIN;
-		line.request(config);
-
-		REQUIRE(line.offset() == 4);
-		REQUIRE(line.name() == "gpio-mockup-A-4");
-		REQUIRE(line.direction() == ::gpiod::line::DIRECTION_OUTPUT);
-		REQUIRE(line.is_active_low());
-		REQUIRE(line.is_used());
-		REQUIRE(line.drive() == ::gpiod::line::DRIVE_OPEN_DRAIN);
-		REQUIRE(line.bias() == ::gpiod::line::BIAS_UNKNOWN);
-	}
-
-	SECTION("exported open source line")
-	{
-		::gpiod::line_request config;
-
-		config.consumer = consumer.c_str();
-		config.request_type = ::gpiod::line_request::DIRECTION_OUTPUT;
-		config.flags = ::gpiod::line_request::FLAG_OPEN_SOURCE;
-		line.request(config);
-
-		REQUIRE(line.offset() == 4);
-		REQUIRE(line.name() == "gpio-mockup-A-4");
-		REQUIRE(line.direction() == ::gpiod::line::DIRECTION_OUTPUT);
-		REQUIRE_FALSE(line.is_active_low());
-		REQUIRE(line.is_used());
-		REQUIRE(line.drive() == ::gpiod::line::DRIVE_OPEN_SOURCE);
-		REQUIRE(line.bias() == ::gpiod::line::BIAS_UNKNOWN);
-	}
-
-	SECTION("exported bias disable line")
-	{
-		::gpiod::line_request config;
-
-		config.consumer = consumer.c_str();
-		config.request_type = ::gpiod::line_request::DIRECTION_OUTPUT;
-		config.flags = ::gpiod::line_request::FLAG_BIAS_DISABLED;
-		line.request(config);
-
-		REQUIRE(line.offset() == 4);
-		REQUIRE(line.name() == "gpio-mockup-A-4");
-		REQUIRE(line.direction() == ::gpiod::line::DIRECTION_OUTPUT);
-		REQUIRE_FALSE(line.is_active_low());
-		REQUIRE(line.is_used());
-		REQUIRE(line.drive() == ::gpiod::line::DRIVE_PUSH_PULL);
-		REQUIRE(line.bias() == ::gpiod::line::BIAS_DISABLED);
-	}
-
-	SECTION("exported pull-down line")
-	{
-		::gpiod::line_request config;
-
-		config.consumer = consumer.c_str();
-		config.request_type = ::gpiod::line_request::DIRECTION_OUTPUT;
-		config.flags = ::gpiod::line_request::FLAG_BIAS_PULL_DOWN;
-		line.request(config);
-
-		REQUIRE(line.offset() == 4);
-		REQUIRE(line.name() == "gpio-mockup-A-4");
-		REQUIRE(line.direction() == ::gpiod::line::DIRECTION_OUTPUT);
-		REQUIRE_FALSE(line.is_active_low());;
-		REQUIRE(line.is_used());
-		REQUIRE(line.drive() == ::gpiod::line::DRIVE_PUSH_PULL);
-		REQUIRE(line.bias() == ::gpiod::line::BIAS_PULL_DOWN);
-	}
-
-	SECTION("exported pull-up line")
-	{
-		::gpiod::line_request config;
-
-		config.consumer = consumer.c_str();
-		config.request_type = ::gpiod::line_request::DIRECTION_OUTPUT;
-		config.flags = ::gpiod::line_request::FLAG_BIAS_PULL_UP;
-		line.request(config);
-
-		REQUIRE(line.offset() == 4);
-		REQUIRE(line.name() == "gpio-mockup-A-4");
-		REQUIRE(line.direction() == ::gpiod::line::DIRECTION_OUTPUT);
-		REQUIRE_FALSE(line.is_active_low());
-		REQUIRE(line.is_used());
-		REQUIRE(line.drive() == ::gpiod::line::DRIVE_PUSH_PULL);
-		REQUIRE(line.bias() == ::gpiod::line::BIAS_PULL_UP);
-	}
-}
-
-TEST_CASE("Line values can be set and read", "[line]")
-{
-	mockup::probe_guard mockup_chips({ 8 });
-	::gpiod::chip chip(mockup::instance().chip_path(0));
-	::gpiod::line_request config;
-
-	config.consumer = consumer.c_str();
-
-	SECTION("get value (single line)")
-	{
-		auto line = chip.get_line(3);
-		config.request_type = ::gpiod::line_request::DIRECTION_INPUT;
-		line.request(config);
-		REQUIRE(line.get_value() == 0);
-		mockup::instance().chip_set_pull(0, 3, 1);
-		REQUIRE(line.get_value() == 1);
-	}
-
-	SECTION("set value (single line)")
-	{
-		auto line = chip.get_line(3);
-		config.request_type = ::gpiod::line_request::DIRECTION_OUTPUT;
-		line.request(config);
-		line.set_value(1);
-		REQUIRE(mockup::instance().chip_get_value(0, 3) == 1);
-		line.set_value(0);
-		REQUIRE(mockup::instance().chip_get_value(0, 3) == 0);
-	}
-
-	SECTION("set value with default value parameter")
-	{
-		auto line = chip.get_line(3);
-		config.request_type = ::gpiod::line_request::DIRECTION_OUTPUT;
-		line.request(config, 1);
-		REQUIRE(mockup::instance().chip_get_value(0, 3) == 1);
-	}
-
-	SECTION("get multiple values at once")
-	{
-		auto lines = chip.get_lines({ 0, 1, 2, 3, 4 });
-		config.request_type = ::gpiod::line_request::DIRECTION_INPUT;
-		lines.request(config);
-		REQUIRE(lines.get_values() == ::std::vector<int>({ 0, 0, 0, 0, 0 }));
-		mockup::instance().chip_set_pull(0, 1, 1);
-		mockup::instance().chip_set_pull(0, 3, 1);
-		mockup::instance().chip_set_pull(0, 4, 1);
-		REQUIRE(lines.get_values() == ::std::vector<int>({ 0, 1, 0, 1, 1 }));
-	}
-
-	SECTION("set multiple values at once")
-	{
-		auto lines = chip.get_lines({ 0, 1, 2, 6, 7 });
-		config.request_type = ::gpiod::line_request::DIRECTION_OUTPUT;
-		lines.request(config);
-		lines.set_values({ 1, 1, 0, 1, 0 });
-		REQUIRE(mockup::instance().chip_get_value(0, 0) == 1);
-		REQUIRE(mockup::instance().chip_get_value(0, 1) == 1);
-		REQUIRE(mockup::instance().chip_get_value(0, 2) == 0);
-		REQUIRE(mockup::instance().chip_get_value(0, 6) == 1);
-		REQUIRE(mockup::instance().chip_get_value(0, 7) == 0);
-	}
-
-	SECTION("set multiple values with default values parameter")
-	{
-		auto lines = chip.get_lines({ 1, 2, 4, 6, 7 });
-		config.request_type = ::gpiod::line_request::DIRECTION_OUTPUT;
-		lines.request(config, { 1, 1, 0, 1, 0 });
-		REQUIRE(mockup::instance().chip_get_value(0, 1) == 1);
-		REQUIRE(mockup::instance().chip_get_value(0, 2) == 1);
-		REQUIRE(mockup::instance().chip_get_value(0, 4) == 0);
-		REQUIRE(mockup::instance().chip_get_value(0, 6) == 1);
-		REQUIRE(mockup::instance().chip_get_value(0, 7) == 0);
-	}
-
-	SECTION("get value (single line, active-low")
-	{
-		auto line = chip.get_line(4);
-		config.request_type = ::gpiod::line_request::DIRECTION_INPUT;
-		config.flags = ::gpiod::line_request::FLAG_ACTIVE_LOW;
-		line.request(config);
-		REQUIRE(line.get_value() == 1);
-		mockup::instance().chip_set_pull(0, 4, 1);
-		REQUIRE(line.get_value() == 0);
-	}
-
-	SECTION("set value (single line, active-low)")
-	{
-		auto line = chip.get_line(3);
-		config.request_type = ::gpiod::line_request::DIRECTION_OUTPUT;
-		config.flags = ::gpiod::line_request::FLAG_ACTIVE_LOW;
-		line.request(config);
-		line.set_value(1);
-		REQUIRE(mockup::instance().chip_get_value(0, 3) == 0);
-		line.set_value(0);
-		REQUIRE(mockup::instance().chip_get_value(0, 3) == 1);
-	}
-}
-
-TEST_CASE("Line can be reconfigured", "[line]")
-{
-	mockup::probe_guard mockup_chips({ 8 });
-	::gpiod::chip chip(mockup::instance().chip_path(0));
-	::gpiod::line_request config;
-
-	config.consumer = consumer.c_str();
-
-	SECTION("set config (single line, active-state)")
-	{
-		auto line = chip.get_line(3);
-		config.request_type = ::gpiod::line_request::DIRECTION_INPUT;
-		config.flags = 0;
-		line.request(config);
-		REQUIRE(line.direction() == ::gpiod::line::DIRECTION_INPUT);
-		REQUIRE_FALSE(line.is_active_low());
-
-		line.set_config(::gpiod::line_request::DIRECTION_OUTPUT,
-			::gpiod::line_request::FLAG_ACTIVE_LOW,1);
-		REQUIRE(line.direction() == ::gpiod::line::DIRECTION_OUTPUT);
-		REQUIRE(line.is_active_low());
-		REQUIRE(mockup::instance().chip_get_value(0, 3) == 0);
-		line.set_value(0);
-		REQUIRE(mockup::instance().chip_get_value(0, 3) == 1);
-
-		line.set_config(::gpiod::line_request::DIRECTION_OUTPUT, 0);
-		REQUIRE(line.direction() == ::gpiod::line::DIRECTION_OUTPUT);
-		REQUIRE_FALSE(line.is_active_low());
-		REQUIRE(mockup::instance().chip_get_value(0, 3) == 0);
-		line.set_value(1);
-		REQUIRE(mockup::instance().chip_get_value(0, 3) == 1);
-	}
-
-	SECTION("set flags (single line, active-state)")
-	{
-		auto line = chip.get_line(3);
-		config.request_type = ::gpiod::line_request::DIRECTION_OUTPUT;
-		config.flags = 0;
-		line.request(config,1);
-		REQUIRE(mockup::instance().chip_get_value(0, 3) == 1);
-
-		line.set_flags(::gpiod::line_request::FLAG_ACTIVE_LOW);
-		REQUIRE(line.direction() == ::gpiod::line::DIRECTION_OUTPUT);
-		REQUIRE(line.is_active_low());
-		REQUIRE(mockup::instance().chip_get_value(0, 3) == 0);
-
-		line.set_flags(0);
-		REQUIRE(line.direction() == ::gpiod::line::DIRECTION_OUTPUT);
-		REQUIRE_FALSE(line.is_active_low());
-		REQUIRE(mockup::instance().chip_get_value(0, 3) == 1);
-	}
-
-	SECTION("set flags (single line, drive)")
-	{
-		auto line = chip.get_line(3);
-		config.request_type = ::gpiod::line_request::DIRECTION_OUTPUT;
-		config.flags = 0;
-		line.request(config);
-		REQUIRE(line.direction() == ::gpiod::line::DIRECTION_OUTPUT);
-		REQUIRE(line.drive() == ::gpiod::line::DRIVE_PUSH_PULL);
-
-		line.set_flags(::gpiod::line_request::FLAG_OPEN_DRAIN);
-		REQUIRE(line.direction() == ::gpiod::line::DIRECTION_OUTPUT);
-		REQUIRE(line.drive() == ::gpiod::line::DRIVE_OPEN_DRAIN);
-
-		line.set_flags(::gpiod::line_request::FLAG_OPEN_SOURCE);
-		REQUIRE(line.direction() == ::gpiod::line::DIRECTION_OUTPUT);
-		REQUIRE(line.drive() == ::gpiod::line::DRIVE_OPEN_SOURCE);
-
-		line.set_flags(0);
-		REQUIRE(line.direction() == ::gpiod::line::DIRECTION_OUTPUT);
-		REQUIRE(line.drive() == ::gpiod::line::DRIVE_PUSH_PULL);
-	}
-
-	SECTION("set flags (single line, bias)")
-	{
-		auto line = chip.get_line(3);
-		config.request_type = ::gpiod::line_request::DIRECTION_OUTPUT;
-		config.flags = 0;
-		line.request(config);
-		REQUIRE(line.direction() == ::gpiod::line::DIRECTION_OUTPUT);
-		REQUIRE(line.drive() == ::gpiod::line::DRIVE_PUSH_PULL);
-
-		line.set_flags(::gpiod::line_request::FLAG_OPEN_DRAIN);
-		REQUIRE(line.direction() == ::gpiod::line::DIRECTION_OUTPUT);
-		REQUIRE(line.drive() == ::gpiod::line::DRIVE_OPEN_DRAIN);
-
-		line.set_flags(::gpiod::line_request::FLAG_OPEN_SOURCE);
-		REQUIRE(line.direction() == ::gpiod::line::DIRECTION_OUTPUT);
-		REQUIRE(line.drive() == ::gpiod::line::DRIVE_OPEN_SOURCE);
-
-		line.set_flags(0);
-		REQUIRE(line.direction() == ::gpiod::line::DIRECTION_OUTPUT);
-		REQUIRE(line.drive() == ::gpiod::line::DRIVE_PUSH_PULL);
-	}
-
-	SECTION("set direction input (single line)")
-	{
-		auto line = chip.get_line(3);
-		config.request_type = ::gpiod::line_request::DIRECTION_OUTPUT;
-		config.flags = 0;
-		line.request(config);
-		REQUIRE(line.direction() == ::gpiod::line::DIRECTION_OUTPUT);
-		line.set_direction_input();
-		REQUIRE(line.direction() == ::gpiod::line::DIRECTION_INPUT);
-	}
-
-	SECTION("set direction output (single line)")
-	{
-		auto line = chip.get_line(3);
-		config.request_type = ::gpiod::line_request::DIRECTION_INPUT;
-		config.flags = 0;
-		line.request(config);
-		REQUIRE(line.direction() == ::gpiod::line::DIRECTION_INPUT);
-		line.set_direction_output(1);
-		REQUIRE(line.direction() == ::gpiod::line::DIRECTION_OUTPUT);
-		REQUIRE(mockup::instance().chip_get_value(0, 3) == 1);
-	}
-}
-
-TEST_CASE("Exported line can be released", "[line]")
-{
-	mockup::probe_guard mockup_chips({ 8 });
-	::gpiod::chip chip(mockup::instance().chip_path(0));
-	auto line = chip.get_line(4);
-	::gpiod::line_request config;
-
-	config.consumer = consumer.c_str();
-	config.request_type = ::gpiod::line_request::DIRECTION_INPUT;
-
-	line.request(config);
-
-	REQUIRE(line.get_value() == 0);
-
-	line.release();
-
-	REQUIRE_THROWS_AS(line.get_value(), ::std::system_error);
-}
-
-TEST_CASE("Uninitialized GPIO line behaves correctly", "[line]")
-{
-	::gpiod::line line;
-
-	SECTION("uninitialized line is 'false'")
-	{
-		REQUIRE_FALSE(line);
-	}
-
-	SECTION("using uninitialized line throws logic_error")
-	{
-		REQUIRE_THROWS_AS(line.name(), ::std::logic_error);
-	}
-}
-
-TEST_CASE("Uninitialized GPIO line_bulk behaves correctly", "[line][bulk]")
-{
-	::gpiod::line_bulk bulk;
-
-	SECTION("uninitialized line_bulk is 'false'")
-	{
-		REQUIRE_FALSE(bulk);
-	}
-
-	SECTION("using uninitialized line_bulk throws logic_error")
-	{
-		REQUIRE_THROWS_AS(bulk.get(0), ::std::logic_error);
-	}
-}
-
-TEST_CASE("Cannot request the same line twice", "[line]")
-{
-	mockup::probe_guard mockup_chips({ 8 });
-	::gpiod::chip chip(mockup::instance().chip_path(0));
-	::gpiod::line_request config;
-
-	config.consumer = consumer.c_str();
-	config.request_type = ::gpiod::line_request::DIRECTION_INPUT;
-
-	SECTION("two separate calls to request()")
-	{
-		auto line = chip.get_line(3);
-
-		REQUIRE_NOTHROW(line.request(config));
-		REQUIRE_THROWS_AS(line.request(config), ::std::system_error);
-	}
-
-	SECTION("request the same line twice in line_bulk")
-	{
-		/*
-		 * While a line_bulk object can hold two or more line objects
-		 * representing the same line - requesting it will fail.
-		 */
-		auto lines = chip.get_lines({ 2, 3, 4, 4 });
-
-		REQUIRE_THROWS_AS(lines.request(config), ::std::system_error);
-	}
-}
-
-TEST_CASE("Cannot get/set values of unrequested lines", "[line]")
-{
-	mockup::probe_guard mockup_chips({ 8 });
-	::gpiod::chip chip(mockup::instance().chip_path(0));
-	auto line = chip.get_line(3);
-
-	SECTION("get value")
-	{
-		REQUIRE_THROWS_AS(line.get_value(), ::std::system_error);
-	}
-
-	SECTION("set value")
-	{
-		REQUIRE_THROWS_AS(line.set_value(1), ::std::system_error);
-	}
-}
-
-TEST_CASE("Line objects can be compared")
-{
-	mockup::probe_guard mockup_chips({ 8 });
-	::gpiod::chip chip(mockup::instance().chip_path(0));
-	auto line1 = chip.get_line(3);
-	auto line2 = chip.get_line(3);
-	auto line3 = chip.get_line(4);
-
-	REQUIRE(line1 == line2);
-	REQUIRE(line2 != line3);
-}
