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

📄 at91_ps2.c

📁 at91_ps2_驱动~at91sam9261的IO口模拟PS2键盘驱动程序设计——最新
💻 C
字号:
/*
 * Driver for PS/2 keyboard on GPIO lines capable of generating interrupts.
 *
 * Copyright 2008 zhixiong peng
 *
 */
#include <linux/module.h>
#include <linux/version.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/sched.h>
#include <linux/pm.h>
#include <linux/sysctl.h>
#include <linux/proc_fs.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/input.h>
#include <linux/irq.h>
#include <linux/gpio_keys.h>
#include <linux/PS2.h>
#include <linux/lib_AT91SAM9261s.h>

#include <asm/gpio.h>

#include <asm/mach/arch.h>
#include <linux/platform_device.h>
#include <asm/arch/board.h>
#include <asm/arch/gpio.h>
#include <asm/arch/at91sam9261.h>
#include <asm/arch/at91sam9261_matrix.h>
#include <asm/arch/at91sam926x_mc.h>


#include <linux/clk.h>
#include <linux/kernel.h>
#include <asm/io.h>
#include <asm/arch/at91_pio.h>

#define irq_no 5
//#define AT91C_BASE_AIC 0x00000000

extern	void	fiq_asm_handler(void);
extern	void	irq2_asm_irq_handler(void);

PS2_BUF	PS2Buf;		// PS/2 键盘

static void at91_ps2_tasklet(unsigned long data);			

DECLARE_TASKLET_DISABLED(ps2_tasklet, at91_ps2_tasklet,0); 
//定义一个tasket结构ps2_tasklet,并把ps2_tasket与at91_ps2_tasklet绑定


static void at91_ps2_tasklet(unsigned long data)
{
	printk(KERN_INFO"at91_ps2_tasklet_ISR test!\n");
}


static irqreturn_t  at91_ps2_isr(int irq, void *dev_id)//struct pt_regs *regs)
{
	int	   j;
	struct platform_device *pdev = dev_id;
	struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
	struct input_dev *input = platform_get_drvdata(pdev);	
	for (j = 0; j < pdata->nbuttons; j++) 
	{
		int gpio = pdata->buttons[j].gpio;
		if (irq == gpio_to_irq(gpio)) 
		{
			int state = (gpio_get_value(gpio) ? 1 : 0) ^ (pdata->buttons[j].active_low);
		//(gpio_get_value(gpio)成立取1不成立取0  
		//异或(pdata->buttons[j].active_low)相同为0不同为 1
			input_report_key(input, pdata->buttons[j].keycode, state);
			input_sync(input);	
		}
	}	
	printk(KERN_INFO"at91_ps2_isr_show\n");
	return IRQ_HANDLED;
}

static int __devinit at91_ps2_probe(struct platform_device *pdev)		//探测设备
{
	struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
	struct input_dev *input;
	int i, error;

	input = input_allocate_device();
	if (!input)
	return -ENOMEM;
	platform_set_drvdata(pdev, input);

	input->evbit[0] = BIT(EV_KEY);

	input->name = pdev->name;
	input->phys = "gpio-keys/input0";
	input->cdev.dev = &pdev->dev;
	input->private  = pdata;

	input->id.bustype = BUS_HOST;
	input->id.vendor  = 0x0001;
	input->id.product = 0x0001;
	input->id.version = 0x0100;

	for (i = 0; i < pdata->nbuttons; i++) {
		int code = pdata->buttons[i].keycode;
		int irq  = gpio_to_irq(pdata->buttons[i].gpio);

		set_irq_type(irq, IRQ_TYPE_EDGE_BOTH);
		error = request_irq(irq, at91_ps2_isr, IRQF_SAMPLE_RANDOM,
				     pdata->buttons[i].desc ? pdata->buttons[i].desc : "gpio_keys",
				     pdev);
		if (error) {
			printk(KERN_ERR "gpio-keys: unable to claim irq %d; error %d\n",
				irq, error);
			goto fail;
		}
		set_bit(code, input->keybit);		//告知input子系统 支持的事件
	}

	error = input_register_device(input);
	if (error)
    {
		printk(KERN_ERR "Unable to register gpio-keys input device\n");
		goto fail;
	}
	return 0;

 fail:
	for (i = i - 1; i >= 0; i--)
	free_irq(gpio_to_irq(pdata->buttons[i].gpio), pdev);
	input_free_device(input);
	printk(KERN_INFO"at91_ps2_probe\n");
	return 0;
}

static int __devexit at91_ps2_remove(struct platform_device *pdev)	//移除/卸载
{
	struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
	struct input_dev *input = platform_get_drvdata(pdev);
	int i;

	for (i = 0; i < pdata->nbuttons; i++) {
		int irq = gpio_to_irq(pdata->buttons[i].gpio);
		free_irq(irq, pdev);
	}

	input_unregister_device(input);

	return 0;
}

struct platform_driver at91_ps2_device_driver = 
{
	.probe		= at91_ps2_probe,
	.remove		= __devexit_p(at91_ps2_remove),
	.driver		= {
	.name 		= "at91_ps2_keyboard",
	},
};

static int __init at91_ps2_init(void)
{
	int result,ret;
	result = platform_driver_register(&at91_ps2_device_driver);		//设备号注册
	if (result == 0)
	{
		printk(KERN_INFO"at91_ps2_keyboard registered new interface driver\n");
		
	}
	if (result != 0)
	{
		printk(KERN_INFO"AT91_PS2_KEYBOARD_can't registered\n");
	}	
		
	ret = request_irq(irq_no,at91_ps2_isr,SA_INTERRUPT,	
			"at91_ps2_irq",&at91_ps2_device_driver);//中断号注册
	if(ret == 0)					//注册成功
	{
		printk(KERN_INFO"at91_ps2_irq registered\n");
	}
	if(ret != 0)				   	//注册失败
	{
		printk(KERN_INFO"IRQ_ERROR\n");
	}
	
	PS2_Init();
	tasklet_enable(&ps2_tasklet);
  	tasklet_schedule(&ps2_tasklet);			//调度ps2_tasklet

	try_module_get(THIS_MODULE);			//此函数为linux 2.6内核增加的,不同于2.4内核,功能是设备计数器的值加1
	return 0;
}

static void __exit at91_ps2_exit(void)
{
	platform_driver_unregister(&at91_ps2_device_driver);
	printk(KERN_INFO"at91_ps2_exit\n");
	free_irq(irq_no,&at91_ps2_device_driver);
	printk(KERN_INFO"at91_ps2_KeyBoard_isr\n");
}

//*----------------------------------------------------------------------------
//* Function Name       : PS2_Init
//* Object              : PS2接口初始化
//* Input Parameters    : 
//* Output Parameters   : 
//*----------------------------------------------------------------------------
void PS2_Init( void )
{	
	PS2_BUF  *pBuf;
		pBuf = &PS2Buf;
		pBuf->pBufInPtr = pBuf->pBufOutPtr = &pBuf->Buf[0];
		pBuf->BufCtr = 0;
		pBuf->Flag_Kbd = 0;
		pBuf->Flag_Shift = 0;
		pBuf->Flag_Caps = 0;
		pBuf->Flag_Ctrl = 0;
		pBuf->Flag_Fn = 0;
		pBuf->Flag_Alt = 0;
		pBuf->Flag_NumLock = 0xff;
		pBuf->Flag_ScrollLock = 0;
  	
	    // open external IRQ2 interrupt		开外部中断IRQ2
//	AT91F_AIC_ConfigureIt ( AT91C_BASE_AIC, AT91C_ID_IRQ2, 
//								IRQ2_INTERRUPT_LEVEL,
//								AT91C_AIC_SRCTYPE_EXT_POSITIVE_EDGE,	// 设置IRQ2中断为上升沿触发
//								irq2_asm_irq_handler); 
//								

	// open  FIQ interrupt
//    AT91F_PIO_CfgPeriph( 
//    	AT91C_BASE_PIOC,	// PIO controller base address PIO控制器基地址
//		0, 					// Peripheral A 	外围A
//		PS2_CLK1); 			// Peripheral B		外围B
//		
//	AT91F_AIC_ConfigureIt ( AT91C_BASE_AIC, AT91C_ID_FIQ, 
//								FIQ_INTERRUPT_LEVEL,
//								AT91C_AIC_SRCTYPE_EXT_POSITIVE_EDGE,	// 设置FIQ中断为上升沿触发
//								fiq_asm_handler); 
								
	printk(KERN_INFO"at91_ps2_init\n");

}							

module_init(at91_ps2_init);
module_exit(at91_ps2_exit);

MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("zhixiong peng");
MODULE_DESCRIPTION("PS/2 Keyboard driver for CPU GPIOs");

⌨️ 快捷键说明

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