settings: handle PERSISTENT REMAPPABLE ACTION for M720 mouse

This commit is contained in:
Peter F. Patel-Schneider 2022-03-10 06:10:56 -05:00
parent 4c7f8c831b
commit 484b097664
3 changed files with 104 additions and 61 deletions

View File

@ -587,21 +587,21 @@ class PersistentRemappableAction():
elif self.actionId == special_keys.ACTIONID.Key: elif self.actionId == special_keys.ACTIONID.Key:
return 'Key: ' + str(self.modifiers) + str(self.remapped) return 'Key: ' + str(self.modifiers) + str(self.remapped)
elif self.actionId == special_keys.ACTIONID.Mouse: elif self.actionId == special_keys.ACTIONID.Mouse:
return 'Mouse Button' return 'Mouse Button: ' + str(self.remapped)
elif self.actionId == special_keys.ACTIONID.Xdisp: elif self.actionId == special_keys.ACTIONID.Xdisp:
return 'X Displacement' return 'X Displacement ' + str(self.remapped)
elif self.actionId == special_keys.ACTIONID.Ydisp: elif self.actionId == special_keys.ACTIONID.Ydisp:
return 'Y Displacement' return 'Y Displacement ' + str(self.remapped)
elif self.actionId == special_keys.ACTIONID.Vscroll: elif self.actionId == special_keys.ACTIONID.Vscroll:
return 'Vertical Scroll' return 'Vertical Scroll ' + str(self.remapped)
elif self.actionId == special_keys.ACTIONID.Hscroll: elif self.actionId == special_keys.ACTIONID.Hscroll:
return 'Horizontal Scroll' return 'Horizontal Scroll: ' + str(self.remapped)
elif self.actionId == special_keys.ACTIONID.Consumer: elif self.actionId == special_keys.ACTIONID.Consumer:
return 'Consumer: ' + str(self.remapped) return 'Consumer: ' + str(self.remapped)
elif self.actionId == special_keys.ACTIONID.Internal: elif self.actionId == special_keys.ACTIONID.Internal:
return 'Internal Action' return 'Internal Action ' + str(self.remapped)
elif self.actionId == special_keys.ACTIONID.Internal: elif self.actionId == special_keys.ACTIONID.Internal:
return 'Power' return 'Power ' + str(self.remapped)
else: else:
return 'Unknown' return 'Unknown'
@ -781,6 +781,8 @@ class KeysArrayPersistent(KeysArray):
remapped = special_keys.USB_HID_KEYCODES[remapped] remapped = special_keys.USB_HID_KEYCODES[remapped]
elif actionId == special_keys.ACTIONID.Mouse: elif actionId == special_keys.ACTIONID.Mouse:
remapped = special_keys.MOUSE_BUTTONS[remapped] remapped = special_keys.MOUSE_BUTTONS[remapped]
elif actionId == special_keys.ACTIONID.Hscroll:
remapped = special_keys.HORIZONTAL_SCROLL[remapped]
elif actionId == special_keys.ACTIONID.Consumer: elif actionId == special_keys.ACTIONID.Consumer:
remapped = special_keys.HID_CONSUMERCODES[remapped] remapped = special_keys.HID_CONSUMERCODES[remapped]
self.keys[index] = PersistentRemappableAction(self.device, index, key, actionId, remapped, modifiers, status) self.keys[index] = PersistentRemappableAction(self.device, index, key, actionId, remapped, modifiers, status)

View File

