linux中IIO子系统------IIO数据结构部分解析1

一、kernel/include/linux/iio/iio.h
1.iio_dev结构体

struct iio_dev {
	int				id;
	struct module			*driver_module;
	int				modes;//表示设备支持的不同操作模式
	int				currentmode;//表示设备实际使用的模式
	struct device			dev;//表示IIO设备所依赖的struct设备(根据Linux设备型号)
	struct iio_event_interface	*event_interface;
	struct iio_buffer		*buffer;//数据缓冲区,在使用触发缓冲区模式时会推送到用户空间
	struct list_head		buffer_list;
	int				scan_bytes;//这是捕获并馈送到缓冲区的字节数。
	struct mutex			mlock;
	const unsigned long		*available_scan_masks;//允许的位掩码的可选数组
	unsigned			masklength;
	const unsigned long		*active_scan_mask;//启用通道的位掩码,只有来自这些通道的数据能被推入缓冲区
	bool				scan_timestamp;//否将捕获时间戳推入缓冲区
	unsigned			scan_index_timestamp;
	struct iio_trigger		*trig;//当前设备触发器(支持缓冲模式时)
	bool				trig_readonly;
	struct iio_poll_func		*pollfunc;//在接收的触发器上运行的函数
	struct iio_poll_func		*pollfunc_event;

	struct iio_chan_spec const	*channels;//表示通道规范结构,用于描述设备具有的每个通道
	int				num_channels;//表示通道中指定的通道数

	struct list_head		channel_attr_list;
	struct attribute_group		chan_attr_group;
	const char			*name;//表示设备名称
	const struct iio_info		*info;//来自驱动程序的回调和持续信息
	clockid_t			clock_id;
	struct mutex			info_exist_lock;
	const struct iio_buffer_setup_ops	*setup_ops;//启用/禁用缓冲区之前和之后调用的回调函数集
	struct cdev			chrdev;//由IIO核心创建的关联字符设备
#define IIO_MAX_GROUPS 6
	const struct attribute_group	*groups[IIO_MAX_GROUPS + 1];
	int				groupcounter;
	unsigned long			flags;
#if defined(CONFIG_DEBUG_FS)
	struct dentry			*debugfs_dentry;
	unsigned			cached_reg_addr;
#endif
};
  • modes:支持的模式有
    INDIO_DIRECT_MODE表示设备提供的sysfs接口。
    INDIO_BUFFER_TRIGGERED表示设备支持硬件触发器。 使用iio_triggered_buffer_setup()函数设置触发缓冲区时,此模式会自动添加到设备中。
    INDIO_BUFFER_HARDWARE表示设备具有硬件缓冲区。
    INDIO_ALL_BUFFER_MODES是上述两者的联合
  • buffer:使用iio_triggered_buffer_setup函数启用触发缓冲区支持时,它会自动分配并与您的设备关联
  • scan_bytes:当从用户空间使用触发缓冲区时,缓冲区应至少为indio->scan_bytes字节大
  • available_scan_masks:使用触发缓冲器时,可以启用通道捕获并将其馈入IIO缓冲区,若不允许某些通道启用,则仅使用允许的通道填充此数组
enum max3012_led_idx {
	MAX30102_LED_RED,
	MAX30102_LED_IR,
	MAX30105_LED_GREEN,
};
//可选
static const unsigned long max30102_scan_masks[] = {
	BIT(MAX30102_LED_RED) | BIT(MAX30102_LED_IR),
	0
};
static const unsigned long max30105_scan_masks[] = {
	BIT(MAX30102_LED_RED) | BIT(MAX30102_LED_IR),
	BIT(MAX30102_LED_RED) | BIT(MAX30102_LED_IR) |
		BIT(MAX30105_LED_GREEN),
	0
};
indio_dev->available_scan_masks = max30105_scan_masks;
  • active_scan_mask:启用通道的位掩码。 只有来自这些通道的数据能被推入缓冲区。例如,对于8通道ADC转换器,如果只启用第一个(0),第三个(2)和最后一个(7)通道,则位掩码将为0b10000101(0x85)。active_scan_mask将设置为0x85。然后,驱动程序可以使用for_each_set_bit宏遍历每个设置位,根据通道获取数据,并填充缓冲区
for_each_set_bit(bit, indio_dev->active_scan_mask,
			 indio_dev->masklength) {
		ret = kmx61_read_measurement(data, base, bit);
		if (ret < 0) {
			mutex_unlock(&data->lock);
			goto err;
		}
		buffer[i++] = ret;
	}
  • scan_timestamp:是否将捕获时间戳推入缓冲区。 如果为true,则将时间戳作为缓冲区的最后一个元素。时间戳大8字节(64位)

