⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 keybutton.c

📁 广州友善2410开发板-2.6.13内核下键盘驱动:广州友善2410开发板仅提供了2.4.18下的驱动
💻 C
字号:
/*
*	Key button driver
*
*	Author: gomo
*	Data: 2007-11-01
*/

#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>

#include <linux/miscdevice.h>
#include <linux/sched.h>
#include <linux/delay.h>
#include <linux/poll.h>
#include <linux/spinlock.h>
#include <linux/delay.h>
#include <linux/interrupt.h>

#include <asm/arch/map.h>
#include <asm/system.h>
#include <asm/irq.h>
#include <asm/arch/regs-gpio.h>


#include <asm/hardware.h>

#define DEVICE_NAME "buttons" /*定义按键设备名*/
#define BUTTON_MAJOR 232 /*定义按键主设备号*/
static struct key_info 
{
	int irq_no;
	unsigned int gpio_port;
	int key_no;
} key_info_tab[4] = 
{ /*按键所使用的CPU资源*/
	{ IRQ_EINT1, GPIO_F1, 1 },
	{ IRQ_EINT2, GPIO_F2, 2 },
	{ IRQ_EINT3, GPIO_F3, 3 },
	{ IRQ_EINT7, GPIO_F7, 4 },
};
static int ready = 0;
static int key_value = 0;
static DECLARE_WAIT_QUEUE_HEAD(buttons_wait);

/*按键的中断服务程序*/
static irqreturn_t buttons_irq(int irq, void *dev_id, struct pt_regs *reg)
{
	struct key_info *k;
	int i = 0;
	int found = 0;
	int up = 0;
	int flags;
	for (i = 0; i < sizeof key_info_tab / sizeof key_info_tab[1]; i++) 
	{
		k = key_info_tab + i;
		if (k->irq_no == irq)
		{
			found = 1;
			break;
		}
	}
	if (!found) 
	{
		printk("bad irq %d in button\n", irq);
		return IRQ_HANDLED;
	}
	local_save_flags(flags);
//	cli();

	set_gpio_mode_user(k->gpio_port, GPIO_MODE_IN);
	up = read_gpio_bit(k->gpio_port);
//	set_external_irq(k->irq_no, S3C2410_EXTINT_BOTHEDGE, GPIO_PULLUP_DIS);
	set_irq_type(k->irq_no, IRQT_FALLING);
//	set_irq_type(k->irq_no, S3C2410_EXTINT_BOTHEDGE);
	local_irq_restore(flags);
	if (up) 
	{
		key_value = k->key_no + 0x80;
	} else
	{
		key_value = k->key_no;
	}
	ready = 1;
	wake_up_interruptible(&buttons_wait);

	return IRQ_HANDLED;
}

/*申请系统中断,中断方式为双边触发,即在上升沿和下降沿均发生中断*/
static int request_irqs(void)
{
	struct key_info *k;
	int i = 0;
	for (i = 0; i < sizeof key_info_tab / sizeof key_info_tab[1]; i++)
	{
		k = key_info_tab + i;
		set_irq_type(k->irq_no, IRQT_FALLING);
//		set_irq_type(k->irq_no, S3C2410_EXTINT_BOTHEDGE);
		if (request_irq(k->irq_no, &buttons_irq, SA_INTERRUPT, DEVICE_NAME, &buttons_irq)) 
		{
			return -1;
		}
	}
	return 0;
}
/*释放中断*/
static void free_irqs(void)
{
	struct key_info *k;
	int i = 0;
	for (i = 0; i < sizeof key_info_tab / sizeof key_info_tab[1]; i++) 
	{
		k = key_info_tab + i;
		free_irq(k->irq_no, buttons_irq);
	}
}

/*file_operations的“读“指针函数实现*/
static int sbc2410_buttons_read(struct file * file, char * buffer, size_t count, loff_t *ppos)
{
	static int key = 0;
	int flags = 0;
/*	int repeat = 0;
	if (!ready)
		return -EAGAIN;
	if (count != sizeof key_value)
		return -EINVAL;
	local_save_flags(flags);
	if (key != key_value) 
	{
		key = key_value;
		repeat = 0;
	} else
	{
		repeat = 1;
	}
	local_irq_restore(flags);
	if (repeat) 
	{
		return -EAGAIN;
	}
*/
	if (!ready)
		return -EAGAIN;
	if (count != sizeof key_value)
		return -EINVAL;
	local_save_flags(flags);
	key = key_value;
	local_irq_restore(flags);

/*使用copy_to_user把键值送到用户空间*/
	copy_to_user(buffer, &key, sizeof key);
	ready = 0;
	return sizeof key_value;
}

static unsigned int sbc2410_buttons_select (struct file *file, 
		struct poll_table_struct *wait)
{
	if (ready)
		return 1;
		poll_wait(file, &buttons_wait, wait);
	return 0;
}


static int sbc2410_buttons_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
	switch(cmd) 
	{
		default:
			return -EINVAL;
	}
}

static struct file_operations sbc2410_buttons_fops = 
{
		owner: THIS_MODULE,
		ioctl: sbc2410_buttons_ioctl,
		poll: sbc2410_buttons_select,
		read: sbc2410_buttons_read,
};

//static devfs_handle_t devfs_handle;
/*按键初始化*/
static int __init sbc2410_buttons_init(void)
{
	int ret = 0;
	ready = 0;
	/*注册按键设备*/
	ret = register_chrdev(BUTTON_MAJOR, DEVICE_NAME, &sbc2410_buttons_fops);
	if (ret < 0)
	{
		printk(DEVICE_NAME " can't register major number\n");
	return ret;
	}

	ret = request_irqs();
	if (ret) 
	{
		unregister_chrdev(BUTTON_MAJOR, DEVICE_NAME);
		printk(DEVICE_NAME " can't request irqs\n");
		return ret;
	}
/*	devfs_handle = devfs_register(NULL, DEVICE_NAME, DEVFS_FL_DEFAULT,
			BUTTON_MAJOR, 0, S_IFCHR | S_IRUSR | S_IWUSR, &sbc2410_buttons_fops, NULL);
*/
	return 0;
}


static void __exit sbc2410_buttons_exit(void)
{
//	devfs_unregister(devfs_handle);
	free_irqs();
	unregister_chrdev(BUTTON_MAJOR, DEVICE_NAME);
}

module_init(sbc2410_buttons_init);
module_exit(sbc2410_buttons_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Key driver");
MODULE_SUPPORTED_DEVICE("arm-linux 3.4.1 sc2410 keyboard");
MODULE_AUTHOR("Gomo");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -