/**
 * @file CosmicAsyncSDK.hpp
 *
 * @brief Header file that declares the CosmicAsyncSDK class. This class
 * contains the Asynchronous or non-blocking C++ API for Binho devices.
 */

#pragma once

#include <vector>

#include "CommunicationManager.hpp"
#include "CosmicSDKExport.h"
#include "Decoder.hpp"
#include "definitions.h"
#include "CosmicSDKVersion.h"

/** \addtogroup CosmicAsyncSDK_Cpp
 *  @{
 */

/**
 * @brief This class provides a non-blocking C++ interface. It allows users to connect to Binho devices
 * and perform various operations asynchronously. Users must set up a response callback using the onResponse method
 * to handle incoming data from the device.
 */
class COSMICSDK_API CosmicAsyncSDK {
public:
  /**
   * @brief Construct a new Cosmic Async SDK object
   */
  CosmicAsyncSDK();

  /**
   * @brief Destroy the Cosmic Async SDK object
   */
  ~CosmicAsyncSDK();

  /**
   * @brief Sets the callback function to be called when a response is received from the device.
   * @param callback The callback function that takes a vector of uint8_t as parameter.
   */
  void onResponse(std::function<void(const std::vector<uint8_t>&)> callback);

  /*****************************************************
   * @section Version Query
   ****************************************************/

  /**
   * @brief Gets the CosmicSDK library version string
   *
   * @details
   * Returns a string containing the version number of the linked CosmicSDK library.
   * This allows verification at startup that the linked library matches what
   * they were built against.
   *
   * @return A version string in the format "MAJOR.MINOR.PATCH", e.g. "1.2.3"
   */
  static std::string getVersion() { return COSMICSDK_VERSION_STRING; }

  /*****************************************************
   * @section System Interface
   ****************************************************/

  /**
   * @brief Connects to the device using the provided path.
   * @param devicePath The path to the device. If empty, connects to the first available device.
   * @return true if the connection was successful, false otherwise.
   */
  bool connect(const std::string& devicePath = "");

  /**
   * @brief Connects to the device using the provided serial number.
   * @param serial The serial number of the device to connect to.
   * @return true if the connection was successful, false otherwise.
   */
  bool connectWithSerialNumber(const std::string& serial);

  /**
   * @brief Disconnects from the device.
   */
  void disconnect();

  /**
   * @brief Checks if the device is connected.
   *
   * @return true if the device is connected.
   * @return false if the device is not connected.
   */
  bool isConnected() { return connected; }

  /**
   * @brief Get one USB String identified by the subcommand.
   *
   * @param id uint16_t Command Id to identify the request. Values from 1 to 65535 are valid. 0 is reserved for notifications.
   * @param subCmd unint8_t Subcommand to identify the USB String to be retrieved.
   * @return uint16_t SUCCESS or SDK_ERROR_DISCONNECT if the device is not connected.
   */
  uint16_t getUsbString(uint16_t id, uint8_t subCmd);

  /**
   * @brief Puts the device into boot mode. Once the device process the request, it immediately jumps into the bootloader. After the user has flashed the device with a firmware, a new connection needs to be done to continue using the device.
   *
   * @param id uint16_t Command Id to identify the request. Values from 1 to 65535 are valid. 0 is reserved for notifications.
   * @return uint16_t Result of the request.
   */
  uint16_t enterBootMode(uint16_t id);

  /*****************************************************
   * @section I2C Interface
   ****************************************************/

  /**
   * @brief Sets the I2C bus voltage.
   * @warning On Supernova and Pulsar host adapters, the I2C interface shares the same voltage domain as SPI, UART and GPIOs.
   * As a result, calling this method to set the I2C voltage will also affect the voltage of SPI, UART and GPIO interfaces.
   * This must be taken into account when more than one interfaces are used simultaneously.
   * @ingroup CosmicAsyncSDK_Cpp_I2C
   *
   * @param id
   *        Command Id to identify the request. Values from 1 to 65535 are valid. 0 is reserved for notifications.
   *
   * @param voltage_mV
   *        Voltage in millivolts to set the I2C bus to. The valid values are 0 mV, and any value in the range 1200 to 3300 mV.
   *        The value 0mV deactivates the VTARG pin and turn offs the downstream devices.
   *
   * @param persist
   *        If true, the voltage setting will be persistent across power cycles. This ensures that any DUT
   *        connected to the I2C bus (e.g. via Pulsar or Supernova) will receive power immediately upon startup, without
   *        waiting for the host to issue the voltage set command. If false, the setting will only apply to the current session.
   *
   * @retval SUCCESS
   *         The command was successfully sent to the host adapter.
   * @retval SDK_ERROR_DISCONNECT
   *         The device was disconnected or became unavailable during the operation.
   */
  uint16_t i2cSetBusVoltage(uint16_t id, uint16_t voltage_mV, bool persist = false);

  /**
   * @brief Initializes the I2C controller.
   * @ingroup CosmicAsyncSDK_Cpp_I2C
   *
   * @details
   * This function initializes the I2C peripheral and must be called successfully before any other
   * I2C-related API is used.
   *
   * @note
   * - This function must be called exactly once.
   * - Calling any I2C API before initialization will result in `FW_INTERFACE_NOT_INITIALIZED`.
   * - Calling this function more than once will result in `FW_INTERFACE_ALREADY_INITIALIZED`.
   * - To modify the I2C configuration after initialization, use @ref i2cSetParameters instead of
   * reinitializing the interface.
   *
   * @param id
   *        Command Id to identify the request. Values from 1 to 65535 are valid. 0 is reserved for notifications.
   *
   * @param bus
   *        I2C bus number (e.g., 0 for I2C_BUS_A). Valid values are defined in definitions.h (e.g., I2C_BUS_A, I2C_BUS_B).
   *
   * @param frequency_Hz
   *        The I2C bus frequency in Hz (e.g., 400000 for 400kHz).
   *
   * @param pullUpResistor
   *        The pull-up resistor value (e.g., I2C_PULLUP_330Ohm).
   *
   * @retval SUCCESS
   *         The command was successfully sent to the host adapter.
   * @retval SDK_ERROR_DISCONNECT
   *         The device was disconnected or became unavailable during the operation.
   */
  uint16_t i2cControllerInit(uint16_t id, uint8_t bus, uint32_t frequency_Hz, uint8_t pullUpResistor);

  /**
   * @brief Sets the I2C bus parameters.
   * @ingroup CosmicAsyncSDK_Cpp_I2C
   *
   * @details
   * This function updates the I2C bus parameters after the I2C interface has been successfully
   * initialized using @ref i2cControllerInit. It allows runtime reconfiguration of the I2C without
   * requiring a full deinitialization or reinitialization of the peripheral.
   *
   * @note
   * - This function must only be called after a successful call to @ref i2cControllerInit.
   * - Calling this function before UART initialization will result in
   * `FW_INTERFACE_NOT_INITIALIZED`.
   *
   * @param id
   *        Command Id to identify the request. Values from 1 to 65535 are valid. 0 is reserved for notifications.
   *
   * @param bus
   *        I2C bus number (e.g., 0 for I2C_BUS_A). Valid values are defined in definitions.h (e.g., I2C_BUS_A, I2C_BUS_B).
   *
   * @param frequency_Hz
   *        The I2C bus frequency in Hz (e.g., 400000 for 400kHz).
   *
   * @param pullUpResistor
   *        The pull-up resistor value (e.g., I2C_PULLUP_330Ohm).
   *
   * @retval SUCCESS
   *         The command was successfully sent to the host adapter.
   * @retval SDK_ERROR_DISCONNECT
   *         The device was disconnected or became unavailable during the operation.
   */
  uint16_t i2cSetParameters(uint16_t id, uint8_t bus, uint32_t frequency_Hz, uint8_t pullUpResistor);

