iio子系统框架分析

学习目的

iio子系统主要提供对ADC、DAC相关的设备驱动框架。面向的设备包括:

1.ADC芯片;2.DAC芯片;3.温度传感器;4.光感器;5.陀螺仪;6.加速度传感器;7.CDCs;​8.IMUs;9.压力传感器等

公司以前的sensor驱动以及sensorHAL都是使用input子系统,而纵观其他厂商以及google,都已经不再使用这个框架,iio这个子系统框架才是目前的主流。因此有必要弄清楚这个子系统通路,了解驱动如何实现以及数据如何读取。

全文主要分两个部分,分别是驱动层实现和用户空间接口。

驱动层主要囊括相关的数据结构以及接口,然后以inv_mpu6050驱动为例进行分析。

用户层以节点的使用为主,以android的invensense hal层为例进行分析。

参考博客:

lickylin的专栏_jerry_chg_CSDN博客-Linux 内核,linux 网络,数据结构与算法领域博主

https://blog.csdn.net/u014078917/category_8417773.html

iio子系统驱动层

iio驱动实际属于字符设备驱动的一种,其核心代码位于kernel/drivers/iio目录下。下图是框架图:

iio子系统框架分析_第1张图片

驱动框架中,核心部分就是iio_ring、iio_core和iio_trigger这三部分。其中iio_core是整个iio子系统的核心组合,iio_ring是连续数据的buffer核心,iio_trigger是触发器的核心,这三个部分与用户空间交互主要是通过字符设备驱动节点与sysfs,iio_core由于是整个的核心,因此交互部分不能绕过它,而iio_ring的读取主要是通过字符设备驱动节点挂钩,而iio_trigger则是通过sysfs来进行控制。

简介

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

主要的数据结构:

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.struct iio_dev

描述一个iio device

507 struct iio_dev {
508     int             id;
509
510     int             modes;
511     int             currentmode;
512     struct device           dev;
513
514     struct iio_event_interface  *event_interface;
515
516     struct iio_buffer       *buffer;
517     struct list_head        buffer_list;
518     int             scan_bytes;
519     struct mutex            mlock;
520
521     const unsigned long     *available_scan_masks;
522     unsigned            masklength;
523     const unsigned long     *active_scan_mask;
524     bool                scan_timestamp;
525     unsigned            scan_index_timestamp;
526     struct iio_trigger      *trig;
527     bool                trig_readonly;
528     struct iio_poll_func        *pollfunc;
529     struct iio_poll_func        *pollfunc_event;
530
531     struct iio_chan_spec const  *channels;
532     int             num_channels;
533
534     struct list_head        channel_attr_list;
535     struct attribute_group      chan_attr_group;
536     const char          *name;
537     const struct iio_info       *info;
538     clockid_t           clock_id;
539     struct mutex            info_exist_lock;
540     const struct iio_buffer_setup_ops   *setup_ops;
541     struct cdev         chrdev;
542 #define IIO_MAX_GROUPS 6
543     const struct attribute_group    *groups[IIO_MAX_GROUPS + 1];
544     int             groupcounter;
545
546     unsigned long           flags;
547 #if defined(CONFIG_DEBUG_FS)
548     struct dentry           *debugfs_dentry;
549     unsigned            cached_reg_addr;
550 #endif
551 };

1.modes与currentmode表示该iio device支持的模式以及当前所处的模式,目前支持5种模式

319 #define INDIO_DIRECT_MODE       0x01
320 #define INDIO_BUFFER_TRIGGERED      0x02
321 #define INDIO_BUFFER_SOFTWARE       0x04
322 #define INDIO_BUFFER_HARDWARE       0x08
323 #define INDIO_EVENT_TRIGGERED       0x10

INDIO_DIRECT_MODE表示不对采集数据进行缓存,可直接读取单次的数据(可通过访问sysfs下的属性节点文件读取)。

INDIO_BUFFER_XXX表示支持对iio device采集数据进行缓存的模式,可理解为采集连续的数据(这些数据则需要通过访问字符设备文件进行读取,即通过iio_ring部分)。

INDIO_EVENT_TRIGGERED则主要表示事件触发功能,如针对温度传感器可监控当前是否超过温度告警上限或下限,当出现温度告警后则向SOC发送中断信号,

2.dev主要借助系统的设备驱动模型,实现对iio device的引用计数,并绑定至iio总线上,同时借助设备驱动模型可在sysfs目录下创建该设备的目录和属性文件。

3.event_interface表示event事件相关的数据结构,该数据结构内部包含一个kfifo,存储iio device push的event信息。

4.buffer表示该iio device对应的iio_buffer,针对连续采集数据模式,若不支持,则无需创建。

5.buffer_list则在一个iio buffer enable时,将active iio buffer加入到该链表中(目前基本上只将iio_dev->buffer添加到该链表上)。

6.scan_bytes表示单次采集数据的长度,该值主要根据当前的active channel的个数,每一个通道采集数据的长度计算而得。

7.available_scan_masks表示当前iio device可使用的channel的掩码,如当前有8个channel,仅前4个channel可用,则可以设置available_scan_masks值为0x0F。

8.active_scan_mask则表示当前已使能的channel掩码,这个mask是available_scan_masks的子集,不能超出其范围。

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

9.scan_timestamp、scan_index_timestamp主要对于通过buffer采集的数据是否需要时间戳,如果需要对采集的数据增加时间戳,则增加IIO_TIMESTAMP类型的虚拟channel,使采集的数据增加时间戳。

10.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的驱动。

11.pollfunc、pollfunc_event则为buffer、event的中断处理函数(使用的中断即为trigger中的virtual irq chip注册时irq)。

12.channels是该iio device所有channel的相关参数信息,iio_chan_spec中详细说明。

13.channel_attr_list包含了iio系统为所有channel创建的动态属性,类似于hwmon子系统,在sysfs下创建属性文件实现与iio device的通信,而channel_attr_list则主要是channel相关的属性集合。

14.groups中包含了所有的group指针,包括channel、event’buffer子模块创建的group,而在调用device_add将该iio device对应的struct device泪习惯变量注册到驱动模型子系统中,会遍历该数组,创建属性文件或目录。

15.setup_ops则主要是创建buffer与trigger的关联,在该ops中的enable接口中,主要是申请trigger的virtual irq chip提供的中断以及中断处理函数没在disable接口中释放中断。

设备中主要填充iio_dev的字段有以下:

1.modes; 2.dev; 3.event_interface;4.buffer; 5.available_scan_masks;6.trig; 7.pollfunc/pollfunc_event; 8.channels; 9.setup_ops;

2.struct iio_event_interface

对event子模块的定义。

 37 struct iio_event_interface {
 38     wait_queue_head_t   wait;
 39     DECLARE_KFIFO(det_events, struct iio_event_data, 16);
 40
 41     struct list_head    dev_attr_list;
 42     unsigned long       flags;
 43     struct attribute_group  group;
 44     struct mutex        read_lock;
 45 };

1.wait等待队列,当应用程序读取触发事件信息时,若当前无数据可读,则将当前进程加入到该等待队列中,待调用iio_push_event将触发事件信息加到到kfifo后,则wakeup该队列中的进程。

2.定义kfifo,存储所有触发的时间信息,供应用程序获取。

3,将event子模块动态定义的event attribute均添加到dev_attr_list中。

4.flags标记该event是否已经使能,即应用程序是否通过ioctl调用创建一个匿名方式,若使能则置位IIO_BUSY_BIT_POS。

3.struct iio_buffer

描述存储连续采集数据的缓存。

 98 struct iio_buffer {
 99     unsigned int                length;
100     size_t                  bytes_per_datum;
101     struct attribute_group          *scan_el_attrs;
102     long                    *scan_mask;
103     bool                    scan_timestamp;
104     const struct iio_buffer_access_funcs    *access;
105     struct list_head            scan_el_dev_attr_list;
106     struct attribute_group          buffer_group;
107     struct attribute_group          scan_el_group;
108     wait_queue_head_t           pollq;
109     bool                    stufftoread;
110     const struct attribute          **attrs;
111     struct list_head            demux_list;
112     void                    *demux_bounce;
113     struct list_head            buffer_list;
114     struct kref             ref;
115     unsigned int                watermark;
116 };

1.length, iio_buffer缓存数据的个数。

2.bytes_per_datum,iio_buffer每一次采集数据的长度,bytes_per_datum * length即kfifo存储数据的内存大小。

3.scan_el_attrs存储各设备驱动自行定义的静态属性,该变量定义的属性文件在scan_elements子目录下。

4.scan_el_dev_attr_list主要用于将所有iio_buffer子模块创建的属性变量集合在一起。

5.attrs也是村纯设备驱动自行定义的静态属性,属性文件在buffer子目录下。

6.buffer_group、scan_el_group包含iio buffer子模块下所以的属性。

7.pollq为等待队列,主要为iio device的字符设备文件使用,该字符设备文件对应的读接口和poll接口使用,当buffer不存在数据时则sleep在该等待队列中。

8.watermark为缓存多少个数据后唤醒pollq。

9.iio_buffer_access_funcs是iio_buffer对应的缓存空间访问接口,目前使用kfifo缓存数据,其访问方法为iio_store_to_kfifo、iio_read_first_n_kfifo等,主要是将数据从kfifo中存储和取出。

4. struct iio_trigger和struct iio_trigger_ops

 63 struct iio_trigger {
 64     const struct iio_trigger_ops    *ops;
 65     int             id;
 66     const char          *name;
 67     struct device           dev;
 68
 69     struct list_head        list;
 70     struct list_head        alloc_list;
 71     atomic_t            use_count;
 72
 73     struct irq_chip         subirq_chip;
 74     int             subirq_base;
 75
 76     struct iio_subirq subirqs[CONFIG_IIO_CONSUMERS_PER_TRIGGER];
 77     unsigned long pool[BITS_TO_LONGS(CONFIG_IIO_CONSUMERS_PER_TRIGGER)];
 78     struct mutex            pool_lock;
 79     bool                attached_own_device;
 80 };
 36 struct iio_trigger_ops {
 37     struct module *owner;
 38     int (*set_trigger_state)(struct iio_trigger *trig, bool state);
 39     int (*try_reenable)(struct iio_trigger *trig);
 40     int (*validate_device)(struct iio_trigger *trig,
 41                    struct iio_dev *indio_dev);
 42 };

1.id表示trigger的id,name为名称。

2.dev,iio trigger也使用device变量加入到iio总线上,iio trigger与iio device均注册到iio总线上,因此它们在sysfs目录下是同级的。

3.list用于将struct iio_trigger添加到全局链表iio_trigger_list中。

4.alloc_list主要用于同一类的trigger可注册多个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提供的处理函数。

7.iio_trigger_ops是trigger操作接口。

5. struct iio_chan_spec

257 struct iio_chan_spec {
258     enum iio_chan_type  type;
259     int         channel;
260     int         channel2;
261     unsigned long       address;
262     int         scan_index;
263     struct {
264         char    sign;
265         u8  realbits;
266         u8  storagebits;
267         u8  shift;
268         u8  repeat;
269         enum iio_endian endianness;
270     } scan_type;
271     long            info_mask_separate;
272     long            info_mask_shared_by_type;
273     long            info_mask_shared_by_dir;
274     long            info_mask_shared_by_all;
275     const struct iio_event_spec *event_spec;
276     unsigned int        num_event_specs;
277     const struct iio_chan_spec_ext_info *ext_info;
278     const char      *extend_name;
279     const char      *datasheet_name;
280     unsigned        modified:1;
281     unsigned        indexed:1;
282     unsigned        output:1;
283     unsigned        differential:1;
284 };

1.type,该channel的类型,如IIO_TEMP、IIO_ACCEL等。

2.channel表示该channel的index,当indexed为1时,才使用该index表示channel里的属性参数。

3.channel2表示channel的别沉,当modified为1时,才则使用该index对应的string藐视channel。如针对三轴陀螺仪而言,如果还是用channel0、channel1进行识别的话不好区分,可使用channelX,channelY、channelZ等。

4.info_mask_separate表示channel的某一个属性为channel专属的。

