Re: [PATCH] hwmon: (aquacomputer_d5next) Add support for reading calculated Aquaero sensors

From: Guenter Roeck
Date: Tue Jan 03 2023 - 16:22:25 EST


On Sun, Jan 01, 2023 at 08:00:56PM +0100, Aleksa Savic wrote:
> Add support for reading four calculated virtual temp sensors on the
> Aquacomputer Aquaero. Values of these sensors are calculated on the
> device itself based on what the user configured in the official software.
> Configuring these sensors is not currently reverse engineered.
>
> Signed-off-by: Aleksa Savic <savicaleksa83@xxxxxxxxx>

Applied to hwmon-next.

Thanks,
Guenter

> ---
> Documentation/hwmon/aquacomputer_d5next.rst | 6 +--
> drivers/hwmon/aquacomputer_d5next.c | 49 ++++++++++++++++++---
> 2 files changed, 47 insertions(+), 8 deletions(-)
>
> diff --git a/Documentation/hwmon/aquacomputer_d5next.rst b/Documentation/hwmon/aquacomputer_d5next.rst
> index b94ff08080bf..3f7880fb8116 100644
> --- a/Documentation/hwmon/aquacomputer_d5next.rst
> +++ b/Documentation/hwmon/aquacomputer_d5next.rst
> @@ -21,9 +21,9 @@ Description
> This driver exposes hardware sensors of listed Aquacomputer devices, which
> communicate through proprietary USB HID protocols.
>
> -The Aquaero devices expose eight temperature sensors, eight virtual temperature
> -sensors and two flow senors. The fans expose their speed (in RPM), power,
> -voltage and current.
> +The Aquaero devices expose eight physical, eight virtual and four calculated
> +virtual temperature sensors, as well as two flow sensors. The fans expose their
> +speed (in RPM), power, voltage and current.
>
> For the D5 Next pump, available sensors are pump and fan speed, power, voltage
> and current, as well as coolant temperature and eight virtual temp sensors. Also
> diff --git a/drivers/hwmon/aquacomputer_d5next.c b/drivers/hwmon/aquacomputer_d5next.c
> index 0fd00cfb86c8..c1b885240ddf 100644
> --- a/drivers/hwmon/aquacomputer_d5next.c
> +++ b/drivers/hwmon/aquacomputer_d5next.c
> @@ -77,11 +77,13 @@ static u8 secondary_ctrl_report[] = {
> #define AQUAERO_NUM_FANS 4
> #define AQUAERO_NUM_SENSORS 8
> #define AQUAERO_NUM_VIRTUAL_SENSORS 8
> +#define AQUAERO_NUM_CALC_VIRTUAL_SENSORS 4
> #define AQUAERO_NUM_FLOW_SENSORS 2
>
> /* Sensor report offsets for Aquaero fan controllers */
> #define AQUAERO_SENSOR_START 0x65
> #define AQUAERO_VIRTUAL_SENSOR_START 0x85
> +#define AQUAERO_CALC_VIRTUAL_SENSOR_START 0x95
> #define AQUAERO_FLOW_SENSORS_START 0xF9
> #define AQUAERO_FAN_VOLTAGE_OFFSET 0x04
> #define AQUAERO_FAN_CURRENT_OFFSET 0x06
> @@ -232,6 +234,13 @@ static const char *const label_virtual_temp_sensors[] = {
> "Virtual sensor 16",
> };
>
> +static const char *const label_aquaero_calc_temp_sensors[] = {
> + "Calc. virtual sensor 1",
> + "Calc. virtual sensor 2",
> + "Calc. virtual sensor 3",
> + "Calc. virtual sensor 4"
> +};
> +
> /* Labels for Octo and Quadro (except speed) */
> static const char *const label_fan_speed[] = {
> "Fan 1 speed",
> @@ -361,6 +370,8 @@ struct aqc_data {
> int temp_sensor_start_offset;
> int num_virtual_temp_sensors;
> int virtual_temp_sensor_start_offset;
> + int num_calc_virt_temp_sensors;
> + int calc_virt_temp_sensor_start_offset;
> u16 temp_ctrl_offset;
> u16 power_cycle_count_offset;
> int num_flow_sensors;
> @@ -378,7 +389,7 @@ struct aqc_data {
> u32 power_cycles;
>
> /* Sensor values */
> - s32 temp_input[20]; /* Max 4 physical and 16 virtual */
> + s32 temp_input[20]; /* Max 4 physical and 16 virtual or 8 physical and 12 virtual */
> u16 speed_input[8];
> u32 power_input[8];
> u16 voltage_input[8];
> @@ -387,6 +398,7 @@ struct aqc_data {
> /* Label values */
> const char *const *temp_label;
> const char *const *virtual_temp_label;
> + const char *const *calc_virt_temp_label; /* For Aquaero */
> const char *const *speed_label;
> const char *const *power_label;
> const char *const *voltage_label;
> @@ -507,7 +519,9 @@ static umode_t aqc_is_visible(const void *data, enum hwmon_sensor_types type, u3
> }
> }
>
> - if (channel < priv->num_temp_sensors + priv->num_virtual_temp_sensors)
> + if (channel <
> + priv->num_temp_sensors + priv->num_virtual_temp_sensors +
> + priv->num_calc_virt_temp_sensors)
> switch (attr) {
> case hwmon_temp_label:
> case hwmon_temp_input:
> @@ -676,12 +690,20 @@ static int aqc_read_string(struct device *dev, enum hwmon_sensor_types type, u32
> {
> struct aqc_data *priv = dev_get_drvdata(dev);
>
> + /* Number of sensors that are not calculated */
> + int num_non_calc_sensors = priv->num_temp_sensors + priv->num_virtual_temp_sensors;
> +
> switch (type) {
> case hwmon_temp:
> - if (channel < priv->num_temp_sensors)
> + if (channel < priv->num_temp_sensors) {
> *str = priv->temp_label[channel];
> - else
> - *str = priv->virtual_temp_label[channel - priv->num_temp_sensors];
> + } else {
> + if (priv->kind == aquaero && channel >= num_non_calc_sensors)
> + *str =
> + priv->calc_virt_temp_label[channel - num_non_calc_sensors];
> + else
> + *str = priv->virtual_temp_label[channel - priv->num_temp_sensors];
> + }
> break;
> case hwmon_fan:
> *str = priv->speed_label[channel];
> @@ -910,6 +932,20 @@ static int aqc_raw_event(struct hid_device *hdev, struct hid_report *report, u8
>
> /* Special-case sensor readings */
> switch (priv->kind) {
> + case aquaero:
> + /* Read calculated virtual temp sensors */
> + i = priv->num_temp_sensors + priv->num_virtual_temp_sensors;
> + for (j = 0; j < priv->num_calc_virt_temp_sensors; j++) {
> + sensor_value = get_unaligned_be16(data +
> + priv->calc_virt_temp_sensor_start_offset +
> + j * AQC_SENSOR_SIZE);
> + if (sensor_value == AQC_TEMP_SENSOR_DISCONNECTED)
> + priv->temp_input[i] = -ENODATA;
> + else
> + priv->temp_input[i] = sensor_value * 10;
> + i++;
> + }
> + break;
> case d5next:
> priv->voltage_input[2] = get_unaligned_be16(data + D5NEXT_5V_VOLTAGE) * 10;
> priv->voltage_input[3] = get_unaligned_be16(data + D5NEXT_12V_VOLTAGE) * 10;
> @@ -1046,11 +1082,14 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id)
> priv->temp_sensor_start_offset = AQUAERO_SENSOR_START;
> priv->num_virtual_temp_sensors = AQUAERO_NUM_VIRTUAL_SENSORS;
> priv->virtual_temp_sensor_start_offset = AQUAERO_VIRTUAL_SENSOR_START;
> + priv->num_calc_virt_temp_sensors = AQUAERO_NUM_CALC_VIRTUAL_SENSORS;
> + priv->calc_virt_temp_sensor_start_offset = AQUAERO_CALC_VIRTUAL_SENSOR_START;
> priv->num_flow_sensors = AQUAERO_NUM_FLOW_SENSORS;
> priv->flow_sensors_start_offset = AQUAERO_FLOW_SENSORS_START;
>
> priv->temp_label = label_temp_sensors;
> priv->virtual_temp_label = label_virtual_temp_sensors;
> + priv->calc_virt_temp_label = label_aquaero_calc_temp_sensors;
> priv->speed_label = label_aquaero_speeds;
> priv->power_label = label_fan_power;
> priv->voltage_label = label_fan_voltage;