Skip to content

Commit

Permalink
hwmon: (aquacomputer_d5next) Insert delay between ctrl report operations
Browse files Browse the repository at this point in the history
Signed-off-by: Aleksa Savic <savicaleksa83@gmail.com>
  • Loading branch information
aleksamagicka committed Aug 7, 2023
1 parent 1af0c22 commit 2b77bbe
Showing 1 changed file with 36 additions and 1 deletion.
37 changes: 36 additions & 1 deletion aquacomputer_d5next.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@

#include <linux/crc16.h>
#include <linux/debugfs.h>
#include <linux/delay.h>
#include <linux/hid.h>
#include <linux/hwmon.h>
#include <linux/jiffies.h>
#include <linux/ktime.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/seq_file.h>
Expand Down Expand Up @@ -63,6 +65,8 @@ static const char *const aqc_device_names[] = {
#define CTRL_REPORT_ID 0x03
#define AQUAERO_CTRL_REPORT_ID 0x0b

#define CTRL_REPORT_DELAY 200 /* ms */

/* The HID report that the official software always sends
* after writing values, currently same for all devices
*/
Expand Down Expand Up @@ -527,6 +531,9 @@ struct aqc_data {
int secondary_ctrl_report_size;
u8 *secondary_ctrl_report;

ktime_t last_ctrl_report_op;
int ctrl_report_delay; /* Delay between two ctrl report operations, in ms */

int buffer_size;
u8 *buffer;
int checksum_start;
Expand Down Expand Up @@ -611,17 +618,35 @@ static int aqc_aquastreamxt_convert_fan_rpm(u16 val)
return 0;
}

static void aqc_delay_ctrl_report(struct aqc_data *priv)
{
/*
* If previous read or write is too close to this one, delay the current operation
* to give the device enough time to process the previous one.
*/
if (priv->ctrl_report_delay) {
s64 delta = ktime_ms_delta(ktime_get(), priv->last_ctrl_report_op);

if (delta < priv->ctrl_report_delay)
msleep(priv->ctrl_report_delay - delta);
}
}

/* Expects the mutex to be locked */
static int aqc_get_ctrl_data(struct aqc_data *priv)
{
int ret;

aqc_delay_ctrl_report(priv);

memset(priv->buffer, 0x00, priv->buffer_size);
ret = hid_hw_raw_request(priv->hdev, priv->ctrl_report_id, priv->buffer, priv->buffer_size,
HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
if (ret < 0)
ret = -ENODATA;

priv->last_ctrl_report_op = ktime_get();

return ret;
}

Expand All @@ -631,6 +656,8 @@ static int aqc_send_ctrl_data(struct aqc_data *priv)
int ret;
u16 checksum;

aqc_delay_ctrl_report(priv);

/* Checksum is not needed for Aquaero */
if (priv->kind != aquaero) {
/* Init and xorout value for CRC-16/USB is 0xffff */
Expand All @@ -646,12 +673,16 @@ static int aqc_send_ctrl_data(struct aqc_data *priv)
ret = hid_hw_raw_request(priv->hdev, priv->ctrl_report_id, priv->buffer, priv->buffer_size,
HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
if (ret < 0)
return ret;
goto record_access_and_ret;

/* The official software sends this report after every change, so do it here as well */
ret = hid_hw_raw_request(priv->hdev, priv->secondary_ctrl_report_id,
priv->secondary_ctrl_report, priv->secondary_ctrl_report_size,
HID_FEATURE_REPORT, HID_REQ_SET_REPORT);

record_access_and_ret:
priv->last_ctrl_report_op = ktime_get();

return ret;
}

Expand Down Expand Up @@ -1524,6 +1555,7 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id)

priv->buffer_size = AQUAERO_CTRL_REPORT_SIZE;
priv->temp_ctrl_offset = AQUAERO_TEMP_CTRL_OFFSET;
priv->ctrl_report_delay = CTRL_REPORT_DELAY;

priv->temp_label = label_temp_sensors;
priv->virtual_temp_label = label_virtual_temp_sensors;
Expand All @@ -1547,6 +1579,7 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id)
priv->temp_ctrl_offset = D5NEXT_TEMP_CTRL_OFFSET;

priv->buffer_size = D5NEXT_CTRL_REPORT_SIZE;
priv->ctrl_report_delay = CTRL_REPORT_DELAY;

priv->power_cycle_count_offset = D5NEXT_POWER_CYCLES;

Expand Down Expand Up @@ -1597,6 +1630,7 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id)
priv->temp_ctrl_offset = OCTO_TEMP_CTRL_OFFSET;

priv->buffer_size = OCTO_CTRL_REPORT_SIZE;
priv->ctrl_report_delay = CTRL_REPORT_DELAY;

priv->power_cycle_count_offset = OCTO_POWER_CYCLES;

Expand Down Expand Up @@ -1624,6 +1658,7 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id)
priv->temp_ctrl_offset = QUADRO_TEMP_CTRL_OFFSET;

priv->buffer_size = QUADRO_CTRL_REPORT_SIZE;
priv->ctrl_report_delay = CTRL_REPORT_DELAY;

priv->flow_pulses_ctrl_offset = QUADRO_FLOW_PULSES_CTRL_OFFSET;
priv->power_cycle_count_offset = QUADRO_POWER_CYCLES;
Expand Down

0 comments on commit 2b77bbe

Please sign in to comment.