  /**
   * @brief Sets the I2C pull-up resistors.
   * @ingroup CosmicAsyncSDK_Cpp_I2C
   *
   * @details
   * Configures the internal pull-up resistors connected to the selected I2C bus.
   * The specified @p value determines the effective pull-up strength according
   * to the hardware capabilities and predefined settings.
   *
   * @note
   * - This function must only be called after a successful call to @ref i2cControllerInit.
   * - On some hardware revisions, this feature may not be available.
   *
   * @param id
   *        Command Id to identify the request. Values from 1 to 65535 are valid. 0 is reserved for notifications.
   *
   * @param bus
   *        I2C bus number (e.g., 0 for I2C_BUS_A). Valid values are defined in definitions.h (e.g., I2C_BUS_A, I2C_BUS_B).
   *
   * @param value
   *        The value of the pull-up resistors to be set.
   *
   * @retval SUCCESS
   *         The command was successfully sent to the host adapter.
   * @retval SDK_ERROR_DISCONNECT
   *         The device was disconnected or became unavailable during the operation.
   */
  uint16_t i2cSetPullUpResistors(uint16_t id, uint8_t bus, uint8_t value);

  /**
   * @brief Writes data to an I2C device at an optional subAddress.
   * @ingroup CosmicAsyncSDK_Cpp_I2C
   *
   * @details
   * Writes data to an I2C target , optionally including an internal subaddress on the target device.
   *
   * @note
   * - This function is valid only when the host is initialized as an I2C controller with @ref
   * i2cControllerInit.
   *
   * @param id
   *        Command Id to identify the request. Values from 1 to 65535 are valid. 0 is reserved for notifications.
   *
   * @param bus
   *        I2C bus number (e.g., 0 for I2C_BUS_A). Valid values are defined in definitions.h (e.g., I2C_BUS_A, I2C_BUS_B).
   *
   * @param address
   *        The I2C address of the device.
   *
   * @param subAddress
   *        The optional sub-address to write to.
   *
   * @param inData
   *        The data to be written to the device.
   *
   * @param nonStop
   *        If true, the operation will not stop after writing.
   *
   * @retval SUCCESS
   *         The command was successfully sent to the host adapter.
   * @retval SDK_ERROR_DISCONNECT
   *         The device was disconnected or became unavailable during the operation.
   */
  uint16_t i2cWrite(uint16_t id, uint8_t bus, uint8_t address, const std::vector<uint8_t>& subAddress,
                    const std::vector<uint8_t>& inData,
                    const bool nonStop);

  /**
   * @brief Reads data from an I2C device at an optional subAddress.
   * @ingroup CosmicAsyncSDK_Cpp_I2C
   *
   * @details
   * Reads data from an I2C target, optionally a subaddress may be written first to select a register
   * or memory location prior to performing the read.
   *
   * @note
   * - This function is valid only when the host is initialized as an I2C controller with @ref
   * i2cControllerInit.
   *
   * @param id
   *        Command Id to identify the request. Values from 1 to 65535 are valid. 0 is reserved for notifications.
   *
   * @param bus
   *        I2C bus number (e.g., 0 for I2C_BUS_A). Valid values are defined in definitions.h (e.g., I2C_BUS_A, I2C_BUS_B).
   *
   * @param address
   *        The I2C address of the device.
   *
   * @param subAddress
   *        The optional sub-address to read from.
   *
   * @param readLength
   *        The length of data to be read.
   *
   * @param nonStop
   *        If true, the operation will not stop after reading.
   *
   * @retval SUCCESS
   *         The command was successfully sent to the host adapter.
   * @retval SDK_ERROR_DISCONNECT
   *         The device was disconnected or became unavailable during the operation.
   */
  uint16_t i2cRead(uint16_t id, uint8_t bus, uint8_t address, const std::vector<uint8_t>& subAddress,
                   uint16_t readLength, const bool nonStop);

  /**
   * @brief Request to the the host device to perform an I2C scan of the I2C bus and return the list of discovered static addresses.
   * @ingroup CosmicAsyncSDK_Cpp_I2C
   *
   * @details
   * Initiates an address scan on the selected I2C bus to detect connected target devices. The scan probes
   * valid address ranges and collects the addresses of devices that acknowledge their address.
   *
   * Discovered addresses are returned in @p deviceAddresses following
   * this order:
   * - All detected 7-bit addresses first (1 byte per address).
   * - All detected 10-bit addresses afterwards (2 bytes per address,
   *   high byte first).
   *
   * The total number of detected 7-bit and 10-bit devices is returned
   * separately via @p count7BitAddresses and @p count10BitAddresses.
   *
   * @note
   * - This function is valid only when the host is initialized as an I2C controller with @ref
   * i2cControllerInit.
   * 
   * @warning
   * Depending on the bus characteristics, such as frequency, voltage, number of targets connected, and the length of the wires used in the 
   * hardware setup, the performance of the I2C SCAN BUS may be affected, and as a result, it might return a wrong list of detected addresses, 
   * an ``SDK_ERROR_TIMEOUT`` error, and the firmware might indeed get stuck, especially in the Pulsar. In order to avoid this scenario, consider 
   * the following recommendations to run a smooth scan bus procedure:
   *   - Set the clock frequency to low values, such as 100KHz and 400 KHz.
   *   - Disable the pull-up resistors, or set their value to high values - weak pull-ups.
   *      - In the case of the Pulsar, suggested values are: ``I2C_PULLUP_DISABLE`` , ``I2C_PULLUP_4kOhm``, or ``I2C_PULLUP_2_2kOhm``
   *      - In the case of the Supernova, suggested values are: ``I2C_PULLUP_DISABLE`` , ``I2C_PULLUP_10kOhm``, or ``I2C_PULLUP_4_7kOhm``
   * 
   * @param id
   *        Command Id to identify the request. Values from 1 to 65535 are valid. 0 is reserved for notifications.
   *
   * @param bus
   *        I2C bus number (e.g., 0 for I2C_BUS_A). Valid values are defined in definitions.h (e.g., I2C_BUS_A, I2C_BUS_B).
   *
   * @param include10BitAddresses
   *        Indicates if the scan must include 10-bit addresses.
   *
   * @retval SUCCESS
   *         The command was successfully sent to the host adapter.
   * @retval SDK_ERROR_DISCONNECT
   *         The device was disconnected or became unavailable during the operation.
   */
  uint16_t i2cScanBus(uint16_t id, uint8_t bus, bool include10BitAddresses);

  /*****************************************************
   * @section I3C Interface
   ****************************************************/

  /**
   * @brief Set the I3C bus supply voltage (VTARG).
   * @ingroup CosmicAsyncSDK_Cpp_I3C
   *
   * @details
   * Configures the output voltage applied to the I3C bus through the Supernova VTARG pin.
   *
   * Setting the voltage to 0 mV disables the VTARG output and powers off the downstream devices
   * connected to the I3C bus.
   *
   * This function controls the physical bus supply and does not perform any I3C protocol
   * transaction.
   *
   * @note
   * - Ensure the selected voltage is compatible with all connected devices.
   * - Disabling VTARG (0 mV) may reset or power down all downstream targets.
   *
   * @param id
   *        Command Id to identify the request. Values from 1 to 65535 are valid. 0 is reserved for
   *        notifications.
   *
   * @param voltage_mV
   *        Voltage in millivolts to set the I3C bus to.
   *        Valid values are 0 mV or any value between 800 mV and 3300 mV.
   *
   * @retval SUCCESS
   *         The command was successfully sent to the host adapter.
   * @retval SDK_ERROR_DISCONNECT
   *         The device was disconnected or became unavailable during the operation.
   */
  uint16_t i3cSetBusVoltage(uint16_t id, uint16_t voltage_mV);

  /**
   * @brief Initializes the I3C controller
   * @ingroup CosmicAsyncSDK_Cpp_I3C
   *
   * @details
   * This function initializes the I3C peripheral and must be called successfully before any other
   * I3C-related API is used.
   *
   * @note
   * - This function must be called exactly once.
   * - To modify the I3C configuration after initialization, use @ref i3cSetParameters instead of
   * reinitializing the interface.
   *
   * @param id
   *        Command Id to identify the request. Values from 1 to 65535 are valid. 0 is reserved for
   *        notifications.
   *
   * @param pushPullFrequency
   *        The I3C SCL frequency in the push-pull phase.
   *        See @ref I3cPushPullRate for supported values.
   *
   * @param openDrainFrequency
   *        The I3C SCL frequency in the open-drain phase.
   *        See @ref I3cOpenDrainTransferRate for supported values.
   *
   * @param i2cOpenDrainFrequency
   *        The I2C SCL open drain frequency.
   *        See @ref I2cTransferRate for supported values.
   *
   * @param driveStrength
   *        The drive strength configuration for the I3C pads.
   *        See @ref I3cDriveStrength for supported values.
   *
   * @retval SUCCESS
   *         The command was successfully sent to the host adapter.
   * @retval SDK_ERROR_DISCONNECT
   *         The device was disconnected or became unavailable during the operation.
   */
  uint16_t i3cControllerInit(uint16_t id, uint8_t pushPullFrequency, uint8_t openDrainFrequency, uint8_t i2cOpenDrainFrequency, uint8_t driveStrength);

  /**
   * @brief Sets the I3C bus parameters.
   * @ingroup CosmicAsyncSDK_Cpp_I3C
   *
   * @details
   * This function updates the I3C bus parameters after the I3C interface has been successfully
   * initialized using @ref i3cControllerInit. It allows runtime reconfiguration of the I3C without
   * requiring a full deinitialization or reinitialization of the peripheral.
   *
   * @note
   * - This function must only be called after a successful call to @ref i3cControllerInit.
   * - Calling this function before UART initialization will result in
   * `FW_INTERFACE_NOT_INITIALIZED`.
   *
   * @param id
   *        Command Id to identify the request. Values from 1 to 65535 are valid. 0 is reserved for
   *        notifications.
   *
   * @param pushPullFrequency
   *        The I3C SCL frequency in the push-pull phase.
   *        See @ref I3cPushPullRate for supported values.
   *
   * @param openDrainFrequency
   *        The I3C SCL frequency in the open-drain phase.
   *        See @ref I3cOpenDrainTransferRate for supported values.
   *
   * @param i2cOpenDrainFrequency
   *        The I2C SCL open drain frequency.
   *        See @ref I2cTransferRate for supported values.
   *
   * @param driveStrength
   *        The drive strength configuration for the I3C pads.
   *        See @ref I3cDriveStrength for supported values.
   *
   * @retval SUCCESS
   *         The command was successfully sent to the host adapter.
   * @retval SDK_ERROR_DISCONNECT
   *         The device was disconnected or became unavailable during the operation.
   */
  uint16_t i3cSetParameters(uint16_t id, uint8_t pushPullFrequency, uint8_t openDrainFrequency, uint8_t i2cOpenDrainFrequency, uint8_t driveStrength);

  /**
   * @brief Initializes the I3C bus.
   * @ingroup CosmicAsyncSDK_Cpp_I3C
   *
   * @details
   * By default, the Supernova acting as the controller issues the RSTDAA followed by the ENTDAA
   * CCCs to discover I3C targets on the bus and automatically assign dynamic addresses.
   *
   * Optionally, a table of target devices can be provided to control the bus initialization
   * process. When the @p targets parameter is provided, the controller uses this information to:
   *  - Assign a specific dynamic address to a known I3C target.
   *  - Register legacy I2C devices on the bus, which do not respond to the ENTDAA CCC.
   *
   * This allows mixed I3C/I2C buses to be initialized correctly and enables deterministic dynamic
   * address assignment for selected targets.
   *
   * If @p targets is empty, the controller relies solely on the standard I3C discovery mechanism
   * (RSTDAA + ENTDAA) and only I3C targets responding to ENTDAA will be detected.
   *
   * @note
   * - This function must be called exactly once.
   * - To modify the I3C configuration after initialization, use @ref i3cSetParameters instead of
   * reinitializing the interface.
   *
   * @param id
   *        Command Id to identify the request. Values from 1 to 65535 are valid. 0 is reserved for
   *        notifications.
   *
   * @param targets
   *        A vector containing information about the target devices connected to the I3C bus.
   *        See @ref I3cTargetInfo for valid table entry format.
   *
   * @retval SUCCESS
   *         The command was successfully sent to the host adapter.
   * @retval SDK_ERROR_DISCONNECT
   *         The device was disconnected or became unavailable during the operation.
   */
  uint16_t i3cInitBus(uint16_t id, std::vector<I3cTargetInfo> targets = {});

  /**
   * @brief Resets the I3C bus.
   * @ingroup CosmicAsyncSDK_Cpp_I3C
   *
   * @details
   * Issue the RSTDAA CCC and clear the target device table.
   *
   * @param id
   *        Command Id to identify the request. Values from 1 to 65535 are valid. 0 is reserved for
   *        notifications.
   *
   * @retval SUCCESS
   *         The command was successfully sent to the host adapter.
   * @retval SDK_ERROR_DISCONNECT
   *         The device was disconnected or became unavailable during the operation.
   */
  uint16_t i3cResetBus(uint16_t id);

