diff --git a/src/bluez/horipad_steam/input_reader.cc b/src/bluez/horipad_steam/input_reader.cc index d8d42cc..8e00430 100644 --- a/src/bluez/horipad_steam/input_reader.cc +++ b/src/bluez/horipad_steam/input_reader.cc @@ -42,9 +42,8 @@ void InputReader::open_and_init() { // Raw Info hidraw_devinfo raw_dev_info{}; - if (const auto res = ioctl(fd.get(), HIDIOCGRAWINFO, &raw_dev_info); - res < 0) { - LOG_ERROR("HIDIOCGRAWINFO"); + if (auto r = sys::ioctl(fd.get(), HIDIOCGRAWINFO, &raw_dev_info); !r) { + LOG_ERROR("HIDIOCGRAWINFO failed: {}", r.error().message()); return; } product_ = raw_dev_info.product; @@ -54,18 +53,18 @@ void InputReader::open_and_init() { // Raw Name std::array buf{}; - auto res = ioctl(fd.get(), HIDIOCGRAWNAME(buf.size()), buf.data()); - if (res < 0) { - LOG_ERROR("HIDIOCGRAWNAME"); + if (auto r = sys::ioctl(fd.get(), HIDIOCGRAWNAME(buf.size()), buf.data()); + !r) { + LOG_ERROR("HIDIOCGRAWNAME failed: {}", r.error().message()); return; } buf.back() = '\0'; // guarantee null-termination LOG_INFO("HID Name: {}", buf.data()); // Raw Physical Location - res = ioctl(fd.get(), HIDIOCGRAWPHYS(buf.size()), buf.data()); - if (res < 0) { - LOG_ERROR("HIDIOCGRAWPHYS"); + if (auto r = sys::ioctl(fd.get(), HIDIOCGRAWPHYS(buf.size()), buf.data()); + !r) { + LOG_ERROR("HIDIOCGRAWPHYS failed: {}", r.error().message()); return; } buf.back() = '\0'; // guarantee null-termination @@ -73,9 +72,8 @@ void InputReader::open_and_init() { // Report Descriptor Size int desc_size = 0; - res = ioctl(fd.get(), HIDIOCGRDESCSIZE, &desc_size); - if (res < 0) { - LOG_ERROR("HIDIOCGRDESCSIZE"); + if (auto r = sys::ioctl(fd.get(), HIDIOCGRDESCSIZE, &desc_size); !r) { + LOG_ERROR("HIDIOCGRDESCSIZE failed: {}", r.error().message()); return; } LOG_INFO("Report Descriptor Size: {}", desc_size); @@ -89,9 +87,8 @@ void InputReader::open_and_init() { // Report Descriptor hidraw_report_descriptor rpt_desc{}; rpt_desc.size = desc_size; - res = ioctl(fd.get(), HIDIOCGRDESC, &rpt_desc); - if (res < 0) { - LOG_ERROR("HIDIOCGRDESC"); + if (auto r = sys::ioctl(fd.get(), HIDIOCGRDESC, &rpt_desc); !r) { + LOG_ERROR("HIDIOCGRDESC failed: {}", r.error().message()); return; } diff --git a/src/bluez/ps5_dual_sense/input_reader.cc b/src/bluez/ps5_dual_sense/input_reader.cc index 3ebf0fb..a797848 100644 --- a/src/bluez/ps5_dual_sense/input_reader.cc +++ b/src/bluez/ps5_dual_sense/input_reader.cc @@ -43,9 +43,8 @@ void InputReader::open_and_init() { // Raw Info hidraw_devinfo raw_dev_info{}; - if (const auto res = ioctl(fd.get(), HIDIOCGRAWINFO, &raw_dev_info); - res < 0) { - LOG_ERROR("HIDIOCGRAWINFO"); + if (auto r = sys::ioctl(fd.get(), HIDIOCGRAWINFO, &raw_dev_info); !r) { + LOG_ERROR("HIDIOCGRAWINFO failed: {}", r.error().message()); return; } product_ = raw_dev_info.product; @@ -55,18 +54,18 @@ void InputReader::open_and_init() { // Raw Name std::array buf{}; - auto res = ioctl(fd.get(), HIDIOCGRAWNAME(buf.size()), buf.data()); - if (res < 0) { - LOG_ERROR("HIDIOCGRAWNAME"); + if (auto r = sys::ioctl(fd.get(), HIDIOCGRAWNAME(buf.size()), buf.data()); + !r) { + LOG_ERROR("HIDIOCGRAWNAME failed: {}", r.error().message()); return; } buf.back() = '\0'; // guarantee null-termination LOG_INFO("HID Name: {}", buf.data()); // Raw Physical Location - res = ioctl(fd.get(), HIDIOCGRAWPHYS(buf.size()), buf.data()); - if (res < 0) { - LOG_ERROR("HIDIOCGRAWPHYS"); + if (auto r = sys::ioctl(fd.get(), HIDIOCGRAWPHYS(buf.size()), buf.data()); + !r) { + LOG_ERROR("HIDIOCGRAWPHYS failed: {}", r.error().message()); return; } buf.back() = '\0'; // guarantee null-termination @@ -74,9 +73,8 @@ void InputReader::open_and_init() { // Report Descriptor Size int desc_size = 0; - res = ioctl(fd.get(), HIDIOCGRDESCSIZE, &desc_size); - if (res < 0) { - LOG_ERROR("HIDIOCGRDESCSIZE"); + if (auto r = sys::ioctl(fd.get(), HIDIOCGRDESCSIZE, &desc_size); !r) { + LOG_ERROR("HIDIOCGRDESCSIZE failed: {}", r.error().message()); return; } LOG_INFO("Report Descriptor Size: {}", desc_size); @@ -90,9 +88,8 @@ void InputReader::open_and_init() { // Report Descriptor hidraw_report_descriptor rpt_desc{}; rpt_desc.size = desc_size; - res = ioctl(fd.get(), HIDIOCGRDESC, &rpt_desc); - if (res < 0) { - LOG_ERROR("HIDIOCGRDESC"); + if (auto r = sys::ioctl(fd.get(), HIDIOCGRDESC, &rpt_desc); !r) { + LOG_ERROR("HIDIOCGRDESC failed: {}", r.error().message()); return; } @@ -160,10 +157,10 @@ void InputReader::dispatch(const short revents) { int InputReader::GetControllerMacAll(const int fd, ReportFeatureInMacAll& mac_all) { mac_all.ReportID = 0x09; - if (const auto res = - ioctl(fd, HIDIOCGFEATURE(sizeof(ReportFeatureInMacAll)), &mac_all); - res < 0) { - LOG_ERROR("GetControllerMacAll failed: {}", strerror(errno)); + if (auto r = sys::ioctl(fd, HIDIOCGFEATURE(sizeof(ReportFeatureInMacAll)), + &mac_all); + !r) { + LOG_ERROR("GetControllerMacAll failed: {}", r.error().message()); return 1; } if (mac_all.ReportID != 0x09 || mac_all.Hard08 != 0x08 || @@ -177,10 +174,10 @@ int InputReader::GetControllerMacAll(const int fd, int InputReader::GetControllerVersion(const int fd, ReportFeatureInVersion& version) { version.Data.ReportID = 0x20; - if (const auto res = - ioctl(fd, HIDIOCGFEATURE(sizeof(ReportFeatureInVersion)), &version); - res < 0) { - LOG_ERROR("GetControllerVersion failed: {}", strerror(errno)); + if (auto r = sys::ioctl(fd, HIDIOCGFEATURE(sizeof(ReportFeatureInVersion)), + &version); + !r) { + LOG_ERROR("GetControllerVersion failed: {}", r.error().message()); return 1; } if (version.Data.ReportID != 0x20) { @@ -200,10 +197,10 @@ int InputReader::GetControllerCalibrationData( ReportFeatureCalibrationData cal_data{}; cal_data.Data.ReportID = 0x05; - if (const auto res = ioctl( + if (auto r = sys::ioctl( fd, HIDIOCGFEATURE(sizeof(ReportFeatureCalibrationData)), &cal_data); - res < 0) { - LOG_ERROR("GetControllerCalibrationData failed: {}", strerror(errno)); + !r) { + LOG_ERROR("GetControllerCalibrationData failed: {}", r.error().message()); return 1; } if (cal_data.Data.ReportID != 0x05) { diff --git a/src/bluez/xbox_controller/input_reader.cc b/src/bluez/xbox_controller/input_reader.cc index 57b4976..204492c 100644 --- a/src/bluez/xbox_controller/input_reader.cc +++ b/src/bluez/xbox_controller/input_reader.cc @@ -42,9 +42,8 @@ void InputReader::open_and_init() { // Raw Info hidraw_devinfo raw_dev_info{}; - if (const auto res = ioctl(fd.get(), HIDIOCGRAWINFO, &raw_dev_info); - res < 0) { - LOG_ERROR("HIDIOCGRAWINFO"); + if (auto r = sys::ioctl(fd.get(), HIDIOCGRAWINFO, &raw_dev_info); !r) { + LOG_ERROR("HIDIOCGRAWINFO failed: {}", r.error().message()); return; } product_ = raw_dev_info.product; @@ -54,18 +53,18 @@ void InputReader::open_and_init() { // Raw Name std::array buf{}; - auto res = ioctl(fd.get(), HIDIOCGRAWNAME(buf.size()), buf.data()); - if (res < 0) { - LOG_ERROR("HIDIOCGRAWNAME"); + if (auto r = sys::ioctl(fd.get(), HIDIOCGRAWNAME(buf.size()), buf.data()); + !r) { + LOG_ERROR("HIDIOCGRAWNAME failed: {}", r.error().message()); return; } buf.back() = '\0'; // guarantee null-termination LOG_INFO("HID Name: {}", buf.data()); // Raw Physical Location - res = ioctl(fd.get(), HIDIOCGRAWPHYS(buf.size()), buf.data()); - if (res < 0) { - LOG_ERROR("HIDIOCGRAWPHYS"); + if (auto r = sys::ioctl(fd.get(), HIDIOCGRAWPHYS(buf.size()), buf.data()); + !r) { + LOG_ERROR("HIDIOCGRAWPHYS failed: {}", r.error().message()); return; } buf.back() = '\0'; // guarantee null-termination @@ -73,9 +72,8 @@ void InputReader::open_and_init() { // Report Descriptor Size int desc_size = 0; - res = ioctl(fd.get(), HIDIOCGRDESCSIZE, &desc_size); - if (res < 0) { - LOG_ERROR("HIDIOCGRDESCSIZE"); + if (auto r = sys::ioctl(fd.get(), HIDIOCGRDESCSIZE, &desc_size); !r) { + LOG_ERROR("HIDIOCGRDESCSIZE failed: {}", r.error().message()); return; } LOG_INFO("Report Descriptor Size: {}", desc_size); @@ -89,9 +87,8 @@ void InputReader::open_and_init() { // Report Descriptor hidraw_report_descriptor rpt_desc{}; rpt_desc.size = desc_size; - res = ioctl(fd.get(), HIDIOCGRDESC, &rpt_desc); - if (res < 0) { - LOG_ERROR("HIDIOCGRDESC"); + if (auto r = sys::ioctl(fd.get(), HIDIOCGRDESC, &rpt_desc); !r) { + LOG_ERROR("HIDIOCGRDESC failed: {}", r.error().message()); return; } diff --git a/src/utils/sys.h b/src/utils/sys.h index 0be4ddf..2afd7c0 100644 --- a/src/utils/sys.h +++ b/src/utils/sys.h @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -92,6 +93,19 @@ make_signalfd(const int fd, const sigset_t& mask, const int flags) noexcept { return fd; } +/// ioctl() with a single argument, returning the (non-negative) result or the +/// errno as a std::error_code. `arg` is typically a pointer to the ioctl's +/// in/out struct. +template +[[nodiscard]] inline std::expected +ioctl(const int fd, const unsigned long request, Arg arg) noexcept { + const int rc = ::ioctl(fd, request, arg); + if (rc < 0) { + return std::unexpected(last_error()); + } + return rc; +} + } // namespace sys #endif // SRC_UTILS_SYS_H diff --git a/src/utils/sys_test.cc b/src/utils/sys_test.cc index 0092d56..27d27d6 100644 --- a/src/utils/sys_test.cc +++ b/src/utils/sys_test.cc @@ -19,6 +19,7 @@ #include #include +#include #include #include "logging.h" @@ -57,6 +58,16 @@ int main() { check(sys::make_timerfd(CLOCK_MONOTONIC, TFD_CLOEXEC).has_value(), "make_timerfd yields a valid fd"); + // ioctl failure: a terminal ioctl on a non-tty fd reports ENOTTY. + if (auto efd = sys::make_eventfd(0, EFD_CLOEXEC)) { + winsize ws{}; + auto r = sys::ioctl(efd->get(), TIOCGWINSZ, &ws); + check(!r && r.error() == std::errc::inappropriate_io_control_operation, + "ioctl on non-tty reports ENOTTY"); + } else { + check(false, "make_eventfd for the ioctl test failed"); + } + if (failures == 0) { LOG_INFO("sys test: PASS"); return 0;