全部博文(36)
分类: LINUX
2009-08-19 20:10:30
//simple key1*4
#ifndef __KERNEL__
#define __KERNEL__
#endif
#ifndef MODULE
#define MODULE
#endif
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "gpio.h"
#define BUFFER_SIZE 256
#define DRIVER_NAME "gpf"
#ifdef DEBUG
#define PRINTK(fmt, arg...) printk(KERN_NOTICE fmt, ##arg)
#else
#define PRINTK(fmt, arg...)
#endif
/*
KERN_EMERG 用于紧急事件,一般是系统崩溃前的提示信息
KERN_ALERT 用于需要立即采取动作的场合
KERN_CRIT 临界状态,通常设计验证的硬件或软件操作失败
KERN_ERR 用于报告错误状态.设备驱动程序通常会用它报告来自硬件的问题
KERN_WARNING 就可能出现的问题提出警告.这些问题通常不会对系统造成严重破坏
KERN_NOTICE 有必要提示的正常情况.许多安全相关的情况用这个级别汇报
KERN_INFO 提示性信息.有很多驱动程序在启动时用这个级别打印相关信息
KERN_DEBUG 用于调试的信息
*/
static int gpfDriver_Major = 0; /* Driver Major Number */
//static unsigned char gpfDriver_inMask = 0x0;
static spinlock_t buffer_lock=SPIN_LOCK_UNLOCKED;
static struct kfifo *buffer;
struct timer_list mytimer;
struct semaphore bufferlock;
/* Driver Operation Functions */
//buffer = kfifo_alloc(BUFFER_SIZE,GFP_KERNEL,&buffer_lock);
void timerhandler(unsigned long data)
{
char data_temp;
data_temp=(char)data;
kfifo_put(buffer,&data_temp,sizeof(data_temp));
up(&bufferlock);
}
void handler(int irq,void *dev_id,struct pt_regs *regs)
{
unsigned long key;
key= (unsigned long)(irq+1);
mytimer.expires = jiffies+2*HZ/100;
mytimer.data = key;
mytimer.function = timerhandler;
add_timer(&mytimer);
}
static int gpfDriver_open(struct inode *inode, struct file *filp)
{
buffer = kfifo_alloc(BUFFER_SIZE,GFP_KERNEL,&buffer_lock);
MOD_INC_USE_COUNT;
PRINTK("gpfDriver open called!\n");
return 0;
}
static int gpfDriver_release(struct inode *inode, struct file *filp)
{
// int Minor = MINOR(inode->i_rdev);
MOD_DEC_USE_COUNT;
PRINTK("gpfDriver release called!\n");
return 0;
}
static ssize_t gpfDriver_read(struct file *filp, char *buf, size_t count, loff_t *f_pos)
{
unsigned int data;
char data_temp;
data_temp = (char)data;
down(&bufferlock);
kfifo_get(buffer,&data_temp,sizeof(data_temp));
PRINTK("in gpfDriver_read data=%d\n",data_temp);
copy_to_user(buf, &data_temp, sizeof(data_temp));
PRINTK("gpfDriver read called!\n");
return sizeof(data);
}
static struct file_operations gpfDriver_fops = {
owner: THIS_MODULE,
read: gpfDriver_read,
open: gpfDriver_open,
release: gpfDriver_release,
};
/* Module Init & Exit function */
#ifdef CONFIG_DEVFS_FS
devfs_handle_t devfs_gpfDriver_dir;
devfs_handle_t devfs_gpfDriver_raw;
#endif
static int __init s3c2410_gpf_init(void)
{
/* Module init code */
PRINTK("s3c2410_gpf_init\n");
GPFUP =0X00 ;
/* Driver register */
gpfDriver_Major = register_chrdev(0, DRIVER_NAME, &gpfDriver_fops);//
if(gpfDriver_Major < 0)
{
PRINTK("register char device fail!\n");
return gpfDriver_Major;
}
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,handler,SA_INTERRUPT,"KEY1",NULL);
request_irq(IRQ_EINT1,handler,SA_INTERRUPT,"KEY2",NULL);
request_irq(IRQ_EINT2,handler,SA_INTERRUPT,"KEY3",NULL);
request_irq(IRQ_EINT3,handler,SA_INTERRUPT,"KEY4",NULL);
enable_irq(IRQ_EINT0);
enable_irq(IRQ_EINT1);
enable_irq(IRQ_EINT2);
enable_irq(IRQ_EINT3);
init_timer(&mytimer);
sema_init(&bufferlock,0);
PRINTK("register gpfDriver OK! Major = %d\n", gpfDriver_Major);
#ifdef CONFIG_DEVFS_FS
devfs_gpfDriver_dir = devfs_mk_dir(NULL, "gpfDriver", NULL);
devfs_gpfDriver_raw = devfs_register(devfs_gpfDriver_dir, "raw0", DEVFS_FL_DEFAULT, gpfDriver_Major, 0, S_IFCHR | S_IRUSR | S_IWUSR, &gpfDriver_fops, NULL);
PRINTK("add dev file to devfs OK!\n");
#endif
return 0;
}
static void __exit s3c2410_gpf_exit(void)
{
/* Module exit code */
PRINTK("s3c2410_gpf_exit\n");
/* Driver unregister */
if(gpfDriver_Major > 0)
{
#ifdef CONFIG_DEVFS_FS
devfs_unregister(devfs_gpfDriver_raw);
devfs_unregister(devfs_gpfDriver_dir);
#endif
unregister_chrdev(gpfDriver_Major, DRIVER_NAME);
}
free_irq(0,"KEY1");
free_irq(1,"KEY2");
free_irq(2,"KEY3");
free_irq(3,"KEY4");
kfifo_free(buffer);
return;
}
MODULE_AUTHOR("*****");
MODULE_LICENSE("Dual BSD/GPL");
module_init(s3c2410_gpf_init);
module_exit(s3c2410_gpf_exit);
//=======makefile
OUTPUT = gpfDriver.o
OUTPUT_DIR = output
KERNEL = /home/zhy/kernel_2.4.18
CROSSPREFIX = /usr/local/arm/2.95.3/bin/arm-linux-
CFLAGS = -Wall -I$(KERNEL)/include -c -DDEBUG
#CFLAGS += -DEXPORT_SYMTAB -DMODVERSIONS -include $(KERNEL)/include/linux/modversions.h
DEST = $(foreach fn, $(OUTPUT), $(OUTPUT_DIR)/$(fn))
ECHO_OK = echo -e "\x1b[40G\x1b[34m[ OK ]\x1b[0m"
ECHO_FAILED = echo -e "\x1b[40G\x1b[31m[ FAILED ]\x1b[0m"
all: $(OUTPUT_DIR) $(OUTPUT_DIR)/$(OUTPUT)
$(OUTPUT_DIR):
@mkdir $@
@chmod 777 -R $@
$(OUTPUT_DIR)/%.o: %.c
@echo -n "Compling $^..."
@if $(CROSSPREFIX)gcc $(CFLAGS) $^ -o $@; then $(ECHO_OK); else $(ECHO_FAILED); fi
clean:
@find . \( -name '*.[oas]' -o -name install.sh \) -type f -print | xargs rm -f
@echo "Cleaned!"