From 00394f239e79cbfe0af36eb11c02290ac76e56e2 Mon Sep 17 00:00:00 2001 From: guowenxue <guowenxue@gmail.com> Date: Thu, 22 Aug 2024 17:50:02 +0800 Subject: [PATCH] move api to modules --- hal/modules/key.c | 171 +++++++++++++++++++++ hal/modules/keypad.c | 197 ++++++++++++++++++++++++ hal/modules/led.c | 0 hal/modules/pwm.c | 0 hal/modules/relay.h | 0 hal/modules/libgpiod/build.sh | 0 hal/modules/relay.c | 0 hal/modules/libgpiod/makefile | 0 /dev/null | 55 ------ hal/modules/infrared.h | 0 hal/modules/infrared.c | 1 hal/modules/makefile | 14 + hal/modules/led.h | 0 13 files changed, 380 insertions(+), 58 deletions(-) diff --git a/hal/api/makefile b/hal/api/makefile deleted file mode 100644 index befd362..0000000 --- a/hal/api/makefile +++ /dev/null @@ -1,55 +0,0 @@ -#******************************************************************************** -# Copyright: (C) 2023 LingYun IoT System Studio -# All rights reserved. -# -# Filename: Makefile -# Description: This file used to compile all the C file to respective binary, -# and it will auto detect cross compile or local compile. -# -# Version: 1.0.0(11/08/23) -# Author: Guo Wenxue <guowenxue@gmail.com> -# ChangeLog: 1, Release initial version on "11/08/23 16:18:43" -# -#******************************************************************************* - -PWD=$(shell pwd) -INSTPATH=/tftp - -CROSS_COMPILE=/opt/gcc-aarch32-10.3-2021.07/bin/arm-none-linux-gnueabihf- -CC=${CROSS_COMPILE}gcc - -LDFLAGS += -lm - -SRCS = $(wildcard ${VPATH}/*.c) -OBJS = $(patsubst %.c,%.o,$(SRCS)) - -SRCFILES = $(wildcard *.c) -BINARIES=$(SRCFILES:%.c=%) - -# libgpiod compile install path -LIBS_PATH=install -CFLAGS+=-I ${LIBS_PATH}/include -LDFLAGS+=-L ${LIBS_PATH}/lib -lgpiod - -all: libs binaries install - -libs: - make -C libgpiod CROSS_COMPILE=${CROSS_COMPILE} - -binaries: ${BINARIES} - -%: %.c - $(CC) $(CFLAGS) -o $@ $< $(LDFLAGS) - -install: - cp $(BINARIES) ${INSTPATH} - -clean: - @rm -f *.o *.lo $(BINARIES) - -distclean: clean - @rm -f tags cscope* - @make clean -C libgpiod - @rm -rf install - -.PHONY: clean entry diff --git a/hal/api/infrared.c b/hal/modules/infrared.c similarity index 99% rename from hal/api/infrared.c rename to hal/modules/infrared.c index 6aa2e36..835593d 100644 --- a/hal/api/infrared.c +++ b/hal/modules/infrared.c @@ -69,7 +69,6 @@ which = atoi(optarg); break; - case 'h': /* Get help information */ program_usage(progname); return 0; diff --git a/hal/api/infrared.h b/hal/modules/infrared.h similarity index 100% rename from hal/api/infrared.h rename to hal/modules/infrared.h diff --git a/hal/modules/key.c b/hal/modules/key.c new file mode 100644 index 0000000..7df5139 --- /dev/null +++ b/hal/modules/key.c @@ -0,0 +1,171 @@ +/********************************************************************************* + * Copyright: (C) 2024 LingYun IoT System Studio + * All rights reserved. + * + * Filename: key.c + * Description: This file is linux GPIO button driver test code. + * + ********************************************************************************/ + +#include <stdio.h> +#include <unistd.h> +#include <errno.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> +#include <fcntl.h> +#include <libgen.h> +#include <getopt.h> +#include <sys/types.h> +#include <sys/ioctl.h> +#include <linux/input.h> +#include <linux/kd.h> +#include <linux/keyboard.h> + +#if 0 /* Just for comment here, Reference to linux-3.3/include/linux/input.h */ +struct input_event +{ + struct timeval time; + __u16 type; /* 0x00:EV_SYN 0x01:EV_KEY 0x04:EV_MSC 0x11:EV_LED*/ + __u16 code; /* key value, which key */ + __s32 value; /* 1: Pressed 0:Not pressed 2:Always Pressed */ +}; +#endif + +#define EV_RELEASED 0 +#define EV_PRESSED 1 +#define EV_REPEAT 2 + +#define BUTTON_CNT 1 + +#define MODE_POLL 0x01 +#define MODE_NORMAL 0x02 + +void usage(char *name); +void display_button_event(struct input_event *ev, int cnt); + +static void program_usage(const char *progname) +{ + printf("Usage: %s [OPTION]...\n", progname); + printf(" This is linux GPIO button driver test program.\n"); + + printf(" -d[device ] Specify input device number, such as 0\n"); + printf(" -h[help ] Display this help information\n"); + + printf("\n"); + printf("%s program Version v1.0.0\n", progname); + printf("Copyright (C) 2023 LingYun IoT System Studio.\n"); + + return; +} + +int main(int argc, char **argv) +{ + char *progname=NULL; + char kbd_dev[128]; + char kbd_name[128] = "Unknown"; + int kbd_fd = -1; + struct input_event ev[BUTTON_CNT]; + int size = sizeof (struct input_event); + + int which = -1; + int rv, opt; + fd_set rds; + + struct option long_options[] = { + {"device", required_argument, NULL, 'd'}, + {"help", no_argument, NULL, 'h'}, + {NULL, 0, NULL, 0} + }; + + progname = basename(argv[0]); + + /* Parser the command line parameters */ + while ((rv = getopt_long(argc, argv, "d:h", long_options, NULL)) != -1) + { + switch (rv) + { + case 'd': /* Set infrared number, such as 0...max */ + which = atoi(optarg); + break; + + case 'h': /* Get help information */ + program_usage(progname); + return 0; + + default: + break; + } + } + + if( !which ) + { + program_usage(progname); + return 1; + } + + if ((getuid ()) != 0) + printf ("You are not root! This may not work...\n"); + + snprintf(kbd_dev, sizeof(kbd_dev), "/dev/input/event%d", which); + if ((kbd_fd = open(kbd_dev, O_RDONLY)) < 0) + { + printf("Open %s failure: %s", kbd_dev, strerror(errno)); + return -1; + } + + ioctl (kbd_fd, EVIOCGNAME (sizeof (kbd_name)), kbd_name); + printf ("Monitor input device %s (%s) event on poll mode:\n", kbd_dev, kbd_name); + + while (1) + { + FD_ZERO(&rds); + FD_SET(kbd_fd, &rds); + + rv = select(kbd_fd + 1, &rds, NULL, NULL, NULL); + if (rv < 0) + { + printf("select() system call failure: %s\n", strerror(errno)); + goto cleanup; + } + else if (FD_ISSET(kbd_fd, &rds)) + { + if ((rv=read(kbd_fd, ev, size*BUTTON_CNT )) < size) + { + printf("Reading data from kbd_fd failure: %s\n", strerror(errno)); + break; + } + else + { + display_button_event(ev, rv/size); + } + } + } + +cleanup: + close(kbd_fd); + + return 0; +} + +void display_button_event(struct input_event *ev, int cnt) +{ + int i; + struct timeval pressed_time, duration_time; + + for(i=0; i<cnt; i++) + { + //printf("type:%d code:%d value:%d\n", ev[i].type, ev[i].code, ev[i].value); + if(EV_KEY==ev[i].type && EV_PRESSED==ev[i].value) + { + pressed_time = ev[i].time; + printf("Keypad[%d] pressed time: %ld.%ld\n", ev[i].code, pressed_time.tv_sec, pressed_time.tv_usec); + } + + if(EV_KEY==ev[i].type && EV_RELEASED==ev[i].value) + { + timersub(&ev[i].time, &pressed_time, &duration_time); + printf("keypad[%d] duration time: %ld.%ld\n", ev[i].code, duration_time.tv_sec, duration_time.tv_usec); + } + } +} diff --git a/hal/modules/keypad.c b/hal/modules/keypad.c new file mode 100644 index 0000000..3426c1b --- /dev/null +++ b/hal/modules/keypad.c @@ -0,0 +1,197 @@ +/********************************************************************************* + * Copyright: (C) 2021 Guo Wenxue<Email:guowenxue@gmail.com QQ:281143292> + * All rights reserved. + * + * Filename: keypad.c + * Description: This file used to test GPIO button driver builtin Linux kernel + * + * Version: 1.0.0(11/17/2021~) + * Author: Guo Wenxue <guowenxue@gmail.com> + * ChangeLog: 1, Release initial version on "11/17/2021 02:46:18 PM" + * + ********************************************************************************/ + +#include <stdio.h> +#include <unistd.h> +#include <errno.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> +#include <fcntl.h> +#include <libgen.h> +#include <getopt.h> +#include <sys/types.h> +#include <sys/ioctl.h> +#include <linux/input.h> +#include <linux/kd.h> +#include <linux/keyboard.h> + +#if 0 /* Just for comment here, Reference to linux-3.3/include/linux/input.h */ +struct input_event +{ + struct timeval time; + __u16 type; /* 0x00:EV_SYN 0x01:EV_KEY 0x04:EV_MSC 0x11:EV_LED*/ + __u16 code; /* key value, which key */ + __s32 value; /* 1: Pressed 0:Not pressed 2:Always Pressed */ +}; +#endif + +#define EV_RELEASED 0 +#define EV_PRESSED 1 + +#define BUTTON_CNT 10 + +/* 在C语言编程中,函数应该先定义再使用,如果函数的定义在函数调用后面,应该前向声明。*/ +void usage(char *name); + +void display_button_event(struct input_event *ev, int cnt); + +int main(int argc, char **argv) +{ + char *kbd_dev = "/dev/input/event1"; //默认监听按键设备; + char kbd_name[256] = "Unknown"; //用于保存获取到的设备名称 + int kbd_fd = -1; //open()打开文件的文件描述符 + int rv=0; // 函数返回值,默认返回0; + int opt; // getopt_long 解析命令行参数返回值; + int size = sizeof (struct input_event); + fd_set rds; //用于监听的事件的集合 + + struct input_event ev[BUTTON_CNT]; + + /* getopt_long参数函数第四个参数的定义,二维数组,每个成员由四个元素组成 */ + struct option long_options[] = { + /* { 参数名称,是否带参数,flags指针(NULL时将val的数值从getopt_long的返回值返回出去), + 函数找到该选项时的返回值(字符)} + */ + {"device", required_argument, NULL, 'd'}, + {"help", no_argument, NULL, 'h'}, + {NULL, 0, NULL, 0} + }; + + //获取命令行参数的解析返回值 + while ((opt = getopt_long(argc, argv, "d:h", long_options, NULL)) != -1) + { + switch (opt) + { + case 'd': + kbd_dev = optarg; + break; + + case 'h': + usage(argv[0]); + return 0; + + default: + break; + } + } + + if(NULL == kbd_dev) + { + /* 命令行argv[0]是输入的命令,如 ./keypad */ + usage(argv[0]); + return -1; + } + + /* 获取uid 建议以root权限运行确保可以正常运行 */ + if ((getuid ()) != 0) + printf ("You are not root! This may not work...\n"); + + /* 打开按键对应的设备节点,如果错误则返回负数 */ + if ((kbd_fd = open(kbd_dev, O_RDONLY)) < 0) + { + printf("Open %s failure: %s", kbd_dev, strerror(errno)); + return -1; + } + + /* 使用ioctl获取 /dev/input/event*对应的设备名字 */ + ioctl (kbd_fd, EVIOCGNAME (sizeof (kbd_name)), kbd_name); + printf ("Monitor input device %s (%s) event on poll mode:\n", kbd_dev, kbd_name); + + /* 循环使用 select() 多路复用监听按键事件 */ + while (1) + { + FD_ZERO(&rds); /* 清空 select() 的读事件集合 */ + FD_SET(kbd_fd, &rds); /* 将按键设备的文件描述符加入到读事件集合中*/ + + /* 使用select开启监听并等待多个描述符发生变化,第一个参数最大描述符+1, + 2、3、4参数分别是要监听读、写、异常三个事件的文军描述符集合; + 最后一个参数是超时时间(NULL-->永不超时,会一直阻塞住) + + 如果按键没有按下,则程序一直阻塞在这里。一旦按键按下,则按键设备有数据 + 可读,此时函数将返回。 + */ + rv = select(kbd_fd + 1, &rds, NULL, NULL, NULL); + if (rv < 0) + { + printf("Select() system call failure: %s\n", strerror(errno)); + goto CleanUp; + } + else if (FD_ISSET(kbd_fd, &rds)) /* 是按键设备发生了事件 */ + { + //read读取input设备的数据包,数据包为input_event结构体类型。 + if ((rv = read (kbd_fd, ev, size*BUTTON_CNT )) < size) + { + printf("Reading data from kbd_fd failure: %s\n", strerror(errno)); + break; + } + else + { + display_button_event(ev, rv/size); + } + } + } + +CleanUp: + close(kbd_fd); + + return 0; +} + +/* 该函数用来打印程序的使用方法 */ +void usage(char *name) +{ + char *progname = NULL; + char *ptr = NULL; + + /* 字符串拷贝函数,该函数内部将调用malloc()来动态分配内存,然后将$name + 字符串内容拷贝到malloc分配的内存中,这样使用完之后需要free释放内存. */ + ptr = strdup(name); + progname = basename(ptr); //去除该可执行文件的路径名,获取其自身名称(即keypad) + + printf("Usage: %s [-p] -d <device>\n", progname); + printf(" -d[device ] button device name\n"); + printf(" -p[poll ] Use poll mode, or default use infinit loop.\n"); + printf(" -h[help ] Display this help information\n"); + + free(ptr); //和strdup对应,释放该内存 + return; +} + +/* 该函数用来解析按键设备上报的数据,并答应按键按下的相关信息 */ +void display_button_event(struct input_event *ev, int cnt) +{ + int i; + static struct timeval pressed_time; //该变量用来存放按键按下的时间,注意static的使用。 + struct timeval duration_time; //该变量用来存放按键按下持续时间 + + for(i=0; i<cnt; i++) + { + /* 当上报的时间type为EV_KEY时候并且,value值为1或0 (1为按下,0为释放) */ + if(EV_KEY==ev[i].type && EV_PRESSED==ev[i].value) + { + pressed_time = ev[i].time; + printf("Keypad[%d] pressed time: %ld.%ld\n", + ev[i].code, pressed_time.tv_sec, pressed_time.tv_usec); + } + if(EV_KEY==ev[i].type && EV_RELEASED==ev[i].value) + { + /* 计算时间差函数 将第一个参数减去第二个参数的值的结果 放到第三个参数之中 */ + timersub(&ev[i].time, &pressed_time, &duration_time); + printf("keypad[%d] released time: %ld.%ld\n", + ev[i].code, ev[i].time.tv_sec, ev[i].time.tv_usec); + printf("keypad[%d] duration time: %ld.%ld\n", + ev[i].code, duration_time.tv_sec, duration_time.tv_usec); + } + } +} diff --git a/hal/api/led.c b/hal/modules/led.c similarity index 100% rename from hal/api/led.c rename to hal/modules/led.c diff --git a/hal/api/led.h b/hal/modules/led.h similarity index 100% rename from hal/api/led.h rename to hal/modules/led.h diff --git a/hal/api/libgpiod/build.sh b/hal/modules/libgpiod/build.sh similarity index 100% rename from hal/api/libgpiod/build.sh rename to hal/modules/libgpiod/build.sh diff --git a/hal/api/libgpiod/makefile b/hal/modules/libgpiod/makefile similarity index 100% rename from hal/api/libgpiod/makefile rename to hal/modules/libgpiod/makefile diff --git a/hal/modules/makefile b/hal/modules/makefile index a904fdc..befd362 100644 --- a/hal/modules/makefile +++ b/hal/modules/makefile @@ -26,7 +26,15 @@ SRCFILES = $(wildcard *.c) BINARIES=$(SRCFILES:%.c=%) -all: binaries install +# libgpiod compile install path +LIBS_PATH=install +CFLAGS+=-I ${LIBS_PATH}/include +LDFLAGS+=-L ${LIBS_PATH}/lib -lgpiod + +all: libs binaries install + +libs: + make -C libgpiod CROSS_COMPILE=${CROSS_COMPILE} binaries: ${BINARIES} @@ -40,6 +48,8 @@ @rm -f *.o *.lo $(BINARIES) distclean: clean - @rm -f tags cscope* + @rm -f tags cscope* + @make clean -C libgpiod + @rm -rf install .PHONY: clean entry diff --git a/hal/api/pwm.c b/hal/modules/pwm.c similarity index 100% rename from hal/api/pwm.c rename to hal/modules/pwm.c diff --git a/hal/api/relay.c b/hal/modules/relay.c similarity index 100% rename from hal/api/relay.c rename to hal/modules/relay.c diff --git a/hal/api/relay.h b/hal/modules/relay.h similarity index 100% rename from hal/api/relay.h rename to hal/modules/relay.h -- Gitblit v1.9.1