Re: Need help with libgpiod gpiod_line_request_both_edges_events()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 03/06/2018 01:46 AM, Bartosz Gołaszewski wrote:
What is the error code (errno) after this function fails? Could you
share some code?

EBUSY (16)

However, strace shows that it never makes any library calls before it returns failure, so I'm not sure if that's accurate.

write(1, "Top of loop\n", 12)           = 12
ioctl(3, _IOC(_IOC_READ|_IOC_WRITE, 0xb4, 0x04, 0x30), 0xffffe5c13270) = 0
ioctl(3, GPIO_GET_LINEINFO_IOCTL, 0xffffe5c131c8) = 0
ppoll([{fd=5, events=POLLIN|POLLPRI}], 1, {1, 0}, NULL, 8) = 1 ([{fd=5, revents=POLLIN}], left {0, 999996750})
write(1, "Top of loop\n", 12)           = 12
write(1, "Error: Could not create event (e"..., 41) = 41

I've attached the source code. I release the line before calling gpiod_line_request_both_edges_events, so I know it's free.

--
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm
Technologies, Inc.  Qualcomm Technologies, Inc. is a member of the
Code Aurora Forum, a Linux Foundation Collaborative Project.
#include <stdio.h>
#include <linux/gpio.h>
#include <gpiod.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include <unistd.h>
#include <errno.h>

struct gpiod_line {
	unsigned int offset;
	int direction;
	int active_state;
	bool used;
	bool open_source;
	bool open_drain;

	int state;
	bool up_to_date;

	struct gpiod_chip *chip;
	int fd;

	char name[32];
	char consumer[32];
};


const char *d(struct gpiod_line *line)
{
	int d = gpiod_line_direction(line);

	return d == GPIOD_LINE_DIRECTION_INPUT ? "input" : "output";
}

int loopback(struct gpiod_chip *chip, struct gpiod_line *output, struct gpiod_line *input, int value)
{
	int ret;

	ret = gpiod_line_set_value(output, value);
	if (ret < 0)
		return ret;

	if (value != gpiod_line_get_value(input))
		return -1;

	return 0;
}

struct toggle_data {
	struct gpiod_line *output;
	unsigned int frequency;
	volatile bool finished;
};

void *oscillate(void *p)
{
	struct toggle_data *data = p;
	unsigned int toggle = 0;
	int ret;

	printf("Oscillate thread started\n");

	while (!data->finished) {
		ret = gpiod_line_set_value(data->output, toggle);
		if (ret < 0)
			break;

		sleep(data->frequency);
		toggle = 1 - toggle;
	}

	return NULL;
}

int interrupt(struct gpiod_chip *chip, struct gpiod_line *output, struct gpiod_line *input)
{
	struct toggle_data data;
	pthread_t thread;
	struct timespec timeout = { 0 };
	unsigned int count = 5;
	int ret;

	data.output = output;
	data.frequency = 1;
	data.finished = false;
	timeout.tv_sec = data.frequency;

	ret = pthread_create(&thread, NULL, oscillate, chip);
	if (ret < 0) {
		printf("Error: Could not create thread (ret=%i)\n", ret);
		return ret;
	}

	printf("Free? %i\n", gpiod_line_is_free(input));
	gpiod_line_release(input);
	printf("Free? %i\n", gpiod_line_is_free(input));

	while (--count) {
		printf("Top of loop\n");
		ret = gpiod_line_request_both_edges_events(input, NULL);
		if (ret < 0) {
			printf("Error: Could not create event (errno=%i)\n", errno);
			break;
		}

		ret = gpiod_line_event_wait(input, &timeout);
		if (ret < 0) {
			printf("Error: Could not wait for event (errno=%i)\n", errno);
			break;
		}
		if (ret == 0) {
			printf("Error: Timeout waiting for event (errno=%i)\n", errno);
			ret = -1;
			break;
		}
	}

	data.finished = true;
	pthread_join(thread, NULL);
	return ret;
}


int test(struct gpiod_chip *chip, int _output, int _input)
{
	struct gpiod_line *output;
	struct gpiod_line *input;
	int ret, i;

	printf("Chip Name: %s\n", gpiod_chip_name(chip));
	printf("Output pin: %i\n", _output);
	printf("Input pin: %i\n", _input);

	output = gpiod_chip_get_line(chip, _output);
	if (!output) {
		printf("Error: Could not obtain gpioline for pin %i\n", _output);
		return 2;
	}

	input = gpiod_chip_get_line(chip, _input);
	if (!input) {
		printf("Error: Could not obtain gpioline for pin %i\n", _input);
		return 2;
	}

	printf("Configuring pins\n");

	ret = gpiod_line_request_output(output, NULL, 0);
	if (ret) {
		printf("Error: Could not configure pin %i to output\n", _output);
		return 2;
	}
	if (gpiod_line_direction(output) != GPIOD_LINE_DIRECTION_OUTPUT) {
		printf("Error: Pin %i refuses to be configured for output\n", _output);
		return 2;
	}

	ret = gpiod_line_request_input(input, NULL);
	if (ret) {
		printf("Error: Could not configure pin $i to input\n", _output);
		return 2;
	}
	if (gpiod_line_direction(input) != GPIOD_LINE_DIRECTION_INPUT) {
		printf("Error: Pin %i refuses to be configured for input\n", _input);
		return 2;
	}

	printf("Running loopback test\n");

	for (i = 0; i < 10; i++) {
		ret = loopback(chip, output, input, 0);
		if (ret) {
			printf("Error: Loopback test #%iA failed\n", i);
			return 2;
		}

		ret = loopback(chip, output, input, 1);
		if (ret) {
			printf("Error: Loopback test #%iB failed\n", i);
			return 2;
		}
	}

	printf("Running interrupt test\n");

	ret = interrupt(chip, output, input);
	if (ret < 0)
		return 2;

	printf("All tests passed\n");

	return 0;
}

int main(int argc, char *argv[])
{
	struct gpiod_chip *chip;
	int ret, fd;

	if (argc != 4) {
		printf("Usage: %s chip-device output-pin input-pin\n", argv[0]);
		return 1;
	}

	/* Test to see if the gpiochip device exists and is readable */
	fd = open(argv[1], O_RDWR);
	close(fd);
	if (fd < 0) {
		printf("Error: Device %s is not accessible\n");
		return 1;
	}

	chip = gpiod_chip_open(argv[1]);
	if (!chip) {
		printf("Error: Device %s is not a gpiochip device\n");
		return 1;
	}

	ret = test(chip, atoi(argv[2]), atoi(argv[3]));
	gpiod_chip_close(chip);

	return ret;
}

[Index of Archives]     [Linux SPI]     [Linux Kernel]     [Linux ARM (vger)]     [Linux ARM MSM]     [Linux Omap]     [Linux Arm]     [Linux Tegra]     [Fedora ARM]     [Linux for Samsung SOC]     [eCos]     [Linux Fastboot]     [Gcc Help]     [Git]     [DCCP]     [IETF Announce]     [Security]     [Linux MIPS]     [Yosemite Campsites]

  Powered by Linux