上一章我们简要说明了IIO子系统的架构,本章我们通过数据结构的定义,分析IIO子系统的设计实现,本章的主要内容如下:

一、IIO子系统各数据结构说明

二、数据结构间的关联说明

一、IIO子系统各数据结构说明

在上一章我们大概说明了IIO子系统的框架,IIO子系统大概包含几个主要的部分,此处我们再说明一下:

  1. 对于连续数据采集相关功能,主要由iio buffer实现;
  2. 连续数据采集的触发机制,主要由iio trigger实现;
  3. Iio device的事件触发机制,主要由iio event实现;
  4. 提供单次原始数据的采集功能,主要通过syfs属性文件实现。

基本就是这些内容,iio子系统主要借助字符设备文件以及sysfs属性文件实现数据的获取与参数设定等操作。而在iio子系统中,主要包括如下几个数据结构:

  1. struct iio_dev,描述一个iio device
  2. struct iio_event_interface,描述iio device的事件触发模块的数据结构;
  3. struct iio_buffer,描述iio device连续数据采集功能相关的数据结构;
  4. struct iio_trigger,描述iio device的trigger机制相关的数据结构
  5. struct iio_chan_spec,描述iio device的一个通道的属性信息;
  6. struct iio_info,描述iio device各通道的原始数据读取接口、event使能与event参数读写相关接口、trigger有效性检测接口、设备树节点解析等接口;
  7. struct iio_buffer_setup_ops,描述iio buffer使能与否的接口(建立iio buffer与iio tigger的关联,从而保证iio trigger触发后,可将数据刷新到对应的iio buffer中);
  8. struct iio_chan_spec_ext_info,描述一个channel扩展属性相关的信息,包括属性名称、读写接口等
  9. struct iio_trigger_ops,表示iio trigger的操作接口,包括设置trigger的状态(使能与否)、重新使能trigger、设备有效性判断等接口;
  10. struct iio_buffer_access_funcs,描述iio buffer的access接口,包括数据写入到iio buffer的缓存、缓存数据是否有效、从缓存中读取数据等等接口。

基本上就是这些数据结构,iio子系统的数据结构比较多,但是数据结构间的关联并不太复杂,主

要就是数据结构太多了。下面我们对每一个数据结构进行简要说明

struct iio_dev

该数据结构表示一个iio device,它属于IIO子系统中的核心数据结构,它负责将所有的IIO子系统的数据结构关联起来,下面即是该数据结构主要的内容,下面我们分几部分进行说明。

  1. modes与currentmode表示该iio device支持的模式及当前所处的模式,目前支持的模式如下,DIRECT_MODE表示不对采集数据进行缓存,可直接读取单次的数据(可通过访问sysfs下的属性文件方式,读取数据);INDIO_BUFFER_XXX表示支持对iio device采集数据进行缓存的模式,可理解为采集连续的数据(这些数据则需要通过访问字符设备文件进行读取);INDIO_EVENT_TRIGGRED则主要表示事件触发功能,如针对温度传感器可监控当前温度是否超过温度告警上限或下限,当出现温度告警后则向SOC发送中断信号,若支持这类功能则增加INDIO_EVENT_TRIGGRED模式的支持即可(事件告警信息也是通过访问字符设备文件读取,但这个字符设备文件有点特殊,其是一个匿名文件)。

/* Device operating modes */

#define INDIO_DIRECT_MODE 0x01

#define INDIO_BUFFER_TRIGGERED 0x02

#define INDIO_BUFFER_SOFTWARE 0x04

#define INDIO_BUFFER_HARDWARE 0x08

#define INDIO_EVENT_TRIGGERED 0x10

  1. dev则主要借助系统的设备驱动模型,实现对iio device的引用计数,并绑定至iio总线上,同时借助设备驱动模型可在sysfs目录下创建该iio dev的目录,并创建该iio device所有属性文件等等;
  2. event_interface表示event事件相关的数据结构,该数据结构内部包含一个kfifo,存储iio device push的event信息;
  3. buffer表示该iio device对应的iio buffer,若系统不支持buffer模式,则无需创建该buffer;
  4. buffer_list则在一个iio buffer enable时,将active iio buffer加入到该链表中(目前基本上即将iio_dev->buffer添加到该链表上);
  5. scan_bytes表示单次采集数据的长度,该值主要根据当前active channel的个数、每一个通道采集数据的长度计算而得;
  6. available_scan_masks表示当前iio device可使用的channel的掩码(如当前由8个通道,仅前四个通道可用,则可以设置available_scan_maks值为{0x0F}),而active_scan_mask则表示当前已enable的channelmask,该mask是available_scan_masks的子集

