hwmon: (aquacomputer_d5next) Add support for Aquacomputer Poweradjust 3
Extend aquacomputer_d5next driver to expose the temp sensor of the Aquacomputer Poweradjust 3 fan controller, which communicates through a proprietary USB HID protocol. The Poweradjust 3 is not currently known to expose firmware version and serial number, so don't create debugfs entries if their values can't be retrieved. Tested by a user on Github [1]. [1] https://github.com/aleksamagicka/aquacomputer_d5next-hwmon/issues/57 Signed-off-by: Aleksa Savic <savicaleksa83@gmail.com> Link: https://lore.kernel.org/r/20230131101210.8095-1-savicaleksa83@gmail.com Signed-off-by: Guenter Roeck <linux@roeck-us.net>
This commit is contained in:
parent
1c999af509
commit
e0f6c370f0
|
@ -12,6 +12,7 @@ Supported devices:
|
|||
* Aquacomputer Octo fan controller
|
||||
* Aquacomputer Quadro fan controller
|
||||
* Aquacomputer High Flow Next sensor
|
||||
* Aquacomputer Poweradjust 3 fan controller
|
||||
|
||||
Author: Aleksa Savic
|
||||
|
||||
|
@ -53,6 +54,8 @@ 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 Poweradjust 3 controller exposes a single external temperature sensor.
|
||||
|
||||
Depending on the device, not all sysfs and debugfs entries will be available.
|
||||
Writing to virtual temperature sensors is not currently supported.
|
||||
|
||||
|
|
|
@ -4,7 +4,8 @@
|
|||
* Quadro, High Flow Next, Aquaero)
|
||||
*
|
||||
* Aquacomputer devices send HID reports (with ID 0x01) every second to report
|
||||
* sensor values.
|
||||
* sensor values, except for devices that communicate through the
|
||||
* legacy way (currently, Poweradjust 3).
|
||||
*
|
||||
* Copyright 2021 Aleksa Savic <savicaleksa83@gmail.com>
|
||||
* Copyright 2022 Jack Doan <me@jackdoan.com>
|
||||
|
@ -28,8 +29,9 @@
|
|||
#define USB_PRODUCT_ID_FARBWERK360 0xf010
|
||||
#define USB_PRODUCT_ID_OCTO 0xf011
|
||||
#define USB_PRODUCT_ID_HIGHFLOWNEXT 0xf012
|
||||
#define USB_PRODUCT_ID_POWERADJUST3 0xf0bd
|
||||
|
||||
enum kinds { d5next, farbwerk, farbwerk360, octo, quadro, highflownext, aquaero };
|
||||
enum kinds { d5next, farbwerk, farbwerk360, octo, quadro, highflownext, aquaero, poweradjust3 };
|
||||
|
||||
static const char *const aqc_device_names[] = {
|
||||
[d5next] = "d5next",
|
||||
|
@ -38,7 +40,8 @@ static const char *const aqc_device_names[] = {
|
|||
[octo] = "octo",
|
||||
[quadro] = "quadro",
|
||||
[highflownext] = "highflownext",
|
||||
[aquaero] = "aquaero"
|
||||
[aquaero] = "aquaero",
|
||||
[poweradjust3] = "poweradjust3"
|
||||
};
|
||||
|
||||
#define DRIVER_NAME "aquacomputer_d5next"
|
||||
|
@ -59,6 +62,9 @@ static u8 secondary_ctrl_report[] = {
|
|||
0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x34, 0xC6
|
||||
};
|
||||
|
||||
/* Report IDs for legacy devices */
|
||||
#define POWERADJUST3_STATUS_REPORT_ID 0x03
|
||||
|
||||
/* Info, sensor sizes and offsets for most Aquacomputer devices */
|
||||
#define AQC_SERIAL_START 0x3
|
||||
#define AQC_FIRMWARE_VERSION 0xD
|
||||
|
@ -176,6 +182,13 @@ static u16 quadro_ctrl_fan_offsets[] = { 0x37, 0x8c, 0xe1, 0x136 }; /* Fan speed
|
|||
#define HIGHFLOWNEXT_5V_VOLTAGE 97
|
||||
#define HIGHFLOWNEXT_5V_VOLTAGE_USB 99
|
||||
|
||||
/* Specs of the Poweradjust 3 */
|
||||
#define POWERADJUST3_NUM_SENSORS 1
|
||||
#define POWERADJUST3_SENSOR_REPORT_SIZE 0x32
|
||||
|
||||
/* Sensor report offsets for the Poweradjust 3 */
|
||||
#define POWERADJUST3_SENSOR_START 0x03
|
||||
|
||||
/* Labels for D5 Next */
|
||||
static const char *const label_d5next_temp[] = {
|
||||
"Coolant temp"
|
||||
|
@ -326,6 +339,11 @@ static const char *const label_highflownext_voltage[] = {
|
|||
"+5V USB voltage"
|
||||
};
|
||||
|
||||
/* Labels for Poweradjust 3 */
|
||||
static const char *const label_poweradjust3_temp_sensors[] = {
|
||||
"External sensor"
|
||||
};
|
||||
|
||||
struct aqc_fan_structure_offsets {
|
||||
u8 voltage;
|
||||
u8 curr;
|
||||
|
@ -357,6 +375,8 @@ struct aqc_data {
|
|||
enum kinds kind;
|
||||
const char *name;
|
||||
|
||||
int status_report_id; /* Used for legacy devices, report is stored in buffer */
|
||||
|
||||
int buffer_size;
|
||||
u8 *buffer;
|
||||
int checksum_start;
|
||||
|
@ -615,14 +635,49 @@ static umode_t aqc_is_visible(const void *data, enum hwmon_sensor_types type, u3
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Read device sensors by manually requesting the sensor report (legacy way) */
|
||||
static int aqc_legacy_read(struct aqc_data *priv)
|
||||
{
|
||||
int ret, i, sensor_value;
|
||||
|
||||
mutex_lock(&priv->mutex);
|
||||
|
||||
memset(priv->buffer, 0x00, priv->buffer_size);
|
||||
ret = hid_hw_raw_request(priv->hdev, priv->status_report_id, priv->buffer,
|
||||
priv->buffer_size, HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
|
||||
if (ret < 0)
|
||||
goto unlock_and_return;
|
||||
|
||||
/* Temperature sensor readings */
|
||||
for (i = 0; i < priv->num_temp_sensors; i++) {
|
||||
sensor_value = get_unaligned_le16(priv->buffer + priv->temp_sensor_start_offset +
|
||||
i * AQC_SENSOR_SIZE);
|
||||
priv->temp_input[i] = sensor_value * 10;
|
||||
}
|
||||
|
||||
priv->updated = jiffies;
|
||||
|
||||
unlock_and_return:
|
||||
mutex_unlock(&priv->mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int aqc_read(struct device *dev, enum hwmon_sensor_types type, u32 attr,
|
||||
int channel, long *val)
|
||||
{
|
||||
int ret;
|
||||
struct aqc_data *priv = dev_get_drvdata(dev);
|
||||
|
||||
if (time_after(jiffies, priv->updated + STATUS_UPDATE_INTERVAL))
|
||||
return -ENODATA;
|
||||
if (time_after(jiffies, priv->updated + STATUS_UPDATE_INTERVAL)) {
|
||||
if (priv->status_report_id != 0) {
|
||||
/* Legacy devices require manual reads */
|
||||
ret = aqc_legacy_read(priv);
|
||||
if (ret < 0)
|
||||
return -ENODATA;
|
||||
} else {
|
||||
return -ENODATA;
|
||||
}
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case hwmon_temp:
|
||||
|
@ -1014,9 +1069,13 @@ static void aqc_debugfs_init(struct aqc_data *priv)
|
|||
dev_name(&priv->hdev->dev));
|
||||
|
||||
priv->debugfs = debugfs_create_dir(name, NULL);
|
||||
debugfs_create_file("serial_number", 0444, priv->debugfs, priv, &serial_number_fops);
|
||||
debugfs_create_file("firmware_version", 0444, priv->debugfs, priv, &firmware_version_fops);
|
||||
|
||||
if (priv->serial_number_start_offset != 0)
|
||||
debugfs_create_file("serial_number", 0444, priv->debugfs, priv,
|
||||
&serial_number_fops);
|
||||
if (priv->firmware_version_offset != 0)
|
||||
debugfs_create_file("firmware_version", 0444, priv->debugfs, priv,
|
||||
&firmware_version_fops);
|
||||
if (priv->power_cycle_count_offset != 0)
|
||||
debugfs_create_file("power_cycles", 0444, priv->debugfs, priv, &power_cycles_fops);
|
||||
}
|
||||
|
@ -1214,6 +1273,17 @@ 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_POWERADJUST3:
|
||||
priv->kind = poweradjust3;
|
||||
|
||||
priv->num_fans = 0;
|
||||
|
||||
priv->num_temp_sensors = POWERADJUST3_NUM_SENSORS;
|
||||
priv->temp_sensor_start_offset = POWERADJUST3_SENSOR_START;
|
||||
priv->buffer_size = POWERADJUST3_SENSOR_REPORT_SIZE;
|
||||
|
||||
priv->temp_label = label_poweradjust3_temp_sensors;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -1225,6 +1295,9 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|||
|
||||
priv->fan_structure = &aqc_aquaero_fan_structure;
|
||||
break;
|
||||
case poweradjust3:
|
||||
priv->status_report_id = POWERADJUST3_STATUS_REPORT_ID;
|
||||
break;
|
||||
default:
|
||||
priv->serial_number_start_offset = AQC_SERIAL_START;
|
||||
priv->firmware_version_offset = AQC_FIRMWARE_VERSION;
|
||||
|
@ -1287,6 +1360,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_POWERADJUST3) },
|
||||
{ }
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue