Since v5.19 the linux GPIO uAPI exposes a new request flag for making the hardware timestamp engine be the source of edge event timestamps. Add support for it to libgpiod. Signed-off-by: Bartosz Golaszewski <brgl@xxxxxxxx> --- bindings/cxx/gpiodcxx/line-info.hpp | 2 +- bindings/cxx/gpiodcxx/line.hpp | 4 +++- bindings/cxx/line-info.cpp | 3 ++- bindings/cxx/line-settings.cpp | 3 ++- bindings/cxx/line.cpp | 3 ++- bindings/cxx/tests/check-kernel.cpp | 2 +- bindings/cxx/tests/tests-line-settings.cpp | 2 ++ bindings/cxx/tests/tests-line.cpp | 2 ++ include/gpiod.h | 2 ++ lib/line-config.c | 3 +++ lib/line-info.c | 2 ++ lib/line-settings.c | 1 + lib/uapi/gpio.h | 3 +++ tests/gpiod-test.c | 4 ++-- tests/tests-line-info.c | 10 ++++++++++ tests/tests-line-settings.c | 6 ++++++ 16 files changed, 44 insertions(+), 8 deletions(-) diff --git a/bindings/cxx/gpiodcxx/line-info.hpp b/bindings/cxx/gpiodcxx/line-info.hpp index cbc8156..189d305 100644 --- a/bindings/cxx/gpiodcxx/line-info.hpp +++ b/bindings/cxx/gpiodcxx/line-info.hpp @@ -143,7 +143,7 @@ public: /** * @brief Read the current event clock setting used for edge event * timestamps. - * @return Returns MONOTONIC or REALTIME. + * @return Returns MONOTONIC, REALTIME or HTE. */ line::clock event_clock() const; diff --git a/bindings/cxx/gpiodcxx/line.hpp b/bindings/cxx/gpiodcxx/line.hpp index 32c4136..a8aae57 100644 --- a/bindings/cxx/gpiodcxx/line.hpp +++ b/bindings/cxx/gpiodcxx/line.hpp @@ -156,8 +156,10 @@ enum class clock { MONOTONIC = 1, /**< Line uses the monotonic clock for edge event timestamps. */ - REALTIME + REALTIME, /**< Line uses the realtime clock for edge event timestamps. */ + HTE, + /*<< Line uses the hardware timestamp engine for event timestamps. */ }; /** diff --git a/bindings/cxx/line-info.cpp b/bindings/cxx/line-info.cpp index 2ad0baf..a6b6dfa 100644 --- a/bindings/cxx/line-info.cpp +++ b/bindings/cxx/line-info.cpp @@ -38,7 +38,8 @@ const ::std::map<int, line::edge> edge_mapping = { const ::std::map<int, line::clock> clock_mapping = { { GPIOD_LINE_EVENT_CLOCK_MONOTONIC, line::clock::MONOTONIC }, - { GPIOD_LINE_EVENT_CLOCK_REALTIME, line::clock::REALTIME } + { GPIOD_LINE_EVENT_CLOCK_REALTIME, line::clock::REALTIME }, + { GPIOD_LINE_EVENT_CLOCK_HTE, line::clock::HTE } }; } /* namespace */ diff --git a/bindings/cxx/line-settings.cpp b/bindings/cxx/line-settings.cpp index dbbe30e..22655e2 100644 --- a/bindings/cxx/line-settings.cpp +++ b/bindings/cxx/line-settings.cpp @@ -57,7 +57,8 @@ const ::std::map<int, line::drive> reverse_drive_mapping = make_reverse_maping(d const ::std::map<line::clock, int> clock_mapping = { { line::clock::MONOTONIC, GPIOD_LINE_EVENT_CLOCK_MONOTONIC }, - { line::clock::REALTIME, GPIOD_LINE_EVENT_CLOCK_REALTIME } + { line::clock::REALTIME, GPIOD_LINE_EVENT_CLOCK_REALTIME }, + { line::clock::HTE, GPIOD_LINE_EVENT_CLOCK_HTE } }; const ::std::map<int, line::clock> reverse_clock_mapping = make_reverse_maping(clock_mapping); diff --git a/bindings/cxx/line.cpp b/bindings/cxx/line.cpp index a9caedd..c2750a8 100644 --- a/bindings/cxx/line.cpp +++ b/bindings/cxx/line.cpp @@ -45,7 +45,8 @@ const ::std::map<line::edge, ::std::string> edge_names = { const ::std::map<line::clock, ::std::string> clock_names = { { line::clock::MONOTONIC, "MONOTONIC" }, - { line::clock::REALTIME, "REALTIME" } + { line::clock::REALTIME, "REALTIME" }, + { line::clock::HTE, "HTE" } }; } /* namespace */ diff --git a/bindings/cxx/tests/check-kernel.cpp b/bindings/cxx/tests/check-kernel.cpp index 5d128a0..e10fb5d 100644 --- a/bindings/cxx/tests/check-kernel.cpp +++ b/bindings/cxx/tests/check-kernel.cpp @@ -43,6 +43,6 @@ public: } }; -kernel_checker require_kernel(5, 17, 4); +kernel_checker require_kernel(5, 19, 0); } /* namespace */ diff --git a/bindings/cxx/tests/tests-line-settings.cpp b/bindings/cxx/tests/tests-line-settings.cpp index a7801a4..a3f4bc5 100644 --- a/bindings/cxx/tests/tests-line-settings.cpp +++ b/bindings/cxx/tests/tests-line-settings.cpp @@ -107,6 +107,8 @@ TEST_CASE("line_settings mutators work", "[line-settings]") REQUIRE(settings.event_clock() == clock_type::REALTIME); settings.set_event_clock(clock_type::MONOTONIC); REQUIRE(settings.event_clock() == clock_type::MONOTONIC); + settings.set_event_clock(clock_type::HTE); + REQUIRE(settings.event_clock() == clock_type::HTE); REQUIRE_THROWS_AS(settings.set_event_clock(static_cast<clock_type>(999)), ::std::invalid_argument); } diff --git a/bindings/cxx/tests/tests-line.cpp b/bindings/cxx/tests/tests-line.cpp index c17122c..319012a 100644 --- a/bindings/cxx/tests/tests-line.cpp +++ b/bindings/cxx/tests/tests-line.cpp @@ -92,9 +92,11 @@ TEST_CASE("stream insertion operators for types in gpiod::line work", "[line]") { auto monotonic = clock_type::MONOTONIC; auto realtime = clock_type::REALTIME; + auto hte = clock_type::HTE; REQUIRE_THAT(monotonic, stringify_matcher<clock_type>("MONOTONIC")); REQUIRE_THAT(realtime, stringify_matcher<clock_type>("REALTIME")); + REQUIRE_THAT(hte, stringify_matcher<clock_type>("HTE")); } SECTION("offsets") diff --git a/include/gpiod.h b/include/gpiod.h index b60a177..a8e002b 100644 --- a/include/gpiod.h +++ b/include/gpiod.h @@ -306,6 +306,8 @@ enum { /**< Line uses the monotonic clock for edge event timestamps. */ GPIOD_LINE_EVENT_CLOCK_REALTIME, /**< Line uses the realtime clock for edge event timestamps. */ + GPIOD_LINE_EVENT_CLOCK_HTE, + /**< Line uses the hardware timestamp engine for event timestamps. */ }; /** diff --git a/lib/line-config.c b/lib/line-config.c index 114d40c..5ee7390 100644 --- a/lib/line-config.c +++ b/lib/line-config.c @@ -341,6 +341,9 @@ static uint64_t make_kernel_flags(struct gpiod_line_settings *settings) case GPIOD_LINE_EVENT_CLOCK_REALTIME: flags |= GPIO_V2_LINE_FLAG_EVENT_CLOCK_REALTIME; break; + case GPIOD_LINE_EVENT_CLOCK_HTE: + flags |= GPIO_V2_LINE_FLAG_EVENT_CLOCK_HTE; + break; } return flags; diff --git a/lib/line-info.c b/lib/line-info.c index 65eca48..9809c43 100644 --- a/lib/line-info.c +++ b/lib/line-info.c @@ -160,6 +160,8 @@ gpiod_line_info_from_uapi(struct gpio_v2_line_info *uapi_info) if (uapi_info->flags & GPIO_V2_LINE_FLAG_EVENT_CLOCK_REALTIME) info->event_clock = GPIOD_LINE_EVENT_CLOCK_REALTIME; + else if (uapi_info->flags & GPIO_V2_LINE_FLAG_EVENT_CLOCK_HTE) + info->event_clock = GPIOD_LINE_EVENT_CLOCK_HTE; else info->event_clock = GPIOD_LINE_EVENT_CLOCK_MONOTONIC; diff --git a/lib/line-settings.c b/lib/line-settings.c index 7125124..f97a90e 100644 --- a/lib/line-settings.c +++ b/lib/line-settings.c @@ -195,6 +195,7 @@ gpiod_line_settings_set_event_clock(struct gpiod_line_settings *settings, switch (event_clock) { case GPIOD_LINE_EVENT_CLOCK_MONOTONIC: case GPIOD_LINE_EVENT_CLOCK_REALTIME: + case GPIOD_LINE_EVENT_CLOCK_HTE: settings->event_clock = event_clock; break; default: diff --git a/lib/uapi/gpio.h b/lib/uapi/gpio.h index eaaea3d..cb9966d 100644 --- a/lib/uapi/gpio.h +++ b/lib/uapi/gpio.h @@ -66,6 +66,8 @@ struct gpiochip_info { * @GPIO_V2_LINE_FLAG_BIAS_PULL_DOWN: line has pull-down bias enabled * @GPIO_V2_LINE_FLAG_BIAS_DISABLED: line has bias disabled * @GPIO_V2_LINE_FLAG_EVENT_CLOCK_REALTIME: line events contain REALTIME timestamps + * @GPIO_V2_LINE_FLAG_EVENT_CLOCK_HTE: line events contain timestamps from + * hardware timestamp engine */ enum gpio_v2_line_flag { GPIO_V2_LINE_FLAG_USED = _BITULL(0), @@ -80,6 +82,7 @@ enum gpio_v2_line_flag { GPIO_V2_LINE_FLAG_BIAS_PULL_DOWN = _BITULL(9), GPIO_V2_LINE_FLAG_BIAS_DISABLED = _BITULL(10), GPIO_V2_LINE_FLAG_EVENT_CLOCK_REALTIME = _BITULL(11), + GPIO_V2_LINE_FLAG_EVENT_CLOCK_HTE = _BITULL(12), }; /** diff --git a/tests/gpiod-test.c b/tests/gpiod-test.c index 38d80a4..39a1f40 100644 --- a/tests/gpiod-test.c +++ b/tests/gpiod-test.c @@ -10,8 +10,8 @@ #include "gpiod-test.h" #define MIN_KERNEL_MAJOR 5 -#define MIN_KERNEL_MINOR 17 -#define MIN_KERNEL_RELEASE 4 +#define MIN_KERNEL_MINOR 19 +#define MIN_KERNEL_RELEASE 0 #define MIN_KERNEL_VERSION KERNEL_VERSION(MIN_KERNEL_MAJOR, \ MIN_KERNEL_MINOR, \ MIN_KERNEL_RELEASE) diff --git a/tests/tests-line-info.c b/tests/tests-line-info.c index ffc4586..45b14ff 100644 --- a/tests/tests-line-info.c +++ b/tests/tests-line-info.c @@ -362,6 +362,7 @@ GPIOD_TEST_CASE(event_clock) g_autoptr(struct_gpiod_line_request) request = NULL; g_autoptr(struct_gpiod_line_info) info0 = NULL; g_autoptr(struct_gpiod_line_info) info1 = NULL; + g_autoptr(struct_gpiod_line_info) info2 = NULL; guint offset; chip = gpiod_test_open_chip_or_fail(g_gpiosim_chip_get_dev_path(sim)); @@ -377,13 +378,22 @@ GPIOD_TEST_CASE(event_clock) gpiod_test_line_config_add_line_settings_or_fail(line_cfg, &offset, 1, settings); + gpiod_line_settings_set_event_clock(settings, + GPIOD_LINE_EVENT_CLOCK_HTE); + offset = 2; + gpiod_test_line_config_add_line_settings_or_fail(line_cfg, &offset, 1, + settings); + request = gpiod_test_request_lines_or_fail(chip, NULL, line_cfg); info0 = gpiod_test_get_line_info_or_fail(chip, 0); info1 = gpiod_test_get_line_info_or_fail(chip, 1); + info2 = gpiod_test_get_line_info_or_fail(chip, 2); g_assert_cmpint(gpiod_line_info_get_event_clock(info0), ==, GPIOD_LINE_EVENT_CLOCK_MONOTONIC); g_assert_cmpint(gpiod_line_info_get_event_clock(info1), ==, GPIOD_LINE_EVENT_CLOCK_REALTIME); + g_assert_cmpint(gpiod_line_info_get_event_clock(info2), ==, + GPIOD_LINE_EVENT_CLOCK_HTE); } diff --git a/tests/tests-line-settings.c b/tests/tests-line-settings.c index d074063..bdf932d 100644 --- a/tests/tests-line-settings.c +++ b/tests/tests-line-settings.c @@ -222,6 +222,12 @@ GPIOD_TEST_CASE(set_event_clock) g_assert_cmpint(gpiod_line_settings_get_event_clock(settings), ==, GPIOD_LINE_EVENT_CLOCK_REALTIME); + ret = gpiod_line_settings_set_event_clock(settings, + GPIOD_LINE_EVENT_CLOCK_HTE); + g_assert_cmpint(ret, ==, 0); + g_assert_cmpint(gpiod_line_settings_get_event_clock(settings), ==, + GPIOD_LINE_EVENT_CLOCK_HTE); + ret = gpiod_line_settings_set_event_clock(settings, 999); g_assert_cmpint(ret, <, 0); g_assert_cmpint(errno, ==, EINVAL); -- 2.34.1