Re: [PATCH 17/17] staging: nuc-led: update the TODOs

Mauro Carvalho Chehab
2021-05-17T08:57:55Z

Em Mon, 17 May 2021 10:05:27 +0200
Pavel Machek <pavel@ucw.cz> escreveu:

> Hi!
>
> > > > - Need to validate the uAPI and document it before moving
> > > > this driver out of staging.
> > >
> > > > - Stabilize and document its sysfs interface.
> > >
> > > Would you mind starting with this one?
> >
> > Do you mean writing the ABI document for it? Surely I can do that,
> > but I'm not sure where to put such document while it is on staging.
>
> No need for formal ABI just yet, but it needs to be clear what the interface
> is.
>
> > > We should have existing APIs
> > > for most of functionality described...
> >
> > I tried to stay as close as possible to the existing API, but
> > there are some things that required a different one.
>
> I believe it should be possible to move _way_ closer to existing APIs.
>
> > For instance, with WMI rev 0.64 and 1.0, any LED of the device
> > can be programmed to be a power indicator.
> >
> > When a LED is programmed this way, there are up to 3 (on rev 1.0) or up
> > to 4 (on rev 0.64) different brightness level of the LED, and those
> > are associated with a power status (like S0, S3, S5, "ready mode").
>
> I'll need a description how this works.
>
> > /sys/class/leds/nuc::front1/
> > ├── blink_behavior
> > ├── blink_frequency
>
> We have timer trigger for these.

Not really. The LED blink behavior is provided by the hardware itself.

The LEDs can blink *even* when the device is suspended or is
hibernating. That's something that a timer trigger can't do ;-)

See below for a draft of the ABI description.

>
> > ├── ethernet_type
> > ├── hdd_default
> > ├── indicator
> > ├── ready_mode_blink_behavior
> > ├── ready_mode_blink_frequency
> > ├── ready_mode_brightness
> > ├── s0_blink_behavior
> > ├── s0_blink_frequency
> > ├── s0_brightness
> > ├── s3_blink_behavior
> > ├── s3_blink_frequency
> > ├── s3_brightness
> > ├── s5_blink_behavior
> > ├── s5_blink_frequency
> > ├── s5_brightness
>
> No. Take a look at triggers; for example hdd monitor should look very
> much like existing disk trigger.

Ok, I'll double-check how this works. Yeah, it would be a way better if
the sysfs nodes could be hidden when changing the indicator type.

For instance, when monitoring disk activity, only those parameters
may be available:

================================= =======================================
Parameter Meaning
================================= =======================================
brightness Brightness in percent (from 0 to 100)
color LED color.
See :ref:`nuc_color`.
hdd_default Default is LED turned ON or OFF.
When set toOFF, the LED will turn on
at disk activity.
When set to ON, the LED will be turned
on by default, turning off at disk
activity.
================================= =======================================

(color is only available for multi-colored or RGB leds).

>
> > On other words, the "indicator" tells what type of hardware event
> > the LED is currently measuring:
> >
> > $ cat /sys/class/leds/nuc\:\:front1/indicator
> > Power State [HDD Activity] Ethernet WiFi Software Power Limit Disable
>
> So this will use existing "trigger" infrastructure.

Ok, I will take a look on that. Are there any driver that I could use
as an example, using it in a configurable way?

> > That should likely be easier to discuss if any changes at the
> > ABI would be needed. Before moving it out of staging, I would
> > add another one under Documentation/ABI describing the meaning
> > of each sysfs node.
>
> Lets get reasonable ABI before moving it _into_ tree, staging or
> otherwise.

I'm enclosing a document that I started to write today, describing the
way the current ABI was designed. The document doesn't describe in
full the NUC6 variant (which is really limited: just two LEDs
with fixed behavior).

Thanks,
Mauro

==================
Intel NUC WMI LEDs
==================

Some models of the Intel Next Unit of Computing (NUC) may have programmable
LEDs on its panel via its BIOS. A subset of those may also be programmed on
user space.

There are currently three different APIs on such devices, depending on the
NUC generation:

* NUC 6/7:
https://www.intel.com/content/www/us/en/support/articles/000023426/intel-nuc/intel-nuc-kits.html
* NUC 8/9:
https://raw.githubusercontent.com/nomego/intel_nuc_led/master/specs/INTEL_WMI_LED_0.64.pdf
* NUC 10 and newer:
https://www.intel.com/content/dam/support/us/en/documents/intel-nuc/WMI-Spec-Intel-NUC-NUC10ixFNx.pdf

This document describes how to use the LEDs API, as supported by the "nuc-wmi"
driver.

Please notice that the LEDs can only be programmed if the BIOS settings
are allowing the Operational System to control them. Instructions about
how to enable it can be found at the manual of each specific NUC, if
the LEDs are userspace programmed for an specific device.

LED devices
===========

When the driver detects NUC LEDs, some sysfs device nodes are created under
the leds class.

On NUC 6, there are (up to) two LEDs available:

============= ==============================
LED name sysfs device node
============= ==============================
Power ``/sys/class/leds/nuc::power``
Ring ``/sys/class/leds/nuc::ring``
============= ==============================

The NUC 6 API is limited, as it allows only to change the LED color, and
its blink state. Its API will be described on :ref:`NUC6 API`.

On NUC 8 and newer generations, up to seven LEDs are supported:

============= ===============================
LED name sysfs device node
============= ===============================
Skull ``/sys/class/leds/nuc::skull``
Skull eyes ``/sys/class/leds/nuc::eyes``
Power ``/sys/class/leds/nuc::power``
HDD ``/sys/class/leds/nuc::hdd``
Front1 ``/sys/class/leds/nuc::front1``
Front2 ``/sys/class/leds/nuc::front2``
Front3 ``/sys/class/leds/nuc::front3``
============= ===============================

The API for NUC 8 and newer allows full control of the LEDs meaning.

NUC 6 API
=========

TODO: describe the limited NUC6 API

NUC 8 and newer generations API
===============================

On NUC8, and newer, several sysfs nodes will allow to control the
functionality of each LED::

