#include <linux/module.h> //驱动层
#include <linux/kernel.h>
#include <mach/gpio.h>
#include <linux/gpio.h>
#include <asm/uaccess.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <plat/gpio-cfg.h>
#include <linux/interrupt.h>
#include <linux/irqreturn.h>
#include <linux/delay.h>
#include <linux/wait.h>
#include <linux/sched.h>
#include <linux/timer.h>
struct keyinfo {
unsigned int gpio;
char name[12];
int value;
int irq;
};
static struct keyinfo g_arrkey[] = {
{EXYNOS4_GPX3(2), "key1", 1, 0},
{EXYNOS4_GPX3(3), "key2", 1, 0},
{EXYNOS4_GPX3(4), "key3", 1, 0},
{EXYNOS4_GPX3(5), "key4", 1, 0},
};
static struct fasync_struct* g_ptfasync = NULL;
static DECLARE_WAIT_QUEUE_HEAD(wq);
static bool condition = 0;
static struct timer_list g_ttimer;
static irqreturn_t key_irq_handler(int irq, void * arg)
{
struct keyinfo* pkey = (struct keyinfo*)arg;
g_ttimer.data = (unsigned long)pkey;
mod_timer(&g_ttimer, jiffies + HZ / 200);
return IRQ_HANDLED;
}
static void key_timer_handler(unsigned long arg)
{
// struct keyinfo* pk = (struct keyinfo*)arg;
// printk("timer_handler: %s pressed!\n", pk->name);
kill_fasync(&g_ptfasync, SIGIO, POLL_IN);
condition = 1;
wake_up_interruptible(&wq);
}
static ssize_t key_read(struct file * filp, char __user * buff, size_t count, loff_t * offset)
{
int i = 0;
char buf[32] = {0};
int ret = 0;
wait_event_interruptible(wq, condition);
condition = 0;
for(i = 0; i < ARRAY_SIZE(g_arrkey); i++)
{
if(!gpio_get_value(g_arrkey[i].gpio))
{
sprintf(buf, "%s is pressed!", g_arrkey[i].name);
break;
}
}
ret = copy_to_user(buff, buf, min(strlen(buf), count));
return min(strlen(buf), count);
}
static int key_fasync(int fd, struct file* filp, int on)
{
printk("---drv_fasync---\n");
return fasync_helper(fd, filp, on, &g_ptfasync);
}
static struct file_operations g_tfops = {
.owner = THIS_MODULE,
.read = key_read,
.fasync = key_fasync,
};
static struct miscdevice g_tmiscdev = {
.minor = MISC_DYNAMIC_MINOR,
.name = "key_irq",
.fops = &g_tfops,
};
static int __init my_fasync_init(void)
{
int i = 0;
int ret = 0;
for(i = 0; i < ARRAY_SIZE(g_arrkey); i++)
{
gpio_request(g_arrkey[i].gpio, g_arrkey[i].name);
s3c_gpio_cfgpin(g_arrkey[i].gpio, S3C_GPIO_INPUT);
g_arrkey[i].irq = gpio_to_irq(g_arrkey[i].gpio);
ret = request_irq(g_arrkey[i].irq, key_irq_handler,
IRQF_SHARED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
g_arrkey[i].name, &g_arrkey[i]);
}
setup_timer(&g_ttimer, key_timer_handler, 0);
misc_register(&g_tmiscdev);
return 0;
}
static void __exit my_fasync_exit(void)
{
int i = 0;
misc_deregister(&g_tmiscdev);
del_timer_sync(&g_ttimer);
for(i = 0; i < ARRAY_SIZE(g_arrkey); i++)
{
free_irq(g_arrkey[i].irq, &g_arrkey[i]);
gpio_free(g_arrkey[i].gpio);
}
}
module_init(my_fasync_init);
module_exit(my_fasync_exit);
MODULE_LICENSE("GPL");
#include <stdio.h> //应用层
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
int fd = 0;
void sig_handler(int sig);
int main(int argc, char* argv[])
{
fd = open(argv[1], O_RDWR);
if(fd < 0)
{
printf("open failed!\n");
return -1;
}
signal(SIGIO, sig_handler);
int oldflag = 0;
fcntl(fd, F_SETOWN, getpid());
oldflag = fcntl(fd, F_GETFL);
printf("app: set FASYNC before...\n");
fcntl(fd, F_SETFL, oldflag | FASYNC);
printf("app: set FASYNC after...\n");
/* 当前程序就可以任意操作 */
while(1)
{
printf("hello haha!\n");
sleep(1);
}
close(fd);
return 0;
}
void sig_handler(int sig)
{
char buf[32] = {0};
printf("***sig handler***\n");
read(fd, buf, sizeof(buf));
printf("read: %s\n", buf);
}
有类似的一段断码程序分析博客:点击打开链接 https://blog.csdn.net/psvoldemort/article/details/21184525
函数的逻辑图如下: