From a97214df431a06e59d5afa86b1fa0c8b08db1327 Mon Sep 17 00:00:00 2001 From: Peter Johnson Date: Fri, 17 Apr 2026 20:19:38 -0700 Subject: [PATCH] [hal] Resource classes: Use expected, refactor errors (#8768) Also revamp SetLastError et al; Instead of taking status by pointer, take by value and return new status instead. Rename from SetLast to Make to make this new usage obvious. Also move declarations for the error functions from duplicated in the per-target HALInternal.hpp to a common ErrorHandling.hpp. --- hal/src/main/native/cpp/ErrorHandling.cpp | 37 ++++++++++--------- .../native/include/wpi/hal/ErrorHandling.hpp | 27 ++++++++++++++ hal/src/main/native/include/wpi/hal/HAL.h | 2 +- .../wpi/hal/handles/DigitalHandleResource.hpp | 33 ++++++++++------- .../wpi/hal/handles/HandlesInternal.hpp | 10 +++++ .../handles/IndexedClassedHandleResource.hpp | 26 +++++++++---- .../wpi/hal/handles/IndexedHandleResource.hpp | 33 ++++++++++------- hal/src/main/native/sim/AddressableLED.cpp | 37 +++++++------------ hal/src/main/native/sim/AnalogInput.cpp | 23 ++++-------- hal/src/main/native/sim/CTREPCM.cpp | 17 +++------ hal/src/main/native/sim/DIO.cpp | 30 ++++++--------- hal/src/main/native/sim/DutyCycle.cpp | 16 +++----- hal/src/main/native/sim/Encoder.cpp | 9 ++--- hal/src/main/native/sim/HALInternal.hpp | 19 ---------- hal/src/main/native/sim/PWM.cpp | 25 +++++-------- hal/src/main/native/sim/PowerDistribution.cpp | 20 +++++----- hal/src/main/native/sim/REVPH.cpp | 22 ++++------- .../main/native/systemcore/AddressableLED.cpp | 25 +++++-------- .../main/native/systemcore/AnalogInput.cpp | 25 +++++-------- hal/src/main/native/systemcore/CTREPCM.cpp | 27 +++++--------- hal/src/main/native/systemcore/CTREPDP.cpp | 28 +++++--------- hal/src/main/native/systemcore/Counter.cpp | 25 +++++-------- hal/src/main/native/systemcore/DIO.cpp | 24 ++++-------- hal/src/main/native/systemcore/DutyCycle.cpp | 25 +++++-------- .../main/native/systemcore/HALInternal.hpp | 9 ----- hal/src/main/native/systemcore/I2C.cpp | 32 +++++++--------- hal/src/main/native/systemcore/PWM.cpp | 29 +++++---------- .../native/systemcore/PowerDistribution.cpp | 15 ++++---- hal/src/main/native/systemcore/REVPDH.cpp | 22 ++++------- hal/src/main/native/systemcore/REVPH.cpp | 37 +++++++------------ .../test/native/cpp/handles/HandleTest.cpp | 6 +-- 31 files changed, 309 insertions(+), 406 deletions(-) create mode 100644 hal/src/main/native/include/wpi/hal/ErrorHandling.hpp delete mode 100644 hal/src/main/native/sim/HALInternal.hpp diff --git a/hal/src/main/native/cpp/ErrorHandling.cpp b/hal/src/main/native/cpp/ErrorHandling.cpp index 35aef02241..f32ab12980 100644 --- a/hal/src/main/native/cpp/ErrorHandling.cpp +++ b/hal/src/main/native/cpp/ErrorHandling.cpp @@ -2,6 +2,8 @@ // Open Source Software; you can modify and/or share it under the terms of // the WPILib BSD license file in the root directory of this project. +#include "wpi/hal/ErrorHandling.hpp" + #include #include "wpi/hal/Errors.h" @@ -21,35 +23,36 @@ static LastErrorStorage& GetThreadLastError() { } namespace wpi::hal { -void SetLastError(int32_t* status, std::string_view value) { +HAL_Status MakeError(HAL_Status status, std::string_view value) { LastErrorStorage& lastError = GetThreadLastError(); lastError.message = value; - lastError.status = *status; - *status = HAL_USE_LAST_ERROR; + lastError.status = status; + return HAL_USE_LAST_ERROR; } -void SetLastErrorIndexOutOfRange(int32_t* status, std::string_view message, - int32_t minimum, int32_t maximum, - int32_t requested) { - SetLastError( +HAL_Status MakeErrorIndexOutOfRange(HAL_Status status, std::string_view message, + int32_t minimum, int32_t maximum, + int32_t requested) { + return MakeError( status, fmt::format("{}\n Status: {}\n Minimum: {} Maximum: {} Requested: {}", - message, *status, minimum, maximum, requested)); + message, status, minimum, maximum, requested)); } -void SetLastErrorPreviouslyAllocated(int32_t* status, std::string_view message, - int32_t channel, - std::string_view previousAllocation) { - wpi::hal::SetLastError( - status, fmt::format("{} {} previously allocated.\n" - "Location of the previous allocation:\n{}\n" - "Location of the current allocation:", - message, channel, previousAllocation)); +HAL_Status MakeErrorPreviouslyAllocated(HAL_Status status, + std::string_view message, + int32_t channel, + std::string_view previousAllocation) { + return MakeError(status, + fmt::format("{} {} previously allocated.\n" + "Location of the previous allocation:\n{}\n" + "Location of the current allocation:", + message, channel, previousAllocation)); } } // namespace wpi::hal extern "C" { -const char* HAL_GetLastError(int32_t* status) { +const char* HAL_GetLastError(HAL_Status* status) { if (*status == HAL_USE_LAST_ERROR) { LastErrorStorage& lastError = GetThreadLastError(); *status = lastError.status; diff --git a/hal/src/main/native/include/wpi/hal/ErrorHandling.hpp b/hal/src/main/native/include/wpi/hal/ErrorHandling.hpp new file mode 100644 index 0000000000..0a81af3980 --- /dev/null +++ b/hal/src/main/native/include/wpi/hal/ErrorHandling.hpp @@ -0,0 +1,27 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +#pragma once + +#include + +#include + +#include "wpi/hal/Types.h" + +namespace wpi::hal { +[[nodiscard]] +HAL_Status MakeError(HAL_Status status, std::string_view value); + +[[nodiscard]] +HAL_Status MakeErrorIndexOutOfRange(HAL_Status status, std::string_view message, + int32_t minimum, int32_t maximum, + int32_t channel); + +[[nodiscard]] +HAL_Status MakeErrorPreviouslyAllocated(HAL_Status status, + std::string_view message, + int32_t channel, + std::string_view previousAllocation); +} // namespace wpi::hal diff --git a/hal/src/main/native/include/wpi/hal/HAL.h b/hal/src/main/native/include/wpi/hal/HAL.h index 59acf610b5..ff538396f2 100644 --- a/hal/src/main/native/include/wpi/hal/HAL.h +++ b/hal/src/main/native/include/wpi/hal/HAL.h @@ -46,7 +46,7 @@ extern "C" { * @return the error message for the code. This does not need to be freed, * but can be overwritten by another hal call on the same thread. */ -const char* HAL_GetLastError(int32_t* status); +const char* HAL_GetLastError(HAL_Status* status); /** * Gets the error message for a specific status code. diff --git a/hal/src/main/native/include/wpi/hal/handles/DigitalHandleResource.hpp b/hal/src/main/native/include/wpi/hal/handles/DigitalHandleResource.hpp index ff7b511729..0cdde01d0e 100644 --- a/hal/src/main/native/include/wpi/hal/handles/DigitalHandleResource.hpp +++ b/hal/src/main/native/include/wpi/hal/handles/DigitalHandleResource.hpp @@ -8,10 +8,14 @@ #include #include +#include +#include +#include "wpi/hal/ErrorHandling.hpp" #include "wpi/hal/Errors.h" #include "wpi/hal/Types.h" #include "wpi/hal/handles/HandlesInternal.hpp" +#include "wpi/util/expected" #include "wpi/util/mutex.hpp" namespace wpi::hal { @@ -37,8 +41,8 @@ class DigitalHandleResource : public HandleBase { DigitalHandleResource(const DigitalHandleResource&) = delete; DigitalHandleResource& operator=(const DigitalHandleResource&) = delete; - std::shared_ptr Allocate(int16_t index, HAL_HandleEnum enumValue, - THandle* handle, int32_t* status); + wpi::util::expected>, HAL_Status> + Allocate(int16_t index, HAL_HandleEnum enumValue, std::string_view name); int16_t GetIndex(THandle handle, HAL_HandleEnum enumValue) { return getHandleTypedIndex(handle, enumValue, m_version); } @@ -52,27 +56,30 @@ class DigitalHandleResource : public HandleBase { }; template -std::shared_ptr +wpi::util::expected>, HAL_Status> DigitalHandleResource::Allocate( - int16_t index, HAL_HandleEnum enumValue, THandle* handle, int32_t* status) { + int16_t index, HAL_HandleEnum enumValue, std::string_view name) { // don't acquire the lock if we can fail early. if (index < 0 || index >= size) { - *handle = HAL_INVALID_HANDLE; - *status = RESOURCE_OUT_OF_RANGE; - return nullptr; + return wpi::util::unexpected( + MakeErrorIndexOutOfRange(RESOURCE_OUT_OF_RANGE, name, 0, size, index)); } std::scoped_lock lock(m_handleMutexes[index]); // check for allocation, otherwise allocate and return a valid handle if (m_structures[index] != nullptr) { - *handle = HAL_INVALID_HANDLE; - *status = RESOURCE_IS_ALLOCATED; - return m_structures[index]; + if constexpr (detail::HasPreviousAllocation) { + return wpi::util::unexpected(MakeErrorPreviouslyAllocated( + RESOURCE_IS_ALLOCATED, name, index, + m_structures[index]->previousAllocation)); + } else { + return wpi::util::unexpected(MakeErrorPreviouslyAllocated( + RESOURCE_IS_ALLOCATED, name, index, "unknown")); + } } m_structures[index] = std::make_shared(); - *handle = + THandle handle = static_cast(wpi::hal::createHandle(index, enumValue, m_version)); - *status = HAL_SUCCESS; - return m_structures[index]; + return std::pair{handle, m_structures[index]}; } template diff --git a/hal/src/main/native/include/wpi/hal/handles/HandlesInternal.hpp b/hal/src/main/native/include/wpi/hal/handles/HandlesInternal.hpp index dc2408fa9b..f287ad9293 100644 --- a/hal/src/main/native/include/wpi/hal/handles/HandlesInternal.hpp +++ b/hal/src/main/native/include/wpi/hal/handles/HandlesInternal.hpp @@ -6,6 +6,9 @@ #include +#include +#include + #include "wpi/hal/Types.h" #include "wpi/util/Synchronization.hpp" @@ -21,6 +24,13 @@ namespace wpi::hal { +namespace detail { +template +concept HasPreviousAllocation = requires(T a) { + { a.previousAllocation } -> std::convertible_to; +}; +} // namespace detail + /** * Base for all HAL Handles. */ diff --git a/hal/src/main/native/include/wpi/hal/handles/IndexedClassedHandleResource.hpp b/hal/src/main/native/include/wpi/hal/handles/IndexedClassedHandleResource.hpp index e8282ead06..5f78f63485 100644 --- a/hal/src/main/native/include/wpi/hal/handles/IndexedClassedHandleResource.hpp +++ b/hal/src/main/native/include/wpi/hal/handles/IndexedClassedHandleResource.hpp @@ -9,9 +9,11 @@ #include #include +#include "wpi/hal/ErrorHandling.hpp" #include "wpi/hal/Errors.h" #include "wpi/hal/Types.h" #include "wpi/hal/handles/HandlesInternal.hpp" +#include "wpi/util/expected" #include "wpi/util/mutex.hpp" namespace wpi::hal { @@ -40,8 +42,9 @@ class IndexedClassedHandleResource : public HandleBase { IndexedClassedHandleResource& operator=(const IndexedClassedHandleResource&) = delete; - THandle Allocate(int16_t index, std::shared_ptr toSet, - int32_t* status); + wpi::util::expected Allocate( + int16_t index, std::shared_ptr toSet, std::string_view name, + int offset = 0); int16_t GetIndex(THandle handle) { return getHandleTypedIndex(handle, enumValue, m_version); } @@ -56,19 +59,26 @@ class IndexedClassedHandleResource : public HandleBase { template -THandle +wpi::util::expected IndexedClassedHandleResource::Allocate( - int16_t index, std::shared_ptr toSet, int32_t* status) { + int16_t index, std::shared_ptr toSet, std::string_view name, + int offset) { // don't acquire the lock if we can fail early. if (index < 0 || index >= size) { - *status = RESOURCE_OUT_OF_RANGE; - return HAL_INVALID_HANDLE; + return wpi::util::unexpected(MakeErrorIndexOutOfRange( + RESOURCE_OUT_OF_RANGE, name, offset, size + offset, index + offset)); } std::scoped_lock lock(m_handleMutexes[index]); // check for allocation, otherwise allocate and return a valid handle if (m_structures[index] != nullptr) { - *status = RESOURCE_IS_ALLOCATED; - return HAL_INVALID_HANDLE; + if constexpr (detail::HasPreviousAllocation) { + return wpi::util::unexpected(MakeErrorPreviouslyAllocated( + RESOURCE_IS_ALLOCATED, name, index + offset, + m_structures[index]->previousAllocation)); + } else { + return wpi::util::unexpected(MakeErrorPreviouslyAllocated( + RESOURCE_IS_ALLOCATED, name, index + offset, "unknown")); + } } m_structures[index] = toSet; return static_cast( diff --git a/hal/src/main/native/include/wpi/hal/handles/IndexedHandleResource.hpp b/hal/src/main/native/include/wpi/hal/handles/IndexedHandleResource.hpp index ad263565e2..ee7db0cec5 100644 --- a/hal/src/main/native/include/wpi/hal/handles/IndexedHandleResource.hpp +++ b/hal/src/main/native/include/wpi/hal/handles/IndexedHandleResource.hpp @@ -8,10 +8,14 @@ #include #include +#include +#include +#include "wpi/hal/ErrorHandling.hpp" #include "wpi/hal/Errors.h" #include "wpi/hal/Types.h" #include "wpi/hal/handles/HandlesInternal.hpp" +#include "wpi/util/expected" #include "wpi/util/mutex.hpp" namespace wpi::hal { @@ -38,8 +42,8 @@ class IndexedHandleResource : public HandleBase { IndexedHandleResource(const IndexedHandleResource&) = delete; IndexedHandleResource& operator=(const IndexedHandleResource&) = delete; - std::shared_ptr Allocate(int16_t index, THandle* handle, - int32_t* status); + wpi::util::expected>, HAL_Status> + Allocate(int16_t index, std::string_view name, int offset = 0); int16_t GetIndex(THandle handle) { return getHandleTypedIndex(handle, enumValue, m_version); } @@ -54,27 +58,30 @@ class IndexedHandleResource : public HandleBase { template -std::shared_ptr +wpi::util::expected>, HAL_Status> IndexedHandleResource::Allocate( - int16_t index, THandle* handle, int32_t* status) { + int16_t index, std::string_view name, int offset) { // don't acquire the lock if we can fail early. if (index < 0 || index >= size) { - *status = RESOURCE_OUT_OF_RANGE; - *handle = HAL_INVALID_HANDLE; - return nullptr; + return wpi::util::unexpected(MakeErrorIndexOutOfRange( + RESOURCE_OUT_OF_RANGE, name, offset, size + offset, index + offset)); } std::scoped_lock lock(m_handleMutexes[index]); // check for allocation, otherwise allocate and return a valid handle if (m_structures[index] != nullptr) { - *status = RESOURCE_IS_ALLOCATED; - *handle = HAL_INVALID_HANDLE; - return m_structures[index]; + if constexpr (detail::HasPreviousAllocation) { + return wpi::util::unexpected(MakeErrorPreviouslyAllocated( + RESOURCE_IS_ALLOCATED, name, index + offset, + m_structures[index]->previousAllocation)); + } else { + return wpi::util::unexpected(MakeErrorPreviouslyAllocated( + RESOURCE_IS_ALLOCATED, name, index + offset, "unknown")); + } } m_structures[index] = std::make_shared(); - *handle = + auto handle = static_cast(wpi::hal::createHandle(index, enumValue, m_version)); - *status = HAL_SUCCESS; - return m_structures[index]; + return std::pair{handle, m_structures[index]}; } template = kNumAddressableLEDs) { - *status = RESOURCE_OUT_OF_RANGE; - wpi::hal::SetLastErrorIndexOutOfRange(status, - "Invalid Index for AddressableLED", 0, - kNumAddressableLEDs, channel); + *status = MakeErrorIndexOutOfRange(RESOURCE_OUT_OF_RANGE, + "Invalid Index for AddressableLED", 0, + kNumAddressableLEDs, channel); return HAL_INVALID_HANDLE; } - HAL_DigitalHandle handle; + auto resource = digitalChannelHandles->Allocate( + channel, HAL_HandleEnum::ADDRESSABLE_LED, "AddressableLED"); - auto port = digitalChannelHandles->Allocate( - channel, HAL_HandleEnum::ADDRESSABLE_LED, &handle, status); - - if (*status != 0) { - if (port) { - wpi::hal::SetLastErrorPreviouslyAllocated(status, "PWM or DIO", channel, - port->previousAllocation); - } else { - wpi::hal::SetLastErrorIndexOutOfRange(status, - "Invalid Index for AddressableLED", - 0, kNumAddressableLEDs, channel); - } + if (!resource) { + *status = resource.error(); return HAL_INVALID_HANDLE; // failed to allocate. Pass error back. } + auto [handle, port] = *resource; port->channel = static_cast(channel); SimAddressableLEDData[channel].start = 0; @@ -80,9 +71,8 @@ void HAL_SetAddressableLEDStart(HAL_AddressableLEDHandle handle, int32_t start, return; } if (start > HAL_ADDRESSABLE_LED_MAX_LEN || start < 0) { - *status = PARAMETER_OUT_OF_RANGE; - wpi::hal::SetLastError( - status, + *status = MakeError( + PARAMETER_OUT_OF_RANGE, fmt::format( "LED start must be less than or equal to {}. {} was requested", HAL_ADDRESSABLE_LED_MAX_LEN, start)); @@ -100,9 +90,8 @@ void HAL_SetAddressableLEDLength(HAL_AddressableLEDHandle handle, return; } if (length > HAL_ADDRESSABLE_LED_MAX_LEN || length < 0) { - *status = PARAMETER_OUT_OF_RANGE; - wpi::hal::SetLastError( - status, + *status = MakeError( + PARAMETER_OUT_OF_RANGE, fmt::format( "LED length must be less than or equal to {}. {} was requested", HAL_ADDRESSABLE_LED_MAX_LEN, length)); diff --git a/hal/src/main/native/sim/AnalogInput.cpp b/hal/src/main/native/sim/AnalogInput.cpp index 07a414727e..9f86d57f0b 100644 --- a/hal/src/main/native/sim/AnalogInput.cpp +++ b/hal/src/main/native/sim/AnalogInput.cpp @@ -6,9 +6,9 @@ #include "AnalogInternal.hpp" #include "HALInitializer.hpp" -#include "HALInternal.hpp" #include "PortsInternal.hpp" #include "mockdata/AnalogInDataInternal.hpp" +#include "wpi/hal/ErrorHandling.hpp" using namespace wpi::hal; @@ -21,27 +21,20 @@ HAL_AnalogInputHandle HAL_InitializeAnalogInputPort( int32_t channel, const char* allocationLocation, int32_t* status) { wpi::hal::init::CheckInit(); if (channel < 0 || channel >= kNumAnalogInputs) { - *status = RESOURCE_OUT_OF_RANGE; - wpi::hal::SetLastErrorIndexOutOfRange( - status, "Invalid Index for Analog Input", 0, kNumAnalogInputs, channel); + *status = MakeErrorIndexOutOfRange(RESOURCE_OUT_OF_RANGE, + "Invalid Index for Analog Input", 0, + kNumAnalogInputs, channel); return HAL_INVALID_HANDLE; } - HAL_AnalogInputHandle handle; - auto analog_port = analogInputHandles->Allocate(channel, &handle, status); + auto resource = analogInputHandles->Allocate(channel, "Analog"); - if (*status != 0) { - if (analog_port) { - wpi::hal::SetLastErrorPreviouslyAllocated( - status, "Analog Input", channel, analog_port->previousAllocation); - } else { - wpi::hal::SetLastErrorIndexOutOfRange(status, - "Invalid Index for Analog Input", 0, - kNumAnalogInputs, channel); - } + if (!resource) { + *status = resource.error(); return HAL_INVALID_HANDLE; // failed to allocate. Pass error back. } + auto [handle, analog_port] = *resource; analog_port->channel = static_cast(channel); SimAnalogInData[channel].initialized = true; diff --git a/hal/src/main/native/sim/CTREPCM.cpp b/hal/src/main/native/sim/CTREPCM.cpp index 9a26f21cf9..0bb04f30c7 100644 --- a/hal/src/main/native/sim/CTREPCM.cpp +++ b/hal/src/main/native/sim/CTREPCM.cpp @@ -7,9 +7,9 @@ #include #include "HALInitializer.hpp" -#include "HALInternal.hpp" #include "PortsInternal.hpp" #include "mockdata/CTREPCMDataInternal.hpp" +#include "wpi/hal/ErrorHandling.hpp" #include "wpi/hal/Errors.h" #include "wpi/hal/handles/IndexedHandleResource.hpp" @@ -40,21 +40,14 @@ HAL_CTREPCMHandle HAL_InitializeCTREPCM(int32_t busId, int32_t module, int32_t* status) { wpi::hal::init::CheckInit(); - HAL_CTREPCMHandle handle; - auto pcm = pcmHandles->Allocate(module, &handle, status); + auto resource = pcmHandles->Allocate(module, "CTRE PCM"); - if (*status != 0) { - if (pcm) { - wpi::hal::SetLastErrorPreviouslyAllocated(status, "CTRE PCM", module, - pcm->previousAllocation); - } else { - wpi::hal::SetLastErrorIndexOutOfRange(status, - "Invalid Index for CTRE PCM", 0, - kNumCTREPCMModules - 1, module); - } + if (!resource) { + *status = resource.error(); return HAL_INVALID_HANDLE; // failed to allocate. Pass error back. } + auto [handle, pcm] = *resource; pcm->previousAllocation = allocationLocation ? allocationLocation : ""; pcm->module = module; diff --git a/hal/src/main/native/sim/DIO.cpp b/hal/src/main/native/sim/DIO.cpp index 8bf3a24d8e..b6cad07986 100644 --- a/hal/src/main/native/sim/DIO.cpp +++ b/hal/src/main/native/sim/DIO.cpp @@ -6,10 +6,11 @@ #include "DigitalInternal.hpp" #include "HALInitializer.hpp" -#include "HALInternal.hpp" #include "PortsInternal.hpp" #include "mockdata/DIODataInternal.hpp" #include "mockdata/DigitalPWMDataInternal.hpp" +#include "wpi/hal/ErrorHandling.hpp" +#include "wpi/hal/Errors.h" #include "wpi/hal/handles/HandlesInternal.hpp" #include "wpi/hal/handles/LimitedHandleResource.hpp" @@ -37,28 +38,21 @@ HAL_DigitalHandle HAL_InitializeDIOPort(int32_t channel, HAL_Bool input, wpi::hal::init::CheckInit(); if (channel < 0 || channel >= kNumDigitalChannels) { - *status = RESOURCE_OUT_OF_RANGE; - wpi::hal::SetLastErrorIndexOutOfRange(status, "Invalid Index for DIO", 0, - kNumDigitalChannels, channel); + *status = + MakeErrorIndexOutOfRange(RESOURCE_OUT_OF_RANGE, "Invalid Index for DIO", + 0, kNumDigitalChannels, channel); return HAL_INVALID_HANDLE; } - HAL_DigitalHandle handle; + auto resource = + digitalChannelHandles->Allocate(channel, HAL_HandleEnum::DIO, "DIO"); - auto port = digitalChannelHandles->Allocate(channel, HAL_HandleEnum::DIO, - &handle, status); - - if (*status != 0) { - if (port) { - wpi::hal::SetLastErrorPreviouslyAllocated(status, "PWM or DIO", channel, - port->previousAllocation); - } else { - wpi::hal::SetLastErrorIndexOutOfRange(status, "Invalid Index for DIO", 0, - kNumDigitalChannels, channel); - } + if (!resource) { + *status = resource.error(); return HAL_INVALID_HANDLE; // failed to allocate. Pass error back. } + auto [handle, port] = *resource; port->channel = static_cast(channel); SimDIOData[channel].initialized = true; @@ -189,8 +183,8 @@ void HAL_SetDIO(HAL_DigitalHandle dioPortHandle, HAL_Bool value, } } if (SimDIOData[port->channel].isInput) { - *status = PARAMETER_OUT_OF_RANGE; - wpi::hal::SetLastError(status, "Cannot set output of an input channel"); + *status = MakeError(PARAMETER_OUT_OF_RANGE, + "Cannot set output of an input channel"); return; } SimDIOData[port->channel].value = value; diff --git a/hal/src/main/native/sim/DutyCycle.cpp b/hal/src/main/native/sim/DutyCycle.cpp index 5be29264c7..96dbeff7d6 100644 --- a/hal/src/main/native/sim/DutyCycle.cpp +++ b/hal/src/main/native/sim/DutyCycle.cpp @@ -7,9 +7,9 @@ #include #include "HALInitializer.hpp" -#include "HALInternal.hpp" #include "PortsInternal.hpp" #include "mockdata/DutyCycleDataInternal.hpp" +#include "wpi/hal/ErrorHandling.hpp" #include "wpi/hal/Errors.h" #include "wpi/hal/handles/HandlesInternal.hpp" #include "wpi/hal/handles/IndexedHandleResource.hpp" @@ -42,20 +42,14 @@ HAL_DutyCycleHandle HAL_InitializeDutyCycle(int32_t channel, int32_t* status) { wpi::hal::init::CheckInit(); - HAL_DutyCycleHandle handle = HAL_INVALID_HANDLE; - auto dutyCycle = dutyCycleHandles->Allocate(channel, &handle, status); + auto resource = dutyCycleHandles->Allocate(channel, "Duty Cycle"); - if (*status != 0) { - if (dutyCycle) { - wpi::hal::SetLastErrorPreviouslyAllocated(status, "SmartIo", channel, - dutyCycle->previousAllocation); - } else { - wpi::hal::SetLastErrorIndexOutOfRange( - status, "Invalid Index for Duty Cycle", 0, kNumDutyCycles, channel); - } + if (!resource) { + *status = resource.error(); return HAL_INVALID_HANDLE; // failed to allocate. Pass error back. } + auto [handle, dutyCycle] = *resource; int16_t index = getHandleIndex(handle); SimDutyCycleData[index].initialized = true; SimDutyCycleData[index].simDevice = 0; diff --git a/hal/src/main/native/sim/Encoder.cpp b/hal/src/main/native/sim/Encoder.cpp index 4bbc3e05d1..a40d10f045 100644 --- a/hal/src/main/native/sim/Encoder.cpp +++ b/hal/src/main/native/sim/Encoder.cpp @@ -8,9 +8,9 @@ #include "CounterInternal.hpp" #include "HALInitializer.hpp" -#include "HALInternal.hpp" #include "PortsInternal.hpp" #include "mockdata/EncoderDataInternal.hpp" +#include "wpi/hal/ErrorHandling.hpp" #include "wpi/hal/Errors.h" #include "wpi/hal/handles/HandlesInternal.hpp" #include "wpi/hal/handles/LimitedHandleResource.hpp" @@ -271,8 +271,7 @@ void HAL_SetEncoderMinRate(HAL_EncoderHandle encoderHandle, double minRate, } if (minRate == 0.0) { - *status = PARAMETER_OUT_OF_RANGE; - wpi::hal::SetLastError(status, "minRate must not be 0"); + *status = MakeError(PARAMETER_OUT_OF_RANGE, "minRate must not be 0"); return; } @@ -288,8 +287,8 @@ void HAL_SetEncoderDistancePerPulse(HAL_EncoderHandle encoderHandle, } if (distancePerPulse == 0.0) { - *status = PARAMETER_OUT_OF_RANGE; - wpi::hal::SetLastError(status, "distancePerPulse must not be 0"); + *status = + MakeError(PARAMETER_OUT_OF_RANGE, "distancePerPulse must not be 0"); return; } encoder->distancePerPulse = distancePerPulse; diff --git a/hal/src/main/native/sim/HALInternal.hpp b/hal/src/main/native/sim/HALInternal.hpp deleted file mode 100644 index 0023442999..0000000000 --- a/hal/src/main/native/sim/HALInternal.hpp +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) FIRST and other WPILib contributors. -// Open Source Software; you can modify and/or share it under the terms of -// the WPILib BSD license file in the root directory of this project. - -#pragma once - -#include - -#include - -namespace wpi::hal { -void SetLastError(int32_t* status, std::string_view value); -void SetLastErrorIndexOutOfRange(int32_t* status, std::string_view message, - int32_t minimum, int32_t maximum, - int32_t channel); -void SetLastErrorPreviouslyAllocated(int32_t* status, std::string_view message, - int32_t channel, - std::string_view previousAllocation); -} // namespace wpi::hal diff --git a/hal/src/main/native/sim/PWM.cpp b/hal/src/main/native/sim/PWM.cpp index baa8bd0648..6ecb9efc27 100644 --- a/hal/src/main/native/sim/PWM.cpp +++ b/hal/src/main/native/sim/PWM.cpp @@ -6,9 +6,9 @@ #include "DigitalInternal.hpp" #include "HALInitializer.hpp" -#include "HALInternal.hpp" #include "PortsInternal.hpp" #include "mockdata/PWMDataInternal.hpp" +#include "wpi/hal/ErrorHandling.hpp" #include "wpi/hal/handles/HandlesInternal.hpp" using namespace wpi::hal; @@ -25,9 +25,9 @@ HAL_DigitalHandle HAL_InitializePWMPort(int32_t channel, wpi::hal::init::CheckInit(); if (channel < 0 || channel >= kNumPWMChannels) { - *status = RESOURCE_OUT_OF_RANGE; - wpi::hal::SetLastErrorIndexOutOfRange(status, "Invalid Index for PWM", 0, - kNumPWMChannels, channel); + *status = + MakeErrorIndexOutOfRange(RESOURCE_OUT_OF_RANGE, "Invalid Index for PWM", + 0, kNumPWMChannels, channel); return HAL_INVALID_HANDLE; } @@ -39,22 +39,15 @@ HAL_DigitalHandle HAL_InitializePWMPort(int32_t channel, channel = remapMXPPWMChannel(channel) + 10; // remap MXP to proper channel } - HAL_DigitalHandle handle; + auto resource = + digitalChannelHandles->Allocate(channel, HAL_HandleEnum::PWM, "PWM"); - auto port = digitalChannelHandles->Allocate(channel, HAL_HandleEnum::PWM, - &handle, status); - - if (*status != 0) { - if (port) { - wpi::hal::SetLastErrorPreviouslyAllocated(status, "PWM or DIO", channel, - port->previousAllocation); - } else { - wpi::hal::SetLastErrorIndexOutOfRange(status, "Invalid Index for PWM", 0, - kNumPWMChannels, channel); - } + if (!resource) { + *status = resource.error(); return HAL_INVALID_HANDLE; // failed to allocate. Pass error back. } + auto [handle, port] = *resource; port->channel = origChannel; SimPWMData[origChannel].initialized = true; diff --git a/hal/src/main/native/sim/PowerDistribution.cpp b/hal/src/main/native/sim/PowerDistribution.cpp index 94f8bb5cbb..6379f312d0 100644 --- a/hal/src/main/native/sim/PowerDistribution.cpp +++ b/hal/src/main/native/sim/PowerDistribution.cpp @@ -8,10 +8,10 @@ #include "CANAPIInternal.hpp" #include "HALInitializer.hpp" -#include "HALInternal.hpp" #include "PortsInternal.hpp" #include "mockdata/PowerDistributionDataInternal.hpp" #include "wpi/hal/CANAPI.h" +#include "wpi/hal/ErrorHandling.hpp" #include "wpi/hal/Errors.h" using namespace wpi::hal; @@ -32,9 +32,9 @@ HAL_PowerDistributionHandle HAL_InitializePowerDistribution( const char* allocationLocation, int32_t* status) { if (type == HAL_POWER_DISTRIBUTION_AUTOMATIC) { if (module != HAL_DEFAULT_POWER_DISTRIBUTION_MODULE) { - *status = PARAMETER_OUT_OF_RANGE; - wpi::hal::SetLastError( - status, "Automatic PowerDistributionType must have default module"); + *status = + MakeError(PARAMETER_OUT_OF_RANGE, + "Automatic PowerDistributionType must have default module"); return HAL_INVALID_HANDLE; } @@ -44,14 +44,14 @@ HAL_PowerDistributionHandle HAL_InitializePowerDistribution( } if (!HAL_CheckPowerDistributionModule(module, type)) { - *status = RESOURCE_OUT_OF_RANGE; if (type == HAL_PowerDistributionType::HAL_POWER_DISTRIBUTION_CTRE) { - wpi::hal::SetLastErrorIndexOutOfRange(status, - "Invalid Index for CTRE PDP", 0, - kNumCTREPDPModules - 1, module); + *status = MakeErrorIndexOutOfRange(RESOURCE_OUT_OF_RANGE, + "Invalid Index for CTRE PDP", 0, + kNumCTREPDPModules - 1, module); } else { - wpi::hal::SetLastErrorIndexOutOfRange(status, "Invalid Index for REV PDH", - 1, kNumREVPDHModules, module); + *status = MakeErrorIndexOutOfRange(RESOURCE_OUT_OF_RANGE, + "Invalid Index for REV PDH", 1, + kNumREVPDHModules, module); } return HAL_INVALID_HANDLE; } diff --git a/hal/src/main/native/sim/REVPH.cpp b/hal/src/main/native/sim/REVPH.cpp index 52eb0f7441..4bf0b4ea35 100644 --- a/hal/src/main/native/sim/REVPH.cpp +++ b/hal/src/main/native/sim/REVPH.cpp @@ -7,9 +7,9 @@ #include #include "HALInitializer.hpp" -#include "HALInternal.hpp" #include "PortsInternal.hpp" #include "mockdata/REVPHDataInternal.hpp" +#include "wpi/hal/ErrorHandling.hpp" #include "wpi/hal/Errors.h" #include "wpi/hal/handles/IndexedHandleResource.hpp" @@ -41,27 +41,21 @@ HAL_REVPHHandle HAL_InitializeREVPH(int32_t busId, int32_t module, wpi::hal::init::CheckInit(); if (!HAL_CheckREVPHModuleNumber(module)) { - *status = RESOURCE_OUT_OF_RANGE; - wpi::hal::SetLastErrorIndexOutOfRange(status, "Invalid Index for REV PH", 1, - kNumREVPHModules, module); + *status = MakeErrorIndexOutOfRange(RESOURCE_OUT_OF_RANGE, + "Invalid Index for REV PH", 1, + kNumREVPHModules, module); return HAL_INVALID_HANDLE; } - HAL_REVPHHandle handle; // Module starts at 1 - auto pcm = pcmHandles->Allocate(module - 1, &handle, status); + auto resource = pcmHandles->Allocate(module - 1, "REV PH", 1); - if (*status != 0) { - if (pcm) { - wpi::hal::SetLastErrorPreviouslyAllocated(status, "REV PH", module, - pcm->previousAllocation); - } else { - wpi::hal::SetLastErrorIndexOutOfRange(status, "Invalid Index for REV PH", - 1, kNumREVPHModules, module); - } + if (!resource) { + *status = resource.error(); return HAL_INVALID_HANDLE; // failed to allocate. Pass error back. } + auto [handle, pcm] = *resource; pcm->previousAllocation = allocationLocation ? allocationLocation : ""; pcm->module = module; diff --git a/hal/src/main/native/systemcore/AddressableLED.cpp b/hal/src/main/native/systemcore/AddressableLED.cpp index fb687c2331..faebaff94e 100644 --- a/hal/src/main/native/systemcore/AddressableLED.cpp +++ b/hal/src/main/native/systemcore/AddressableLED.cpp @@ -14,11 +14,11 @@ #include "AddressableLEDSimd.hpp" #include "HALInitializer.hpp" -#include "HALInternal.hpp" #include "PortsInternal.hpp" #include "SmartIo.hpp" #include "SystemServerInternal.hpp" #include "wpi/hal/AddressableLEDTypes.h" +#include "wpi/hal/ErrorHandling.hpp" #include "wpi/hal/Errors.h" #include "wpi/hal/handles/HandlesInternal.hpp" #include "wpi/hal/monotonic_clock.hpp" @@ -89,28 +89,21 @@ HAL_AddressableLEDHandle HAL_InitializeAddressableLED( wpi::hal::init::CheckInit(); if (channel < 0 || channel >= kNumSmartIo) { - *status = RESOURCE_OUT_OF_RANGE; - wpi::hal::SetLastErrorIndexOutOfRange( - status, "Invalid Index for AddressableLED", 0, kNumSmartIo, channel); + *status = MakeErrorIndexOutOfRange(RESOURCE_OUT_OF_RANGE, + "Invalid Index for AddressableLED", 0, + kNumSmartIo, channel); return HAL_INVALID_HANDLE; } - HAL_DigitalHandle handle; + auto resource = smartIoHandles->Allocate( + channel, HAL_HandleEnum::ADDRESSABLE_LED, "AddressableLED"); - auto port = smartIoHandles->Allocate(channel, HAL_HandleEnum::ADDRESSABLE_LED, - &handle, status); - - if (*status != 0) { - if (port) { - wpi::hal::SetLastErrorPreviouslyAllocated(status, "SmartIo", channel, - port->previousAllocation); - } else { - wpi::hal::SetLastErrorIndexOutOfRange( - status, "Invalid Index for AddressableLED", 0, kNumSmartIo, channel); - } + if (!resource) { + *status = resource.error(); return HAL_INVALID_HANDLE; // failed to allocate. Pass error back. } + auto [handle, port] = *resource; port->channel = channel; *status = port->InitializeMode(SmartIoMode::AddressableLED); diff --git a/hal/src/main/native/systemcore/AnalogInput.cpp b/hal/src/main/native/systemcore/AnalogInput.cpp index 30f1bbea72..498b3d01f9 100644 --- a/hal/src/main/native/systemcore/AnalogInput.cpp +++ b/hal/src/main/native/systemcore/AnalogInput.cpp @@ -8,9 +8,9 @@ #include #include "HALInitializer.hpp" -#include "HALInternal.hpp" #include "PortsInternal.hpp" #include "SmartIo.hpp" +#include "wpi/hal/ErrorHandling.hpp" #include "wpi/hal/Errors.h" #include "wpi/hal/handles/HandlesInternal.hpp" #include "wpi/hal/monotonic_clock.hpp" @@ -28,28 +28,21 @@ HAL_AnalogInputHandle HAL_InitializeAnalogInputPort( wpi::hal::init::CheckInit(); if (channel < 0 || channel >= kNumSmartIo) { - *status = RESOURCE_OUT_OF_RANGE; - wpi::hal::SetLastErrorIndexOutOfRange(status, "Invalid Index for Analog", 0, - kNumSmartIo, channel); + *status = MakeErrorIndexOutOfRange(RESOURCE_OUT_OF_RANGE, + "Invalid Index for Analog", 0, + kNumSmartIo, channel); return HAL_INVALID_HANDLE; } - HAL_DigitalHandle handle; + auto resource = + smartIoHandles->Allocate(channel, HAL_HandleEnum::ANALOG_INPUT, "Analog"); - auto port = smartIoHandles->Allocate(channel, HAL_HandleEnum::ANALOG_INPUT, - &handle, status); - - if (*status != 0) { - if (port) { - wpi::hal::SetLastErrorPreviouslyAllocated(status, "SmartIo", channel, - port->previousAllocation); - } else { - wpi::hal::SetLastErrorIndexOutOfRange(status, "Invalid Index for Analog", - 0, kNumSmartIo, channel); - } + if (!resource) { + *status = resource.error(); return HAL_INVALID_HANDLE; // failed to allocate. Pass error back. } + auto [handle, port] = *resource; port->channel = channel; *status = port->InitializeMode(SmartIoMode::AnalogInput); diff --git a/hal/src/main/native/systemcore/CTREPCM.cpp b/hal/src/main/native/systemcore/CTREPCM.cpp index 556da4a5b0..1b4b0ce786 100644 --- a/hal/src/main/native/systemcore/CTREPCM.cpp +++ b/hal/src/main/native/systemcore/CTREPCM.cpp @@ -9,9 +9,9 @@ #include #include "HALInitializer.hpp" -#include "HALInternal.hpp" #include "PortsInternal.hpp" #include "wpi/hal/CANAPI.h" +#include "wpi/hal/ErrorHandling.hpp" #include "wpi/hal/Errors.h" #include "wpi/hal/handles/IndexedHandleResource.hpp" @@ -180,21 +180,14 @@ HAL_CTREPCMHandle HAL_InitializeCTREPCM(int32_t busId, int32_t module, int32_t* status) { wpi::hal::init::CheckInit(); - HAL_CTREPCMHandle handle; - auto pcm = pcmHandles->Allocate(module, &handle, status); + auto resource = pcmHandles->Allocate(module, "CTRE PCM"); - if (*status != 0) { - if (pcm) { - wpi::hal::SetLastErrorPreviouslyAllocated(status, "CTRE PCM", module, - pcm->previousAllocation); - } else { - wpi::hal::SetLastErrorIndexOutOfRange(status, - "Invalid Index for CTRE PCM", 0, - kNumCTREPCMModules - 1, module); - } + if (!resource) { + *status = resource.error(); return HAL_INVALID_HANDLE; // failed to allocate. Pass error back. } + auto [handle, pcm] = *resource; pcm->canHandle = HAL_InitializeCAN(busId, manufacturer, module, deviceType, status); if (*status != 0) { @@ -360,9 +353,8 @@ void HAL_ClearAllCTREPCMStickyFaults(HAL_CTREPCMHandle handle, void HAL_FireCTREPCMOneShot(HAL_CTREPCMHandle handle, int32_t index, int32_t* status) { if (index > 7 || index < 0) { - *status = PARAMETER_OUT_OF_RANGE; - wpi::hal::SetLastError( - status, + *status = MakeError( + PARAMETER_OUT_OF_RANGE, fmt::format("Only [0-7] are valid index values. Requested {}", index)); return; } @@ -392,9 +384,8 @@ void HAL_FireCTREPCMOneShot(HAL_CTREPCMHandle handle, int32_t index, void HAL_SetCTREPCMOneShotDuration(HAL_CTREPCMHandle handle, int32_t index, int32_t durMs, int32_t* status) { if (index > 7 || index < 0) { - *status = PARAMETER_OUT_OF_RANGE; - wpi::hal::SetLastError( - status, + *status = MakeError( + PARAMETER_OUT_OF_RANGE, fmt::format("Only [0-7] are valid index values. Requested {}", index)); return; } diff --git a/hal/src/main/native/systemcore/CTREPDP.cpp b/hal/src/main/native/systemcore/CTREPDP.cpp index 4b6e0c9af9..c3c5835345 100644 --- a/hal/src/main/native/systemcore/CTREPDP.cpp +++ b/hal/src/main/native/systemcore/CTREPDP.cpp @@ -9,10 +9,10 @@ #include #include "HALInitializer.hpp" -#include "HALInternal.hpp" #include "PortsInternal.hpp" #include "wpi/hal/CAN.h" #include "wpi/hal/CANAPI.h" +#include "wpi/hal/ErrorHandling.hpp" #include "wpi/hal/Errors.h" #include "wpi/hal/handles/IndexedHandleResource.hpp" @@ -133,27 +133,20 @@ HAL_PDPHandle HAL_InitializePDP(int32_t busId, int32_t module, int32_t* status) { wpi::hal::init::CheckInit(); if (!HAL_CheckPDPModule(module)) { - *status = RESOURCE_OUT_OF_RANGE; - wpi::hal::SetLastErrorIndexOutOfRange(status, "Invalid Index for CTRE PDP", - 0, kNumCTREPDPModules - 1, module); + *status = MakeErrorIndexOutOfRange(RESOURCE_OUT_OF_RANGE, + "Invalid Index for CTRE PDP", 0, + kNumCTREPDPModules - 1, module); return HAL_INVALID_HANDLE; } - HAL_PDPHandle handle; - auto pdp = pdpHandles->Allocate(module, &handle, status); + auto resource = pdpHandles->Allocate(module, "CTRE PDP"); - if (*status != 0) { - if (pdp) { - wpi::hal::SetLastErrorPreviouslyAllocated(status, "CTRE PDP", module, - pdp->previousAllocation); - } else { - wpi::hal::SetLastErrorIndexOutOfRange(status, - "Invalid Index for CTRE PDP", 0, - kNumCTREPDPModules - 1, module); - } + if (!resource) { + *status = resource.error(); return HAL_INVALID_HANDLE; // failed to allocate. Pass error back. } + auto [handle, pdp] = *resource; pdp->canHandle = HAL_InitializeCAN(busId, manufacturer, module, deviceType, status); if (*status != 0) { @@ -231,9 +224,8 @@ double HAL_GetPDPVoltage(HAL_PDPHandle handle, int32_t* status) { double HAL_GetPDPChannelCurrent(HAL_PDPHandle handle, int32_t channel, int32_t* status) { if (!HAL_CheckPDPChannel(channel)) { - *status = PARAMETER_OUT_OF_RANGE; - wpi::hal::SetLastError(status, - fmt::format("Invalid pdp channel {}", channel)); + *status = MakeError(PARAMETER_OUT_OF_RANGE, + fmt::format("Invalid pdp channel {}", channel)); return 0; } diff --git a/hal/src/main/native/systemcore/Counter.cpp b/hal/src/main/native/systemcore/Counter.cpp index e8fbfb5039..18c7207523 100644 --- a/hal/src/main/native/systemcore/Counter.cpp +++ b/hal/src/main/native/systemcore/Counter.cpp @@ -10,9 +10,9 @@ #include #include "HALInitializer.hpp" -#include "HALInternal.hpp" #include "PortsInternal.hpp" #include "SmartIo.hpp" +#include "wpi/hal/ErrorHandling.hpp" #include "wpi/hal/monotonic_clock.hpp" using namespace wpi::hal; @@ -28,28 +28,21 @@ HAL_CounterHandle HAL_InitializeCounter(int channel, HAL_Bool risingEdge, int32_t* status) { wpi::hal::init::CheckInit(); if (channel == INVALID_HANDLE_INDEX || channel >= kNumSmartIo) { - *status = RESOURCE_OUT_OF_RANGE; - wpi::hal::SetLastErrorIndexOutOfRange(status, "Invalid Index for Counter", - 0, kNumSmartIo, channel); + *status = MakeErrorIndexOutOfRange(RESOURCE_OUT_OF_RANGE, + "Invalid Index for Counter", 0, + kNumSmartIo, channel); return HAL_INVALID_HANDLE; } - HAL_CounterHandle handle; + auto resource = + smartIoHandles->Allocate(channel, HAL_HandleEnum::COUNTER, "Counter"); - auto port = smartIoHandles->Allocate(channel, HAL_HandleEnum::COUNTER, - &handle, status); - - if (*status != 0) { - if (port) { - wpi::hal::SetLastErrorPreviouslyAllocated(status, "SmartIo", channel, - port->previousAllocation); - } else { - wpi::hal::SetLastErrorIndexOutOfRange(status, "Invalid Index for Counter", - 0, kNumSmartIo, channel); - } + if (!resource) { + *status = resource.error(); return HAL_INVALID_HANDLE; // failed to allocate. Pass error back. } + auto [handle, port] = *resource; port->channel = channel; *status = diff --git a/hal/src/main/native/systemcore/DIO.cpp b/hal/src/main/native/systemcore/DIO.cpp index 07ee2348c9..de9adad034 100644 --- a/hal/src/main/native/systemcore/DIO.cpp +++ b/hal/src/main/native/systemcore/DIO.cpp @@ -9,9 +9,9 @@ #include #include "HALInitializer.hpp" -#include "HALInternal.hpp" #include "PortsInternal.hpp" #include "SmartIo.hpp" +#include "wpi/hal/ErrorHandling.hpp" #include "wpi/hal/Errors.h" #include "wpi/hal/handles/HandlesInternal.hpp" #include "wpi/hal/monotonic_clock.hpp" @@ -30,28 +30,20 @@ HAL_DigitalHandle HAL_InitializeDIOPort(int32_t channel, HAL_Bool input, wpi::hal::init::CheckInit(); if (channel < 0 || channel >= kNumSmartIo) { - *status = RESOURCE_OUT_OF_RANGE; - wpi::hal::SetLastErrorIndexOutOfRange(status, "Invalid Index for DIO", 0, - kNumSmartIo, channel); + *status = + MakeErrorIndexOutOfRange(RESOURCE_OUT_OF_RANGE, "Invalid Index for DIO", + 0, kNumSmartIo, channel); return HAL_INVALID_HANDLE; } - HAL_DigitalHandle handle; + auto resource = smartIoHandles->Allocate(channel, HAL_HandleEnum::DIO, "DIO"); - auto port = - smartIoHandles->Allocate(channel, HAL_HandleEnum::DIO, &handle, status); - - if (*status != 0) { - if (port) { - wpi::hal::SetLastErrorPreviouslyAllocated(status, "SmartIo", channel, - port->previousAllocation); - } else { - wpi::hal::SetLastErrorIndexOutOfRange(status, "Invalid Index for DIO", 0, - kNumSmartIo, channel); - } + if (!resource) { + *status = resource.error(); return HAL_INVALID_HANDLE; // failed to allocate. Pass error back. } + auto [handle, port] = *resource; port->channel = channel; *status = port->InitializeMode(input ? SmartIoMode::DigitalInput diff --git a/hal/src/main/native/systemcore/DutyCycle.cpp b/hal/src/main/native/systemcore/DutyCycle.cpp index 4647d6cce6..86714d0bdf 100644 --- a/hal/src/main/native/systemcore/DutyCycle.cpp +++ b/hal/src/main/native/systemcore/DutyCycle.cpp @@ -8,9 +8,9 @@ #include #include "HALInitializer.hpp" -#include "HALInternal.hpp" #include "PortsInternal.hpp" #include "SmartIo.hpp" +#include "wpi/hal/ErrorHandling.hpp" #include "wpi/hal/Errors.h" #include "wpi/hal/handles/HandlesInternal.hpp" #include "wpi/hal/monotonic_clock.hpp" @@ -28,28 +28,21 @@ HAL_DutyCycleHandle HAL_InitializeDutyCycle(int32_t channel, wpi::hal::init::CheckInit(); if (channel < 0 || channel >= kNumSmartIo) { - *status = RESOURCE_OUT_OF_RANGE; - wpi::hal::SetLastErrorIndexOutOfRange(status, "Invalid Index for DutyCycle", - 0, kNumSmartIo, channel); + *status = MakeErrorIndexOutOfRange(RESOURCE_OUT_OF_RANGE, + "Invalid Index for DutyCycle", 0, + kNumSmartIo, channel); return HAL_INVALID_HANDLE; } - HAL_DigitalHandle handle; + auto resource = smartIoHandles->Allocate(channel, HAL_HandleEnum::DUTY_CYCLE, + "DutyCycle"); - auto port = smartIoHandles->Allocate(channel, HAL_HandleEnum::DUTY_CYCLE, - &handle, status); - - if (*status != 0) { - if (port) { - wpi::hal::SetLastErrorPreviouslyAllocated(status, "SmartIo", channel, - port->previousAllocation); - } else { - wpi::hal::SetLastErrorIndexOutOfRange( - status, "Invalid Index for DutyCycle", 0, kNumSmartIo, channel); - } + if (!resource) { + *status = resource.error(); return HAL_INVALID_HANDLE; // failed to allocate. Pass error back. } + auto [handle, port] = *resource; port->channel = channel; *status = port->InitializeMode(SmartIoMode::PwmInput); diff --git a/hal/src/main/native/systemcore/HALInternal.hpp b/hal/src/main/native/systemcore/HALInternal.hpp index 628763c9ed..db84145b8c 100644 --- a/hal/src/main/native/systemcore/HALInternal.hpp +++ b/hal/src/main/native/systemcore/HALInternal.hpp @@ -6,15 +6,6 @@ #include -#include - namespace wpi::hal { -void SetLastError(int32_t* status, std::string_view value); -void SetLastErrorIndexOutOfRange(int32_t* status, std::string_view message, - int32_t minimum, int32_t maximum, - int32_t channel); -void SetLastErrorPreviouslyAllocated(int32_t* status, std::string_view message, - int32_t channel, - std::string_view previousAllocation); uint64_t GetDSInitializeTime(); } // namespace wpi::hal diff --git a/hal/src/main/native/systemcore/I2C.cpp b/hal/src/main/native/systemcore/I2C.cpp index 6b10841713..66c3381509 100644 --- a/hal/src/main/native/systemcore/I2C.cpp +++ b/hal/src/main/native/systemcore/I2C.cpp @@ -15,8 +15,8 @@ #include #include "HALInitializer.hpp" -#include "HALInternal.hpp" #include "PortsInternal.hpp" +#include "wpi/hal/ErrorHandling.hpp" #include "wpi/hal/Errors.h" #include "wpi/util/mutex.hpp" #include "wpi/util/print.hpp" @@ -45,9 +45,8 @@ void HAL_InitializeI2C(HAL_I2CPort port, int32_t* status) { wpi::hal::init::CheckInit(); if (port < 0 || port > 2) { - *status = RESOURCE_OUT_OF_RANGE; - wpi::hal::SetLastErrorIndexOutOfRange(status, "Invalid Index for I2C", 0, 1, - port); + *status = MakeErrorIndexOutOfRange(RESOURCE_OUT_OF_RANGE, + "Invalid Index for I2C", 0, 1, port); return; } @@ -59,9 +58,8 @@ void HAL_InitializeI2C(HAL_I2CPort port, int32_t* status) { int handle = open(physicalPorts[port], O_RDWR); if (handle < 0) { int err = errno; - *status = NO_AVAILABLE_RESOURCES; - wpi::hal::SetLastError( - status, + *status = MakeError( + NO_AVAILABLE_RESOURCES, fmt::format("Failed to open onboard i2c bus: {}", std::strerror(err))); wpi::util::print("Failed to open onboard i2c bus: {}\n", std::strerror(err)); @@ -76,9 +74,8 @@ int32_t HAL_TransactionI2C(HAL_I2CPort port, int32_t deviceAddress, const uint8_t* dataToSend, int32_t sendSize, uint8_t* dataReceived, int32_t receiveSize) { if (port < 0 || port > 2) { - int32_t status = 0; - wpi::hal::SetLastErrorIndexOutOfRange(&status, "Invalid Index for I2C", 0, - 1, port); + (void)MakeErrorIndexOutOfRange(PARAMETER_OUT_OF_RANGE, + "Invalid Index for I2C", 0, 1, port); return -1; } @@ -103,9 +100,8 @@ int32_t HAL_TransactionI2C(HAL_I2CPort port, int32_t deviceAddress, int32_t HAL_WriteI2C(HAL_I2CPort port, int32_t deviceAddress, const uint8_t* dataToSend, int32_t sendSize) { if (port < 0 || port > 2) { - int32_t status = 0; - wpi::hal::SetLastErrorIndexOutOfRange(&status, "Invalid Index for I2C", 0, - 2, port); + (void)MakeErrorIndexOutOfRange(PARAMETER_OUT_OF_RANGE, + "Invalid Index for I2C", 0, 2, port); return -1; } @@ -126,9 +122,8 @@ int32_t HAL_WriteI2C(HAL_I2CPort port, int32_t deviceAddress, int32_t HAL_ReadI2C(HAL_I2CPort port, int32_t deviceAddress, uint8_t* buffer, int32_t count) { if (port < 0 || port > 2) { - int32_t status = 0; - wpi::hal::SetLastErrorIndexOutOfRange(&status, "Invalid Index for I2C", 0, - 1, port); + (void)MakeErrorIndexOutOfRange(PARAMETER_OUT_OF_RANGE, + "Invalid Index for I2C", 0, 1, port); return -1; } @@ -148,9 +143,8 @@ int32_t HAL_ReadI2C(HAL_I2CPort port, int32_t deviceAddress, uint8_t* buffer, void HAL_CloseI2C(HAL_I2CPort port) { if (port < 0 || port > 2) { - int32_t status = 0; - wpi::hal::SetLastErrorIndexOutOfRange(&status, "Invalid Index for I2C", 0, - 1, port); + (void)MakeErrorIndexOutOfRange(PARAMETER_OUT_OF_RANGE, + "Invalid Index for I2C", 0, 1, port); return; } diff --git a/hal/src/main/native/systemcore/PWM.cpp b/hal/src/main/native/systemcore/PWM.cpp index d20b940e0a..b51fc44d2f 100644 --- a/hal/src/main/native/systemcore/PWM.cpp +++ b/hal/src/main/native/systemcore/PWM.cpp @@ -11,9 +11,9 @@ #include #include "HALInitializer.hpp" -#include "HALInternal.hpp" #include "PortsInternal.hpp" #include "SmartIo.hpp" +#include "wpi/hal/ErrorHandling.hpp" #include "wpi/hal/Errors.h" #include "wpi/hal/handles/HandlesInternal.hpp" #include "wpi/hal/monotonic_clock.hpp" @@ -32,28 +32,20 @@ HAL_DigitalHandle HAL_InitializePWMPort(int32_t channel, wpi::hal::init::CheckInit(); if (channel < 0 || channel >= kNumSmartIo) { - *status = RESOURCE_OUT_OF_RANGE; - wpi::hal::SetLastErrorIndexOutOfRange(status, "Invalid Index for PWM", 0, - kNumSmartIo, channel); + *status = + MakeErrorIndexOutOfRange(RESOURCE_OUT_OF_RANGE, "Invalid Index for PWM", + 0, kNumSmartIo, channel); return HAL_INVALID_HANDLE; } - HAL_DigitalHandle handle; + auto resource = smartIoHandles->Allocate(channel, HAL_HandleEnum::PWM, "PWM"); - auto port = - smartIoHandles->Allocate(channel, HAL_HandleEnum::PWM, &handle, status); - - if (*status != 0) { - if (port) { - wpi::hal::SetLastErrorPreviouslyAllocated(status, "SmartIo", channel, - port->previousAllocation); - } else { - wpi::hal::SetLastErrorIndexOutOfRange(status, "Invalid Index for PWM", 0, - kNumSmartIo, channel); - } + if (!resource) { + *status = resource.error(); return HAL_INVALID_HANDLE; // failed to allocate. Pass error back. } + auto [handle, port] = *resource; port->channel = channel; *status = port->InitializeMode(SmartIoMode::PwmOutput); @@ -113,9 +105,8 @@ void HAL_SetPWMPulseTimeMicroseconds(HAL_DigitalHandle pwmPortHandle, if (microsecondPulseTime < 0 || (microsecondPulseTime != 0xFFFF && microsecondPulseTime >= 4096)) { - *status = PARAMETER_OUT_OF_RANGE; - wpi::hal::SetLastError( - status, + *status = MakeError( + PARAMETER_OUT_OF_RANGE, fmt::format("Pulse time {} out of range. Expect [0-4096) or 0xFFFF", microsecondPulseTime)); return; diff --git a/hal/src/main/native/systemcore/PowerDistribution.cpp b/hal/src/main/native/systemcore/PowerDistribution.cpp index 05a94651ca..d4c9249a33 100644 --- a/hal/src/main/native/systemcore/PowerDistribution.cpp +++ b/hal/src/main/native/systemcore/PowerDistribution.cpp @@ -11,6 +11,7 @@ #include "HALInternal.hpp" #include "PortsInternal.hpp" #include "REVPDH.h" +#include "wpi/hal/ErrorHandling.hpp" #include "wpi/hal/Errors.h" #include "wpi/hal/HAL.h" #include "wpi/hal/handles/HandlesInternal.hpp" @@ -24,9 +25,9 @@ HAL_PowerDistributionHandle HAL_InitializePowerDistribution( const char* allocationLocation, int32_t* status) { if (type == HAL_PowerDistributionType::HAL_POWER_DISTRIBUTION_AUTOMATIC) { if (moduleNumber != HAL_DEFAULT_POWER_DISTRIBUTION_MODULE) { - *status = PARAMETER_OUT_OF_RANGE; - wpi::hal::SetLastError( - status, "Automatic PowerDistributionType must have default module"); + *status = + MakeError(PARAMETER_OUT_OF_RANGE, + "Automatic PowerDistributionType must have default module"); return HAL_INVALID_HANDLE; } @@ -158,15 +159,15 @@ void HAL_GetPowerDistributionAllChannelCurrents( int32_t currentsLength, int32_t* status) { if (IsCtre(handle)) { if (currentsLength < kNumCTREPDPChannels) { - *status = PARAMETER_OUT_OF_RANGE; - SetLastError(status, "Output array not large enough"); + *status = + MakeError(PARAMETER_OUT_OF_RANGE, "Output array not large enough"); return; } return HAL_GetPDPAllChannelCurrents(handle, currents, status); } else { if (currentsLength < kNumREVPDHChannels) { - *status = PARAMETER_OUT_OF_RANGE; - SetLastError(status, "Output array not large enough"); + *status = + MakeError(PARAMETER_OUT_OF_RANGE, "Output array not large enough"); return; } return HAL_GetREVPDHAllChannelCurrents(handle, currents, status); diff --git a/hal/src/main/native/systemcore/REVPDH.cpp b/hal/src/main/native/systemcore/REVPDH.cpp index 6688a79f52..95cc493446 100644 --- a/hal/src/main/native/systemcore/REVPDH.cpp +++ b/hal/src/main/native/systemcore/REVPDH.cpp @@ -11,12 +11,12 @@ #include #include "HALInitializer.hpp" -#include "HALInternal.hpp" #include "PortsInternal.hpp" #include "rev/PDHFrames.h" #include "wpi/hal/CAN.h" #include "wpi/hal/CANAPI.h" #include "wpi/hal/CANAPITypes.h" +#include "wpi/hal/ErrorHandling.hpp" #include "wpi/hal/Errors.h" #include "wpi/hal/handles/HandlesInternal.hpp" #include "wpi/hal/handles/IndexedHandleResource.hpp" @@ -193,26 +193,20 @@ HAL_REVPDHHandle HAL_InitializeREVPDH(int32_t busId, int32_t module, int32_t* status) { wpi::hal::init::CheckInit(); if (!HAL_CheckREVPDHModuleNumber(module)) { - *status = RESOURCE_OUT_OF_RANGE; - wpi::hal::SetLastErrorIndexOutOfRange(status, "Invalid Index for REV PDH", - 1, kNumREVPDHModules, module); + *status = MakeErrorIndexOutOfRange(RESOURCE_OUT_OF_RANGE, + "Invalid Index for REV PDH", 1, + kNumREVPDHModules, module); return HAL_INVALID_HANDLE; } - HAL_REVPDHHandle handle; // Module starts at 1 - auto hpdh = REVPDHHandles->Allocate(module - 1, &handle, status); - if (*status != 0) { - if (hpdh) { - wpi::hal::SetLastErrorPreviouslyAllocated(status, "REV PDH", module, - hpdh->previousAllocation); - } else { - wpi::hal::SetLastErrorIndexOutOfRange(status, "Invalid Index for REV PDH", - 1, kNumREVPDHModules, module); - } + auto resource = REVPDHHandles->Allocate(module - 1, "REV PDH", 1); + if (!resource) { + *status = resource.error(); return HAL_INVALID_HANDLE; // failed to allocate. Pass error back. } + auto [handle, hpdh] = *resource; HAL_CANHandle hcan = HAL_InitializeCAN(busId, manufacturer, module, deviceType, status); diff --git a/hal/src/main/native/systemcore/REVPH.cpp b/hal/src/main/native/systemcore/REVPH.cpp index 33433978bd..fe4a7afbab 100644 --- a/hal/src/main/native/systemcore/REVPH.cpp +++ b/hal/src/main/native/systemcore/REVPH.cpp @@ -10,10 +10,10 @@ #include #include "HALInitializer.hpp" -#include "HALInternal.hpp" #include "PortsInternal.hpp" #include "rev/PHFrames.h" #include "wpi/hal/CANAPI.h" +#include "wpi/hal/ErrorHandling.hpp" #include "wpi/hal/Errors.h" #include "wpi/hal/handles/IndexedHandleResource.hpp" @@ -196,26 +196,20 @@ HAL_REVPHHandle HAL_InitializeREVPH(int32_t busId, int32_t module, int32_t* status) { wpi::hal::init::CheckInit(); if (!HAL_CheckREVPHModuleNumber(module)) { - *status = RESOURCE_OUT_OF_RANGE; - wpi::hal::SetLastErrorIndexOutOfRange(status, "Invalid Index for REV PH", 1, - kNumREVPHModules, module); + *status = MakeErrorIndexOutOfRange(RESOURCE_OUT_OF_RANGE, + "Invalid Index for REV PH", 1, + kNumREVPHModules, module); return HAL_INVALID_HANDLE; } - HAL_REVPHHandle handle; // Module starts at 1 - auto hph = REVPHHandles->Allocate(module - 1, &handle, status); - if (*status != 0) { - if (hph) { - wpi::hal::SetLastErrorPreviouslyAllocated(status, "REV PH", module, - hph->previousAllocation); - } else { - wpi::hal::SetLastErrorIndexOutOfRange(status, "Invalid Index for REV PH", - 1, kNumREVPHModules, module); - } + auto resource = REVPHHandles->Allocate(module - 1, "REV PH", 1); + if (!resource) { + *status = resource.error(); return HAL_INVALID_HANDLE; // failed to allocate. Pass error back. } + auto [handle, hph] = *resource; HAL_CANHandle hcan = HAL_InitializeCAN(busId, manufacturer, module, deviceType, status); @@ -397,9 +391,8 @@ double HAL_GetREVPHAnalogVoltage(HAL_REVPHHandle handle, int32_t channel, } if (channel < 0 || channel > 1) { - *status = PARAMETER_OUT_OF_RANGE; - wpi::hal::SetLastErrorIndexOutOfRange(status, "Invalid REV Analog Index", 0, - 2, channel); + *status = MakeErrorIndexOutOfRange( + PARAMETER_OUT_OF_RANGE, "Invalid REV Analog Index", 0, 2, channel); return 0; } @@ -600,17 +593,15 @@ void HAL_FireREVPHOneShot(HAL_REVPHHandle handle, int32_t index, int32_t durMs, } if (index >= kNumREVPHChannels || index < 0) { - *status = PARAMETER_OUT_OF_RANGE; - wpi::hal::SetLastError( - status, + *status = MakeError( + PARAMETER_OUT_OF_RANGE, fmt::format("Only [0-15] are valid index values. Requested {}", index)); return; } if (!HAL_CheckREVPHPulseTime(durMs)) { - *status = PARAMETER_OUT_OF_RANGE; - wpi::hal::SetLastError( - status, + *status = MakeError( + PARAMETER_OUT_OF_RANGE, fmt::format("Time not within expected range [0-65534]. Requested {}", durMs)); return; diff --git a/hal/src/test/native/cpp/handles/HandleTest.cpp b/hal/src/test/native/cpp/handles/HandleTest.cpp index 32684cc0e1..f5b59a312a 100644 --- a/hal/src/test/native/cpp/handles/HandleTest.cpp +++ b/hal/src/test/native/cpp/handles/HandleTest.cpp @@ -19,9 +19,9 @@ TEST(HandleTest, ClassedHandle) { wpi::hal::IndexedClassedHandleResource testClass; - int32_t status = 0; - testClass.Allocate(0, std::make_unique(), &status); - EXPECT_EQ(0, status); + auto resource = + testClass.Allocate(0, std::make_shared(), "TestResource"); + EXPECT_TRUE(resource.has_value()); } } // namespace wpi::hal