Linux IIO子系统分析2(基于Linux6.6)---数据结构介绍
一、IIO子系统各数据结构说明
IIO子系统大概包含几个主要的部分:
- 对于连续数据采集相关功能,主要由iio buffer实现;
- 连续数据采集的触发机制,主要由iio trigger实现;
- Iio device的事件触发机制,主要由iio event实现;
- 提供单次原始数据的采集功能,主要通过syfs属性文件实现。
基本就是这些内容,iio子系统主要借助字符设备文件以及sysfs属性文件实现数据的获取与参数设定等操作。
而在iio子系统中,主要包括如下几个数据结构:
- struct iio_dev,描述一个iio device
- struct iio_event_interface,描述iio device的事件触发模块的数据结构;
- struct iio_buffer,描述iio device连续数据采集功能相关的数据结构;
- struct iio_trigger,描述iio device的trigger机制相关的数据结构
- struct iio_chan_spec,描述iio device的一个通道的属性信息;
- struct iio_info,描述iio device各通道的原始数据读取接口、event使能与event参数读写相关接口、trigger有效性检测接口、设备树节点解析等接口;
- struct iio_buffer_setup_ops,描述iio buffer使能与否的接口(建立iio buffer与iio tigger的关联,从而保证iio trigger触发后,可将数据刷新到对应的iio buffer中);
- struct iio_chan_spec_ext_info,描述一个channel扩展属性相关的信息,包括属性名称、读写接口等
- struct iio_trigger_ops,表示iio trigger的操作接口,包括设置trigger的状态(使能与否)、重新使能trigger、设备有效性判断等接口;
- struct iio_buffer_access_funcs,描述iio buffer的access接口,包括数据写入到iio buffer的缓存、缓存数据是否有效、从缓存中读取数据等等接口。
1.1、struct iio_dev
该数据结构表示一个iio device,它属于IIO子系统中的核心数据结构,它负责将所有的IIO子系统的数据结构关联起来,下面即是该数据结构主要的内容,下面我们分几部分进行说明。
- modes与currentmode表示该iio device支持的模式及当前所处的模式,目前支持的模式如下,DIRECT_MODE表示不对采集数据进行缓存,可直接读取单次的数据(可通过访问sysfs下的属性文件方式,读取数据);INDIO_BUFFER_XXX表示支持对iio device采集数据进行缓存的模式,可理解为采集连续的数据(这些数据则需要通过访问字符设备文件进行读取);INDIO_EVENT_TRIGGRED则主要表示事件触发功能,如针对温度传感器可监控当前温度是否超过温度告警上限或下限,当出现温度告警后则向SOC发送中断信号,若支持这类功能则增加INDIO_EVENT_TRIGGRED模式的支持即可(事件告警信息也是通过访问字符设备文件读取,但这个字符设备文件有点特殊,其是一个匿名文件)。
include/linux/iio/iio.h
#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
#define INDIO_HARDWARE_TRIGGERED 0x20
- dev则主要借助系统的设备驱动模型,实现对iio device的引用计数,并绑定至iio总线上,同时借助设备驱动模型可在sysfs目录下创建该iio dev的目录,并创建该iio device所有属性文件等等;
- event_interface表示event事件相关的数据结构,该数据结构内部包含一个kfifo,存储iio device push的event信息;
- buffer表示该iio device对应的iio buffer,若系统不支持buffer模式,则无需创建该buffer;
- buffer_list则在一个iio buffer enable时,将active iio buffer加入到该链表中(目前基本上即将iio_dev->buffer添加到该链表上);
- scan_bytes表示单次采集数据的长度,该值主要根据当前active channel的个数、每一个通道采集数据的长度计算而得;
- 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;
- scan_timestamp、scan_index_timestamp主要对于通过buffer采集的数据是否需要时间戳,如果需要对采集的数据增加时间戳,则增加IIO_TIMESTAMP类型的虚拟channel,主要用于对采集的数据增加时间戳;
- 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的驱动);
- pollfunc、pollfunc_event则为buffer、event的中断处理函数的接口信息(使用的中断即为trigger中virtual irq chip注册的irq),现在仅需要关注pollfunc即可,基本上没有使用pollfunc_event的;
- channels是该iio device所有channel相关的参数信息,我们在iio_chan_spec中将详细说明;
- channel_attr_list链表包含了IIO子系统为所有channel创建的动态属性(针对hwmon子系统我们之前也分析过,其主要通过在sysfs下创建属性文件实现与hwmon device的通信,而IIO子系统也类似,其也在sysfs下创建属性文件实现与iio device的通信,而channel_attr_lis则主要是channel相关的属性的集合);
- groups中包含了所有的group指针,包括channel、event、buffer子模块创建的group,而在调用device_add将该iio device对应的struct device类型变量注册到设备驱动模型子系统中,即遍历该数组,创建属性文件或目录。
- setup_ops则主要是建立buffer与trigger的关联,在该ops中的enable接口中,主要是申请trigger的virt irq chip提供的中断及中断处理函数;在该ops的disable接口中则释放中断。
include/linux/iio/iio.h
struct iio_dev {
int modes;
struct device dev;
struct iio_buffer *buffer;
int scan_bytes;
const unsigned long *available_scan_masks;
unsigned masklength;
const unsigned long *active_scan_mask;
bool scan_timestamp;
struct iio_trigger *trig;
struct iio_poll_func *pollfunc;
struct iio_poll_func *pollfunc_event;
struct iio_chan_spec const *channels;
int num_channels;
const char *name;
const char *label;
const struct iio_info *info;
const struct iio_buffer_setup_ops *setup_ops;
void *priv;
};
1.2、struct iio_event_interface
该数据结构主要是对event子模块的定义,其中:
- 等待队列wait,当应用程序读取触发事件信息时,若当前无数据可读,则将当前进程加入到该等待队列,待调用iio_push_event将触发事件信息加入kfifo后,则wakeup该队列中的进程;
- 定义kfifo,存储所有触发的事件信息,供应用程序获取;
- 将even子模块动态定义的event attribute均添加至该链表中(属性名称格式为{iio_dir}_{iio_channel_type}{channel-Index/channel_modify}_{ev_type}_{ev_dir}_{ev_info});
- flags标记该event是否已使能(即应用程序是否通过ioctl调用创建一个匿名fd,若使能则置位IIO_BUSY_BIT_POS)
/**
* struct iio_event_interface - chrdev interface for an event line
* @wait: wait queue to allow blocking reads of events
* @det_events: list of detected events
* @dev_attr_list: list of event interface sysfs attribute
* @flags: file operations related flags including busy flag.
* @group: event interface sysfs attribute group
* @read_lock: lock to protect kfifo read operations
*/
struct iio_event_interface {
wait_queue_head_t wait;
DECLARE_KFIFO(det_events, struct iio_event_data, 16);
struct list_head dev_attr_list;
unsigned long flags;
struct attribute_group group;
struct mutex read_lock;
};
1.3、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主要包括如下几个方面的内容:
- iio_buffer缓存数据的个数(即length);
- iio_buffer每一次采集数据的长度(bytes_per_datum,而bytes_per_datum*length即为kfifo存储数据的内存空间大小);
- Scan_el_dev_attr_list主要用于将所有iio_buffer子模块创建的属性变量集合在一起(iio_buffer);
- scan_el_attrs存储各设备驱动自行定义的静态属性(生成的属性文件在scan_elements子目录下);
- attrs也是存储存储各设备驱动自行定义的静态属性(该变量定义的属性文件在buffer子目录下);
- buffer_group、scan_el_group包含iio buffer子模块下所有属性,其中buffer_group里的属性均在buffer子目录下创建对应的属性文件;scan_el_group里的属性均在scan_elements子目录下创建对应的属性文件;
- pollq为等待队列,主要为iio device的字符设备文件使用(该字符设备文件对应的读接口和poll接口使用,当buffer中不存在数据时则sleep在该等待队列中);
- 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中取出缓存数据等。
include/linux/iio/buffer_impl.h
/**
* struct iio_buffer - general buffer structure
*
* Note that the internals of this structure should only be of interest to
* those writing new buffer implementations.
*/
struct iio_buffer {
/** @length: Number of datums in buffer. */
unsigned int length;
/** @flags: File ops flags including busy flag. */
unsigned long flags;
/** @bytes_per_datum: Size of individual datum including timestamp. */
size_t bytes_per_datum;
/* @direction: Direction of the data stream (in/out). */
enum iio_buffer_direction direction;
/**
* @access: Buffer access functions associated with the
* implementation.
*/
const struct iio_buffer_access_funcs *access;
/** @scan_mask: Bitmask used in masking scan mode elements. */
long *scan_mask;
/** @demux_list: List of operations required to demux the scan. */
struct list_head demux_list;
/** @pollq: Wait queue to allow for polling on the buffer. */
wait_queue_head_t pollq;
/** @watermark: Number of datums to wait for poll/read. */
unsigned int watermark;
/* private: */
/* @scan_timestamp: Does the scan mode include a timestamp. */
bool scan_timestamp;
/* @buffer_attr_list: List of buffer attributes. */
struct list_head buffer_attr_list;
/*
* @buffer_group: Attributes of the new buffer group.
* Includes scan elements attributes.
*/
struct attribute_group buffer_group;
/* @attrs: Standard attributes of the buffer. */
const struct iio_dev_attr **attrs;
/* @demux_bounce: Buffer for doing gather from incoming scan. */
void *demux_bounce;
/* @attached_entry: Entry in the devices list of buffers attached by the driver. */
struct list_head attached_entry;
/* @buffer_list: Entry in the devices list of current buffers. */
struct list_head buffer_list;
/* @ref: Reference count of the buffer. */
struct kref ref;
};
include/linux/iio/buffer_impl.h
struct iio_buffer_access_funcs {
int (*store_to)(struct iio_buffer *buffer, const void *data);
int (*read)(struct iio_buffer *buffer, size_t n, char __user *buf);
size_t (*data_available)(struct iio_buffer *buffer);
int (*remove_from)(struct iio_buffer *buffer, void *data);
int (*write)(struct iio_buffer *buffer, size_t n, const char __user *buf);
size_t (*space_available)(struct iio_buffer *buffer);
int (*request_update)(struct iio_buffer *buffer);
int (*set_bytes_per_datum)(struct iio_buffer *buffer, size_t bpd);
int (*set_length)(struct iio_buffer *buffer, unsigned int length);
int (*enable)(struct iio_buffer *buffer, struct iio_dev *indio_dev);
int (*disable)(struct iio_buffer *buffer, struct iio_dev *indio_dev);
void (*release)(struct iio_buffer *buffer);
unsigned int modes;
unsigned int flags;
};
1.4、struct iio_trigger与struct iio_trigger_ops
这两个数据结构主要实现iio 的trigger机制,类似于led子系统的led trigger。主要内容如下:
- id表示trigger的id、name为名称;
- 该iio trigger也使用struct device类型的变量加入到iio总线上,iio trigger与iio device均注册到iio总线上,因此它们在sysfs目录下是同级的;
- list用于将struct iio trigger添加系统全局链表iio_trigger_list中;
- alloc_list主要用于同一类型的trigger可注册多个trigger实例的请求,如trigger-period则使用该变量将trigger插入到iio_prtc_trigger_list中,目前使用这一变量的trigger并不多;
- 使用计数use_count;
- 而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绑定,则可以实现该接口进行限制操作)
include/linux/iio/trigger.h
struct iio_trigger {
const struct iio_trigger_ops *ops;
struct module *owner;
int id;
const char *name;
struct device dev;
struct list_head list;
struct list_head alloc_list;
atomic_t use_count;
struct irq_chip subirq_chip;
int subirq_base;
struct iio_subirq subirqs[CONFIG_IIO_CONSUMERS_PER_TRIGGER];
unsigned long pool[BITS_TO_LONGS(CONFIG_IIO_CONSUMERS_PER_TRIGGER)];
struct mutex pool_lock;
bool attached_own_device;
struct work_struct reenable_work;
};
include/linux/iio/trigger.h
struct iio_trigger_ops {
int (*set_trigger_state)(struct iio_trigger *trig, bool state);
void (*reenable)(struct iio_trigger *trig);
int (*validate_device)(struct iio_trigger *trig,
struct iio_dev *indio_dev);
};
1.5、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主要涉及如下内容:
- 该channel的类型,channel类型的定义为等等enum iio_chan_type,包括IIO_TEMP、IIO_VOLTAGE等;
- channel表示该channel的index,当indexed为1时,才使用该index表示channel里的属性参数;
- channel2表示channel的别称,当modified为1时,则使用该index对应的string描述channel的别称(如针对三轴陀螺仪而言,如果还使用channel0、channel1进行识别的话不好区分,可使用modified识别为channelX、channelY、channelZ等)
- info_mask_separate表示channel的某一个属性为channel专属的
- Shared_by_type则表示该iio device下所有相同类型channel所共享的属性;
- Shared_by_dir则表示该iio device下所有相同方向channel所共享的属性;
- Shared_by_all则表示该iio device下所有channel所共享的属性
- scan_index、scan_type则表示采集数据的index及数据的类型等(这两个变量主要由buffer使用)
- event_spec定义event相关的信息;
该数据结构定义的变量,主要用于创建channel相关的属性参数,命名规则为{iio_dir}_{iio_channel_type}{channel-Index/channel_modify}_xxx。
include/linux/iio/iio.h
struct iio_chan_spec {
enum iio_chan_type type;
int channel;
int channel2;
unsigned long address;
int scan_index;
struct {
char sign;
u8 realbits;
u8 storagebits;
u8 shift;
u8 repeat;
enum iio_endian endianness;
} scan_type;
long info_mask_separate;
long info_mask_shared_by_type;
long info_mask_shared_by_dir;
long info_mask_shared_by_all;
const struct iio_event_spec *event_spec;
unsigned int num_event_specs;
const struct iio_chan_spec_ext_info *ext_info;
const char *extend_name;
const char *datasheet_name;
unsigned modified:1;
unsigned indexed:1;
unsigned output:1;
unsigned differential:1;
};
而struct iio_event_spec主要内容如下:
该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})。
1.6、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相关的属性参数)。
include/linux/iio/iio.h
struct iio_info {
const struct attribute_group *event_attrs;
const struct attribute_group *attrs;
int (*read_raw)(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val,
int *val2,
long mask);
int (*read_raw_multi)(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int max_len,
int *vals,
int *val_len,
long mask);
int (*read_avail)(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
const int **vals,
int *type,
int *length,
long mask);
int (*write_raw)(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int val,
int val2,
long mask);
int (*read_label)(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
char *label);
int (*write_raw_get_fmt)(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
long mask);
int (*read_event_config)(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir);
int (*write_event_config)(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
int state);
int (*read_event_value)(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
enum iio_event_info info, int *val, int *val2);
int (*write_event_value)(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
enum iio_event_info info, int val, int val2);
int (*validate_trigger)(struct iio_dev *indio_dev,
struct iio_trigger *trig);
int (*update_scan_mode)(struct iio_dev *indio_dev,
const unsigned long *scan_mask);
int (*debugfs_reg_access)(struct iio_dev *indio_dev,
unsigned reg, unsigned writeval,
unsigned *readval);
int (*fwnode_xlate)(struct iio_dev *indio_dev,
const struct fwnode_reference_args *iiospec);
int (*hwfifo_set_watermark)(struct iio_dev *indio_dev, unsigned val);
int (*hwfifo_flush_to_buffer)(struct iio_dev *indio_dev,
unsigned count);
};
二、数据结构间的关联说明
如下为上述这些数据结构间的关联图,通过struct iio_dev,将所有定义的数据结构关联起来,这些数据结构基本上是在iio_device_register时完成关联的。借助这种数据结构间的关联也方便我们较好的理解该子系统的设计实现。
以下是 IIO 子系统中一些关键数据结构之间的关系及其作用说明:
1. IIO 设备 (struct iio_dev
)
struct iio_dev
是 IIO 子系统中最重要的结构体之一,它代表一个 IIO 设备。每个硬件传感器或数据采集设备都会有一个对应的 struct iio_dev
实例。
- 作用:它表示一个具体的设备,包含设备的配置信息、状态、属性、缓冲区和事件处理等。
struct iio_dev {
struct device dev; // 内核设备结构体
struct iio_info *info; // 指向设备相关操作的函数结构体
unsigned int num_channels; // 设备的通道数
struct iio_chan_spec *channels; // 设备通道配置
struct iio_buffer *buffer; // 指向设备数据缓冲区
// 其他成员,包含时间戳、状态标志等
};
2. IIO 设备通道 (struct iio_chan_spec
)
IIO 设备通常有多个通道,表示不同的物理传感器或数据源。每个通道通过 struct iio_chan_spec
进行描述。
- 作用:
struct iio_chan_spec
存储了 IIO 设备每个通道的配置和属性。不同的传感器可能有不同的数据类型、采样率等,因此需要独立描述。
struct iio_chan_spec {
unsigned int channel; // 通道号
enum iio_chan_type type; // 通道类型,如电压、温度、压力等
unsigned int address; // 通道的物理地址
unsigned int info_mask_separate[2]; // 设备支持的操作集合
// 其他成员,例如放大倍数、采样频率等
};
3. IIO 信息结构 (struct iio_info
)
struct iio_info
提供了一组指针,指向设备操作的回调函数。这些回调函数包括数据读取、配置、事件处理等操作。
- 作用:
struct iio_info
定义了与 IIO 设备交互的接口,通过该结构,内核代码和用户空间应用程序能够与设备进行交互。
struct iio_info {
int (*read_raw)(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2);
int (*write_raw)(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int val, int val2);
int (*read_event_value)(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val);
// 其他回调函数,例如事件处理、缓冲区管理等
};
4. IIO 缓冲区 (struct iio_buffer
)
IIO 支持将设备的输出数据存储到缓冲区中,尤其适用于需要周期性数据采集的传感器。struct iio_buffer
描述了这些缓冲区。
- 作用:
struct iio_buffer
用于缓存从传感器获取的数据,提供了用户空间与设备之间的高效数据交换机制。
struct iio_buffer {
struct iio_dev *indio_dev; // 设备的指针
unsigned long size; // 缓冲区的大小
void *data; // 缓冲区的数据
// 其他成员,包含 DMA 信息、读写指针等
};
5. IIO 事件 (struct iio_event_data
)
IIO 支持基于阈值和其他条件触发的事件。struct iio_event_data
用于描述这些事件。
- 作用:
struct iio_event_data
存储与 IIO 设备相关的事件信息,例如事件触发的阈值、时间戳等。
struct iio_event_data {
struct iio_chan_spec chan; // 触发事件的通道
int event_type; // 事件类型,例如阈值超限等
int event_value; // 事件的值
// 其他成员,包含时间戳等
};
6. IIO 驱动结构 (struct iio_driver
)
IIO 驱动程序负责与硬件设备进行交互,通过提供 struct iio_driver
结构体来注册驱动。
- 作用:
struct iio_driver
描述了与 IIO 设备交互的函数和设备的匹配关系。
struct iio_driver {
struct device_driver driver; // 驱动的基础结构
int (*probe)(struct iio_dev *indio_dev); // 驱动探测函数
int (*remove)(struct iio_dev *indio_dev); // 驱动移除函数
// 其他成员,包含与设备的配置相关的操作
};
7. IIO 事件缓冲区 (struct iio_event_buffer
)
IIO 事件缓冲区用于存储事件数据,通常在事件发生时将数据写入缓冲区,以供用户空间程序读取。
- 作用:
struct iio_event_buffer
存储触发的事件信息和相关的元数据。
struct iio_event_buffer {
struct iio_event_data *data; // 存储事件的数据
unsigned int size; // 缓冲区大小
// 其他成员,包含读写指针、DMA 配置等
};
8.数据结构间的关联
-
struct iio_dev
是 IIO 设备的核心结构,包含了与设备操作相关的信息,如设备属性、通道、驱动回调函数等。- 它通过
channels
指针关联了多个struct iio_chan_spec
结构,每个通道描述了传感器的具体配置。 - 它通过
info
指针关联了struct iio_info
,其中包含了读取和控制设备数据的回调函数。 - 通过
buffer
指针,它还可以与struct iio_buffer
关联,从而支持数据的缓冲。
- 它通过
-
struct iio_event_data
描述了设备的事件,可以通过iio_event_buffer
被存储,便于事件的处理和用户空间的访问。 -
驱动通过
struct iio_driver
注册到内核,将设备与操作函数(如数据读取、事件处理等)连接起来。