  /**
   * @brief Get the target device table stored internally in the Supernova.
   * @ingroup CosmicAsyncSDK_Cpp_I3C
   *
   * @details
   * Retrieves the current I3C target device table maintained internally by the Supernova firmware.
   *
   * The table contains information about the targets discovered or configured on the I3C bus, such
   * as dynamic address, static address (if available), PID (if retrieved), and other relevant
   * attributes.
   *
   * This function does not perform any bus transaction. It only queries the internal device table
   * maintained by the firmware.
   *
   * @note
   * - The returned table reflects the current internal state of the Supernova.
   * - The content of the table depends on previous operations such as ENTDAA, SETDASA, SETAASA,
   * GETPID, etc.
   *
   * @param id
   *        Command Id to identify the request. Values from 1 to 65535 are valid. 0 is reserved for
   *        notifications.
   *
   * @retval SUCCESS
   *         The command was successfully sent to the host adapter.
   * @retval SDK_ERROR_DISCONNECT
   *         The device was disconnected or became unavailable during the operation.
   */
  uint16_t i3cGetDeviceTable(uint16_t id);

  /**
   * @brief Changes de configuration of an I3C target given by a dictionary containing the new
   * target configuration.
   * @ingroup CosmicAsyncSDK_Cpp_I3C
   *
   * @details
   * Updates the configuration of a target device stored in the Supernova's internal I3C device
   * table.
   *
   * @note
   * - The target must exist in the internal device table prior to calling this function.
   *
   * @param id
   *        Command Id to identify the request. Values from 1 to 65535 are valid. 0 is reserved for
   *        notifications.
   *
   * @param address
   *        Target address whose configuration will be set.
   *
   * @param targetConfiguration
   *        A dictionary containing the new configuration.
   *
   * @retval SUCCESS
   *         The command was successfully sent to the host adapter.
   * @retval SDK_ERROR_DISCONNECT
   *         The device was disconnected or became unavailable during the operation.
   */
  uint16_t i3cSetTargetDeviceConfiguration(uint16_t id, uint8_t address, I3cTargetConfiguration targetConfiguration);

  /**
   * @brief Performs an I3C write using Legacy I2C mode.
   * @ingroup CosmicAsyncSDK_Cpp_I3C
   *
   * @details
   * Writes data to an I2C target using a Legacy I2C Private Transfer over the I3C bus. This
   * function issues a standard I2C write transaction (Legacy I2C mode), optionally including an
   * internal subaddress on the target device. The transfer may also begin with a broadcast address
   * (0x7E) if required by the higher-level protocol being implemented.
   *
   * @note
   * - This function is valid only when the host is initialized as an I3C controller with @ref
   * i3cControllerInit.
   *
   * @param id
   *        Command Id to identify the request. Values from 1 to 65535 are valid. 0 is reserved for
   *        notifications.
   *
   * @param address
   *        The static address of the I2C target.
   *
   * @param subAddress
   *        The optional sub-address to write to.
   *
   * @param inData
   *        The data to be written to the device.
   *
   * @param flags
   *        Bitmask of transfer options controlling the behavior of the I3C/I2C transaction. Flags
   *        can be combined using bitwise OR. See @ref I3cTransferFlags for supported values.
   *
   * @retval SUCCESS
   *         The command was successfully sent to the host adapter.
   * @retval SDK_ERROR_DISCONNECT
   *         The device was disconnected or became unavailable during the operation.
   */
  uint16_t i3cLegacyI2cWrite(uint16_t id, uint8_t address, const std::vector<uint8_t>& subAddress, const std::vector<uint8_t>& inData,
                             I3cTransferFlags flags);

  /**
   * @brief Performs an I3C read using Legacy I2C mode.
   * @ingroup CosmicAsyncSDK_Cpp_I3C
   *
   * @details
   * Reads data from an I2C target using a Legacy I2C Private Transfer over the I3C bus. This
   * function performs a standard I2C read operation (Legacy I2C mode). Optionally, a subaddress may
   * be written first to select a register or memory location prior to performing the read.
   *
   * @note
   * - This function is valid only when the host is initialized as an I3C controller with @ref
   * i3cControllerInit.
   *
   * @param id
   *        Command Id to identify the request. Values from 1 to 65535 are valid. 0 is reserved for
   *        notifications.
   *
   * @param address
   *        The static address of the I2C target.
   *
   * @param subAddress
   *        The optional sub-address to write to.
   *
   * @param readLength
   *        The length of data to be read.
   *
   * @param flags
   *        Bitmask of transfer options controlling the behavior of the I3C/I2C transaction. Flags
   *        can be combined using bitwise OR. See @ref I3cTransferFlags for supported values.
   *
   * @retval SUCCESS
   *         The command was successfully sent to the host adapter.
   * @retval SDK_ERROR_DISCONNECT
   *         The device was disconnected or became unavailable during the operation.
   */
  uint16_t i3cLegacyI2cRead(uint16_t id, uint8_t address, const std::vector<uint8_t>& subAddress, uint16_t readLength,
                            I3cTransferFlags flags);

  /**
   * @brief Performs an I3C write in SDR mode.
   * @ingroup CosmicAsyncSDK_Cpp_I3C
   *
   * @details
   * Writes data to an I3C device or to a group of I3C targets through an I3C Private Transfer in
   * SDR mode. Optionally, the internal subaddress of the target memory where the data is written to
   * can be set, especially when writing to a single target.
   *
   * @note
   * - This function is valid only when the host is initialized as an I3C controller with @ref
   * i3cControllerInit.
   *
   * @param id
   *        Command Id to identify the request. Values from 1 to 65535 are valid. 0 is reserved for
   *        notifications.
   *
   * @param address
   *        The dynamic address of the I3C target, or the group address.
   *
   * @param subAddress
   *        The optional sub-address to write to.
   *
   * @param inData
   *        The data to be written to the device.
   *
   * @param flags
   *        Bitmask of transfer options controlling the behavior of the I3C/I2C transaction. Flags
   *        can be combined using bitwise OR. See @ref I3cTransferFlags for supported values.
   *
   * @retval SUCCESS
   *         The command was successfully sent to the host adapter.
   * @retval SDK_ERROR_DISCONNECT
   *         The device was disconnected or became unavailable during the operation.
   */
  uint16_t i3cSdrWrite(uint16_t id, uint8_t address, const std::vector<uint8_t>& subAddress, const std::vector<uint8_t>& inData,
                       I3cTransferFlags flags);

  /**
   * @brief Performs an I3C read in SDR mode.
   * @ingroup CosmicAsyncSDK_Cpp_I3C
   *
   * @details
   * Reads data from an I3C target through an I3C Private Read transfer in SDR mode. Optionally, the
   * internal subaddress of the target where the data is read from can be also set.
   *
   * @note
   * - This function is valid only when the host is initialized as an I3C controller with @ref
   * i3cControllerInit.
   *
   * @param id
   *        Command Id to identify the request. Values from 1 to 65535 are valid. 0 is reserved for
   *        notifications.
   *
   * @param address
   *        The dynamic address of the I3C target.
   *
   * @param subAddress
   *        The optional sub-address to write to.
   *
   * @param readLength
   *        The length of data to be read.
   *
   * @param flags
   *        Bitmask of transfer options controlling the behavior of the I3C/I2C transaction. Flags
   *        can be combined using bitwise OR. See @ref I3cTransferFlags for supported values.
   *
   * @retval SUCCESS
   *         The command was successfully sent to the host adapter.
   * @retval SDK_ERROR_DISCONNECT
   *         The device was disconnected or became unavailable during the operation.
   */
  uint16_t i3cSdrRead(uint16_t id, uint8_t address, const std::vector<uint8_t>& subAddress, uint16_t readLength,
                      I3cTransferFlags flags);

  /**
   * @brief Performs an I3C write in HDR-DDR mode.
   * @ingroup CosmicAsyncSDK_Cpp_I3C
   *
   * @details
   * Writes data to an I3C target using an HDR-DDR Private Transfer. If the bus is currently
   * operating in SDR mode, this function will automatically issue the ENTHDR0 CCC before starting
   * the HDR-DDR transfer.
   *
   * @note
   * - This function is valid only when the host is initialized as an I3C controller with @ref
   * i3cControllerInit.
   *
   * @param id
   *        Command Id to identify the request. Values from 1 to 65535 are valid. 0 is reserved for
   *        notifications.
   *
   * @param address
   *        The dynamic address of the I3C target.
   *
   * @param command
   *        The HDR-DDR command byte. Must be in the range [0x00, 0x7F].
   *
   * @param inData
   *        The data payload to be written. The payload length must be a multiple of 2.
   *
   * @retval SUCCESS
   *         The command was successfully sent to the host adapter.
   * @retval SDK_ERROR_DISCONNECT
   *         The device was disconnected or became unavailable during the operation.
   */
  uint16_t i3cHdrDdrWrite(uint16_t id, uint8_t address, uint8_t command, const std::vector<uint8_t>& inData);

  /**
   * @brief Performs an I3C read in HDR-DDR mode.
   * @ingroup CosmicAsyncSDK_Cpp_I3C
   *
   * @details
   * Reads data from an I3C target using an HDR-DDR Private Read Transfer. If the bus is currently
   * operating in SDR mode, this function will automatically issue the ENTHDR0 CCC before starting
   * the HDR-DDR transfer.
   *
   * @note
   * - This function is valid only when the host is initialized as an I3C controller with @ref
   * i3cControllerInit.
   *
   * @param id
   *        Command Id to identify the request. Values from 1 to 65535 are valid. 0 is reserved for
   *        notifications.
   *
   * @param address
   *        The dynamic address of the I3C target.
   *
   * @param command
   *        The HDR-DDR command byte. Must be in the range [0x80, 0xFF].
   *
   * @param readLength
   *        The length of the data to read. Must be a multiple of 2.
   *
   * @retval SUCCESS
   *         The command was successfully sent to the host adapter.
   * @retval SDK_ERROR_DISCONNECT
   *         The device was disconnected or became unavailable during the operation.
   */
  uint16_t i3cHdrDdrRead(uint16_t id, uint8_t address, uint8_t command, uint16_t readLength);

  /**
   * @brief Emit the Target Reset Pattern to trigger the default or configured reset action on the
   * I3C targets.
   * @ingroup CosmicAsyncSDK_Cpp_I3C
   *
   * @details
   * Emits the I3C Target Reset Pattern on the bus.
   *
   * All targets that recognize the Target Reset Pattern and support reset functionality will
   * perform the corresponding reset action.
   *
   * @note
   * - This function is valid only when the host is initialized as an I3C controller with @ref
   * i3cControllerInit.
   * - The reset action executed depends on the most recent RSTACT configuration, or the default
   * reset behavior if none was configured.
   *
   * @param id
   *        Command Id to identify the request. Values from 1 to 65535 are valid. 0 is reserved for
   *        notifications.
   *
   * @retval SUCCESS
   *         The command was successfully sent to the host adapter.
   * @retval SDK_ERROR_DISCONNECT
   *         The device was disconnected or became unavailable during the operation.
   */
  uint16_t i3cTargetResetPattern(uint16_t id);

  /**
   * @brief Issue the HDR Exit Pattern to leave the current HDR mode and exit back to SDR mode.
   * @ingroup CosmicAsyncSDK_Cpp_I3C
   *
   * @details
   * Emits the I3C HDR Exit Pattern on the bus.
   *
   * This pattern terminates the current High Data Rate (HDR) mode and forces all participating
   * devices to return to Standard Data Rate (SDR) mode, as defined by the I3C specification.
   *
   * @note
   * - This function is valid only when the host is initialized as an I3C controller with @ref
   * i3cControllerInit.
   * - It must be issued while the bus is operating in HDR mode.
   *
   * @param id
   *        Command Id to identify the request. Values from 1 to 65535 are valid. 0 is reserved for
   *        notifications.
   *
   * @retval SUCCESS
   *         The command was successfully sent to the host adapter.
   * @retval SDK_ERROR_DISCONNECT
   *         The device was disconnected or became unavailable during the operation.
   */
  uint16_t i3cHdrExitPattern(uint16_t id);

  /**
   * @brief Perform a CCC transfer.
   * @ingroup CosmicAsyncSDK_Cpp_I3C
   *
   * @details
   * Sends a Common Command Code (CCC) to one or more I3C targets.
   *
   * @param id
   *        Command Id to identify the request. Values from 1 to 65535 are valid. 0 is reserved for
   *        notifications.
   *
   * @param address
   *        Target dynamic address on the I3C bus.
   *
   * @param direction
   *        Data transfer direction (read or write).
   *        See @ref I3cTransferDirection for supported values.
   *
   * @param mode
   *        I3C transfer mode used for the transaction.
   *        See @ref I3cTransferMode for supported values.
   *
   * @param nonStop
   *        If true, the transfer will not issue a STOP condition after completion.
   *
   * @param type
   *        Type of CCC command, indicating whether a defining byte is used.
   *        See @ref I3cCccType for supported values.
   *
   * @param payloadLength
   *        Length in bytes of the CCC payload.
   *
   * @param ccc
   *        The specific CCC to send to the target.
   *        See @ref CCC for supported values.
   *
   * @param definingByte
   *        Optional defining byte associated with the CCC, if required by the command type.
   *
   * @param inData
   *        The data to be transferred for write transfers.
   *
   * @retval SUCCESS
   *         The command was successfully sent to the host adapter.
   * @retval SDK_ERROR_DISCONNECT
   *         The device was disconnected or became unavailable during the operation.
   */
  uint16_t i3cCccTransfer(uint16_t id, uint8_t address, I3cTransferDirection direction,
                          I3cTransferMode mode, bool nonStop, I3cCccType type,
                          uint8_t payloadLength, CCC ccc, uint8_t definingByte,
                          const std::vector<uint8_t>& inData = std::vector<uint8_t>{});

  /*****************************************************
   * @section UART Interface
   ****************************************************/

  /**
   * @brief Set the operating voltage of the UART interface.
   * @warning On Supernova and Pulsar host adapters, the UART interface shares the same voltage domain as I2C, SPI and GPIOs.
   * As a result, calling this method to set the UART voltage will also affect the voltage of I2C, SPI and GPIO interfaces.
   * This must be taken into account when more than one interface is used simultaneously.
   * @ingroup CosmicAsyncSDK_Cpp_UART
   *
   * @param id uint16_t Command Id to identify the request. Values from 1 to 65535 are valid. 0 is reserved for notifications.
   * @param voltage_mV uint16_t Voltage in millivolts to set the UART interface to. The valid values are 0 mV, and any value in the range 1200 to 3300 mV.
   * The value 0mV deactivates the VTARG pin and turn offs the downstream devices.
   * @param persist bool If true, the voltage setting will be persistent across power cycles. This ensures that any DUT
   * connected to the UART interface (e.g. via Pulsar or Supernova) will receive power immediately upon startup, without
   * waiting for the host to issue the voltage set command. If false, the setting will only apply to the current session.
   * @return uint16_t Result of the request.
   */
  uint16_t uartSetBusVoltage(uint16_t id, uint16_t voltage_mV, bool persist = false);

  /**
   * @brief Initialize the UART interface.
   * @ingroup CosmicAsyncSDK_Cpp_UART
   *
   * @details
   * This function initializes the UART peripheral and must be called
   * successfully before any other UART-related API is used.
   *
   * @note
   * - This function must be called exactly once.
   * - To modify the UART configuration after initialization, use
   * @ref uartSetParameters instead of reinitializing the interface.
   *
   * @param id
   *        Command Id to identify the request. Values from 1 to 65535 are valid.
   *        0 is reserved for notifications.
   *
   * @param baudrate
   *        UART baud rate used for both transmission (TX) and reception (RX).
   *        See @ref UartBaudRate for supported values.
   *
   * @param hardwareHandshake
   *        Enables or disables hardware flow control (RTS/CTS), if supported
   *        by the underlying hardware.
   *        See @ref UartHwHandshake for supported values.
   *
   * @param parityMode
   *        UART parity configuration.
   *        See @ref UartParity for supported values.
   *
   * @param dataSize
   *        Number of data bits per UART frame.
   *        See @ref UartDataSize for supported values.
   *
   * @param stopBit
   *        Number of stop bits per UART frame.
   *        See @ref UartStopBit for supported values.
   *
   * @retval SUCCESS
   *         The command was successfully sent to the host adapter.
   * @retval SDK_ERROR_DISCONNECT
   *         The device was disconnected or became unavailable during the operation.
   */
  uint16_t uartInit(uint16_t id, UartBaudRate baudrate, UartHwHandshake hardwareHandshake, UartParity parityMode, UartDataSize dataSize, UartStopBit stopBit);

  /**
   * @brief Configure UART peripheral communication parameters.
   * @ingroup CosmicAsyncSDK_Cpp_UART
   *
   * @details
   * This function updates the UART communication parameters after the UART
   * interface has been successfully initialized using @ref uartInit.
   * It allows runtime reconfiguration of the UART without requiring a full
   * deinitialization or reinitialization of the peripheral.
   *
   * @note
   * - This function must only be called after a successful call to @ref uartInit.
   *
   * @param id
   *        Command Id to identify the request. Values from 1 to 65535 are valid.
   *        0 is reserved for notifications.
   *
   * @param baudrate
   *        UART baud rate used for both transmission (TX) and reception (RX).
   *        See @ref UartBaudRate for supported values.
   *
   * @param hardwareHandshake
   *        Enables or disables hardware flow control (RTS/CTS), if supported
   *        by the underlying hardware.
   *        See @ref UartHwHandshake for supported values.
   *
   * @param parityMode
   *        UART parity configuration.
   *        See @ref UartParity for supported values.
   *
   * @param dataSize
   *        Number of data bits per UART frame.
   *        See @ref UartDataSize for supported values.
   *
   * @param stopBit
   *        Number of stop bits per UART frame.
   *        See @ref UartStopBit for supported values.
   *
   * @retval SUCCESS
   *         The command was successfully sent to the host adapter.
   * @retval SDK_ERROR_DISCONNECT
   *         The device was disconnected or became unavailable during the operation.
   */
  uint16_t uartSetParameters(uint16_t id, UartBaudRate baudrate, UartHwHandshake hardwareHandshake, UartParity parityMode, UartDataSize dataSize, UartStopBit stopBit);

  /**
   * @brief Transmit a UART message through the host adapter device.
   * @ingroup CosmicAsyncSDK_Cpp_UART
   *
   * @details
   * Requests the host adapter to send data using the currently active
   * UART configuration (see @ref uartInit and @ref uartSetParameters).
   *
   * @note
   * - The UART interface must be successfully initialized with @ref uartInit
   *   before calling this function.
   *
   * @param id
   *        Command Id to identify the request. Values from 1 to 65535 are valid.
   *        0 is reserved for notifications.
   *
   * @param inData
   *        Reference to the vector containing the bytes to transmit.
   *
   * @retval SUCCESS
   *         The command was successfully sent to the host adapter.
   * @retval SDK_ERROR_DISCONNECT
   *         The device was disconnected or became unavailable during the operation.
   */
  uint16_t uartSendMessage(uint16_t id, const std::vector<uint8_t>& inData);

  /*****************************************************
   * @section GPIO Interface
   ****************************************************/

  /**
   * @brief Set the operating voltage of the GPIO pins.
   * @warning On Supernova and Pulsar host adapters, the GPIO interface shares the same voltage domain as I2C, SPI and UART.
   * As a result, calling this method to set the GPIOs voltage will also affect the voltage of I2C, SPI and UART interfaces.
   * This must be taken into account when more than one interfaces are used simultaneously.
   * @ingroup CosmicAsyncSDK_Cpp_GPIO
   *
   * @param id uint16_t Command Id to identify the request. Values from 1 to 65535 are valid. 0 is reserved for notifications.
   * @param voltage_mV uint16_t Voltage in millivolts to set the GPIO pins to. The valid values are 0 mV, and any value in the range 1200 to 3300 mV.
   * The value 0mV deactivates the VTARG pin and turn offs the downstream devices.
   * @param persist bool If true, the voltage setting will be persistent across power cycles. This ensures that any DUT
   * connected to the GPIO pins (e.g. via Pulsar or Supernova) will receive power immediately upon startup, without
   * waiting for the host to issue the voltage set command. If false, the setting will only apply to the current session.
   * @return uint16_t Result of the request.
   */
  uint16_t gpioSetVoltage(uint16_t id, uint16_t voltage_mV, bool persist = false);

  /**
   * @brief Configures a GPIO pin with the specified functionality.
   * @ingroup CosmicAsyncSDK_Cpp_GPIO
   *
   * @details
   * Sends a request to configure a single GPIO pin as a digital input or output.
   *
   * @note
   * - This function must be called before any other GPIO operation on the pin.
   * - When @p functionality is `GPIO_DIGITAL_INPUT`, @p initialOutputLogicLevel is ignored.
   * - The host adapter response may return `FW_INVALID_PARAMETER` if the pin number or functionality is invalid.
   * - This function only reports whether the command was sent; check the response for the operation result.
   *
   * @param id
   *        Command Id to identify the request. Values from 1 to 65535 are valid.
   *        0 is reserved for notifications.
   * @param pinNumber
   *        The GPIO pin number to configure. See @ref GpioPinNumber.
   * @param functionality
   *        The desired functionality for the GPIO pin. See @ref GpioFunctionality.
   * @param initialOutputLogicLevel
   *        Initial output logic level applied when configuring as a digital output.
   *        See @ref GpioLogicLevel for valid values.
   *        This parameter is ignored when configuring as a digital input.
   *
   * @retval SUCCESS
   *         The command was successfully sent to the host adapter.
   * @retval SDK_ERROR_DISCONNECT
   *         The device was disconnected or became unavailable during the operation.
   */
  uint16_t gpioConfigurePin(uint16_t id, GpioPinNumber pinNumber, GpioFunctionality functionality, GpioLogicLevel initialOutputLogicLevel);

