linux轮询脚本,Linux驱动注册轮询设备

一般情况下很少需要使用注册轮询设备的,

因为轮询设备需要高频率调用获取外设的状态,增加CPU的负担.

但是碰到过2次需要使用注册轮询的情况:

1 外设IO口非常紧张的情况下,没有空出多余的IO口作为中断脚.

2 所使用的IO口没有带有中断功能.芯片中没有设计其对应的中断号

#include

#include

#include

struct pollgpio_key_data {

int m_id;

struct input_polled_dev *poll_dev;

};

static void adgpiokeys_poll(struct input_polled_dev *dev){

struct timex txc;

struct rtc_time tm;

do_gettimeofday(&(txc.time));

rtc_time_to_tm(txc.time.tv_sec,&tm);

printk("[%d-%02d-%02d %02d:%02d:%02d][%s,pid=%d]\n",

tm.tm_year+1900,tm.tm_mon+1, tm.tm_mday,

tm.tm_hour,tm.tm_min,tm.tm_sec,

__FUNCTION__, current->pid);

}

static int adgpiokeys_probe(struct platform_device *pdev){

struct pollgpio_key_data *adkey;

struct input_polled_dev *poll_dev;

int err;

printk("%s, pid=%d\n", __func__, current->pid);

adkey = kzalloc(sizeof(struct pollgpio_key_data), GFP_KERNEL);

if (!adkey){

return -ENOMEM;

}

poll_dev = input_allocate_polled_device();

if (!poll_dev) {

err = -ENOMEM;

goto fail;

}

platform_set_drvdata(pdev, adkey);

// 不设置名字会警告 input: Unspecified device as /devices/virtual/input/input10

poll_dev->input->name = "demo-name01";

poll_dev->input->phys = "demopoll-key/input0";

poll_dev->poll = adgpiokeys_poll;

poll_dev->poll_interval = 200; // 设置轮询的频率为200毫秒, default = 500

adkey->poll_dev = poll_dev; // for set_drvdata and get_drvdata

adkey->m_id = 0x8008;

err = input_register_polled_device(poll_dev);

if (err)

goto fail;

return 0;

fail:

printk(KERN_ERR "Adkey: failed to register driver, error: %d\n", err);

platform_set_drvdata(pdev, NULL);

input_free_polled_device(poll_dev);

kfree(adkey);

return err;

}

static int adgpiokeys_remove(struct platform_device *pdev){

struct pollgpio_key_data *adkey = platform_get_drvdata(pdev);

printk("%s,m_id=0x%x\n", __func__, adkey->m_id);

input_unregister_polled_device(adkey->poll_dev);

input_free_polled_device(adkey->poll_dev);

kfree(adkey);

return 0;

}

static struct platform_driver analog_ops = {

.probe = adgpiokeys_probe,

.remove = __devexit_p(adgpiokeys_remove),

.suspend = NULL,

.resume = NULL,

.driver = {

.owner = THIS_MODULE,

.name = "analog-key",

},

};

static int __init ad_gpio_key_init(void){

return platform_driver_register(&analog_ops);

}

static void __exit ad_gpio_key_exit(void){

printk("analog_gpio_key_exit\n");

platform_driver_unregister(&analog_ops);

}

//late_initcall(ad_gpio_key_init);

module_init(ad_gpio_key_init);

module_exit(ad_gpio_key_exit);

MODULE_LICENSE("GPL");

MODULE_AUTHOR("Mr.linux.debug");

MODULE_DESCRIPTION("Demo ad gpio poll for kernel module");

相关函数接口的原型分析

/// 向内核申请一个轮询设备

struct input_polled_dev *input_allocate_polled_device(void)

{

struct input_polled_dev *dev;

dev = kzalloc(sizeof(struct input_polled_dev), GFP_KERNEL);

if (!dev)

return NULL;

dev->input = input_allocate_device();

if (!dev->input) {

kfree(dev);

return NULL;

}

return dev;

}

向输入子系统注册一个轮询设备

int input_register_polled_device(struct input_polled_dev *dev)

{

struct input_dev *input = dev->input;

input_set_drvdata(input, dev);

INIT_DELAYED_WORK(&dev->work, input_polled_device_work);

if (!dev->poll_interval)

dev->poll_interval = 500;

input->open = input_open_polled_device;

input->close = input_close_polled_device;

return input_register_device(input);

}

/// 轮询设备的结构体

struct input_polled_dev {

void *private; // 私有的驱动数据

void (*flush)(struct input_polled_dev *dev); // 驱动程序提供的方法,刷新设备的状态(可选)

void (*poll)(struct input_polled_dev *dev); // 轮询调用的处理函数

unsigned int poll_interval; /* msec */ // 轮询的间隔时间, 以毫秒为单位

struct input_dev *input; // 普通的输入子设备

struct delayed_work work; // 包含一个延时工作队列

};

可以看出来两个接口的处理原理

input_allocate_polled_device

向内核申请一个轮询设备

就是对申请输入子系统设备(input_allocate_device)二次封装

input_register_polled_device

向输入子系统注册一个轮询设备

就是对注册输入子系统设备(input_register_device)二次封装

本文地址:https://blog.csdn.net/dreamInTheWorld/article/details/107554314

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值