sysfs接口函数的建立_DEVICE_ATTR

最近在弄Sensor驱动,看过一个某厂家的成品驱动,里面实现的全都是sysfs接口,hal层利用sysfs生成的接口,对Sensor进行操作。

说道sysfs接口,就不得不提到函数宏 DEVICE_ATTR

原型是#define DEVICE_ATTR(_name, _mode, _show, _store) \

struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store)

函数宏DEVICE_ATTR内封装的是__ATTR(_name,_mode,_show,_stroe)方法,_show表示的是读方法,_stroe表示的是写方法。

当然_ATTR不是独生子女,他还有一系列的姊妹__ATTR_RO宏只有读方法,__ATTR_NULL等等

如对设备的使用  DEVICE_ATTR  ,对总线使用  BUS_ATTR  ,对驱动使用 DRIVER_ATTR  ,对类别 (class) 使用  CLASS_ATTR,  这四个高级的宏来自于<include/linux/device.h> 

DEVICE_ATTR  宏声明有四个参数,分别是名称、权限位、读函数、写函数。其中读函数和写函数是读写功能函数的函数名。

如果你完成了DEVICE_ATTR函数宏的填充,下面就需要创建接口了

例如:

    static DEVICE_ATTR(polling, S_IRUGO | S_IWUSR, show_polling, set_polling);
    static struct attribute *dev_attrs[] = {
            &dev_attr_polling.attr,
            NULL,
    };

当你想要实现的接口名字是polling的时候,需要实现结构体struct attribute *dev_attrs[]

其中成员变量的名字必须是&dev_attr_polling.attr

然后再封装

    static struct attribute_group dev_attr_grp = {
            .attrs = dev_attrs,
    };

 

在利用sysfs_create_group(&pdev->dev.kobj, &dev_attr_grp);创建接口

通过以上简单的三个步骤,就可以在adb shell 终端查看到接口了。当我们将数据 echo 到接口中时,在上层实际上完成了一次 write 操作,对应到 kernel ,调用了驱动中的 “store”。同理,当我们cat 一个 接口时则会调用 “show” 。到这里,只是简单的建立了 android 层到 kernel 的桥梁,真正实现对硬件操作的,还是在 "show" 和 "store" 中完成的。


######################################################################

以下来个例子:


/*
 * Sample kobject implementation
 *
 * Copyright (C) 2004-2007 Greg Kroah-Hartman <greg@kroah.com>
 * Copyright (C) 2007 Novell Inc.
 *
 * Released under the GPL version 2 only.
 *
 */
#include <linux/kobject.h>
#include <linux/string.h>
#include <linux/sysfs.h>
#include <linux/module.h>
#include <linux/init.h>
#include <asm/gpio.h>
#include <linux/delay.h>

/*
 * This module shows how to create a simple subdirectory in sysfs called
 * /sys/kernel/kobject-example  In that directory, 3 files are created:
 * "foo", "baz", and "bar".  If an integer is written to these files, it can be
 * later read out of it.
 */

static int foo;

/*
 * The "foo" file where a static variable is read from and written to.
 */

static struct msm_gpio qup_i2c_gpios_io[] = {
     { GPIO_CFG(60, 0, GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_8MA),
           "qup_scl" },
     { GPIO_CFG(61, 0, GPIO_CFG_INPUT, GPIO_CFG_NO_PULL, GPIO_CFG_8MA),
           "qup_sda" },
     { GPIO_CFG(131, 0, GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_8MA),
           "qup_scl" },
     { GPIO_CFG(132, 0, GPIO_CFG_INPUT, GPIO_CFG_NO_PULL, GPIO_CFG_8MA),
           "qup_sda" },
};

static struct msm_gpio qup_i2c_gpios_hw[] = {
     { GPIO_CFG(60, 1, GPIO_CFG_INPUT, GPIO_CFG_NO_PULL, GPIO_CFG_8MA),
           "qup_scl" },
     { GPIO_CFG(61, 1, GPIO_CFG_INPUT, GPIO_CFG_NO_PULL, GPIO_CFG_8MA),
           "qup_sda" },
     { GPIO_CFG(131, 2, GPIO_CFG_INPUT, GPIO_CFG_NO_PULL, GPIO_CFG_8MA),
           "qup_scl" },
     { GPIO_CFG(132, 2, GPIO_CFG_INPUT, GPIO_CFG_NO_PULL, GPIO_CFG_8MA),
           "qup_sda" },
};

static void gsbi_qup_i2c_gpio_config(int adap_id, int config_type)
{
     int rc;

     if (adap_id < 0 || adap_id > 1)
           return;

     /* Each adapter gets 2 lines from the table */
     if (config_type)
           rc = msm_gpios_enable(&qup_i2c_gpios_hw[adap_id*2], 2);
     else
           rc = msm_gpios_enable(&qup_i2c_gpios_io[adap_id*2], 2);
     if (rc < 0)
           pr_err("QUP GPIO request/enable failed: %d\n", rc);
}

static ssize_t foo_show(struct kobject *kobj, struct kobj_attribute *attr,
    char *buf)
{
      return sprintf(buf, "%d\n", foo);
}

static ssize_t foo_store(struct kobject *kobj, struct kobj_attribute *attr,
      const char *buf, size_t count)
{
     int sda,scl;
     int i;
     sscanf(buf, "%du", &foo);
     printk("foo = %d.\n",foo);

     foo = foo -1;

     if  (foo < 0 || foo > 1)
     {
           printk("input foo error. foo=%d.\n",foo);
           return 0;
     }
           
      sda = GPIO_PIN((&qup_i2c_gpios_hw[foo*2+1])->gpio_cfg);
      scl = GPIO_PIN((&qup_i2c_gpios_hw[foo*2])->gpio_cfg);
      
     printk("sda = %d.\n",sda);
     printk("scl = %d.\n",scl);
     
     gsbi_qup_i2c_gpio_config(foo,0);

     for(i=0;i<9;i++)
     {
           if(gpio_get_value(sda))
           {
                printk("sda of i2c%d is high when %d pulse is output on scl.\n",foo,i);
                break;
           }
           gpio_set_value(scl,0);
           udelay(5);
           gpio_set_value(scl,1);
           udelay(5);
     }
     
     gsbi_qup_i2c_gpio_config(foo,1);

     printk("finish.\n");
     return count;
}

static struct kobj_attribute foo_attribute =
      __ATTR(i2c_unlock, 0666, foo_show, foo_store);

/*
 * Create a group of attributes so that we can create and destroy them all
 * at once.
 */
static struct attribute *attrs[] = {
      &foo_attribute.attr,
      NULL,»  /* need to NULL terminate the list of attributes */
};

/*
 * An unnamed attribute group will put all of the attributes directly in
 * the kobject directory.  If we specify a name, a subdirectory will be
 * created for the attributes with the directory being the name of the
 * attribute group.
 */
static struct attribute_group attr_group = {
      .attrs = attrs,
};

static struct kobject *example_kobj;

static int __init example_init(void)
{
     int retval;

     /*
      * Create a simple kobject with the name of "kobject_example",
      * located under /sys/kernel/
      *
      * As this is a simple directory, no uevent will be sent to
      * userspace.  That is why this function should not be used for
      * any type of dynamic kobjects, where the name and number are
      * not known ahead of time.
      */
     example_kobj = kobject_create_and_add("i2c_recovery", kernel_kobj);
     if (!example_kobj)
          return -ENOMEM;

     /* Create the files associated with this kobject */
     retval = sysfs_create_group(example_kobj, &attr_group);
     if (retval)
          kobject_put(example_kobj);

     return retval;
}

static void __exit example_exit(void)
{
     kobject_put(example_kobj);
}

module_init(example_init);
module_exit(example_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Wupeng");


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/403848.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ant中table表格的多选框如何清空

项目需求&#xff1a;表格前加一列多选框&#xff0c;可以做多选和提交&#xff0c;还可以在提交后、重置或者翻页后对多选框清空 使用的组件是ant中下的可操作选择的table&#xff1b;这样我们就知道复选框选中的那些数据id&#xff0c;其实就是selectedRowKeys数组里的id&am…

SCCM 2012系列1 服务器准备上

各位您好&#xff0c;今天我将开始给大家分享微软最新的SCCM 2012系列文章&#xff0c;让大家逐步了解在企业内如何搭建SCCM 2012的同时&#xff0c;了解各个功能模块&#xff0c;对应自己的企业环境来看&#xff0c;那些功能是您现在所需要的。当然还可以看看SCCM 2012比之前…

linux内核源代码分析----内核基础设施之klist

概述klist是list的线程安全版本&#xff0c;他提供了整个链表的自旋锁&#xff0c;查找链表节点&#xff0c;对链表节点的插入和删除操作都要获得这个自旋锁。klist的节点数据结构是klist_node,klist_node引入引用计数&#xff0c;只有点引用计数减到0时才允许该node从链表中移…

近期H5项目开发小结

前言&#xff1a;2016差不多又过了半啦&#xff0c;最近参与了公司好几个h5项目&#xff08;严格来说&#xff0c;也只能算是推广页面活动&#xff09;。主要是新品牌的推广需要&#xff0c;当然也有给公司以前老客户做的案例。今天主要总结下为新品牌开发的2个h5推广&#xff…

vue-cli3中的vue.config.js配置

vue-cli3中的vue.config.js配置 我的跨域是配置通过chrome浏览器的跨域设置&#xff0c;前端修改跨域问题&#xff0c;以此解决跨域的&#xff0c; 故如果需要配置代理&#xff0c;就看proxy部分&#xff1b; const path require(path) const resolve (dir) > path.join…

获取python版本

import sys# global variablepyVersion 2 # set default python version to 2.x# init global variable(s)def init():global pyVersionpyVersion sys.version_info[0] # get major version of pythondef test():print(pyVersion)if __name__ __main__:init()test()运行情况…

会计的思考(37):“弱水三千,只取一瓢饮”--业务人员的财务意识

关键字: 会计体系 财务意识 投入产出 "任凭弱水三千&#xff0c;我只取一瓢饮"&#xff0c; 出自《红楼梦》,第九十一回里&#xff0c;贾宝玉曾经这样语带机锋地试图去化解林黛玉刚刚上来的醋劲。本文以此引出对业务人员的财务意识的思考。 成功企业家&#xff0c;如…

编译QtAV工程库

去https://github.com/wang-bin/QtAV下载源代码 去https://sourceforge.net/projects/qtav/files/depends/QtAV-depends-windows-x86%2Bx64.7z/download下载依赖库QtAV-depends-windows-x86x64.7z 将里面的include目录内容和lib内容分别拷贝到Qt的include和lib目录下 QtAV解压后…

make -j32 21 | tee show.log

2. 2>&1是什么意思&#xff1f;2>&1应该分成两个部分来看&#xff0c;一个是2>以及另一个是&1&#xff0c;其中2>就是将标准出错重定向到某个特定的地方&#xff1b;&1是指无论标准输出在哪里。所以2>&1的意思就是说无论标准出错在哪里(哪怕…

依赖包报错Invalid options object. Less Loader has been initialized using an options object that does not

1.问题&#xff1a;yarn安装依赖包&#xff0c;启动项目报错 error in ./node_modules/ant-design-vue/dist/antd.less Module build failed: ValidationError: Invalid options object. Less Loader has been initialized using an options object that does not match the A…

Windows下显示目录大小及文件个数

From: http://blog.csdn.net/wmnothing/article/details/6590376 用批处理实现Windows下子目录大小统计功能 吴旻 泰岩网络工作室 统计当前目录下各文件夹的大小&#xff0c;在Linux下面比较简单&#xff0c;一个 du -sh * 命令就基本解决问题了。虽然在资源管理器是单击右键…

Asp.net页面和Html页面之间的关系

Asp.net页面显然要转化为普通的html页面才能在浏览器中显示&#xff0c;但是对于两者的关系&#xff0c;或者说从服务器在接受请求处理请求这段时间内对asp.net页面的操作一直不是很明白&#xff0c;下边的一段话可以让人豁然开朗&#xff0c;虽然并未谈论技术&#xff0c;但简…

kmalloc/kfree,vmalloc/vfree函数用法和区别

1.kmalloc1>kmalloc内存分配和malloc相似&#xff0c;除非被阻塞否则他执行的速度非常快&#xff0c;而且不对获得空间清零.< tiger说明&#xff1a;在用kmalloc申请函数后&#xff0c;要对起清零用memset()函数对申请的内存进行清零。> 2>kamlloc函数原型&#xf…

SQL Server开发接口生成方法

为提高开发效率&#xff0c;生成固定格式的接口是必须的&#xff0c;以下以提供新增/修改/删除/读取接口为例&#xff1a; 以常见的表结构为例&#xff0c;特殊表结构可自己尝试去调整方法 主要通过系视图 sys.columns生成方法:为包含列的对象&#xff08;如视图或表&#xff0…

vue-cli2定制ant-design-vue主题

本篇是vue-cli2定制主题&#xff0c;vue-cli3通过vue.config.js定制主题点击此处 1.引入less和less-loader&#xff08;如果报错&#xff0c;请将less-loader版本更改到5.0.0&#xff09; npm install less less-loader --save2.在 vue cli 2 中定制主题&#xff0c;修改build…

python中thread的setDaemon、join的用法

From: http://doudouclever.blog.163.com/blog/static/17511231020127232303469/ python中得thread的一些机制和C/C不同&#xff1a;在C/C中&#xff0c;主线程结束后&#xff0c;其子线程会默认被主线程kill掉。而在python中&#xff0c;主线程结束后&#xff0c;会默认等待子…

谈谈软件兼容性测试

1.软件兼容性测试兼容性测试之待测试项目在特定的硬件平台上&#xff0c;不同的应用软件不同&#xff0c;不同的操作系统平台上&#xff0c;在不同的网络等环境中能正常的运行的测试。兼容性测试的目的&#xff1a;带测试项目在不同的操作系统上正常运行&#xff0c;包括待测试…

YUV视频格式分析

Andrew Huang <bluedrum163.com> 转载请注明作者及联络方式在摄像头之类编程经常是会碰到YUV格式,而非大家比较熟悉的RGB格式. 我们可以把YUV看成是一个RGB的变种来理解.YUV的原理是把亮度与色度分离&#xff0c;研究证明,人眼对亮度的敏感超过色度。利用这个原理&#x…

自定义ant中table表格的展开图标 修改ant-vue-design中嵌套表格table的expandIcon自定义图标

效果&#xff1a; 1. <a-table:expandIcon"expandIcon":loading"loading":columns"columns":data-source"data"class"components-table-demo-nested"change"onChangeTable":scroll"{x:1300,y:y}":p…

Foundationd和Application Kit的类层次

Foundationd类 Application Kit类 转载于:https://www.cnblogs.com/ikodota/archive/2012/08/01/2618590.html