00-Linux leds子系统分析

1.简介

Linux版本:linux-4.15

leds子系统主要是通过 /sys/class/leds/ 下面文件给用户空间提供功能:打开关闭LED,使LED闪烁,利用系统事件使LED亮灭

对应的文件节点是:brightness blink trigger

涉及主要文件在drivers/leds/的 led-class.c led-core.c 数据结构头文件:include/linux/leds.h

2.注册一个LED设备流程

int devm_of_led_classdev_register(struct device *parent,
                  struct device_node *np,
                  struct led_classdev *led_cdev)

其中重要的是led_cdev这个参数,这个参数我们传入了这个LED设备设置brightness和blink的方法和其它的一下属性。

struct led_classdev 结构如下:

struct led_classdev {
	const char		*name;
	enum led_brightness	 brightness;
	enum led_brightness	 max_brightness;
	int			 flags;
	unsigned long		work_flags;

	/* Set LED brightness level
	 * Must not sleep. Use brightness_set_blocking for drivers
	 * that can sleep while setting brightness.
	 */
	void		(*brightness_set)(struct led_classdev *led_cdev,
					  enum led_brightness brightness);
	/*
	 * Set LED brightness level immediately - it can block the caller for
	 * the time required for accessing a LED device register.
	 */
	int (*brightness_set_blocking)(struct led_classdev *led_cdev,
				       enum led_brightness brightness);
	/* Get LED brightness level */
	enum led_brightness (*brightness_get)(struct led_classdev *led_cdev);

	/*
	 * Activate hardware accelerated blink, delays are in milliseconds
	 * and if both are zero then a sensible default should be chosen.
	 * The call should adjust the timings in that case and if it can't
	 * match the values specified exactly.
	 * Deactivate blinking again when the brightness is set to LED_OFF
	 * via the brightness_set() callback.
	 */
	int		(*blink_set)(struct led_classdev *led_cdev,
				     unsigned long *delay_on,
				     unsigned long *delay_off);

	struct device		*dev;
	const struct attribute_group	**groups;

	struct list_head	 node;			/* LED Device list */
	const char		*default_trigger;	/* Trigger to use */

	unsigned long		 blink_delay_on, blink_delay_off;
	struct timer_list	 blink_timer;
	int			 blink_brightness;
	int			 new_blink_brightness;
	void			(*flash_resume)(struct led_classdev *led_cdev);

	struct work_struct	set_brightness_work;
	int			delayed_set_value;

#ifdef CONFIG_LEDS_TRIGGERS
	/* Protects the trigger data below */
	struct rw_semaphore	 trigger_lock;

	struct led_trigger	*trigger;
	struct list_head	 trig_list;
	void			*trigger_data;
	/* true if activated - deactivate routine uses it to do cleanup */
	bool			activated;
#endif

#ifdef CONFIG_LEDS_BRIGHTNESS_HW_CHANGED
	int			 brightness_hw_changed;
	struct kernfs_node	*brightness_hw_changed_kn;
#endif

	/* Ensures consistent access to the LED Flash Class device */
	struct mutex		led_access;
};

其中设置亮度:     brightness_set(struct led_classdev *led_cdev, enum led_brightness brightness);这个函数不能睡眠。

brightness_set_blocking这个版本的函数可以睡眠。

闪烁功能是.blink_set函数实现的

3. leds核心层实现细节

在led-class.c文件中,开机时调用了leds_init函数。这个函数 

static int __init leds_init(void)
{
	leds_class = class_create(THIS_MODULE, "leds");
	if (IS_ERR(leds_class))
		return PTR_ERR(leds_class);
	leds_class->pm = &leds_class_dev_pm_ops;
	leds_class->dev_groups = led_groups;
	return 0;
}

这个函数通过class_create注册了leds这个class,所以我们在/sys/class下面能看见leds这个目录。这里有个class : leds_class

当我们通过前面注册驱动时会通过它关联到我们注册的class

 leds_class->dev_groups = led_groups;这句话将我们leds下面的文件操作关联起来了。其中就有brightness_show,brightness_store通过他们可以查看和设置亮度,同理还有blink节点。

你可能感兴趣的:(Linux,leds)