Reputation: 207
I'm imitating the gpio-hammer example in Linux source code. I'm using Raspberry Pi 3B+ and want an LED to blink.
Here's what I do:
#include <linux/gpio.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
int main(int argc, const char **argv) {
int fd, ret;
struct gpiohandle_request req;
struct gpiohandle_data data;
char *gpio_dev_name = "/dev/gpiochip0";
unsigned int gpio_line = 8;
memset(&data.values, 0, sizeof(data.values));
// open device
fd = open(gpio_dev_name, 0);
if (fd == -1) {
fprintf(stderr, "Failed to open %s, %s\n",
gpio_dev_name, strerror(errno));
}
// request gpio output
req.lineoffsets[0] = gpio_line;
req.flags = GPIOHANDLE_REQUEST_OUTPUT | GPIOHANDLE_REQUEST_ACTIVE_LOW;
strcpy(req.consumer_label, "blink");
req.lines = 1;
memcpy(req.default_values, &data, sizeof(req.default_values));
ret = ioctl(fd, GPIO_GET_LINEHANDLE_IOCTL, &req);
if (ret == -1) {
fprintf(stderr, "Failed to issue %s (%d), %s\n",
"GPIO_GET_LINEHANDLE_IOCTL", ret, strerror(errno));
}
// blink
while (1) {
// read data
ret = ioctl(fd, GPIOHANDLE_GET_LINE_VALUES_IOCTL, &data);
if (ret == -1) {
ret = -errno;
fprintf(stderr, "Failed to issue %s (%d), %s\n",
"GPIOHANDLE_GET_LINE_VALUES_IOCTL", ret, strerror(errno));
exit(ret);
}
// flip digits
data.values[0] = !data.values[0];
// set data
ret = ioctl(fd, GPIOHANDLE_SET_LINE_VALUES_IOCTL, &data);
if (ret == -1) {
ret = -errno;
fprintf(stderr, "Failed to issue %s (%d), %s\n",
"GPIOHANDLE_SET_LINE_VALUES_IOCTL", ret, strerror(errno));
exit(ret);
}
// delay
sleep(1);
}
}
I can compile the gpio-hammer example on RPi and run it with ./gpio-hammer -n gpiochip0 -o 8
. Attached to gpiochip0 line8 is an LED and it blinks.
But my program does not work. It fails with
Failed to issue GPIOHANDLE_GET_LINE_VALUES_IOCTL (-22), Invalid argument
I looked into the implement of gpiolib. The ioctl
of gpio line handle returns EINVAL (22)
if ioctl cmd is not GPIOHANDLE_GET_LINE_VALUES_IOCTL
nor GPIOHANDLE_SET_LINE_VALUES_IOCTL
. But that's not the case. What's going wrong?
Upvotes: 3
Views: 6305
Reputation: 207
In linux/gpio.h
, the description of struct gpiohandle_request
says:
/*
* ...
* @fd: if successful this field will contain a valid anonymous file handle
* after a GPIO_GET_LINEHANDLE_IOCTL operation, zero or negative value
* means error
*/
struct gpiohandle_request {
__u32 lineoffsets[GPIOHANDLES_MAX];
__u32 flags;
__u8 default_values[GPIOHANDLES_MAX];
char consumer_label[32];
__u32 lines;
int fd;
};
When use GPIO_GET_LINEHANDLE_IOCTL
, the file handle of GPIO chip device is passed through the first argument of ioctl()
, and another file handle will be sent back in gpiohandle_request::fd
, if the operation successes. This new fd
should be used in ioctl
of GPIO_GET_LINE_VALUES_IOCTL
or GPIO_SET_LINE_VALUES_IOCTL
.
So the code should be
ret = ioctl(fd, GPIO_GET_LINEHANDLE_IOCTL, &req);
if (ret == -1) {
fprintf(stderr, "Failed to issue %s (%d), %s\n",
"GPIO_GET_LINEHANDLE_IOCTL", ret, strerror(errno));
}
else {
if (close(fd) == -1) {
fprintf(stderr, "Failed to close GPIO char dev.\n");
}
fd = req.fd;
}
Upvotes: 1