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

📄 mykey.c

📁 最常用的嵌入式LINUX字符设备驱动:触摸屏和小键盘驱动。触摸屏使用SPI接口
💻 C
字号:
/************************************************************文档类型: 原代码 项目编号: 文档编号: 修订版本: v1.0生成日期: 2001.8.15文档作者: 何雄伦审    核: ************************************************************相关文档: ucdimm上的键盘连接 文档编号      说明 ************************************************************修订说明修订版本	v1.1	修订说明 重写了select函数************************************************************/#include <linux/kernel.h>#include <asm/MC68VZ328.h>#include <asm/segment.h>#include <linux/types.h>#include <linux/fs.h>#include <linux/mm.h>#include <linux/errno.h>#include <linux/sched.h>#include <linux/tqueue.h>#include <linux/interrupt.h>#include "kbd.h"/*The size of keyboard input buffer.*/unsigned int kbd_major = 99;/*The keyboard input buffer.*/unsigned char kbd_buf[MAX_KEY_COUNT];/* The keyboard wait queque */struct wait_queque *kbd_wait;int key_count = 0;int kbd_head = 0;int kbd_end = 0;/************************************************************函数原型: static int kbd_read(struct inode*,struct file*,short*,int)功    能: Read one byte from keyboard driver's buffer,输入参数: short *buf:The point of save the readed one byte data.	 int   count:Not used.返 回 值: Sucess return 1,failed return 0.************************************************************/static int kbd_read(struct inode *node, struct file *fp,		    short *buf, int count){	if (verify_area(VERIFY_WRITE, buf, 1) == -EFAULT)		return -1;		if (key_count == 0)		return 0;		__put_user(kbd_buf[kbd_head],buf,1);	key_count --;	kbd_head ++;		if (kbd_head == MAX_KEY_COUNT) kbd_head = 0;	return 1;}/************************************************************函数原型: static int kbd_open(struct inode *,struct file*)功    能: Open the keyboard driver.输入参数: struct inode *node:not used.	 struct file  *file:not used.返 回 值: Always success so always return 0.************************************************************/static int kbd_open(struct inode *node, struct file *fp){	kbd_head = 0;	kbd_end = 0;	key_count = 0;	return 0;}/************************************************************函数原型: static void kbd_close(struct inode *node,struct file *fp) 功    能: Close the keyboard driver.In here,it do nothing.输入参数: struct inode *node:not used.	 struct file  *fp:not used.返 回 值: no return value.************************************************************/static void kbd_close(struct inode *node, struct file *fp){}/************************************************************函数原型: kbd_write(struct inode *,struct file*,const char *,int)功    能: Write the data to keyboard driver.But in our driver,	 can not write to the keyboard,so it do nothing.输入参数: All not used返 回 值: always return 0.************************************************************/int kbd_write(struct inode *node, struct file *fp,		    const char *buf, int count){	int i;		if (verify_area(VERIFY_READ, buf, 1) == -EFAULT)		return -1;		if (key_count + count < MAX_KEY_COUNT)	{		for (i = 0;i < count;i ++)		{			kbd_buf[kbd_end] = buf[i];			kbd_end ++;			key_count ++;			if (kbd_end >= MAX_KEY_COUNT)				kbd_end = 0;		}		wake_up(&kbd_wait);		return count;	}	else		return 0;}/************************************************************函数原型: static int kbd_select(struct inode *,struct file*,int,select_table *)功    能: If the keyboard driver's buffer have data to read,return 1,otherwise,	 return 0.输入参数: All arguments are not used.返 回 值: If the keyboard driver's buffer have data to read,return 1,otherwise,	 return 0.************************************************************/static int kbd_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;}static unsigned int charcase = 0;static int kbd_ioctl(struct inode *inode,struct file *filp,unsigned int cmd,unsigned long arg){	int result;	switch (cmd)	{	case 0:		/* Set the low case */		charcase = 0;		result = 2;		break;	case 1:		/* Set the up case */		charcase = 1;		result = 2;		break;	case 2:		/* Get the char case */		result = charcase;		break;	}	return result;}struct file_operations kbd_fops = {	NULL,	kbd_read,	kbd_write,	NULL,	kbd_select,	kbd_ioctl,	NULL,	kbd_open,	kbd_close,	NULL,	NULL,	NULL,	NULL};/************************************************************函数原型: static unsigned short invert(unsigned short)功    能: Invert the input data.输入参数: unsigned short data:the data witch want to invert.返 回 值: return the inverted data.************************************************************/static unsigned short invert(unsigned short data){	unsigned short tmp = 0;	int i;	for (i=0; i<11; i++)	{		if (data&(1<<i))			tmp |= (1<<(10-i));	}	return tmp;}/************************************************************函数原型: static unsigned char check(unsigned short data)功    能: Check the input data(delete the start and stop bit,check	 the parity and delete the parity bit).输入参数: unsigned short data:the data witch want to check.返 回 值: return the checked data.************************************************************/static unsigned char check(unsigned short data){	int i,par = 0;	/*Check the end bit*/	if (!(data & 0x400))		return 255;	/*Check the start bit*/	if (data & 0x1)		return 255;	/*Discard the start bit*/	data >>= 1;	for (i=0; i<8; i++)	{		if (data & (1<<i))			par++;	}		if (data & 0x100)		par++;	/*Check the parity*/	if (par%2 == 0)		return 255;	return data;}static unsigned char nortable[132] = {	/*		0    1    2    3    4    5    6    7    8    9    a    b    c    d    e    f	*/	/*00...0f*/	0x00,0x43,0x00,0x3f,0x3d,0x3b,0x3c,0x58,0x00,0x44,0x42,0x40,0x3e,0x0f,0x29,0x00,	/*10...1f*/	0x00,0x38,0x2a,0x00,0x1d,0x10,0x02,0x00,0x00,0x00,0x2c,0x1f,0x1e,0x11,0x03,0x00,	/*20...2f*/	0x00,0x2e,0x2d,0x20,0x12,0x05,0x04,0x00,0x00,0x39,0x2f,0x21,0x14,0x13,0x06,0x00,	/*30...3f*/	0x00,0x31,0x30,0x23,0x22,0x15,0x07,0x00,0x00,0x00,0x32,0x24,0x16,0x08,0x09,0x00,	/*40...4f*/	0x00,0x33,0x25,0x17,0x18,0x0b,0x0a,0x00,0x00,0x34,0x35,0x26,0x27,0x19,0x0c,0x00,	/*50...5f*/	0x00,0x00,0x28,0x00,0x1a,0x0d,0x00,0x00,0x3a,0x36,0x1c,0x1b,0x00,0x2b,0x00,0x00,	/*60...6f*/	0x00,0x56,0x00,0x00,0x00,0x00,0x0e,0x00,0x00,0x4f,0x00,0x4b,0x47,0x00,0x00,0x00,	/*70...7f*/	0x52,0x53,0x50,0x4c,0x4d,0x48,0x01,0x45,0x57,0x4e,0x51,0x4a,0x37,0x49,0x46,0x00,	/*80...83*/	0x00,0x00,0x00,0x41};static unsigned char exttable[14][2] = {	{0x11,0x64},	{0x14,0x61},	{0x70,0x6e},	{0x71,0x6f},	{0x6b,0x69},	{0x6c,0x66},	{0x69,0x6b},	{0x75,0x67},	{0x72,0x6c},	{0x7d,0x68},	{0x7a,0x6d},	{0x74,0x6a},	{0x4a,0x62},	{0x5a,0x60},};/*The PrintScreen key's make scancode*/static unsigned char PrtScr[4] = {0xe0,0x12,0xe0,0x7c};/*The PrintScreen key's break scancode*/static unsigned char BreakPrt[5] = {0xf0,0x7c,0xe0,0xf0,0x12};/*The Pause/Break key's scancode*/static unsigned char Brk[8] = {0xe1,0x14,0x77,0xe1,0xf0,0x14,0xf0,0x77};static short flag_e0 = 0;static short flag_e1 = 0;static short flag_f0 = 0;/************************************************************函数原型: static unsigned char nortrans(unsigned char scancode)功    能: Translate the normal scancode from AT scancode to microwindows'	 scancode(include make and break scancode).输入参数: unsigned char scancode:the data witch want to translate.返 回 值: return the corresponding microwindows' scancode.************************************************************/static unsigned char nortrans(unsigned char scancode){	unsigned char xtcode;	if (flag_f0 == 0)	{		if (scancode == 0xf0)		{			flag_f0 = 1;			return 0;		}		/*If the AT scancode is too lage then return*/		if (scancode > 131)			return 0;		xtcode = nortable[scancode];		/*If can't find the xt scancode then return*/		if (xtcode == 0)			return 0;	}	else	{		/* translate the break scancode */		flag_f0 = 0;		if (scancode > 131)			return 0;		xtcode = nortable[scancode];		if (xtcode == 0)			return 0;		xtcode |= 0x80;	}	/*Write the xt scancode to buffer*/	if (key_count < MAX_KEY_COUNT)	{		kbd_buf[kbd_end] = xtcode;		kbd_end ++;		key_count ++;		if (kbd_end >= MAX_KEY_COUNT)			kbd_end = 0;	}	return 1;}/************************************************************函数原型: unsigned char exttrans(unsigned char scancode)功    能: Translate the extend scancode.输入参数: unsigned char scancode:the data witch want to translate.返 回 值: return the corresponding microwindows' scancode.************************************************************/unsigned char exttrans(unsigned char scancode){	unsigned char xtcode;	int i;	if (flag_f0 == 0)	{		/* process the make scancode */		if (scancode == PrtScr[flag_e0])		{			flag_e0 ++;			if (flag_e0 >= 4)			{				/*Write the xt scancode(PrtScr make) to buffer*/				if (key_count < MAX_KEY_COUNT)				{					kbd_buf[kbd_end] = 0x63;					kbd_end ++;					key_count ++;					if (kbd_end >= MAX_KEY_COUNT)						kbd_end = 0;				}				flag_e0 = 0;			}			return 0;		}			if (scancode == 0xf0)		{			flag_f0 = 1;			return 0;		}		flag_e0 = 0;		for (i = 0;i < 14;i ++)		{			if (exttable[i][0] == scancode)			{				xtcode = exttable[i][1];				break;			}		}		if (i >= 14)			return 0;	}	else	{		/* process the break scancode */		if (scancode == BreakPrt[flag_e0])		{			flag_e0 ++;			if (flag_e0 >= 5)			{				/*Write the xt scancode(PrtScr break) to buffer*/				if (key_count < MAX_KEY_COUNT)				{					kbd_buf[kbd_end] = 0xe3;					kbd_end ++;					key_count ++;					if (kbd_end >= MAX_KEY_COUNT)						kbd_end = 0;				}				flag_f0 = 0;				flag_e0 = 0;			}			return 0;		}			flag_f0 = 0;		flag_e0 = 0;		for (i = 0;i < 14;i ++)		{			if (exttable[i][0] == scancode)			{				xtcode = exttable[i][1];				xtcode |= 0x80;				break;			}		}		if (i >= 14)			return 0;	}	/*Write the xt scancode to buffer*/	if (key_count < MAX_KEY_COUNT)	{		kbd_buf[kbd_end] = xtcode;		kbd_end ++;		key_count ++;		if (kbd_end >= MAX_KEY_COUNT)			kbd_end = 0;	}	return 1;}/************************************************************函数原型: unsigned char translate(unsigned char scancode)功    能: The translate main function,include normal and extend	 key's scancode.输入参数: unsigned char scancode:The data want to translate.返 回 值: return the translated scancode.************************************************************/unsigned char translate(unsigned char scancode){	if (flag_e0 == 0 && flag_e1 == 0)	{		/* process the normal AT scancode */		if (scancode == 0xe0)		{			flag_e0 = 1;			return 0;		}		else if (scancode == 0xe1)		{			flag_e1 = 1;			return 0;		}		return (nortrans(scancode));	}	else if (flag_e1)	{		/* process the Pause/Break key's scancode */		if (scancode == Brk[flag_e1])		{			flag_e1 ++;			if (flag_e1 >= 8)			{				/*Write the xt scancode(PrtScr break) to buffer*/				if (key_count < MAX_KEY_COUNT)				{					kbd_buf[kbd_end] = 0x77;					kbd_end ++;					key_count ++;					if (kbd_end >= MAX_KEY_COUNT)						kbd_end = 0;				}				flag_e1 = 0;			}		}		else			flag_e1 = 0;		return 0;	}	else	{		/* process the extend scancode */		return (exttrans(scancode));	}}/************************************************************函数原型: void irp_handler(int,void *,struct pt_regs)功    能: This is a interrupt handler function,it read the 11bits	 data from the SPI receive register.输入参数: All arguments are not used.返 回 值: Have not return value.************************************************************/void irq_handler(int irq, void* dev_id, struct pt_regs* regs){	short tmp;	unsigned char scancode = 0;	unsigned char result;printk("keyboard irq hander\n");		cli();	tmp = SPI1RDATA;	tmp = invert(tmp);		scancode = check(tmp);	if (scancode == 255)	{//		printk("scancode error!\n");		return;	}		result = translate(scancode);	wake_up(&kbd_wait);		sti();}/************************************************************函数原型: void initSPI()功    能: Initialize the SPI.输入参数: Have not input arguments.返 回 值: Have not return value.************************************************************/void initSPI(){	//set pin selection	PJSEL = (PJSEL&0xF2);	//SET_PKSEL(0);		//set SPI1 control/status register	SPI1CONT = 0x021A;//0000,0010,00??,1010			//set SPI1 interrupt control/status register	SPI1ICONT = 0x0800;}/************************************************************函数原型: void init_mykey()功    能: Do all the initialize work,include registe device,	 initialize the SPI,request interrupt.输入参数: No input argument.返 回 值: No return value.************************************************************/void init_mykey(){	int result;	result = register_chrdev(kbd_major, "keyboard", &kbd_fops);	if (result<0)	{		printk("keyboard: can't get major number\n");		return;	}	/*Init SPI*///	initSPI();		//free_irq(12|0x10000000, NULL);//	if (request_irq(21|0x10000000, irq_handler, SA_SHIRQ,//		"test_keyboard_irq_handler", NULL))//		printk("Cannot request irq\n");	kbd_wait = NULL;}

⌨️ 快捷键说明

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