📄 key_driver.c
字号:
/********************************************
* *GEC2410-BOX
* *date : created at 2007-09-19 by baijb
********************************************/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/miscdevice.h>
#include <linux/delay.h>
#include <linux/poll.h>
#include <linux/spinlock.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/devfs_fs_kernel.h>
#include <asm/hardware.h>
#include <asm/io.h>
#include <asm/arch/regs-gpio.h>
#define DEVICE_NAME "key_driver"
#define LEDRAW_MINOR 1
#define KBD_TIMER_DELAY (HZ/50)
static int keyMajor = 0;
//--------------------------------------------
static struct key_info
{
unsigned int irq_num;
unsigned int gpio_port;
unsigned int key_num;
} keys[2] = {
{ IRQ_EINT10, S3C2410_GPG2, 1 },
{ IRQ_EINT11, S3C2410_GPG3, 2 },
};
static int key_value = 0;
static int ready = 0;
static struct timer_list kbd_timer;
static DECLARE_WAIT_QUEUE_HEAD(key_wait);
/****************************************
* *Pin function: EXINT
****************************************/
static void init_key_exint(void)
{
__raw_writel(__raw_readl(S3C2410_GPGCON) & (~(0x0f<<4)) | (0x0a<<4), S3C2410_GPGCON); //GPG2,3--EXINT10,11
__raw_writel(__raw_readl(S3C2410_EXTINT1) & (~(0x77<<8)) | (0x22<<8), S3C2410_EXTINT1); //EXINT10,11--falling edge triger
}
/****************************************
* * Pin funciton: input
****************************************/
static void init_key_input(void)
{
__raw_writel(__raw_readl(S3C2410_GPGCON) & (~(0x0f<<4)), S3C2410_GPGCON); //GPG2,3--EXINT10,11
}
//-------------------------------------------
static void kbd_timer_handler(unsigned long date)
{
struct key_info *key=NULL;
key_value = 0;
if((__raw_readl(S3C2410_GPGDAT) & (1<<2)) == 0 ) { //GPG2--pressed
key = &keys[0];
key_value = key->key_num;
}
else if((__raw_readl(S3C2410_GPGDAT) & (1<<3)) == 0 ) { //GPG3--pressed
key = &keys[1];
key_value = key->key_num;
}
ready = 1;
del_timer(&kbd_timer);
wake_up_interruptible(&key_wait);
init_key_exint();
}
//--------------------------------------------
static irqreturn_t key_irq_handle(int irq, void *devid, struct pt_regs *regs){
init_key_input(); //GPG2,3--input.delay 20 ms,then query which key is pressed.
kbd_timer.expires = jiffies + KBD_TIMER_DELAY; //delay 20 ms
add_timer(&kbd_timer);
return IRQ_HANDLED;
}
//---------------------------------------------
static int s3c2410_key_open(struct inode *inode, struct file *filp)
{
int ret;
struct key_info *key=NULL;
printk(KERN_INFO DEVICE_NAME ": opened.\n");
init_key_exint();
ready = 0;
key = &keys[0];
ret = request_irq(key->irq_num, key_irq_handle, SA_INTERRUPT, DEVICE_NAME, NULL);
if(ret) {
printk(KERN_INFO DEVICE_NAME " Failed to request irq.\n");
return ret;
}
key = &keys[1];
ret = request_irq(key->irq_num, key_irq_handle, SA_INTERRUPT, DEVICE_NAME, NULL);
if(ret) {
printk(KERN_INFO DEVICE_NAME " Failed to request irq.\n");
return ret;
}
init_timer(&kbd_timer);
kbd_timer.function = kbd_timer_handler;
return 0;
}
//-------------------------------------------------
static ssize_t s3c2410_key_read(struct file *filp, char *buffer, size_t count, loff_t *ppos)
{
static int value;
wait_event_interruptible(key_wait, ready == 1);
// interruptible_sleep_on(&key_wait);
if(count != sizeof(key_value)) {
printk("there is no key pressed!\n");
return -EINVAL;
}
value = key_value;
copy_to_user(buffer, &value, sizeof(value));
ready = 0;
return sizeof(value);
}
//----------------------------------------------------------
static int s3c2410_key_release(struct inode *inode, struct file *filp)
{
struct key_info *key=NULL;
printk(KERN_INFO DEVICE_NAME ": released.\n");
key = &keys[0];
free_irq(key->irq_num, NULL);
key = &keys[1];
free_irq(key->irq_num, NULL);
return 0;
}
//--------------------------------------------------------
static struct file_operations s3c2410_fops = {
owner: THIS_MODULE,
open: s3c2410_key_open,
read: s3c2410_key_read,
release: s3c2410_key_release,
};
static int __init key_driver_init(void)
{
int ret;
printk("s3c2410 key_driver init\n");
ret = register_chrdev(0, DEVICE_NAME, &s3c2410_fops);
if (ret < 0) {
printk(DEVICE_NAME " can't get major number\n");
return ret;
}
keyMajor = ret;
#ifdef CONFIG_DEVFS_FS
devfs_mk_dir("key");
devfs_mk_cdev(MKDEV(keyMajor, LEDRAW_MINOR), S_IFCHR|S_IRUGO|S_IWUSR, "key/%d", 0);
#endif
return ret;
}
static void __exit key_driver_exit(void)
{
printk("key_driver exit!\n");
#ifdef CONFIG_DEVFS_FS
devfs_remove("key/%d", 0);
devfs_remove("key");
#endif
unregister_chrdev(keyMajor, DEVICE_NAME);
}
module_init(key_driver_init);
module_exit(key_driver_exit);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -