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

📄 keyboard.c

📁 在linux内核下面的键盘驱动程序
💻 C
字号:
#include <asm/system.h> 

#include <linux/config.h> 

#include <linux/types.h> 

#include <linux/major.h> 

#include <linux/string.h> 

#include <linux/fcntl.h> 

#include <linux/slab.h> 

#include <linux/timer.h> 

#include <linux/module.h> 

#include <linux/init.h> 

#include <linux/ioport.h> 

#include <linux/poll.h> 

#include <linux/fs.h> 

#include <linux/sched.h> 

  

#include <asm/io.h> 

#include <asm/memory.h> 

#include <asm/uaccess.h> 

#include <asm/segment.h> 

#include <asm/arch/hardware.h> 

#include <asm/arch/io.h> 

#include <asm/arch/irqs.h> 

#include <asm/arch/regmap.h> 

#include <asm/irq.h> 

#define SKB_NAME "/dev/skbdriver" 

  

int __init skb_init(void); 

void __exit skb_exit(void); 

void gpio_init(void); 

static unsigned int skb_poll(struct file *filp, poll_table *wait); 

static void skb_interrupt(int irq, void *dev_id, struct pt_regs *regs); 

static ssize_t skb_read(struct file *filp, char *buf, size_t count, loff_t *l); 

static int skb_open(struct inode *inode, struct file *filp); 

static int skb_release(struct inode *inode, struct file *filp); 

  

//static wait_queue_head_t queue; 

static DECLARE_WAIT_QUEUE_HEAD(queue); 

  

static unsigned char portdata[2]; 

  

  

void gpio_init(void){ 

    unsigned long temp; 

//disable interrupt 

//  temp = readl(VIC1INTENABLE)&0xf7ffffff; 

//  writel(temp,VIC1INTENABLE); 

    disable_irq(IRQ_GPIO); 

//select irq mode   

    temp = readl(VIC1INTSELECT)&0xf7ffffff; 

    writel(temp,VIC1INTSELECT); 

//setup EGPIO(A(3-7),B(0,2)) 

//direction register 

    temp = readl(GPIO_PADDR)&0x07; 

    writel(temp,GPIO_PADDR); 

    temp = readl(GPIO_PBDDR)&0xfa; 

    writel(temp,GPIO_PBDDR); 

//interrupt enable register 

    temp = readl(GPIO_AINTEN)|~0x07; 

    writel(temp,GPIO_AINTEN); 

    temp = readl(GPIO_BINTEN)|~0xfa; 

        writel(temp,GPIO_BINTEN); 

//inttype1 register 

    temp = readl(GPIO_AINTTYPE1)|~0x07; 

    writel(temp,GPIO_AINTTYPE1); 

    temp = readl(GPIO_AINTTYPE2)|~0xfa; 

        writel(temp,GPIO_AINTTYPE2); 

    temp = readl(GPIO_BINTTYPE1)&0x07; 

        writel(temp,GPIO_BINTTYPE1); 

    temp = readl(GPIO_BINTTYPE2)&0xfa; 

        writel(temp,GPIO_BINTTYPE2); 

//EOI register 

    temp = readl(GPIO_AEOI)|~0x07; 

    writel(temp,GPIO_AEOI); 

        temp = readl(GPIO_BEOI)|~0xfa; 

        writel(temp,GPIO_BEOI); 

//debounce register 

    temp = readl(GPIO_ADB)|~0x07; 

    writel(temp,GPIO_ADB); 

        temp = readl(GPIO_BDB)|~0xfa; 

        writel(temp,GPIO_BDB); 

//enable interrupt 

//        temp = readl(VIC1INTENABLE)|~0xf7ffffff; 

//        writel(temp,VIC1INTENABLE); 

    

//  init_waitqueue_head(&queue); 

    portdata[0]=0xf8; 

    portdata[1]=0x05; 

    enable_irq(IRQ_GPIO); 

        

} 

  

static unsigned int skb_poll(struct file *filp, poll_table *wait) 

{ 

//  printk("before poll_wait\n"); 

        poll_wait(filp, &queue, wait); 

//  printk("in skb_poll\n"); 

        if (((portdata[0]&0xf8)!=0xf8)||((portdata[1]&0x05)!=0x05)) 

    { 

//      printk("faint\n"); 

                return POLLIN | POLLRDNORM; 

    } 

        return 0; 

} 

  

static void skb_interrupt(int irq, void *dev_id, struct pt_regs *regs) 

{ 

    unsigned long temp; 

    disable_irq(IRQ_GPIO); 

  

        temp = readl(GPIO_AEOI)|~0x07; 

        writel(temp,GPIO_AEOI); 

        temp = readl(GPIO_BEOI)|~0xfa; 

        writel(temp,GPIO_BEOI); 

    

    portdata[0]=readl(GPIO_PADR); 

    portdata[1]=readl(GPIO_PBDR); 

  

//  printk("%x\t%x\n",portdata[0],portdata[1]); 

  

    

    wake_up_interruptible(&queue); 

    enable_irq(IRQ_GPIO); 

} 

  

static ssize_t skb_read(struct file *filp, char *buf, size_t count, loff_t *l) 

{ 

    unsigned char data[2]; 

    ssize_t retval; 

  

  

    data[0]=portdata[0]; 

    data[1]=portdata[1]; 

        

    if(((data[0]&0xf8)==0xf8)&&((data[1]&0x05)==0x05)) 

    { 

        if (filp->f_flags & O_NONBLOCK) 

        { 

                        retval = -EAGAIN; 

        } 

    } 

    

    

    if(copy_to_user(buf, &data, sizeof(data))) 

        return -EFAULT; 

//  printk("in skb_read\n"); 

    portdata[0]=0xf8; 

    portdata[1]=0x05; 

                                                                                

        return (sizeof(data)); 

  

} 

  

static int skb_open(struct inode *inode, struct file *filp) 

{ 

//  printk("in open\n"); 

        MOD_INC_USE_COUNT; 

        return 0; 

} 

  

static int skb_release(struct inode *inode, struct file *filp) 

{ 

//  printk("in release\n"); 

        MOD_DEC_USE_COUNT; 

        return 0; 

} 

  

struct file_operations skb_fops = { 

        read:           skb_read, 

    poll:       skb_poll, 

        open:           skb_open, 

        release:        skb_release, 

}; 

  

int __init skb_init(void){ 

    int rc; 

    int ret; 

    rc = register_chrdev(144,SKB_NAME, &skb_fops); 

    if(rc<0){ 

      printk(KERN_INFO"LINBUS: Can't get Major \n"); 

      return rc; 

    } 

         printk("<1>*****************rc is %d\n",rc) ; 

  

    if ((ret = request_irq(IRQ_GPIO,skb_interrupt,SA_INTERRUPT, SKB_NAME, NULL))) 

        { 

                printk("skb_init: failed to register IRQ\n"); 

                free_irq(IRQ_GPIO, NULL); 

                return ret; 

        } 

    

    gpio_init(); 

    return 0; 

  

} 

void __exit skb_exit(void) 

{ 

        free_irq(IRQ_GPIO, NULL); 

//        devfs_unregister_chrdev(TS_MAJOR, TS_NAME); 

//        printk("ads7843 touch screen driver removed\n"); 

} 

  

module_init(skb_init); 

module_exit(skb_exit); 

⌨️ 快捷键说明

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