2.iio_info结构体

//kernel/include/linux/iio/iio.h
struct iio_info {
	const struct attribute_group	*event_attrs;
	const struct attribute_group	*attrs;//表示设备属性
	//用户读取设备sysfs文件属性时的回调运行
	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 (*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 (*of_xlate)(struct iio_dev *indio_dev,const struct of_phandle_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);
};
//示例
static const struct iio_info kmx61_acc_info = {
	.read_raw		= kmx61_read_raw,
	.write_raw		= kmx61_write_raw,
	.attrs			= &kmx61_acc_attribute_group,
	.read_event_value	= kmx61_read_event,
	.write_event_value	= kmx61_write_event,
	.read_event_config	= kmx61_read_event_config,
	.write_event_config	= kmx61_write_event_config,
	.validate_trigger	= kmx61_acc_validate_trigger,
};
indio_dev->info = &kmx61_acc_info;

3.iio_chan_spec结构体

//通道代表单条采集线
struct iio_chan_spec {
	enum iio_chan_type	type;//指定了通道的测量类型
	int			channel;//指定.indexed设置为1时的通道索引
	int			channel2;//指定.modified设置为1时的通道修饰
	unsigned long		address;
//scan_index and scan_type: 当使用缓冲区触发器时,这些字段用于标识缓冲区中的元素
	int			scan_index;//设置缓冲区内捕获的通道的位置,.scan_index=-1将阻止通道缓冲捕获
	struct {
		char	sign; //'s' or 'u'描述有符号和无符号
		u8	realbits;//有效位数
		u8	storagebits;//Realbits + padding
		u8	shift;
		u8	repeat;
		enum iio_endian endianness; //little or big endian,字节序
	} scan_type;
	long			info_mask_separate;//将属性标记为特定于此通道
	long			info_mask_separate_available;
	long			info_mask_shared_by_type;//将该属性标记为由相同类型的所有通道共享
	long			info_mask_shared_by_type_available;
	long			info_mask_shared_by_dir;//将属性标记为由同一方向的所有通道共享
	long			info_mask_shared_by_dir_available;
	long			info_mask_shared_by_all;//将属性标记为所有通道共享
	long			info_mask_shared_by_all_available;
	const struct iio_event_spec *event_spec;
	unsigned int		num_event_specs;
	const struct iio_chan_spec_ext_info *ext_info;//描述一个channel扩展属性相关的信息,包括属性名称、读写接口等
	const char		*extend_name;
	const char		*datasheet_name;
	unsigned		modified:1;//指定是否将修饰符应用于此通道属性名称,饰符设置在.channel2中
	unsigned		indexed:1;//指定通道属性名称是否具有索引,若是,在.channel字段中指定索引
	unsigned		output:1;  //channel是输出
	unsigned		differential:1;
};
  • type: 指定了通道的测量类型。 在电压测量的情况下,它应该是IIO_VOLTAGE。 对于光传感器,它是IIO_LIGHT。对于加速度计,使用IIO_ACCEL。 所有可用类型都在include / uapi / linux / iio /types.h中定义,如enum iio_chan_type。 要为给定转换器编写驱动程序,请查看该文件以查看每个通道所属的类型
//type对应的通道类型根据iio_chan_type_name_spec
static const char * const iio_chan_type_name_spec[] = {
	[IIO_VOLTAGE] = "voltage",
	[IIO_CURRENT] = "current",
	[IIO_POWER] = "power",
	[IIO_ACCEL] = "accel",
};
//channel2字段根据modifier=1时iio_modifier_names
static const char * const iio_modifier_names[] = {
	[IIO_MOD_X] = "x",
	[IIO_MOD_Y] = "y",
	[IIO_MOD_Z] = "z",
	[IIO_MOD_X_AND_Y] = "x&y",
};
//info_mask取决于char数组iio_chan_info_postfix中的通道信息掩码
static const char * const iio_chan_info_postfix[] = {
	[IIO_CHAN_INFO_RAW] = "raw",
	[IIO_CHAN_INFO_PROCESSED] = "input",
	[IIO_CHAN_INFO_SCALE] = "scale",
	[IIO_CHAN_INFO_OFFSET] = "offset",
};

参考链接请点击而此处
IIO子系统概述请点击此处
在学习中进步,如有错误,请多多批评指正

你可能感兴趣的:(linux驱动学习,linux,数据结构)