corsair_hid_psu: read exactly 4 bytes for timedeltas

The response from the device may contain non-nil bytes beyond the range
applicable to the command being replied to.

This is generally taken care of by LINEAR11, ULINEAR16, or when reading
a single byte. However, as we weren't sure how many bytes could actually
be returned by _get_timedelta, it was allowed to try and parse the
entire response as an integer.

That was fine since we were reading with little endianess, and no
devices were known that actually send extra non-nil bytes. That has
changed with the H1500i: only 4 bytes can be safely read from the
response.

Fix _get_timedelta with this new information.

Fixes: #575
Fixes: 64523ef337
This commit is contained in:
Jonas Malaco 2023-02-26 15:23:18 -03:00
parent dd2d1c1cf1
commit 2dd235e536
2 changed files with 5 additions and 3 deletions

View File

@ -306,7 +306,7 @@ class CorsairHidPsu(UsbHidDriver):
def _get_timedelta(self, command):
"""Get timedelta with `command`."""
secs = int.from_bytes(self._exec(WriteBit.READ, command)[2:], byteorder='little')
secs = int.from_bytes(self._exec(WriteBit.READ, command)[2:6], byteorder='little')
return timedelta(seconds=secs)
def set_screen(self, channel, mode, value, **kwargs):

View File

@ -45,9 +45,11 @@ SAMPLE_RESPONSES = [
'fe03524d3130303069',
# https://github.com/liquidctl/liquidctl/pull/54#issuecomment-543760522
'03d29215',
'03d1224711',
# https://github.com/liquidctl/liquidctl/issues/575#issue-1600123046
'03d213c60000414952204858313530306920505355', # with extra non-nil bytes
# artificial
'0390c803',
'03f001',
@ -127,7 +129,7 @@ def test_reads_status_directly(mock_psu, has_hwmon, direct_access):
got = mock_psu.get_status(direct_access=direct_access)
expected = [
('Current uptime', timedelta(seconds=5522), ''),
('Current uptime', timedelta(seconds=50707), ''),
('Total uptime', timedelta(days=13, seconds=9122), ''),
('VRM temperature', approx(33.5, rel=1e-3), '°C'),
('Case temperature', approx(26.5, rel=1e-3), '°C'),