Re: [PATCH] hwmon: (aquacomputer_d5next) Add support for Aquacomputer Aquastream Ultimate

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

 



On Fri, Feb 03, 2023 at 01:03:24PM +0100, Aleksa Savic wrote:
> Extend aquacomputer_d5next driver to expose various hardware sensors of the
> Aquacomputer Aquastream Ultimate watercooling pump, which communicates
> through a proprietary USB HID protocol.
> 
> Coolant temp and external temp sensor readings are available, along with
> speed, power, voltage and current of both the pump and optionally connected
> fan. It also exposes pressure and flow speed readings.
> 
> Additionally, serial number and firmware version are exposed through
> debugfs.
> 
> Tested by a user on Github [1].
> 
> [1] https://github.com/aleksamagicka/aquacomputer_d5next-hwmon/issues/50
> 
> Signed-off-by: Aleksa Savic <savicaleksa83@xxxxxxxxx>

Applied.

Thanks,
Guenter

> ---
>  Documentation/hwmon/aquacomputer_d5next.rst |   5 +
>  drivers/hwmon/aquacomputer_d5next.c         | 126 +++++++++++++++++++-
>  2 files changed, 125 insertions(+), 6 deletions(-)
> 
> diff --git a/Documentation/hwmon/aquacomputer_d5next.rst b/Documentation/hwmon/aquacomputer_d5next.rst
> index 527bcd3edda9..7d0d015b1a52 100644
> --- a/Documentation/hwmon/aquacomputer_d5next.rst
> +++ b/Documentation/hwmon/aquacomputer_d5next.rst
> @@ -12,6 +12,7 @@ Supported devices:
>  * Aquacomputer Octo fan controller
>  * Aquacomputer Quadro fan controller
>  * Aquacomputer High Flow Next sensor
> +* Aquacomputer Aquastream Ultimate watercooling pump
>  * Aquacomputer Poweradjust 3 fan controller
>  
>  Author: Aleksa Savic
> @@ -54,6 +55,10 @@ The High Flow Next exposes +5V voltages, water quality, conductivity and flow re
>  A temperature sensor can be connected to it, in which case it provides its reading
>  and an estimation of the dissipated/absorbed power in the liquid cooling loop.
>  
> +The Aquastream Ultimate pump exposes coolant temp and an external temp sensor, along
> +with speed, power, voltage and current of both the pump and optionally connected fan.
> +It also exposes pressure and flow speed readings.
> +
>  The Poweradjust 3 controller exposes a single external temperature sensor.
>  
>  Depending on the device, not all sysfs and debugfs entries will be available.
> diff --git a/drivers/hwmon/aquacomputer_d5next.c b/drivers/hwmon/aquacomputer_d5next.c
> index 2945b630b4a0..12682a610ce7 100644
> --- a/drivers/hwmon/aquacomputer_d5next.c
> +++ b/drivers/hwmon/aquacomputer_d5next.c
> @@ -1,7 +1,7 @@
>  // SPDX-License-Identifier: GPL-2.0+
>  /*
>   * hwmon driver for Aquacomputer devices (D5 Next, Farbwerk, Farbwerk 360, Octo,
> - * Quadro, High Flow Next, Aquaero)
> + * Quadro, High Flow Next, Aquaero, Aquastream Ultimate)
>   *
>   * Aquacomputer devices send HID reports (with ID 0x01) every second to report
>   * sensor values, except for devices that communicate through the
> @@ -29,9 +29,13 @@
>  #define USB_PRODUCT_ID_FARBWERK360	0xf010
>  #define USB_PRODUCT_ID_OCTO		0xf011
>  #define USB_PRODUCT_ID_HIGHFLOWNEXT	0xf012
> +#define USB_PRODUCT_ID_AQUASTREAMULT	0xf00b
>  #define USB_PRODUCT_ID_POWERADJUST3	0xf0bd
>  
> -enum kinds { d5next, farbwerk, farbwerk360, octo, quadro, highflownext, aquaero, poweradjust3 };
> +enum kinds {
> +	d5next, farbwerk, farbwerk360, octo, quadro,
> +	highflownext, aquaero, poweradjust3, aquastreamult
> +};
>  
>  static const char *const aqc_device_names[] = {
>  	[d5next] = "d5next",
> @@ -41,6 +45,7 @@ static const char *const aqc_device_names[] = {
>  	[quadro] = "quadro",
>  	[highflownext] = "highflownext",
>  	[aquaero] = "aquaero",
> +	[aquastreamult] = "aquastreamultimate",
>  	[poweradjust3] = "poweradjust3"
>  };
>  
> @@ -117,6 +122,26 @@ static u16 d5next_sensor_fan_offsets[] = { D5NEXT_PUMP_OFFSET, D5NEXT_FAN_OFFSET
>  #define D5NEXT_TEMP_CTRL_OFFSET		0x2D	/* Temperature sensor offsets location */
>  static u16 d5next_ctrl_fan_offsets[] = { 0x97, 0x42 };	/* Pump and fan speed (from 0-100%) */
>  
> +/* Specs of the Aquastream Ultimate pump */
> +/* Pump does not follow the standard structure, so only consider the fan */
> +#define AQUASTREAMULT_NUM_FANS		1
> +#define AQUASTREAMULT_NUM_SENSORS	2
> +
> +/* Sensor report offsets for the Aquastream Ultimate pump */
> +#define AQUASTREAMULT_SENSOR_START		0x2D
> +#define AQUASTREAMULT_PUMP_OFFSET		0x51
> +#define AQUASTREAMULT_PUMP_VOLTAGE		0x3D
> +#define AQUASTREAMULT_PUMP_CURRENT		0x53
> +#define AQUASTREAMULT_PUMP_POWER		0x55
> +#define AQUASTREAMULT_FAN_OFFSET		0x41
> +#define AQUASTREAMULT_PRESSURE_OFFSET		0x57
> +#define AQUASTREAMULT_FLOW_SENSOR_OFFSET	0x37
> +#define AQUASTREAMULT_FAN_VOLTAGE_OFFSET	0x02
> +#define AQUASTREAMULT_FAN_CURRENT_OFFSET	0x00
> +#define AQUASTREAMULT_FAN_POWER_OFFSET		0x04
> +#define AQUASTREAMULT_FAN_SPEED_OFFSET		0x06
> +static u16 aquastreamult_sensor_fan_offsets[] = { AQUASTREAMULT_FAN_OFFSET };
> +
>  /* Spec and sensor report offset for the Farbwerk RGB controller */
>  #define FARBWERK_NUM_SENSORS		4
>  #define FARBWERK_SENSOR_START		0x2f
> @@ -339,6 +364,34 @@ static const char *const label_highflownext_voltage[] = {
>  	"+5V USB voltage"
>  };
>  
> +/* Labels for Aquastream Ultimate */
> +static const char *const label_aquastreamult_temp[] = {
> +	"Coolant temp",
> +	"External temp"
> +};
> +
> +static const char *const label_aquastreamult_speeds[] = {
> +	"Fan speed",
> +	"Pump speed",
> +	"Pressure [mbar]",
> +	"Flow speed [dL/h]"
> +};
> +
> +static const char *const label_aquastreamult_power[] = {
> +	"Fan power",
> +	"Pump power"
> +};
> +
> +static const char *const label_aquastreamult_voltages[] = {
> +	"Fan voltage",
> +	"Pump voltage"
> +};
> +
> +static const char *const label_aquastreamult_current[] = {
> +	"Fan current",
> +	"Pump current"
> +};
> +
>  /* Labels for Poweradjust 3 */
>  static const char *const label_poweradjust3_temp_sensors[] = {
>  	"External sensor"
> @@ -359,7 +412,15 @@ static struct aqc_fan_structure_offsets aqc_aquaero_fan_structure = {
>  	.speed = AQUAERO_FAN_SPEED_OFFSET
>  };
>  
> -/* Fan structure offsets for all devices except Aquaero */
> +/* Fan structure offsets for Aquastream Ultimate */
> +static struct aqc_fan_structure_offsets aqc_aquastreamult_fan_structure = {
> +	.voltage = AQUASTREAMULT_FAN_VOLTAGE_OFFSET,
> +	.curr = AQUASTREAMULT_FAN_CURRENT_OFFSET,
> +	.power = AQUASTREAMULT_FAN_POWER_OFFSET,
> +	.speed = AQUASTREAMULT_FAN_SPEED_OFFSET
> +};
> +
> +/* Fan structure offsets for all devices except those above */
>  static struct aqc_fan_structure_offsets aqc_general_fan_structure = {
>  	.voltage = AQC_FAN_VOLTAGE_OFFSET,
>  	.curr = AQC_FAN_CURRENT_OFFSET,
> @@ -565,6 +626,14 @@ static umode_t aqc_is_visible(const void *data, enum hwmon_sensor_types type, u3
>  		case hwmon_fan_input:
>  		case hwmon_fan_label:
>  			switch (priv->kind) {
> +			case aquastreamult:
> +				/*
> +				 * Special case to support pump RPM, fan RPM,
> +				 * pressure and flow sensor
> +				 */
> +				if (channel < 4)
> +					return 0444;
> +				break;
>  			case highflownext:
>  				/* Special case to support flow sensor, water quality
>  				 * and conductivity
> @@ -595,6 +664,11 @@ static umode_t aqc_is_visible(const void *data, enum hwmon_sensor_types type, u3
>  		break;
>  	case hwmon_power:
>  		switch (priv->kind) {
> +		case aquastreamult:
> +			/* Special case to support pump and fan power */
> +			if (channel < 2)
> +				return 0444;
> +			break;
>  		case highflownext:
>  			/* Special case to support one power sensor */
>  			if (channel == 0)
> @@ -607,8 +681,17 @@ static umode_t aqc_is_visible(const void *data, enum hwmon_sensor_types type, u3
>  		}
>  		break;
>  	case hwmon_curr:
> -		if (channel < priv->num_fans)
> -			return 0444;
> +		switch (priv->kind) {
> +		case aquastreamult:
> +			/* Special case to support pump and fan current */
> +			if (channel < 2)
> +				return 0444;
> +			break;
> +		default:
> +			if (channel < priv->num_fans)
> +				return 0444;
> +			break;
> +		}
>  		break;
>  	case hwmon_in:
>  		switch (priv->kind) {
> @@ -617,6 +700,7 @@ static umode_t aqc_is_visible(const void *data, enum hwmon_sensor_types type, u3
>  			if (channel < priv->num_fans + 2)
>  				return 0444;
>  			break;
> +		case aquastreamult:
>  		case highflownext:
>  			/* Special case to support two voltage sensors */
>  			if (channel < 2)
> @@ -1001,6 +1085,17 @@ static int aqc_raw_event(struct hid_device *hdev, struct hid_report *report, u8
>  			i++;
>  		}
>  		break;
> +	case aquastreamult:
> +		priv->speed_input[1] = get_unaligned_be16(data + AQUASTREAMULT_PUMP_OFFSET);
> +		priv->speed_input[2] = get_unaligned_be16(data + AQUASTREAMULT_PRESSURE_OFFSET);
> +		priv->speed_input[3] = get_unaligned_be16(data + AQUASTREAMULT_FLOW_SENSOR_OFFSET);
> +
> +		priv->power_input[1] = get_unaligned_be16(data + AQUASTREAMULT_PUMP_POWER) * 10000;
> +
> +		priv->voltage_input[1] = get_unaligned_be16(data + AQUASTREAMULT_PUMP_VOLTAGE) * 10;
> +
> +		priv->current_input[1] = get_unaligned_be16(data + AQUASTREAMULT_PUMP_CURRENT);
> +		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;
> @@ -1273,6 +1368,21 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id)
>  		priv->power_label = label_highflownext_power;
>  		priv->voltage_label = label_highflownext_voltage;
>  		break;
> +	case USB_PRODUCT_ID_AQUASTREAMULT:
> +		priv->kind = aquastreamult;
> +
> +		priv->num_fans = AQUASTREAMULT_NUM_FANS;
> +		priv->fan_sensor_offsets = aquastreamult_sensor_fan_offsets;
> +
> +		priv->num_temp_sensors = AQUASTREAMULT_NUM_SENSORS;
> +		priv->temp_sensor_start_offset = AQUASTREAMULT_SENSOR_START;
> +
> +		priv->temp_label = label_aquastreamult_temp;
> +		priv->speed_label = label_aquastreamult_speeds;
> +		priv->power_label = label_aquastreamult_power;
> +		priv->voltage_label = label_aquastreamult_voltages;
> +		priv->current_label = label_aquastreamult_current;
> +		break;
>  	case USB_PRODUCT_ID_POWERADJUST3:
>  		priv->kind = poweradjust3;
>  
> @@ -1302,7 +1412,10 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id)
>  		priv->serial_number_start_offset = AQC_SERIAL_START;
>  		priv->firmware_version_offset = AQC_FIRMWARE_VERSION;
>  
> -		priv->fan_structure = &aqc_general_fan_structure;
> +		if (priv->kind == aquastreamult)
> +			priv->fan_structure = &aqc_aquastreamult_fan_structure;
> +		else
> +			priv->fan_structure = &aqc_general_fan_structure;
>  		break;
>  	}
>  
> @@ -1360,6 +1473,7 @@ static const struct hid_device_id aqc_table[] = {
>  	{ HID_USB_DEVICE(USB_VENDOR_ID_AQUACOMPUTER, USB_PRODUCT_ID_OCTO) },
>  	{ HID_USB_DEVICE(USB_VENDOR_ID_AQUACOMPUTER, USB_PRODUCT_ID_QUADRO) },
>  	{ HID_USB_DEVICE(USB_VENDOR_ID_AQUACOMPUTER, USB_PRODUCT_ID_HIGHFLOWNEXT) },
> +	{ HID_USB_DEVICE(USB_VENDOR_ID_AQUACOMPUTER, USB_PRODUCT_ID_AQUASTREAMULT) },
>  	{ HID_USB_DEVICE(USB_VENDOR_ID_AQUACOMPUTER, USB_PRODUCT_ID_POWERADJUST3) },
>  	{ }
>  };



[Index of Archives]     [Kernel Newbies]     [Security]     [Netfilter]     [Bugtraq]     [Linux FS]     [Yosemite Forum]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Device Mapper]     [Linux Resources]

  Powered by Linux