Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add tactile button mapping for the rival 700/710 [WIP] #133

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions rivalcfg/devices/rival700.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,15 @@
"default": _DEFAULT_RGBGRADIENTV2,
},

"tactile_button_mapping": {
"label": "Maps feedback to mouse click",
"description": "Maps tactile feedback on button click",
"cli": ["-t", "--tactile-mapping"],
"command": [0x92, 0x00],
"report_type": usbhid.HID_REPORT_TYPE_OUTPUT,
"value_type": "tactile_button_map",
},

},

"save_command": {
Expand Down
1 change: 1 addition & 0 deletions rivalcfg/handlers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from . import rgbgradientv2
from . import multidpi_range
from . import multi_rgbcolor
from . import tactile_button_map
from .buttons import buttons

# flake8: noqa
152 changes: 152 additions & 0 deletions rivalcfg/handlers/tactile_button_map.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
"""
The "tactile" type handles feedback on the rival 700 family of mice.


Device Profile
--------------

Example of a tactile value type in a device profile:

::

profile = {

# ...

"settings": {

"feedback": {
"label": "Feedback",
"description": "Feedback type",
"command": [0x92, 0x00],
"value_type": "tactile_button_map",
},
},

# ...

}


CLI
---

tactile is a none cli command

LUA API
-------

Todo

Functions
---------
"""

from ..helpers import parse_param_string


NAMED_HAPTIC = {
"none": 0x00,
"strongclick": 0x04,
"softbump": 0x07,
"doubleclick": 0x0a,
"shortdoubleclick": 0x1b,
"tripleclick": 0x03,
"buzz": 0x2f,
"longbuzz": 0x0f,
"sharptick": 0x18,
"pulsing": 0x35,
}

# Button offset in command stream
BUTTON_OFFSETS = {
"button1": 0x01,
"leftclick": 0x01,
"button2": 0x05,
"rightclick": 0x05,
"button3": 0x09,
"button4": 0x0d,
"backwards": 0x0d,
"button5": 0x11,
"forwards": 0x11,
"button6": 0x15,
"button7": 0x19,
"cpi": 0x19,
"cpitoggle": 0x19,
}


def split_table(table):
buttons = []
feedback = []
tact = []
for keys, args in table.items():
for bn, fb in args.items():
buttons.append(bn)
feedback.append(fb)
tact = keys
return tact, buttons, feedback


def is_button(string):
if string.lower() in BUTTON_OFFSETS:
return True


def is_feedback(string):
if string.lower() in NAMED_HAPTIC:
return True


def is_valid_mapping(mapping):
tact, buttons, feedbacks = split_table(parse_param_string(mapping))
if tact == "tactile":
for keys in buttons:
if not is_button(keys):
raise ValueError("Unable to parse button type %s" % (keys))
return False
for keys in feedbacks:
if not is_feedback(keys):
raise ValueError("Unable to parse feedback type %s" % (keys))
return False
return True
else:
raise ValueError("Unable to parse key tactile")
return False


def process_value(setting_info, mapping):
"""Called by the :class:`rivalcfg.mouse.Mouse` class when processing a
"tactile_button_map" type setting.

:param dict setting_info: The information dict of the setting from the
device profile.
"""
"""Converts a list of buttons and feeback types to a list of command bytes.
"""
if is_valid_mapping(mapping):
command_field = [0x00] * 28
tact, buttons, feedbacks = split_table(parse_param_string(mapping))
for index in range(len(buttons)):
feedback = feedbacks[index]
button = buttons[index]
offset = BUTTON_OFFSETS[button]
haptic = NAMED_HAPTIC[feedback]
command_field[offset] = haptic
return (command_field)


def add_cli_option(cli_parser, setting_name, setting_info):

description = setting_info["description"] + (
", Buttons 1-7 are avilable for mapping, to clear a"
" setting use feedback type none, syntax: "
"tactile(button1=strongclick; button2=shortdoubleclick)")

cli_parser.add_argument(
*setting_info["cli"],
dest=setting_name,
help=description,
type=str,
metavar=setting_name.upper()
)