scan_bytes、available_scan_masks、active_scan_mask主要由iio buffer使用,scan_bytes是单次采集数据的长度,因此通过字符设备文件读取buffer采集数据时,传递的内存长度至少应为scan_bytes;

  1. scan_timestamp、scan_index_timestamp主要对于通过buffer采集的数据是否需要时间戳,如果需要对采集的数据增加时间戳,则增加IIO_TIMESTAMP类型的虚拟channel,主要用于对采集的数据增加时间戳;
  2. trig表示一个trigger,针对event、buffer而言,均需要结合trigger机制作为数据可采集的信号,一般在trigger中将event信息、数据信息刷新到event的kfifo或buffer中去(不过目前event信息一般并没有使用trigger机制,大多数event信息均是在event irq的中断处理函数中push到event 的kfifo中,虽然IIO子系统设计上期望通过trigger将数据push到buffer或event上去,但event信息一般并不是连续事件,且trigger内部又实现了虚拟的irq chip,而在虚拟irq的中断处理函数中实现数据push到buffer或event的kfifo中。显然对于event信息处理而言,若使用trigger机制,则多了一个虚拟中断的触发与处理操作,也没有必要啊,因此现有系统中基本上没有使用trigger机制将event信息push到event kfifo的驱动);
  3. pollfunc、pollfunc_event则为buffer、event的中断处理函数的接口信息(使用的中断即为trigger中virtual irq chip注册的irq),现在仅需要关注pollfunc即可,基本上没有使用pollfunc_event的;
  4. channels是该iio device所有channel相关的参数信息,我们在iio_chan_spec中将详细说明;
  5. channel_attr_list链表包含了IIO子系统为所有channel创建的动态属性(针对hwmon子系统我们之前也分析过,其主要通过在sysfs下创建属性文件实现与hwmon device的通信,而IIO子系统也类似,其也在sysfs下创建属性文件实现与iio device的通信,而channel_attr_lis则主要是channel相关的属性的集合);
  6. groups中包含了所有的group指针,包括channel、event、buffer子模块创建的group,而在调用device_add将该iio device对应的struct device类型变量注册到设备驱动模型子系统中,即遍历该数组,创建属性文件或目录。
  7. setup_ops则主要是建立buffer与trigger的关联,在该ops中的enable接口中,主要是申请trigger的virt irq chip提供的中断及中断处理函数;在该ops的disable接口中则释放中断。

struct iio_event_interface

该数据结构主要是对event子模块的定义,其中:

  1. 等待队列wait,当应用程序读取触发事件信息时,若当前无数据可读,则将当前进程加入到该等待队列,待调用iio_push_event将触发事件信息加入kfifo后,则wakeup该队列中的进程;
  2. 定义kfifo,存储所有触发的事件信息,供应用程序获取;
  3. 将even子模块动态定义的event attribute均添加至该链表中(属性名称格式为{iio_dir}_{iio_channel_type}{channel-Index/channel_modify}_{ev_type}_{ev_dir}_{ev_info});
  4. flags标记该event是否已使能(即应用程序是否通过ioctl调用创建一个匿名fd,若使能则置位IIO_BUSY_BIT_POS)

struct iio_buffer与struct iio_buffer_setup_ops

iio_buffer主要是用于存储连续采集数据的缓存,其主要包括两个主要的数据结构struct iio_buffer、struct iio_buffer_access_func(其实是三个数据结构,还有数据结构struct iio_kfifo,其内部包含struct iio_buffer类型变量和struct kfifo类型变量用于缓存数据)。

针对struct iio_buffer主要包括如下几个方面的内容:

  1. iio_buffer缓存数据的个数(即length);
  2. iio_buffer每一次采集数据的长度(bytes_per_datum,而bytes_per_datum*length即为kfifo存储数据的内存空间大小);
  3. Scan_el_dev_attr_list主要用于将所有iio_buffer子模块创建的属性变量集合在一起(iio_buffer);
  4. scan_el_attrs存储各设备驱动自行定义的静态属性(生成的属性文件在scan_elements子目录下);
  5. attrs也是存储存储各设备驱动自行定义的静态属性(该变量定义的属性文件在buffer子目录下);
  6. buffer_group、scan_el_group包含iio buffer子模块下所有属性,其中buffer_group里的属性均在buffer子目录下创建对应的属性文件;scan_el_group里的属性均在scan_elements子目录下创建对应的属性文件;
  7. pollq为等待队列,主要为iio device的字符设备文件使用(该字符设备文件对应的读接口和poll接口使用,当buffer中不存在数据时则sleep在该等待队列中);
  8. watermark为缓存多少个数据后,唤醒pollq(实际内存空间大小为watermark*bytes_per_datum)。

针对struct iio_buffer_access_funcs则是该iio_buffer对应的缓存空间的访问访问,目前使用kfifo缓存数据,则其访问方法为iio_store_to_kfifo、iio_read_first_n_kfifo等,主要是将数据存储至kfifo或从kfifo中取出缓存数据等

struct iio_trigger与struct iio_trigger_ops

这两个数据结构主要实现iio 的trigger机制,类似于led子系统的led trigger。主要内容如下:

  1. id表示trigger的id、name为名称;
  2. 该iio trigger也使用struct device类型的变量加入到iio总线上,iio trigger与iio device均注册到iio总线上,因此它们在sysfs目录下是同级的;
  3. list用于将struct iio trigger添加系统全局链表iio_trigger_list中;
  4. alloc_list主要用于同一类型的trigger可注册多个trigger实例的请求,如trigger-period则使用该变量将trigger插入到iio_prtc_trigger_list中,目前使用这一变量的trigger并不多;
  5. 使用计数use_count;
  6. 而subirq_chip、subirq_base、subirqs、pool则主要用于创建虚拟的irq chip,在trigger内部,当多个trigger consumer注册时,则trigger内部会为其分配一个虚拟的irq,并根据trigger consumer提供给pollfunc,为该irq注册中断处理函数,这样当该trigger触发后,则会遍历所有该trigger上已注册的虚拟irq,调用其中断处理函数从而执行trigger consumer提供的处理函数(关于linux中断子系统的内容可参考我之前写的中断子系统专栏,我在中断子系统专栏也实现了一个虚拟的irq chip,实现的原理和此处trigger实现的虚拟irq chip的原理是一样的)。

iio trigger也提供了操作接口,set_trigger_state主要设置trigger的状态(使能与否)、reenable接口(try_reenable),validate_device(如实现的trigger只允许父device相同的iio device绑定,则可以实现该接口进行限制操作)

struct iio_chan_spec

该数据结构主要说明iio device一个channel的信息,主要涉及struct iio_chan_spec、struct iio_event_spec、struct iio_chan_spec_ext_info

针对struct iio_chan_spec主要涉及如下内容:

  1. 该channel的类型,channel类型的定义为等等enum iio_chan_type,包括IIO_TEMP、IIO_VOLTAGE等;
  2. channel表示该channel的index,当indexed为1时,才使用该index表示channel里的属性参数;
  3. channel2表示channel的别称,当modified为1时,则使用该index对应的string描述channel的别称(如针对三轴陀螺仪而言,如果还使用channel0、channel1进行识别的话不好区分,可使用modified识别为channelX、channelY、channelZ等)
  4. info_mask_separate表示channel的某一个属性为channel专属的
  5. Shared_by_type则表示该iio device下所有相同类型channel所共享的属性;
  6. Shared_by_dir则表示该iio device下所有相同方向channel所共享的属性;
  7. Shared_by_all则表示该iio device下所有channel所共享的属性
  8. scan_index、scan_type则表示采集数据的index及数据的类型等(这两个变量主要由buffer使用)
  9. event_spec定义event相关的信息;

该数据结构定义的变量,主要用于创建channel相关的属性参数,命名规则为{iio_dir}_{iio_channel_type}{channel-Index/channel_modify}_xxx。

而struct iio_event_spec主要内容如下:

  1. 该event的type、dir,而mask_separate等参数与iio_chan_spec中的info_mask_xxx的意义类似;而该数据结构体也主要用于创建该channel中event相关的属性参数,属性参数在sysfs文件系统创建的属性文件的名称规则为{iio_dir}_{iio_channel_type}{channel-Index/channel_modify}_{ev_type}_{ev_dir}_{ev_info})

struct iio_info

该数据结构主要定义了通过syfs读写channel属性的接口,其中read_raw、write_raw可用于读取通道的raw数据等;而write_event_value则主要用于event事件触发的阈值参数的设置与读取等、而read_event_config、write_event_config则可以用于实现event的使能与否;而event_attrs、attrs则主要用于设备驱动自定义的属性参数(包括event属性参数以及iio device相关的属性参数)

二、数据结构间的关联说明

如下为上述这些数据结构间的关联图,通过struct iio_dev,将所有定义的数据结构关联起来,这些数据结构基本上是在iio_device_register时完成关联的。借助这种数据结构间的关联也方便我们较好的理解该子系统的设计实现。

以上即是本章的主要内容,对于iio子系统而言,其定义的数据结构种类虽然多,但大多数数据结构主要用于创建sysfs的attribute而设计的,而真正体现到架构设计部分的设计,主要就是trigger、buffer、event这几个方面,而我认为设计的比较好的就是其trigger机制中,每一个trigger均实现一个虚拟irq chip,对于所有attach到该trigger上的consumer均为其分配虚拟的irq并注册对应的中断处理函数,当一个trigger触发后,则通过generic_handle_irq触发所有已注册的虚拟中断的处理操作。下一章我们就介绍iio trigger的设计。

dev 点击子控件触发panelcontrol事件_LINUX IIO子系统分析之二 IIO子系统数据结构分析...相关推荐

  1. [习题]如何触发 GridView 身体里面的「子控件」的事件 (ASP.NET案例精编 / 清华大学出版社 Ch.10/11两章的补充)...

    [习题]如何触发 GridView 身体里面的「子控件」的事件?#1 (ASP.NET案例精编 / 清华大学出版社 Ch.10/11两章的补充) 這個範例是要補充書本「上集」(ASP.NET專題實務) ...

  2. [习题].FindControl()方法 与 PlaceHolder控件 #2(动态加入「子控件」的事件)

    这是我的文章备份,有空请到我的网站走走, http://www.dotblogs.com.tw/mis2000lab/ 才能掌握我提供的第一手信息,谢谢您. http://www.dotblogs.c ...

  3. winform 鼠标离开子控件触发mouseleave事件处理

    Winform 控件鼠标离开事件 中 鼠标进入子控件也会触发mouseleave事件处理 最近在做一个关于语音与文本互相转化的小工具,利用的是百度的语音与文本转化接口.由于百度的语音转文本极速版接口中 ...

  4. [转]如何在数据绑定时不让combox控件触发SelectedIndexChanged事件

    this.cboVendor.SelectedIndexChanged -= new System.EventHandler(this.cboVendor_SelectedIndexChanged); ...

  5. android item 点击 获取position,Android ListView 子控件onClick正确获取position的方法

    在实际开发中,我们有时候不仅需要响应ListView的onItemClick,还需要响应其子控件的点击事件,这个时候我们就会 发现,由于复用等原因,如果直接在子控件的onClick事件中调用getVi ...

  6. qt整个窗口上绘制矩形与在窗口的子控件上绘制矩形

    引言 创建一个基于QDialog的项目,自动生成ui文件,此时再添加新文件,创建一个基于QWidget的ui类,此类具有自定义标题栏,让该自定义类显示在窗口Dialog上,一开始具有红色的边框线,且四 ...

  7. 初步探讨WPF的ListView控件(涉及模板、查找子控件)

    本文结合模板的应用初步介绍ListView的应用 一.Xaml中如何建立数据资源 大部分数据都会来自于后台代码,如何Xaml同样的建立数据源呢?比如建立一个学生List: 首先引入命名空间: xmln ...

  8. 小程序:自定义控件,父控件与子控件的交互triggerEvent

    实现目标,自定义控件一通用型喜欢按钮组件,包含喜欢和取消喜欢两种状态:如图 1.组件内的交互 点击爱心,UI上会变红心与空心  数据+1  -1 2.与父控件的交互,点击喜欢和取消喜欢,父控件发送网络 ...

  9. Cocos2dx中Scrollview控件滑动与其子控件监听冲突的解决方案(不改底层、最优)

    语言环境: Cocos2dx 3.6 Lua 5.1 UI编辑器:Cocos Studio v2.0.6 问题:Scrollview控件滑动与其子控件监听发生冲突. 在点击子控件时,若在子控件上进行移 ...

最新文章

  1. QIIME 2用户文档. 14数据评估和质控Evaluating and controlling(2019.7)
  2. 解密TDE加密数据库
  3. linux 常用命令技巧
  4. c# 接收网络汉字乱码_50种网络故障及解决方法
  5. bird 报表_轻松完成Birt报告
  6. 以太坊geth节点各种报错(求助)
  7. java tostring是什么意思_Java程序员不会用Lombok就落伍了
  8. SpringMVC自定义拦截器拦截请求后返回中文时乱码
  9. IDEA:IDEA更换主题,好看的主题汇总
  10. 图像处理--图像细化处理
  11. Xamarin.Forms学习之路——黑猫时钟App
  12. matlab 期权分析,matlab程序优化 (期权计算为例)
  13. 最好的Vue组件库之Vuetify的入坑指南(持续更新中)
  14. springboot整合thymeleaf启动错误
  15. 儿时经典电影回顾,你看过几部?
  16. Windows11快速入门
  17. 关于市场(闸机头--人脸识别桌面终端)
  18. Android Studio最完整的插件整理
  19. 基于微信小程序的订餐类系统设计与实现完整思路
  20. 如何启用chrome中的java_CentOS 上的Chrome 如何启用Java

热门文章

  1. NodeJS API Process全局对象
  2. 基于Springboot实现共享自习室管理系统
  3. Spark的RDD依赖关系
  4. while循环,递进,linux按行读入并按数组存储
  5. matlab学习——1.基本操作
  6. java诡异的String.split()方法
  7. 工作中总结的一些C#小经验,随时更新
  8. H5跟ios、android交互跟数据对接
  9. POJ_1195 Mobile phones 【二维树状数组】
  10. C# DateTimePicker控件如何精确设置显示时分秒