驱动报告uevent示例
2016-03-31 15:44
399 查看
#include <linux/module.h> #include <linux/init.h> #include <linux/gpio.h> #include <linux/slab.h> #include <linux/kobject.h> #include <linux/sysfs.h> #include <linux/kernel.h> #include <linux/interrupt.h> #include <linux/platform_device.h> #include <asm/irq.h> #include <mach/fp8102_det.h> int irqnum = 0; struct uevent_platform_data* uinfo = NULL; static struct kset *uevent_kset = NULL; static struct work_struct uevent_wq; static char charged_str[] = "fully-charged"; static char charging_str[] = "charging"; struct uevent_obj { struct kobject kobj; int val; }; struct uevent_obj *uobj; struct uevent_attribute { struct attribute attr; ssize_t (*show)(struct uenent_obj *uobj, struct attribute *attr, char *buf); ssize_t (*store)(struct uevent_obj *uobj, struct attribute *attr, const char *buf, size_t count); }; static ssize_t uevent_attr_show(struct kobject *kobj, struct attribute *attr, char *buf) { ssize_t count; if (gpio_get_value(uinfo->detect_pin) ^ uinfo->charge_active_low) count = sprintf(buf, "%s\n", charging_str); else count = sprintf(buf, "%s\n", charged_str); return count; } static ssize_t uevent_attr_store(struct kobject *kobj, struct attribute *attr, const char *buf, size_t len) { return 0; } static const struct sysfs_ops uevent_sysfs_ops = { .show = uevent_attr_show, .store = uevent_attr_store, }; static void uevent_release(struct kobject *kobj) { kfree(uobj); } static ssize_t uevent_show(struct uevent_obj *uevent_obj, struct attribute *attr, char *buf) { /*do nothing*/ return 0; } static ssize_t uevent_store(struct uvent_obj *uevent_obj, struct attribute *attr, const char *buf, size_t count) { /*do nothing*/ return 0; } static struct uevent_attribute fp8102_uevent_attr = __ATTR(uevent, 0666, uevent_show, uevent_store); static struct attribute *uevent_default_attrs[] = { &fp8102_uevent_attr.attr, NULL, }; static struct kobj_type uevent_ktype = { .sysfs_ops = &uevent_sysfs_ops, .release = uevent_release, .default_attrs = uevent_default_attrs, }; static void destroy_uevent_obj(struct uevent_obj *ub) { kobject_put(&ub->kobj); kfree(&ub->kobj); } void uevent_do_work(struct work_struct *work) { char *msg[] = {NULL, NULL}; if (gpio_get_value(uinfo->detect_pin) ^ uinfo->charge_active_low) msg[0] = charging_str; else msg[0] = charged_str; kobject_uevent_env(&uobj->kobj, KOBJ_CHANGE, msg); } static irqreturn_t interrupt_isr(int irq, void *data) { schedule_work(&uevent_wq); return IRQ_HANDLED; } static int fp8102_det_probe( struct platform_device *pdev) { int ret = 0; uinfo = pdev->dev.platform_data; if(!uinfo){ printk("get uevent pdata failed \n"); return -EINVAL; } uevent_kset = kset_create_and_add("uevent_report", NULL, kernel_kobj); if (!uevent_kset){ return -ENOMEM; } uobj = kzalloc(sizeof(*uobj), GFP_KERNEL); if (!uobj){ goto kset_error; } INIT_WORK(&uevent_wq, uevent_do_work); uobj->kobj.kset = uevent_kset; ret = kobject_init_and_add(&uobj->kobj, &uevent_ktype, NULL, "%s", "uevent_report"); if (ret){ goto uevent_error; } ret = gpio_request(uinfo->detect_pin, "uevent_report"); if (ret){ printk("gpio reuest for uevent report failed\n"); goto uevent_error; } irqnum = gpio_to_irq(uinfo->detect_pin); if (request_irq(irqnum, interrupt_isr, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "uevent_report", NULL)) { printk(KERN_ERR "uevent.c: Can't allocate irq %d\n", irqnum); goto gpio_error; } return 0; gpio_error: gpio_free(uinfo->detect_pin); uevent_error: destroy_uevent_obj(uobj); kset_error: kset_unregister(uevent_kset); return -EINVAL; } static int fp8102_det_remove(struct platform_device *dev) { destroy_uevent_obj(uobj); kset_unregister(uevent_kset); free_irq(irqnum, NULL); gpio_free(uinfo->detect_pin); return 0; } static struct platform_driver fp8102_det_driver = { .driver = { .name = "fp8102_det", .owner = THIS_MODULE, }, .probe = fp8102_det_probe, .remove = fp8102_det_remove, }; static int __init fp8102_det_init(void) { return platform_driver_register(&fp8102_det_driver); } static void __exit fp8102_det_exit(void) { platform_driver_unregister(&fp8102_det_driver); } module_init(fp8102_det_init); module_exit(fp8102_det_exit); MODULE_DESCRIPTION("fp8102 charge status report"); MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Bing");
代码功能:
实现底层向上层报告uevent的功能,比如说底层有个按键按下或者电池充电状态发生改变,而应用程序需要获取这一事件,我们就可以在按键按下的时候发出uevent事件.
细节问题:
uevent必须依附一个kobj;
底半部最好用工作队列,而不是软中断.
相关文章推荐
- Android开源项目分类汇总(五)ColorPickView、GraphView、UI Style
- iOS开发-搜索栏UISearchBar和UISearchController
- LeetCode 303 Range Sum Query - Immutable
- Java GUI 画点
- 【hdu1242】Rescue——bfs+小根堆
- QML QuickItem鼠标键盘处理
- sql自动uuid,导表exp,imp指令
- EasyUI——DateBox和DateTimeBox的汉化和显示格式修改
- 96. Unique Binary Search Trees
- 回归基础系列-call by value / call by reference区别与实例
- LValue RValue
- hdu 2604 Queuing【递推+矩阵快速幂】
- ${pageContext.request.contextPath} JSP路径问题
- 多线程实现Thread.Start()与ThreadPool.QueueUserWorkItem两种方式对比
- YTKKeyValueStore用法
- 【poj 1019】Number Sequence
- Java中的String、StringBuffer和StringBuilder区别
- GCD的同步异步串行并行、NSOperation和NSOperationQueue一级用dispatch_once实现单例
- [Form Builder]:CREATE_GROUP Built-in
- 并发队列ConcurrentLinkedQueue和阻塞队列LinkedBlockingQueue用法