Current section
Files
Jump to
Current section
Files
src/gpio_chip.c
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <string.h>
#include <linux/gpio.h>
#include "gpio_chip.h"
void chip_close(struct gpio_chip *chip)
{
close(chip->fd);
}
void chip_event_handle_close(struct gpio_chip_event_handle *handle)
{
close(handle->fd);
}
int chip_open(struct gpio_chip *chip, const char *path)
{
int fd = open(path, O_RDWR);
if (fd < 0)
return fd;
chip->fd = fd;
return 0;
}
int chip_get_info(struct gpio_chip *chip) {
if (chip->has_info == 1)
return 0;
struct gpiochip_info info;
memset(&info, 0, sizeof(info));
int rv = ioctl(chip->fd, GPIO_GET_CHIPINFO_IOCTL, &info);
if (rv < 0)
return rv;
chip->num_lines = info.lines;
strncpy(chip->name, info.name, sizeof(chip->name));
if (info.label[0] == '\0')
strncpy(chip->label, "unknown", sizeof(chip->label));
else
strncpy(chip->label, info.label, sizeof(chip->label));
chip->has_info = 1;
return 0;
}
void chip_line_handle_close(struct gpio_chip_line_handle *handle) {
close(handle->handle_fd);
}
int chip_get_line_info(struct gpio_chip *chip, int offset, struct gpio_chip_line_info *line_info)
{
struct gpioline_info info;
memset(&info, 0, sizeof(info));
info.line_offset = offset;
int rv = ioctl(chip->fd, GPIO_GET_LINEINFO_IOCTL, &info);
if (rv < 0)
return -1;
line_info->direction = info.flags & GPIOLINE_FLAG_IS_OUT
? GPIO_CHIP_LINE_OUTPUT
: GPIO_CHIP_LINE_INPUT;
line_info->active_low = info.flags & GPIOLINE_FLAG_ACTIVE_LOW
? GPIO_CHIP_ACTIVE_LOW
: GPIO_CHIP_ACTIVE_HIGH;
strncpy(line_info->name, info.name, sizeof(line_info->name));
strncpy(line_info->consumer, info.consumer, sizeof(line_info->consumer));
return 0;
}
int chip_read_event_data(struct gpio_chip_event_handle *handle, struct gpio_chip_event_data *data)
{
struct gpioevent_data event_data;
int bytes_read = read(handle->fd, &event_data, sizeof(event_data));
if (bytes_read == -1)
return -1;
data->timestamp = event_data.timestamp;
data->id = event_data.id;
return 0;
}
int chip_read_values(struct gpio_chip_line_handle *handle, int *buff)
{
struct gpiohandle_data data;
memset(&data, 0, sizeof(data));
int rv = ioctl(handle->handle_fd, GPIOHANDLE_GET_LINE_VALUES_IOCTL, &data);
if (rv < 0)
return -1;
for (int i = 0; i < handle->num_lines; i++) {
buff[i] = (int)data.values[i];
}
return 0;
}
int chip_request_event(struct gpio_chip *chip, int offset, struct gpio_chip_event_handle *handle)
{
struct gpioevent_request req;
memset(&req, 0, sizeof(req));
req.lineoffset = offset;
req.handleflags = GPIOHANDLE_REQUEST_INPUT;
req.eventflags = GPIOEVENT_REQUEST_BOTH_EDGES;
strncpy(req.consumer_label, "circuits_cdev", sizeof(req.consumer_label - 1));
int rv = ioctl(chip->fd, GPIO_GET_LINEEVENT_IOCTL, &req);
if (rv < 0)
return -1;
handle->fd = req.fd;
return 0;
}
int chip_request_lines(struct gpio_chip *chip, int offsets[], int direction, struct gpio_chip_line_handle *handle)
{
if (handle->num_lines == 0)
return 0;
if (handle->num_lines >= GPIOHANDLES_MAX)
return -2;
int gpio_direction = -1;
if (direction == 0) {
gpio_direction = GPIOHANDLE_REQUEST_INPUT;
} else if (direction == 1) {
gpio_direction = GPIOHANDLE_REQUEST_OUTPUT;
} else {
return -1;
}
struct gpiohandle_request req;
memset(&req, 0, sizeof(req));
req.flags |= gpio_direction;
req.lines = handle->num_lines;
for (int i = 0; i < handle->num_lines; i++) {
req.lineoffsets[i] = offsets[i];
}
for (int i = 0; i < handle->num_lines; i++) {
req.default_values[i] = 0;
}
strcpy(req.consumer_label, "circuits_gpio_chip");
int rv = ioctl(chip->fd, GPIO_GET_LINEHANDLE_IOCTL, &req);
if (rv > 0)
return -3;
handle->handle_fd = req.fd;
return 0;
}
int chip_set_values(struct gpio_chip_line_handle *handle, int values[])
{
struct gpiohandle_data data;
for (int i = 0; i < handle->num_lines; i++) {
data.values[i] = values[i];
}
int rv = ioctl(handle->handle_fd, GPIOHANDLE_SET_LINE_VALUES_IOCTL, &data);
if (rv < 0)
return -1;
return 0;
}