Chinaunix首页 | 论坛 | 博客
  • 博客访问: 51073
  • 博文数量: 36
  • 博客积分: 2000
  • 博客等级: 大尉
  • 技术积分: 390
  • 用 户 组: 普通用户
  • 注册时间: 2009-05-23 15:42
文章分类
文章存档

2011年(1)

2009年(35)

我的朋友
最近访客

分类: LINUX

2009-08-19 20:10:30

 

//simple key1*4

#ifndef __KERNEL__
 #define __KERNEL__
#endif
#ifndef MODULE
 #define MODULE
#endif

#include
#include
#include  /* printk() */
#include  /* __init __exit */

#include  /* size_t */
#include  /* file_operation */
#include  /* Error number */
#include  /* udelay */
#include  /* copy_to_user, copy_from_user */
#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!"

阅读(533) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~