AW: Setting multi-color intensities stops software blink

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Sven,

> -----Ursprüngliche Nachricht-----
> Von: Sven Schwermer <sven@xxxxxxxxxxxxxxxx>
> Gesendet: Dienstag, 3. Mai 2022 14:17
> An: linux-leds@xxxxxxxxxxxxxxx
> Cc: pavel@xxxxxx
> Betreff: Setting multi-color intensities stops software blink
> 
> Hi,
> 
> I'm experiencing an issue with multi-color LEDs when setting the
> intensities while software blinking is active (e.g. trigger=timer). This
> manifests itself by delay_on and delay_off being set to 0 when writing
> multi_intensities while the LED is off. If doing this while the LED is
> on, everything works as expected.

At least I can see the same thing. Setup a led like this:
echo 255 0 0 | sudo tee /sys/class/leds/rgb\:fbx-led-1/multi_intensity
echo 100 | sudo tee /sys/class/leds/rgb\:fbx-led-1/brightness
echo "timer" | sudo tee /sys/class/leds/rgb\:fbx-led-1/trigger
echo 5000 | sudo tee /sys/class/leds/rgb\:fbx-led-1/delay_on
echo 5000 | sudo tee /sys/class/leds/rgb\:fbx-led-1/delay_off

Change the color afterwards while the LED is in the "on" cycle
echo 0 255 0 | sudo tee /sys/class/leds/rgb\:fbx-led-1/multi_intensity
no problem, on the next "on" cycle the led has the new intensity

Change the color afterwards while the LED is in the "off" cycle
echo 0 255 0 | sudo tee /sys/class/leds/rgb\:fbx-led-1/multi_intensity
the led stays off because delay_on and delay_off is 0.

This also looks like incorrect behavior to me.

> I suspect that this happens because multi_intensity_store() calls
> led_set_brightness(led_cdev, led_cdev->brightness) at the end. It seems
> like the software blinking modifies led_cdev->brightness directly, so if
> the LED is in its off-phase, we're effectively switching the LED off
> because we're setting its brightness to 0 which clears delay_on and
> delay_off to 0:
> 
> led_set_brightness(brightness=0): sets LED_BLINK_DISABLE
>   -> set_brightness_delayed()
>    -> led_stop_software_blink(): clears blink delays
> 
> How would one fix this properly? Should multi_intensity_store() call
> led_set_brightness() with brightness=led_cdev->blink_brightness if
> blinking is active? That feels like an unclean solution.
> 
> I'm hoping for some input. Thanks :)

To me this looks wrong:

void led_set_brightness(struct led_classdev *led_cdev, unsigned int brightness)
{
	/*
	 * If software blink is active, delay brightness setting
	 * until the next timer tick.
	 */
	if (test_bit(LED_BLINK_SW, &led_cdev->work_flags)) {
		/*
		 * If we need to disable soft blinking delegate this to the
		 * work queue task to avoid problems in case we are called
		 * from hard irq context.
		 */
		if (!brightness) {
			set_bit(LED_BLINK_DISABLE, &led_cdev->work_flags);

I think it is wrong to ask for the brightness over here when we know
that the led is blinking and could be currently in it's off cycle.

			schedule_work(&led_cdev->set_brightness_work);
		} else {
			set_bit(LED_BLINK_BRIGHTNESS_CHANGE,
				&led_cdev->work_flags);
			led_cdev->new_blink_brightness = brightness;

I think the else path could always be done regardless of the brightness?

		}
		return;
	}


Regards,

   Sven





[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux OMAP]     [Linux MIPS]     [ECOS]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux