/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : hal_eth.c
  * @brief          : Hardware Abstraction Layer Ethernet interface implementation
  ******************************************************************************
  */
/* USER CODE END Header */

#include "hal_eth.h"

/* Architecture specific header */
#if HAL_TARGET_ARCH == HAL_ARCH_STM32F4
#include "arch/stm32f4/hal_stm32f4_eth.h"
#endif

/**
 * @brief Default Ethernet configuration
 */
static const hal_eth_config_t hal_eth_default_config = {
    .enable = 1,
    .instance = HAL_ETH_INSTANCE_1,
    .mode = HAL_ETH_MODE_FULLDUPLEX,
    .speed = HAL_ETH_SPEED_100MBPS,
    .phy_addr = 0,
    .mac_addr = {
        .byte = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55}
    },
    .auto_negotiation = 1,
    .interrupt_enable = 1
};

/**
 * @brief Ethernet instance handle
 */
static struct {
    hal_eth_config_t config;
    uint8_t initialized;
} hal_eth_instances[HAL_ETH_INSTANCE_MAX];

/**
 * @brief Initialize Ethernet module
 * @param config: Pointer to Ethernet configuration structure
 * @retval HAL status code
 */
hal_ret_t hal_eth_init(const hal_eth_config_t* config)
{
    if (!config) {
        return HAL_RET_INVALID_PARAM;
    }

    hal_eth_instance_t instance = config->instance;
    if (instance >= HAL_ETH_INSTANCE_MAX) {
        return HAL_RET_INVALID_PARAM;
    }

    /* Store configuration */
    hal_eth_instances[instance].config = *config;

    /* Call architecture specific initialization */
#if HAL_TARGET_ARCH == HAL_ARCH_STM32F4
    if (hal_stm32f4_eth_init(config) != HAL_RET_OK) {
        return HAL_RET_INIT_ERROR;
    }
#else
    return HAL_RET_NOT_SUPPORTED;
#endif

    hal_eth_instances[instance].initialized = 1;
    return HAL_RET_OK;
}

/**
 * @brief Deinitialize Ethernet module
 * @param instance: Ethernet instance
 * @retval HAL status code
 */
hal_ret_t hal_eth_deinit(hal_eth_instance_t instance)
{
    if (instance >= HAL_ETH_INSTANCE_MAX) {
        return HAL_RET_INVALID_PARAM;
    }

    if (!hal_eth_instances[instance].initialized) {
        return HAL_RET_OK;
    }

    /* Call architecture specific deinitialization */
#if HAL_TARGET_ARCH == HAL_ARCH_STM32F4
    if (hal_stm32f4_eth_deinit(instance) != HAL_RET_OK) {
        return HAL_RET_DEINIT_ERROR;
    }
#else
    return HAL_RET_NOT_SUPPORTED;
#endif

    hal_eth_instances[instance].initialized = 0;
    return HAL_RET_OK;
}

/**
 * @brief Get Ethernet status
 * @param instance: Ethernet instance
 * @param status: Pointer to Ethernet status structure
 * @retval HAL status code
 */
hal_ret_t hal_eth_get_status(hal_eth_instance_t instance, hal_eth_status_t* status)
{
    if (instance >= HAL_ETH_INSTANCE_MAX || !status) {
        return HAL_RET_INVALID_PARAM;
    }

    if (!hal_eth_instances[instance].initialized) {
        return HAL_RET_INIT_ERROR;
    }

    /* Call architecture specific implementation */
#if HAL_TARGET_ARCH == HAL_ARCH_STM32F4
    return hal_stm32f4_eth_get_status(instance, status);
#else
    return HAL_RET_NOT_SUPPORTED;
#endif
}

/**
 * @brief Set Ethernet MAC address
 * @param instance: Ethernet instance
 * @param mac_addr: Pointer to MAC address structure
 * @retval HAL status code
 */
hal_ret_t hal_eth_set_mac_addr(hal_eth_instance_t instance, const hal_eth_mac_addr_t* mac_addr)
{
    if (instance >= HAL_ETH_INSTANCE_MAX || !mac_addr) {
        return HAL_RET_INVALID_PARAM;
    }

    if (!hal_eth_instances[instance].initialized) {
        return HAL_RET_INIT_ERROR;
    }

    /* Call architecture specific implementation */
#if HAL_TARGET_ARCH == HAL_ARCH_STM32F4
    return hal_stm32f4_eth_set_mac_addr(instance, mac_addr);
#else
    return HAL_RET_NOT_SUPPORTED;
#endif
}

/**
 * @brief Get Ethernet MAC address
 * @param instance: Ethernet instance
 * @param mac_addr: Pointer to MAC address structure
 * @retval HAL status code
 */
hal_ret_t hal_eth_get_mac_addr(hal_eth_instance_t instance, hal_eth_mac_addr_t* mac_addr)
{
    if (instance >= HAL_ETH_INSTANCE_MAX || !mac_addr) {
        return HAL_RET_INVALID_PARAM;
    }

    if (!hal_eth_instances[instance].initialized) {
        return HAL_RET_INIT_ERROR;
    }

    /* Call architecture specific implementation */
#if HAL_TARGET_ARCH == HAL_ARCH_STM32F4
    return hal_stm32f4_eth_get_mac_addr(instance, mac_addr);
#else
    return HAL_RET_NOT_SUPPORTED;
#endif
}

/**
 * @brief Check Ethernet link status
 * @param instance: Ethernet instance
 * @param link_up: Pointer to store link up status
 * @retval HAL status code
 */
hal_ret_t hal_eth_check_link(hal_eth_instance_t instance, uint8_t* link_up)
{
    if (instance >= HAL_ETH_INSTANCE_MAX || !link_up) {
        return HAL_RET_INVALID_PARAM;
    }

    if (!hal_eth_instances[instance].initialized) {
        return HAL_RET_INIT_ERROR;
    }

    /* Call architecture specific implementation */
#if HAL_TARGET_ARCH == HAL_ARCH_STM32F4
    return hal_stm32f4_eth_check_link(instance, link_up);
#else
    return HAL_RET_NOT_SUPPORTED;
#endif
}

/**
 * @brief Reset Ethernet PHY
 * @param instance: Ethernet instance
 * @param phy_addr: PHY address
 * @retval HAL status code
 */
hal_ret_t hal_eth_reset_phy(hal_eth_instance_t instance, hal_eth_phy_addr_t phy_addr)
{
    if (instance >= HAL_ETH_INSTANCE_MAX) {
        return HAL_RET_INVALID_PARAM;
    }

    if (!hal_eth_instances[instance].initialized) {
        return HAL_RET_INIT_ERROR;
    }

    /* Call architecture specific implementation */
#if HAL_TARGET_ARCH == HAL_ARCH_STM32F4
    return hal_stm32f4_eth_reset_phy(instance, phy_addr);
#else
    return HAL_RET_NOT_SUPPORTED;
#endif
}

/**
 * @brief Read PHY register
 * @param instance: Ethernet instance
 * @param phy_addr: PHY address
 * @param reg_addr: Register address
 * @param value: Pointer to store register value
 * @retval HAL status code
 */
hal_ret_t hal_eth_read_phy_reg(hal_eth_instance_t instance, hal_eth_phy_addr_t phy_addr, uint16_t reg_addr, uint16_t* value)
{
    if (instance >= HAL_ETH_INSTANCE_MAX || !value) {
        return HAL_RET_INVALID_PARAM;
    }

    if (!hal_eth_instances[instance].initialized) {
        return HAL_RET_INIT_ERROR;
    }

    /* Call architecture specific implementation */
#if HAL_TARGET_ARCH == HAL_ARCH_STM32F4
    return hal_stm32f4_eth_read_phy_reg(instance, phy_addr, reg_addr, value);
#else
    return HAL_RET_NOT_SUPPORTED;
#endif
}

/**
 * @brief Write PHY register
 * @param instance: Ethernet instance
 * @param phy_addr: PHY address
 * @param reg_addr: Register address
 * @param value: Register value
 * @retval HAL status code
 */
hal_ret_t hal_eth_write_phy_reg(hal_eth_instance_t instance, hal_eth_phy_addr_t phy_addr, uint16_t reg_addr, uint16_t value)
{
    if (instance >= HAL_ETH_INSTANCE_MAX) {
        return HAL_RET_INVALID_PARAM;
    }

    if (!hal_eth_instances[instance].initialized) {
        return HAL_RET_INIT_ERROR;
    }

    /* Call architecture specific implementation */
#if HAL_TARGET_ARCH == HAL_ARCH_STM32F4
    return hal_stm32f4_eth_write_phy_reg(instance, phy_addr, reg_addr, value);
#else
    return HAL_RET_NOT_SUPPORTED;
#endif
}

/**
 * @brief Get default Ethernet configuration
 * @return Pointer to default Ethernet configuration
 */
const hal_eth_config_t* hal_eth_get_default_config(void)
{
    return &hal_eth_default_config;
}
