Skip to content

Commit

Permalink
libgpiod 2 API supported
Browse files Browse the repository at this point in the history
  • Loading branch information
mdevaev committed Jan 7, 2024
1 parent a0f549b commit 8a75217
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 8 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ CFLAGS ?= -O3
LDFLAGS ?=

_APP = kvmd-fan
_CFLAGS = -MD -c -std=c17 -Wall -Wextra -D_GNU_SOURCE
_CFLAGS = -MD -c -std=c17 -Wall -Wextra -D_GNU_SOURCE $(shell pkg-config --atleast-version=2 libgpiod 2> /dev/null && echo -DHAVE_GPIOD2)
_LDFLAGS = $(LDFLAGS) -lm -lpthread -liniparser -lmicrohttpd -lgpiod
_SRCS = $(shell ls src/*.c)
_BUILD = build
Expand Down
76 changes: 74 additions & 2 deletions src/fan.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,48 @@ fan_s *fan_init(unsigned pwm_pin, unsigned pwm_low, unsigned pwm_high, unsigned
atomic_init(&fan->rpm, 0);
if (hall_pin >= 0) {
LOG_INFO("fan.hall", "Using pin=%d for the Hall sensor", hall_pin);

# ifdef HAVE_GPIOD2
struct gpiod_chip *chip;
if ((chip = gpiod_chip_open("/dev/gpiochip0")) == NULL) {
LOG_PERROR("fan.hall", "Can't open GPIO chip");
goto error;
}

struct gpiod_line_settings *line_settings;
assert(line_settings = gpiod_line_settings_new());
assert(!gpiod_line_settings_set_direction(line_settings, GPIOD_LINE_DIRECTION_INPUT));
assert(!gpiod_line_settings_set_edge_detection(line_settings, GPIOD_LINE_EDGE_FALLING));
assert(!gpiod_line_settings_set_bias(line_settings,
hall_bias == FAN_BIAS_PULL_DOWN ? GPIOD_LINE_BIAS_PULL_DOWN
: hall_bias == FAN_BIAS_PULL_UP ? GPIOD_LINE_BIAS_PULL_UP
: GPIOD_LINE_BIAS_DISABLED
));

struct gpiod_line_config *line_config;
assert(line_config = gpiod_line_config_new());
const unsigned offset = hall_pin;
assert(!gpiod_line_config_add_line_settings(line_config, &offset, 1, line_settings));

struct gpiod_request_config *request_config;
assert(request_config = gpiod_request_config_new());
gpiod_request_config_set_consumer(request_config, "kvmd-fan::hall");

if ((fan->line = gpiod_chip_request_lines(chip, request_config, line_config)) == NULL) {
LOG_PERROR("fan.hall", "Can't request GPIO notification");
}

gpiod_request_config_free(request_config);
gpiod_line_config_free(line_config);
gpiod_line_settings_free(line_settings);
gpiod_chip_close(chip);

if (fan->line == NULL) {
goto error;
}

# else

if ((fan->chip = gpiod_chip_open_by_number(0)) == NULL) {
LOG_PERROR("fan.hall", "Can't open GPIO chip");
goto error;
Expand All @@ -69,6 +111,7 @@ fan_s *fan_init(unsigned pwm_pin, unsigned pwm_low, unsigned pwm_high, unsigned
LOG_PERROR("fan.hall", "Can't request GPIO notification");
goto error;
}
# endif

atomic_store(&fan->stop, false);
A_THREAD_CREATE(&fan->tid, _hall_thread, fan);
Expand All @@ -85,12 +128,18 @@ void fan_destroy(fan_s *fan) {
atomic_store(&fan->stop, true);
A_THREAD_JOIN(fan->tid);
}
# ifdef HAVE_GPIOD2
if (fan->line) {
gpiod_line_request_release(fan->line);
}
# else
if (fan->line) {
gpiod_line_release(fan->line);
}
if (fan->chip) {
gpiod_chip_close(fan->chip);
}
# endif
free(fan);
}

Expand Down Expand Up @@ -118,19 +167,36 @@ int fan_get_hall_rpm(fan_s *fan) {
}

static void *_hall_thread(void *v_fan) {
# define _MAX_EVENTS 16

fan_s *fan = (fan_s *)v_fan;
const struct timespec timeout = {0, 100000000};
long double next_ts = get_now_monotonic() + 1;
unsigned pulses = 0;

# ifdef HAVE_GPIOD2
struct gpiod_edge_event_buffer *events;
assert(events = gpiod_edge_event_buffer_new(_MAX_EVENTS));
# else
struct gpiod_line_event events[_MAX_EVENTS];
# endif

while (!atomic_load(&fan->stop)) {
# ifdef HAVE_GPIOD2
int retval = gpiod_line_request_wait_edge_events(fan->line, 100000000);
# else
const struct timespec timeout = {0, 100000000};
int retval = gpiod_line_event_wait(fan->line, &timeout);
# endif
if (retval < 0) {
LOG_PERROR("fan.hall", "Can't wait events");
atomic_store(&fan->rpm, -1);
break;
} else if (retval > 0) {
retval = gpiod_line_event_read_multiple(fan->line, fan->events, ARRAY_LEN(fan->events));
# ifdef HAVE_GPIOD2
retval = gpiod_line_request_read_edge_events(fan->line, events, _MAX_EVENTS);
# else
retval = gpiod_line_event_read_multiple(fan->line, events, _MAX_EVENTS);
# endif
if (retval < 0) {
LOG_PERROR("fan.hall", "Can't read events");
atomic_store(&fan->rpm, -1);
Expand All @@ -149,5 +215,11 @@ static void *_hall_thread(void *v_fan) {

usleep(10000);
}

# ifdef HAVE_GPIOD2
gpiod_edge_event_buffer_free(events);
# endif
return NULL;

# undef _MAX_EVENTS
}
10 changes: 7 additions & 3 deletions src/fan.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include <stdatomic.h>
#include <unistd.h>
#include <math.h>
#include <assert.h>

#include <pthread.h>
#ifndef WITH_WIRINGPI_STUB
Expand All @@ -53,9 +54,12 @@ typedef struct {
unsigned pwm_soft;

// Hall sensor
struct gpiod_chip *chip;
struct gpiod_line *line;
struct gpiod_line_event events[16];
# ifdef HAVE_GPIOD2
struct gpiod_line_request *line;
# else
struct gpiod_chip *chip;
struct gpiod_line *line;
# endif

pthread_t tid;
atomic_int rpm;
Expand Down
2 changes: 0 additions & 2 deletions src/tools.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,6 @@
#define A_CALLOC(_dest, _nmemb) assert((_dest = calloc(_nmemb, sizeof(*(_dest)))))
#define A_ASPRINTF(_dest, _fmt, ...) assert(asprintf(&(_dest), _fmt, ##__VA_ARGS__) >= 0)

#define ARRAY_LEN(_array) (sizeof(_array) / sizeof(_array[0]))

#define A_THREAD_CREATE(_tid, _func, _arg) assert(!pthread_create(_tid, NULL, _func, _arg))
#define A_THREAD_JOIN(_tid) assert(!pthread_join(_tid, NULL))
#define A_MUTEX_INIT(_mutex) assert(!pthread_mutex_init(_mutex, NULL))
Expand Down

0 comments on commit 8a75217

Please sign in to comment.