📄 keydriver.c
字号:
#ifndef __KERNEL__
#define __KERNEL__
#endif
#ifndef MODULE
#define MODULE
#endif
#include <linux/capability.h>
#include <linux/smp_lock.h>
#include <linux/module.h>
#include <linux/spinlock.h>
#include <linux/poll.h>
#include <asm/hardware.h>
#include <asm/io.h>
#include <linux/irq.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/init.h>
#include "7289.c"
#if LINUX_KERNEL_VERSION >= KERNEL_VERSION(2,4,0)
#include "linux/smp_lock.h"
#endif
#define KEY_NULL 0
//#define KEY_DOWN 0x80
#define MAX_KBD_BUF 16 /* how many do we want to buffer */
typedef unsigned char KBD_RET;
typedef struct {
//unsigned int kbdmode; /*KEYSTATUS_UP KEYSTATUS_DOWN and KEYSTATUS_REPEAT*/
KBD_RET buf[MAX_KBD_BUF]; /* protect against overrun */
unsigned int head, tail; /* head and tail for queued events */
wait_queue_head_t wq;
spinlock_t lock;
unsigned char key;
} KBD_DEV;
static KBD_DEV kbddev;
typedef struct{
unsigned char key;
//unsigned char RepeatCnt;
//unsigned char Funckey;
}Zlg7290Key;
#define zlg7289_MAJOR 18
#define BUF_HEAD (kbddev.buf[kbddev.head])
#define BUF_TAIL (kbddev.buf[kbddev.tail])
#define INCBUF(x,mod) ((++(x)) & ((mod) - 1))
char kernel_version[]=UTS_RELEASE;
devfs_handle_t dev_handle3;
static KBD_RET kbdRead(void)
{
KBD_RET kbd_ret;
spin_lock_irq(&(kbddev.lock));
kbd_ret= BUF_TAIL; //读取按键值
kbddev.tail = INCBUF(kbddev.tail, MAX_KBD_BUF);
spin_unlock_irq(&(kbddev.lock));
return kbd_ret;
}
static inline unsigned char s3c2410_Get_Key(void)
{
Zlg7290Key key;
int flags;
static unsigned char lastkey=0;
int oldiiccon;
local_irq_save(flags);
key.key = ZLG7289_Key();
local_irq_restore(flags);
if (key.key == 0xff) //没有按键
return 0;
return key.key;
}
static inline void kbdEvent_raw(void)
{
BUF_HEAD = kbddev.key; //将健值写近bufhead
kbddev.head = INCBUF(kbddev.head, MAX_KBD_BUF);
wake_up_interruptible(&(kbddev.wq));
}
void Keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
static int keystatus,oldkey;
//printk("in interrupt\n");
spin_lock_irq(&(kbddev.lock));
keystatus = GPGDAT&0x04;
//printk("%x\n",keystatus);
if(!keystatus)
{
if((oldkey=kbddev.key=s3c2410_Get_Key())!=0xff)
{ //读取健值
kbdEvent_raw();
}
} else {
kbddev.key = oldkey|0x80;
kbdEvent_raw();
}
spin_unlock_irq(&(kbddev.lock));
EINTPEND |=(1<<10);
SRCPND |= (1<<5);
INTPND |= (1<<5);
}
void zlg_7289init(void)
{
GPECON = GPECON & ~(0x3f<<22) | (0x15<<22);
ZLG7289_Init(2000);
ZLG7289_Reset();
ZLG7289_Test();
}
static int read_zlg7289(struct file *file, char *buffer, size_t count,loff_t *f_pos)
{
KBD_RET kbd_ret;
retry:
if (kbddev.head != kbddev.tail) {
kbd_ret = kbdRead();
copy_to_user(buffer, (char *)&kbd_ret, sizeof(KBD_RET));
return sizeof(KBD_RET);
} else {
if (file->f_flags & O_NONBLOCK)
return -EAGAIN;
interruptible_sleep_on(&(kbddev.wq));
if (signal_pending(current))
return -ERESTARTSYS;
goto retry;
}
return sizeof(KBD_RET);
}
static int write_zlg7289(struct file *file,const char *buf,size_t count,loff_t *f_pos)
{
return 0;
}
static int open_zlg7289(struct inode *inode,struct file *file)
{
kbddev.head = kbddev.tail = 0;
init_waitqueue_head(&(kbddev.wq));
MOD_INC_USE_COUNT;
return 0;
}
static int release_zlg7289(struct inode *inode,struct file *file)
{
MOD_DEC_USE_COUNT;
return 0;
}
static int ioctl_zlg7289(struct inode *inode,struct file *file,unsigned int cmd,unsigned long arg)
{
return 0;
}
static unsigned int s3c2410_kbd_poll(struct file *filp, struct poll_table_struct *wait)
{
//printk("poll!\n");
poll_wait(filp, &(kbddev.wq), wait);
return (kbddev.head == kbddev.tail) ? 0 : (POLLIN | POLLRDNORM);
}
struct file_operations zlg7289_fops={
read : read_zlg7289,
write: write_zlg7289,
ioctl: ioctl_zlg7289,
open : open_zlg7289,
release: release_zlg7289,
};
static int __init zlg72890_init_module(void)
{
int result,i;
char ret;
int flags;
dev_handle3 = devfs_register( NULL, "zlg7289", DEVFS_FL_DEFAULT, zlg7289_MAJOR, 0, S_IFCHR, &zlg7289_fops, NULL);
ret = set_external_irq(IRQ_EINT10, EXT_BOTH_EDGES, GPIO_PULLUP_EN);
result = request_irq(IRQ_EINT10,Keyboard_interrupt,SA_INTERRUPT,"fftkeyboard",NULL);
if (result < 0)
{
printk(KERN_INFO "test: can't install interrupt\n");
}
local_irq_save(flags);
zlg_7289init();
local_irq_restore(flags);
printk("congraulation,zlg7289 are successful registed\n");
kbddev.head = kbddev.tail = 0;
init_waitqueue_head(&(kbddev.wq));
return 0;
}
static void __exit fftclr72890_module(void)
{
//unregister_chrdev(zlg7289_major,"zlg7289");
devfs_unregister (dev_handle3);
free_irq(IRQ_EINT10, NULL);
printk("exit zlg7289\n");
}
MODULE_LICENSE("GPL");
module_init(zlg72890_init_module);
module_exit(fftclr72890_module);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -