什么时候唤醒?
报告事件input_event(dev,x) input_event(dev,y) input_event(dev,SYN)
--------------------
Linux内核中的总线设备驱动
总线 include/device.h
Struct bus_type
{
Name;
Match;//(匹配规则,匹配设备和设备驱动)
};
注册:bus_register(....)
注销:bus_unregister(。。。);
设备
Struct device{
Struct bus_type *bus;
};
device_register(...);
device_unregister(...);
Device.bus =&i2c_bus_type
Device_register(...)
设备驱动
Struct device_driver{
Name;
Probe;
Remove;
Struct bus_type *bus
}
Driver_register(...);
Driver_unregister(...);
2,平台设备总线:
Platform总线 bus_type
总线 driver/base/platform.c
struct bus_type platform_bus_type = {
.name= "platform",
.dev_attrs= platform_dev_attrs,
.match= platform_match,
.uevent= platform_uevent,
.pm= &platform_dev_pm_ops,
};
设备
Platform_device_register()
Platform_device
设备驱动
Platform_driver_register
Platform_driver
Device_driver
Platform_match
两边的name对比
之后probe函数
当有一方注销时
Remove函数会被调用
Gpio_get_value
反思:
平台设备总线架构有什么作用
便于你的驱动程序的移植和管理, 2.6以后才出现的
跟最小系统无关的硬件设备都可以按照平台设备架构来编写
Input子系统架构有什么作用
二者之间有什么关系
Input子系统在解决什么问题
平台设备架构在解决什么问题?
内核中自带的按键驱动程序:
make menuconfig 找到对应的 * 在 help就可以显示路径查找到他们了
例:路径:drivers/input/keyboard变量:CINFIG_KEYBOARD_S3C_GPIO
在路径下的makefile中找到变量找到对应的.o文件
是按照平台总线架构完成的
总线platform,设备,设备驱动gpio。。。。。C
根据driver中的name找device device没有.c文件在machine_init调用platform_add_devices添加device,platform_add_devices中有driver_register(
Platform_driver_register
->driver_register
->bus_add_driver
->driver_attach
->bus_for_each_dev(drv->bus,NULL,drv,__driver_attch)
->__driver_attch
->driver_match_device
->driver_probe_device
->really_probe
->drv->probe
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/stat.h>
#include <linux/slab.h>
//#include <linux/unicore.h>
#include <linux/gpio.h>
#include <linux/moduleparam.h>
#include <linux/kdev_t.h>
#include <linux/delay.h>
#include <linux/wait.h>
#include <linux/sched.h>
#include <linux/input.h>
#include <linux/platform_device.h>
#include <mach/regs-gpio.h>
#include <linux/regulator/consumer.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <mach/gpio-exynos4.h>
#include <asm/gpio.h>
#include <asm/io.h>
#include <plat/gpio-cfg.h>
#define GPX1_1_IRQ S3C_GPIO_SFN(0xF)
#define DRIVER_NAME "button_irq"
MODULE_LICENSE("Dual BSD/GPL");
/*声明是开源的,没有内核版本限制*/
MODULE_AUTHOR("songmao");
/*声明作者*/
struct input_dev *my_input=NULL;
struct timer_list pin_timer;
struct pin_desc
{
int irq;
unsigned int pin;
char *name;
char *label;
unsigned int value;
};
struct pin_desc pindesc[]={
{IRQ_EINT(9),EXYNOS4_GPX1(2),"key_home","EINT9",KEY_HOME},
};
volatile struct pin_desc *irq_pd = NULL;
static irqreturn_t plat_irq_handled (int irq,void *dev_id)
{
irq_pd = (volatile struct pin_desc *)dev_id;
mod_timer(&pin_timer,jiffies+HZ/100);
return IRQ_HANDLED;
}
static void pin_timer_functions(unsigned int data)
{
unsigned int pinval = 0;
struct pin_desc *pindescs = (volatile struct pin_desc *)irq_pd;
if(!pindescs)
{
return 0;
}
unsigned int con_temp = 0;
con_temp=gpio_get_value(pindescs->pin);
if(con_temp)
{
input_event(my_input,EV_KEY,pindesc[0].value,0);
input_event(my_input,EV_SYN,pindesc[0].value,0);
}
else
{
printk(KERN_WARNING "My_plat_irq:no input_event");
}
}
static int my_plat_irq_probe(struct platform_device *dev)
{
int ret=0;
my_input=input_allocate_device();
if(my_input==NULL)
{
printk(KERN_ERR "My_plat_irq: Failure is input_allocate_device ");
}
printk(KERN_INFO"My_plat_irq: Success is input_allocate_device ");
set_bit(EV_KEY,my_input->evbit);
set_bit(EV_SYN,my_input->evbit);
set_bit(KEY_HOME,my_input->keybit);
my_input->name = "my_inpt_irq";
ret=input_register_device(&my_input);
if(ret<0)
{
printk(KERN_ERR"My_plat_irq:Failure is input_register_device");
goto fail_input_register;
}
printk(KERN_INFO"My_plat_irq:Success is input_register_device");
ret = gpio_request(pindesc[0].pin,pindesc[0].label);
if(ret)
{
printk(KERN_ERR"My_plat_irq:Failure is gpio_request");
goto fail_gpio_request;
}
printk(KERN_INFO"My_plat_irq:Success is gpio_request");
s3c_gpio_cfgpin(pindesc[0].pin,GPX1_1_IRQ);
s3c_gpio_setpull(pindesc[0].pin,S3C_GPIO_PULL_UP);
ret=request_irq(pindesc[0].irq,plat_irq_handled,IRQF_TRIGGER_FALLING,pindesc[0].name,pindesc);
if(ret<0)
{
printk(KERN_ERR"My_plat_irq:Failure is request_irq");
goto fail_request_irq;
}
init_timer(&pin_timer);
pin_timer.function = pin_timer_functions;
add_timer(&pin_timer);
return 0;
fail_request_irq:
gpio_free(pindesc[0].pin);
fail_gpio_request:
input_unregister_device(&my_input);
fail_input_register:
input_free_device(&my_input);
}
static int my_plat_irq_remove(struct platform_device *dev)
{
return 0;
}
static struct platform_driver my_plat_irq = {
.probe=my_plat_irq_probe,
.remove=my_plat_irq_remove,
.driver = {
.name = DRIVER_NAME,
.owner = THIS_MODULE,
},
/*int (*probe)(struct platform_device *);
int (*remove)(struct platform_device *);
void (*shutdown)(struct platform_device *);
int (*suspend)(struct platform_device *, pm_message_t state);
int (*resume)(struct platform_device *);
struct device_driver driver;
const struct platform_device_id *id_table; */
};
static int __init init_my_plat_irq(void)
{
int ret;
ret = platform_driver_register( &my_plat_irq);
return 0;
}
static void __exit exit_my_plat_irq (void)
{
gpio_free(pindesc[0].pin);
input_unregister_device(&my_input);
input_free_device(&my_input);
}
module(init_my_plat_irq);
module(exit_my_plat_irq);