/** * @file se050_i2c_hal.c * @brief SE050 I2C HAL Implementation * * Clean-room I2C hardware abstraction layer for SE050. * * License: MIT (Clean-room implementation) */ #define _POSIX_C_SOURCE 200809L #include "se050_i2c_hal.h" #include "se050_wireguard.h" #include #include #include #include #include #include #include #include #include #ifdef __linux__ /* Linux-specific I2C IOCTL definitions */ #ifndef I2C_SLAVE #define I2C_SLAVE 0x0703 #endif #ifndef I2C_SMBUS #define I2C_SMBUS 0x0720 #endif #endif /* SE050 default I2C address (7-bit) */ #define SE050_I2C_ADDR_DEFAULT 0x48 /* I2C timeout in milliseconds */ #define SE050_I2C_TIMEOUT_MS 1000 /* Maximum retry count for I2C operations */ #define SE050_I2C_MAX_RETRY 3 /* SE050 wakeup delay in milliseconds */ #define SE050_WAKEUP_DELAY_MS 5 /** * @brief Sleep for specified milliseconds */ static void se050_sleep_ms(unsigned int ms) { #ifdef __linux__ struct timespec ts; ts.tv_sec = ms / 1000; ts.tv_nsec = (ms % 1000) * 1000000L; nanosleep(&ts, NULL); #else /* Fallback for non-Linux platforms */ volatile int i; for (i = 0; i < ms * 1000; i++); #endif } /** * @brief Open I2C device */ static void *i2c_open(const char *dev_path) { int fd; if (!dev_path) { return NULL; } fd = open(dev_path, O_RDWR); if (fd < 0) { perror("I2C open failed"); return NULL; } return (void *)(intptr_t)fd; } /** * @brief Close I2C device */ static void i2c_close(void *handle) { int fd = (int)(intptr_t)handle; if (fd >= 0) { close(fd); } } /** * @brief Set I2C slave address */ static se050_status_t i2c_set_slave_addr(void *handle, uint8_t addr) { int fd = (int)(intptr_t)handle; int ret; /* addr is already 7-bit address */ ret = ioctl(fd, I2C_SLAVE, addr); if (ret < 0) { perror("I2C set slave address failed"); return SE050_ERR_I2C; } return SE050_OK; } /* ============================================================================ * Public API Implementation * ============================================================================ */ se050_status_t se050_i2c_init(se050_i2c_hal_t *hal, const char *dev_path, uint8_t slave_addr) { void *handle; if (!hal || !dev_path) { return SE050_ERR_INVALID_ARG; } memset(hal, 0, sizeof(*hal)); /* Open I2C device */ handle = i2c_open(dev_path); if (!handle) { return SE050_ERR_I2C; } /* Set slave address */ if (i2c_set_slave_addr(handle, slave_addr) != SE050_OK) { i2c_close(handle); return SE050_ERR_I2C; } hal->handle = handle; hal->slave_addr = slave_addr; strncpy(hal->dev_path, dev_path, SE050_I2C_DEV_PATH_MAX - 1); hal->dev_path[SE050_I2C_DEV_PATH_MAX - 1] = '\0'; return SE050_OK; } void se050_i2c_close(se050_i2c_hal_t *hal) { if (!hal) { return; } if (hal->handle) { i2c_close(hal->handle); hal->handle = NULL; } hal->dev_path[0] = '\0'; hal->slave_addr = 0; } int se050_i2c_read(se050_i2c_hal_t *hal, uint8_t *buffer, int length) { int fd; int retry; int bytes_read; if (!hal || !buffer || length <= 0) { return -1; } fd = (int)(intptr_t)hal->handle; for (retry = 0; retry < SE050_I2C_MAX_RETRY; retry++) { bytes_read = read(fd, buffer, length); if (bytes_read > 0) { return bytes_read; } if (errno != EAGAIN && errno != ETIMEDOUT) { /* Permanent error */ break; } /* Retry with delay */ se050_sleep_ms(SE050_WAKEUP_DELAY_MS); } return -1; } int se050_i2c_write(se050_i2c_hal_t *hal, const uint8_t *buffer, int length) { int fd; int retry; int bytes_written; if (!hal || !buffer || length <= 0) { return -1; } fd = (int)(intptr_t)hal->handle; for (retry = 0; retry < SE050_I2C_MAX_RETRY; retry++) { bytes_written = write(fd, buffer, length); if (bytes_written > 0) { return bytes_written; } if (errno != EAGAIN && errno != ETIMEDOUT) { /* Permanent error */ break; } /* Retry with delay */ se050_sleep_ms(SE050_WAKEUP_DELAY_MS); } return -1; } se050_status_t se050_i2c_wakeup(se050_i2c_hal_t *hal) { uint8_t wakeup_cmd = 0x00; int ret; if (!hal) { return SE050_ERR_INVALID_ARG; } /* Send wakeup command (dummy write) */ ret = se050_i2c_write(hal, &wakeup_cmd, 1); if (ret < 0) { return SE050_ERR_I2C; } /* Wait for SE050 to respond */ se050_sleep_ms(SE050_WAKEUP_DELAY_MS); return SE050_OK; }