diff options
| -rw-r--r-- | include/uvcgadget/meson.build | 1 | ||||
| -rw-r--r-- | include/uvcgadget/timer.h | 59 | ||||
| -rw-r--r-- | lib/meson.build | 1 | ||||
| -rw-r--r-- | lib/timer.c | 96 | 
4 files changed, 157 insertions, 0 deletions
| diff --git a/include/uvcgadget/meson.build b/include/uvcgadget/meson.build index c79ea18..d5aaf17 100644 --- a/include/uvcgadget/meson.build +++ b/include/uvcgadget/meson.build @@ -5,6 +5,7 @@ uvcgadget_public_headers = files([    'events.h',    'list.h',    'stream.h', +  'timer.h',    'v4l2-source.h',    'video-source.h',    ]) diff --git a/include/uvcgadget/timer.h b/include/uvcgadget/timer.h new file mode 100644 index 0000000..de93287 --- /dev/null +++ b/include/uvcgadget/timer.h @@ -0,0 +1,59 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * libuvcgadget timer utils + * + * Copyright (C) 2022 Daniel Scally + * + * Contact: Daniel Scally <dan.scally@ideasonboard.com> + */ + +struct timer; + +/* + * timer_new - Create a new timer + * + * Allocates and returns a new struct timer. This must be configured with + * timer_set_fps() and then armed with timer_arm(), following which calls to + * timer_wait() will block until the expiration of a period as defined by + * timer_set_fps(). + * + * Timers allocated with this function should be removed with timer_destroy() + */ +struct timer *timer_new(void); + +/* + * timer_set_fps - Configure the timer's wait period + * + * Configure the timer to wait for a period of time such that expirations per + * second matches @fps + */ +void timer_set_fps(struct timer *timer, int fps); + +/* + * timer_arm + * + * Arms the timer such that calls to timer_wait() become blocking until the + * expiration of a period. + */ +int timer_arm(struct timer *timer); + +/* + * timer_disarm + * + * Disarms the timer such that calls to timer_wait() return without blocking. + */ +int timer_disarm(struct timer *timer); + +/* + * timer_wait + * + * If the timer is armed, block until the expiration of a period + */ +void timer_wait(struct timer *timer); + +/* + * timer_destroy + * + * Close the timer's file descriptor and free the memory + */ +void timer_destroy(struct timer *timer); diff --git a/lib/meson.build b/lib/meson.build index f6991d5..a0d67d5 100644 --- a/lib/meson.build +++ b/lib/meson.build @@ -6,6 +6,7 @@ libuvcgadget_sources = files([    'jpg-source.c',    'stream.c',    'test-source.c', +  'timer.c',    'uvc.c',    'v4l2.c',    'v4l2-source.c', diff --git a/lib/timer.c b/lib/timer.c new file mode 100644 index 0000000..6627656 --- /dev/null +++ b/lib/timer.c @@ -0,0 +1,96 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * libuvcgadget timer utils + * + * Copyright (C) 2022 Daniel Scally + * + * Contact: Daniel Scally <dan.scally@ideasonboard.com> + */ + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/timerfd.h> +#include <unistd.h> + +#include "timer.h" + +struct timer { +        int fd; +        struct itimerspec settings; +}; + +struct timer *timer_new(void) +{ +        struct timer *timer; + +        timer = malloc(sizeof(*timer)); +        if (!timer) +                return NULL; + +        memset(timer, 0, sizeof(*timer)); + +        timer->fd = timerfd_create(CLOCK_REALTIME, 0); +        if (timer->fd < 0) { +		fprintf(stderr, "failed to create timer: %s (%d)\n", +			strerror(errno), errno); +		goto err_free_timer; +	} + +        return timer; + +err_free_timer: +        free(timer); + +        return NULL; +} + +void timer_set_fps(struct timer *timer, int fps) +{ +	int ns_per_frame = 1000000000 / fps; + +	timer->settings.it_value.tv_nsec = ns_per_frame; +	timer->settings.it_interval.tv_nsec = ns_per_frame; +} + +int timer_arm(struct timer *timer) +{ +        int ret; + +	ret = timerfd_settime(timer->fd, 0, &timer->settings, NULL); +	if (ret) +		fprintf(stderr, "failed to change timer settings: %s (%d)\n", +			strerror(errno), errno); + +        return ret; +} + +int timer_disarm(struct timer *timer) +{ +	static const struct itimerspec disable_settings = { +		{ 0, 0 }, +		{ 0, 0 }, +	}; +	int ret; + +	ret = timerfd_settime(timer->fd, 0, &disable_settings, NULL); +	if (ret) +		fprintf(stderr, "failed to disable timer: %s (%d)\n", +			strerror(errno), errno); + +	return ret; +} + +void timer_wait(struct timer *timer) +{ +        char read_buf[8]; + +        read(timer->fd, read_buf, 8); +} + +void timer_destroy(struct timer *timer) +{ +        close(timer->fd); +        free(timer); +} | 
