键盘中断驱动实验

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

} else if(kpc_value&KPC_DIR){ kbd->kbd_buff=KPDK&0xFF; if(kbd->kbd_buff!=0x0){ switch(kbd->kbd_buff){ case 0x40: kbd->kbd_buff=1; break; case 0x2: kbd->kbd_buff=2; break; case 0x4: kbd->kbd_buff=3; break; case 0x20: kbd->kbd_buff=4; break; default: break; } kbd->kbd_status=KEYVALUE_HAVE; } } if ( fasync ) kill_fasync( &(fasync), SIGIO, POLL_IN ); wake_up_interruptible(&(kbd->wq)); spin_unlock_irq(&(kbd->lock)); }
kbd_ret = kbd->kbd_buff; copy_to_user(buffer, &kbd_ret, sizeof(KBD_RET)); kbd->kbd_status=KEYVALUE_NO; return sizeof(KBD_RET); } else{ if (filp->f_flags & O_NONBLOCK) return -EAGAIN; interruptible_sleep_on(&(kbd->wq)); if (signal_pending(current)) return -ERESTARTSYS; } } return sizeof(KBD_RET); }
8-2 键盘中断驱动实验
第 1 步:利用 vi 编辑器,编写一个 Keypad.c 驱动代码; (1)增加驱动所需的头文件和变量
#include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> #include #include #include #include #include <linux/delay.h> <linux/poll.h> <linux/spinlock.h> <asm/hardware.h> <asm/arch-pxa/pxa-regs.h>
ret = request_irq(IRQ_KEYPAD, Emdoor_isr_kbd, SA_INTERRUPT, DEVICE_NAME, kbd); if (ret) { printk(KERN_EMERG " Interrupt init=%x!!!!\n",ret); return ret; } return 0; }
(6)实现键盘驱动非阻塞访问操作函数
static int Emdoor_kbd_fasync(int fd, struct file * file, int mode) { return fasync_helper(fd, file, mode, &(fasync) ); }
(7)键盘驱动文件结构体定义
static struct file_operations Keypad_fops = { open: Emdoor_kbd_open, read: Emdoor_kbd_read, release: Emdoor_kbd_release, poll: Emdoor_kbd_poll, fasync: Emdoor_kbd_fasync, owner: THIS_MODULE, };
(5)实现键盘驱动 select 和 poll 操作函数
static unsigned int Emdoor_kbd_poll(struct file *filp,struct poll_table_struct *wait) { printk(KERN_EMERG " Emdoor_kbd_poll!\n"); KBD_DEV * kbd=filp->private_data; poll_wait(filp,&(kbd->wq),wait); return (kbd->kbd_status==KEYVALUE_HAVE) ? (POLLIN|POLLRDNORM): 0 ; } static int Emdoor_kbd_release(struct inode *inode, struct file *filp) { printk(KERN_EMERG " Emdoor_kbd_release!\n"); KBD_DEV * kbd = filp->private_data; KPC=0x0; Emdoor_kbd_fasync(-1, filp, 0); kfree(kbd ); free_irq(IRQ_KEYPAD, kbd); return 0; }
(2)实现键盘驱动读操作函数
static ssize_t Emdoor_kbd_read(struct file *filp, char *buffer, size_t count, loff_t *ppos) { KBD_DEV * kbd=filp->private_data; KBD_RET kbd_ret; while(1) { if(kbd->kbd_status==KEYVALUE_HAVE) {
(4)实现键源自文库驱动设备打开操作函数
static int Emdoor_kbd_open(struct inode *inode, struct file *filp) { int ret; printk(KERN_EMERG " Emdoor_kbd_open!\n"); KBD_DEV * kbd; kbd =(KBD_DEV *) kmalloc(sizeof(KBD_DEV ), GFP_KERNEL); KPC=KPC_ASACT | (3<<26) | (7<<23 ) | KPC_IMKP | KPC_MS6 | KPC_MS5 |KPC_MS4 | KPC_MS3 | KPC_MS2 | KPC_MS1 | KPC_MS0 | KPC_ME |KPC_MIE | (7<<6) | KPC_DE | KPC_DIE; init_waitqueue_head(&(kbd->wq)); pxa_gpio_mode(94 | GPIO_ALT_FN_1_IN);//KP_DKIN<1> pxa_gpio_mode(95 | GPIO_ALT_FN_1_IN);//KP_DKIN<2> pxa_gpio_mode(98 | GPIO_ALT_FN_1_IN); pxa_gpio_mode(99 | GPIO_ALT_FN_1_IN); pxa_gpio_mode(100 | GPIO_ALT_FN_1_IN); pxa_gpio_mode(101 | GPIO_ALT_FN_1_IN); pxa_gpio_mode(102 | GPIO_ALT_FN_1_IN); pxa_gpio_mode(103 | GPIO_ALT_FN_2_OUT);//KP_MKOUT<0> pxa_gpio_mode(104 | GPIO_ALT_FN_2_OUT);//KP_MKOUT<1> pxa_gpio_mode(105 | GPIO_ALT_FN_2_OUT);//KP_MKOUT<2> pxa_gpio_mode(108 | GPIO_ALT_FN_2_OUT);//KP_MKOUT<5> kbd->kbd_status=KEYVALUE_NO; filp->private_data=kbd;
(8)键盘驱动初始化函数定义
static int __init Emdoor_kbd_init(void) { printk(KERN_EMERG " Emdoor_kpd initialized\n"); int ret; ret = register_chrdev(62, DEVICE_NAME, &Keypad_fops); if (ret < 0) { printk(DEVICE_NAME " can't get major number\n"); return ret; } free_irq(IRQ_KEYPAD,NULL); udelay(10); return 0; }
(3)实现键盘驱动中断服务例程
static void Emdoor_isr_kbd(int irq, void *dev_id, struct pt_regs *reg) { printk(KERN_EMERG"Emdoor_isr_kbd,Interrupt\n"); int kpc_value; KBD_DEV * kbd = (KBD_DEV *) dev_id; spin_lock_irq(&(kbd->lock)); kpc_value=KPC; if(kpc_value&KPC_MAT) { kbd->kbd_buff=KPAS&0xFF; if(kbd->kbd_buff!=0xFF){ switch(kbd->kbd_buff){ case 0x0: kbd->kbd_buff=5; break; case 0x1: kbd->kbd_buff=6; break; case 0x2: kbd->kbd_buff=7; break; case 0x5: kbd->kbd_buff=8; break; case 0x10: kbd->kbd_buff=9; break; case 0x11: kbd->kbd_buff=10; break; case 0x12: kbd->kbd_buff=11; break; case 0x15: kbd->kbd_buff=12; break; case 0x20: kbd->kbd_buff=13; break; case 0x21: kbd->kbd_buff=14; break; case 0x22: kbd->kbd_buff=15; break; case 0x25: kbd->kbd_buff=16; break; default: break; } kbd->kbd_status=KEYVALUE_HAVE; }
(8)键盘驱动退出函数定义
static void __exit Emdoor_kbd_exit(void) { printk(KERN_EMERG " Emdoor_kpd exit\n"); unregister_chrdev(62, DEVICE_NAME); } module_init(Emdoor_kbd_init); module_exit(Emdoor_kbd_exit); MODULE_AUTHOR("Ben.li@emdoor.com.cn"); MODULE_DESCRIPTION("This is a Keypad driver demo");
MODULE_LICENSE("GPL"); #define DEVICE_NAME "emdoor_kbd" #define KEYVALUE_HAVE 1 #define KEYVALUE_NO 0 #define KPC_DIR 1<<5 #define KPC_MAT 1<<22 static int Emdoor_kbd_fasync(int, struct file* ,int); typedef unsigned char KBD_RET; struct fasync_struct * fasync; //键盘结构体定义 typedef struct { KBD_RET kbd_buff; /* protect against overrun */ unsigned int kbd_status; wait_queue_head_t wq; spinlock_t lock; } KBD_DEV;
相关文档
最新文档