led系统trigger下的pattern模式

客户需求亮屏灯常亮,休眠灯闪烁,默认的指示灯使用的pattern模式,把相关的代码捋一捋。

展讯平台打开呼吸灯的方式

cd /sys/class/leds/sc27xx:blue/
echo pattern > trigger
echo 50 255 875 255 75 255 1000 255 > hw_pattern

把pattern模式注册到trigger_list

static struct attribute *pattern_trig_attrs[] = {
	&dev_attr_pattern.attr,
	&dev_attr_hw_pattern.attr,
	&dev_attr_repeat.attr,
	NULL
};

static const struct attribute_group pattern_trig_group = {
	.attrs = pattern_trig_attrs,
	.is_visible = pattern_trig_attrs_mode,
};

static const struct attribute_group *pattern_trig_groups[] = {
	&pattern_trig_group,
	NULL,
};
extern struct list_head trigger_list;
static struct led_trigger pattern_led_trigger = {
	.name = "pattern",
	.activate = pattern_trig_activate,
	.deactivate = pattern_trig_deactivate,
	.groups = pattern_trig_groups,
};

static int __init pattern_trig_init(void)
{
	return led_trigger_register(&pattern_led_trigger);
}

int led_trigger_register(struct led_trigger *trig)
{
	...
	list_add_tail(&trig->next_trig, &trigger_list);
	...
}

echo pattern>trigger 选中pattern模式

ssize_t led_trigger_store(struct device *dev, struct device_attribute *attr,
		const char *buf, size_t count)
{
	struct led_classdev *led_cdev = dev_get_drvdata(dev);
	struct led_trigger *trig;
	int ret = count;

	list_for_each_entry(trig, &trigger_list, next_trig) {
		if (sysfs_streq(buf, trig->name)) {
			led_trigger_set(led_cdev, trig);
		}
	}
}
EXPORT_SYMBOL_GPL(led_trigger_store);
int led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trig)
{
	...
	if (trig) {
		list_add_tail(&led_cdev->trig_list, &trig->led_cdevs);
		led_cdev->trigger = trig;

		if (trig->activate)
			ret = trig->activate(led_cdev);
		ret = device_add_groups(led_cdev->dev, trig->groups);
		if (ret) {
			dev_err(led_cdev->dev, "Failed to add trigger attributes\n");
			goto err_add_groups;
		}
	}
	...
}

device_add_groups生成pattern/pattern_hw/repeat节点 

static int pattern_trig_activate(struct led_classdev *led_cdev)
{
	struct pattern_trig_data *data;

	data = kzalloc(sizeof(*data), GFP_KERNEL);
	if (!data)
		return -ENOMEM;

	data->is_indefinite = true;
	data->last_repeat = -1;
	data->led_cdev = led_cdev;
	led_set_trigger_data(led_cdev, data);
	timer_setup(&data->timer, pattern_trig_timer_function, 0);
	led_cdev->activated = true;

	return 0;
}
static ssize_t hw_pattern_store(struct device *dev,struct device_attribute *attr,const char *buf, size_t count)
{
	struct led_classdev *led_cdev = dev_get_drvdata(dev);
	return pattern_trig_store_patterns(led_cdev, buf, count, true);
}

static ssize_t pattern_trig_store_patterns(struct led_classdev *led_cdev,const char *buf, size_t count, bool hw_pattern)
{
	struct pattern_trig_data *data = led_cdev->trigger_data;
	while (offset < count - 1 && data->npatterns < MAX_PATTERNS) {
		cr = 0;
		ccount = sscanf(buf + offset, "%d %u %n",&data->patterns[data->npatterns].brightness,&data->patterns[data->npatterns].delta_t, &cr);
		if (ccount != 2) {
			data->npatterns = 0;
			err = -EINVAL;
			goto out;
		}

		offset += cr;
		data->npatterns++;
	}

	err = pattern_trig_start_pattern(led_cdev);
	if (err)
		data->npatterns = 0;
}

static int pattern_trig_start_pattern(struct led_classdev *led_cdev)
{
	struct pattern_trig_data *data = led_cdev->trigger_data;

	if (data->is_hw_pattern) {
		return led_cdev->pattern_set(led_cdev, data->patterns,
					     data->npatterns, data->repeat);
	}

}

把数据写到led_cdev->pattern_set(平台的控制器已实现),如

static int sc27xx_led_pattern_set(struct led_classdev *ldev,
				  struct led_pattern *pattern,
				  u32 len, int repeat)
{
	struct sc27xx_led *leds = to_sc27xx_led(ldev);
	u32 base = sc27xx_led_get_offset(leds);
	u32 ctrl_base = leds->priv->base + SC27XX_LEDS_CTRL;
	u8 ctrl_shift = SC27XX_CTRL_SHIFT * leds->line;
	struct regmap *regmap = leds->priv->regmap;
	int err;

	/*
	 * Must contain 4 tuples to configure the rise time, high time, fall
	 * time and low time to enable the breathing mode.
	 */
	if (len != SC27XX_LEDS_PATTERN_CNT)
		return -EINVAL;

	mutex_lock(&leds->priv->lock);

	sc27xx_led_clamp_align_delta_t(&pattern[0].delta_t);
	err = regmap_update_bits(regmap, base + SC27XX_LEDS_CURVE0,
				 SC27XX_CURVE_L_MASK,
				 pattern[0].delta_t / SC27XX_LEDS_STEP);
	if (err)
		goto out;

	sc27xx_led_clamp_align_delta_t(&pattern[1].delta_t);
	err = regmap_update_bits(regmap, base + SC27XX_LEDS_CURVE1,
				 SC27XX_CURVE_L_MASK,
				 pattern[1].delta_t / SC27XX_LEDS_STEP);
	if (err)
		goto out;

	sc27xx_led_clamp_align_delta_t(&pattern[2].delta_t);
	err = regmap_update_bits(regmap, base + SC27XX_LEDS_CURVE0,
				 SC27XX_CURVE_H_MASK,
				 (pattern[2].delta_t / SC27XX_LEDS_STEP) <<
				 SC27XX_CURVE_SHIFT);
	if (err)
		goto out;

	sc27xx_led_clamp_align_delta_t(&pattern[3].delta_t);
	err = regmap_update_bits(regmap, base + SC27XX_LEDS_CURVE1,
				 SC27XX_CURVE_H_MASK,
				 (pattern[3].delta_t / SC27XX_LEDS_STEP) <<
				 SC27XX_CURVE_SHIFT);
	if (err)
		goto out;

	err = regmap_update_bits(regmap, base + SC27XX_LEDS_DUTY,
				 SC27XX_DUTY_MASK,
				 (pattern[1].brightness << SC27XX_DUTY_SHIFT) |
				 SC27XX_MOD_MASK);
	if (err)
		goto out;

	/* Enable the LED breathing mode */
	err = regmap_update_bits(regmap, ctrl_base,
				 SC27XX_LED_RUN << ctrl_shift,
				 SC27XX_LED_RUN << ctrl_shift);
	if (!err)
		ldev->brightness = pattern[1].brightness;

out:
	mutex_unlock(&leds->priv->lock);

	return err;
}

 

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值