2013-10-24 实验之input子系统__

实验描述:input子系统

注意事项:上报值时存在bug,只能输出一次

内核版本:Linux 2.6.38

开发板:  Mini 6410


驱动程序:

(dev)

#include <linux/init.h>  
#include <linux/module.h>  
#include <linux/device.h>
#include <linux/kdev_t.h>
#include <linux/fs.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
#include <asm/io.h>  
#include <linux/delay.h>
#include <linux/irq.h>
#include <linux/interrupt.h> 
#include <linux/platform_device.h>
#include <linux/cdev.h>
#include <linux/input.h>
/*
      Kernel Version: Linux 2.6.38
      Arm Version: Mini 6410
*/

#define MyPrintk  printk

static struct input_dev *buttons_dev;
static struct timer_list timer_leds;  

struct button_irq_desc {
	int irq;
	unsigned long flags;
	char name[20];
	unsigned int key_value;
};

static struct button_irq_desc button_irqs [] = {
		{IRQ_EINT(0), IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, "K1", KEY_L},
		{IRQ_EINT(1), IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, "K2", KEY_S},
		{IRQ_EINT(2), IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, "K3", KEY_ENTER},
		{IRQ_EINT(3), IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, "K4", KEY_LEFTSHIFT},
	};

static unsigned int pin[4];
static unsigned int ledsvalue [4];
volatile unsigned long *gpkcon0 = NULL;
volatile unsigned long *gpkdat    = NULL;
static char *DEVICE_NAME = "INPUT_DRIVER";
static struct pin_desc *irq_pd;

void leds_ctl(unsigned long value)  
{  
	struct button_irq_desc * pindesc = irq_pd;
	unsigned int pinval;
	if (!pindesc)
		return;
	//printk("interrupt irq: %d, flags: %lu, name: %s, count: %u\n",pindesc->irq,
	//	pindesc->flags, pindesc->name,pindesc->key_value);
	input_event(buttons_dev, EV_KEY, pindesc->key_value, 0);
	input_sync(buttons_dev);
}  

static irqreturn_t buttons_hander(int irq, void * dev)
{
	irq_pd = (struct button_irq_desc *)dev;
	int i;
	for (i=0; i < sizeof(button_irqs) /sizeof(button_irqs[0]); i++)
	{
		if(irq == button_irqs[i].irq){
			break;
		}
	}
	//MyPrintk (KERN_EMERG "gpkndata: %lu\n", *gpndat);  
	*gpkdat |= (1<<pin[0]) | (1<<pin[1]) | (1<<pin[2]) | (1<<pin[3]) ;  
	*gpkdat &= ledsvalue[i];
	//MyPrintk (KERN_EMERG "gpkkdata: %lu %d\n", *gpkdat, i);  
	mod_timer(&timer_leds, jiffies + HZ/100);  
	return IRQ_RETVAL(IRQ_HANDLED);
}

static int led_probe(struct platform_device *pdev)
{
	struct resource *res;

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	gpkcon0 = ioremap(res->start, res->end - res->start + 1);
	gpkdat = gpkcon0 + 2;

	int i;
	for(i = 0;i < 4; i++){
		res = platform_get_resource(pdev, IORESOURCE_IRQ, i);
		pin[i] = res->start;

	}
	
	*gpkcon0 &= ~( (0xF<<pin[0]*4) | (0xF<<pin[1]*4) | (0xF<<pin[2]*4) | (0xF<<pin[3]*4));
	*gpkcon0 |= ( (0x1<<pin[0]*4) |(0x1<<pin[1]*4) | (0x1<<pin[2]*4) | (0x1<<pin[3]*4));
	*gpkdat |= (1<<pin[0]) | (1<<pin[1]) | (1<<pin[2]) | (1<<pin[3]) ;  

	
	int err;
	for (i=0; i < sizeof(button_irqs) /sizeof(button_irqs[0]); i++)
	{
		err = request_irq(button_irqs[i].irq, buttons_hander, button_irqs[i].flags,
			button_irqs[i].name, (void *)&button_irqs[i]);
		if(err){
			break;
		}
		printk("register this interrupt %d \n", button_irqs[i].irq);
	}
	if(err){
		i--;
		for(; i >= 0; i--)
		{
			free_irq(button_irqs[i].irq, (void *)&button_irqs[i]);
		}
		printk("Sorry, can not register these interrupts");
	}

	buttons_dev = input_allocate_device();
	set_bit(EV_KEY, buttons_dev->evbit);
	set_bit(EV_REP, buttons_dev->evbit);
	set_bit(KEY_L, buttons_dev->keybit);
	set_bit(KEY_S, buttons_dev->keybit);
	set_bit(KEY_ENTER, buttons_dev->keybit);
	set_bit(KEY_LEFTSHIFT, buttons_dev->keybit);
	buttons_dev->name = "MyInput";
	input_register_device(buttons_dev);
	
	ledsvalue[0] = ~ ((1<<pin[0]) | (0<<pin[1]) | (0<<pin[2]) | (0<<pin[3])) ;
	ledsvalue[1] = ~ ((0<<pin[0]) | (1<<pin[1]) | (0<<pin[2]) | (0<<pin[3])) ;
	ledsvalue[2] = ~ ((0<<pin[0]) | (0<<pin[1]) | (1<<pin[2]) | (0<<pin[3])) ;
	ledsvalue[3] = ~ ((0<<pin[0]) | (0<<pin[1]) | (0<<pin[2]) | (1<<pin[3])) ;
	
	 init_timer(&timer_leds);  
  	 timer_leds.data = 0;  
  	 timer_leds.function = leds_ctl;  
	  add_timer(&timer_leds);  

	return 0;
}


static int led_remove(struct platform_device *pdev)
{	
	iounmap(gpkcon0);
	del_timer(&timer_leds); 

	int i;
	for (i=0; i < sizeof(button_irqs) /sizeof(button_irqs[0]); i++)
	{
		free_irq(button_irqs[i].irq, (void *)&button_irqs[i]);
	}
	return 0;
  	MyPrintk (KERN_EMERG "%s  Linux Byebye\n", DEVICE_NAME);  
	return 0;
}

struct platform_driver my_led_drv = {
	.probe		= led_probe,
	.remove		= led_remove,
	.driver		= {
	.name	= "my",
	}
};

static int myleds_init(void)  
{   
	platform_driver_register(&my_led_drv);
	return 0;  
}  

static int myleds_exit(void)  
{   
	platform_driver_unregister(&my_led_drv);
  	return 0;  
}  
  
module_init(myleds_init);  
module_exit(myleds_exit);
MODULE_LICENSE("GPL");  

(dev)

#include <linux/init.h>  
#include <linux/module.h>  
#include <linux/device.h>
#include <linux/kdev_t.h>
#include <linux/fs.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
#include <asm/io.h>  
#include <linux/delay.h>
#include <linux/irq.h>
#include <linux/interrupt.h> 
#include <linux/platform_device.h>
/*
      Kernel Version: Linux 2.6.38
      Arm Version: Mini 6410
*/

#define MyPrintk  printk

static struct resource led_resource[] = {
  [0] = {
        .start = 0x7F008800,
        .end   = 0x7F008800 + 12 - 1,
        .flags = IORESOURCE_MEM,
    },
    [1] = {
        .start = 4,    
        .end   = 4,
      .flags = IORESOURCE_IRQ,
    },
     [2] = {
        .start = 5,  
        .end   = 5,
        .flags = IORESOURCE_IRQ,
    },
	 [3] = {
        .start = 6,   
        .end   = 6,
      .flags = IORESOURCE_IRQ,
    },
	  [4] = {
      .start = 7,    
        .end   = 7,
        .flags = IORESOURCE_IRQ,
    },
};

static void led_release(struct device * dev)
{
}

static struct platform_device my_device = {
	.name         = "my",
	.id       = -1,
	.num_resources    = ARRAY_SIZE(led_resource),
  	.resource     = led_resource,
 	.dev = { 
    		.release = led_release, 
	},
};

static int myleds_init(void)  
{   
	platform_device_register(&my_device);
	MyPrintk (KERN_EMERG "platform device register\n");  
	return 0;  
}  

static int myleds_exit(void)  
{   
	platform_device_unregister(&my_device);
  	MyPrintk (KERN_EMERG "platform device unregister\n");  
  	return 0;  
}  
  
module_init(myleds_init);  
module_exit(myleds_exit);
MODULE_LICENSE("GPL");  




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值