linuxOS_D21X/source/artinchip/test-gpio/test_gpio_output.c
2024-11-29 16:33:21 +08:00

139 lines
3.4 KiB
C

// SPDX-License-Identifier: Apache-2.0
/*
* Copyright (C) 2022-2023 ArtInChip Technology Co., Ltd.
*/
/*
* This sample code sets one gpio pin as output,
* flip the output level every second.
*/
#include <stdio.h>
#include <linux/gpio.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <getopt.h>
#include <signal.h>
volatile int gpio_abort = 0;
void print_usage(void)
{
fprintf(stderr, "Usage: test_gpio_output <GPIO_NAME> <LINE_OFFSET> <OUTPUT_LEVEL>\n"
" Example:\n"
" test_gpio_output gpiochip3 6 flipped\n"
" test_gpio_output gpiochip3 6 high\n"
" test_gpio_output gpiochip3 6 low\n");
}
void signal_handler(int sig)
{
printf("test_gpio_output aborted by signal %s...\n", strsignal(sig));
gpio_abort = 1;
}
int main(int argc, char *argv[])
{
int gfd, lfd, ret, offset;
struct gpio_v2_line_request req;
struct gpio_v2_line_values value;
char device_name[10];
char gpio_dev[20];
if (argc != 4) {
print_usage();
exit(-1);
}
memcpy(device_name, argv[1], 10);
offset = (int)strtoul(argv[2], NULL, 10);
memset(&req, 0, sizeof(req));
/* Configure output mode */
req.config.flags |= GPIO_V2_LINE_FLAG_OUTPUT;
snprintf(gpio_dev, 20, "/dev/%s", device_name);
/* open GPIO group device, get the fd */
gfd = open(gpio_dev, 0);
if (gfd == -1) {
ret = -errno;
fprintf(stderr, "Failed to open %s, %s\n",
gpio_dev, strerror(errno));
return ret;
}
/* line offset in requested GPIO group */
req.offsets[0] = offset;
/* just request one line */
req.num_lines = 1;
strcpy(req.consumer, "gpio output pin");
ret = ioctl(gfd, 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));
goto __exit_device_close;
} else {
/* request line success, get the gpio line fd */
lfd = req.fd;
}
/* a bitmap identifying the lines to get or set */
value.mask = 1;
/* a bitmap containing the value of the lines */
signal(SIGINT, signal_handler);
signal(SIGTERM, signal_handler);
signal(SIGABRT, signal_handler);
if (!strncmp(argv[3], "flipped", 12)) {
value.bits = 1;
gpio_abort = 0;
printf("%s line %d output level will be flipped every second...\n",
device_name, offset);
while (!gpio_abort) {
ret = ioctl(lfd, GPIO_V2_LINE_SET_VALUES_IOCTL, &value);
if (ret == -1) {
ret = -errno;
fprintf(stderr, "Failed to issue %s (%d), %s\n",
"GPIOHANDLE_SET_LINE_VALUES_IOCTL", ret,
strerror(errno));
break;
}
value.bits ^= 1;
sleep(1);
}
}
if (!strncmp(argv[3], "high", 12)) {
value.bits = 1;
printf("%s line %d output level will be high\n", device_name, offset);
ret = ioctl(lfd, GPIO_V2_LINE_SET_VALUES_IOCTL, &value);
if (ret == -1) {
ret = -errno;
fprintf(stderr, "Failed to issue %s (%d), %s\n",
"GPIOHANDLE_SET_LINE_VALUES_IOCTL", ret,
strerror(errno));
}
}
if (!strncmp(argv[3], "low", 12)) {
value.bits = 0;
printf("%s line %d output level will be low\n", device_name, offset);
ret = ioctl(lfd, GPIO_V2_LINE_SET_VALUES_IOCTL, &value);
if (ret == -1) {
ret = -errno;
fprintf(stderr, "Failed to issue %s (%d), %s\n",
"GPIOHANDLE_SET_LINE_VALUES_IOCTL", ret,
strerror(errno));
}
}
if (close(lfd) == -1)
perror("Failed to close line file");
__exit_device_close:
if (close(gfd))
perror("Failed to close GPIO group file");
return ret;
}