⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 irda_dvs.c

📁 GPIO 中断 红外遥控的红外源码(值得大家看看)
💻 C
字号:
//CR5004设备用的是gpio_3 1--4管脚  071119   zdguan


#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/poll.h>
#include <linux/delay.h>

#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/irq.h>

#include  "hi_gpio.h"
#include  "irda_dvs.h"

static Irkey_Dev irkey_t;

#define BUF_HEAD irkey_t.buf[irkey_t.head]  //?
#define BUF_TAIL irkey_t.buf[irkey_t.tail]  //?
#define INC_BUF(x,len) ((++(x))&(len-1))  

#define IN_MODE   0
#define INT_MODE  1
 

void ir_gpio_read(void)
{
    unsigned int ret ;
    gpio_dirgetbyte(GPIO_0,&ret);
//    printk("GPIO_0_DIR=0X%x\n",ret);
    ret=readw(GPIO_0_BASE+GPIO_DIR);
    printk("PIO_0_BASE+GPIO_DIR=0x%x\n",ret);
    ret=readw(GPIO_0_BASE+GPIO_IS);
    printk("GPIO_0_BASE+GPIO_IS=0x%x\n",ret);
    ret=readw(GPIO_0_BASE+GPIO_IE);
    printk("GPIO_0_BASE+GPIO_IE=0x%x\n",ret);
    ret=readw(GPIO_0_BASE+GPIO_IBE);
    printk("GPIO_0_BASE+GPIO_IBE=0x%x\n",ret);

    ret= readw(GPIO_BASE+GPIO_DIR);
    printk("PIO_2_BASE+GPIO_DIR=0x%x\n",ret);

}

static int irkey_port_init(unsigned int port_mode)
{
    if(port_mode == IN_MODE)
    {
        gpio_interruptclear(IRKEY_PORT, IRKEY_RX_PIN);
        gpio_interruptdisable(IRKEY_PORT,IRKEY_RX_PIN);
        gpio_dirsetbit(IRKEY_PORT,IRKEY_RX_PIN,DIRECTION_INPUT);
    }
    else if( port_mode == INT_MODE)
    {
       // gpio_dirsetbit(IRKEY_PORT,IRKEY_RX_PIN, DIRECTION_INPUT);
       // gpio_dirsetbit(IRKEY_PORT,3, DIRECTION_OUTPUT);
     //  printk("here\n");
        //gpio_dirsetbyte(GPIO_2,0xdf);       
        writew(0xdf,(GPIO_BASE+GPIO_DIR));
 
        gpio_interruptset(
                              IRKEY_PORT, 
                              IRKEY_RX_PIN, 
                              SENSE_BOTH, 
                              SENSE_EDGE, 
                              EVENT_FALLING_EDGE
                             );  
        gpio_interruptenable(IRKEY_PORT, IRKEY_RX_PIN);
    }
    return 0;
}



static int irkey_start(void)
{
    init_waitqueue_head(&(irkey_t.irkey_wait));
    irkey_port_init(INT_MODE);
    return 0;
}


static int read_irkey(Irkey_Info *irkey_to_user)
{
    irkey_to_user->sys_id_code =BUF_TAIL.sys_id_code;
        //printk("sys_id0x%x\n",irkey_to_user->sys_id_code);
    irkey_to_user->irkey_code =BUF_TAIL.irkey_code;
        //printk("irkey_id0x%x\n",irkey_to_user->irkey_code);
    irkey_to_user->irkey_mask_code =BUF_TAIL.irkey_mask_code;
        //printk("mask_id0x%x\n",irkey_to_user->irkey_mask_code);
    irkey_t.tail=INC_BUF(irkey_t.tail,MAX_BUF);
    return sizeof (Irkey_Info);
}