5.info_mask_shared_by_type则表示该iio device下所有相同类型的channel所共享的属性。

6.info_mask_shared_by_dir表示该iio device下所有相同方向channel所共享的属性。

7.info_mask_shared_by_all表示该iio device下所有channel所共享的属性。

8.scan_index、scan_type表示采集数据的index以及数据的类型等。

9.event_spac定义event相关的信息。

6. struct iio_info

382 struct iio_info {
383     struct module           *driver_module;
384     struct attribute_group      *event_attrs;
385     const struct attribute_group    *attrs;
386
387     int (*read_raw)(struct iio_dev *indio_dev,
388             struct iio_chan_spec const *chan,
389             int *val,
390             int *val2,
391             long mask);
392
393     int (*read_raw_multi)(struct iio_dev *indio_dev,
394             struct iio_chan_spec const *chan,
395             int max_len,
396             int *vals,
397             int *val_len,
398             long mask);
399
400     int (*write_raw)(struct iio_dev *indio_dev,
401              struct iio_chan_spec const *chan,
402              int val,
403              int val2,
404              long mask);
405
406     int (*write_raw_get_fmt)(struct iio_dev *indio_dev,
407              struct iio_chan_spec const *chan,
408              long mask);
409
410     int (*read_event_config)(struct iio_dev *indio_dev,
411                  const struct iio_chan_spec *chan,
412                  enum iio_event_type type,
413                  enum iio_event_direction dir);
414
415     int (*write_event_config)(struct iio_dev *indio_dev,
416                   const struct iio_chan_spec *chan,
417                   enum iio_event_type type,
418                   enum iio_event_direction dir,
419                   int state);
420
421     int (*read_event_value)(struct iio_dev *indio_dev,
422                 const struct iio_chan_spec *chan,
423                 enum iio_event_type type,
424                 enum iio_event_direction dir,
425                 enum iio_event_info info, int *val, int *val2);
426
427     int (*write_event_value)(struct iio_dev *indio_dev,
428                  const struct iio_chan_spec *chan,
429                  enum iio_event_type type,
430                  enum iio_event_direction dir,
431                  enum iio_event_info info, int val, int val2);
432
433     int (*validate_trigger)(struct iio_dev *indio_dev,
434                 struct iio_trigger *trig);
435     int (*update_scan_mode)(struct iio_dev *indio_dev,
436                 const unsigned long *scan_mask);
437     int (*debugfs_reg_access)(struct iio_dev *indio_dev,
438                   unsigned reg, unsigned writeval,
439                   unsigned *readval);
440     int (*of_xlate)(struct iio_dev *indio_dev,
441             const struct of_phandle_args *iiospec);
442     int (*hwfifo_set_watermark)(struct iio_dev *indio_dev, unsigned val);
443     int (*hwfifo_flush_to_buffer)(struct iio_dev *indio_dev,
444                       unsigned count);
445 };

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

下面我们来看看inv_mpu6050这个驱动是怎么实现的。

inv_mpu6050驱动分析

整个驱动我们主要挑了以下几个方面来看:

1.重要的数据结构是怎么填充以及所调用的接口。

2.数据是如何采集上报的。

probe中的数据结构填充

我们来看i2c设备下的probe,源码在:drivers/iio/imu/inv_mpu6050目录下。我们只关注与iio相关的代码

 92 static int inv_mpu_probe(struct i2c_client *client,
 93              const struct i2c_device_id *id)
 94 {
 95     struct inv_mpu6050_state *st;
 96     int result, chip_type;
 97     struct regmap *regmap;
 98     const char *name;
        ……
122     result = inv_mpu_core_probe(regmap, client->irq, name,
123                     NULL, chip_type);
124     if (result < 0)
125         return result;
126
127     st = iio_priv(dev_get_drvdata(&client->dev));
        ……
144
145     return 0;
152 }

inv_mpu_probe方法与iio相关的操作都在inv_mpu_core_probe中,iio_priv方法是从iio_dev地址上获取到私有数据。

846 int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
847         int (*inv_mpu_bus_setup)(struct iio_dev *), int chip_type)
848 {
849     struct inv_mpu6050_state *st;
850     struct iio_dev *indio_dev;
851     struct inv_mpu6050_platform_data *pdata;
852     struct device *dev = regmap_get_device(regmap);
853     int result;
854
855     indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
856     if (!indio_dev)
857         return -ENOMEM;
858
        ……
899     indio_dev->dev.parent = dev;
900     /* name will be NULL when enumerated via ACPI */
901     if (name)
902         indio_dev->name = name;
903     else
904         indio_dev->name = dev_name(dev);
905     indio_dev->channels = inv_mpu_channels;
906     indio_dev->num_channels = ARRAY_SIZE(inv_mpu_channels);
907
908     indio_dev->info = &mpu_info;
909     indio_dev->modes = INDIO_BUFFER_TRIGGERED;
910
911     result = iio_triggered_buffer_setup(indio_dev,
912                         inv_mpu6050_irq_handler,
913                         inv_mpu6050_read_fifo,
914                         NULL);
915     if (result) {
916         dev_err(dev, "configure buffer fail %d\n", result);
917         return result;
918     }
919     result = inv_mpu6050_probe_trigger(indio_dev);
920     if (result) {
921         dev_err(dev, "trigger probe fail %d\n", result);
922         goto out_unreg_ring;
923     }
924
925     INIT_KFIFO(st->timestamps);
926     spin_lock_init(&st->time_stamp_lock);
927     result = iio_device_register(indio_dev);
928     if (result) {
929         dev_err(dev, "IIO register fail %d\n", result);
930         goto out_remove_trigger;
931     }
932
933     return 0;
934
935 out_remove_trigger:
936     inv_mpu6050_remove_trigger(st);
937 out_unreg_ring:
938     iio_triggered_buffer_cleanup(indio_dev);
939     return result;
940 }

1.devm_iio_device_alloc,用于创建构造iio_dev变量,同时初始化了iio_dev->dev变量,设备的名字是"iio:device%d"格式。

2.indio_dev->dev.parent = dev,此处dev是i2c子设备的device。

3.indio_dev->channels = inv_mpu_channels; && indio_dev->num_channels = ARRAY_SIZE(inv_mpu_channels); iio_chan_spec的填充如下:

714 #define INV_MPU6050_CHAN(_type, _channel2, _index)                    \
715     {                                                             \
716         .type = _type,                                        \
717         .modified = 1,                                        \
718         .channel2 = _channel2,                                \
719         .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
720         .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |        \
721                       BIT(IIO_CHAN_INFO_CALIBBIAS),   \
722         .scan_index = _index,                                 \
723         .scan_type = {                                        \
724                 .sign = 's',                          \
725                 .realbits = 16,                       \
726                 .storagebits = 16,                    \
727                 .shift = 0,                           \
728                 .endianness = IIO_BE,                 \
729                  },                                       \
730         .ext_info = inv_ext_info,                             \
731     }
732
733 static const struct iio_chan_spec inv_mpu_channels[] = {
734     IIO_CHAN_SOFT_TIMESTAMP(INV_MPU6050_SCAN_TIMESTAMP),
735     /*
736      * Note that temperature should only be via polled reading only,
737      * not the final scan elements output.
738      */
739     {
740         .type = IIO_TEMP,
741         .info_mask_separate = BIT(IIO_CHAN_INFO_RAW)
742                 | BIT(IIO_CHAN_INFO_OFFSET)
743                 | BIT(IIO_CHAN_INFO_SCALE),
744         .scan_index = -1,
745     },
746     INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_X, INV_MPU6050_SCAN_GYRO_X),
747     INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_Y, INV_MPU6050_SCAN_GYRO_Y),
748     INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_Z, INV_MPU6050_SCAN_GYRO_Z),
749
750     INV_MPU6050_CHAN(IIO_ACCEL, IIO_MOD_X, INV_MPU6050_SCAN_ACCL_X),
751     INV_MPU6050_CHAN(IIO_ACCEL, IIO_MOD_Y, INV_MPU6050_SCAN_ACCL_Y),
752     INV_MPU6050_CHAN(IIO_ACCEL, IIO_MOD_Z, INV_MPU6050_SCAN_ACCL_Z),
753 };

共有8个channel,分别是IIO_TIMESTAMP(表示虚拟通道-时间戳)、IIO_TEMP(温度)、3个IIO_ANGL_VEL(角度传感器3个轴)和3个IIO_ACCEL(加速度传感器3个轴)。6轴的channel使用宏INV_MPU6050_CHAN来定义,表明他们的参数基本一致。

4.indio_dev->info = &mpu_info;

784 static const struct iio_info mpu_info = {
785     .driver_module = THIS_MODULE,
786     .read_raw = &inv_mpu6050_read_raw,
787     .write_raw = &inv_mpu6050_write_raw,
788     .write_raw_get_fmt = &inv_write_raw_get_fmt,
789     .attrs = &inv_attribute_group,
790     .validate_trigger = inv_mpu6050_validate_trigger,
791 };

5.indio_dev->modes = INDIO_BUFFER_TRIGGERED;inv_mpu6050只使用了buffer trigger这种模式。

6.iio_triggered_buffer_setup,创建kfifo和iio_buffer_setup_ops,是iio的标准接口。

 44 int iio_triggered_buffer_setup(struct iio_dev *indio_dev,
 45     irqreturn_t (*h)(int irq, void *p),
 46     irqreturn_t (*thread)(int irq, void *p),
 47     const struct iio_buffer_setup_ops *setup_ops)
 48 {
 49     struct iio_buffer *buffer;
 50     int ret;
 51
 52     buffer = iio_kfifo_allocate();
 53     if (!buffer) {
 54         ret = -ENOMEM;
 55         goto error_ret;
 56     }
 57
 58     iio_device_attach_buffer(indio_dev, buffer);
 59
 60     indio_dev->pollfunc = iio_alloc_pollfunc(h,
 61                          thread,
 62                          IRQF_ONESHOT,
 63                          indio_dev,
 64                          "%s_consumer%d",
 65                          indio_dev->name,
 66                          indio_dev->id);
 67     if (indio_dev->pollfunc == NULL) {
 68         ret = -ENOMEM;
 69         goto error_kfifo_free;
 70     }
 71
 72     /* Ring buffer functions - here trigger setup related */
 73     if (setup_ops)
 74         indio_dev->setup_ops = setup_ops;
 75     else
 76         indio_dev->setup_ops = &iio_triggered_buffer_setup_ops;
 77
 78     /* Flag that polled ring buffering is possible */
 79     indio_dev->modes |= INDIO_BUFFER_TRIGGERED;
 80
 81     return 0;
 82
 83 error_kfifo_free:
 84     iio_kfifo_free(indio_dev->buffer);
 85 error_ret:
 86     return ret;
 87 }

iio_kfifo_allocate创建了iio_buffer,并未iio_buffer填充了access和length字段,length默认为2。iio_device_attach_buffer将创建的iio_buffer与iio_dev关联起来。函数参数h和thread分别是irq的上半部和下半部,并调用iio_alloc_pollfunc生成pollfunc。iio_dev的setup_ops,如果传参为NULL,则使用默认的参数&iio_triggered_buffer_setup_ops。

7.inv_mpu6050_probe_trigger,调用devm_iio_trigger_alloc申请注册trigger的virtual irq,并调用iio_trigger_register注册trigger。

8.完成以上准备操作后,注册iio_dev,调用iio_device_register进行注册。

以上是iio设备驱动probe所做的事情,这样看起来probe做的事情并不多,实际上大部分的sysfs节点和chrdev的注册都是有iio core实现的。下面我们主要分析iio的核心框架是怎么做的。

iio_buffer

iio_device_register方法为iio设备驱动创建了buffer和channel的sysfs。

1478 int iio_device_register(struct iio_dev *indio_dev)
1479 {
1480     int ret;
1481
1482     /* If the calling driver did not initialize of_node, do it here */
1483     if (!indio_dev->dev.of_node && indio_dev->dev.parent)
1484         indio_dev->dev.of_node = indio_dev->dev.parent->of_node;
1485     // channels scan_index不能有重复
1486     ret = iio_check_unique_scan_index(indio_dev);
1487     if (ret < 0)
1488         return ret;
1489
1490     /* configure elements for the chrdev */
1491     indio_dev->dev.devt = MKDEV(MAJOR(iio_devt), indio_dev->id);
1492
1493     ret = iio_device_register_debugfs(indio_dev);
1494     if (ret) {
1495         dev_err(indio_dev->dev.parent,
1496             "Failed to register debugfs interfaces\n");
1497         return ret;
1498     }
1499     // 创建buffer和scan_elements下的属性节点
1500     ret = iio_buffer_alloc_sysfs_and_mask(indio_dev);
1501     if (ret) {
1502         dev_err(indio_dev->dev.parent,
1503             "Failed to create buffer sysfs interfaces\n");
1504         goto error_unreg_debugfs;
1505     }
1506    // 创建channel的属性节点。
1507     ret = iio_device_register_sysfs(indio_dev);
1508     if (ret) {
1509         dev_err(indio_dev->dev.parent,
1510             "Failed to register sysfs interfaces\n");
1511         goto error_buffer_free_sysfs;
1512     }
1513     ret = iio_device_register_eventset(indio_dev);  //创建events的属性节点
1514     if (ret) {
1515         dev_err(indio_dev->dev.parent,
1516             "Failed to register event set\n");
1517         goto error_free_sysfs;
1518     }
1519     if (indio_dev->modes & (INDIO_BUFFER_TRIGGERED | INDIO_EVENT_TRIGGERED))
1520         iio_device_register_trigger_consumer(indio_dev);  //创建trigger属性节点
1521
1522     if ((indio_dev->modes & INDIO_ALL_BUFFER_MODES) &&
1523         indio_dev->setup_ops == NULL)
1524         indio_dev->setup_ops = &noop_ring_setup_ops;
1525    // 创建字符设备节点,fops操作绑定iio_buffer
1526     cdev_init(&indio_dev->chrdev, &iio_buffer_fileops);
1527     indio_dev->chrdev.owner = indio_dev->info->driver_module;
1528     indio_dev->chrdev.kobj.parent = &indio_dev->dev.kobj;
1529     ret = cdev_add(&indio_dev->chrdev, indio_dev->dev.devt, 1);
1530     if (ret < 0)
1531         goto error_unreg_eventset;
1532
1533     ret = device_add(&indio_dev->dev);
1534     if (ret < 0)
1535         goto error_cdev_del;
1536
1537     return 0;
1538 error_cdev_del:
1539     cdev_del(&indio_dev->chrdev);
1540 error_unreg_eventset:
1541     iio_device_unregister_eventset(indio_dev);
1542 error_free_sysfs:
1543     iio_device_unregister_sysfs(indio_dev);
1544 error_buffer_free_sysfs:
1545     iio_buffer_free_sysfs_and_mask(indio_dev);
1546 error_unreg_debugfs:
1547     iio_device_unregister_debugfs(indio_dev);
1548     return ret;
1549 }

iio_device_register过程中,为iio_dev创建了其所需的sysfs节点,主要包括buffer、channels、debug、event和trigger等模块的节点。我们主要分析一下buffer这个核心模块的sysfs节点和iio_buffer的创建过程,了解使能/失能 buffer/enable时iio框架究竟做了些什么。

1064 int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev)
1065 {
            ……
1090     attr = kcalloc(attrcount + ARRAY_SIZE(iio_buffer_attrs) + 1,
1091                sizeof(struct attribute *), GFP_KERNEL);
1092     if (!attr)
1093         return -ENOMEM;
1094
1095     memcpy(attr, iio_buffer_attrs, sizeof(iio_buffer_attrs));
1096     if (!buffer->access->set_length)
1097         attr[0] = &dev_attr_length_ro.attr;
1098
1099     if (buffer->access->flags & INDIO_BUFFER_FLAG_FIXED_WATERMARK)
1100         attr[2] = &dev_attr_watermark_ro.attr;
1101
1102     if (buffer->attrs)
1103         memcpy(&attr[ARRAY_SIZE(iio_buffer_attrs)], buffer->attrs,
1104                sizeof(struct attribute *) * attrcount);
1105
1106     attr[attrcount + ARRAY_SIZE(iio_buffer_attrs)] = NULL;
1107
1108     buffer->buffer_group.name = "buffer";
1109     buffer->buffer_group.attrs = attr;
            ……
1174 }

kfifo的创建/释放

