allow settings to be bound to certain device types
avoids stuff like smooth-scroll being attached to a keyboard
This commit is contained in:
parent
daad9b5d5f
commit
c464e049bf
|
@ -27,25 +27,31 @@ _FN_SWAP = ('fn-swap', 'Swap Fx function',
|
||||||
# using Features
|
# using Features
|
||||||
def _register_fn_swap(register=0x09, true_value=b'\x00\x01', mask=b'\x00\x01'):
|
def _register_fn_swap(register=0x09, true_value=b'\x00\x01', mask=b'\x00\x01'):
|
||||||
return _settings.register_toggle(_FN_SWAP[0], register, true_value=true_value, mask=mask,
|
return _settings.register_toggle(_FN_SWAP[0], register, true_value=true_value, mask=mask,
|
||||||
label=_FN_SWAP[1], description=_FN_SWAP[2])
|
label=_FN_SWAP[1], description=_FN_SWAP[2],
|
||||||
|
device_kind=_hidpp10.DEVICE_KIND.keyboard)
|
||||||
|
|
||||||
def _register_smooth_scroll(register=0x01, true_value=0x40, mask=0x40):
|
def _register_smooth_scroll(register=0x01, true_value=0x40, mask=0x40):
|
||||||
return _settings.register_toggle(_SMOOTH_SCROLL[0], register, true_value=true_value, mask=mask,
|
return _settings.register_toggle(_SMOOTH_SCROLL[0], register, true_value=true_value, mask=mask,
|
||||||
label=_SMOOTH_SCROLL[1], description=_SMOOTH_SCROLL[2])
|
label=_SMOOTH_SCROLL[1], description=_SMOOTH_SCROLL[2],
|
||||||
|
device_kind=_hidpp10.DEVICE_KIND.mouse)
|
||||||
|
|
||||||
|
|
||||||
|
_PERFORMANCE_MX_DPIS = _NamedInts.range(0x81, 0x8F, lambda x: str((x - 0x80) * 100))
|
||||||
def _register_dpi(register=0x63, choices=None):
|
def _register_dpi(register=0x63, choices=None):
|
||||||
return _settings.register_choices(_DPI[0], register, choices,
|
return _settings.register_choices(_DPI[0], register, choices,
|
||||||
label=_DPI[1], description=_DPI[2])
|
label=_DPI[1], description=_DPI[2],
|
||||||
|
device_kind=_hidpp10.DEVICE_KIND.mouse)
|
||||||
|
|
||||||
|
|
||||||
def _feature_fn_swap():
|
def _feature_fn_swap():
|
||||||
return _settings.feature_toggle(_FN_SWAP[0], _hidpp20.FEATURE.FN_INVERSION,
|
return _settings.feature_toggle(_FN_SWAP[0], _hidpp20.FEATURE.FN_INVERSION,
|
||||||
write_returns_value=True,
|
write_returns_value=True,
|
||||||
label=_FN_SWAP[1], description=_FN_SWAP[2])
|
label=_FN_SWAP[1], description=_FN_SWAP[2],
|
||||||
|
device_kind=_hidpp10.DEVICE_KIND.keyboard)
|
||||||
|
|
||||||
|
|
||||||
def check_features(device, already_known):
|
def check_features(device, already_known):
|
||||||
|
"""Try to auto-detect device settings by the HID++ 2.0 features they have."""
|
||||||
if device.protocol is not None and device.protocol < 2.0:
|
if device.protocol is not None and device.protocol < 2.0:
|
||||||
return
|
return
|
||||||
if not any(s.name == _FN_SWAP[0] for s in already_known) and _hidpp20.FEATURE.FN_INVERSION in device.features:
|
if not any(s.name == _FN_SWAP[0] for s in already_known) and _hidpp20.FEATURE.FN_INVERSION in device.features:
|
||||||
|
@ -72,7 +78,7 @@ def _D(name, codename=None, kind=None, product_id=None, protocol=None, registers
|
||||||
assert kind is not None, "descriptor for %s does not have 'kind' set" % name
|
assert kind is not None, "descriptor for %s does not have 'kind' set" % name
|
||||||
|
|
||||||
# heuristic: the codename is the last word in the device name
|
# heuristic: the codename is the last word in the device name
|
||||||
if codename is None:
|
if codename is None and ' ' in name:
|
||||||
codename = name.split(' ')[-1]
|
codename = name.split(' ')[-1]
|
||||||
assert codename is not None, "descriptor for %s does not have codename set" % name
|
assert codename is not None, "descriptor for %s does not have codename set" % name
|
||||||
|
|
||||||
|
@ -196,7 +202,7 @@ _D('Anywhere Mouse MX', codename='Anywhere MX')
|
||||||
_D('Performance Mouse MX', codename='Performance MX', protocol=1.0,
|
_D('Performance Mouse MX', codename='Performance MX', protocol=1.0,
|
||||||
registers={'battery_charge': -0x0D, 'battery_status': 0x07, 'leds': 0x51},
|
registers={'battery_charge': -0x0D, 'battery_status': 0x07, 'leds': 0x51},
|
||||||
settings=[
|
settings=[
|
||||||
_register_dpi(choices=_NamedInts.range(0x81, 0x8F, lambda x: str((x - 0x80) * 100))),
|
_register_dpi(choices=_PERFORMANCE_MX_DPIS),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -16,14 +16,17 @@ from .common import NamedInt as _NamedInt, NamedInts as _NamedInts
|
||||||
KIND = _NamedInts(toggle=0x1, choice=0x02, range=0x12)
|
KIND = _NamedInts(toggle=0x1, choice=0x02, range=0x12)
|
||||||
|
|
||||||
class _Setting(object):
|
class _Setting(object):
|
||||||
__slots__ = ['name', 'label', 'description', 'kind', 'persister',
|
"""A setting descriptor.
|
||||||
|
Needs to be instantiated for each specific device."""
|
||||||
|
__slots__ = ['name', 'label', 'description', 'kind', 'persister', 'device_kind',
|
||||||
'_rw', '_validator', '_device', '_value']
|
'_rw', '_validator', '_device', '_value']
|
||||||
|
|
||||||
def __init__(self, name, rw, validator, kind=None, label=None, description=None):
|
def __init__(self, name, rw, validator, kind=None, label=None, description=None, device_kind=None):
|
||||||
assert name
|
assert name
|
||||||
self.name = name
|
self.name = name
|
||||||
self.label = label or name
|
self.label = label or name
|
||||||
self.description = description
|
self.description = description
|
||||||
|
self.device_kind = device_kind
|
||||||
|
|
||||||
self._rw = rw
|
self._rw = rw
|
||||||
self._validator = validator
|
self._validator = validator
|
||||||
|
@ -34,6 +37,7 @@ class _Setting(object):
|
||||||
|
|
||||||
def __call__(self, device):
|
def __call__(self, device):
|
||||||
assert not hasattr(self, '_value')
|
assert not hasattr(self, '_value')
|
||||||
|
assert self.device_kind is None or self.device_kind == device.kind
|
||||||
o = _copy(self)
|
o = _copy(self)
|
||||||
o._value = None
|
o._value = None
|
||||||
o._device = device # _proxy(device)
|
o._device = device # _proxy(device)
|
||||||
|
@ -213,26 +217,26 @@ class _ChoicesValidator(object):
|
||||||
def register_toggle(name, register,
|
def register_toggle(name, register,
|
||||||
true_value=_BooleanValidator.default_true, false_value=_BooleanValidator.default_false,
|
true_value=_BooleanValidator.default_true, false_value=_BooleanValidator.default_false,
|
||||||
mask=_BooleanValidator.default_mask, write_returns_value=False,
|
mask=_BooleanValidator.default_mask, write_returns_value=False,
|
||||||
label=None, description=None):
|
label=None, description=None, device_kind=None):
|
||||||
rw = _RegisterRW(register)
|
rw = _RegisterRW(register)
|
||||||
validator = _BooleanValidator(true_value=true_value, false_value=false_value, mask=mask, write_returns_value=write_returns_value)
|
validator = _BooleanValidator(true_value=true_value, false_value=false_value, mask=mask, write_returns_value=write_returns_value)
|
||||||
return _Setting(name, rw, validator, label=label, description=description)
|
return _Setting(name, rw, validator, label=label, description=description, device_kind=device_kind)
|
||||||
|
|
||||||
|
|
||||||
def register_choices(name, register, choices,
|
def register_choices(name, register, choices,
|
||||||
kind=KIND.choice, write_returns_value=False,
|
kind=KIND.choice, write_returns_value=False,
|
||||||
label=None, description=None):
|
label=None, description=None, device_kind=None):
|
||||||
assert choices
|
assert choices
|
||||||
rw = _RegisterRW(register)
|
rw = _RegisterRW(register)
|
||||||
validator = _ChoicesValidator(choices, write_returns_value=write_returns_value)
|
validator = _ChoicesValidator(choices, write_returns_value=write_returns_value)
|
||||||
return _Setting(name, rw, validator, kind=kind, label=label, description=description)
|
return _Setting(name, rw, validator, kind=kind, label=label, description=description, device_kind=device_kind)
|
||||||
|
|
||||||
|
|
||||||
def feature_toggle(name, feature,
|
def feature_toggle(name, feature,
|
||||||
read_function_id=_FeatureRW.default_read_fnid, write_function_id=_FeatureRW.default_write_fnid,
|
read_function_id=_FeatureRW.default_read_fnid, write_function_id=_FeatureRW.default_write_fnid,
|
||||||
true_value=_BooleanValidator.default_true, false_value=_BooleanValidator.default_false,
|
true_value=_BooleanValidator.default_true, false_value=_BooleanValidator.default_false,
|
||||||
mask=_BooleanValidator.default_mask, write_returns_value=False,
|
mask=_BooleanValidator.default_mask, write_returns_value=False,
|
||||||
label=None, description=None):
|
label=None, description=None, device_kind=None):
|
||||||
rw = _FeatureRW(feature, read_function_id, write_function_id)
|
rw = _FeatureRW(feature, read_function_id, write_function_id)
|
||||||
validator = _BooleanValidator(true_value=true_value, false_value=false_value, mask=mask, write_returns_value=write_returns_value)
|
validator = _BooleanValidator(true_value=true_value, false_value=false_value, mask=mask, write_returns_value=write_returns_value)
|
||||||
return _Setting(name, rw, validator, label=label, description=description)
|
return _Setting(name, rw, validator, label=label, description=description, device_kind=device_kind)
|
||||||
|
|
Loading…
Reference in New Issue