* [PATCH v4 0/5] hwmon: AMPINEL telemetry support and shared fixes
@ 2026-09-27 18:37 Vas Zayarskiy
2026-09-27 18:37 ` [PATCH v4 1/5] hwmon: (aquacomputer_d5next) Avoid truncating scaled sensor readings Vas Zayarskiy
` (4 more replies)
0 siblings, 5 replies; 6+ messages in thread
From: Vas Zayarskiy @ 2026-09-27 18:37 UTC (permalink / raw)
To: linux, Aleksa Savic, Jack Doan
Cc: linux-hwmon, linux-kernel, linux-doc, Jonathan Corbet, Shuah Khan,
Randy Dunlap
This revision limits AMPINEL support to read-only telemetry. It drops the
hid-generic change and the hwmon match callback, so the series no longer
needs a HID change. The separate keyboard interface is deliberately
unsupported and remains unbound with the default driver selection.
Changes since v3:
- Select the telemetry interface in the existing probe switch using its
vendor collection and input report layout. Reject the keyboard there,
following the Aquaero and Leakshield approach. Remove the USB parent
cast, USB header dependency and interface-number check.
- Split shared report type/length validation and unknown firmware-version
handling into their own patches. Check received status reports against
the HID descriptor length for all devices using the raw-event path.
- Add the missing trailing comma and correct the -ENODATA and unit
conversion wording in the numeric-fix commit message.
- Rebase onto hwmon-next 9edd5ab2656f (7.3-rc4). The relevant driver and
HID matching code are unchanged from the previous base.
The earlier probe-time callback concern was resolved in review: HID core
blocks callbacks throughout probe unless hid_device_io_start() is called.
This driver does not call it, so no initialization-race fix is included.
Validation of this revision:
- The changed hwmon object builds on x86_64 and i386 with W=1 and Sparse.
- All 995 previously captured reports pass the actual C parser/read replay
with ASan/UBSan, including simulated 32-bit long clamping.
- Shared regression cases cover invalid report types and lengths, power
and current conversion, unavailable readings, startup expiry and unknown
firmware offsets. Removing the new shared validation fails the tests.
- A userspace harness exercises the actual stock HID matching and probe
selection/error unwind: telemetry is accepted and the keyboard rejected.
This is not a live kernel binding test.
- All seven Python tests pass; the updated RST renders without warnings.
V3 was tested on physical AMPINEL hardware across loading, reload,
suspend/resume and reboot. The telemetry decoding is unchanged here, but
this exact revision has not been loaded on hardware. Validation of the
other Aquacomputer models remains synthetic. Channel labels follow report
order; alarm reporting and protection configuration are not supported.
AI assistance: Codex assisted with implementation, tests and submission
text; Sparse was used for static analysis.
V3: https://lore.kernel.org/linux-hwmon/20260914233728.22725-1-contact@vasily.cc/
Review: https://lore.kernel.org/linux-hwmon/a968a02f-c513-42f0-993f-ede4f785025c@roeck-us.net/
Probe clarification: https://lore.kernel.org/linux-hwmon/d45d4de8-6925-40ad-a5b7-b8cef6356175@roeck-us.net/
Vas Zayarskiy (5):
hwmon: (aquacomputer_d5next) Avoid truncating scaled sensor readings
hwmon: (aquacomputer_d5next) Expire the initial sensor cache
hwmon: (aquacomputer_d5next) Validate incoming status reports
hwmon: (aquacomputer_d5next) Skip unknown firmware version offsets
hwmon: (aquacomputer_d5next) Add AMPINEL telemetry support
Documentation/hwmon/aquacomputer_d5next.rst | 13 +++
drivers/hwmon/Kconfig | 4 +-
drivers/hwmon/aquacomputer_d5next.c | 101 ++++++++++++++++++--
3 files changed, 106 insertions(+), 12 deletions(-)
base-commit: 9edd5ab2656f040d726b5388f49ceac10bb2944f
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v4 1/5] hwmon: (aquacomputer_d5next) Avoid truncating scaled sensor readings
2026-09-27 18:37 [PATCH v4 0/5] hwmon: AMPINEL telemetry support and shared fixes Vas Zayarskiy
@ 2026-09-27 18:37 ` Vas Zayarskiy
2026-09-27 18:37 ` [PATCH v4 2/5] hwmon: (aquacomputer_d5next) Expire the initial sensor cache Vas Zayarskiy
` (3 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Vas Zayarskiy @ 2026-09-27 18:37 UTC (permalink / raw)
To: linux, Aleksa Savic, Jack Doan
Cc: linux-hwmon, linux-kernel, linux-doc, Jonathan Corbet, Shuah Khan,
Randy Dunlap
High Flow Next power is reported in watts. Multiplying the 16-bit value
by one million can overflow both the signed intermediate and the u32
cache. Store power in long, perform the conversion in u64, and clamp to
LONG_MAX. The other existing power conversions fit in a signed 32-bit
value. Return -ENODATA for unavailable power instead of exposing the
stored error as a reading.
Widen the shared current cache to u32. The Aquastream XT conversion to
milliamperes can exceed 65535 mA; clamp its negative conversion results
to zero before assigning to the unsigned cache. This also permits devices
with scaled aggregate currents to store milliamperes directly.
Assisted-by: LLM sparse
Signed-off-by: Vas Zayarskiy <contact@vasily.cc>
---
drivers/hwmon/aquacomputer_d5next.c | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/drivers/hwmon/aquacomputer_d5next.c b/drivers/hwmon/aquacomputer_d5next.c
index 1ca70e726..9178ac4cb 100644
--- a/drivers/hwmon/aquacomputer_d5next.c
+++ b/drivers/hwmon/aquacomputer_d5next.c
@@ -19,6 +19,7 @@
#include <linux/hwmon.h>
#include <linux/jiffies.h>
#include <linux/ktime.h>
+#include <linux/limits.h>
#include <linux/module.h>
#include <linux/seq_file.h>
#include <linux/unaligned.h>
@@ -599,9 +600,9 @@ struct aqc_data {
u32 speed_input_min[1];
u32 speed_input_target[1];
u32 speed_input_max[1];
- u32 power_input[8];
+ long power_input[8];
u16 voltage_input[8];
- u16 current_input[8];
+ u32 current_input[8];
/* Label values */
const char *const *temp_label;
@@ -976,7 +977,7 @@ static int aqc_legacy_read(struct aqc_data *priv)
/* Calculation derived from linear regression */
sensor_value = get_unaligned_le16(priv->buffer + AQUASTREAMXT_PUMP_CURR_OFFSET);
- priv->current_input[0] = DIV_ROUND_CLOSEST(sensor_value * 176, 100) - 52;
+ priv->current_input[0] = max(DIV_ROUND_CLOSEST(sensor_value * 176, 100) - 52, 0);
sensor_value = get_unaligned_le16(priv->buffer + AQUASTREAMXT_PUMP_VOLTAGE_OFFSET);
priv->voltage_input[0] = DIV_ROUND_CLOSEST(sensor_value * 1000, 61);
@@ -1070,6 +1071,8 @@ static int aqc_read(struct device *dev, enum hwmon_sensor_types type, u32 attr,
}
break;
case hwmon_power:
+ if (priv->power_input[channel] == -ENODATA)
+ return -ENODATA;
*val = priv->power_input[channel];
break;
case hwmon_pwm:
@@ -1426,7 +1429,8 @@ static int aqc_raw_event(struct hid_device *hdev, struct hid_report *report, u8
priv->power_input[0] = -ENODATA;
else
priv->power_input[0] =
- get_unaligned_be16(data + HIGHFLOWNEXT_POWER) * 1000000;
+ min_t(u64, get_unaligned_be16(data + HIGHFLOWNEXT_POWER) * 1000000ULL,
+ LONG_MAX);
priv->voltage_input[0] = get_unaligned_be16(data + HIGHFLOWNEXT_5V_VOLTAGE) * 10;
priv->voltage_input[1] =
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v4 2/5] hwmon: (aquacomputer_d5next) Expire the initial sensor cache
2026-09-27 18:37 [PATCH v4 0/5] hwmon: AMPINEL telemetry support and shared fixes Vas Zayarskiy
2026-09-27 18:37 ` [PATCH v4 1/5] hwmon: (aquacomputer_d5next) Avoid truncating scaled sensor readings Vas Zayarskiy
@ 2026-09-27 18:37 ` Vas Zayarskiy
2026-09-27 18:37 ` [PATCH v4 3/5] hwmon: (aquacomputer_d5next) Validate incoming status reports Vas Zayarskiy
` (2 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Vas Zayarskiy @ 2026-09-27 18:37 UTC (permalink / raw)
To: linux, Aleksa Savic, Jack Doan
Cc: linux-hwmon, linux-kernel, linux-doc, Jonathan Corbet, Shuah Khan,
Randy Dunlap
The initial update timestamp makes the cache expire at the current
jiffy. Since aqc_read() uses time_after(), a read in that same jiffy can
expose zero-initialized data or skip the first legacy report request.
Initialize the timestamp one tick earlier so the cache starts expired
for every supported device.
Assisted-by: LLM sparse
Signed-off-by: Vas Zayarskiy <contact@vasily.cc>
---
drivers/hwmon/aquacomputer_d5next.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/hwmon/aquacomputer_d5next.c b/drivers/hwmon/aquacomputer_d5next.c
index 9178ac4cb..b58f5b5c9 100644
--- a/drivers/hwmon/aquacomputer_d5next.c
+++ b/drivers/hwmon/aquacomputer_d5next.c
@@ -1531,7 +1531,7 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id)
priv->hdev = hdev;
hid_set_drvdata(hdev, priv);
- priv->updated = jiffies - STATUS_UPDATE_INTERVAL;
+ priv->updated = jiffies - STATUS_UPDATE_INTERVAL - 1;
ret = hid_parse(hdev);
if (ret)
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v4 3/5] hwmon: (aquacomputer_d5next) Validate incoming status reports
2026-09-27 18:37 [PATCH v4 0/5] hwmon: AMPINEL telemetry support and shared fixes Vas Zayarskiy
2026-09-27 18:37 ` [PATCH v4 1/5] hwmon: (aquacomputer_d5next) Avoid truncating scaled sensor readings Vas Zayarskiy
2026-09-27 18:37 ` [PATCH v4 2/5] hwmon: (aquacomputer_d5next) Expire the initial sensor cache Vas Zayarskiy
@ 2026-09-27 18:37 ` Vas Zayarskiy
2026-09-27 18:37 ` [PATCH v4 4/5] hwmon: (aquacomputer_d5next) Skip unknown firmware version offsets Vas Zayarskiy
2026-09-27 18:37 ` [PATCH v4 5/5] hwmon: (aquacomputer_d5next) Add AMPINEL telemetry support Vas Zayarskiy
4 siblings, 0 replies; 6+ messages in thread
From: Vas Zayarskiy @ 2026-09-27 18:37 UTC (permalink / raw)
To: linux, Aleksa Savic, Jack Doan
Cc: linux-hwmon, linux-kernel, linux-doc, Jonathan Corbet, Shuah Khan,
Randy Dunlap
The raw-event callback runs before HID core pads a short report. Check
that the report is an input report and that its length matches the HID
report descriptor before decoding sensor fields. Otherwise a truncated
report can be read past its received data, and a feature report with the
same ID can be mistaken for sensor data.
Apply these checks to every device using the shared raw-event path and
check the report ID byte before updating the cache. Legacy devices keep
using their separate feature-report read path.
Assisted-by: LLM sparse
Signed-off-by: Vas Zayarskiy <contact@vasily.cc>
---
drivers/hwmon/aquacomputer_d5next.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/hwmon/aquacomputer_d5next.c b/drivers/hwmon/aquacomputer_d5next.c
index b58f5b5c9..d4ed204ca 100644
--- a/drivers/hwmon/aquacomputer_d5next.c
+++ b/drivers/hwmon/aquacomputer_d5next.c
@@ -1332,7 +1332,8 @@ static int aqc_raw_event(struct hid_device *hdev, struct hid_report *report, u8
int i, j, sensor_value;
struct aqc_data *priv;
- if (report->id != STATUS_REPORT_ID)
+ if (report->id != STATUS_REPORT_ID || report->type != HID_INPUT_REPORT ||
+ size != hid_report_len(report) || data[0] != STATUS_REPORT_ID)
return 0;
priv = hid_get_drvdata(hdev);
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v4 4/5] hwmon: (aquacomputer_d5next) Skip unknown firmware version offsets
2026-09-27 18:37 [PATCH v4 0/5] hwmon: AMPINEL telemetry support and shared fixes Vas Zayarskiy
` (2 preceding siblings ...)
2026-09-27 18:37 ` [PATCH v4 3/5] hwmon: (aquacomputer_d5next) Validate incoming status reports Vas Zayarskiy
@ 2026-09-27 18:37 ` Vas Zayarskiy
2026-09-27 18:37 ` [PATCH v4 5/5] hwmon: (aquacomputer_d5next) Add AMPINEL telemetry support Vas Zayarskiy
4 siblings, 0 replies; 6+ messages in thread
From: Vas Zayarskiy @ 2026-09-27 18:37 UTC (permalink / raw)
To: linux, Aleksa Savic, Jack Doan
Cc: linux-hwmon, linux-kernel, linux-doc, Jonathan Corbet, Shuah Khan,
Randy Dunlap
Only decode the firmware version when its offset is known, matching the
condition used to expose the firmware_version debugfs file. This lets a
device leave the offset at zero without interpreting the report ID and
following byte as a firmware version.
Assisted-by: LLM sparse
Signed-off-by: Vas Zayarskiy <contact@vasily.cc>
---
drivers/hwmon/aquacomputer_d5next.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/hwmon/aquacomputer_d5next.c b/drivers/hwmon/aquacomputer_d5next.c
index d4ed204ca..5c0c47eb0 100644
--- a/drivers/hwmon/aquacomputer_d5next.c
+++ b/drivers/hwmon/aquacomputer_d5next.c
@@ -1342,7 +1342,8 @@ static int aqc_raw_event(struct hid_device *hdev, struct hid_report *report, u8
priv->serial_number[0] = get_unaligned_be16(data + priv->serial_number_start_offset);
priv->serial_number[1] = get_unaligned_be16(data + priv->serial_number_start_offset +
SERIAL_PART_OFFSET);
- priv->firmware_version = get_unaligned_be16(data + priv->firmware_version_offset);
+ if (priv->firmware_version_offset)
+ priv->firmware_version = get_unaligned_be16(data + priv->firmware_version_offset);
/* Physical temperature sensor readings */
for (i = 0; i < priv->num_temp_sensors; i++) {
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v4 5/5] hwmon: (aquacomputer_d5next) Add AMPINEL telemetry support
2026-09-27 18:37 [PATCH v4 0/5] hwmon: AMPINEL telemetry support and shared fixes Vas Zayarskiy
` (3 preceding siblings ...)
2026-09-27 18:37 ` [PATCH v4 4/5] hwmon: (aquacomputer_d5next) Skip unknown firmware version offsets Vas Zayarskiy
@ 2026-09-27 18:37 ` Vas Zayarskiy
4 siblings, 0 replies; 6+ messages in thread
From: Vas Zayarskiy @ 2026-09-27 18:37 UTC (permalink / raw)
To: linux, Aleksa Savic, Jack Doan
Cc: linux-hwmon, linux-kernel, linux-doc, Jonathan Corbet, Shuah Khan,
Randy Dunlap
Add read-only total power, total current, input voltage, hotspot
temperature and six channel currents for the Aquacomputer AMPINEL.
Decode its 544-byte input report through the existing serial-number,
temperature and update path, with power, current and voltage handled in
the device-specific switch. Store all readings in hwmon units.
Select the telemetry interface in probe by its vendor collection and
input report layout, following the existing Aquaero and Leakshield
probe filtering. No match callback or HID core change is required.
The separate keyboard interface is not supported. The driver rejects
it in probe, and stock hid-generic yields to this driver's product ID
entry, leaving it unbound. This intentionally limits support to telemetry;
keyboard support can be addressed separately. Channel labels follow
report order; configuration and alarms are not supported.
Assisted-by: LLM sparse
Signed-off-by: Vas Zayarskiy <contact@vasily.cc>
---
Documentation/hwmon/aquacomputer_d5next.rst | 13 ++++
drivers/hwmon/Kconfig | 4 +-
drivers/hwmon/aquacomputer_d5next.c | 81 ++++++++++++++++++++-
3 files changed, 93 insertions(+), 5 deletions(-)
diff --git a/Documentation/hwmon/aquacomputer_d5next.rst b/Documentation/hwmon/aquacomputer_d5next.rst
index 49163f387..ad8f85b1c 100644
--- a/Documentation/hwmon/aquacomputer_d5next.rst
+++ b/Documentation/hwmon/aquacomputer_d5next.rst
@@ -13,6 +13,7 @@ Supported devices:
* Aquacomputer Quadro fan controller
* Aquacomputer High Flow Next sensor
* Aquacomputer Leakshield leak prevention system
+* Aquacomputer AMPINEL power monitor
* Aquacomputer Aquastream XT watercooling pump
* Aquacomputer Aquastream Ultimate watercooling pump
* Aquacomputer Poweradjust 3 fan controller
@@ -69,6 +70,18 @@ The Aquastream XT pump exposes temperature readings for the coolant, external se
and fan IC. It also exposes pump and fan speeds (in RPM), voltages, as well as pump
current.
+The AMPINEL exposes total power, total current, input voltage, hotspot
+temperature and six channel currents. Channel numbers follow report order;
+their mapping to physical connector pins has not been verified. The readings
+are received approximately twice per second. Only sensor reads are supported;
+the driver does not configure protection settings or report alarms.
+The separate keyboard interface is not supported and remains unbound while
+this driver is registered.
+
+For AMPINEL, ``power1_input`` is total power, ``in0_input`` is input voltage,
+``temp1_input`` is hotspot temperature, ``curr1_input`` is total current, and
+``curr[2-7]_input`` are the six channel currents.
+
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.
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 18c682e1a..ae90f4894 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -257,14 +257,14 @@ config SENSORS_AHT10
will be called aht10.
config SENSORS_AQUACOMPUTER_D5NEXT
- tristate "Aquacomputer D5 Next, Octo, Quadro, Farbwerk, Farbwerk 360, High Flow Next"
+ tristate "Aquacomputer D5 Next and other USB devices"
depends on USB_HID
select CRC16
help
If you say yes here you get support for sensors and fans of
the Aquacomputer D5 Next watercooling pump, Octo and Quadro fan
controllers, Farbwerk and Farbwerk 360 RGB controllers, High Flow
- Next sensor, where available.
+ Next sensor and AMPINEL power monitor, where available.
This driver can also be built as a module. If so, the module
will be called aquacomputer_d5next.
diff --git a/drivers/hwmon/aquacomputer_d5next.c b/drivers/hwmon/aquacomputer_d5next.c
index 5c0c47eb0..7604e7636 100644
--- a/drivers/hwmon/aquacomputer_d5next.c
+++ b/drivers/hwmon/aquacomputer_d5next.c
@@ -2,7 +2,7 @@
/*
* hwmon driver for Aquacomputer devices (D5 Next, Farbwerk, Farbwerk 360, Octo,
* Quadro, High Flow Next, Aquaero, Aquastream Ultimate, Leakshield,
- * High Flow USB/MPS Flow family)
+ * High Flow USB/MPS Flow family, AMPINEL)
*
* Aquacomputer devices send HID reports (with ID 0x01) every second to report
* sensor values, except for devices that communicate through the
@@ -33,6 +33,7 @@
#define USB_PRODUCT_ID_OCTO 0xf011
#define USB_PRODUCT_ID_HIGHFLOWNEXT 0xf012
#define USB_PRODUCT_ID_LEAKSHIELD 0xf014
+#define USB_PRODUCT_ID_AMPINEL 0xf015
#define USB_PRODUCT_ID_AQUASTREAMXT 0xf0b6
#define USB_PRODUCT_ID_AQUASTREAMULT 0xf00b
#define USB_PRODUCT_ID_POWERADJUST3 0xf0bd
@@ -41,7 +42,7 @@
enum kinds {
d5next, farbwerk, farbwerk360, octo, quadro,
highflownext, aquaero, poweradjust3, aquastreamult,
- aquastreamxt, leakshield, highflow
+ aquastreamxt, leakshield, highflow, ampinel
};
static const char *const aqc_device_names[] = {
@@ -56,7 +57,8 @@ static const char *const aqc_device_names[] = {
[aquaero] = "aquaero",
[aquastreamult] = "aquastreamultimate",
[poweradjust3] = "poweradjust3",
- [highflow] = "highflow" /* Covers MPS Flow devices */
+ [highflow] = "highflow", /* Covers MPS Flow devices */
+ [ampinel] = "ampinel",
};
#define DRIVER_NAME "aquacomputer_d5next"
@@ -111,6 +113,15 @@ static u8 aquaero_secondary_ctrl_report[] = {
#define AQC_FAN_POWER_OFFSET 0x06
#define AQC_FAN_SPEED_OFFSET 0x08
+/* AMPINEL offsets include the report ID byte. */
+#define AMPINEL_STATUS_REPORT_SIZE 544
+#define AMPINEL_NUM_CHANNELS 6
+#define AMPINEL_CHANNEL_CURRENT_START 0x6f
+#define AMPINEL_POWER 0xc7
+#define AMPINEL_CURRENT 0xc9
+#define AMPINEL_VOLTAGE 0xcf
+#define AMPINEL_HOTSPOT 0xe1
+
/* Specs of the Aquaero fan controllers */
#define AQUAERO_SERIAL_START 0x07
#define AQUAERO_FIRMWARE_VERSION 0x0B
@@ -516,6 +527,24 @@ static const char *const label_highflow_speeds[] = {
"Flow speed [dL/h]"
};
+static const char *const label_ampinel_temp[] = {
+ "Hotspot"
+};
+
+static const char *const label_ampinel_power[] = {
+ "Total power"
+};
+
+static const char *const label_ampinel_voltage[] = {
+ "VCC In"
+};
+
+static const char *const label_ampinel_current[] = {
+ "Total current",
+ "Channel 1", "Channel 2", "Channel 3",
+ "Channel 4", "Channel 5", "Channel 6"
+};
+
struct aqc_fan_structure_offsets {
u8 voltage;
u8 curr;
@@ -869,6 +898,10 @@ static umode_t aqc_is_visible(const void *data, enum hwmon_sensor_types type, u3
break;
case hwmon_power:
switch (priv->kind) {
+ case ampinel:
+ if (channel == 0)
+ return 0444;
+ break;
case aquastreamult:
/* Special case to support pump and fan power */
if (channel < 2)
@@ -889,6 +922,10 @@ static umode_t aqc_is_visible(const void *data, enum hwmon_sensor_types type, u3
break;
case hwmon_curr:
switch (priv->kind) {
+ case ampinel:
+ if (channel < AMPINEL_NUM_CHANNELS + 1)
+ return 0444;
+ break;
case aquastreamult:
/* Special case to support pump and fan current */
if (channel < 2)
@@ -907,6 +944,10 @@ static umode_t aqc_is_visible(const void *data, enum hwmon_sensor_types type, u3
break;
case hwmon_in:
switch (priv->kind) {
+ case ampinel:
+ if (channel == 0)
+ return 0444;
+ break;
case d5next:
/* Special case to support +5V and +12V voltage sensors */
if (channel < priv->num_fans + 2)
@@ -1396,6 +1437,17 @@ static int aqc_raw_event(struct hid_device *hdev, struct hid_report *report, u8
/* Special-case sensor readings */
switch (priv->kind) {
+ case ampinel:
+ priv->power_input[0] =
+ min_t(u64, get_unaligned_be16(data + AMPINEL_POWER) * 100000ULL,
+ LONG_MAX);
+ priv->current_input[0] = get_unaligned_be16(data + AMPINEL_CURRENT) * 10;
+ for (i = 0; i < AMPINEL_NUM_CHANNELS; i++)
+ priv->current_input[i + 1] =
+ get_unaligned_be16(data + AMPINEL_CHANNEL_CURRENT_START +
+ i * AQC_SENSOR_SIZE);
+ priv->voltage_input[0] = get_unaligned_be16(data + AMPINEL_VOLTAGE);
+ break;
case aquaero:
/* Read calculated virtual temp sensors */
i = priv->num_temp_sensors + priv->num_virtual_temp_sensors;
@@ -1523,6 +1575,7 @@ static void aqc_debugfs_init(struct aqc_data *priv)
static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id)
{
+ struct hid_report *report;
struct aqc_data *priv;
int ret;
@@ -1548,6 +1601,24 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id)
goto fail_and_stop;
switch (hdev->product) {
+ case USB_PRODUCT_ID_AMPINEL:
+ /* The other AMPINEL HID interface is a keyboard. */
+ report = hdev->report_enum[HID_INPUT_REPORT].report_id_hash[STATUS_REPORT_ID];
+ if (hdev->maxcollection != 1 ||
+ hdev->collection[0].usage != (HID_UP_MSVENDOR | 1) ||
+ !report || report->size != (AMPINEL_STATUS_REPORT_SIZE - 1) * 8) {
+ ret = -ENODEV;
+ goto fail_and_close;
+ }
+
+ priv->kind = ampinel;
+ priv->num_temp_sensors = 1;
+ priv->temp_sensor_start_offset = AMPINEL_HOTSPOT;
+ priv->temp_label = label_ampinel_temp;
+ priv->power_label = label_ampinel_power;
+ priv->voltage_label = label_ampinel_voltage;
+ priv->current_label = label_ampinel_current;
+ break;
case USB_PRODUCT_ID_AQUAERO:
/*
* Aquaero presents itself as three HID devices under the same product ID:
@@ -1797,6 +1868,9 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id)
}
switch (priv->kind) {
+ case ampinel:
+ priv->serial_number_start_offset = AQC_SERIAL_START;
+ break;
case aquaero:
priv->serial_number_start_offset = AQUAERO_SERIAL_START;
priv->firmware_version_offset = AQUAERO_FIRMWARE_VERSION;
@@ -1892,6 +1966,7 @@ static const struct hid_device_id aqc_table[] = {
{ 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_LEAKSHIELD) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_AQUACOMPUTER, USB_PRODUCT_ID_AMPINEL) },
{ HID_USB_DEVICE(USB_VENDOR_ID_AQUACOMPUTER, USB_PRODUCT_ID_AQUASTREAMXT) },
{ HID_USB_DEVICE(USB_VENDOR_ID_AQUACOMPUTER, USB_PRODUCT_ID_AQUASTREAMULT) },
{ HID_USB_DEVICE(USB_VENDOR_ID_AQUACOMPUTER, USB_PRODUCT_ID_POWERADJUST3) },
^ permalink raw reply related [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-09-27 18:37 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-27 18:37 [PATCH v4 0/5] hwmon: AMPINEL telemetry support and shared fixes Vas Zayarskiy
2026-09-27 18:37 ` [PATCH v4 1/5] hwmon: (aquacomputer_d5next) Avoid truncating scaled sensor readings Vas Zayarskiy
2026-09-27 18:37 ` [PATCH v4 2/5] hwmon: (aquacomputer_d5next) Expire the initial sensor cache Vas Zayarskiy
2026-09-27 18:37 ` [PATCH v4 3/5] hwmon: (aquacomputer_d5next) Validate incoming status reports Vas Zayarskiy
2026-09-27 18:37 ` [PATCH v4 4/5] hwmon: (aquacomputer_d5next) Skip unknown firmware version offsets Vas Zayarskiy
2026-09-27 18:37 ` [PATCH v4 5/5] hwmon: (aquacomputer_d5next) Add AMPINEL telemetry support Vas Zayarskiy
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox