You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
105 lines
2.9 KiB
105 lines
2.9 KiB
/**
|
|
* @file gpio_linux.c
|
|
* @brief GPIO implementation for Linux using libgpiod and internal context management.
|
|
*/
|
|
|
|
#include "../../ked/peripherals/gpio/gpio.h"
|
|
#include <gpiod.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
|
|
/**
|
|
* @brief Internal Linux GPIO context.
|
|
*/
|
|
typedef struct {
|
|
struct gpiod_chip* chip;
|
|
struct gpiod_line* line;
|
|
} gpio_linux_ctx_t;
|
|
|
|
static gpio_linux_ctx_t gpio_ctx;
|
|
|
|
void ked_gpio_set(gpio_t* gpio, uint8_t value) {
|
|
gpiod_line_set_value(gpio_ctx.line, value);
|
|
}
|
|
|
|
uint8_t ked_gpio_read(gpio_t* gpio) {
|
|
return (uint8_t)gpiod_line_get_value(gpio_ctx.line);
|
|
}
|
|
|
|
void ked_gpio_toggle(gpio_t* gpio) {
|
|
uint8_t current = (uint8_t)gpiod_line_get_value(gpio_ctx.line);
|
|
gpiod_line_set_value(gpio_ctx.line, !current);
|
|
}
|
|
|
|
void gpio_linux_deinit(gpio_t* gpio) {
|
|
if (gpio_ctx.line) {
|
|
gpiod_line_release(gpio_ctx.line);
|
|
gpio_ctx.line = NULL;
|
|
}
|
|
if (gpio_ctx.chip) {
|
|
gpiod_chip_close(gpio_ctx.chip);
|
|
gpio_ctx.chip = NULL;
|
|
}
|
|
}
|
|
|
|
void ked_gpio_handle_error(gpio_error_t err) {
|
|
fprintf(stderr, "[GPIO ERROR] Code: %d\n", err);
|
|
}
|
|
|
|
gpio_error_t ked_gpio_init(const gpio_t* gpio) {
|
|
gpio_ctx.chip = gpiod_chip_open(gpio->chipname);
|
|
if (!gpio_ctx.chip) {
|
|
ked_gpio_handle_error(T_GPIO_ERR_NOT_AVAILABLE);
|
|
return T_GPIO_ERR_NOT_AVAILABLE;
|
|
}
|
|
|
|
gpio_ctx.line = gpiod_chip_get_line(gpio_ctx.chip, gpio->line_offset);
|
|
if (!gpio_ctx.line) {
|
|
gpiod_chip_close(gpio_ctx.chip);
|
|
ked_gpio_handle_error(T_GPIO_ERR_NOT_AVAILABLE);
|
|
return T_GPIO_ERR_NOT_AVAILABLE;
|
|
}
|
|
|
|
struct gpiod_line_request_config req_cfg = {
|
|
.consumer = "ked_gpio",
|
|
.request_type = (gpio->direction == T_GPIO_DIRECTION_OUTPUT)
|
|
? GPIOD_LINE_REQUEST_DIRECTION_OUTPUT
|
|
: GPIOD_LINE_REQUEST_DIRECTION_INPUT,
|
|
.flags = 0
|
|
};
|
|
|
|
if (gpio->bias == T_GPIO_BIAS_PULL_UP)
|
|
req_cfg.flags |= GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_UP;
|
|
else if (gpio->bias == T_GPIO_BIAS_PULL_DOWN)
|
|
req_cfg.flags |= GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_DOWN;
|
|
else if (gpio->bias == T_GPIO_BIAS_DISABLE)
|
|
req_cfg.flags |= GPIOD_LINE_REQUEST_FLAG_BIAS_DISABLE;
|
|
else if (gpio->bias == T_GPIO_BIAS_DEFAULT)
|
|
req_cfg.request_type = GPIOD_LINE_REQUEST_DIRECTION_AS_IS;
|
|
|
|
if (gpiod_line_request(gpio_ctx.line, &req_cfg, 0) < 0) {
|
|
gpiod_chip_close(gpio_ctx.chip);
|
|
ked_gpio_handle_error(T_GPIO_ERR_BUS_BUSY);
|
|
return T_GPIO_ERR_BUS_BUSY;
|
|
}
|
|
|
|
}
|
|
|
|
//3812 340 16 4168 1048 ked_executable
|
|
//3816 340 16 4172 104c ked_executable
|
|
//3692 332 16 4040 fc8 ked_executable
|
|
|
|
void ked_gpio_deinit(gpio_t* gpio) {
|
|
/*
|
|
if (gpio && gpio->deinit) {
|
|
gpio->deinit();
|
|
gpio->status = T_GPIO_STATUS_NOT_INIT;
|
|
}*/
|
|
}
|
|
|
|
gpio_error_t ked_gpio_update(gpio_t* gpio) {
|
|
ked_gpio_deinit(gpio);
|
|
return ked_gpio_init(gpio);
|
|
}
|
|
|