buffer的enable/length/watermark是常规必备的attr,enable节点所对应的show/store方法分别对应了iio_buffer_show_enable/iio_buffer_store_enable,show方法我们无需关注,主要关注store方法:

 966 static ssize_t iio_buffer_store_enable(struct device *dev,
 967                        struct device_attribute *attr,
 968                        const char *buf,
 969                        size_t len)
 970 {
 971     int ret;
 972     bool requested_state;
 973     struct iio_dev *indio_dev = dev_to_iio_dev(dev);
 974     bool inlist;
 975
 976     ret = strtobool(buf, &requested_state);
 977     if (ret < 0)
 978         return ret;
 979
 980     mutex_lock(&indio_dev->mlock);
 981
 982     /* Find out if it is in the list */
 983     inlist = iio_buffer_is_active(indio_dev->buffer);
 984     /* Already in desired state */
 985     if (inlist == requested_state)
 986         goto done;
 987    // 当enable为1时,insert_buffer为indio_dev->buffer,表示将这个buffer插入到列表中,否则就移除它
 988     if (requested_state)
 989         ret = __iio_update_buffers(indio_dev,
 990                      indio_dev->buffer, NULL);
 991     else
 992         ret = __iio_update_buffers(indio_dev,
 993                      NULL, indio_dev->buffer);
 994
 995 done:
 996     mutex_unlock(&indio_dev->mlock);
 997     return (ret < 0) ? ret : len;
 998 }
 869 static int __iio_update_buffers(struct iio_dev *indio_dev,
 870                struct iio_buffer *insert_buffer,
 871                struct iio_buffer *remove_buffer)
 872 {
 873     struct iio_device_config new_config;
 874     int ret;
 875
 876     ret = iio_verify_update(indio_dev, insert_buffer, remove_buffer,
 877         &new_config);
 878     if (ret)
 879         return ret;
 880    // 申请创建kfifo,计算kfifo的容量与每次数据的大小
 881     if (insert_buffer) {
 882         ret = iio_buffer_request_update(indio_dev, insert_buffer);
 883         if (ret)
 884             goto err_free_config;
 885     }
 886
 887     ret = iio_disable_buffers(indio_dev);
 888     if (ret)
 889         goto err_deactivate_all;
 890    // 移除/添加buffer列表,目前看来,buffer_list只有一个buffer
 891     if (remove_buffer)
 892         iio_buffer_deactivate(remove_buffer);
 893     if (insert_buffer)
 894         iio_buffer_activate(indio_dev, insert_buffer);
 895
 896     /* If no buffers in list, we are done */
 897     if (list_empty(&indio_dev->buffer_list))
 898         return 0;
 899    // 更新 iio_buffer的配置信息。
 900     ret = iio_enable_buffers(indio_dev, &new_config);
 901     if (ret)
 902         goto err_deactivate_all;
 903
 904     return 0;

iio_buffer_request_update是创建看kfifo的重心,这里进行了两个操作:①iio_buffer_update_bytes_per_datum,计算每次数据上报的大小。②申请kfifo的空间。

 545 static int iio_compute_scan_bytes(struct iio_dev *indio_dev,
 546                 const unsigned long *mask, bool timestamp)
 547 {
 548     unsigned bytes = 0;
 549     int length, i;
 550
 551     /* How much space will the demuxed element take? */
 552     for_each_set_bit(i, mask,
 553              indio_dev->masklength) {
 554         length = iio_storage_bytes_for_si(indio_dev, i);
 555         bytes = ALIGN(bytes, length);
 556         bytes += length;
 557     }
 558
 559     if (timestamp) {
 560         length = iio_storage_bytes_for_timestamp(indio_dev);
 561         bytes = ALIGN(bytes, length);
 562         bytes += length;
 563     }
 564     return bytes;
 565 }

每次上报的数据大小并不是完全根据channels中指定的storagebits来计算,而是还是数据的对齐。ALIGN是一个宏,展开后核心如下:

(((x) + (mask)) & ~(mask))

x就是第一个参数,mask是第二个参数-1。例如一次使能了4个channels,前三个channel的storagebits为2bytes,第四个channel为4bytes。那么最后bytes的值就是12.

计算过程如下:

channel0:length = 2; bytes = (0 + 2) &(~1) + 2 = 2
channel1:length = 2; bytes = (2 + 2) & (~1) + 2 = 4
channel2:length = 2; bytes = (4 + 2) & (~1) + 2 = 6
channel3:length = 4; bytes = (6 + 4) & (~3) + 4 = 12

这个值最后被设置到iio_buffer的bytes_per_datum字段中。然后在iio_buffer的request_update操作中进行kfifo的申请。

 38 static int iio_request_update_kfifo(struct iio_buffer *r)
 39 {
 40     int ret = 0;
 41     struct iio_kfifo *buf = iio_to_kfifo(r);
 42
 43     mutex_lock(&buf->user_lock);
 44     if (buf->update_needed) {
 45         kfifo_free(&buf->kf);
 46         ret = __iio_allocate_kfifo(buf, buf->buffer.bytes_per_datum,
 47                    buf->buffer.length);
 48         if (ret >= 0)
 49             buf->update_needed = false;
 50     } else {
 51         kfifo_reset_out(&buf->kf);
 52     }
 53     mutex_unlock(&buf->user_lock);
 54
 55     return ret;
 56 }
 38 int __kfifo_alloc(struct __kfifo *fifo, unsigned int size,
 39         size_t esize, gfp_t gfp_mask)
 40 {
 41     /*
 42      * round down to the next power of 2, since our 'let the indices
 43      * wrap' technique works only in this case.
 44      */
 45     size = roundup_pow_of_two(size);
 46
 47     fifo->in = 0;
 48     fifo->out = 0;
 49     fifo->esize = esize;
 50
 51     if (size < 2) {
 52         fifo->data = NULL;
 53         fifo->mask = 0;
 54         return -EINVAL;
 55     }
 56
 57     fifo->data = kmalloc(size * esize, gfp_mask);
 58
 59     if (!fifo->data) {
 60         fifo->mask = 0;
 61         return -ENOMEM;
 62     }
 63     fifo->mask = size - 1;
 64
 65     return 0;
 66 }

kfifo的esize就是iio_buffer的bytes_per_datum。fifo的data内存大小就是iio_buffer->length * iio_buffer->bytes_per_datum.

而当enable为0时,则简单得多了,只需要释放kfifo:

 574 static void iio_buffer_deactivate(struct iio_buffer *buffer)
 575 {
 576     list_del_init(&buffer->buffer_list);
 577     wake_up_interruptible(&buffer->pollq);
 578     iio_buffer_put(buffer);
 579 }
 69 void __kfifo_free(struct __kfifo *fifo)
 70 {
 71     kfree(fifo->data);
 72     fifo->in = 0;
 73     fifo->out = 0;
 74     fifo->esize = 0;
 75     fifo->data = NULL;
 76     fifo->mask = 0;
 77 }

kfifo的in/out

前面说完kfifo的创建,而kfifo的数据写入和读取我们在inv_mpu6050驱动中再展开分析。

数据上报/读取

iio子系统框架分析_第2张图片

inv_mpu6050的trigger是通过中断来触发的。当mpu数据采集完成后,触发irq,调用iio_trigger_generic_data_rdy_poll这个中断,iio trigger触发其创建的虚拟中断来回调iio_dev的pollfunc,并进入到我们定义的pollfunc中采集数据,并通过iio_push_to_buffer接口将数据store到kfifo中。

本节的重点是iio trigger的触发过程和iio_push_to_buffer将数据store到kfifo的过程细节。

trigger的触发

trigger默认是没有打开的,trigger的使能/关闭都与buffer的使能/关闭挂钩。在iio_buffer小节中,iio_buffer的使能/失能会调用iio_enable_buffers/iio_disable_buffers去,在这两个操作中,会顺带控制了trigger的使能/关闭。

 755 static int iio_enable_buffers(struct iio_dev *indio_dev,
 756     struct iio_device_config *config)
 757 {
        ……
 801     if (indio_dev->setup_ops->postenable) {
 802         ret = indio_dev->setup_ops->postenable(indio_dev);
 803         if (ret) {
 804             dev_dbg(&indio_dev->dev,
 805                    "Buffer not started: postenable failed (%d)\n", ret);
 806             goto err_disable_buffers;
 807         }
 808     }
 826 static int iio_disable_buffers(struct iio_dev *indio_dev)
 827 { 
        ……
 857     if (indio_dev->setup_ops->postdisable) {
 858         ret2 = indio_dev->setup_ops->postdisable(indio_dev);
 859         if (ret2 && !ret)
 860             ret = ret2;
 861     }

setup_ops中默认是iio_triggered_buffer_setup_ops,这个也是mpu6050中所使用的。

 19 static const struct iio_buffer_setup_ops iio_triggered_buffer_setup_ops = {
 20     .postenable = &iio_triggered_buffer_postenable,
 21     .predisable = &iio_triggered_buffer_predisable,
 22 };
245 static int iio_trigger_attach_poll_func(struct iio_trigger *trig,
246                     struct iio_poll_func *pf)
247 {
248     int ret = 0;
249     bool notinuse
250         = bitmap_empty(trig->pool, CONFIG_IIO_CONSUMERS_PER_TRIGGER);
251
252     /* Prevent the module from being removed whilst attached to a trigger */
253     __module_get(pf->indio_dev->info->driver_module);
254
255     /* Get irq number */
256     pf->irq = iio_trigger_get_irq(trig);
257     if (pf->irq < 0)
258         goto out_put_module;
259
260     /* Request irq */
261     ret = request_threaded_irq(pf->irq, pf->h, pf->thread,
262                    pf->type, pf->name,
263                    pf);
264     if (ret < 0)
265         goto out_put_irq;
266
267     /* Enable trigger in driver */
268     if (trig->ops->set_trigger_state && notinuse) {
269         ret = trig->ops->set_trigger_state(trig, true);
270         if (ret < 0)
271             goto out_free_irq;
272     }

iio_trigger_get_irq返回trigger所使用的虚拟中断号,调用request_threaded_irq向系统注册这个虚拟中断,pf就是probe中的inv_mpu6050_irq_handler/inv_mpu6050_read_fifo.

predisable则更简单,直接free_irq。

虚拟中断已经创建好,那么剩下的就是软件触发,而iio_trigger_poll就是触发这个中断的接口。

166 void iio_trigger_poll(struct iio_trigger *trig)
167 {
168     int i;
169
170     if (!atomic_read(&trig->use_count)) {
171         atomic_set(&trig->use_count, CONFIG_IIO_CONSUMERS_PER_TRIGGER);
172
173         for (i = 0; i < CONFIG_IIO_CONSUMERS_PER_TRIGGER; i++) {
174             if (trig->subirqs[i].enabled)
175                 generic_handle_irq(trig->subirq_base + i);
176             else
177                 iio_trigger_notify_done(trig);
178         }
179     }
180 }

generic_handle_irq是irq子系统的接口,在这里不再展开。此时就可以回调到我们设备驱动中的回调。

iio_push_to_buffer

iio_push_to_buffer是往kfifo写入数据:

1245 static int iio_push_to_buffer(struct iio_buffer *buffer, const void *data)
1246 {
1247     const void *dataout = iio_demux(buffer, data);
1248     int ret;
1249
1250     ret = buffer->access->store_to(buffer, dataout);
1251     if (ret)
1252         return ret;
1253
1254     /*
1255      * We can't just test for watermark to decide if we wake the poll queue
1256      * because read may request less samples than the watermark.
1257      */
1258     wake_up_interruptible_poll(&buffer->pollq, POLLIN | POLLRDNORM);
1259     return 0;
1260 }

store_to是kfifo的iio_store_to_kfifo:

 86 static int iio_store_to_kfifo(struct iio_buffer *r,
 87                   const void *data)
 88 {
 89     int ret;
 90     struct iio_kfifo *kf = iio_to_kfifo(r);
 91     ret = kfifo_in(&kf->kf, data, 1);
 92     if (ret != 1)
 93         return -EBUSY;
 94     return 0;
 95 }
126 unsigned int __kfifo_in(struct __kfifo *fifo,
127         const void *buf, unsigned int len)
128 {
129     unsigned int l;
130
131     l = kfifo_unused(fifo);
132     if (len > l)
133         len = l;
134
135     kfifo_copy_in(fifo, buf, len, fifo->in);
136     fifo->in += len;
137     return len;
138 }
102 static void kfifo_copy_in(struct __kfifo *fifo, const void *src,
103         unsigned int len, unsigned int off)
104 {
105     unsigned int size = fifo->mask + 1;
106     unsigned int esize = fifo->esize;
107     unsigned int l;
108
109     off &= fifo->mask;
110     if (esize != 1) {
111         off *= esize;
112         size *= esize;
113         len *= esize;
114     }
115     l = min(len, size - off);
116
117     memcpy(fifo->data + off, src, l);
118     memcpy(fifo->data, src + l, len - l);
119     /*
120      * make sure that the data in the fifo is up to date before
121      * incrementing the fifo->in index counter
122      */
123     smp_wmb();
124 }

kfifo_copy_in每次copy的字节数是esize,因此iio_push_to_buffer接口参数并没有传入大小,只传入了指针,因为每次store_to都是固定的大小,因此data所指向的数据必须不能小于esize的大小,esize就是前面kfifo的创建中根据channel的storagebits的大小并对齐后的大小。

store_to之后就是唤醒poll的等待.

数据读取

这里的数据读取是指通过chrdev节点读取的方式。在前面iio_device_register方法中可以看到,chrdev的fops是iio_buffer_fileops,里面提供了read和poll的接口方法。我们这里只看一下read接口:

 105 ssize_t iio_buffer_read_first_n_outer(struct file *filp, char __user *buf,
 106                       size_t n, loff_t *f_ps)
 107 {
 108     struct iio_dev *indio_dev = filp->private_data;
 109     struct iio_buffer *rb = indio_dev->buffer;
 110     DEFINE_WAIT_FUNC(wait, woken_wake_function);
 111     size_t datum_size;
 112     size_t to_wait;
 113     int ret = 0;
 114
 115     if (!indio_dev->info)
 116         return -ENODEV;
 117
 118     if (!rb || !rb->access->read_first_n)
 119         return -EINVAL;
 120
 121     datum_size = rb->bytes_per_datum;
 122
 123     /*
 124      * If datum_size is 0 there will never be anything to read from the
 125      * buffer, so signal end of file now.
 126      */
 127     if (!datum_size)
 128         return 0;
 129
 130     if (filp->f_flags & O_NONBLOCK)
 131         to_wait = 0;
 132     else
 133         to_wait = min_t(size_t, n / datum_size, rb->watermark);
 134
 135     add_wait_queue(&rb->pollq, &wait);
 136     do {
 137         if (!indio_dev->info) {
 138             ret = -ENODEV;
 139             break;
 140         }
 141
 142         if (!iio_buffer_ready(indio_dev, rb, to_wait, n / datum_size)) {
 143             if (signal_pending(current)) {
 144                 ret = -ERESTARTSYS;
 145                 break;
 146             }
 147
 148             wait_woken(&wait, TASK_INTERRUPTIBLE,
 149                    MAX_SCHEDULE_TIMEOUT);
 150             continue;
 151         }
 152
 153         ret = rb->access->read_first_n(rb, n, buf);
 154         if (ret == 0 && (filp->f_flags & O_NONBLOCK))
 155             ret = -EAGAIN;
 156     } while (ret == 0);
 157     remove_wait_queue(&rb->pollq, &wait);
 158
 159     return ret;
 160 }

如果open是传入的参数是O_NONBLOCK,则不用等待,否则会根据read的size/bytes_per_datum和watermark的最小值来判断返回时机。当有足够数据足以返回时,则调用kfifo的read_first_n接口取读取数据:

 97 static int iio_read_first_n_kfifo(struct iio_buffer *r,
 98                size_t n, char __user *buf)
 99 {
100     int ret, copied;
101     struct iio_kfifo *kf = iio_to_kfifo(r);
102
103     if (mutex_lock_interruptible(&kf->user_lock))
104         return -ERESTARTSYS;
105
106     if (!kfifo_initialized(&kf->kf) || n < kfifo_esize(&kf->kf))
107         ret = -EINVAL;
108     else
109         ret = kfifo_to_user(&kf->kf, buf, n, &copied);
110     mutex_unlock(&kf->user_lock);
111     if (ret < 0)
112         return ret;
113
114     return copied;
115 }

这里要注意一点,当read的size小于esize,那么read就会被返回-EINVAL,由于iio认为每次读取数据都必须大于一个完整的数据。

283 int __kfifo_to_user(struct __kfifo *fifo, void __user *to,
284         unsigned long len, unsigned int *copied)
285 {
286     unsigned int l;
287     unsigned long ret;
288     unsigned int esize = fifo->esize;
289     int err;
290
291     if (esize != 1)
292         len /= esize;
293
294     l = fifo->in - fifo->out;
295     if (len > l)
296         len = l;
297     ret = kfifo_copy_to_user(fifo, to, len, fifo->out, copied);
298     if (unlikely(ret)) {
299         len -= ret;
300         err = -EFAULT;
301     } else
302         err = 0;
303     fifo->out += len;
304     return err;
305 }
249 static unsigned long kfifo_copy_to_user(struct __kfifo *fifo, void __user *to,
250         unsigned int len, unsigned int off, unsigned int *copied)
251 {
252     unsigned int l;
253     unsigned long ret;
254     unsigned int size = fifo->mask + 1;
255     unsigned int esize = fifo->esize;
256
257     off &= fifo->mask;
258     if (esize != 1) {
259         off *= esize;
260         size *= esize;
261         len *= esize;
262     }
263     l = min(len, size - off);
264
265     ret = copy_to_user(to, fifo->data + off, l);
266     if (unlikely(ret))
267         ret = DIV_ROUND_UP(ret + len - l, esize);
268     else {
269         ret = copy_to_user(to + l, fifo->data, len - l);
270         if (unlikely(ret))
271             ret = DIV_ROUND_UP(ret, esize);
272     }
273     /*
274      * make sure that the data is copied before
275      * incrementing the fifo->out index counter
276      */
277     smp_wmb();
278     *copied = len - ret * esize;
279     /* return the number of elements which are not copied */
280     return ret;
281 }

就这样,用户空间就可以完成数据的读取。

iio子系统用户空间

iio子系统提供了很多的sysfs节点供用户去配置/操作iio设备。操作iio设备主要关注一个目录和一个节点:

目录就是/sys/bus/iio/devices/iio:deviceX,这个是iio的sysfs节点所在的目录,节点就是/dev/iio:deviceX,这个是iio字符设备驱动节点。

一般操作步骤:

1.或者iio设备驱动的信息,如channel的index、type(数据的类型/大小/偏移等信息),这部分在scan_elements子目录下;in_xxxx_scale信息,各个设备的scale信息,这个关乎数据计算;sampling_frequency,这个名字不固定,一般都会提供一个设置频率的节点。

1.设置channel使能,节点名一般是in_xxxx_x_en,在scan_elements子目录下。

2.设置频率。

3.使能buffer,节点在buffer/enable下,也可以设置buffer的length和watermark,但一般无需设置。

4.读取/dev/iio:deviceX节点,如cat /dev/iio:device0 | xxd -c 2

5.根据channel信息来获取数据,并根据scale来换算单位。

iio还提供单独单次获取一个channel的数据,如in_xxxx_x_raw节点,cat这个节点即可获取这个channel的数据。

另外,iio为了数据的安全,所有的设置都必须在buffer/enable为0的状态下进行设置。

你可能感兴趣的:(驱动,linux)