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

📄 s3c2410-kbd-zlg7290.c

📁 此程序时周立功ZLG7290源码驱动
💻 C
字号:
/* * s3c2410-kbd-zlg7290.c * * touchScreen driver for SAMSUNG S3C2410 * * Author: threewater <threewater@up-tech.com> * Date  : $Date: 2004/06/15 17:25:00 $  * * $Revision: 1.1.2.6 $ * * Based on s3c2410-ts-ads7843.c * * This file is subject to the terms and conditions of the GNU General Public * License.  See the file COPYING in the main directory of this archive * for more details. * * History: * *  */#include <linux/config.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/init.h>#include <linux/miscdevice.h>#include <linux/sched.h>#include <linux/delay.h>#include <linux/poll.h>#include <linux/spinlock.h>#include <linux/irq.h>#include <linux/delay.h>#include <asm/hardware.h>#include <asm/arch/iic.h>/* debug macros */#undef DEBUG//#define DEBUG#ifdef DEBUG#define DPRINTK( x... )	printk("s3c2410-kbd: " ##x)#else#define DPRINTK( x... )#endif#define KEY_NULL	0#define KEY_DOWN	0x80#define MAX_KBD_BUF	16	/* how many do we want to buffer */#define DEVICE_NAME		"s3c44b0-kbd"#define KBDRAW_MINOR	1#define ZLG7289_IICCON		(IICCON_ACKEN |IICCON_CLK512 | IICCON_INTR | IICCON_CLKPRE(0x3))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 IRQ_KBD		IRQ_EINT4#define KBD_OPEN_INT()		#define KBD_CLOSE_INT()		#define ZLG7290_ADDR			0x70#define KEYMODE_REPEAT			0#define KEYMODE_NOREPEAT		1#define ZLG7290_SysReg			0#define ZLG7290_Key				1#define ZLG7290_RepeatCnt		2#define ZLG7290_FunctionKey		3#define BUF_HEAD	(kbddev.buf[kbddev.head])#define BUF_TAIL	(kbddev.buf[kbddev.tail])#define INCBUF(x,mod) 	((++(x)) & ((mod) - 1))static int kbdMajor = 0;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 ssize_t s3c2410_kbd_write(struct file *file, const char *buffer, size_t count, loff_t * ppos){	int data;	if(count!=sizeof(data)){		//error input data size		DPRINTK("the size of  input data must be %d\n", sizeof(data));		return 0;	}	copy_from_user(&data, buffer, count);	if(data==0)		kbddev.kbdmode=KEYMODE_REPEAT;	else		kbddev.kbdmode=KEYMODE_NOREPEAT;	DPRINTK("set kbdmode=%d\n", kbddev.kbdmode);	return count;}static ssize_t s3c2410_kbd_read(struct file *filp, char *buffer, size_t count, loff_t *ppos){	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 (filp->f_flags & O_NONBLOCK)			return -EAGAIN;		interruptible_sleep_on(&(kbddev.wq));		if (signal_pending(current))			return -ERESTARTSYS;		goto retry;	}	return sizeof(KBD_RET);}static unsigned int s3c2410_kbd_poll(struct file *filp, struct poll_table_struct *wait){  poll_wait(filp, &(kbddev.wq), wait);  return (kbddev.head == kbddev.tail) ? 0 : (POLLIN | POLLRDNORM); }static inline unsigned char s3c2410_Get_Key(void){	Zlg7290Key key;	static unsigned char lastkey=0;	int oldiiccon;//	int flags;//	local_irq_save(flags);		Set_IIC_mode(ZLG7289_IICCON, &oldiiccon);	IIC_ReadSerial(ZLG7290_ADDR, 1, &key, 3);	Set_IIC_mode(oldiiccon, NULL);//	local_irq_restore(flags);	if(kbddev.kbdmode==KEYMODE_REPEAT){		if(key.RepeatCnt==0 && key.Funckey!=0xff)			return 0;		if(key.key==0xff)			return 0;		DPRINTK("key=0x%x, repeat=%d, func=0x%x\n", key.key, key.RepeatCnt, key.Funckey);		if(key.key!=0){			lastkey=key.key;			return key.key|KEY_DOWN;		}		return lastkey;	}	else{ //KEYMODE_NOREPEAT mode		if (key.key == 0xff)			return 0;		if (key.key==0){			DPRINTK("key=0x%x up\n", lastkey);			return lastkey;		}				if(key.RepeatCnt==0 && key.Funckey==0xff){			lastkey=key.key;			DPRINTK("key = 0x%x\n", key.key);			return key.key|KEY_DOWN;		}	}	return 0;	}static inline void kbdEvent_raw(void){	BUF_HEAD = kbddev.key;	kbddev.head = INCBUF(kbddev.head, MAX_KBD_BUF);	wake_up_interruptible(&(kbddev.wq));}static void s3c2410_isr_kbd(int irq, void *dev_id, struct pt_regs *reg){	//DPRINTK("Zlg7290 keyboard Interrupt occured\n");	spin_lock_irq(&(kbddev.lock));	if((kbddev.key=s3c2410_Get_Key())!=0){		kbdEvent_raw();	}	spin_unlock_irq(&(kbddev.lock));}static int s3c2410_kbd_open(struct inode *inode, struct file *filp){	kbddev.head = kbddev.tail = 0;	kbddev.kbdmode= KEY_NULL;	init_waitqueue_head(&(kbddev.wq));	KBD_OPEN_INT ();	MOD_INC_USE_COUNT;	DPRINTK( "opened\n");	return 0;}static int s3c2410_kbd_release(struct inode *inode, struct file *filp){	KBD_CLOSE_INT();	MOD_DEC_USE_COUNT;	DPRINTK("closed\n");	return 0;}static struct file_operations s3c2410_fops = {  owner:	THIS_MODULE,  open:	s3c2410_kbd_open,  read:	s3c2410_kbd_read,	  write:	s3c2410_kbd_write,	  release:	s3c2410_kbd_release,  poll:	s3c2410_kbd_poll,};#ifdef CONFIG_DEVFS_FSstatic devfs_handle_t devfs_kbd_dir, devfs_kbdraw;#endifstatic int __init s3c2410_kbd_init(void){	int ret;	int oldiiccon;	int flags;	ret = set_external_irq(IRQ_KBD, EXT_FALLING_EDGE, GPIO_PULLUP_EN);	local_irq_save(flags);	IIC_init();		Set_IIC_mode(ZLG7289_IICCON, &oldiiccon);	ret=IIC_Read(ZLG7290_ADDR, 0);	//restore IICCON	Set_IIC_mode(oldiiccon, NULL);	local_irq_save(flags);	DPRINTK("zlg7290 system register=0x%x\n", ret);	KBD_CLOSE_INT();	ret = register_chrdev(0, DEVICE_NAME, &s3c2410_fops);	if (ret < 0) {		printk(DEVICE_NAME " can't get major number\n");		return ret;	}	kbdMajor = ret;	/* Enable touch interrupt */	ret = request_irq(IRQ_KBD, s3c2410_isr_kbd,SA_INTERRUPT,			DEVICE_NAME, s3c2410_isr_kbd);	if (ret) {		return ret;	}	kbddev.head = kbddev.tail = 0;	kbddev.kbdmode= KEY_NULL;	init_waitqueue_head(&(kbddev.wq));#ifdef CONFIG_DEVFS_FS	devfs_kbd_dir = devfs_mk_dir(NULL, "keyboard", NULL);	devfs_kbdraw = devfs_register(devfs_kbd_dir, "0raw", DEVFS_FL_DEFAULT,				kbdMajor, KBDRAW_MINOR, S_IFCHR | S_IRUSR | S_IWUSR, &s3c2410_fops, NULL);#endif	printk (DEVICE_NAME"\tinitialized\n");	return 0;}static void __exit s3c2410_kbd_exit(void){#ifdef CONFIG_DEVFS_FS		devfs_unregister(devfs_kbdraw);	devfs_unregister(devfs_kbd_dir);#endif	unregister_chrdev(kbdMajor, DEVICE_NAME);	free_irq(IRQ_KBD, s3c2410_isr_kbd);}module_init(s3c2410_kbd_init);module_exit(s3c2410_kbd_exit);

⌨️ 快捷键说明

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