device: limited support for extended adjustable dpi
This commit is contained in:
parent
c70e8b54bf
commit
ab94f1be07
|
@ -738,7 +738,7 @@ class ReprogrammableKeys(_Settings):
|
||||||
|
|
||||||
class DpiSlidingXY(_RawXYProcessing):
|
class DpiSlidingXY(_RawXYProcessing):
|
||||||
def activate_action(self):
|
def activate_action(self):
|
||||||
self.dpiSetting = next(filter(lambda s: s.name == "dpi", self.device.settings), None)
|
self.dpiSetting = next(filter(lambda s: s.name == "dpi" or s.name == "dpi_extended", self.device.settings), None)
|
||||||
self.dpiChoices = list(self.dpiSetting.choices)
|
self.dpiChoices = list(self.dpiSetting.choices)
|
||||||
self.otherDpiIdx = self.device.persister.get("_dpi-sliding", -1) if self.device.persister else -1
|
self.otherDpiIdx = self.device.persister.get("_dpi-sliding", -1) if self.device.persister else -1
|
||||||
if not isinstance(self.otherDpiIdx, int) or self.otherDpiIdx < 0 or self.otherDpiIdx >= len(self.dpiChoices):
|
if not isinstance(self.otherDpiIdx, int) or self.otherDpiIdx < 0 or self.otherDpiIdx >= len(self.dpiChoices):
|
||||||
|
@ -801,7 +801,7 @@ class DpiSlidingXY(_RawXYProcessing):
|
||||||
|
|
||||||
class MouseGesturesXY(_RawXYProcessing):
|
class MouseGesturesXY(_RawXYProcessing):
|
||||||
def activate_action(self):
|
def activate_action(self):
|
||||||
self.dpiSetting = next(filter(lambda s: s.name == "dpi", self.device.settings), None)
|
self.dpiSetting = next(filter(lambda s: s.name == "dpi" or s.name == "dpi_extended", self.device.settings), None)
|
||||||
self.fsmState = "idle"
|
self.fsmState = "idle"
|
||||||
self.initialize_data()
|
self.initialize_data()
|
||||||
|
|
||||||
|
@ -936,35 +936,66 @@ class AdjustableDpi(_Setting):
|
||||||
"""Pointer Speed feature"""
|
"""Pointer Speed feature"""
|
||||||
|
|
||||||
# Assume sensorIdx 0 (there is only one sensor)
|
# Assume sensorIdx 0 (there is only one sensor)
|
||||||
# [2] getSensorDpi(sensorIdx) -> sensorIdx, dpiMSB, dpiLSB
|
|
||||||
# [3] setSensorDpi(sensorIdx, dpi)
|
|
||||||
name = "dpi"
|
name = "dpi"
|
||||||
label = _("Sensitivity (DPI)")
|
label = _("Sensitivity (DPI)")
|
||||||
description = _("Mouse movement sensitivity")
|
description = _("Mouse movement sensitivity")
|
||||||
feature = _F.ADJUSTABLE_DPI
|
feature = _F.ADJUSTABLE_DPI
|
||||||
rw_options = {"read_fnid": 0x20, "write_fnid": 0x30}
|
rw_options = {"read_fnid": 0x20, "write_fnid": 0x30}
|
||||||
choices_universe = _NamedInts.range(200, 4000, str, 50)
|
choices_universe = _NamedInts.range(100, 4000, str, 50)
|
||||||
|
sensor_list_function = 0x10
|
||||||
|
sensor_list_bytes_ignore = 1
|
||||||
|
|
||||||
class validator_class(_ChoicesV):
|
class validator_class(_ChoicesV):
|
||||||
@classmethod
|
@staticmethod
|
||||||
def build(cls, setting_class, device):
|
def produce_dpi_list(setting_class, device, direction):
|
||||||
# [1] getSensorDpiList(sensorIdx)
|
reply = device.feature_request(setting_class.feature, setting_class.sensor_list_function, 0x00, direction, 0x00)
|
||||||
reply = device.feature_request(_F.ADJUSTABLE_DPI, 0x10)
|
|
||||||
assert reply, "Oops, DPI list cannot be retrieved!"
|
assert reply, "Oops, DPI list cannot be retrieved!"
|
||||||
|
dpi_bytes = reply[setting_class.sensor_list_bytes_ignore :]
|
||||||
|
i = 1
|
||||||
|
while dpi_bytes[-2:] != b"\x00\x00":
|
||||||
|
reply = device.feature_request(setting_class.feature, setting_class.sensor_list_function, 0x00, direction, i)
|
||||||
|
assert reply, "Oops, DPI list cannot be retrieved!"
|
||||||
|
dpi_bytes += reply[setting_class.sensor_list_bytes_ignore :]
|
||||||
|
i += 1
|
||||||
dpi_list = []
|
dpi_list = []
|
||||||
step = None
|
i = 0
|
||||||
for val in _unpack("!7H", reply[1 : 1 + 14]):
|
while i < len(dpi_bytes):
|
||||||
|
val = _bytes2int(dpi_bytes[i : i + 2])
|
||||||
if val == 0:
|
if val == 0:
|
||||||
break
|
break
|
||||||
if val >> 13 == 0b111:
|
if val >> 13 == 0b111:
|
||||||
assert step is None and len(dpi_list) == 1, f"Invalid DPI list item: {val!r}"
|
|
||||||
step = val & 0x1FFF
|
step = val & 0x1FFF
|
||||||
|
last = _bytes2int(dpi_bytes[i + 2 : i + 4])
|
||||||
|
assert len(dpi_list) > 0 and last > dpi_list[-1], f"Invalid DPI list item: {val!r}"
|
||||||
|
dpi_list += range(dpi_list[-1] + step, last + 1, step)
|
||||||
|
i += 4
|
||||||
else:
|
else:
|
||||||
dpi_list.append(val)
|
dpi_list.append(val)
|
||||||
if step:
|
i += 2
|
||||||
assert len(dpi_list) == 2, f"Invalid DPI list range: {dpi_list!r}"
|
return dpi_list
|
||||||
dpi_list = range(dpi_list[0], dpi_list[1] + 1, step)
|
|
||||||
return cls(choices=_NamedInts.list(dpi_list), byte_count=3) if dpi_list else None
|
@classmethod
|
||||||
|
def build(cls, setting_class, device):
|
||||||
|
y = False
|
||||||
|
if setting_class.feature == _F.EXTENDED_ADJUSTABLE_DPI:
|
||||||
|
reply = device.feature_request(setting_class.feature, 0x10, 0x00)
|
||||||
|
y = reply[2] & 0x01
|
||||||
|
reply = device.feature_request(setting_class.feature, setting_class.sensor_list_function, 0x00, 0x00, 0x00)
|
||||||
|
assert reply, "Oops, DPI list cannot be retrieved!"
|
||||||
|
dpilist_x = cls.produce_dpi_list(setting_class, device, 0)
|
||||||
|
dpilist_y = cls.produce_dpi_list(setting_class, device, 1) if y else []
|
||||||
|
print("DPY LIST X", dpilist_x)
|
||||||
|
print("DPY LIST Y", dpilist_y)
|
||||||
|
setting = cls(choices=_NamedInts.list(dpilist_x), byte_count=2, write_prefix_bytes=b"\x00") if dpilist_x else None
|
||||||
|
setting.y = y
|
||||||
|
return setting
|
||||||
|
|
||||||
|
def prepare_write(self, new_value, current_value=None):
|
||||||
|
data_bytes = super().prepare_write(new_value, current_value)
|
||||||
|
if self.y:
|
||||||
|
bytes = data_bytes[len(self._write_prefix_bytes) :]
|
||||||
|
data_bytes = self._write_prefix_bytes + bytes + bytes
|
||||||
|
return data_bytes
|
||||||
|
|
||||||
def validate_read(self, reply_bytes): # special validator to use default DPI if needed
|
def validate_read(self, reply_bytes): # special validator to use default DPI if needed
|
||||||
reply_value = _bytes2int(reply_bytes[1:3])
|
reply_value = _bytes2int(reply_bytes[1:3])
|
||||||
|
@ -975,6 +1006,16 @@ class AdjustableDpi(_Setting):
|
||||||
return valid_value
|
return valid_value
|
||||||
|
|
||||||
|
|
||||||
|
class ExtendedAdjustableDpi(AdjustableDpi):
|
||||||
|
# the extended version allows for two dimensions, longer dpi descriptions
|
||||||
|
# still assume only one sensor (and X only?)
|
||||||
|
name = "dpi_extended"
|
||||||
|
feature = _F.EXTENDED_ADJUSTABLE_DPI
|
||||||
|
rw_options = {"read_fnid": 0x50, "write_fnid": 0x60}
|
||||||
|
sensor_list_function = 0x20
|
||||||
|
sensor_list_bytes_ignore = 3
|
||||||
|
|
||||||
|
|
||||||
class SpeedChange(_Setting):
|
class SpeedChange(_Setting):
|
||||||
"""Implements the ability to switch Sensitivity by clicking on the DPI_Change button."""
|
"""Implements the ability to switch Sensitivity by clicking on the DPI_Change button."""
|
||||||
|
|
||||||
|
@ -1632,6 +1673,7 @@ SETTINGS = [
|
||||||
ExtendedReportRate,
|
ExtendedReportRate,
|
||||||
PointerSpeed, # simple
|
PointerSpeed, # simple
|
||||||
AdjustableDpi, # working
|
AdjustableDpi, # working
|
||||||
|
ExtendedAdjustableDpi,
|
||||||
SpeedChange,
|
SpeedChange,
|
||||||
# Backlight, # not working - disabled temporarily
|
# Backlight, # not working - disabled temporarily
|
||||||
Backlight2, # working
|
Backlight2, # working
|
||||||
|
|
Loading…
Reference in New Issue