  /**
   * @brief Writes a digital logic level to a GPIO pin.
   * @ingroup CosmicAsyncSDK_Cpp_GPIO
   *
   * @details
   * Sends a request to write the provided logic level to a pin configured
   * as a digital output.
   *
   * @note
   * - The pin must be configured as `GPIO_DIGITAL_OUTPUT` using @ref gpioConfigurePin.
   * - If the pin is not configured, the host adapter response returns `FW_GPIO_NOT_CONFIGURED`.
   * - If the pin is configured as a digital input, the host adapter response returns `FW_GPIO_WRONG_CONFIGURATION`.
   * - The host adapter response may return `FW_INVALID_PARAMETER` if the pin number is invalid.
   * - This function only reports whether the command was sent; check the response for the operation result.
   *
   * @param id
   *        Command Id to identify the request. Values from 1 to 65535 are valid.
   *        0 is reserved for notifications.
   * @param pinNumber
   *        The GPIO pin number to write to. See @ref GpioPinNumber.
   * @param logicLevel
   *        The logic level to write to the GPIO pin. See @ref GpioLogicLevel.
   *
   * @retval SUCCESS
   *         The command was successfully sent to the host adapter.
   * @retval SDK_ERROR_DISCONNECT
   *         The device was disconnected or became unavailable during the operation.
   */
  uint16_t gpioDigitalWrite(uint16_t id, GpioPinNumber pinNumber, GpioLogicLevel logicLevel);

  /**
   * @brief Reads the digital logic level from a GPIO pin.
   * @ingroup CosmicAsyncSDK_Cpp_GPIO
   *
   * @details
   * Sends a request to read the logic level from a pin configured
   * as a digital input. The logic level is returned in the corresponding
   * response payload.
   *
   * @note
   * - The pin must be configured as `GPIO_DIGITAL_INPUT` using @ref gpioConfigurePin.
   * - If the pin is not configured, the host adapter response returns `FW_GPIO_NOT_CONFIGURED`.
   * - If the pin is configured as a digital output, the host adapter response returns `FW_GPIO_WRONG_CONFIGURATION`.
   * - The host adapter response may return `FW_INVALID_PARAMETER` if the pin number is invalid.
   * - This function only reports whether the command was sent; check the response for the operation result.
   *
   * @param id
   *        Command Id to identify the request. Values from 1 to 65535 are valid.
   *        0 is reserved for notifications.
   * @param pinNumber
   *        The GPIO pin number to read from. See @ref GpioPinNumber.
   *
   * @retval SUCCESS
   *         The command was successfully sent to the host adapter.
   * @retval SDK_ERROR_DISCONNECT
   *         The device was disconnected or became unavailable during the operation.
   */
  uint16_t gpioDigitalRead(uint16_t id, GpioPinNumber pinNumber);

  /**
   * @brief Configures and enables interrupts in a GPIO pin.
   * @ingroup CosmicAsyncSDK_Cpp_GPIO
   *
   * @details
   * Sends a request to configure the interrupt trigger for a GPIO pin and
   * enable its callback.
   *
   * @note
   * - The pin must be configured as `GPIO_DIGITAL_INPUT` using @ref gpioConfigurePin.
   * - If the pin is not configured, the host adapter response returns `FW_GPIO_NOT_CONFIGURED`.
   * - If the pin is configured as a digital output, the host adapter response returns `FW_GPIO_WRONG_CONFIGURATION`.
   * - If the pin does not support interrupts, the host adapter response returns `FW_FEATURE_NOT_SUPPORTED_BY_HARDWARE`.
   * - The host adapter response may return `FW_INVALID_PARAMETER` if the pin number or trigger is invalid.
   * - This function only reports whether the command was sent; check the response for the operation result.
   *
   * @param id
   *        Command Id to identify the request. Values from 1 to 65535 are valid.
   *        0 is reserved for notifications.
   * @param pinNumber
   *        The GPIO pin number to configure interrupts for. See @ref GpioPinNumber.
   * @param trigger
   *        The trigger type used for the interruption. See @ref GpioTriggerType.
   *
   * @retval SUCCESS
   *         The command was successfully sent to the host adapter.
   * @retval SDK_ERROR_DISCONNECT
   *         The device was disconnected or became unavailable during the operation.
   */
  uint16_t gpioConfigureInterrupt(uint16_t id, GpioPinNumber pinNumber, GpioTriggerType trigger);

  /**
   * @brief Disables interruptions of a GPIO pin.
   * @ingroup CosmicAsyncSDK_Cpp_GPIO
   *
   * @details
   * Sends a request to disable interrupts for a GPIO pin configured as
   * a digital input.
   *
   * @note
   * - The pin must be configured as `GPIO_DIGITAL_INPUT` using @ref gpioConfigurePin.
   * - If the pin is not configured, the host adapter response returns `FW_GPIO_NOT_CONFIGURED`.
   * - If the pin is configured as a digital output, the host adapter response returns `FW_GPIO_WRONG_CONFIGURATION`.
   * - The host adapter response may return `FW_INVALID_PARAMETER` if the pin number is invalid.
   * - This function only reports whether the command was sent; check the response for the operation result.
   *
   * @param id
   *        Command Id to identify the request. Values from 1 to 65535 are valid.
   *        0 is reserved for notifications.
   * @param pinNumber
   *        The GPIO pin number to which the interrupt will be disabled. See @ref GpioPinNumber.
   *
   * @retval SUCCESS
   *         The command was successfully sent to the host adapter.
   * @retval SDK_ERROR_DISCONNECT
   *         The device was disconnected or became unavailable during the operation.
   */
  uint16_t gpioDisableInterrupt(uint16_t id, GpioPinNumber pinNumber);

  /*****************************************************
   * @section SPI Interface
   ****************************************************/

  /**
   * @brief Set the operating voltage of the SPI bus.
   * @warning On Supernova and Pulsar host adapters, the SPI interface shares the same voltage domain as I2C, UART and GPIOs.
   * As a result, calling this method to set the SPI voltage will also affect the voltage of I2C, UART and GPIO interfaces.
   * This must be taken into account when more than one interface is used simultaneously.
   * @ingroup CosmicAsyncSDK_Cpp_SPI
   *
   * @param id uint16_t Command Id to identify the request. Values from 1 to 65535 are valid. 0 is reserved for notifications.
   * @param voltage_mV uint16_t Voltage in millivolts to set the SPI bus to. The valid values are 0 mV, and any value in the range 1200 to 3300 mV.
   * The value 0mV deactivates the VTARG pin and turn offs the downstream devices.
   * @param persist bool If true, the voltage setting will be persistent across power cycles. This ensures that any DUT
   * connected to the SPI bus (e.g. via Pulsar or Supernova) will receive power immediately upon startup, without
   * waiting for the host to issue the voltage set command. If false, the setting will only apply to the current session.
   * @return uint16_t Result of the request.
   */
  uint16_t spiSetBusVoltage(uint16_t id, uint16_t voltage_mV, bool persist = false);

  /**
   * @brief Initializes the SPI controller
   * @ingroup CosmicAsyncSDK_Cpp_SPI
   *
   * @details
   * This function initializes the SPI peripheral and must be called
   * successfully before any other SPI-related API is used.
   *
   * @note
   * - This function must be called exactly once.
   * - Calling any SPI API before initialization will result in `FW_INTERFACE_NOT_INITIALIZED`.
   * - Calling this function more than once will result in `FW_INTERFACE_ALREADY_INITIALIZED`.
   * - To modify the SPI configuration after initialization, use
   * @ref spiSetParameters instead of reinitializing the interface.
   *
   * @param id
   *        Command Id to identify the request. Values from 1 to 65535 are valid.
   *        0 is reserved for notifications.
   *
   * @param bitOrder
   *        Bit transmission order (MSB-first or LSB-first).
   *        See @ref SpiBitOrder for supported values.
   *
   * @param mode
   *        SPI clock mode (CPOL/CPHA configuration).
   *        See @ref SpiMode for supported values.
   *
   * @param dataWidth
   *        Width of a single SPI data frame, in bits.
   *        See @ref SpiDataWidth for supported values.
   *
   * @param chipSelect
   *        Chip select line to be used by the controller.
   *        See @ref SpiChipSelect for supported values.
   *
   * @param chipSelectPol
   *        Polarity of the chip select signal (active high or low).
   *        See @ref SpiChipSelectPolarity for supported values.
   *
   * @param frequency
   *        SPI clock frequency in Hertz. Valid range: 10000 (10 kHz) to 50000000 (50 MHz).
   *        The maximum frequency may vary depending on the USB host device model and hardware revision.
   *
   * @retval SUCCESS
   *         The command was successfully sent to the host adapter.
   * @retval SDK_ERROR_DISCONNECT
   *         The device was disconnected or became unavailable during the operation.
   */
  uint16_t spiControllerInit(uint16_t id, SpiBitOrder bitOrder, SpiMode mode,
                             SpiDataWidth dataWidth, SpiChipSelect chipSelect,
                             SpiChipSelectPolarity chipSelectPol, uint32_t frequency);

  /**
   * @brief Sets the SPI bus parameters
   * @ingroup CosmicAsyncSDK_Cpp_SPI
   *
   * This function updates the SPI bus parameters after the SPI interface has been
   * successfully initialized using @ref spiControllerInit.
   * It allows runtime reconfiguration of the SPI without requiring a full
   * deinitialization or reinitialization of the peripheral.
   *
   * @note
   * - This function must only be called after a successful call to @ref spiControllerInit.
   * - Calling this function before UART initialization will result in `FW_INTERFACE_NOT_INITIALIZED`.
   *
   * @param id
   *        Command Id to identify the request. Values from 1 to 65535 are valid.
   *        0 is reserved for notifications.
   *
   * @param bitOrder
   *        Bit transmission order (MSB-first or LSB-first).
   *        See @ref SpiBitOrder for supported values.
   *
   * @param mode
   *        SPI clock mode (CPOL/CPHA configuration).
   *        See @ref SpiMode for supported values.
   *
   * @param dataWidth
   *        Width of a single SPI data frame, in bits.
   *        See @ref SpiDataWidth for supported values.
   *
   * @param chipSelect
   *        Chip select line to be used by the controller.
   *        See @ref SpiChipSelect for supported values.
   *
   * @param chipSelectPol
   *        Polarity of the chip select signal (active high or low).
   *        See @ref SpiChipSelectPolarity for supported values.
   *
   * @param frequency
   *        SPI clock frequency in Hertz. Valid range: 10000 (10 kHz) to 50000000 (50 MHz).
   *        The maximum frequency may vary depending on the USB host device model and hardware revision.
   *
   * @retval SUCCESS
   *         The command was successfully sent to the host adapter.
   * @retval SDK_ERROR_DISCONNECT
   *         The device was disconnected or became unavailable during the operation.
   */
  uint16_t spiSetParameters(uint16_t id, SpiBitOrder bitOrder, SpiMode mode,
                            SpiDataWidth dataWidth, SpiChipSelect chipSelect,
                            SpiChipSelectPolarity chipSelectPol, uint32_t frequency);

  /**
   * @brief Performs a SPI transfer
   * @ingroup CosmicAsyncSDK_Cpp_SPI
   *
   * @details
   * Requests the host adapter to send data using the currently active
   * SPI configuration (see @ref spiControllerInit and @ref spiSetParameters).
   *
   * @note
   * - The SPI interface must be successfully initialized with @ref spiControllerInit
   *   before calling this function.
   * - If the UART interface is not initialized, this function returns `FW_INTERFACE_NOT_INITIALIZED`.
   *
   * @param id
   *        Command Id to identify the request. Values from 1 to 65535 are valid.
   *        0 is reserved for notifications.
   *
   * @param inData
   *        Buffer containing the data to be transmitted over SPI MOSI pin.
   *
   * @param transferLength
   *        Total length of the transfer in terms of frames or data units.
   *        Typically, the frame size is 8 bits, or in other words, 1 byte.
   *        It is worth mentioning that the @p transferLength can be equal or
   *        greater than the length of the @p inData buffer.
   *
   * @retval SUCCESS
   *         The command was successfully sent to the host adapter.
   * @retval SDK_ERROR_DISCONNECT
   *         The device was disconnected or became unavailable during the operation.
   */
  uint16_t spiTransfer(uint16_t id, std::vector<uint8_t>& inData, uint16_t transferLength);

#ifdef __wasm__
  /**
   * @brief Connects in WASM mode with a known endpoint size.
   * Bypasses enumeration — JS host has already opened the device via WebHID.
   * @param endpointSize The endpoint size (64 for Supernova, 1024 for Pulsar).
   * @return true if the connection was successful, false otherwise.
   */
  bool connectWasm(uint16_t endpointSize);

  /**
   * @brief Returns a callable that invokes the driver's pollOnce().
   * Used to wire polling through to BlockingApi in WASM mode.
   */
  std::function<void()> getPollFunction() { return communicationManager->getPollFunction(); }

  /**
   * @brief Pushes a raw HID input report into the SDK's response pipeline (WASM only).
   * In native builds, input reports are read by the polling thread. In pure WASM,
   * the JS host pushes reports directly via this method.
   * @param report The raw HID input report bytes.
   */
  void processInputReport(const std::vector<uint8_t>& report);

  /**
   * @brief Returns a pointer to the underlying CosmicDriver (WASM only).
   * Used by the WASM C API to set the endpoint size after connection.
   */
  CosmicDriver* getDriver();
#endif

private:
  /// Unique pointer to the CommunicationManager
  std::unique_ptr<CommunicationManager> communicationManager;

  /// Track if the device is connected
  bool connected;

  /// Method to set voltage for I2C, GPIO, SPI and UART protocols
  uint16_t setI2cSpiUartGpioVoltage(uint16_t id, uint16_t voltage_mV, bool persist);
};

/** @} */  // end of CosmicAsyncSDK_Cpp
