TQ2440 按键驱动程序 异步通知(发送信号)

按键驱动程序:

#include<linux/module.h>
#include<linux/kernel.h>
#include<linux/fs.h>
#include<linux/init.h>
#include<linux/delay.h>
#include<asm/irq.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/device.h>
#include<linux/miscdevice.h>
#include<linux/cdev.h>

#define DEVICE_NAME "mybuttons"

struct button_irq_desc{
	int irq;
	int pin;
	int pin_setting;
	int number;
	char *name;
};

static struct button_irq_desc button_irqs[] ={
	{IRQ_EINT1, S3C2410_GPF1, S3C2410_GPF1_EINT1, 0, "KET1"},
	{IRQ_EINT4, S3C2410_GPF4, S3C2410_GPF4_EINT4, 1, "KET2"},
	{IRQ_EINT2, S3C2410_GPF2, S3C2410_GPF2_EINT2, 2, "KET3"},
	{IRQ_EINT0, S3C2410_GPF0, S3C2410_GPF0_EINT0, 3, "KET4"},
};

static volatile int key_values;

static DECLARE_WAIT_QUEUE_HEAD(button_waitq);
static volatile int ev_press = 0;

//定义信号发送结构体
static struct fasync_struct *button_async;

static irqreturn_t irq_interrupt(int irq,void *dev_id)
{
	struct button_irq_desc *button_irqs = (struct button_irq_desc *)dev_id;
	int up;
	up = s3c2410_gpio_getpin(button_irqs->pin);

	if(up)
		key_values = (button_irqs->number+1)+0x80;
//		key_values[button_irqs->number] = (button_irqs->number+1)+0x80;
	else
		key_values = (button_irqs->number+1);
//		key_values[button_irqs->number] = (button_irqs->number+1);
	ev_press = 1;
	wake_up_interruptible(&button_waitq);

	//给应用程序发送信号
	kill_fasync(&button_async,SIGIO,POLL_IN);

	return IRQ_RETVAL(IRQ_HANDLED);
}


static int irq_open(struct inode *inode,struct file *file)
{
        int i;
	int err = 0;
        for(i = 0;i < sizeof(button_irqs)/sizeof(button_irqs[0]);i++)
        {
                s3c2410_gpio_cfgpin(button_irqs[i].pin,button_irqs[i].pin_setting);
		err = request_irq(button_irqs[i].irq,irq_interrupt,IRQ_TYPE_EDGE_BOTH,button_irqs[i].name,(void *)&button_irqs[i]);
		if(err)
			break;
        }
	if(err)
	{
		i--;
		for(;i >= 0; i--)
		{
			if(button_irqs[i].irq < 0)
				continue;
			disable_irq(button_irqs[i].irq);
			free_irq(button_irqs[i].irq,(void *)&button_irqs[i]);
		}
		return -EBUSY;
	}
	ev_press = 1;
        return 0;
}


static int irq_close(struct inode *inode,struct file *file)
{
	int i;
	for(i = 0; i < sizeof(button_irqs)/sizeof(button_irqs[0]); i++)
	{
		disable_irq(button_irqs[i].irq);
		free_irq(button_irqs[i].irq,(void *)&button_irqs[i]);
	}
	return 0;
}

static int irq_read(struct file *file,char __user *buff,size_t count,loff_t *offp)
{
	unsigned long err;
	if(!ev_press)
	{
		if(file->f_flags & O_NONBLOCK)
			return -EAGAIN;
		else
			wait_event_interruptible(button_waitq,ev_press);
	}
	err = copy_to_user(buff,&key_values,1);
	ev_press = 0;
	return 1;

}

static unsigned int irq_poll(struct file *file,struct poll_table_struct *wait)
{
	unsigned int mask = 0;
	poll_wait(file,&button_waitq,wait);
	if(ev_press)
		mask |= POLLIN | POLLRDNORM;
	return mask;

}

//分配或者释放button_fasync结构体
static int button_fasync(int fd,struct file *file,int on)
{
	return fasync_helper(fd,file,on,&button_async);
}

static struct file_operations buttons_fops =
{
        .owner	 = THIS_MODULE,
        .open 	 = irq_open,
        .release = irq_close,
	.read 	 = irq_read,
	.poll 	 = irq_poll,
	.fasync  = button_fasync,	//调用该函数设置button_fasync结构体
};

static struct miscdevice misc = {
        .minor =MISC_DYNAMIC_MINOR,
        .name = DEVICE_NAME,
        .fops = &buttons_fops,
};


static int __init buttons_init(void)
{
        int reg;
        reg = misc_register(&misc);
        printk(DEVICE_NAME" initialized\n");
        return reg;
}

static void __exit buttons_exit(void)
{
        misc_deregister(&misc);
        printk("deregister\n");
}

module_init(buttons_init);
module_exit(buttons_exit);

MODULE_AUTHOR("xh");
MODULE_DESCRIPTION("learn");
MODULE_LICENSE("GPL");

Makefile:


ifneq	($(KERNELRELEASE),)
	obj-m :=key.o
else
#	KERNELDIR :=/lib/modules/2.6.32-21-generic/build
	KERNELDIR :=/opt/EmbedSky/linux-2.6.30.4
	PWD :=$(shell pwd)

default:
	$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
endif
clean:
	rm -f *.o *.ko
.PHONY:clean

按键测试函数:

#include<stdlib.h>
#include<stdio.h>
#include<unistd.h>
#include<sys/ioctl.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<sys/select.h>
#include<sys/time.h>
#include<errno.h>
#include<fcntl.h>
#include<unistd.h>
#include<signal.h>

#define DEV "/dev/mybuttons"

int buttons_fd;

//信号处理函数
void my_signal_fun(int signum)
{
	unsigned char key_val;
	read(buttons_fd,&key_val,1);
	printf("key_val : 0x%x\n",key_val);
}

int main(void)
{
	int ret;
	int oflags;
	
	//注册信号
	signal(SIGIO,my_signal_fun);

	buttons_fd = open(DEV,O_RDWR);
	if(buttons_fd < 0)
	{
		perror(DEV);
		exit(1);
	}

	
	fcntl(buttons_fd,F_SETOWN,getpid());	//告诉驱动程序发送信号的目的进程

	oflags = fcntl(buttons_fd,F_GETFL);
	fcntl(buttons_fd,F_SETFL,oflags|FASYNC);

	while(1)
	{
		sleep(100);
	}
	return 0;
}



驱动程序还有同步互斥阻塞操作




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值