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

📄 smallkbd.c

📁 最常用的嵌入式LINUX字符设备驱动:触摸屏和小键盘驱动。触摸屏使用SPI接口
💻 C
字号:
/***********************************************************Document Type  : source codeItem number    : Document number:Version        : v1.0Date           : 2002.4.22Author         :zhou ze mingAuditing       : ************************************************************Correlation Document: Document number     :Explain             :************************************************************Edit explain :Edit version :************************************************************/#include <linux/kernel.h>#include <asm/MC68VZ328.h>#include <linux/fs.h>#include <linux/param.h>#include <linux/errno.h>#include <linux/sched.h>#include <linux/timer.h>#include <linux/mm.h>#include <linux/delay.h>#include "kbd.h"extern unsigned char kbd_buf[MAX_KEY_COUNT]; // keyboard bufferextern int key_count;  // key number in keyboard bufferextern int kbd_head;       // head pointer of keyboard bufferextern int kbd_end;        // tail pointer of keyboard bufferextern struct wait_queue *kbd_wait;  // keyboard wait queuestatic unsigned int _nMajor = SMALLKBD_MAJOR;	 // major devide idstruct timer_list _tmlist;static int _nDelayTime = SMALLKBD_DELAY*HZ/1000;// s1 ~ s9 key default value//static unsigned char _s[SMALLKBD_KEYNUM] = {LEFT,RIGHT,UP,DOWN,PAGEUP,PAGEDOWN,HOME,END,UNDEFINE};static unsigned char _s[SMALLKBD_KEYNUM] = {UNDEFINE,UP,RIGHT,LEFT,DOWN,PAGEUP,PAGEDOWN,UNDEFINE,UNDEFINE};// enable/disable small keyboardstatic int _smallkbd_enable = SMALLKBD_ENABLE;  // 0,disable;otherwise,enable/************************************************************Prototype: static int smallkbd_read(struct inode*,struct file*,short*,int)Function : Read one byte from keyboard driver's buffer,Parameter: short *buf : The point of save the readed one byte data.	      int count : byte number which is user required readingReturn   : Sucess return non-zero,failed return 0.************************************************************/static int smallkbd_read(struct inode *node, struct file *fp,char *buf, int count){	int i = 0;	if (-EFAULT == verify_area(VERIFY_WRITE,buf,count))		return -1;		if (0 >= key_count)	{		sleep_on(&kbd_wait);		return 0;	}	while ((i < count) && (0 < key_count))	{		__put_user(kbd_buf[kbd_head],buf+i,1);		key_count--;		kbd_head++;		if (MAX_KEY_COUNT <= kbd_head)			kbd_head = 0;		i++;	}	return i;}/************************************************************Prototype: static int smallkbd_open(struct inode *,struct file*)Function : Open the keyboard driver.Parameter: struct inode *node : not used.	      struct file  *file : not used.Return   : Always success so always return 0.************************************************************/static int smallkbd_open(struct inode *node, struct file *fp){	return 0;}/************************************************************Prototype: static void smallkbd_close(struct inode *node,struct file *fp) Function : Close the keyboard driver.In here,it do nothing.Parameter: struct inode *node : not used.	       struct file *fp : not used.Return   : no************************************************************/static void smallkbd_release(struct inode *node, struct file *fp){}/************************************************************Prototype: smallkbd_write(struct inode *,struct file*,const char *,int)Function : Write the data to keyboard driver.But in our driver,	       can not write to the keyboard,so it do nothing.Parameter: All not usedReturn   : always return 0.************************************************************/static int smallkbd_write(struct inode *node, struct file *fp,		    const char *buf, int count){	int i = 0;		if (-EFAULT == verify_area(VERIFY_READ,buf,count))		return -1;	while ((i < count) && (key_count < MAX_KEY_COUNT))	{		kbd_buf[kbd_end++] = (unsigned char)(*(buf+i));		i++;		if (MAX_KEY_COUNT <= kbd_end)			kbd_end = 0;		key_count++;	}	if (0 < i)		wake_up(&kbd_wait);	return i;}/************************************************************Prototype: static int smallkbd_select(struct inode *,struct file*,int,select_table *)Function : If the keyboard driver's buffer have data to read,return 1,otherwise,return 0Parameter: All arguments are not used.Return   : If the keyboard driver's buffer have data to read,return 1,otherwise,return 0************************************************************/static int smallkbd_select(struct inode *inode,struct file *file,int mode,select_table *table){	if (mode == SEL_IN)	{		if (key_count)			return 1;		select_wait(&kbd_wait,table);	}	return 0;}/************************************************************Prototype: static int smallkbd_ioctl(struct inode *,struct file*,unsigned int,unsigned long)Function : redefine key s1~s9Parameter: cmd = which key,1=s1,2=s2,...,9=s9           arg = key valueReturn   : 0,success,-EFAULT failure.************************************************************/static int smallkbd_ioctl(struct inode *inode,struct file *filp,unsigned int cmd,unsigned long arg){	switch(cmd)	{		case SMALLKBD_EN_DIS:			if (arg)				_smallkbd_enable = SMALLKBD_ENABLE; // enable small keyboard			else				_smallkbd_enable = SMALLKBD_DISABLE; // disable small keyboard			break;		case SMALLKBD_KEY1:		case SMALLKBD_KEY2:		case SMALLKBD_KEY3:		case SMALLKBD_KEY4:		case SMALLKBD_KEY5:		case SMALLKBD_KEY6:		case SMALLKBD_KEY7:		case SMALLKBD_KEY8:		case SMALLKBD_KEY9:			_s[cmd-1] = (unsigned char)arg;			break;		default:			return -EFAULT;			break;	}	return 0;}struct file_operations smallkbd_fops ={	NULL,	smallkbd_read,	smallkbd_write,	NULL,	smallkbd_select,	smallkbd_ioctl,	NULL,	smallkbd_open,	smallkbd_release,};/*********************************************************Prototype: unsigned int read_scancode(unsigned int nScanCode)Function : receive input-scancode,output output-scancodeParameter: nScanCode,input-scancodeReturn   : output-scancode*********************************************************/unsigned char read_scancode(const unsigned char nScanCode){	unsigned char nTemp;	nTemp = nScanCode & 0x03;	PGDATA &= 0xfc;	// write scan code to PG0~PG1	PGDATA |= nTemp;		nTemp = (PKDATA & 0x0c) >> 2;	// read scan code from PM5,PK3,PK2	nTemp |= (PMDATA & 0x20) >> 3;	return nTemp;}//extern int kbd_write(struct inode *node,struct file *fp,const char *buf,int count);/**************************************************Prototype: void AddKeytoBuf(const unsigned char keycode)Function : Add key code to keyboard bufferParameter: keycode -- key codeReturn   : no**************************************************/void AddKeytoBuf(unsigned char keycode){	if (MAX_KEY_COUNT <= key_count)			return;	kbd_buf[kbd_end] = keycode;//	printk("key value=%d\n",kbd_buf[kbd_end]);	kbd_end++;	key_count++;	if (MAX_KEY_COUNT <= kbd_end)		kbd_end = 0;	wake_up(&kbd_wait);//	kbd_write(NULL,NULL,&keycode,1);}/*********************************************************Prototype: void scan_smallkbd(void)Function : scan small keyboard,rejoin self to kernel timer list,wait for another run.Parameter: noReturn   : no*********************************************************/static unsigned char _byOldScanCode1 = 0x00,_byOldScanCode2 = 0x00;//,_byOldScanCode3 = 0x00;static short _bKeyDownFlag1 = 0,_bKeyDownFlag2 = 0;//,_bKeyDownFlag3 = 0;void scan_smallkbd(void){	unsigned char byScanCode1,byScanCode2,byScanCode3;	if (!_smallkbd_enable)	{  // disable small keyboard		init_timer(&_tmlist);		_tmlist.expires = jiffies + _nDelayTime;		_tmlist.function = (void*)scan_smallkbd;		add_timer(&_tmlist);		return;	}	byScanCode1 = read_scancode(0x02);	if ((_byOldScanCode1 == byScanCode1) && (0 == _bKeyDownFlag1))	{		_bKeyDownFlag1 = 1;		switch (byScanCode1)		{			case 0x06:  // s7 key is pressed				if (UNDEFINE != _s[1]) 					AddKeytoBuf(_s[1]);				printk("s1 is pressed\n");				break;			case 0x05:  // s8 key is pressed				if (UNDEFINE != _s[2])					AddKeytoBuf(_s[2]);				printk("s2 is pressed\n");				break;			case 0x03:  // s9 key is pressed				if (UNDEFINE != _s[3])					AddKeytoBuf(_s[3]);				printk("s3 is pressed\n");				break;			case 0x01:  // both s8,s9 are pressed				printk("s8 & s9 is pressed\n");				break;			case 0x02:  // both s7,s9 are pressed				printk("s7 & s9 is pressed\n");				break;			case 0x04:  // both s7,s8 are pressed				printk("s7 & s8 is pressed\n");				break;			case 0x00:  // s7,s8,s9 are pressed				printk("s7 & s8 & s9 is pressed\n");				break;			case 0x07:  // no key is pressed				break;			default:    // error				break;printk("scan code1 %d\n",byScanCode1);		}	}	else if (_byOldScanCode1 != byScanCode1)	{		_bKeyDownFlag1 = 0;		_byOldScanCode1 = byScanCode1;	}	byScanCode2 = read_scancode(0x01);	if ((_byOldScanCode2 == byScanCode2) && (0 == _bKeyDownFlag2))	{		_bKeyDownFlag2 = 1;		switch (byScanCode2)		{			case 0x06:  // s6 key is pressed				if (UNDEFINE != _s[4])					AddKeytoBuf(_s[4]);				printk("s4 is pressed\n");				break;			case 0x05:  // s5 key is pressed				if (UNDEFINE != _s[5])					AddKeytoBuf(_s[5]);				printk("s5 is pressed\n");				break;			case 0x03:  // s4 key is pressed				if (UNDEFINE != _s[6])					AddKeytoBuf(_s[6]);				printk("s6 is pressed\n");				break;			case 0x01:  // both s5,s6 are pressed				printk("s5 & s6 is pressed\n");				break;			case 0x02:  // both s4,s6 are pressed				printk("s4 & s6 is pressed\n");				break;			case 0x04:  // both s4,s5 are pressed				printk("s4 & s5 is pressed\n");				break;			case 0x00:  // s4,s5,s6 are pressed				printk("s4 & s5 & s6 is pressed\n");				break;			case 0x07:  // no key is pressed				break;			default:    // error				break;printk("scan code2 %d\n",byScanCode2);		}	}	else if (_byOldScanCode2 != byScanCode2)	{		_bKeyDownFlag2 = 0;		_byOldScanCode2 = byScanCode2;	}	/*byScanCode3 = read_scancode(0x06);	if ((_byOldScanCode3 == byScanCode3) && (0 == _bKeyDownFlag3))	{		_bKeyDownFlag3 = 1;		switch (byScanCode3)		{			case 0x03:  // s3 key is pressed				if (UNDEFINE != _s[2])					AddKeytoBuf(_s[2]);				printk("s3 is pressed\n");				break;			case 0x05:  // s2 key is pressed				if (UNDEFINE != _s[1])					AddKeytoBuf(_s[1]);				printk("s2 is pressed\n");				break;			case 0x06:  // s1 key is pressed				if (UNDEFINE != _s[0])					AddKeytoBuf(_s[0]);				printk("s1 is pressed\n");				break;			case 0x01:  // both s2,s3 are pressed				printk("s2 & s3 is pressed\n");				break;			case 0x02:  // both s1,s3 are pressed				printk("s1 & s3 is pressed\n");				break;			case 0x04:  // both s1,s2 are pressed				printk("s1 & s2 is pressed\n");				break;			case 0x00:  // s1,s2,s3 are pressed				printk("s1 & s2 & s3 is pressed\n");				break;			case 0x07:  // no key is pressed				break;			default:    // error				break;		}	}	else if (_byOldScanCode3 != byScanCode3)	{		_bKeyDownFlag3 = 0;		_byOldScanCode3 = byScanCode3;		}	*/	if ( (0 == byScanCode1) && (0 == byScanCode2) /*&& (0 == byScanCode3)*/ )		_byOldScanCode1 = _byOldScanCode2 /*= _byOldScanCode3*/ = 0x00;	init_timer(&_tmlist);	_tmlist.expires = jiffies + _nDelayTime;	_tmlist.function = (void*)scan_smallkbd;	add_timer(&_tmlist);}/************************************************************Prototype: void init_smallkbd(void)Function : Do all the initialize work.Parameter: No input argument.Return   : No return value.************************************************************/void init_smallkbd(void){	int nResult;	// register device	nResult = register_chrdev(_nMajor, "smallkbd", &smallkbd_fops);	if (nResult<0)	{		printk("smallkbd: can't get small keyboard major device number\n");		return;	}	// initial wait queue//	init_waitqueue(&kbd_wait);	// init PG0 ~ PG2,PK2,PK3,PM5	PKSEL |= 0x0c;	//PK2,PK3 as I/O port(set to 1)	PMSEL |= 0x20;	//PM5 as I/O port(set to 1)	PGSEL |= 0x03;	//PG0 ~ PG1 as I/O port(set to 1)	PKDIR &= 0xf3;	//PK2,PK3 as input pin(set to 0)	PMDIR &= 0xdf;	//PM5 as input pin(set to 0)	PGDIR |= 0x03;	//PG0 ~ PG1 set to output pin(set to 1)	PGPUEN |= 0x03;	//PG0 ~ PG1 pull-up enable	// initial timer list	init_timer(&_tmlist);	_tmlist.expires = _nDelayTime;	_tmlist.function = (void*)scan_smallkbd;	add_timer(&_tmlist);	printk("Init smallkbd module success.\n");}

⌨️ 快捷键说明

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