// SPDX-License-Identifier: GPL-2.0-only
/*
* GPIO tools - helpers library for the GPIO tools
*
* Copyright ( C ) 2015 Linus Walleij
* Copyright ( C ) 2016 Bamvor Jian Zhang
*/
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <getopt.h>
#include <sys/ioctl.h>
#include <linux/gpio.h>
#include "gpio-utils.h"
#define CONSUMER "gpio-utils"
/**
* DOC : Operation of gpio
*
* Provide the api of gpiochip for chardev interface . There are two
* types of api . The first one provide as same function as each
* ioctl , including request and release for lines of gpio , read / write
* the value of gpio . If the user want to do lots of read and write of
* lines of gpio , user should use this type of api .
*
* The second one provide the easy to use api for user . Each of the
* following api will request gpio lines , do the operation and then
* release these lines .
*/
/**
* gpiotools_request_line ( ) - request gpio lines in a gpiochip
* @ device_name : The name of gpiochip without prefix " / dev / " ,
* such as " gpiochip0 "
* @ lines : An array desired lines , specified by offset
* index for the associated GPIO device .
* @ num_lines : The number of lines to request .
* @ config : The new config for requested gpio . Reference
* " linux / gpio . h " for config details .
* @ consumer : The name of consumer , such as " sysfs " ,
* " powerkey " . This is useful for other users to
* know who is using .
*
* Request gpio lines through the ioctl provided by chardev . User
* could call gpiotools_set_values ( ) and gpiotools_get_values ( ) to
* read and write respectively through the returned fd . Call
* gpiotools_release_line ( ) to release these lines after that .
*
* Return : On success return the fd ;
* On failure return the errno .
*/
int gpiotools_request_line(const char *device_name, unsigned int *lines,
unsigned int num_lines,
struct gpio_v2_line_config *config,
const char *consumer)
{
struct gpio_v2_line_request req;
char *chrdev_name;
int fd;
int i;
int ret;
ret = asprintf(&chrdev_name, "/dev/%s" , device_name);
if (ret < 0 )
return -ENOMEM;
fd = open(chrdev_name, 0 );
if (fd == -1 ) {
ret = -errno;
fprintf(stderr, "Failed to open %s, %s\n" ,
chrdev_name, strerror(errno));
goto exit_free_name;
}
memset(&req, 0 , sizeof (req));
for (i = 0 ; i < num_lines; i++)
req.offsets[i] = lines[i];
req.config = *config;
strcpy(req.consumer, consumer);
req.num_lines = num_lines;
ret = ioctl(fd, GPIO_V2_GET_LINE_IOCTL, &req);
if (ret == -1 ) {
ret = -errno;
fprintf(stderr, "Failed to issue %s (%d), %s\n" ,
"GPIO_GET_LINE_IOCTL" , ret, strerror(errno));
}
if (close(fd) == -1 )
perror("Failed to close GPIO character device file" );
exit_free_name:
free(chrdev_name);
return ret < 0 ? ret : req.fd;
}
/**
* gpiotools_set_values ( ) - Set the value of gpio ( s )
* @ fd : The fd returned by
* gpiotools_request_line ( ) .
* @ values : The array of values want to set .
*
* Return : On success return 0 ;
* On failure return the errno .
*/
int gpiotools_set_values(const int fd, struct gpio_v2_line_values *values)
{
int ret;
ret = ioctl(fd, GPIO_V2_LINE_SET_VALUES_IOCTL, values);
if (ret == -1 ) {
ret = -errno;
fprintf(stderr, "Failed to issue %s (%d), %s\n" ,
"GPIOHANDLE_SET_LINE_VALUES_IOCTL" , ret,
strerror(errno));
}
return ret;
}
/**
* gpiotools_get_values ( ) - Get the value of gpio ( s )
* @ fd : The fd returned by
* gpiotools_request_line ( ) .
* @ values : The array of values get from hardware .
*
* Return : On success return 0 ;
* On failure return the errno .
*/
int gpiotools_get_values(const int fd, struct gpio_v2_line_values *values)
{
int ret;
ret = ioctl(fd, GPIO_V2_LINE_GET_VALUES_IOCTL, values);
if (ret == -1 ) {
ret = -errno;
fprintf(stderr, "Failed to issue %s (%d), %s\n" ,
"GPIOHANDLE_GET_LINE_VALUES_IOCTL" , ret,
strerror(errno));
}
return ret;
}
/**
* gpiotools_release_line ( ) - Release the line ( s ) of gpiochip
* @ fd : The fd returned by
* gpiotools_request_line ( ) .
*
* Return : On success return 0 ;
* On failure return the errno .
*/
int gpiotools_release_line(const int fd)
{
int ret;
ret = close(fd);
if (ret == -1 ) {
perror("Failed to close GPIO LINE device file" );
ret = -errno;
}
return ret;
}
/**
* gpiotools_get ( ) - Get value from specific line
* @ device_name : The name of gpiochip without prefix " / dev / " ,
* such as " gpiochip0 "
* @ line : number of line , such as 2 .
*
* Return : On success return 0 ;
* On failure return the errno .
*/
int gpiotools_get(const char *device_name, unsigned int line)
{
int ret;
unsigned int value;
unsigned int lines[] = {line};
ret = gpiotools_gets(device_name, lines, 1 , &value);
if (ret)
return ret;
return value;
}
/**
* gpiotools_gets ( ) - Get values from specific lines .
* @ device_name : The name of gpiochip without prefix " / dev / " ,
* such as " gpiochip0 " .
* @ lines : An array desired lines , specified by offset
* index for the associated GPIO device .
* @ num_lines : The number of lines to request .
* @ values : The array of values get from gpiochip .
*
* Return : On success return 0 ;
* On failure return the errno .
*/
int gpiotools_gets(const char *device_name, unsigned int *lines,
unsigned int num_lines, unsigned int *values)
{
int fd, i;
int ret;
int ret_close;
struct gpio_v2_line_config config;
struct gpio_v2_line_values lv;
memset(&config, 0 , sizeof (config));
config.flags = GPIO_V2_LINE_FLAG_INPUT;
ret = gpiotools_request_line(device_name, lines, num_lines,
&config, CONSUMER);
if (ret < 0 )
return ret;
fd = ret;
for (i = 0 ; i < num_lines; i++)
gpiotools_set_bit(&lv.mask, i);
ret = gpiotools_get_values(fd, &lv);
if (!ret)
for (i = 0 ; i < num_lines; i++)
values[i] = gpiotools_test_bit(lv.bits, i);
ret_close = gpiotools_release_line(fd);
return ret < 0 ? ret : ret_close;
}
/**
* gpiotools_set ( ) - Set value to specific line
* @ device_name : The name of gpiochip without prefix " / dev / " ,
* such as " gpiochip0 "
* @ line : number of line , such as 2 .
* @ value : The value of gpio , must be 0 ( low ) or 1 ( high ) .
*
* Return : On success return 0 ;
* On failure return the errno .
*/
int gpiotools_set(const char *device_name, unsigned int line,
unsigned int value)
{
unsigned int lines[] = {line};
return gpiotools_sets(device_name, lines, 1 , &value);
}
/**
* gpiotools_sets ( ) - Set values to specific lines .
* @ device_name : The name of gpiochip without prefix " / dev / " ,
* such as " gpiochip0 " .
* @ lines : An array desired lines , specified by offset
* index for the associated GPIO device .
* @ num_lines : The number of lines to request .
* @ values : The array of values set to gpiochip , must be
* 0 ( low ) or 1 ( high ) .
*
* Return : On success return 0 ;
* On failure return the errno .
*/
int gpiotools_sets(const char *device_name, unsigned int *lines,
unsigned int num_lines, unsigned int *values)
{
int ret, i;
struct gpio_v2_line_config config;
memset(&config, 0 , sizeof (config));
config.flags = GPIO_V2_LINE_FLAG_OUTPUT;
config.num_attrs = 1 ;
config.attrs[0 ].attr.id = GPIO_V2_LINE_ATTR_ID_OUTPUT_VALUES;
for (i = 0 ; i < num_lines; i++) {
gpiotools_set_bit(&config.attrs[0 ].mask, i);
gpiotools_assign_bit(&config.attrs[0 ].attr.values,
i, values[i]);
}
ret = gpiotools_request_line(device_name, lines, num_lines,
&config, CONSUMER);
if (ret < 0 )
return ret;
return gpiotools_release_line(ret);
}
Messung V0.5 in Prozent C=95 H=92 G=93
¤ Dauer der Verarbeitung: 0.10 Sekunden
(vorverarbeitet am 2026-10-11)
¤
*© Formatika GbR, Deutschland