S3C6410 按键驱动(五) --- 驱动源代码(我采用自动分配设备号的方法,注册设备)
2012-09-22 18:03
483 查看
/**********wzk_key.c ************/ /******wzk*********/ #include "wzk_key.h" int DOWN = 0; /* #define DEVICE_NAME "keys" #define KEY_MAJOR 232 static unsigned long key_table [] = { S3C64XX_GPN(0), S3C64XX_GPN(1), S3C64XX_GPN(2), S3C64XX_GPN(3), S3C64XX_GPN(4), S3C64XX_GPN(5), }; */ //timer void my_timer_callback(unsigned long tmp) { DOWN = 0; printk("timer\n"); } void init_mytimer(void) { init_timer(&mytimer); mytimer.data = 5; mytimer.expires = jiffies + 1; mytimer.function = my_timer_callback; add_timer(&mytimer); return; } void start_timer(int time_value) { int ret; DOWN = 1; ret = mod_timer(&mytimer,jiffies + msecs_to_jiffies(time_value)); if(ret) { printk("mod_timer error!\n"); return; } return; } void clear_keys(void) { int i; for(i = 0; i < 6; i++) { key_values[i] = '0'; } return; } static irqreturn_t keys_interrupt(int irq,void *dev_id) { struct key_irq *key_irqs = (struct key_irq *)dev_id; int number; clear_keys(); number = key_irqs->number; printk("number = %d\n",number); if(DOWN == 0) { switch(number) { case 0: // key_values[number] = '1'; start_timer(1000); break; case 1: // key_values[number] = '1'; start_timer(1000); break; case 2: // key_values[number] = '1'; start_timer(1000); break; case 3: // key_values[number] = '1'; start_timer(1000); break; case 4: // key_values[number] = '1'; start_timer(1000); break; case 5: // key_values[number] = '1'; start_timer(1000); break; /* tmp = readl(S3C64XX_GPNDAT); down = !(tmp & (1 << number)); break; */ default: key_values[number] = '0'; return IRQ_RETVAL(IRQ_HANDLED); } key_values[number] = '1'; ev_press = 1; wake_up_interruptible(&key_waitq); /* if(down != (key_values[number] & 1)) { key_values[number] = '0' + down; ev_press = 1; wake_up_interruptible(&key_waitq); */ printk("interrupt\n"); } return IRQ_RETVAL(IRQ_HANDLED); } int s3c6410_keys_open(struct inode *inode,struct file *file) { int num; int ret; for(num = 0; num < KEYNUM; num++) { ret = request_irq(key_irqs[num].irq,keys_interrupt,key_irqs[num].flags,key_irqs[num].name,(void*)&key_irqs[num]); } init_mytimer(); return 0; } int s3c6410_keys_close(struct inode *inode,struct file *file) { int i; int ret; for(i = 0; i < KEYNUM; i++) { free_irq(key_irqs[i].irq,(void*)&key_irqs[i]); } ret = del_timer(&mytimer); if(ret) { printk("timer is using ...\n"); } return 0; } static int s3c6410_keys_read(struct file *filp,char __user *buff,size_t count,loff_t *offp) { unsigned long err; if(!ev_press) { wait_event_interruptible(key_waitq,ev_press); printk("ev_press = %d\n",ev_press); } ev_press = 0; err = copy_to_user((void *)buff,(const void*)(&key_values),min(sizeof(key_values),count)); return min(sizeof(key_values),count); } static unsigned int s3c6410_keys_poll(struct file *file,struct poll_table_struct *wait) { unsigned int mask = 0; poll_wait(file,&key_waitq,wait); if(ev_press) mask |= POLLIN | POLLRDNORM; return mask; } static long s3c6410_keys_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { return 0; } //set gpk is interrupt mode void init_dev(void) { unsigned int tmp; s3c_gpio_cfgpin(key_table[0],S3C_GPIO_SFN(2)); s3c_gpio_cfgpin(key_table[1],S3C_GPIO_SFN(2)); s3c_gpio_cfgpin(key_table[2],S3C_GPIO_SFN(2)); s3c_gpio_cfgpin(key_table[3],S3C_GPIO_SFN(2)); s3c_gpio_cfgpin(key_table[4],S3C_GPIO_SFN(2)); s3c_gpio_cfgpin(key_table[5],S3C_GPIO_SFN(2)); tmp = readl(S3C64XX_GPNCON); printk("%x\n",tmp); } static struct file_operations s3c6410_keys_fops = { .owner = THIS_MODULE, .open = s3c6410_keys_open, .unlocked_ioctl = s3c6410_keys_ioctl, .release = s3c6410_keys_close, .read = s3c6410_keys_read, .poll = s3c6410_keys_poll }; static struct cdev cdev_keys; struct class * my_class; dev_t devno; static int __init s3c6410_keys_init(void) { int ret; // dev_t devno; printk(KERN_NOTICE "enter s3c6410_keys_init\n"); devno = MKDEV(KEY_MAJOR,0); ret = alloc_chrdev_region(&devno,0,1,DEVICE_NAME); if(ret) { printk(KERN_NOTICE "can not register led device"); return ret; } cdev_init(&cdev_keys,&s3c6410_keys_fops); cdev_keys.owner = THIS_MODULE; ret =cdev_add(&cdev_keys,devno,1); if(ret) { printk(KERN_NOTICE "can not add leds device"); return ret; } my_class = class_create(THIS_MODULE,DEVICE_NAME); if(IS_ERR(my_class)) { printk("Err: Failed in creating class\n"); return -1; } device_create(my_class,NULL,devno,NULL,DEVICE_NAME); init_dev(); printk(DEVICE_NAME " initialized\n"); return 0; } static void __exit s3c6410_keys_exit(void) { device_destroy(my_class,devno); class_destroy(my_class); cdev_del(&cdev_keys); unregister_chrdev_region(devno,1); printk(KERN_NOTICE "s3c6410_keys_exit\n"); } module_init(s3c6410_keys_init); module_exit(s3c6410_keys_exit); MODULE_LICENSE("GPL");
/**********wzk_key.h***********/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/miscdevice.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/cdev.h>
#include <asm/irq.h>
#include <mach/gpio.h>
#include <mach/regs-gpio.h>
#include <mach/gpio-bank-n.h>
#include <mach/map.h> //S3C64XX_VA_GPIO
#include <plat/gpio-cfg.h>
#include <mach/hardware.h>
#include <linux/io.h>
#include <asm/io.h>
#include <linux/sched.h>
#include <linux/poll.h>
#include <linux/interrupt.h>
#include <linux/semaphore.h>
#include <linux/timer.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
#include <mach/irqs.h>
#include <linux/timer.h>
#include <linux/jiffies.h>
#define DEVICE_NAME "keys"
#define KEY_MAJOR 189
static unsigned long key_table [] = {
S3C64XX_GPN(0),
S3C64XX_GPN(1),
S3C64XX_GPN(2),
S3C64XX_GPN(3),
S3C64XX_GPN(4),
S3C64XX_GPN(5),
};
struct key_irq{
int irq;
int number;
unsigned long flags;
char *name;
};
static struct key_irq key_irqs[] = {
{IRQ_EINT(0),0,IRQF_TRIGGER_FALLING,"KEY1"},
//./include/linux/interrupt.h
//./arch/arm/mach-s3c64xx/include/mach/irqs.h
{IRQ_EINT(1),1,IRQF_TRIGGER_FALLING,"KEY2"},
{IRQ_EINT(2),2,IRQF_TRIGGER_FALLING,"KEY3"},
{IRQ_EINT(3),3,IRQF_TRIGGER_FALLING,"KEY4"},
{IRQ_EINT(4),4,IRQF_TRIGGER_FALLING,"KEY5"},
{IRQ_EINT(5),5,IRQF_TRIGGER_FALLING,"KEY6"}
};
static DECLARE_WAIT_QUEUE_HEAD(key_waitq);
#define KEYNUM 6
static volatile int ev_press = 0;
static volatile char key_values[] = {0,0,0,0,0,0};
//static volatile int press_cnt[KEYNUM] = {0,0,0,0,0,0};
static struct timer_list mytimer;
相关文章推荐
- TQ2440 LINUX 2.6.30.4 LED驱动感言,从最初的打印字符,到自动分配设备号,到自动创建设备节点,到此设备号分控led
- 驱动中自动生成设备文件的方法
- Linux 输入设备驱动上报按键值方法
- TQ2440 LINUX 2.6.30.4 LED驱动感言,从最初的打印字符,到自动分配设备号,到自动创建设备节点,到次设备号分控led
- i2c 与 spi 设备在新版内核中不采用DTS设备树形式 在驱动添加设备信息(board_info)的方法
- linux中platform总线解析(四)(platform设备注册后自动匹配驱动)
- linux驱动入门之自动分配主设备号/创建设备节点
- Linux_8th_第1个linux驱动___自动分配主设备号
- linux字符设备驱动 自动创建设备节点的的方法
- Linux驱动编程 step-by-step (四) 字符设备的注册与设备节点的自动创建
- Linux驱动编程 step-by-step (四) 字符设备的注册与设备节点的自动创建
- linux驱动开发之自动创建设备节点的方法
- 以杂项设备驱动的方法注册字符设备驱动
- 详解C#自动注册Dll(OCX)控件的两种方法(转)
- C#自动实现Dll(OCX)控件注册的两种方法
- linux2.6标准字符设备驱动模型(手动注册)
- C#实现Dll(OCX)控件自动注册的两种方法(转)
- Linux字符驱动中动态分配设备号与动态生成设备节点
- 字符设备驱动查询方式读取按键值
- Linux那些事儿之我是Block层(2)注册一个块设备驱动