/*********************************************************************************
|
* Copyright: (C) 2021 Guo Wenxue<Email:guowenxue@gmail.com QQ:281143292>
|
* All rights reserved.
|
*
|
* Filename: test_key.c
|
* Description: This file used to test GPIO button driver builtin Linux kernel on ARM board
|
*
|
* 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
|
|
|
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/event2";
|
char kbd_name[256] = "Unknown";
|
int kbd_fd = -1;
|
|
int rv, opt;
|
int size = sizeof (struct input_event);
|
fd_set rds;
|
|
struct input_event ev[BUTTON_CNT];
|
|
struct option long_options[] = {
|
{"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)
|
{
|
usage(argv[0]);
|
return -1;
|
}
|
|
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 (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 usage(char *name)
|
{
|
char *progname = NULL;
|
char *ptr = NULL;
|
|
ptr = strdup(name);
|
progname = basename(ptr);
|
|
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);
|
|
return;
|
}
|
|
void display_button_event(struct input_event *ev, int cnt)
|
{
|
int i;
|
struct timeval pressed_time, duration_time;
|
|
for(i=0; i<cnt; i++)
|
{
|
|
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);
|
}
|
} /* for(i=0; i<cnt; i++) */
|
}
|