allow settings to be bound to certain device types

avoids stuff like smooth-scroll being attached to a keyboard
This commit is contained in:
Daniel Pavel 2013-06-29 20:54:06 +02:00
parent daad9b5d5f
commit c464e049bf
2 changed files with 24 additions and 14 deletions

View File

@ -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),
], ],
) )

View File

@ -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)