static   irqreturn_t hi_irkey_interrupt (int irq, void * dev_id, struct pt_regs *regs)
{
     int handled;
     unsigned int key_code;
     unsigned short sys_id;
     unsigned short irkey;
     unsigned short irkey_mask;
     static unsigned int count =0;
     unsigned int i;
     static unsigned int start;
     unsigned int current_irq;
     current_irq=readw(IRKEY_PORT_ADDR+GPIO_MIS);
     if(((current_irq)&(1<<IRKEY_RX_PIN))!=(1<<IRKEY_RX_PIN))goto  no_find_irq;
     spin_lock_irq(& irkey_t.irkey_lock);
     irkey_port_init(IN_MODE);
     key_code=0x00000000;
     if(((readw(IRKEY_RX_ADDR))&(IRKEY_START_MASK))!=IRKEY_START_MASK)
     {  
         for(i=0;i<8;i++)
         {
            mdelay(1);
            if(((readw(IRKEY_RX_ADDR))&(IRKEY_START_MASK))==IRKEY_START_MASK)
            goto out ;
            start=1;
         }
        while((readw(IRKEY_RX_ADDR)&(IRKEY_START_MASK))!=IRKEY_START_MASK);
        mdelay(5);
        while(count <32)
        {
            while((readw(IRKEY_RX_ADDR)&(IRKEY_START_MASK))!=IRKEY_START_MASK);
            udelay(850);
            key_code=key_code <<1;
            if(((readw(IRKEY_RX_ADDR))&(IRKEY_START_MASK))!=IRKEY_START_MASK)
                key_code =  key_code & 0xfffffffe;
            else 
            {
                key_code =  key_code |0x00000001;
                while((readw(IRKEY_RX_ADDR)&(IRKEY_START_MASK))==IRKEY_START_MASK); 
            }
            count++ ;
        }
         if(key_code!=0xffffffff)
         {
            while((key_code & 0x80000000)==0x80000000)key_code=(key_code<<1)|0x01;
         }
        sys_id=(key_code )  >> 16 ;
        //printk("sys_id0x%x\n",sys_id);
        irkey =((key_code << 16) & 0xff000000) >> 24;
       // printk("irkey0x%x\n",irkey);
        irkey_mask=(key_code & 0x000000ff);
       // printk("irkey_mask0x%x\n",irkey_mask);
        if(((irkey) & (irkey_mask))==0)
        {
            BUF_HEAD.sys_id_code=sys_id;
            BUF_HEAD.irkey_code=irkey;
            BUF_HEAD.irkey_mask_code=irkey_mask;
            irkey_t.head = INC_BUF(irkey_t.head,MAX_BUF);
        }
out :
        count=0;
        irkey_port_init(INT_MODE);
        spin_unlock_irq(& irkey_t.irkey_lock);
        handled=1;
       return  IRQ_RETVAL(handled);
    }
no_find_irq:
    irkey_port_init(INT_MODE);
    spin_unlock_irq(& irkey_t.irkey_lock);
    handled=1;
    return IRQ_RETVAL(handled);
}



static ssize_t hi_irkey_read(struct file *filp, char *buf ,size_t count,loff_t * ppos)
{   
     Irkey_Info irkey_to_user;
retry :
    if((irkey_t.head)==(irkey_t.tail))
    {
        if((filp->f_flags & O_NONBLOCK) == O_NONBLOCK)return -EAGAIN;
        interruptible_sleep_on(&(irkey_t.irkey_wait));
        if (signal_pending(current))return -ERESTARTSYS;
        goto retry;
    }
    else
    {
        int count ;
        count = read_irkey(&irkey_to_user);
        copy_to_user((struct Irkey_Info *)buf,&irkey_to_user,count);
    }
    return sizeof(Irkey_Info);
    
}




static unsigned int hi_irkey_select(struct file *file, struct poll_table_struct *wait)
{
        printk("poll ok\n");
    if((irkey_t.head)!=(irkey_t.tail)) {
        printk("poll ok\n");
        return 1;
    }
    poll_wait(file,&(irkey_t.irkey_wait),wait);
    return 0;
}




static int hi_irkey_open(struct inode *inode,struct file *filp )
{
    return irkey_start();
    
}



static int hi_irkey_release(struct inode *inode , struct file *filp)
{
    gpio_interruptdisable(IRKEY_PORT, IRKEY_RX_PIN);
    return 0;
}




static struct file_operations  hi_irkey_fops =
{
    owner   : THIS_MODULE,
    open    : hi_irkey_open,
    ioctl   :  NULL,
    poll    : hi_irkey_select,
    read    : hi_irkey_read,
    release : hi_irkey_release,
};


static int __init hi_irkey_init(void)
{
    int ret ;
    gpio_remap();
    ret = register_chrdev(DEVICE_MAJOR,DEVICE_NAME,&hi_irkey_fops);
    if(ret < 0)
    {
        printk(DEVICE_NAME"can't register\n");
        return -EAGAIN;
    }
    ret = request_irq(DEVICE_IRQ_NO,&hi_irkey_interrupt,SA_SHIRQ|SA_INTERRUPT,DEVICE_NAME,&hi_irkey_interrupt);
    if(ret)
    {
        printk(DEVICE_NAME"request IRQ(%d) failed\n",DEVICE_IRQ_NO);
        goto request_irq_failed;
    }
    printk("DVS IR_Remote Device Driver v1.0\n");
    //irkey_start();
        gpio_interruptdisable(IRKEY_PORT, IRKEY_RX_PIN);
    //ir_gpio_read();
    return 0;
    request_irq_failed:

                    unregister_chrdev(DEVICE_MAJOR,DEVICE_NAME);
    return ret;
}


static void __exit hi_irkey_exit(void)
{
    gpio_unmap();
    free_irq(DEVICE_IRQ_NO,&hi_irkey_interrupt);
    unregister_chrdev(DEVICE_MAJOR,DEVICE_NAME);
}

module_init(hi_irkey_init);
module_exit(hi_irkey_exit);
MODULE_LICENSE("GPL");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -