Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for setting fan speed for D5 Next #499

Merged
merged 33 commits into from
Sep 21, 2022

Conversation

aleksamagicka
Copy link
Member

@aleksamagicka aleksamagicka commented Aug 28, 2022

Add support for setting pump and fan speed for the D5 Next pump in the aquacomputer.py driver.

I had to use the crcmod library to calculate CRC-16/USB checksums, because the control HID report (that contains all the settings for a device) has one at the end and it needs to be updated when the settings are changed. Please let me know if I missed adding it somewhere.

Also I wanted to ask if it's OK to utilize the hwmon driver for writing stuff to the device. I don't really see than being done in other drivers, so maybe --use-hwmon can be passed in here to let the user go through the kernel driver?

Related: #439


Checklist:

  • Adhere to the development process
  • Conform to the style guide
  • Verify that the changes work as expected on real hardware
  • Add automated tests cases
  • Verify that all (other) automated tests (still) pass
  • Update the README and other applicable documentation pages
  • Update the liquidctl.8 Linux/Unix/Mac OS man page
  • Update or add applicable docs/*guide.md device guides
  • Submit relevant data, scripts or dissectors to https://github.com/liquidctl/collected-device-data

New CLI flag?

  • Adjust the completion scripts in extra/completions/

New device?

  • Regenerate extra/linux/71-liquidctl.rules (instructions in the file header)
  • Add entry to the README's supported device list with applicable notes (at least en)

New driver?

  • Document the protocol in docs/developer/protocol/

@aleksamagicka aleksamagicka marked this pull request as ready for review August 29, 2022 07:43
@jonasmalacofilho
Copy link
Member

Sorry again for the delay.

Also I wanted to ask if it's OK to utilize the hwmon driver for writing stuff to the device.

Yes, and it should actually be preferred (when there's a hwmon driver).

I don't really see than being done in other drivers,

That's mostly just because hwmon support in liquidctl is new and not yet complete, but also because not all current hwmon drivers expose PWM control (e.g. Kraken X2, because of device/protocol issues, or Corsair RMi/HXi, due to safety concerns, IIRC).

so maybe --use-hwmon can be passed in here to let the user go through the kernel driver?

No, I think it should be the other way around, just as with get_status(): the hwmon driver is used by default, unless --direct-access is passed.

Besides being more consistent, this minimizes the chances of putting either the device or the kernel driver in a inconsistent/unexpected state.

@aleksamagicka
Copy link
Member Author

Great, thanks. I'll rework it to use hwmon first, if possible.

@aleksamagicka
Copy link
Member Author

Writing to hwmon is now implemented in the aquacomputer driver, please take a look.

Copy link
Member

@jonasmalacofilho jonasmalacofilho left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

Comment on lines 51 to 53
Valid channel values on the D5 Next are `pump` and `fan`. The hwmon driver is always used first, if it's available and
exposes `pwmX` and `pwmX_enable` attributes. You can pass in `--direct-access` to bypass it and communicate with the
device directly.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it's necessary to talk about hwmon here, especially since the very next section is about it (and how to bypass it).

liquidctl.8 Outdated
@@ -236,7 +236,7 @@ Internal data used by some drivers.
.SS Aquacomputer Farbwerk 360
.SS Aquacomputer Octo
.SS Aquacomputer Quadro
Cooling channels: (D5 Next, Octo, Quadro:) not yet supported; (Farbwerk 360:) not applicable.
Cooling channels: (D5 Next): supported, (Octo, Quadro:) not yet supported; (Farbwerk 360:) not applicable.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Cooling channels: (D5 Next): supported, (Octo, Quadro:) not yet supported; (Farbwerk 360:) not applicable.
Cooling channels: (D5 Next): \fIfan\fR, \fIpump\fR; (Octo, Quadro:) not yet supported; (Farbwerk 360:) not applicable.

_LOGGER.info(
"bound to %s kernel driver, writing fixed speed to hwmon", self._hwmon.driver
)
return self._set_fixed_speed_hwmon(channel, duty)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will fail if the hwmon driver is present, but doesn't expose the necessary PWM attributes.

I think we should instead automatically fallback to direct access in that case.

Comment on lines 424 to 426
_LOGGER.warning(
"directly writing fixed speed despite %s kernel driver", self._hwmon.driver
)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Related to the previous comment, in my opinion a warning is only necessary if we're re-implementing (and possibly conflicting with) something the kernel driver actually supports/exposes.

Comment on lines 38 to 39
def write_str(self, name, value):
(self.path / name).write_text(value)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For symmetry, I think a write_int API would be better, and move the str() conversion within it.

On a related note, it would also probably make sense to rename get_int to read_int, also for symmetry.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since renaming get_int to read_int touches more drivers than aquacomputer.py, do you want me to create a separate PR right after this one or do it here?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right, that would be better.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will do!

def test_d5next_set_fixed_speeds_not_supported(mockD5NextDevice):
with pytest.raises(NotSupportedByDriver):
mockD5NextDevice.set_fixed_speed("fan", 42)
def test_d5next_set_fixed_speeds_directly(mockD5NextDevice):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similarly to test_d5next_get_status_directly, this should also test whether --direct-access is honored, even if a (complete) hwmon driver is present.

But I do see how this might be getting a bit repetitive/annoying.

assert pump_report.data[0x95:0x98] == [0, 32, 208] # 0, <8400>


def test_d5next_set_fixed_speeds_hwmon(mockD5NextDevice, tmp_path):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be wise to also test whether the fallback to direct mode when the PWM attributes are missing.

@jonasmalacofilho
Copy link
Member

Since crcmod is stable but not actively maintained, let's exceptionally pin its required version to 1.7.

# on setup.cfg, .github/workflows/*.yml, README.md, etc:
crcmod == 1.7

I usually don't do this type of thing in order to avoid issues with distro-supplied packages. But in this case we really don't expect to see a new version, and I'm not super comfortable leaving a highly popular but potentially1 neglected dependency unpinned.

Footnotes

  1. I don't know the crcmod developers. It's perfectly possible that they are active and super careful, and that crcmod simply hasn't needed any change in the last decade. However, I couldn't immediately assert that's indeed the case, and pinning this one dependency should be nearly painless... after all, it hasn't received any intentional updates in more than a decade.

@aleksamagicka
Copy link
Member Author

Thanks for the review, things you mentioned should be fixed now, except the get_int to read_int conversion.

@jonasmalacofilho jonasmalacofilho merged commit a81c9b5 into liquidctl:main Sep 21, 2022
@jonasmalacofilho
Copy link
Member

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants