按键驱动insmode时gpio_keys_probe没有被调用,是什么原因?

java_hero 2010-12-17 10:31:20
/**
* 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);
...全文
316 1 打赏 收藏 转发到动态 举报
写回复
用AI写文章
1 条回复
切换为时间正序
请发表友善的回复…
发表回复
谭海燕 2010-12-17
  • 打赏
  • 举报
回复
发帖给点建议:

LZ,贴这么大篇幅的代码,不用[code]括起来,代码是没人看的。我遇到这种直接跳过。



按键驱动,加载是否成功。。

调试下。
内容概要:本文系统研究了并网虚拟同步发电机(VSG)的自适应惯量阻尼调控策略及其对频率动态响应稳定性的影响,聚焦于VSG在并网工况下的惯量与阻尼协同自适应控制机制。通过构建Simulink仿真模型并结合Matlab代码实现,深入分析VSG的动态特性、有功/无功功率响应及电网频率稳定性,采用根轨迹法评估不同调节系数对系统稳定性的敏感性,揭示其支撑电网频率稳定的能力。研究进一步拓展至微电网黑启动、预同步控制、虚拟阻抗技术以及双机VSG间的功率精确分配等关键应用场景,旨在应对高比例新能源接入带来的系统惯量下降与频率稳定挑战,提升电力系统的韧性与可靠运行水平。; 适合人群:具备电力系统分析、自动控制理论及新能源并网技术背景,熟练掌握Matlab/Simulink仿真工具,从事电气工程、能源互联网、微电网控制等相关领域的研究生、科研人员及工程技术人员。; 使用场景及目标:①深入探究VSG在并网模式下惯量与阻尼参数的自适应协同调控原理与实现方法;②系统分析VSG控制策略对电网频率动态响应过程的影响规律与稳定边界;③通过仿真实践掌握VSG关键控制参数(如虚拟惯量、阻尼系数)的设计、整定及其对系统性能影响的量化评估;④为微电网的自主黑启动、无缝并网及高渗透率可再生能源系统的频率稳定控制提供先进的技术方案与决策依据。; 阅读建议:建议读者结合文中提供的完整Matlab代码与Simulink模型进行动手仿真实验,重点关注控制策略的模块化设计逻辑、参数动态调整过程与系统整体性能之间的关联,务必结合电力系统小信号稳定性分析理论,深入理解根轨迹、特征值等分析结果所蕴含的物理意义,从而实现从理论到实践的贯通。

23,223

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 应用程序开发区
社区管理员
  • 应用程序开发区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