/sys/class/leds/nuc::front1
|-- blink_behavior
|-- blink_frequency
|-- brightness
|-- color
|-- ethernet_type
|-- hdd_default
|-- indicator
|-- max_brightness
|-- power_limit_scheme
|-- ready_mode_blink_behavior
|-- ready_mode_blink_frequency
|-- ready_mode_brightness
|-- s0_blink_behavior
|-- s0_blink_frequency
|-- s0_brightness
|-- s3_blink_behavior
|-- s3_blink_frequency
|-- s3_brightness
|-- s5_blink_behavior
|-- s5_blink_frequency
`-- s5_brightness

The sessions below will explain the meaning of each aspect of the API.

.. note::

For the entire NUC8+ API, the following rules apply:

1. any user can read the LEDs parameter;
2. changing a LED parameter is limited to the owner of the sysfs device
nodes (usually, the ``root`` user);
3. changing a LED parameter is case-insensitive;
4. The LED ``indicator`` parameter controls the function of the LED.
All other parameters can be enabled or disabled in runtime, depending
on it. When a certain parameter is disabled, an error code will be
returned.

LED indicator
-------------

Despite the LED's name, the LED API may allow them to indicate different
hardware events.

This is controlled via the ``indicator`` device node. Reading from it displays
all the supported events for a giving LED, and the currently ative one::

$ cat /sys/class/leds/nuc::front1/indicator
Power State [HDD Activity] Ethernet WiFi Software Power Limit Disable

Each LED may support the following indicator types:

============== =======================================================
Indicator type Meaning
============== =======================================================
Power State Shows if the device is powered and what power level
it is (e. g. if the device is suspended or not, and
on which kind of suspended level).
HDD Activity Indicates if the LED is measuring the hard disk (or
SDD) activity.
Ethernet Indicates the activity Ethernet adapter(s)
WiFi Indicates if WiFi is enabled
Software Doesn't indicate any hardware level. Instead, the LED
status is controlled via software.
Power Limit Changes the LED color when the computer is throttling
its power limits.
Disable The LED was disabled.
============== =======================================================

In order to change the type of indicator, you should
just write a new value to the indicator type::

# echo "wifi" > /sys/class/leds/nuc::front1/indicator

$ cat /sys/class/leds/nuc::front1/indicator
Power State HDD Activity Ethernet [WiFi] Software Power Limit Disable

Power State parameters
----------------------

When the LED indicator is measuring *Power State*, the following parameters
may be available:

================================= =======================================
Parameter Meaning
================================= =======================================
<power_state>_brightness Brightness in percent (from 0 to 100)
<power_state>_blink_behavior type of blink.
See :ref:`nuc_blink_behavior`.
<power_state>_blink_frequency Blink frequency.
See :ref:`nuc_blink_behavior`.
<power_state>_color LED color
See :ref:`nuc_color`.
================================= =======================================

Where <power_state> can be:

On NUC8/9 API:

+------------+
| S0 |
+------------+
| S3 |
+------------+
| S5 |
+------------+
| Ready mode |
+------------+

On NUC10 API:

+------------+
| S0 |
+------------+
| S3 |
+------------+
| Standby |
+------------+

HDD Activity parameters
-----------------------

When the LED indicator is measuring *HDD Activity*, the following parameters
may be available:

================================= =======================================
Parameter Meaning
================================= =======================================
brightness Brightness in percent (from 0 to 100)
color LED color.
See :ref:`nuc_color`.
hdd_default Default is LED turned ON or OFF.
When set toOFF, the LED will turn on
at disk activity.
When set to ON, the LED will be turned
on by default, turning off at disk
activity.
================================= =======================================

Ethernet parameters
-------------------

When the LED indicator is measuring *Ethernet*, the following parameters
may be available:

================================= =======================================
Parameter Meaning
================================= =======================================
brightness Brightness in percent (from 0 to 100)
color LED color.
See :ref:`nuc_color`.
ethernet_type What Ethernet interface is monitored.
Can be:
LAN1, LAN2 or LAN1+LAN2.
================================= =======================================

Power limit parameters
----------------------

When the LED indicator is measuring *Power limit*, the following parameters
may be available:

================================= =======================================
Parameter Meaning
================================= =======================================
brightness Brightness in percent (from 0 to 100)
color LED color.
See :ref:`nuc_color`.
power_limit_scheme Indication scheme can be either:
- green to red
- single color
================================= =======================================

.. nuc_color::

NUC LED colors
==============

The NUC LED API may support 3 types of LEDs:

- Mono-colored LEDs;
- Dual-colored LEDs;
- multi-colored LEDs (only on NUC6/7);
- RGB LEDs.

Also, when a let is set to be a *Power limit* indicator, despite the
physical device's LED color, the API may limit it to be a led that
can display only green and red, or just a single color.

The ``color`` and ``<power_state>_color`` parameter supports all those
different settings.

NUC6/7
------

On NUC6 API, the power LED color can be:

+---------+
| disable |
+---------+
| blue |
+---------+
| amber |
+---------+

And the ring LED color can be:

+---------+
| disable |
+---------+
| cyan |
+---------+
| pink |
+---------+
| yellow |
+---------+
| blue |
+---------+
| red |
+---------+
| green |
+---------+
| white |
+---------+

NUC 8 and newer generations
---------------------------

On NUC10 API, the color can be:

============ ====== ===== =====
Color name Red Green Blue
============ ====== ===== =====
blue 0 0 255
amber 255 191 0
white 255 255 255
red 255 0 0
green 0 255 0
yellow 255 255 0
cyan 0 255 255
magenta 255 0 255
<r>,<g>, <r> <g>
============ ====== ===== =====

The color parameter will refuse to set a LED on a color that it is not
supported by the hardware or when the setting is incompatible with the
indicator type. So, when the indicator is set to *Power limit*, and
the ``power_limit_scheme`` is set to ``green to red``, it doesn't
let to set the LED's color.

On the other hand, the behavior is identical if a color is written using
the color's name or its RGB value.

So::

$ cat /sys/class/leds/nuc::front1/color
red
# echo "green" > /sys/class/leds/nuc::front1/color
$ cat /sys/class/leds/nuc::front1/color
green
# echo "255,0,0" > /sys/class/leds/nuc::front1/color
$ cat /sys/class/leds/nuc::front1/color
red

.. nuc_blink_behavior::

NUC Blink behavior
==================

The NUC LEDs hardware supports the following types of blink behavior:

+------------+
| Solid |
+------------+
| Breathing |
+------------+
| Pulsing |
+------------+
| Strobing |
+------------+

Changing the blink behavior will change how the led will be turning
on and off when blinking. Setting it to ``Solid`` disables blinking.

Please notice that not all types of indicator supports blinking.

When blinking, the blink frequency can be changed via ``blink_frequency``
or ``<power_state>_blink_frequency``, depending on the indicator.

Setting it allows to change the blink frequency in Hz, ranging from 0.1 Hz
to 1.0 Hz.