linux kernel之在驱动中增加异步通知的例子

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include //新版内核

#include
#include
 
 
static struct class *key_irq_class;
static struct class_device  *key_class_irq;
volatile unsigned long  *gpncon=NULL;
volatile unsigned long  *gpndat=NULL;
 
static DECLARE_WAIT_QUEUE_HEAD(button_waitq);
 
/* 中断事件标志, 中断服务程序将它置1,third_drv_read将它清0 */
static volatile int ev_press = 0;
struct key_desc{
    unsigned int pin;
    unsigned int key_val;
    };
/*键值:按下时,0x01,0x02,0x03,0x04,0x05,0x06*/
/*键值:松开时,0x81,0x82,0x83,0x84,0x85,0x86*/
static unsigned char key_num;
struct key_desc keys_desc[6]={
    {1,0x01},
    {2,0x02},
    {3,0x03},
    {4,0x04},
    {5,0x05},
    {6,0x06},
};
 
static irqreturn_t key_irq(int irq, void *dev_id)
{
    struct key_desc *pin=(struct key_desc*)dev_id;
    unsigned int pinval;
    pinval=gpio_get_value(S3C64XX_GPN(pin->pin));
    if(pinval)
        {
            key_num=0x80|pin->key_val;
        }
    else
        {
            key_num=pin->key_val;
        }
    //printk("*********************");
    //printk("key_num= %x\n",key_num);
    //printk("*********************");
    //ev_press=1;/*表示中断发生了*/
    wake_up_interruptible(&button_waitq);/*唤醒休眠的进程*/
    return IRQ_HANDLED;
}
 
static int key_drv_open(struct inode  * inode, struct file * file)
{
    request_irq(IRQ_EINT(1),key_irq,IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING,"S1",&keys_desc[0]);
    request_irq(IRQ_EINT(2),key_irq,IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING,"S2",&keys_desc[1]);
    request_irq(IRQ_EINT(3),key_irq,IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING,"S3",&keys_desc[2]);
    request_irq(IRQ_EINT(4),key_irq,IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING,"S4",&keys_desc[3]);
    request_irq(IRQ_EINT(5),key_irq,IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING,"S5",&keys_desc[4]);
    request_irq(IRQ_EINT(6),key_irq,IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING,"S6",&keys_desc[5]);
    return 0;
}
static ssize_t key_drv_write(struct inode * file, const char __user *buf, size_t count, loff_t *ppos)
{
 
    return 0;
}
ssize_t key_drv_read (struct file *file, char __user *buf, size_t size, loff_t *ppos)
{
    //返回四个引脚的电平
    if(size != 1)
        return -EINVAL;
    /*如果没有按键动作发生就休眠*/
    wait_event_interruptible(button_waitq, ev_press);
    /*如果有按键动作,返回键值*/
    copy_to_user(buf,&key_num,1);
    ev_press=0;
    return 1;
}
int key_drv_release(struct inode * inode, struct file * file)
{
    free_irq(IRQ_EINT(1),&keys_desc[0]);
    free_irq(IRQ_EINT(2),&keys_desc[1]);
    free_irq(IRQ_EINT(3),&keys_desc[2]);
    free_irq(IRQ_EINT(4),&keys_desc[3]);
    free_irq(IRQ_EINT(5),&keys_desc[4]);
    free_irq(IRQ_EINT(6),&keys_desc[5]);
     
    return 0;
}
static struct file_operations key_drv_openration ={
    .owner = THIS_MODULE,
    .open = key_drv_open,
    .write =key_drv_write,
    .read=key_drv_read,
    .release=key_drv_release,
};
int major;
static int key_drv_init(void)
{
    major=register_chrdev(0,"key_irq",&key_drv_openration);
     
    key_irq_class = class_create(THIS_MODULE, "key_irq");
        //自动创建设备节点
    /* 新版的内核不能用class_device_create 要用device_create*/
    key_class_irq = device_create(key_irq_class, NULL, MKDEV(major, 0), NULL, "key"); /* /dev/xyz */
         
    gpncon = (volatile unsigned long*)ioremap(0x7F008830,16);
    gpndat=gpncon+1;//指针的操作是按照指针指向的长度为单位?
                        /*本例中使用的是unsigned long类型刚好是4个字节*/
 
    return 0;
}
static void key_drv_exit(void)
{
    unregister_chrdev(major,"key_irq");
    device_unregister(key_class_irq);
    class_destroy(key_irq_class);
 
    iounmap(gpncon);
    return 0;
}
 
module_init(key_drv_init);
module_exit(key_drv_exit);
MODULE_LICENSE("GPL");

///

#define S3C_IRQ_EINT_BASE S3C_IRQ(64+5)

#define S3C_EINT(x) ((x) + S3C_IRQ_EINT_BASE)
#define IRQ_EINT(x) S3C_EINT(x)

图片

XEINT0/GPN0    XEINT1/GPN1    XEINT2/GPN2    XEINT3/GPN3
XEINT4/GPN4    XEINT5/GPN5    XEINT6/GPN6    XEINT7/GPN7 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xx-xx-xxx-xxx

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值