@ -18,6 +18,7 @@
from logging import DEBUG as _DEBUG from logging import DEBUG as _DEBUG
from logging import INFO as _INFO from logging import INFO as _INFO
from logging import WARN as _WARN
from logging import getLogger from logging import getLogger
from time import time as _time from time import time as _time
@ -1042,7 +1043,8 @@ class MRKeyLED(_Setting):
return b'\x00' return b'\x00'
## Only implemented for devices that can produce HID and Consumer Key Codes ## Only implemented for devices that can produce Key and Consumer Codes (e.g., Craft)
## and devices that can produce Key, Mouse, and Horizontal Scroll (e.g., M720)
## Only interested in current host, so use 0xFF for it ## Only interested in current host, so use 0xFF for it
class PersistentRemappableAction(_Settings): class PersistentRemappableAction(_Settings):
name = 'persistent-remappable-keys' name = 'persistent-remappable-keys'
@ -1074,12 +1076,21 @@ class PersistentRemappableAction(_Settings):
@classmethod @classmethod
def build(cls, setting_class, device): def build(cls, setting_class, device):
remap_keys = device.remap_keys remap_keys = device.remap_keys
if not remap_keys or not device.remap_keys.capabilities & 0x0041 == 0x0041: # HID and Consumer Key Codes if not remap_keys:
return None
capabilities = device.remap_keys.capabilities
if capabilities & 0x0041 == 0x0041: # Key and Consumer Codes
keys = _special_keys.KEYS_KEYS_CONSUMER
elif capabilities & 0x0023 == 0x0023: # Key, Mouse, and HScroll Codes
keys = _special_keys.KEYS_KEYS_MOUSE_HSCROLL
else:
if _log.isEnabledFor(_WARN):
_log.warn('%s: unimplemented Persistent Remappable capability %s', device.name, hex(capabilities))
return None return None
choices = {} choices = {}
for k in remap_keys: for k in remap_keys:
key = _special_keys.CONTROL[k.key] key = _special_keys.CONTROL[k.key]
choices[key] = _special_keys.KEYS choices[key] = keys # TO RECOVER FROM BAD VALUES use _special_keys.KEYS
return cls(choices, key_byte_count=2, byte_count=4) if choices else None return cls(choices, key_byte_count=2, byte_count=4) if choices else None

View File

@ -597,34 +597,6 @@ DISABLE = _NamedInts(
) )
DISABLE._fallback = lambda x: 'unknown:%02X' % x DISABLE._fallback = lambda x: 'unknown:%02X' % x
##
## Information for x1c00 Persistent from https://drive.google.com/drive/folders/0BxbRzx7vEV7eWmgwazJ3NUFfQ28
##
KEYMOD = _NamedInts(CTRL=0x01, SHIFT=0x02, ALT=0x04, META=0x08, RCTRL=0x10, RSHIFT=0x20, RALT=0x40, RMETA=0x80)
ACTIONID = _NamedInts(
Empty=0x00,
Key=0x01,
Mouse=0x02,
Xdisp=0x03,
Ydisp=0x04,
Vscroll=0x05,
Hscroll=0x06,
Consumer=0x07,
Internal=0x08,
Power=0x09
)
MOUSE_BUTTONS = _NamedInts(
Left=0x01,
Right=0x02,
Middle=0x04,
Back=0x08,
Forward=0x10,
)
MOUSE_BUTTONS._fallback = lambda x: 'unknown:%02X' % x
# HID USB Keycodes from https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf # HID USB Keycodes from https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf
# Modified by information from Linux HID driver linux/drivers/hid/hid-input.c # Modified by information from Linux HID driver linux/drivers/hid/hid-input.c
USB_HID_KEYCODES = _NamedInts( USB_HID_KEYCODES = _NamedInts(
@ -798,28 +770,6 @@ USB_HID_KEYCODES[0x26] = '9'
USB_HID_KEYCODES[0x27] = '0' USB_HID_KEYCODES[0x27] = '0'
USB_HID_KEYCODES[0x64] = '102ND' USB_HID_KEYCODES[0x64] = '102ND'
# Construct keys plus modifiers
modifiers = {
0x0: '',
0x1: 'Cntrl+',
0x2: 'Shift+',
0x4: 'Alt+',
0x8: 'Meta+',
0x3: 'Cntrl+Shift+',
0x5: 'Alt+Cntrl+',
0x9: 'Meta+Cntrl+',
0x6: 'Alt+Shift+',
0xA: 'Meta+Shift+',
0xC: 'Meta+Alt+'
}
KEYS_Default = 0x7FFFFFFF # Special value to reset key to default - has to be different from all others
KEYS = _UnsortedNamedInts()
KEYS[KEYS_Default] = 'Default' # Value to reset to default
KEYS[0] = 'None' # Value for no output
for val, name in modifiers.items():
for key in USB_HID_KEYCODES:
KEYS[0x01000000 + (int(key) << 8) + val] = name + str(key)
HID_CONSUMERCODES = _NamedInts( HID_CONSUMERCODES = _NamedInts(
# Unassigned=0x00, # Unassigned=0x00,
# Consumer_Control=0x01, # Consumer_Control=0x01,
@ -1203,5 +1153,85 @@ HID_CONSUMERCODES[0x20] = '+10'
HID_CONSUMERCODES[0x21] = '+100' HID_CONSUMERCODES[0x21] = '+100'
HID_CONSUMERCODES._fallback = lambda x: 'unknown:%04X' % x HID_CONSUMERCODES._fallback = lambda x: 'unknown:%04X' % x
## Information for x1c00 Persistent from https://drive.google.com/drive/folders/0BxbRzx7vEV7eWmgwazJ3NUFfQ28
KEYMOD = _NamedInts(CTRL=0x01, SHIFT=0x02, ALT=0x04, META=0x08, RCTRL=0x10, RSHIFT=0x20, RALT=0x40, RMETA=0x80)
ACTIONID = _NamedInts(
Empty=0x00,
Key=0x01,
Mouse=0x02,
Xdisp=0x03,
Ydisp=0x04,
Vscroll=0x05,
Hscroll=0x06,
Consumer=0x07,
Internal=0x08,
Power=0x09
)
MOUSE_BUTTONS = _NamedInts(
Mouse_Button_Left=0x0001,
Mouse_Button_Right=0x0002,
Mouse_Button_Middle=0x0004,
Mouse_Button_Back=0x0008,
Mouse_Button_Forward=0x0010,
)
MOUSE_BUTTONS._fallback = lambda x: 'unknown mouse button:%04X' % x
HORIZONTAL_SCROLL = _NamedInts(
Horizontal_Scroll_Left=0x4000,
Horizontal_Scroll_Right=0x8000,
)
HORIZONTAL_SCROLL._fallback = lambda x: 'unknown horizontal scroll:%04X' % x
# Construct universe for Persistent Remappable Keys setting (only for supported values)
KEYS = _UnsortedNamedInts()
KEYS_Default = 0x7FFFFFFF # Special value to reset key to default - has to be different from all others
KEYS[KEYS_Default] = 'Default' # Value to reset to default
KEYS[0] = 'None' # Value for no output
# Add HID keys plus modifiers
modifiers = {
0x00: '',
0x01: 'Cntrl+',
0x02: 'Shift+',
0x04: 'Alt+',
0x08: 'Meta+',
0x03: 'Cntrl+Shift+',
0x05: 'Alt+Cntrl+',
0x09: 'Meta+Cntrl+',
0x06: 'Alt+Shift+',
0x0A: 'Meta+Shift+',
0x0C: 'Meta+Alt+'
}
for val, name in modifiers.items():
for key in USB_HID_KEYCODES:
KEYS[(ACTIONID.Key << 24) + (int(key) << 8) + val] = name + str(key)
# Add HID Consumer Codes
for code in HID_CONSUMERCODES: for code in HID_CONSUMERCODES:
KEYS[0x07000000 + (int(code) << 8)] = str(code) KEYS[(ACTIONID.Consumer << 24) + (int(code) << 8)] = str(code)
# Add Mouse Buttons
for code in MOUSE_BUTTONS:
KEYS[(ACTIONID.Mouse << 24) + (int(code) << 8)] = str(code)
# Add Horizontal Scroll
for code in HORIZONTAL_SCROLL:
KEYS[(ACTIONID.Hscroll << 24) + (int(code) << 8)] = str(code)
# Construct subsets for known devices
def persistent_keys(action_ids):
keys = _UnsortedNamedInts()
keys[KEYS_Default] = 'Default' # Value to reset to default
keys[0] = 'None' # Value for no output
for key in KEYS:
if (int(key) >> 24) in action_ids:
keys[int(key)] = str(key)
return keys
KEYS_KEYS_CONSUMER = persistent_keys([ACTIONID.Key, ACTIONID.Consumer])
KEYS_KEYS_MOUSE_HSCROLL = persistent_keys([ACTIONID.Key, ACTIONID.Mouse, ACTIONID.Hscroll])