LingYun Studio embeded system framwork software, such as thirdparty build shell and lingyun library
guowenxue
2024-08-22 00394f239e79cbfe0af36eb11c02290ac76e56e2
move api to modules
1 files modified
1 files deleted
2 files added
9 files renamed
438 ■■■■ changed files
hal/api/makefile 55 ●●●●● patch | view | raw | blame | history
hal/modules/infrared.c 1 ●●●● patch | view | raw | blame | history
hal/modules/infrared.h patch | view | raw | blame | history
hal/modules/key.c 171 ●●●●● patch | view | raw | blame | history
hal/modules/keypad.c 197 ●●●●● patch | view | raw | blame | history
hal/modules/led.c patch | view | raw | blame | history
hal/modules/led.h patch | view | raw | blame | history
hal/modules/libgpiod/build.sh patch | view | raw | blame | history
hal/modules/libgpiod/makefile patch | view | raw | blame | history
hal/modules/makefile 14 ●●●● patch | view | raw | blame | history
hal/modules/pwm.c patch | view | raw | blame | history
hal/modules/relay.c patch | view | raw | blame | history
hal/modules/relay.h patch | view | raw | blame | history
hal/api/makefile
File was deleted
hal/modules/infrared.c
File was renamed from hal/api/infrared.c
@@ -69,7 +69,6 @@
                which = atoi(optarg);
                break;
            case 'h':  /* Get help information */
                program_usage(progname);
                return 0;
hal/modules/infrared.h
hal/modules/key.c
New file
@@ -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);
        }
    }
}
hal/modules/keypad.c
New file
@@ -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);
        }
    }
}
hal/modules/led.c
hal/modules/led.h
hal/modules/libgpiod/build.sh
hal/modules/libgpiod/makefile
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
hal/modules/pwm.c
hal/modules/relay.c
hal/modules/relay.h