按键驱动insmode时gpio_keys_probe没有被调用,是什么原因?
/**
* hello.c
* ------Test for kernel module
*/
#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/random.h>
#define GPIO_KEY1 (32 * 2 + 20)
#define GPIO_KEY2 (32 * 5 + 20)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Phil Blundell <pb@handhelds.org>");
MODULE_DESCRIPTION("Keyboard driver for CPU GPIOs");
struct gpio_keys_button {
/* Configuration parameters */
int code; /* input event code (KEY_*, SW_*) */
int gpio;
int active_low;
char *desc;
int type; /* input event type (EV_KEY, EV_SW) */
int wakeup; /* configure the button as a wake-up source */
};
struct gpio_keys_platform_data {
struct gpio_keys_button *buttons;
int nbuttons;
};
static struct gpio_keys_button the_buttons[] = {
{
.gpio = GPIO_KEY1,
.code = KEY_1,
.desc = "Button 0",
.active_low = 1,
},
{
.gpio = GPIO_KEY2,
.code = KEY_2,
.desc = "Button 1",
.active_low = 1,
},
};
static struct gpio_keys_platform_data the_button_data = {
.buttons = the_buttons,
.nbuttons = ARRAY_SIZE(the_buttons),
};
static struct platform_device the_button_device = {
.name = "gpio-keys",
.id = -1,
.num_resources = 0,
.dev = {
.platform_data = &the_button_data,
}
};
static int gpio_get_value(int gpio)
{
int rand;
get_random_bytes(&rand,sizeof(rand));
return (rand % 2);
}
static irqreturn_t gpio_keys_isr(int irq, void *dev_id)
{
int i;
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 (i = 0; i < pdata->nbuttons; i++)
{
struct gpio_keys_button *button = &pdata->buttons[i];
int gpio = button->gpio;
//if (irq == gpio_to_irq(gpio))
{//判断哪个键被按了?
unsigned int type = button->type ?: EV_KEY;
int state = (gpio_get_value(gpio) ? 1 : 0) ^ button->active_low;//记录按键状态
input_event(input, type, button->code, !!state);//汇报输入事件
input_sync(input);//等待输入事件处理完成
}
}
return IRQ_HANDLED;
}
static void gpiodev_init(void)
{
int error;
//this function will init gpio
//printk(KERN_INFO "Java gpiodev_init begin!...\n");
error = platform_device_register(&the_button_device);
printk(KERN_INFO "gpiodev_init: error = %d \n",error);
//printk(KERN_INFO "Java gpiodev_init end!...\n");
}
static int __devinit gpio_keys_probe(struct platform_device *pdev)
{
int error;
struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
struct input_dev *input;
int i;
printk(KERN_INFO "Java gpio_keys_probe begin!...\n");
input = input_allocate_device();
if (!input)
{
printk(KERN_INFO "gpio_keys_probe input == NULL!...\n");
return -ENOMEM;
}
platform_set_drvdata(pdev, input);
input->name = pdev->name;
input->id.bustype = BUS_HOST;
input->id.vendor = 0x01;
input->id.product = 0x01;
input->id.version = 0x0100;
input->evbit[0] = BIT(EV_KEY)| BIT(EV_SYN) | BIT(EV_REP);
for(i = 0;i < pdata->nbuttons;i++)
{
struct gpio_keys_button *button = &pdata->buttons[i];
int irq = button->gpio;
error = request_irq(irq,gpio_keys_isr,IRQF_SAMPLE_RANDOM | IRQF_DISABLED, button->desc ? button->desc : "gpio_keys",pdev);
if(error)
{
printk(KERN_INFO "gpio_keys_probe: request_irq Failed!...\n");
goto FAILED;
}
}
error = input_register_device(input);//注册输入设备,并和对应的handler处理函数挂钩
if (error)
{
printk(KERN_ERR "Unable to register gpio-keys input device\n");
goto FAILED;
}
printk(KERN_INFO "Java gpio_keys_probe end!...\n");
return error;
FAILED:
while (--i >= 0)
{
free_irq(pdata->buttons[i].gpio, pdev);
}
platform_set_drvdata(pdev, NULL);
input_free_device(input);
return -1;
}
static int __devexit gpio_keys_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;
device_init_wakeup(&pdev->dev, 0);
for (i = 0; i < pdata->nbuttons; i++) {
int irq = pdata->buttons[i].gpio ;//+ IRQ_GPIO_0;
free_irq(irq, pdev);
}
input_unregister_device(input);
return 0;
return 0;
}
static int gpio_keys_suspend(struct platform_device *pdev, pm_message_t state)
{
struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
int i;
if (device_may_wakeup(&pdev->dev)) {
for (i = 0; i < pdata->nbuttons; i++) {
struct gpio_keys_button *button = &pdata->buttons[i];
if (button->wakeup) {
int irq = button->gpio;// + IRQ_GPIO_0;
enable_irq_wake(irq);
}
}
}
return 0;
}
static int gpio_keys_resume(struct platform_device *pdev)
{
struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
int i;
if (device_may_wakeup(&pdev->dev)) {
for (i = 0; i < pdata->nbuttons; i++) {
struct gpio_keys_button *button = &pdata->buttons[i];
if (button->wakeup) {
int irq = button->gpio;// + IRQ_GPIO_0;
disable_irq_wake(irq);
}
}
}
return 0;
}
struct platform_driver gpio_keys_device_driver = {
.probe = gpio_keys_probe,
.remove = __devexit_p(gpio_keys_remove),
.suspend = gpio_keys_suspend,
.resume = gpio_keys_resume,
.driver = {
.name = "gpiokeys",
}
};
static int gpiokeys_init(void)//(2)
{
int error;
gpiodev_init();
error = platform_driver_register(&gpio_keys_device_driver);
printk(KERN_INFO "gpiokeys_init,error = %d\n",error); //(3)
return error;
}
static void gpiokeys_exit(void)
{
printk(KERN_INFO "Goodbye, cruel world\n");
platform_device_unregister(&the_button_device);
platform_driver_unregister(&gpio_keys_device_driver);
}
module_init(gpiokeys_init);
module_exit(gpiokeys_exit);