GT2440按键驱动添加fasync机制

来源:互联网 发布:微博显示mac客户端的 编辑:程序博客网 时间:2024/06/01 09:42

完整驱动代码如下:

#include <linux/module.h>#include <linux/kernel.h>#include <linux/fs.h>#include <linux/init.h>#include <linux/delay.h>#include <linux/poll.h>#include <linux/irq.h>#include <asm/irq.h>#include <linux/interrupt.h>#include <asm/uaccess.h>#include <mach/regs-gpio.h>#include <mach/hardware.h>#include <linux/platform_device.h>#include <linux/cdev.h>#include <linux/miscdevice.h>#include <linux/sched.h>#include <linux/spinlock.h>#include <linux/gpio.h>#define MODULE_NAME_IRQ"button_fasync"#define BUTTON_IRQ_MAJOR210static struct class *btn_fasync_class;static unsigned char key_vals[4] = {'0', '0', '0', '0'};static DECLARE_WAIT_QUEUE_HEAD(btn_fasync_waitq);static DEFINE_MUTEX(btn_lock);static volatile int ev_press = 0;struct fasync_struct *btn_fasync_queue;struct btn_fasync_desc {unsigned int irq_num;unsigned int pin;unsigned int pin_set;unsigned int key_num;unsigned char *btn_name;};static struct btn_fasync_desc btns_irq_desc[] = {{IRQ_EINT19,S3C2410_GPG(11),S3C2410_GPG11_EINT19,0, "KEY1"}, /* K1 */{IRQ_EINT11,S3C2410_GPG(3),S3C2410_GPG3_EINT11,1, "KEY2"}, /* K2 */{IRQ_EINT2,S3C2410_GPF(2),S3C2410_GPF2_EINT2,2, "KEY3"}, /* K3 */{IRQ_EINT0,S3C2410_GPF(0),S3C2410_GPF0_EINT0,3, "KEY4"} /* K4 */};static irqreturn_t irq_interrupt(int irq, void *dev_id){struct btn_fasync_desc *btn_fasyncs = (struct btn_fasync_desc *)dev_id;int down;down = !s3c2410_gpio_getpin(btn_fasyncs->pin);if (down != (key_vals[btn_fasyncs->key_num] & 1)){key_vals[btn_fasyncs->key_num] = '0' + down;ev_press = 1;wake_up_interruptible(&btn_fasync_waitq);kill_fasync(&btn_fasync_queue, SIGIO, POLL_IN);}return IRQ_RETVAL(IRQ_HANDLED);}static int btn_fasync_open (struct inode *inode, struct file *file){unsigned int i;down(&btn_lock);for (i = 0; i < sizeof(btns_irq_desc)/sizeof(btns_irq_desc[0]); i++) {if (btns_irq_desc[i].irq_num < 0) {continue;}request_irq(btns_irq_desc[i].irq_num, irq_interrupt, IRQ_TYPE_EDGE_BOTH,btns_irq_desc[i].btn_name,(void *)&btns_irq_desc[i]);}return 0;}static ssize_t btn_fasync_read (struct file *filp, char __user *buf, size_t count, loff_t *ppos){unsigned long cnt;if (!ev_press){if (filp->f_flags & O_NONBLOCK)return -EAGAIN;elsewait_event_interruptible(btn_fasync_waitq, ev_press);}ev_press = 0;cnt = copy_to_user(buf, (const void *)key_vals, min(sizeof(key_vals), count));return cnt ? -EFAULT : min(sizeof(key_vals), count);}static int btn_fasync_close (struct inode *inode, struct file *file){unsigned int i;for (i = 0; i < sizeof(btns_irq_desc)/sizeof(btns_irq_desc[0]); i++) {if (btns_irq_desc[i].irq_num < 0) {continue;}free_irq(btns_irq_desc[i].irq_num, (void *)&btns_irq_desc[i]);}up(&btn_lock);return 0;}static unsigned int btn_poll (struct file *file, struct poll_table_struct *wait){unsigned int mask = 0;poll_wait(file, &btn_fasync_waitq, wait);if (ev_press)mask |= POLLIN | POLLRDNORM;return mask;}static int btn_fasync (int fd, struct file *filp, int on){return fasync_helper(fd, filp, on, &btn_fasync_queue);}static struct file_operations btn_fasync_fops = {.owner =   THIS_MODULE,.open =   btn_fasync_open,.read =   btn_fasync_read,.release = btn_fasync_close,.poll =  btn_poll,.fasync  =   btn_fasync,};static int __init __btn_fasync_init(void){unsigned int ret;ret = register_chrdev(BUTTON_IRQ_MAJOR, MODULE_NAME_IRQ, &btn_fasync_fops);btn_fasync_class = class_create(THIS_MODULE, MODULE_NAME_IRQ);device_create(btn_fasync_class, NULL, MKDEV(BUTTON_IRQ_MAJOR, 0), NULL, MODULE_NAME_IRQ);return ret;}static void __exit __btn_fasync_exit(void){device_destroy(btn_fasync_class, BUTTON_IRQ_MAJOR);class_destroy(btn_fasync_class);unregister_chrdev(BUTTON_IRQ_MAJOR, MODULE_NAME_IRQ);printk("<0>button_fasync module remove.\n");}module_init(__btn_fasync_init);module_exit(__btn_fasync_exit);MODULE_LICENSE("GPL");MODULE_AUTHOR("toriejiang1991@sina.cn");MODULE_DESCRIPTION("Button irq_module test for GT2440 Board");

完整测试程序如下:

#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <fcntl.h>#include <errno.h>#include <signal.h>#include <sys/types.h>#include <sys/poll.h>int  fd;void button_signal_func(int signal_num){int  i;unsigned char key_vals[4] = {'0', '0', '0', '0'};unsigned char key_tmp_vals[4];signal_num = signal_num;if (read(fd, key_tmp_vals, sizeof(key_tmp_vals)) != sizeof(key_tmp_vals)) {printf("return values error.\n");}for (i = 0; i < sizeof(key_vals)/sizeof(key_vals[0]); i++) {if (key_vals[i] != key_tmp_vals[i]) {key_vals[i] = key_tmp_vals[i];printf("The key %d is %s\n", i+1, key_vals[i] == '0' ? "up" : "down");}}}int main(int argv,char **argc){int Oflags;signal(SIGIO, button_signal_func);if (!(fd = open("/dev/button_fasync", O_RDWR))) {printf("open the driver_node error!\n");return -EINVAL;}fcntl(fd, F_SETOWN, getpid());Oflags = fcntl(fd, F_GETFL);fcntl(fd, F_SETFL, Oflags | FASYNC);while (1){sleep(1000);}return 0;}

Makefile如下:

ifeq ($(KERNELRELEASE),)#learn to write Makefile for driverKERN_VERSION = /opt/GTStudio/GT2440/linux-2.6.38.6PWD := $(shell pwd)#Specify flags for the module compilation.#EXTAR_CFLAGS = -g -O0#Build Kernerl modulemodules:$(MAKE) -C $(KERN_VERSION) M=$(PWD) modulesmodules_install:$(MAKE) -C $(KERN_VERSION) M=$(PWD) modules_installclean:rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions Module* modules*.PHONY: modules modules_install cleanelse #Kernel moduleobj-m += btn_fasync_dev.oendif


原创粉丝点击