LINE_EVENT,
};
+struct handle_data {
+ struct gpiohandle_request request;
+ int refcount;
+};
+
struct gpiod_line {
int state;
bool up_to_date;
struct gpiod_chip *chip;
struct gpioline_info info;
- struct gpiohandle_request *request;
- struct gpioevent_request event;
+ union {
+ struct handle_data *handle;
+ struct gpioevent_request event;
+ };
};
struct gpiod_chip_iter
line->state = state;
}
+static int line_get_handle_fd(struct gpiod_line *line)
+{
+ if (line_get_state(line) != LINE_TAKEN)
+ return -1;
+ else
+ return line->handle->request.fd;
+}
+
+static int line_get_event_fd(struct gpiod_line *line)
+{
+ if (line_get_state(line) != LINE_EVENT)
+ return -1;
+ else
+ return line->event.fd;
+}
+
+static void line_set_handle(struct gpiod_line *line,
+ struct handle_data *handle)
+{
+ line->handle = handle;
+ handle->refcount++;
+}
+
+static void line_remove_handle(struct gpiod_line *line)
+{
+ struct handle_data *handle;
+
+ if (!line->handle)
+ return;
+
+ handle = line->handle;
+ line->handle = NULL;
+ handle->refcount--;
+ if (handle->refcount <= 0) {
+ close(handle->request.fd);
+ free(handle);
+ }
+}
+
unsigned int gpiod_line_offset(struct gpiod_line *line)
{
return (unsigned int)line->info.line_offset;
int *default_vals)
{
struct gpiohandle_request *req;
+ struct handle_data *handle;
struct gpiod_chip *chip;
struct gpiod_line *line;
int status, fd;
if (!verify_line_bulk(line_bulk))
return -1;
- req = zalloc(sizeof(*req));
- if (!req)
+ handle = zalloc(sizeof(*handle));
+ if (!handle)
return -1;
+ req = &handle->request;
+
if (config->flags & GPIOD_REQUEST_OPEN_DRAIN)
req->flags |= GPIOHANDLE_REQUEST_OPEN_DRAIN;
if (config->flags & GPIOD_REQUEST_OPEN_SOURCE)
for (i = 0; i < line_bulk->num_lines; i++) {
line = line_bulk->lines[i];
- line->request = req;
+ line_set_handle(line, handle);
line_set_state(line, LINE_TAKEN);
/*
* Update line info to include the changes after the
unsigned int i;
int status;
- close(line_bulk->lines[0]->request->fd);
- free(line_bulk->lines[0]->request);
-
for (i = 0; i < line_bulk->num_lines; i++) {
line = line_bulk->lines[i];
- line->request = NULL;
+ line_remove_handle(line);
line_set_state(line, LINE_FREE);
status = gpiod_line_update(line);
memset(&data, 0, sizeof(data));
- status = gpio_ioctl(line_bulk->lines[0]->request->fd,
+ status = gpio_ioctl(line_get_handle_fd(line_bulk->lines[0]),
GPIOHANDLE_GET_LINE_VALUES_IOCTL, &data);
if (status < 0)
return -1;
for (i = 0; i < line_bulk->num_lines; i++)
data.values[i] = (__u8)!!values[i];
- status = gpio_ioctl(line_bulk->lines[0]->request->fd,
+ status = gpio_ioctl(line_get_handle_fd(line_bulk->lines[0]),
GPIOHANDLE_SET_LINE_VALUES_IOCTL, &data);
if (status < 0)
return -1;
void gpiod_line_event_release(struct gpiod_line *line)
{
- close(line->event.fd);
+ close(line_get_event_fd(line));
line_set_state(line, LINE_FREE);
}
for (i = 0; i < bulk->num_lines; i++) {
linetmp = bulk->lines[i];
- fds[i].fd = linetmp->event.fd;
+ fds[i].fd = line_get_event_fd(linetmp);
fds[i].events = POLLIN | POLLPRI;
}
memset(&evdata, 0, sizeof(evdata));
- rd = read(line->event.fd, &evdata, sizeof(evdata));
+ rd = read(line_get_event_fd(line), &evdata, sizeof(evdata));
if (rd < 0) {
last_error_from_errno();
return -1;
int gpiod_line_event_get_fd(struct gpiod_line *line)
{
- return line_get_state(line) == LINE_EVENT ? line->event.fd : -1;
+ return line_get_state(line) == LINE_EVENT
+ ? line_get_event_fd(line) : -1;
}
struct gpiod_chip * gpiod_chip_open(const char *path)