diff --git a/windows/devices/uwb/UwbConnector.cxx b/windows/devices/uwb/UwbConnector.cxx index 9cb88c06..5660bb6f 100644 --- a/windows/devices/uwb/UwbConnector.cxx +++ b/windows/devices/uwb/UwbConnector.cxx @@ -136,41 +136,60 @@ UwbConnector::DeviceName() const noexcept return m_deviceName; } -std::future -UwbConnector::Reset() +template +void +UwbConnector::DeviceIoControlWrapper(std::promise& resultPromise, std::string strFail, std::string strSuccess, std::function interpret, ArgTs&&... args) { - std::promise resultPromise{}; - auto resultFuture = resultPromise.get_future(); - wil::unique_hfile handleDriver; auto hr = OpenDriverHandle(handleDriver, m_deviceName.c_str()); if (FAILED(hr)) { PLOG_ERROR << "failed to obtain driver handle for " << m_deviceName << ", hr=" << std::showbase << std::hex << hr; resultPromise.set_exception(std::make_exception_ptr(UwbException(UwbStatusGeneric::Rejected))); - return resultFuture; + return; } + BOOL ioResult = DeviceIoControl(handleDriver.get(), std::forward(args)...); + if (!LOG_IF_WIN32_BOOL_FALSE(ioResult)) { + HRESULT hr = HRESULT_FROM_WIN32(GetLastError()); + PLOG_ERROR << strFail << ", hr = " << std::showbase << std::hex << hr; + resultPromise.set_exception(std::make_exception_ptr(UwbException(UwbStatusGeneric::Rejected))); + } else { + PLOG_DEBUG << strSuccess; + interpret(); + } +} + +std::future +UwbConnector::Reset() +{ + std::promise resultPromise{}; + auto resultFuture = resultPromise.get_future(); + const UWB_DEVICE_RESET deviceReset{ .size = sizeof(UWB_DEVICE_RESET), .resetConfig = UWB_RESET_CONFIG_UWBS_RESET, }; UWB_STATUS status; - BOOL ioResult = DeviceIoControl(handleDriver.get(), IOCTL_UWB_DEVICE_RESET, const_cast(&deviceReset), sizeof deviceReset, &status, sizeof status, nullptr, nullptr); - if (!LOG_IF_WIN32_BOOL_FALSE(ioResult)) { - HRESULT hr = HRESULT_FROM_WIN32(GetLastError()); - PLOG_ERROR << "error when sending IOCTL_UWB_DEVICE_RESET, hr=" << std::showbase << std::hex << hr; - resultPromise.set_exception(std::make_exception_ptr(UwbException(UwbStatusGeneric::Failed))); - return resultFuture; - } else { - PLOG_DEBUG << "IOCTL_UWB_DEVICE_RESET succeeded"; - auto uwbStatus = UwbCxDdi::To(status); - if (!IsUwbStatusOk(uwbStatus)) { - resultPromise.set_exception(std::make_exception_ptr(UwbException(std::move(uwbStatus)))); - } else { - resultPromise.set_value(); - } - } + DeviceIoControlWrapper( + resultPromise, + "error when sending IOCTL_UWB_DEVICE_RESET", + "IOCTL_UWB_DEVICE_RESET succeeded", + [&]() { + auto uwbStatus = UwbCxDdi::To(status); + if (!IsUwbStatusOk(uwbStatus)) { + resultPromise.set_exception(std::make_exception_ptr(UwbException(std::move(uwbStatus)))); + } else { + resultPromise.set_value(); + } + }, + IOCTL_UWB_DEVICE_RESET, + const_cast(&deviceReset), + sizeof deviceReset, + &status, + sizeof status, + nullptr, + nullptr); return resultFuture; } @@ -637,14 +656,6 @@ UwbConnector::SetApplicationConfigurationParameters(uint32_t sessionId, std::vec std::promise>> resultPromise; auto resultFuture = resultPromise.get_future(); - wil::shared_hfile handleDriver; - auto hr = OpenDriverHandle(handleDriver, m_deviceName.c_str()); - if (FAILED(hr)) { - PLOG_ERROR << "failed to obtain driver handle for " << m_deviceName << ", hr=" << std::showbase << std::hex << hr; - resultPromise.set_exception(std::make_exception_ptr(UwbException(UwbStatusGeneric::Rejected))); - return resultFuture; - } - UwbCxDdi::UwbSetApplicationConfigurationParameters uwbSetApplicationConfigurationParameters{ .SessionId = sessionId, .Parameters = std::move(applicationConfigurationParameters), @@ -655,24 +666,29 @@ UwbConnector::SetApplicationConfigurationParameters(uint32_t sessionId, std::vec auto statusSize = offsetof(UWB_SET_APP_CONFIG_PARAMS_STATUS, appConfigParamsStatus[std::size(uwbSetApplicationConfigurationParameters.Parameters)]); std::vector statusBuffer(statusSize); - BOOL ioResult = DeviceIoControl(handleDriver.get(), IOCTL_UWB_SET_APP_CONFIG_PARAMS, std::data(paramsBuffer), std::size(paramsBuffer), std::data(statusBuffer), statusSize, nullptr, nullptr); - if (!LOG_IF_WIN32_BOOL_FALSE(ioResult)) { - HRESULT hr = HRESULT_FROM_WIN32(GetLastError()); - PLOG_ERROR << "error when sending IOCTL_UWB_SET_APP_CONFIG_PARAMS with sessionId " << sessionId << ", hr = " << std::showbase << std::hex << hr; - resultPromise.set_exception(std::make_exception_ptr(UwbException(UwbStatusGeneric::Rejected))); - return resultFuture; - } else { - PLOG_DEBUG << "IOCTL_UWB_SET_APP_CONFIG_PARAMS succeeded"; - auto& setApplicationConfigurationParametersStatus = *reinterpret_cast(std::data(statusBuffer)); - auto uwbStatus = UwbCxDdi::To(setApplicationConfigurationParametersStatus.status); - if (!IsUwbStatusOk(uwbStatus)) { - resultPromise.set_exception(std::make_exception_ptr(UwbException(std::move(uwbStatus)))); - } else { - auto uwbSetApplicationConfigurationParametersStatus = UwbCxDdi::To(setApplicationConfigurationParametersStatus); - auto result = std::make_tuple(uwbSetApplicationConfigurationParametersStatus.Status, std::move(uwbSetApplicationConfigurationParametersStatus.ParameterStatuses)); - resultPromise.set_value(std::move(result)); - } - } + + DeviceIoControlWrapper( + resultPromise, + "error when sending IOCTL_UWB_SET_APP_CONFIG_PARAMS with sessionId " + std::to_string(sessionId), + "IOCTL_UWB_SET_APP_CONFIG_PARAMS succeeded", + [&]() { + auto& setApplicationConfigurationParametersStatus = *reinterpret_cast(std::data(statusBuffer)); + auto uwbStatus = UwbCxDdi::To(setApplicationConfigurationParametersStatus.status); + if (!IsUwbStatusOk(uwbStatus)) { + resultPromise.set_exception(std::make_exception_ptr(UwbException(std::move(uwbStatus)))); + } else { + auto uwbSetApplicationConfigurationParametersStatus = UwbCxDdi::To(setApplicationConfigurationParametersStatus); + auto result = std::make_tuple(uwbSetApplicationConfigurationParametersStatus.Status, std::move(uwbSetApplicationConfigurationParametersStatus.ParameterStatuses)); + resultPromise.set_value(std::move(result)); + } + }, + IOCTL_UWB_SET_APP_CONFIG_PARAMS, + std::data(paramsBuffer), + std::size(paramsBuffer), + std::data(statusBuffer), + statusSize, + nullptr, + nullptr); return resultFuture; } diff --git a/windows/devices/uwb/include/windows/devices/uwb/UwbConnector.hxx b/windows/devices/uwb/include/windows/devices/uwb/UwbConnector.hxx index 2ec10dce..7de97207 100644 --- a/windows/devices/uwb/include/windows/devices/uwb/UwbConnector.hxx +++ b/windows/devices/uwb/include/windows/devices/uwb/UwbConnector.hxx @@ -222,6 +222,22 @@ private: bool CallbacksPresent(); + // Internal function that wraps DeviceIoControl, handles errors and insufficient buffer size + /** + * @brief + * + * @tparam PromiseT + * @tparam ArgTs is everything that goes into a standard DeviceIOControl() call, aside from the leading handle argument + * @param resultPromise + * @param strFail + * @param strSuccess + * @param interpret + * @param args + */ + template + void + DeviceIoControlWrapper(std::promise& resultPromise, std::string strFail, std::string strSuccess, std::function interpret, ArgTs&&... args); + private: std::string m_deviceName{}; std::jthread m_notificationThread;