#ifndef __KERNEL__
#define __KERNEL__
#endif
#ifndef MODULE
#define MODULE
#endif
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h> /* printk() */
#include <linux/init.h> /* __init __exit */
#include <linux/types.h> /* size_t */
#include <linux/fs.h> /* file_operation */
#include <asm/uaccess.h> /* copy_to_user, copy_from_user */
#include <asm/arch/S3C2410.h>
#include <asm/hardware.h>
#include <asm/irq.h>
#include <asm/delay.h>
#include <linux/kfifo.h>
#define DRIVER_NAME "keyDriver"
#ifdef DEBUG
#define PRINTK(fmt, arg...) printk(KERN_NOTICE fmt, ##arg)
#else
#define PRINTK(fmt, arg...)
#endif
spinlock_t buff_lock;
struct kfifo *buffer;
extern void init_IO();
extern int re_IO();
static int keyDriver_Major = 0; /* Driver Major Number */
static void int_func(int irq, void *dev_id, struct pt_regs *regs)
{
char pestion=0;
int key=0;
key = re_IO();
key = key&0xf0;
key = key>>4;
switch (irq)
{
case 3:
pestion = 0xA0;
break;
case 2:
pestion = 0xB0;
break;
case 1:
pestion = 0xC0;
break;
case 0:
pestion = 0xD0;
default :
break;
}
switch (key)
{
case 0x08:
pestion |= 0x01;
break;
case 0x04:
pestion |= 0x02;
break;
case 0x02:
pestion |= 0x03;
break;
case 0x01:
pestion |= 0x04;
break;
default :
break;
}
PRINTK("pes=%x/n", pestion);
kfifo_put(buffer, &pestion, sizeof(pestion));
init_IO();
}
int re_IO()
{
int gpiodata=0;
GPFDAT = 0;
set_gpio_ctrl(GPIO_MODE_OUT|GPIO_PULLUP_EN|GPIO_F0);
set_gpio_ctrl(GPIO_MODE_OUT|GPIO_PULLUP_EN|GPIO_F1);
set_gpio_ctrl(GPIO_MODE_OUT|GPIO_PULLUP_EN|GPIO_F2);
set_gpio_ctrl(GPIO_MODE_OUT|GPIO_PULLUP_EN|GPIO_F3);
set_gpio_ctrl(GPIO_MODE_IN|GPIO_PULLUP_DIS|GPIO_F4);
set_gpio_ctrl(GPIO_MODE_IN|GPIO_PULLUP_DIS|GPIO_F5);
set_gpio_ctrl(GPIO_MODE_IN|GPIO_PULLUP_DIS|GPIO_F6);
set_gpio_ctrl(GPIO_MODE_IN|GPIO_PULLUP_DIS|GPIO_F7);
udelay(300);
write_gpio_reg(GPIO_F0,0x0f);
udelay(200);
gpiodata = read_gpio_reg(GPIO_F0);
return gpiodata;
}
void init_IO()
{
GPFDAT = 0;
GPFUP = 0;
PRINTK("io init ok_mxd/n");
set_gpio_ctrl(GPIO_MODE_IN|GPIO_PULLUP_EN|GPIO_F0);
set_gpio_ctrl(GPIO_MODE_IN|GPIO_PULLUP_EN|GPIO_F1);
set_gpio_ctrl(GPIO_MODE_IN|GPIO_PULLUP_EN|GPIO_F2);
set_gpio_ctrl(GPIO_MODE_IN|GPIO_PULLUP_EN|GPIO_F3);
set_gpio_ctrl(GPIO_MODE_OUT|GPIO_PULLUP_EN|GPIO_F4);
set_gpio_ctrl(GPIO_MODE_OUT|GPIO_PULLUP_EN|GPIO_F5);
set_gpio_ctrl(GPIO_MODE_OUT|GPIO_PULLUP_EN|GPIO_F6);
set_gpio_ctrl(GPIO_MODE_OUT|GPIO_PULLUP_EN|GPIO_F7);
udelay(200);
GPFDAT = 0x0f;
set_external_irq(IRQ_EINT0, EXT_FALLING_EDGE, 0);
set_external_irq(IRQ_EINT1, EXT_FALLING_EDGE, 0);
set_external_irq(IRQ_EINT2, EXT_FALLING_EDGE, 0);
set_external_irq(IRQ_EINT3, EXT_FALLING_EDGE, 0);
request_irq(IRQ_EINT0, int_func,SA_INTERRUPT, "GPF", int_func);
request_irq(IRQ_EINT1, int_func,SA_INTERRUPT, "GPF", int_func);
request_irq(IRQ_EINT2, int_func,SA_INTERRUPT, "GPF", int_func);
request_irq(IRQ_EINT3, int_func,SA_INTERRUPT, "GPF", int_func);
// PRINTK("out%x-%x-%x/n", GPFCON, GPFDAT, GFPUP);
}
static int keyDriver_open(struct inode *inode, struct file *filp)
{
MOD_INC_USE_COUNT;
enable_irq(IRQ_EINT0);
enable_irq(IRQ_EINT1);
enable_irq(IRQ_EINT2);
enable_irq(IRQ_EINT3);
PRINTK("myDriver open calkey!/n");
return 0;
}
static int keyDriver_release(struct inode *inode, struct file *filp)
{
MOD_DEC_USE_COUNT;
PRINTK("myDriver release calkey!/n");
return 0;
}
static ssize_t keyDriver_read(struct file *filp, char *buf, size_t count, loff_t *f_pos)
{
char key=0;
kfifo_get(buffer, &key, sizeof(key));
copy_to_user(buf, &key, sizeof(key));
return sizeof(key);
}
static struct file_operations keyDriver_fops = {
owner: THIS_MODULE,
read: keyDriver_read,
open: keyDriver_open,
release: keyDriver_release,
};
/* Module Init & Exit function */
#ifdef CONFIG_DEVFS_FS
devfs_handle_t devfs_keyDriver_dir;
devfs_handle_t devfs_keyDriver_raw;
#endif
static int __init keyModule_init(void)
{
buffer = kfifo_alloc(128, GFP_KERNEL, &buff_lock);
PRINTK("myModule_init/n");
init_IO();
keyDriver_Major = register_chrdev(0, DRIVER_NAME, &keyDriver_fops);
if(keyDriver_Major < 0)
{
PRINTK("register char device fail!/n");
return keyDriver_Major;
}
PRINTK("register myDriver OK! Major = %d/n", keyDriver_Major);
#ifdef CONFIG_DEVFS_FS
devfs_keyDriver_dir = devfs_mk_dir(NULL, "key", NULL);
devfs_keyDriver_raw = devfs_register(devfs_keyDriver_dir, "key0", DEVFS_FL_DEFAULT, keyDriver_Major, 0, S_IFCHR | S_IRUSR | S_IWUSR, &keyDriver_fops, NULL);
PRINTK("add dev file to devfs OK!/n");
#endif
return 0;
}
static void __exit keyModule_exit(void)
{
PRINTK("myModule_exit/n");
disable_irq(IRQ_EINT0);
disable_irq(IRQ_EINT1);
disable_irq(IRQ_EINT2);
disable_irq(IRQ_EINT3);
free_irq(IRQ_EINT0, NULL);
free_irq(IRQ_EINT1, NULL);
free_irq(IRQ_EINT2, NULL);
free_irq(IRQ_EINT3, NULL);
kfifo_free(buffer);
if(keyDriver_Major > 0)
{
#ifdef CONFIG_DEVFS_FS
devfs_unregister(devfs_keyDriver_raw);
devfs_unregister(devfs_keyDriver_dir);
#endif
unregister_chrdev(keyDriver_Major, DRIVER_NAME);
}
return;
}
module_init(keyModule_init);
module_exit(keyModule_exit);
这个是在试验箱上跑的,不过键盘去抖功能没加的,仅供测试的。
S3C2410, linux 2.4,GPIO_F0~F3和F4~F7端口.
呵呵~首次发一篇啊