mirror of
https://github.com/libratbag/libratbag.git
synced 2026-11-08 07:33:53 +01:00
Compare commits
85 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
42787ee422 | ||
|
|
611dd9be0d | ||
|
|
fd20f9e642 | ||
|
|
9be5576967 | ||
|
|
9fe511fcc5 | ||
|
|
f0b69aab19 | ||
|
|
7610b80ced | ||
|
|
f0a05bb522 | ||
|
|
2669cc28b2 | ||
|
|
302702d94a | ||
|
|
e1136c4d30 | ||
|
|
0012853a1d | ||
|
|
afb85f868c | ||
|
|
b76fcdadde | ||
|
|
ba7c092ee2 | ||
|
|
3483bd8c14 | ||
|
|
0fb0eb3d42 | ||
|
|
5fb1f4429d | ||
|
|
5f5e294598 | ||
|
|
b4218737cd | ||
|
|
3875bb70fd | ||
|
|
e9d67b7235 | ||
|
|
8a476a8724 | ||
|
|
d67cbec5f8 | ||
|
|
f82c6f72b6 | ||
|
|
af30fc28cd | ||
|
|
3fb8a51456 | ||
|
|
ceaa3c3ad5 | ||
|
|
551b918ba8 | ||
|
|
3105428ba1 | ||
|
|
b3f2406180 | ||
|
|
902160f430 | ||
|
|
fd6d0b6198 | ||
|
|
5ed98fdb22 | ||
|
|
e0e73c2971 | ||
|
|
0d3b4f1b64 | ||
|
|
20b6e3deeb | ||
|
|
ffcdee912d | ||
|
|
5357d4cbc2 | ||
|
|
26c534cc74 | ||
|
|
904c7988bb | ||
|
|
7d255a2f93 | ||
|
|
d0a5cb1f0e | ||
|
|
71b1d66287 | ||
|
|
32ebbca42f | ||
|
|
a0afbfeb3f | ||
|
|
9dfd4fd03a | ||
|
|
b0ea75979a | ||
|
|
a5c1ca202e | ||
|
|
8d40ad6c0c | ||
|
|
72d11de597 | ||
|
|
47cc5fce92 | ||
|
|
5da791b268 | ||
|
|
e63802b01a | ||
|
|
cd89b123ce | ||
|
|
f6546b3222 | ||
|
|
cd8ddc8444 | ||
|
|
cdb3226ef1 | ||
|
|
ce377fc36c | ||
|
|
fe1308fe38 | ||
|
|
983d3e2a88 | ||
|
|
3a3d9e1148 | ||
|
|
afbba26feb | ||
|
|
8cc37047fb | ||
|
|
c8f56cc535 | ||
|
|
b6936ddd3b | ||
|
|
d4d9712316 | ||
|
|
2353af214b | ||
|
|
a4d19efb93 | ||
|
|
cb0b458824 | ||
|
|
48c476b28c | ||
|
|
d6c3bf881d | ||
|
|
1b000e627a | ||
|
|
75bcf39114 | ||
|
|
33ced3dfb7 | ||
|
|
906f17add2 | ||
|
|
016de548fc | ||
|
|
665c022382 | ||
|
|
81c7b42bec | ||
|
|
edb054c6f8 | ||
|
|
8ae995b72d | ||
|
|
a941b75ef2 | ||
|
|
8cb85da6be | ||
|
|
7ff59a636f | ||
|
|
6cd050f541 |
@@ -1,5 +1,10 @@
|
|||||||
# vim: set expandtab shiftwidth=2 tabstop=8:
|
|
||||||
libratbag_references:
|
libratbag_references:
|
||||||
|
build_dependencies: &build_dependencies
|
||||||
|
FEDORA_DEP_BUILD: gcc gcc-c++ meson dbus-daemon glib2-devel json-glib-devel libevdev-devel libudev-devel libunistring-devel python3-devel python3-evdev swig
|
||||||
|
FEDORA_DEP_TEST: check-devel python3-gobject python3-lxml valgrind
|
||||||
|
FEDORA_DEP_DOC: python3-sphinx python3-sphinx_rtd_theme
|
||||||
|
UBUNTU_DEP_BUILD: gcc g++ meson pkg-config systemd libevdev-dev libglib2.0-dev libjson-glib-dev libsystemd-dev libudev-dev libunistring-dev python3-dev python3-evdev swig
|
||||||
|
UBUNTU_DEP_TEST: check python3-gi python3-lxml valgrind
|
||||||
default_settings: &default_settings
|
default_settings: &default_settings
|
||||||
working_directory: ~/libratbag
|
working_directory: ~/libratbag
|
||||||
environment:
|
environment:
|
||||||
@@ -52,10 +57,7 @@ libratbag_references:
|
|||||||
name: Checking if any files are left after uninstall
|
name: Checking if any files are left after uninstall
|
||||||
command: |
|
command: |
|
||||||
PREFIX=/root/test_install
|
PREFIX=/root/test_install
|
||||||
# workaround until https://github.com/mesonbuild/meson/pull/2033 is merged
|
meson build_install --prefix=$PREFIX
|
||||||
# and a new release appears
|
|
||||||
git clone https://github.com/whot/meson -b wip/remove-directories-on-uninstall
|
|
||||||
./meson/meson.py build_install --prefix=$PREFIX
|
|
||||||
ninja -C build_install install
|
ninja -C build_install install
|
||||||
ninja -C build_install uninstall
|
ninja -C build_install uninstall
|
||||||
if [ -d $PREFIX ]
|
if [ -d $PREFIX ]
|
||||||
@@ -78,11 +80,13 @@ fedora_prep_cache: &fedora_prep_cache
|
|||||||
steps:
|
steps:
|
||||||
- run:
|
- run:
|
||||||
name: Initializing Fedora dnf cache
|
name: Initializing Fedora dnf cache
|
||||||
command: dnf install -y --downloadonly libsolv tree git gcc gcc-c++ meson check-devel libudev-devel libevdev-devel valgrind python3-gobject python3-evdev glib2-devel python3-lxml libunistring-devel dbus-daemon json-glib-devel
|
command: dnf install -y --downloadonly git ${FEDORA_DEP_BUILD} ${FEDORA_DEP_TEST} ${FEDORA_DEP_DOC}
|
||||||
- persist_to_workspace:
|
- persist_to_workspace:
|
||||||
root: /var/cache/
|
root: /var/cache/
|
||||||
paths:
|
paths:
|
||||||
- dnf/*
|
- dnf/*
|
||||||
|
environment:
|
||||||
|
*build_dependencies
|
||||||
|
|
||||||
fedora_fetch_cache: &fedora_fetch_cache
|
fedora_fetch_cache: &fedora_fetch_cache
|
||||||
attach_workspace:
|
attach_workspace:
|
||||||
@@ -93,8 +97,7 @@ fedora_install: &fedora_install
|
|||||||
name: Install prerequisites
|
name: Install prerequisites
|
||||||
command: |
|
command: |
|
||||||
echo keepcache=1 >> /etc/dnf/dnf.conf
|
echo keepcache=1 >> /etc/dnf/dnf.conf
|
||||||
dnf upgrade -y libsolv
|
dnf install -y git ${FEDORA_DEP_BUILD} ${FEDORA_DEP_TEST}
|
||||||
dnf install -y tree git gcc gcc-c++ meson check-devel libudev-devel libevdev-devel valgrind python3-gobject python3-evdev glib2-devel python3-lxml python3-devel swig libunistring-devel dbus-daemon json-glib-devel
|
|
||||||
sed -i 's/systemd//' /etc/nsswitch.conf
|
sed -i 's/systemd//' /etc/nsswitch.conf
|
||||||
|
|
||||||
fedora_settings: &fedora_settings
|
fedora_settings: &fedora_settings
|
||||||
@@ -111,7 +114,8 @@ fedora_settings: &fedora_settings
|
|||||||
- *build_buildtype_plain
|
- *build_buildtype_plain
|
||||||
- *build_buildtype_release
|
- *build_buildtype_release
|
||||||
- *export_logs
|
- *export_logs
|
||||||
|
environment:
|
||||||
|
*build_dependencies
|
||||||
|
|
||||||
ubuntu_settings: &ubuntu_settings
|
ubuntu_settings: &ubuntu_settings
|
||||||
<<: *default_settings
|
<<: *default_settings
|
||||||
@@ -124,7 +128,7 @@ ubuntu_settings: &ubuntu_settings
|
|||||||
apt-get remove -y libnss-systemd
|
apt-get remove -y libnss-systemd
|
||||||
add-apt-repository universe
|
add-apt-repository universe
|
||||||
apt-get update
|
apt-get update
|
||||||
apt-get install -y tree git gcc g++ pkg-config meson check libudev-dev libevdev-dev libsystemd-dev valgrind python3-gi python3-evdev libglib2.0-dev python3-lxml python3-dev swig systemd libunistring-dev libjson-glib-dev
|
apt-get install -y git ${UBUNTU_DEP_BUILD} ${UBUNTU_DEP_TEST}
|
||||||
- checkout
|
- checkout
|
||||||
- *start_dbus
|
- *start_dbus
|
||||||
- *build_and_test
|
- *build_and_test
|
||||||
@@ -134,6 +138,8 @@ ubuntu_settings: &ubuntu_settings
|
|||||||
- *build_buildtype_plain
|
- *build_buildtype_plain
|
||||||
- *build_buildtype_release
|
- *build_buildtype_release
|
||||||
- *export_logs
|
- *export_logs
|
||||||
|
environment:
|
||||||
|
*build_dependencies
|
||||||
|
|
||||||
doc_build: &doc_build
|
doc_build: &doc_build
|
||||||
<<: *default_settings
|
<<: *default_settings
|
||||||
@@ -142,7 +148,7 @@ doc_build: &doc_build
|
|||||||
- *fedora_install
|
- *fedora_install
|
||||||
- run:
|
- run:
|
||||||
name: Install documentation build-deps
|
name: Install documentation build-deps
|
||||||
command: dnf install -y python3-sphinx python3-sphinx_rtd_theme
|
command: dnf install -y ${FEDORA_DEP_DOC}
|
||||||
- checkout
|
- checkout
|
||||||
- *build_with_docs
|
- *build_with_docs
|
||||||
- *export_logs
|
- *export_logs
|
||||||
@@ -152,6 +158,8 @@ doc_build: &doc_build
|
|||||||
root: build
|
root: build
|
||||||
paths:
|
paths:
|
||||||
- doc/html/*
|
- doc/html/*
|
||||||
|
environment:
|
||||||
|
*build_dependencies
|
||||||
|
|
||||||
docs_deploy: &docs_deploy
|
docs_deploy: &docs_deploy
|
||||||
<<: *default_settings
|
<<: *default_settings
|
||||||
@@ -193,18 +201,14 @@ docs_deploy: &docs_deploy
|
|||||||
|
|
||||||
version: 2
|
version: 2
|
||||||
jobs:
|
jobs:
|
||||||
fedora_rawhide:
|
|
||||||
<<: *fedora_settings
|
|
||||||
docker:
|
|
||||||
- image: fedora:rawhide
|
|
||||||
fedora_cache:
|
fedora_cache:
|
||||||
<<: *fedora_prep_cache
|
<<: *fedora_prep_cache
|
||||||
docker:
|
docker:
|
||||||
- image: fedora:30
|
- image: fedora:31
|
||||||
fedora_latest:
|
fedora_31:
|
||||||
<<: *fedora_settings
|
<<: *fedora_settings
|
||||||
docker:
|
docker:
|
||||||
- image: fedora:30
|
- image: fedora:31
|
||||||
ubuntu_19_04:
|
ubuntu_19_04:
|
||||||
<<: *ubuntu_settings
|
<<: *ubuntu_settings
|
||||||
docker:
|
docker:
|
||||||
@@ -212,21 +216,20 @@ jobs:
|
|||||||
doc_build:
|
doc_build:
|
||||||
<<: *doc_build
|
<<: *doc_build
|
||||||
docker:
|
docker:
|
||||||
- image: fedora:30
|
- image: fedora:31
|
||||||
doc_deploy:
|
doc_deploy:
|
||||||
<<: *docs_deploy
|
<<: *docs_deploy
|
||||||
docker:
|
docker:
|
||||||
- image: fedora:30
|
- image: fedora:31
|
||||||
|
|
||||||
|
|
||||||
workflows:
|
workflows:
|
||||||
version: 2
|
version: 2
|
||||||
compile_and_test:
|
compile_and_test:
|
||||||
jobs:
|
jobs:
|
||||||
# - fedora_rawhide
|
|
||||||
- fedora_cache
|
- fedora_cache
|
||||||
- ubuntu_19_04
|
- ubuntu_19_04
|
||||||
- fedora_latest:
|
- fedora_31:
|
||||||
requires:
|
requires:
|
||||||
- fedora_cache
|
- fedora_cache
|
||||||
- doc_build:
|
- doc_build:
|
||||||
|
|||||||
20
.editorconfig
Normal file
20
.editorconfig
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
end_of_line = lf
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
insert_final_newline = true
|
||||||
|
|
||||||
|
[*.{c,h}]
|
||||||
|
indent_style = tab
|
||||||
|
tab_width = 8
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
|
||||||
|
[{*.{py,py.in},tools/ratbagctl.*.in}]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 4
|
||||||
|
|
||||||
|
[*.{yml,xsl}]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
36
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
36
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
---
|
||||||
|
name: Bug report
|
||||||
|
about: Create a report to help us improve
|
||||||
|
title: ''
|
||||||
|
labels: bug
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Information**
|
||||||
|
<!-- If your issue is related to a Logitech device please make sure you are running at least Linux 5.2 -->
|
||||||
|
- `ratbagd` version (`ratbagd --version`):
|
||||||
|
- Distribution:
|
||||||
|
- Kernel version (ex. `uname -srmo`): `KERNEL VERSION HERE`
|
||||||
|
|
||||||
|
**Describe the bug**
|
||||||
|
A clear and concise description of what the bug is.
|
||||||
|
|
||||||
|
**To Reproduce**
|
||||||
|
Steps to reproduce the behavior:
|
||||||
|
1. Go to '...'
|
||||||
|
2. Click on '....'
|
||||||
|
3. Scroll down to '....'
|
||||||
|
4. See error
|
||||||
|
|
||||||
|
**Logs**
|
||||||
|
Please start the daemon with verbosity and reproduce the issue.
|
||||||
|
|
||||||
|
First make sure it isn't running already.
|
||||||
|
```
|
||||||
|
$ ratbagd --verbose=raw
|
||||||
|
OUTPUT HERE
|
||||||
|
```
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context about the problem here.
|
||||||
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
---
|
||||||
|
name: Feature request
|
||||||
|
about: Suggest an idea for this project
|
||||||
|
title: ''
|
||||||
|
labels: enhancement
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Is your feature request related to a problem? Please describe.**
|
||||||
|
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||||
|
|
||||||
|
**Describe the solution you'd like**
|
||||||
|
A clear and concise description of what you want to happen.
|
||||||
|
|
||||||
|
**Describe alternatives you've considered**
|
||||||
|
A clear and concise description of any alternative solutions or features you've considered.
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context or screenshots about the feature request here.
|
||||||
11
.gitignore
vendored
11
.gitignore
vendored
@@ -1,11 +0,0 @@
|
|||||||
*.o
|
|
||||||
*.pc
|
|
||||||
*.swp
|
|
||||||
*~
|
|
||||||
*.sig
|
|
||||||
*.tar.*
|
|
||||||
*.announce
|
|
||||||
*.patch
|
|
||||||
*.rej
|
|
||||||
*.trs
|
|
||||||
tags
|
|
||||||
@@ -3,9 +3,10 @@ libratbag
|
|||||||
|
|
||||||
<img src="https://libratbag.github.io/_images/logo.svg" alt="" width="30%" align="right">
|
<img src="https://libratbag.github.io/_images/logo.svg" alt="" width="30%" align="right">
|
||||||
|
|
||||||
libratbag provides **ratbagd**, a DBus daemon to configure gaming mice.
|
libratbag provides **ratbagd**, a DBus daemon to configure input devices,
|
||||||
The daemon provides a generic way to access the various features exposed by
|
mainly gaming mice. The daemon provides a generic way to access the various
|
||||||
these mice and abstracts away hardware-specific and kernel-specific quirks.
|
features exposed by these mice and abstracts away hardware-specific and
|
||||||
|
kernel-specific quirks.
|
||||||
|
|
||||||
libratbag currently supports devices from Logitech, Etekcity, GSkill,
|
libratbag currently supports devices from Logitech, Etekcity, GSkill,
|
||||||
Roccat, Steelseries. See [the device
|
Roccat, Steelseries. See [the device
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# vim: set expandtab shiftwidth=4 tabstop=4:
|
|
||||||
#
|
#
|
||||||
# Copyright © 2017 Red Hat, Inc.
|
# Copyright © 2017 Red Hat, Inc.
|
||||||
#
|
#
|
||||||
@@ -27,6 +26,7 @@
|
|||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import configparser
|
import configparser
|
||||||
|
import re
|
||||||
|
|
||||||
|
|
||||||
def assertIn(element, l):
|
def assertIn(element, l):
|
||||||
@@ -57,7 +57,7 @@ def check_match_str(string):
|
|||||||
|
|
||||||
|
|
||||||
def check_ledtypes_str(string):
|
def check_ledtypes_str(string):
|
||||||
permitted_types = ['logo', 'side', 'battery', 'dpi']
|
permitted_types = ['logo', 'side', 'battery', 'dpi', 'switches']
|
||||||
|
|
||||||
types = string.split(';')
|
types = string.split(';')
|
||||||
for t in types:
|
for t in types:
|
||||||
@@ -137,9 +137,8 @@ def check_section_hidpp10(section):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
try:
|
try:
|
||||||
index = int(section['DeviceIndex'])
|
index = int(section['DeviceIndex'], 16)
|
||||||
# 10 is arbitrarily chosen
|
assert(index > 0 and index <= 0xff)
|
||||||
assert(index > 0 and index < 10)
|
|
||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@@ -169,14 +168,13 @@ def check_section_hidpp10(section):
|
|||||||
|
|
||||||
|
|
||||||
def check_section_hidpp20(section):
|
def check_section_hidpp20(section):
|
||||||
permitted = ['DeviceIndex']
|
permitted = ['DeviceIndex', 'Quirk']
|
||||||
for key in section.keys():
|
for key in section.keys():
|
||||||
assertIn(key, permitted)
|
assertIn(key, permitted)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
index = int(section['DeviceIndex'])
|
index = int(section['DeviceIndex'], 16)
|
||||||
# 10 is arbitrarily chosen
|
assert(index > 0 and index <= 0xff)
|
||||||
assert(index > 0 and index < 10)
|
|
||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@@ -190,6 +188,15 @@ def check_section_driver(driver, section):
|
|||||||
assert('Unsupported driver section {}'.format(driver))
|
assert('Unsupported driver section {}'.format(driver))
|
||||||
|
|
||||||
|
|
||||||
|
def validate_data_file_name(path):
|
||||||
|
# Matching any of the characters in the regular expression will throw an
|
||||||
|
# error. Currently only tests the square brackets [], parentheses, and curly
|
||||||
|
# braces.
|
||||||
|
illegal_characters_regex = '([\[\]\{\}\(\)])'
|
||||||
|
found_characters = re.findall(illegal_characters_regex, path)
|
||||||
|
if found_characters:
|
||||||
|
raise AssertionError("data file name '{}' contains illegal characters: '{}'".format(path, ''.join(found_characters)))
|
||||||
|
|
||||||
def parse_data_file(path):
|
def parse_data_file(path):
|
||||||
print('Parsing file {}'.format(path))
|
print('Parsing file {}'.format(path))
|
||||||
data = configparser.ConfigParser(strict=True)
|
data = configparser.ConfigParser(strict=True)
|
||||||
@@ -216,4 +223,5 @@ if __name__ == "__main__":
|
|||||||
parser.add_argument('file', nargs='+')
|
parser.add_argument('file', nargs='+')
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
for path in args.file:
|
for path in args.file:
|
||||||
|
validate_data_file_name(path)
|
||||||
parse_data_file(path)
|
parse_data_file(path)
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# vim: set expandtab shiftwidth=4 tabstop=4:
|
|
||||||
#
|
#
|
||||||
# Copyright © 2018 Red Hat, Inc.
|
# Copyright © 2018 Red Hat, Inc.
|
||||||
#
|
#
|
||||||
|
|||||||
5
data/devices/logitech-M585-M590.device
Normal file
5
data/devices/logitech-M585-M590.device
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
# Logitech M585/M590
|
||||||
|
[Device]
|
||||||
|
Name=Logitech M585/M590
|
||||||
|
DeviceMatch=usb:046d:406b;bluetooth:046d:b01b
|
||||||
|
Driver=hidpp20
|
||||||
5
data/devices/logitech-MX-Master-3.device
Normal file
5
data/devices/logitech-MX-Master-3.device
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
# Logitech MX Master 3
|
||||||
|
[Device]
|
||||||
|
Name=Logitech MX Master 3
|
||||||
|
DeviceMatch=bluetooth:046d:b023;usb:046d:4082
|
||||||
|
Driver=hidpp20
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
# Logitech MX Master
|
# Logitech MX Master
|
||||||
[Device]
|
[Device]
|
||||||
Name=Logitech MX Master
|
Name=Logitech MX Master
|
||||||
DeviceMatch=usb:046d:4041;bluetooth:046d:b012;usb:046d:4060;bluetooth:046d:b017
|
DeviceMatch=usb:046d:4041;bluetooth:046d:b012;usb:046d:4060;bluetooth:046d:b017;bluetooth:046d:b01e;usb:046d:4071
|
||||||
Driver=hidpp20
|
Driver=hidpp20
|
||||||
|
|||||||
8
data/devices/logitech-g-powerplay.device
Normal file
8
data/devices/logitech-g-powerplay.device
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
[Device]
|
||||||
|
Name=Logitech G Powerplay
|
||||||
|
DeviceMatch=usb:046d:405f
|
||||||
|
LedTypes=logo
|
||||||
|
Driver=hidpp20
|
||||||
|
|
||||||
|
[Driver/hidpp20]
|
||||||
|
DeviceIndex=7
|
||||||
7
data/devices/logitech-g305.device
Normal file
7
data/devices/logitech-g305.device
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
[Device]
|
||||||
|
Name=Logitech Gaming Mouse G305
|
||||||
|
DeviceMatch=usb:046d:4074
|
||||||
|
Driver=hidpp20
|
||||||
|
|
||||||
|
[Driver/hidpp20]
|
||||||
|
Quirk=G305
|
||||||
4
data/devices/logitech-g502-hero-wireless.device
Normal file
4
data/devices/logitech-g502-hero-wireless.device
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
[Device]
|
||||||
|
Name=Logitech G502 Hero Wireless
|
||||||
|
DeviceMatch=usb:046d:407f;usb:046d:c08d
|
||||||
|
Driver=hidpp20
|
||||||
5
data/devices/logitech-g513.device
Normal file
5
data/devices/logitech-g513.device
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
[Device]
|
||||||
|
Name=Logitech G513
|
||||||
|
DeviceMatch=usb:046d:c33c
|
||||||
|
LedTypes=switches
|
||||||
|
Driver=hidpp20
|
||||||
@@ -6,3 +6,4 @@ Driver=hidpp20
|
|||||||
|
|
||||||
[Driver/hidpp20]
|
[Driver/hidpp20]
|
||||||
DeviceIndex=1
|
DeviceIndex=1
|
||||||
|
Quirk=G602
|
||||||
|
|||||||
4
data/devices/logitech-g604.device
Normal file
4
data/devices/logitech-g604.device
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
[Device]
|
||||||
|
Name=Logitech G604
|
||||||
|
DeviceMatch=usb:046d:4085;bluetooth:046d:b024
|
||||||
|
Driver=hidpp20
|
||||||
5
data/devices/logitech-g815.device
Normal file
5
data/devices/logitech-g815.device
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
[Device]
|
||||||
|
Name=Logitech G815
|
||||||
|
DeviceMatch=usb:046d:c33f
|
||||||
|
LedTypes=logo;switches
|
||||||
|
Driver=hidpp20
|
||||||
8
data/devices/logitech-g910.device
Normal file
8
data/devices/logitech-g910.device
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
[Device]
|
||||||
|
Name=Logitech G910
|
||||||
|
DeviceMatch=usb:046d:c335
|
||||||
|
LedTypes=logo;switches
|
||||||
|
Driver=hidpp20
|
||||||
|
|
||||||
|
[Driver/hidpp20]
|
||||||
|
DeviceIndex=ff
|
||||||
8
data/devices/logitech-g915.device
Normal file
8
data/devices/logitech-g915.device
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
[Device]
|
||||||
|
Name=Logitech G915
|
||||||
|
DeviceMatch=usb:046d:c33e
|
||||||
|
LedTypes=logo;switches
|
||||||
|
Driver=hidpp20
|
||||||
|
|
||||||
|
[Driver/hidpp20]
|
||||||
|
DeviceIndex=1
|
||||||
74
data/devices/receiver-check.py
Executable file
74
data/devices/receiver-check.py
Executable file
@@ -0,0 +1,74 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
#
|
||||||
|
# Copyright © 2018 Red Hat, Inc.
|
||||||
|
#
|
||||||
|
# Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
# copy of this software and associated documentation files (the "Software"),
|
||||||
|
# to deal in the Software without restriction, including without limitation
|
||||||
|
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
# and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
# Software is furnished to do so, subject to the following conditions:
|
||||||
|
#
|
||||||
|
# The above copyright notice and this permission notice (including the next
|
||||||
|
# paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
# Software.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
# DEALINGS IN THE SOFTWARE.
|
||||||
|
#
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import configparser
|
||||||
|
|
||||||
|
# see the IDs from
|
||||||
|
# https://github.com/torvalds/linux/blob/master/drivers/hid/hid-ids.h#L772
|
||||||
|
# https://github.com/torvalds/linux/blob/master/drivers/hid/hid-logitech-dj.c#L1826
|
||||||
|
logitech_receivers = [
|
||||||
|
0xc50c, # USB_DEVICE_ID_S510_RECEIVER
|
||||||
|
0xc517, # USB_DEVICE_ID_S510_RECEIVER_2
|
||||||
|
0xc512, # USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500
|
||||||
|
0xc513, # USB_DEVICE_ID_MX3000_RECEIVER
|
||||||
|
0xc51b, # USB_DEVICE_ID_LOGITECH_27MHZ_MOUSE_RECEIVER
|
||||||
|
0xc52b, # USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER
|
||||||
|
0xc52f, # USB_DEVICE_ID_LOGITECH_NANO_RECEIVER
|
||||||
|
0xc532, # USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER_2
|
||||||
|
0xc534, # USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_2
|
||||||
|
0xc539, # USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_LIGHTSPEED_1
|
||||||
|
0xc53f, # USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_LIGHTSPEED_1_1
|
||||||
|
0xc53a, # USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_POWERPLAY
|
||||||
|
]
|
||||||
|
RECEIVERS = ['usb:046d:{}'.format(r) for r in logitech_receivers]
|
||||||
|
|
||||||
|
|
||||||
|
def parse_data_file(path):
|
||||||
|
data = configparser.ConfigParser(strict=True)
|
||||||
|
# Don't convert to lowercase
|
||||||
|
data.optionxform = lambda option: option
|
||||||
|
data.read(path)
|
||||||
|
|
||||||
|
matches = data['Device']['DeviceMatch']
|
||||||
|
return matches.split(';')
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
parser = argparse.ArgumentParser(description='Checks that no unifying receiver ID is in the device files')
|
||||||
|
parser.add_argument('file', nargs='+')
|
||||||
|
args = parser.parse_args()
|
||||||
|
receiver_found = False
|
||||||
|
for path in args.file:
|
||||||
|
matches = parse_data_file(path)
|
||||||
|
fname = os.path.basename(path)
|
||||||
|
for m in matches:
|
||||||
|
if m in RECEIVERS:
|
||||||
|
print('Receiver ID {} found in file {}'.format(m, fname))
|
||||||
|
receiver_found = True
|
||||||
|
|
||||||
|
if receiver_found:
|
||||||
|
sys.exit(1)
|
||||||
4
data/devices/roccat-kone-pure.device
Normal file
4
data/devices/roccat-kone-pure.device
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
[Device]
|
||||||
|
Name=Roccat Kone Pure
|
||||||
|
DeviceMatch=usb:1e7d:2dc2
|
||||||
|
Driver=roccat-kone-pure
|
||||||
11
data/devices/steelseries-kinzu-v3.device
Normal file
11
data/devices/steelseries-kinzu-v3.device
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
[Device]
|
||||||
|
Name=SteelSeries Kinzu V3
|
||||||
|
DeviceMatch=usb:1038:1388
|
||||||
|
Driver=steelseries
|
||||||
|
|
||||||
|
[Driver/steelseries]
|
||||||
|
DeviceVersion=1
|
||||||
|
Buttons=3
|
||||||
|
Leds=0
|
||||||
|
DpiList=400;800;1600;2000
|
||||||
|
MacroLength=0
|
||||||
35
meson.build
35
meson.build
@@ -1,5 +1,5 @@
|
|||||||
project('libratbag', 'c',
|
project('libratbag', 'c',
|
||||||
version : '0.10',
|
version : '0.13',
|
||||||
license : 'MIT/Expat',
|
license : 'MIT/Expat',
|
||||||
default_options : [ 'c_std=gnu99', 'warning_level=2' ],
|
default_options : [ 'c_std=gnu99', 'warning_level=2' ],
|
||||||
meson_version : '>= 0.40.0')
|
meson_version : '>= 0.40.0')
|
||||||
@@ -172,6 +172,7 @@ src_libratbag = [
|
|||||||
'src/driver-logitech-g300.c',
|
'src/driver-logitech-g300.c',
|
||||||
'src/driver-logitech-g600.c',
|
'src/driver-logitech-g600.c',
|
||||||
'src/driver-roccat.c',
|
'src/driver-roccat.c',
|
||||||
|
'src/driver-roccat-kone-pure.c',
|
||||||
'src/driver-gskill.c',
|
'src/driver-gskill.c',
|
||||||
'src/driver-steelseries.c',
|
'src/driver-steelseries.c',
|
||||||
'src/driver-test.c',
|
'src/driver-test.c',
|
||||||
@@ -281,19 +282,23 @@ data_files = files(
|
|||||||
'data/devices/gskill-MX-780.device',
|
'data/devices/gskill-MX-780.device',
|
||||||
'data/devices/logitech-M325.device',
|
'data/devices/logitech-M325.device',
|
||||||
'data/devices/logitech-M570.device',
|
'data/devices/logitech-M570.device',
|
||||||
|
'data/devices/logitech-M585-M590.device',
|
||||||
'data/devices/logitech-M705.device',
|
'data/devices/logitech-M705.device',
|
||||||
'data/devices/logitech-MX-Ergo.device',
|
'data/devices/logitech-MX-Ergo.device',
|
||||||
'data/devices/logitech-MX-Master.device',
|
'data/devices/logitech-MX-Master.device',
|
||||||
'data/devices/logitech-MX-Master-2S.device',
|
'data/devices/logitech-MX-Master-2S.device',
|
||||||
|
'data/devices/logitech-MX-Master-3.device',
|
||||||
'data/devices/logitech-MX518.device',
|
'data/devices/logitech-MX518.device',
|
||||||
'data/devices/logitech-T650.device',
|
'data/devices/logitech-T650.device',
|
||||||
'data/devices/logitech-Wireless-Touchpad.device',
|
'data/devices/logitech-Wireless-Touchpad.device',
|
||||||
|
'data/devices/logitech-g-powerplay.device',
|
||||||
'data/devices/logitech-g-pro-wireless.device',
|
'data/devices/logitech-g-pro-wireless.device',
|
||||||
'data/devices/logitech-g-pro.device',
|
'data/devices/logitech-g-pro.device',
|
||||||
'data/devices/logitech-g102-g203.device',
|
'data/devices/logitech-g102-g203.device',
|
||||||
'data/devices/logitech-g300.device',
|
'data/devices/logitech-g300.device',
|
||||||
'data/devices/logitech-g302.device',
|
'data/devices/logitech-g302.device',
|
||||||
'data/devices/logitech-g303.device',
|
'data/devices/logitech-g303.device',
|
||||||
|
'data/devices/logitech-g305.device',
|
||||||
'data/devices/logitech-g402.device',
|
'data/devices/logitech-g402.device',
|
||||||
'data/devices/logitech-g403-hero.device',
|
'data/devices/logitech-g403-hero.device',
|
||||||
'data/devices/logitech-g403-wireless.device',
|
'data/devices/logitech-g403-wireless.device',
|
||||||
@@ -302,12 +307,15 @@ data_files = files(
|
|||||||
'data/devices/logitech-g5.device',
|
'data/devices/logitech-g5.device',
|
||||||
'data/devices/logitech-g500.device',
|
'data/devices/logitech-g500.device',
|
||||||
'data/devices/logitech-g500s.device',
|
'data/devices/logitech-g500s.device',
|
||||||
|
'data/devices/logitech-g502-hero-wireless.device',
|
||||||
'data/devices/logitech-g502-hero.device',
|
'data/devices/logitech-g502-hero.device',
|
||||||
'data/devices/logitech-g502-proteus-core.device',
|
'data/devices/logitech-g502-proteus-core.device',
|
||||||
'data/devices/logitech-g502-proteus-spectrum.device',
|
'data/devices/logitech-g502-proteus-spectrum.device',
|
||||||
|
'data/devices/logitech-g513.device',
|
||||||
'data/devices/logitech-g600.device',
|
'data/devices/logitech-g600.device',
|
||||||
'data/devices/logitech-g602.device',
|
'data/devices/logitech-g602.device',
|
||||||
'data/devices/logitech-g603.device',
|
'data/devices/logitech-g603.device',
|
||||||
|
'data/devices/logitech-g604.device',
|
||||||
'data/devices/logitech-g7.device',
|
'data/devices/logitech-g7.device',
|
||||||
'data/devices/logitech-g700-wireless.device',
|
'data/devices/logitech-g700-wireless.device',
|
||||||
'data/devices/logitech-g700.device',
|
'data/devices/logitech-g700.device',
|
||||||
@@ -318,14 +326,19 @@ data_files = files(
|
|||||||
'data/devices/logitech-g900.device',
|
'data/devices/logitech-g900.device',
|
||||||
'data/devices/logitech-g903-hero.device',
|
'data/devices/logitech-g903-hero.device',
|
||||||
'data/devices/logitech-g903.device',
|
'data/devices/logitech-g903.device',
|
||||||
'data/devices/logitech-g9x-[Call-of-Duty-MW3-Edition].device',
|
'data/devices/logitech-g815.device',
|
||||||
'data/devices/logitech-g9x-[Original].device',
|
'data/devices/logitech-g910.device',
|
||||||
|
'data/devices/logitech-g915.device',
|
||||||
|
'data/devices/logitech-g9x-Call-of-Duty-MW3-Edition.device',
|
||||||
|
'data/devices/logitech-g9x-Original.device',
|
||||||
'data/devices/logitech-Marathon-M705.device',
|
'data/devices/logitech-Marathon-M705.device',
|
||||||
'data/devices/logitech-MX-Anywhere2.device',
|
'data/devices/logitech-MX-Anywhere2.device',
|
||||||
'data/devices/logitech-MX-Anywhere2S.device',
|
'data/devices/logitech-MX-Anywhere2S.device',
|
||||||
'data/devices/logitech-MX-Vertical.device',
|
'data/devices/logitech-MX-Vertical.device',
|
||||||
|
'data/devices/roccat-kone-pure.device',
|
||||||
'data/devices/roccat-kone-xtd.device',
|
'data/devices/roccat-kone-xtd.device',
|
||||||
'data/devices/steelseries-kinzu-v2.device',
|
'data/devices/steelseries-kinzu-v2.device',
|
||||||
|
'data/devices/steelseries-kinzu-v3.device',
|
||||||
'data/devices/steelseries-rival-310.device',
|
'data/devices/steelseries-rival-310.device',
|
||||||
'data/devices/steelseries-rival-600.device',
|
'data/devices/steelseries-rival-600.device',
|
||||||
'data/devices/steelseries-rival.device',
|
'data/devices/steelseries-rival.device',
|
||||||
@@ -342,6 +355,9 @@ test('data-parse-test', data_parse_test, args: data_files)
|
|||||||
duplicate_test = find_program(join_paths(meson.source_root(), 'data/devices/duplicate-check.py'))
|
duplicate_test = find_program(join_paths(meson.source_root(), 'data/devices/duplicate-check.py'))
|
||||||
test('duplicate-test', duplicate_test, args : data_files)
|
test('duplicate-test', duplicate_test, args : data_files)
|
||||||
|
|
||||||
|
reciever_id_test = find_program(join_paths(meson.source_root(), 'data/devices/receiver-check.py'))
|
||||||
|
test('receiver-id-test', reciever_id_test, args : data_files)
|
||||||
|
|
||||||
#### tests ####
|
#### tests ####
|
||||||
enable_tests = get_option('tests')
|
enable_tests = get_option('tests')
|
||||||
if enable_tests
|
if enable_tests
|
||||||
@@ -615,6 +631,19 @@ shared_library(
|
|||||||
install: false,
|
install: false,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
i_source = join_paths(meson.source_root(), 'src', 'hidpp.i')
|
||||||
|
c_source = swig_gen.process(i_source)
|
||||||
|
shared_library(
|
||||||
|
'hidpp',
|
||||||
|
c_source,
|
||||||
|
name_prefix: '_',
|
||||||
|
c_args : ['-Wno-missing-prototypes', '-Wno-format-nonliteral'],
|
||||||
|
extra_files: [ i_source ] + src_libratbag ,
|
||||||
|
dependencies: deps_libratbag + wrapper_deps,
|
||||||
|
include_directories : include_directories('src', 'tools'),
|
||||||
|
install: false,
|
||||||
|
)
|
||||||
|
|
||||||
# ratbagc is the layer that maps ratbagctl to the swig bindings
|
# ratbagc is the layer that maps ratbagctl to the swig bindings
|
||||||
ratbagc_py_conf = configuration_data()
|
ratbagc_py_conf = configuration_data()
|
||||||
ratbagc_py_conf.set('LIBRATBAG_DATA_DIR', libratbag_data_dir_devel)
|
ratbagc_py_conf.set('LIBRATBAG_DATA_DIR', libratbag_data_dir_devel)
|
||||||
|
|||||||
12
ratbagd/.gitignore
vendored
12
ratbagd/.gitignore
vendored
@@ -1,12 +0,0 @@
|
|||||||
*.a
|
|
||||||
*.log
|
|
||||||
*.o
|
|
||||||
*.stamp
|
|
||||||
*.swp
|
|
||||||
*.trs
|
|
||||||
*~
|
|
||||||
.dirstamp
|
|
||||||
.libs/
|
|
||||||
/*.tar.xz
|
|
||||||
tags
|
|
||||||
__pycache__
|
|
||||||
@@ -172,6 +172,8 @@ static void ratbagd_device_commit_pending(void *data)
|
|||||||
int r;
|
int r;
|
||||||
|
|
||||||
r = ratbag_device_commit(device->lib_device);
|
r = ratbag_device_commit(device->lib_device);
|
||||||
|
if (r)
|
||||||
|
log_error("error committing device (%d)\n", r);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
ratbagd_device_resync(device, device->ctx->bus);
|
ratbagd_device_resync(device, device->ctx->bus);
|
||||||
ratbagd_device_unref(device);
|
ratbagd_device_unref(device);
|
||||||
|
|||||||
@@ -170,7 +170,7 @@ static void parse_led_member(JsonObject *obj, const gchar *name,
|
|||||||
if (streq(name, "type")) {
|
if (streq(name, "type")) {
|
||||||
gboolean v = json_object_get_int_member(obj, name);
|
gboolean v = json_object_get_int_member(obj, name);
|
||||||
|
|
||||||
if (v < 0 || v > RATBAG_LED_TYPE_WHEEL)
|
if (v < 0 || v > RATBAG_LED_TYPE_SWITCHES)
|
||||||
parser_error("type");
|
parser_error("type");
|
||||||
|
|
||||||
led->type = v;
|
led->type = v;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
ratbagd \- system daemon to introspect and modify configurable mice
|
ratbagd \- system daemon to introspect and modify configurable mice
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
.B ratbagd
|
.B ratbagd
|
||||||
.RB [ \-\-verbose[=raw]|\-\-quiet|\-\-version|\-\-help]
|
.RB [ \-\-verbose[=debug]|\-\-quiet|\-\-version|\-\-help]
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
.B ratbagd
|
.B ratbagd
|
||||||
starts the daemon. It shouldn't be invoked directly;
|
starts the daemon. It shouldn't be invoked directly;
|
||||||
@@ -14,7 +14,7 @@ is normally started through DBus activation.
|
|||||||
.B \-\-help
|
.B \-\-help
|
||||||
Print help and exit
|
Print help and exit
|
||||||
.TP 8
|
.TP 8
|
||||||
.B \-\-verbose, \-\-verbose=raw
|
.B \-\-verbose, \-\-verbose=debug
|
||||||
Enable verbose output, optionally including raw messages as sent and
|
Enable verbose output, optionally including raw messages as sent and
|
||||||
received from the device. This should be use to debug any issues with the
|
received from the device. This should be use to debug any issues with the
|
||||||
device.
|
device.
|
||||||
|
|||||||
@@ -356,6 +356,7 @@ static int ratbagd_new(struct ratbagd **out)
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
log_verbose("Initializing libratbag\n");
|
||||||
ctx->lib_ctx = ratbag_create_context(&ratbagd_lib_interface, ctx);
|
ctx->lib_ctx = ratbag_create_context(&ratbagd_lib_interface, ctx);
|
||||||
if (!ctx->lib_ctx)
|
if (!ctx->lib_ctx)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
@@ -520,6 +521,8 @@ static int ratbagd_run(struct ratbagd *ctx)
|
|||||||
ctx);
|
ctx);
|
||||||
sd_event_add_post(ctx->event, NULL, before_idle_cb, ctx);
|
sd_event_add_post(ctx->event, NULL, before_idle_cb, ctx);
|
||||||
|
|
||||||
|
log_verbose("DBus server ready\n");
|
||||||
|
|
||||||
return sd_event_loop(ctx->event);
|
return sd_event_loop(ctx->event);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -617,12 +620,12 @@ int main(int argc, char *argv[])
|
|||||||
return 0;
|
return 0;
|
||||||
} else if (streq(argv[1], "--quiet")) {
|
} else if (streq(argv[1], "--quiet")) {
|
||||||
log_level = LL_QUIET;
|
log_level = LL_QUIET;
|
||||||
} else if (streq(argv[1], "--verbose=raw")) {
|
} else if (streq(argv[1], "--verbose") || streq(argv[1], "--verbose=raw")) {
|
||||||
log_level = LL_RAW;
|
log_level = LL_RAW;
|
||||||
} else if (streq(argv[1], "--verbose")) {
|
} else if (streq(argv[1], "--verbose=debug")) {
|
||||||
log_level = LL_VERBOSE;
|
log_level = LL_VERBOSE;
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "Usage: %s [--version | --quiet | --verbose[=raw]]\n",
|
fprintf(stderr, "Usage: %s [--version | --quiet | --verbose[=debug]]\n",
|
||||||
program_invocation_short_name);
|
program_invocation_short_name);
|
||||||
r = -EINVAL;
|
r = -EINVAL;
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|||||||
120
release.sh
120
release.sh
@@ -90,13 +90,11 @@ check_option_args() {
|
|||||||
#
|
#
|
||||||
check_modules_specification() {
|
check_modules_specification() {
|
||||||
|
|
||||||
if [ x"$MODFILE" = x ]; then
|
if [ x"${INPUT_MODULES}" = x ]; then
|
||||||
if [ x"${INPUT_MODULES}" = x ]; then
|
echo ""
|
||||||
echo ""
|
echo "Error: no modules specified (blank command line)."
|
||||||
echo "Error: no modules specified (blank command line)."
|
usage
|
||||||
usage
|
exit 1
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -112,7 +110,7 @@ Subject: [ANNOUNCE] $pkg_name $pkg_version
|
|||||||
To: $list_to
|
To: $list_to
|
||||||
Cc: $list_cc
|
Cc: $list_cc
|
||||||
|
|
||||||
libratbag $tag_name is out.
|
$pkg_name $tag_name is out.
|
||||||
|
|
||||||
The list of interesting changes are:
|
The list of interesting changes are:
|
||||||
|
|
||||||
@@ -129,43 +127,12 @@ RELEASE
|
|||||||
The libratbag project does not generate tarballs for releases, you can
|
The libratbag project does not generate tarballs for releases, you can
|
||||||
grab one directly from github:
|
grab one directly from github:
|
||||||
|
|
||||||
https://github.com/libratbag/libratbag/archive/$tag_name/$tarball
|
https://github.com/libratbag/$pkg_name/archive/$tag_name/$tarball
|
||||||
|
|
||||||
RELEASE
|
RELEASE
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# Function: read_modfile
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
#
|
|
||||||
# Read the module names from the file and set a variable to hold them
|
|
||||||
# This will be the same interface as cmd line supplied modules
|
|
||||||
#
|
|
||||||
read_modfile() {
|
|
||||||
|
|
||||||
if [ x"$MODFILE" != x ]; then
|
|
||||||
# Make sure the file is sane
|
|
||||||
if [ ! -r "$MODFILE" ]; then
|
|
||||||
echo "Error: module file '$MODFILE' is not readable or does not exist."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
# read from input file, skipping blank and comment lines
|
|
||||||
while read line; do
|
|
||||||
# skip blank lines
|
|
||||||
if [ x"$line" = x ]; then
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
# skip comment lines
|
|
||||||
if echo "$line" | $GREP -q "^#" ; then
|
|
||||||
continue;
|
|
||||||
fi
|
|
||||||
INPUT_MODULES="$INPUT_MODULES $line"
|
|
||||||
done <"$MODFILE"
|
|
||||||
fi
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------
|
||||||
# Function: print_epilog
|
# Function: print_epilog
|
||||||
#------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------
|
||||||
@@ -215,46 +182,6 @@ process_modules() {
|
|||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# Function: get_section
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# Code 'return 0' on success
|
|
||||||
# Code 'return 1' on error
|
|
||||||
# Sets global variable $section
|
|
||||||
get_section() {
|
|
||||||
local module_url
|
|
||||||
local full_module_url
|
|
||||||
|
|
||||||
# Obtain the git url in order to find the section to which this module belongs
|
|
||||||
full_module_url=`git config --get remote.$remote_name.url | sed 's:\.git$::'`
|
|
||||||
if [ $? -ne 0 ]; then
|
|
||||||
echo "Error: unable to obtain git url for remote \"$remote_name\"."
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# The last part of the git url will tell us the section. Look for xorg first
|
|
||||||
echo "$full_module_url"
|
|
||||||
module_url=`echo "$full_module_url" | $GREP -o "libratbag/.*"`
|
|
||||||
if [ $? -eq 0 ]; then
|
|
||||||
module_url=`echo $module_url | cut -d'/' -f2,3`
|
|
||||||
else
|
|
||||||
echo "Error: unable to locate a valid project url from \"$full_module_url\"."
|
|
||||||
echo "Cannot establish url as one of libratbag"
|
|
||||||
cd $top_src
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Find the section (subdirs) where the tarballs are to be uploaded
|
|
||||||
# The module relative path can be app/xfs, xserver, or mesa/drm for example
|
|
||||||
section=`echo $module_url | cut -d'/' -f1`
|
|
||||||
if [ $? -ne 0 ]; then
|
|
||||||
echo "Error: unable to extract section from $module_url first field."
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------
|
||||||
# Function: process_module
|
# Function: process_module
|
||||||
#------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------
|
||||||
@@ -299,26 +226,27 @@ process_module() {
|
|||||||
current_branch=`git branch | $GREP "\*" | sed -e "s/\* //"`
|
current_branch=`git branch | $GREP "\*" | sed -e "s/\* //"`
|
||||||
remote_name=`git config --get branch.$current_branch.remote`
|
remote_name=`git config --get branch.$current_branch.remote`
|
||||||
remote_branch=`git config --get branch.$current_branch.merge | cut -d'/' -f3,4`
|
remote_branch=`git config --get branch.$current_branch.merge | cut -d'/' -f3,4`
|
||||||
remote_url_root="https://github.com/libratbag/libratbag/archive"
|
|
||||||
echo "Info: working off the \"$current_branch\" branch tracking the remote \"$remote_name/$remote_branch\"."
|
echo "Info: working off the \"$current_branch\" branch tracking the remote \"$remote_name/$remote_branch\"."
|
||||||
|
|
||||||
# Obtain the section
|
|
||||||
get_section
|
|
||||||
if [ $? -ne 0 ]; then
|
|
||||||
cd $top_src
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Find out the tarname from meson.build
|
# Find out the tarname from meson.build
|
||||||
pkg_name=$($GREP '^project(' meson.build | sed 's|project(\([^\s,]*\).*|\1|' | sed "s/'//g")
|
pkg_name=$($GREP '^project(' meson.build | sed 's|project(\([^\s,]*\).*|\1|' | sed "s/'//g")
|
||||||
pkg_version=$($GREP -m 1 '^ version : ' meson.build | sed 's| version : \([^\s,]*\).*|\1|' | sed "s/'//g")
|
pkg_version=$($GREP -m 1 '^[ ]*version \?: ' meson.build | sed 's|[ ]*version \?: \([^\s,]*\).*|\1|' | sed "s/'//g")
|
||||||
tar_name="$pkg_name-$pkg_version"
|
tar_name="$pkg_name-$pkg_version"
|
||||||
targz=$tar_name.tar.gz
|
targz=$tar_name.tar.gz
|
||||||
tag_name=$(echo "v$pkg_version" | sed 's|.0$||')
|
# libratbag tags with v0.3 but piper user just 0.3
|
||||||
|
case `git describe` in
|
||||||
|
v*)
|
||||||
|
tag_name=$(echo "v$pkg_version" | sed 's|\.0$||')
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
tag_name=$(echo "$pkg_version" | sed 's|\.0$||')
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
remote_url_root="https://github.com/libratbag/$pkg_name/archive"
|
||||||
|
|
||||||
# Now get the tarballs from github directly to compute their checksum
|
# Now get the tarballs from github directly to compute their checksum
|
||||||
remote_targz_url=$remote_url_root/$tag_name/$targz
|
remote_targz_url=$remote_url_root/$tag_name/$targz
|
||||||
echo "downloading the tarbal from $remote_targz_url"
|
echo "downloading the tarball from $remote_targz_url"
|
||||||
curl $remote_targz_url > $targz
|
curl $remote_targz_url > $targz
|
||||||
|
|
||||||
# Obtain the top commit SHA which should be the version bump
|
# Obtain the top commit SHA which should be the version bump
|
||||||
@@ -513,13 +441,6 @@ do
|
|||||||
exit 1
|
exit 1
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
if [ x"${MODFILE}" != x ]; then
|
|
||||||
echo ""
|
|
||||||
echo "Error: specifying both modules and --modfile is not permitted"
|
|
||||||
echo ""
|
|
||||||
usage
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
INPUT_MODULES="${INPUT_MODULES} $1"
|
INPUT_MODULES="${INPUT_MODULES} $1"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
@@ -530,9 +451,6 @@ done
|
|||||||
# If no modules specified (blank cmd line) display help
|
# If no modules specified (blank cmd line) display help
|
||||||
check_modules_specification
|
check_modules_specification
|
||||||
|
|
||||||
# Read the module file and normalize input in INPUT_MODULES
|
|
||||||
read_modfile
|
|
||||||
|
|
||||||
# Loop through each module to release
|
# Loop through each module to release
|
||||||
# Exit on error if --no-quit no specified
|
# Exit on error if --no-quit no specified
|
||||||
process_modules
|
process_modules
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ struct hidpp20drv_data {
|
|||||||
unsigned num_controls;
|
unsigned num_controls;
|
||||||
struct hidpp20_control_id *controls;
|
struct hidpp20_control_id *controls;
|
||||||
struct hidpp20_profiles *profiles;
|
struct hidpp20_profiles *profiles;
|
||||||
|
struct hidpp20_led *leds;
|
||||||
union hidpp20_generic_led_zone_info led_infos;
|
union hidpp20_generic_led_zone_info led_infos;
|
||||||
|
|
||||||
unsigned int report_rates[4];
|
unsigned int report_rates[4];
|
||||||
@@ -334,14 +335,24 @@ static void
|
|||||||
hidpp20drv_read_led_8070(struct ratbag_led *led, struct hidpp20drv_data* drv_data)
|
hidpp20drv_read_led_8070(struct ratbag_led *led, struct hidpp20drv_data* drv_data)
|
||||||
{
|
{
|
||||||
struct hidpp20_profile *profile;
|
struct hidpp20_profile *profile;
|
||||||
struct hidpp20_led *h_led;
|
struct hidpp20_led h_led_val;
|
||||||
|
struct hidpp20_led *h_led = &h_led_val;
|
||||||
struct hidpp20_color_led_zone_info* led_info;
|
struct hidpp20_color_led_zone_info* led_info;
|
||||||
struct hidpp20_color_led_info info;
|
struct hidpp20_color_led_info info;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
led_info = &drv_data->led_infos.color_leds_8070[led->index];
|
led_info = &drv_data->led_infos.color_leds_8070[led->index];
|
||||||
profile = &drv_data->profiles->profiles[led->profile->index];
|
|
||||||
h_led = &profile->leds[led->index];
|
if (drv_data->capabilities & HIDPP_CAP_ONBOARD_PROFILES_8100) {
|
||||||
|
profile = &drv_data->profiles->profiles[led->profile->index];
|
||||||
|
h_led = &profile->leds[led->index];
|
||||||
|
} else {
|
||||||
|
rc = hidpp20_color_led_effects_get_zone_effect(drv_data->dev, led->index, h_led);
|
||||||
|
if (rc) {
|
||||||
|
log_debug(led->profile->device->ratbag,
|
||||||
|
"Failed to read led settings\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch (h_led->mode) {
|
switch (h_led->mode) {
|
||||||
case HIDPP20_LED_ON:
|
case HIDPP20_LED_ON:
|
||||||
@@ -397,10 +408,10 @@ hidpp20drv_read_led_8070(struct ratbag_led *led, struct hidpp20drv_data* drv_dat
|
|||||||
ratbag_led_set_mode_capability(led, RATBAG_LED_BREATHING);
|
ratbag_led_set_mode_capability(led, RATBAG_LED_BREATHING);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
log_bug_libratbag(led->profile->device->ratbag,
|
log_debug(led->profile->device->ratbag,
|
||||||
"%s: Unknown effect id %d\n",
|
"%s: Unsupported effect (%d)\n",
|
||||||
led->profile->device->name,
|
led->profile->device->name,
|
||||||
ei.effect_id);
|
ei.effect_id);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -412,11 +423,11 @@ hidpp20drv_read_led_8071(struct ratbag_led *led, struct hidpp20drv_data* drv_dat
|
|||||||
struct hidpp20_profile *profile;
|
struct hidpp20_profile *profile;
|
||||||
struct hidpp20_led *h_led;
|
struct hidpp20_led *h_led;
|
||||||
struct hidpp20_rgb_device_info device_info;
|
struct hidpp20_rgb_device_info device_info;
|
||||||
struct hidpp20_rgb_cluster_info *cluster_info;
|
struct hidpp20_rgb_cluster_info cluster_info;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
hidpp20_rgb_effects_get_device_info(drv_data->dev, &device_info);
|
hidpp20_rgb_effects_get_device_info(drv_data->dev, &device_info);
|
||||||
cluster_info = &drv_data->led_infos.color_leds_8071[led->index];
|
cluster_info = drv_data->led_infos.color_leds_8071[led->index];
|
||||||
profile = &drv_data->profiles->profiles[led->profile->index];
|
profile = &drv_data->profiles->profiles[led->profile->index];
|
||||||
h_led = &profile->leds[led->index];
|
h_led = &profile->leds[led->index];
|
||||||
|
|
||||||
@@ -437,7 +448,7 @@ hidpp20drv_read_led_8071(struct ratbag_led *led, struct hidpp20drv_data* drv_dat
|
|||||||
|
|
||||||
/* pre-filled, only override if unknown */
|
/* pre-filled, only override if unknown */
|
||||||
if (led->type == RATBAG_LED_TYPE_UNKNOWN)
|
if (led->type == RATBAG_LED_TYPE_UNKNOWN)
|
||||||
led->type = hidpp20_led_get_location_mapping(cluster_info->location);
|
led->type = hidpp20_led_get_location_mapping(cluster_info.location);
|
||||||
led->color.red = h_led->color.red;
|
led->color.red = h_led->color.red;
|
||||||
led->color.green = h_led->color.green;
|
led->color.green = h_led->color.green;
|
||||||
led->color.blue = h_led->color.blue;
|
led->color.blue = h_led->color.blue;
|
||||||
@@ -449,10 +460,10 @@ hidpp20drv_read_led_8071(struct ratbag_led *led, struct hidpp20drv_data* drv_dat
|
|||||||
else
|
else
|
||||||
led->colordepth = RATBAG_LED_COLORDEPTH_RGB_888;
|
led->colordepth = RATBAG_LED_COLORDEPTH_RGB_888;
|
||||||
|
|
||||||
for (int i = 0; i < cluster_info->num_effects; i++) {
|
for (int i = 0; i < cluster_info.num_effects; i++) {
|
||||||
struct hidpp20_rgb_effect_info ei;
|
struct hidpp20_rgb_effect_info ei;
|
||||||
rc = hidpp20_rgb_effects_get_effect_info(drv_data->dev,
|
rc = hidpp20_rgb_effects_get_effect_info(drv_data->dev,
|
||||||
cluster_info->index,
|
cluster_info.index,
|
||||||
i, &ei);
|
i, &ei);
|
||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
break;
|
break;
|
||||||
@@ -472,10 +483,10 @@ hidpp20drv_read_led_8071(struct ratbag_led *led, struct hidpp20drv_data* drv_dat
|
|||||||
ratbag_led_set_mode_capability(led, RATBAG_LED_BREATHING);
|
ratbag_led_set_mode_capability(led, RATBAG_LED_BREATHING);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
log_bug_libratbag(led->profile->device->ratbag,
|
log_debug(led->profile->device->ratbag,
|
||||||
"%s: Unknown effect id %d\n",
|
"%s: Unsupported effect (%d)\n",
|
||||||
led->profile->device->name,
|
led->profile->device->name,
|
||||||
ei.effect_id);
|
ei.effect_id);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -691,11 +702,13 @@ hidpp20drv_update_led_8070_8071(struct ratbag_led *led, struct ratbag_profile* p
|
|||||||
struct hidpp20drv_data *drv_data)
|
struct hidpp20drv_data *drv_data)
|
||||||
{
|
{
|
||||||
struct hidpp20_profile *h_profile;
|
struct hidpp20_profile *h_profile;
|
||||||
struct hidpp20_led *h_led;
|
struct hidpp20_led h_led_val;
|
||||||
|
struct hidpp20_led *h_led = &h_led_val;
|
||||||
|
|
||||||
h_profile = &drv_data->profiles->profiles[profile->index];
|
if (drv_data->capabilities & HIDPP_CAP_ONBOARD_PROFILES_8100) {
|
||||||
|
h_profile = &drv_data->profiles->profiles[profile->index];
|
||||||
h_led = &(h_profile->leds[led->index]);
|
h_led = &(h_profile->leds[led->index]);
|
||||||
|
}
|
||||||
|
|
||||||
if (!h_led)
|
if (!h_led)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@@ -720,6 +733,13 @@ hidpp20drv_update_led_8070_8071(struct ratbag_led *led, struct ratbag_profile* p
|
|||||||
h_led->period = led->ms;
|
h_led->period = led->ms;
|
||||||
h_led->brightness = led->brightness * 100 / 255;
|
h_led->brightness = led->brightness * 100 / 255;
|
||||||
|
|
||||||
|
if (!(drv_data->capabilities & HIDPP_CAP_ONBOARD_PROFILES_8100)) {
|
||||||
|
if (drv_data->capabilities & HIDPP_CAP_COLOR_LED_EFFECTS_8070)
|
||||||
|
hidpp20_color_led_effects_set_zone_effect(drv_data->dev,
|
||||||
|
led->index,
|
||||||
|
h_led_val);
|
||||||
|
}
|
||||||
|
|
||||||
return RATBAG_SUCCESS;
|
return RATBAG_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -822,9 +842,12 @@ hidpp20drv_read_report_rate_8060(struct ratbag_device *device)
|
|||||||
{
|
{
|
||||||
struct hidpp20drv_data *drv_data = ratbag_get_drv_data(device);
|
struct hidpp20drv_data *drv_data = ratbag_get_drv_data(device);
|
||||||
struct ratbag *ratbag = device->ratbag;
|
struct ratbag *ratbag = device->ratbag;
|
||||||
|
struct ratbag_profile *profile;
|
||||||
uint8_t bitflags_ms;
|
uint8_t bitflags_ms;
|
||||||
int nrates = 0;
|
int nrates = 0;
|
||||||
int rc;
|
int rc;
|
||||||
|
uint8_t rate_ms;
|
||||||
|
unsigned rate_hz;
|
||||||
|
|
||||||
rc = hidpp20_adjustable_report_rate_get_report_rate_list(drv_data->dev,
|
rc = hidpp20_adjustable_report_rate_get_report_rate_list(drv_data->dev,
|
||||||
&bitflags_ms);
|
&bitflags_ms);
|
||||||
@@ -843,6 +866,37 @@ hidpp20drv_read_report_rate_8060(struct ratbag_device *device)
|
|||||||
|
|
||||||
drv_data->num_report_rates = nrates;
|
drv_data->num_report_rates = nrates;
|
||||||
|
|
||||||
|
if (!hidpp20_adjustable_report_rate_get_report_rate(drv_data->dev, &rate_ms)) {
|
||||||
|
switch (rate_ms)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
rate_hz = 1000;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
case 3: /* 3ms = 333.(3)Hz, we round to 500Hz */
|
||||||
|
rate_hz = 500;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
case 5: /* 5ms = 200Hz, we round to 250Hz */
|
||||||
|
rate_hz = 250;
|
||||||
|
break;
|
||||||
|
case 6: /* 6ms = 166.(6)Hz, we round to 125Hz */
|
||||||
|
case 7: /* 7ms = 142Hz, we round to 125Hz */
|
||||||
|
case 8:
|
||||||
|
rate_hz = 125;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
rate_hz = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rate_hz) {
|
||||||
|
log_debug(ratbag, "report rate is %u\n", rate_hz);
|
||||||
|
ratbag_device_for_each_profile(device, profile)
|
||||||
|
profile->hz = rate_hz;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
log_debug(ratbag, "device has %d report rates\n", nrates);
|
log_debug(ratbag, "device has %d report rates\n", nrates);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -859,7 +913,8 @@ hidpp20drv_read_resolution_dpi(struct ratbag_profile *profile)
|
|||||||
unsigned int default_rate = 500;
|
unsigned int default_rate = 500;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if (drv_data->capabilities & HIDPP_CAP_RESOLUTION_2200) {
|
if ((drv_data->capabilities & HIDPP_CAP_RESOLUTION_2200) &&
|
||||||
|
(drv_data->capabilities & HIDPP_CAP_SWITCHABLE_RESOLUTION_2201) == 0) {
|
||||||
uint16_t resolution;
|
uint16_t resolution;
|
||||||
uint8_t flags;
|
uint8_t flags;
|
||||||
|
|
||||||
@@ -928,6 +983,9 @@ hidpp20drv_update_resolution_dpi_8100(struct ratbag_resolution *resolution,
|
|||||||
h_profile = &drv_data->profiles->profiles[profile->index];
|
h_profile = &drv_data->profiles->profiles[profile->index];
|
||||||
h_profile->dpi[resolution->index] = dpi;
|
h_profile->dpi[resolution->index] = dpi;
|
||||||
|
|
||||||
|
if (resolution->is_default)
|
||||||
|
h_profile->default_dpi = resolution->index;
|
||||||
|
|
||||||
return RATBAG_SUCCESS;
|
return RATBAG_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -939,7 +997,7 @@ hidpp20drv_update_resolution_dpi(struct ratbag_resolution *resolution,
|
|||||||
struct ratbag_device *device = profile->device;
|
struct ratbag_device *device = profile->device;
|
||||||
struct hidpp20drv_data *drv_data = ratbag_get_drv_data(device);
|
struct hidpp20drv_data *drv_data = ratbag_get_drv_data(device);
|
||||||
struct hidpp20_sensor *sensor;
|
struct hidpp20_sensor *sensor;
|
||||||
int rc, i;
|
int i;
|
||||||
int dpi = dpi_x; /* dpi_x == dpi_y if we don't have the individual resolution cap */
|
int dpi = dpi_x; /* dpi_x == dpi_y if we don't have the individual resolution cap */
|
||||||
|
|
||||||
if (drv_data->capabilities & HIDPP_CAP_ONBOARD_PROFILES_8100)
|
if (drv_data->capabilities & HIDPP_CAP_ONBOARD_PROFILES_8100)
|
||||||
@@ -955,14 +1013,13 @@ hidpp20drv_update_resolution_dpi(struct ratbag_resolution *resolution,
|
|||||||
sensor = &drv_data->sensors[0];
|
sensor = &drv_data->sensors[0];
|
||||||
|
|
||||||
/* validate that the sensor accepts the given DPI */
|
/* validate that the sensor accepts the given DPI */
|
||||||
rc = -EINVAL;
|
|
||||||
if (dpi < sensor->dpi_min || dpi > sensor->dpi_max)
|
if (dpi < sensor->dpi_min || dpi > sensor->dpi_max)
|
||||||
goto out;
|
return -EINVAL;
|
||||||
if (sensor->dpi_steps) {
|
if (sensor->dpi_steps) {
|
||||||
for (i = sensor->dpi_min; i < dpi; i += sensor->dpi_steps) {
|
for (i = sensor->dpi_min; i < dpi; i += sensor->dpi_steps) {
|
||||||
}
|
}
|
||||||
if (i != dpi)
|
if (i != dpi)
|
||||||
goto out;
|
return -EINVAL;
|
||||||
} else {
|
} else {
|
||||||
i = 0;
|
i = 0;
|
||||||
while (sensor->dpi_list[i]) {
|
while (sensor->dpi_list[i]) {
|
||||||
@@ -970,13 +1027,24 @@ hidpp20drv_update_resolution_dpi(struct ratbag_resolution *resolution,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (sensor->dpi_list[i] != dpi)
|
if (sensor->dpi_list[i] != dpi)
|
||||||
goto out;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = hidpp20_adjustable_dpi_set_sensor_dpi(drv_data->dev, sensor, dpi);
|
return hidpp20_adjustable_dpi_set_sensor_dpi(drv_data->dev, sensor, dpi);
|
||||||
|
}
|
||||||
|
|
||||||
out:
|
static int
|
||||||
return rc;
|
hidpp20drv_update_report_rate_8060(struct ratbag_profile *profile, int hz)
|
||||||
|
{
|
||||||
|
struct ratbag_device *device = profile->device;
|
||||||
|
struct hidpp20drv_data *drv_data = ratbag_get_drv_data(device);
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = hidpp20_adjustable_report_rate_set_report_rate(drv_data->dev, 1000/hz);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
return RATBAG_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@@ -997,12 +1065,20 @@ hidpp20drv_update_report_rate(struct ratbag_profile *profile, int hz)
|
|||||||
{
|
{
|
||||||
struct ratbag_device *device = profile->device;
|
struct ratbag_device *device = profile->device;
|
||||||
struct hidpp20drv_data *drv_data = ratbag_get_drv_data(device);
|
struct hidpp20drv_data *drv_data = ratbag_get_drv_data(device);
|
||||||
|
int rc;
|
||||||
|
|
||||||
if (drv_data->capabilities & HIDPP_CAP_ONBOARD_PROFILES_8100)
|
if (drv_data->capabilities & HIDPP_CAP_ONBOARD_PROFILES_8100)
|
||||||
return hidpp20drv_update_report_rate_8100(profile, hz);
|
return hidpp20drv_update_report_rate_8100(profile, hz);
|
||||||
|
|
||||||
if (drv_data->capabilities & HIDPP_CAP_ADJUSTIBLE_REPORT_RATE_8060)
|
if (drv_data->capabilities & HIDPP_CAP_ADJUSTIBLE_REPORT_RATE_8060) {
|
||||||
return -ENOTSUP;
|
rc = hidpp20drv_update_report_rate_8060(profile, hz);
|
||||||
|
|
||||||
|
/* re-populate the profile with the correct value if we fail */
|
||||||
|
if (rc)
|
||||||
|
hidpp20drv_read_report_rate_8060(profile->device);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
@@ -1175,6 +1251,60 @@ hidpp20drv_read_profile_8100(struct ratbag_profile *profile)
|
|||||||
ratbag_profile_set_report_rate(profile, p->report_rate);
|
ratbag_profile_set_report_rate(profile, p->report_rate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
hidpp20drv_init_leds_8070_8071(struct ratbag_device *device)
|
||||||
|
{
|
||||||
|
struct hidpp20drv_data *drv_data = ratbag_get_drv_data(device);
|
||||||
|
struct ratbag *ratbag = device->ratbag;
|
||||||
|
|
||||||
|
/* we only support 0x8071 via 0x8100 */
|
||||||
|
if (!(drv_data->capabilities & HIDPP_CAP_ONBOARD_PROFILES_8100) &&
|
||||||
|
drv_data->capabilities & HIDPP_CAP_RGB_EFFECTS_8071) {
|
||||||
|
log_debug(ratbag, "disabling 0x8071 (RGB Effects) feature because the device doesn't have 0x8100 (Onboard Memory Profiles)\n");
|
||||||
|
drv_data->capabilities &= ~HIDPP_CAP_RGB_EFFECTS_8071;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (drv_data->capabilities & HIDPP_CAP_COLOR_LED_EFFECTS_8070 ||
|
||||||
|
drv_data->capabilities & HIDPP_CAP_RGB_EFFECTS_8071) {
|
||||||
|
/* we read the profile once to get the correct number of
|
||||||
|
* supported leds. */
|
||||||
|
if (hidpp20drv_read_color_leds(device))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
device->num_leds = drv_data->num_leds;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
hidpp20drv_init_profile_8100(struct ratbag_device *device)
|
||||||
|
{
|
||||||
|
struct hidpp20drv_data *drv_data = ratbag_get_drv_data(device);
|
||||||
|
struct ratbag *ratbag = device->ratbag;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
log_debug(ratbag, "initializing onboard profiles\n");
|
||||||
|
rc = hidpp20_onboard_profiles_allocate(drv_data->dev, &drv_data->profiles);
|
||||||
|
if (rc < 0)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
rc = hidpp20_onboard_profiles_initialize(drv_data->dev, drv_data->profiles);
|
||||||
|
if (rc < 0)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
drv_data->num_profiles = drv_data->profiles->num_profiles;
|
||||||
|
drv_data->num_buttons = drv_data->profiles->num_buttons;
|
||||||
|
|
||||||
|
if (drv_data->capabilities & HIDPP_CAP_SWITCHABLE_RESOLUTION_2201)
|
||||||
|
drv_data->num_resolutions = drv_data->profiles->num_modes;
|
||||||
|
/* We ignore the profile's num_leds and require
|
||||||
|
* HIDPP_PAGE_COLOR_LED_EFFECTS to succeed instead
|
||||||
|
*/
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
hidpp20drv_read_profile(struct ratbag_profile *profile)
|
hidpp20drv_read_profile(struct ratbag_profile *profile)
|
||||||
{
|
{
|
||||||
@@ -1302,27 +1432,18 @@ hidpp20drv_init_feature(struct ratbag_device *device, uint16_t feature)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case HIDPP_PAGE_COLOR_LED_EFFECTS: {
|
case HIDPP_PAGE_COLOR_LED_EFFECTS: {
|
||||||
|
/* The 8070 feauture implemented in the G602 doesn't follow the spec,
|
||||||
|
* so we ignore it */
|
||||||
|
if (ratbag_device_data_hidpp20_get_quirk(device->data) == HIDPP20_QUIRK_G602)
|
||||||
|
break;
|
||||||
|
|
||||||
log_debug(ratbag, "device has color effects\n");
|
log_debug(ratbag, "device has color effects\n");
|
||||||
drv_data->capabilities |= HIDPP_CAP_COLOR_LED_EFFECTS_8070;
|
drv_data->capabilities |= HIDPP_CAP_COLOR_LED_EFFECTS_8070;
|
||||||
|
|
||||||
/* we read the profile once to get the correct number of
|
|
||||||
* supported leds. */
|
|
||||||
if (hidpp20drv_read_color_leds(device))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
device->num_leds = drv_data->num_leds;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case HIDPP_PAGE_RGB_EFFECTS: {
|
case HIDPP_PAGE_RGB_EFFECTS: {
|
||||||
log_debug(ratbag, "device has color effects\n");
|
log_debug(ratbag, "device has color effects\n");
|
||||||
drv_data->capabilities |= HIDPP_CAP_RGB_EFFECTS_8071;
|
drv_data->capabilities |= HIDPP_CAP_RGB_EFFECTS_8071;
|
||||||
|
|
||||||
/* we read the profile once to get the correct number of
|
|
||||||
* supported leds. */
|
|
||||||
if (hidpp20drv_read_color_leds(device))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
device->num_leds = drv_data->num_leds;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case HIDPP_PAGE_LED_SW_CONTROL: {
|
case HIDPP_PAGE_LED_SW_CONTROL: {
|
||||||
@@ -1340,22 +1461,6 @@ hidpp20drv_init_feature(struct ratbag_device *device, uint16_t feature)
|
|||||||
case HIDPP_PAGE_ONBOARD_PROFILES: {
|
case HIDPP_PAGE_ONBOARD_PROFILES: {
|
||||||
log_debug(ratbag, "device has onboard profiles\n");
|
log_debug(ratbag, "device has onboard profiles\n");
|
||||||
drv_data->capabilities |= HIDPP_CAP_ONBOARD_PROFILES_8100;
|
drv_data->capabilities |= HIDPP_CAP_ONBOARD_PROFILES_8100;
|
||||||
|
|
||||||
rc = hidpp20_onboard_profiles_allocate(drv_data->dev, &drv_data->profiles);
|
|
||||||
if (rc < 0)
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
rc = hidpp20_onboard_profiles_initialize(drv_data->dev, drv_data->profiles);
|
|
||||||
if (rc < 0)
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
drv_data->num_profiles = drv_data->profiles->num_profiles;
|
|
||||||
drv_data->num_resolutions = drv_data->profiles->num_modes;
|
|
||||||
drv_data->num_buttons = drv_data->profiles->num_buttons;
|
|
||||||
/* We ignore the profile's num_leds and require
|
|
||||||
* HIDPP_PAGE_COLOR_LED_EFFECTS to succeed instead
|
|
||||||
*/
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case HIDPP_PAGE_MOUSE_BUTTON_SPY: {
|
case HIDPP_PAGE_MOUSE_BUTTON_SPY: {
|
||||||
@@ -1377,27 +1482,27 @@ hidpp20drv_commit(struct ratbag_device *device)
|
|||||||
struct ratbag_led *led;
|
struct ratbag_led *led;
|
||||||
struct ratbag_resolution *resolution;
|
struct ratbag_resolution *resolution;
|
||||||
int rc;
|
int rc;
|
||||||
unsigned int dpi_index = 0;
|
|
||||||
|
|
||||||
list_for_each(profile, &device->profiles, link) {
|
list_for_each(profile, &device->profiles, link) {
|
||||||
if (!profile->dirty)
|
if (!profile->dirty)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
rc = hidpp20drv_update_report_rate(profile, profile->hz);
|
if (profile->rate_dirty) {
|
||||||
if (rc)
|
rc = hidpp20drv_update_report_rate(profile, profile->hz);
|
||||||
return RATBAG_ERROR_DEVICE;
|
if (rc) {
|
||||||
|
log_error(device->ratbag, "hidpp20: failed to update report rate\n");
|
||||||
|
return RATBAG_ERROR_DEVICE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ratbag_profile_for_each_resolution(profile, resolution) {
|
ratbag_profile_for_each_resolution(profile, resolution) {
|
||||||
if (resolution->is_active) {
|
|
||||||
log_raw(device->ratbag, "dpi index: %d, profile %d\n", resolution->index, profile->index);
|
|
||||||
dpi_index = resolution->index;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = hidpp20drv_update_resolution_dpi(resolution,
|
rc = hidpp20drv_update_resolution_dpi(resolution,
|
||||||
resolution->dpi_x,
|
resolution->dpi_x,
|
||||||
resolution->dpi_y);
|
resolution->dpi_y);
|
||||||
if (rc)
|
if (rc) {
|
||||||
|
log_error(device->ratbag, "hidpp20: failed to update resolution\n");
|
||||||
return RATBAG_ERROR_DEVICE;
|
return RATBAG_ERROR_DEVICE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
list_for_each(button, &profile->buttons, link) {
|
list_for_each(button, &profile->buttons, link) {
|
||||||
@@ -1405,8 +1510,10 @@ hidpp20drv_commit(struct ratbag_device *device)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
rc = hidpp20drv_update_button(button);
|
rc = hidpp20drv_update_button(button);
|
||||||
if (rc)
|
if (rc) {
|
||||||
|
log_error(device->ratbag, "hidpp20: failed to update button\n");
|
||||||
return RATBAG_ERROR_DEVICE;
|
return RATBAG_ERROR_DEVICE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
list_for_each(led, &profile->leds, link) {
|
list_for_each(led, &profile->leds, link) {
|
||||||
@@ -1414,10 +1521,11 @@ hidpp20drv_commit(struct ratbag_device *device)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
rc = hidpp20drv_update_led(led);
|
rc = hidpp20drv_update_led(led);
|
||||||
if (rc)
|
if (rc) {
|
||||||
|
log_error(device->ratbag, "hidpp20: failed to update led\n");
|
||||||
return RATBAG_ERROR_DEVICE;
|
return RATBAG_ERROR_DEVICE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (drv_data->capabilities & HIDPP_CAP_ONBOARD_PROFILES_8100) {
|
if (drv_data->capabilities & HIDPP_CAP_ONBOARD_PROFILES_8100) {
|
||||||
@@ -1426,17 +1534,18 @@ hidpp20drv_commit(struct ratbag_device *device)
|
|||||||
|
|
||||||
rc = hidpp20_onboard_profiles_commit(drv_data->dev,
|
rc = hidpp20_onboard_profiles_commit(drv_data->dev,
|
||||||
drv_data->profiles);
|
drv_data->profiles);
|
||||||
if (rc)
|
if (rc) {
|
||||||
|
log_error(device->ratbag, "hidpp20: failed to commit profile\n");
|
||||||
return RATBAG_ERROR_DEVICE;
|
return RATBAG_ERROR_DEVICE;
|
||||||
|
}
|
||||||
|
|
||||||
list_for_each(profile, &device->profiles, link) {
|
list_for_each(profile, &device->profiles, link) {
|
||||||
if (profile->is_active) {
|
if (profile->is_active) {
|
||||||
ratbag_profile_for_each_resolution(profile, resolution) {
|
ratbag_profile_for_each_resolution(profile, resolution) {
|
||||||
if (resolution->is_active)
|
if (resolution->is_active)
|
||||||
dpi_index = resolution->index;
|
hidpp20_onboard_profiles_set_current_dpi_index(drv_data->dev,
|
||||||
|
resolution->index);
|
||||||
}
|
}
|
||||||
hidpp20_onboard_profiles_set_current_dpi_index(drv_data->dev,
|
|
||||||
dpi_index);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1467,8 +1576,21 @@ hidpp20drv_20_probe(struct ratbag_device *device)
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
/* initializations that depend on other features */
|
||||||
|
if (drv_data->capabilities & HIDPP_CAP_COLOR_LED_EFFECTS_8070 ||
|
||||||
|
drv_data->capabilities & HIDPP_CAP_RGB_EFFECTS_8071) {
|
||||||
|
rc = hidpp20drv_init_leds_8070_8071(device);
|
||||||
|
if (rc < 0)
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (drv_data->capabilities & HIDPP_CAP_ONBOARD_PROFILES_8100) {
|
||||||
|
rc = hidpp20drv_init_profile_8100(device);
|
||||||
|
if (rc < 0)
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@@ -1500,9 +1622,9 @@ hidpp20drv_remove(struct ratbag_device *device)
|
|||||||
if (drv_data->profiles)
|
if (drv_data->profiles)
|
||||||
hidpp20_onboard_profiles_destroy(drv_data->profiles);
|
hidpp20_onboard_profiles_destroy(drv_data->profiles);
|
||||||
free(drv_data->led_infos.color_leds_8070);
|
free(drv_data->led_infos.color_leds_8070);
|
||||||
free(drv_data->led_infos.color_leds_8071);
|
|
||||||
free(drv_data->controls);
|
free(drv_data->controls);
|
||||||
free(drv_data->sensors);
|
free(drv_data->sensors);
|
||||||
|
free(drv_data->leds);
|
||||||
if (drv_data->dev)
|
if (drv_data->dev)
|
||||||
hidpp20_device_destroy(drv_data->dev);
|
hidpp20_device_destroy(drv_data->dev);
|
||||||
free(drv_data);
|
free(drv_data);
|
||||||
@@ -1513,6 +1635,7 @@ hidpp20drv_init_device(struct ratbag_device *device,
|
|||||||
struct hidpp20drv_data *drv_data)
|
struct hidpp20drv_data *drv_data)
|
||||||
{
|
{
|
||||||
struct ratbag_profile *profile;
|
struct ratbag_profile *profile;
|
||||||
|
bool active_profile = false;
|
||||||
|
|
||||||
ratbag_device_init_profiles(device,
|
ratbag_device_init_profiles(device,
|
||||||
drv_data->num_profiles,
|
drv_data->num_profiles,
|
||||||
@@ -1522,6 +1645,18 @@ hidpp20drv_init_device(struct ratbag_device *device,
|
|||||||
|
|
||||||
ratbag_device_for_each_profile(device, profile)
|
ratbag_device_for_each_profile(device, profile)
|
||||||
hidpp20drv_read_profile(profile);
|
hidpp20drv_read_profile(profile);
|
||||||
|
|
||||||
|
if (drv_data->capabilities & HIDPP_CAP_ONBOARD_PROFILES_8100) {
|
||||||
|
/* Fallback to the first profile if no profile is active */
|
||||||
|
list_for_each(profile, &device->profiles, link)
|
||||||
|
if (profile->is_active)
|
||||||
|
active_profile = true;
|
||||||
|
|
||||||
|
if (!active_profile && device->num_profiles >= 1) {
|
||||||
|
profile = ratbag_device_get_profile(device, 0);
|
||||||
|
profile->is_active = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@@ -1554,19 +1689,24 @@ hidpp20drv_probe(struct ratbag_device *device)
|
|||||||
* If there is a special need like for G900, we can add this in the
|
* If there is a special need like for G900, we can add this in the
|
||||||
* device data file.
|
* device data file.
|
||||||
*/
|
*/
|
||||||
dev = hidpp20_device_new(&base, device_idx);
|
dev = hidpp20_device_new(&base, device_idx, (struct hidpp_hid_report*) device->hidraw[0].reports, device->hidraw[0].num_reports);
|
||||||
if (!dev) {
|
if (!dev) {
|
||||||
rc = -ENODEV;
|
rc = -ENODEV;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dev->quirk = ratbag_device_data_hidpp20_get_quirk(device->data);
|
||||||
|
|
||||||
drv_data->dev = dev;
|
drv_data->dev = dev;
|
||||||
|
|
||||||
log_debug(device->ratbag, "'%s' is using protocol v%d.%d\n", ratbag_device_get_name(device), dev->proto_major, dev->proto_minor);
|
log_debug(device->ratbag, "'%s' is using protocol v%d.%d\n", ratbag_device_get_name(device), dev->proto_major, dev->proto_minor);
|
||||||
|
|
||||||
|
if(dev->quirk != HIDPP20_QUIRK_NONE)
|
||||||
|
log_debug(device->ratbag, "'%s' is quirked (%s)\n", ratbag_device_get_name(device), hidpp20_get_quirk_string(dev->quirk));
|
||||||
|
|
||||||
/* add some defaults that will be overwritten by the device */
|
/* add some defaults that will be overwritten by the device */
|
||||||
drv_data->num_profiles = 1;
|
drv_data->num_profiles = 1;
|
||||||
drv_data->num_resolutions = 1;
|
drv_data->num_resolutions = 0;
|
||||||
drv_data->num_buttons = 8;
|
drv_data->num_buttons = 8;
|
||||||
drv_data->num_leds = 0;
|
drv_data->num_leds = 0;
|
||||||
|
|
||||||
|
|||||||
845
src/driver-roccat-kone-pure.c
Normal file
845
src/driver-roccat-kone-pure.c
Normal file
@@ -0,0 +1,845 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2015 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the next
|
||||||
|
* paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
* Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <libevdev/libevdev.h>
|
||||||
|
#include <linux/input.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "libratbag-private.h"
|
||||||
|
#include "libratbag-hidraw.h"
|
||||||
|
|
||||||
|
#define ROCCAT_PROFILE_MAX 4
|
||||||
|
#define ROCCAT_BUTTON_MAX 17
|
||||||
|
#define ROCCAT_NUM_DPI 5
|
||||||
|
#define ROCCAT_LED_MAX 0
|
||||||
|
|
||||||
|
#define ROCCAT_MAX_RETRY_READY 10
|
||||||
|
|
||||||
|
#define ROCCAT_REPORT_ID_CONFIGURE_PROFILE 4
|
||||||
|
#define ROCCAT_REPORT_ID_PROFILE 5
|
||||||
|
#define ROCCAT_REPORT_ID_SETTINGS 6
|
||||||
|
#define ROCCAT_REPORT_ID_KEY_MAPPING 7
|
||||||
|
#define ROCCAT_REPORT_ID_MACRO 8
|
||||||
|
|
||||||
|
#define ROCCAT_REPORT_SIZE_PROFILE 59
|
||||||
|
#define ROCCAT_REPORT_SIZE_SETTINGS 31
|
||||||
|
#define ROCCAT_REPORT_SIZE_MACRO 2082
|
||||||
|
|
||||||
|
#define ROCCAT_CONFIG_SETTINGS 0x80
|
||||||
|
#define ROCCAT_CONFIG_KEY_MAPPING 0x90
|
||||||
|
|
||||||
|
#define ROCCAT_MAX_MACRO_LENGTH 500
|
||||||
|
|
||||||
|
struct roccat_settings_report {
|
||||||
|
uint8_t reportID;
|
||||||
|
uint8_t twoB;
|
||||||
|
uint8_t profileID;
|
||||||
|
uint8_t x_y_linked;
|
||||||
|
uint8_t x_sensitivity; /* 0x06 means 0 */
|
||||||
|
uint8_t y_sensitivity; /* 0x06 means 0 */
|
||||||
|
uint8_t dpi_mask;
|
||||||
|
uint8_t xres[5];
|
||||||
|
uint8_t current_dpi;
|
||||||
|
uint8_t yres[5];
|
||||||
|
uint8_t padding1;
|
||||||
|
uint8_t report_rate;
|
||||||
|
uint8_t padding2[11];
|
||||||
|
// uint16_t checksum;
|
||||||
|
// uint8_t padding2[4];
|
||||||
|
// uint8_t light;
|
||||||
|
// uint8_t light_heartbit;
|
||||||
|
// uint8_t padding3[5];
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
struct roccat_macro {
|
||||||
|
uint8_t reportID;
|
||||||
|
uint8_t twentytwo;
|
||||||
|
uint8_t height;
|
||||||
|
uint8_t profile;
|
||||||
|
uint8_t button_index;
|
||||||
|
uint8_t active;
|
||||||
|
uint8_t padding[24];
|
||||||
|
char group[24];
|
||||||
|
char name[24];
|
||||||
|
uint16_t length;
|
||||||
|
struct {
|
||||||
|
uint8_t keycode;
|
||||||
|
uint8_t flag;
|
||||||
|
uint16_t time;
|
||||||
|
} keys[ROCCAT_MAX_MACRO_LENGTH];
|
||||||
|
uint16_t checksum;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
struct roccat_data {
|
||||||
|
uint8_t profiles[(ROCCAT_PROFILE_MAX + 1)][ROCCAT_REPORT_SIZE_PROFILE];
|
||||||
|
struct roccat_settings_report settings[(ROCCAT_PROFILE_MAX + 1)];
|
||||||
|
struct roccat_macro macros[(ROCCAT_PROFILE_MAX + 1)][(ROCCAT_BUTTON_MAX + 1)];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct roccat_button_type_mapping {
|
||||||
|
uint8_t raw;
|
||||||
|
enum ratbag_button_type type;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct roccat_button_type_mapping roccat_button_type_mapping[] = {
|
||||||
|
{ 0, RATBAG_BUTTON_TYPE_LEFT },
|
||||||
|
{ 1, RATBAG_BUTTON_TYPE_RIGHT },
|
||||||
|
{ 2, RATBAG_BUTTON_TYPE_MIDDLE },
|
||||||
|
{ 3, RATBAG_BUTTON_TYPE_EXTRA },
|
||||||
|
{ 4, RATBAG_BUTTON_TYPE_SIDE },
|
||||||
|
{ 5, RATBAG_BUTTON_TYPE_WHEEL_UP },
|
||||||
|
{ 6, RATBAG_BUTTON_TYPE_WHEEL_DOWN },
|
||||||
|
{ 7, RATBAG_BUTTON_TYPE_RESOLUTION_UP },
|
||||||
|
{ 8, RATBAG_BUTTON_TYPE_RESOLUTION_DOWN },
|
||||||
|
{ 9, RATBAG_BUTTON_TYPE_LEFT },
|
||||||
|
{ 10, RATBAG_BUTTON_TYPE_RIGHT },
|
||||||
|
{ 11, RATBAG_BUTTON_TYPE_MIDDLE },
|
||||||
|
{ 12, RATBAG_BUTTON_TYPE_EXTRA },
|
||||||
|
{ 13, RATBAG_BUTTON_TYPE_SIDE },
|
||||||
|
{ 14, RATBAG_BUTTON_TYPE_WHEEL_UP },
|
||||||
|
{ 15, RATBAG_BUTTON_TYPE_WHEEL_DOWN },
|
||||||
|
{ 16, RATBAG_BUTTON_TYPE_RESOLUTION_UP },
|
||||||
|
{ 17, RATBAG_BUTTON_TYPE_RESOLUTION_DOWN },
|
||||||
|
};
|
||||||
|
|
||||||
|
static enum ratbag_button_type
|
||||||
|
roccat_raw_to_button_type(uint8_t data)
|
||||||
|
{
|
||||||
|
const struct roccat_button_type_mapping *mapping;
|
||||||
|
|
||||||
|
ARRAY_FOR_EACH(roccat_button_type_mapping, mapping) {
|
||||||
|
if (mapping->raw == data)
|
||||||
|
return mapping->type;
|
||||||
|
}
|
||||||
|
|
||||||
|
return RATBAG_BUTTON_TYPE_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct roccat_button_mapping {
|
||||||
|
uint8_t raw;
|
||||||
|
struct ratbag_button_action action;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct roccat_button_mapping roccat_button_mapping[] = {
|
||||||
|
/* FIXME: { 0, Disabled }, */
|
||||||
|
{ 1, BUTTON_ACTION_BUTTON(1) },
|
||||||
|
{ 2, BUTTON_ACTION_BUTTON(2) },
|
||||||
|
{ 3, BUTTON_ACTION_BUTTON(3) },
|
||||||
|
{ 4, BUTTON_ACTION_SPECIAL(RATBAG_BUTTON_ACTION_SPECIAL_DOUBLECLICK) },
|
||||||
|
/* FIXME: { 5, Shortcut (modifier + key) }, */
|
||||||
|
{ 6, BUTTON_ACTION_NONE },
|
||||||
|
{ 7, BUTTON_ACTION_BUTTON(4) },
|
||||||
|
{ 8, BUTTON_ACTION_BUTTON(5) },
|
||||||
|
//{ 9, BUTTON_ACTION_SPECIAL(RATBAG_BUTTON_ACTION_SPECIAL_WHEEL_LEFT) },
|
||||||
|
//{ 10, BUTTON_ACTION_SPECIAL(RATBAG_BUTTON_ACTION_SPECIAL_WHEEL_RIGHT) },
|
||||||
|
{ 13, BUTTON_ACTION_SPECIAL(RATBAG_BUTTON_ACTION_SPECIAL_WHEEL_UP) },
|
||||||
|
{ 14, BUTTON_ACTION_SPECIAL(RATBAG_BUTTON_ACTION_SPECIAL_WHEEL_DOWN) },
|
||||||
|
/* FIXME: { 15, quicklaunch }, -> hidraw report 03 00 60 07 01 00 00 00 */
|
||||||
|
{ 16, BUTTON_ACTION_SPECIAL(RATBAG_BUTTON_ACTION_SPECIAL_PROFILE_CYCLE_UP) },
|
||||||
|
{ 17, BUTTON_ACTION_SPECIAL(RATBAG_BUTTON_ACTION_SPECIAL_PROFILE_UP) },
|
||||||
|
{ 18, BUTTON_ACTION_SPECIAL(RATBAG_BUTTON_ACTION_SPECIAL_PROFILE_DOWN) },
|
||||||
|
{ 20, BUTTON_ACTION_SPECIAL(RATBAG_BUTTON_ACTION_SPECIAL_RESOLUTION_CYCLE_UP) },
|
||||||
|
{ 21, BUTTON_ACTION_SPECIAL(RATBAG_BUTTON_ACTION_SPECIAL_RESOLUTION_UP) },
|
||||||
|
{ 22, BUTTON_ACTION_SPECIAL(RATBAG_BUTTON_ACTION_SPECIAL_RESOLUTION_DOWN) },
|
||||||
|
{ 26, BUTTON_ACTION_KEY(KEY_LEFTMETA) },
|
||||||
|
/* FIXME: { 27, open driver }, -> hidraw report 02 83 01 00 00 00 00 00 */
|
||||||
|
//{ 32, BUTTON_ACTION_KEY(KEY_CONFIG) },
|
||||||
|
{ 33, BUTTON_ACTION_KEY(KEY_PREVIOUSSONG) },
|
||||||
|
{ 34, BUTTON_ACTION_KEY(KEY_NEXTSONG) },
|
||||||
|
{ 35, BUTTON_ACTION_KEY(KEY_PLAYPAUSE) },
|
||||||
|
{ 36, BUTTON_ACTION_KEY(KEY_STOPCD) },
|
||||||
|
{ 37, BUTTON_ACTION_KEY(KEY_MUTE) },
|
||||||
|
{ 38, BUTTON_ACTION_KEY(KEY_VOLUMEUP) },
|
||||||
|
{ 39, BUTTON_ACTION_KEY(KEY_VOLUMEDOWN) },
|
||||||
|
{ 48, BUTTON_ACTION_MACRO },
|
||||||
|
{ 65, BUTTON_ACTION_SPECIAL(RATBAG_BUTTON_ACTION_SPECIAL_SECOND_MODE) },
|
||||||
|
/* FIXME: { 66, Easywheel sensitivity }, */
|
||||||
|
/* FIXME: { 67, Easywheel profile }, */
|
||||||
|
/* FIXME: { 68, Easywheel CPI }, */
|
||||||
|
/* FIXME: { 81, Other Easyshift }, -> hidraw report 03 00 ff 05 01 00 00 00 */
|
||||||
|
/* FIXME: { 82, Other Easyshift Lock }, -> hidraw report 03 00 ff 05 01 00 00 00 */
|
||||||
|
/* FIXME: { 83, Both Easyshift }, -> hidraw report 03 00 ff 04 01 00 00 00 */
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct ratbag_button_action*
|
||||||
|
roccat_raw_to_button_action(uint8_t data)
|
||||||
|
{
|
||||||
|
struct roccat_button_mapping *mapping;
|
||||||
|
|
||||||
|
ARRAY_FOR_EACH(roccat_button_mapping, mapping) {
|
||||||
|
if (mapping->raw == data)
|
||||||
|
return &mapping->action;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t
|
||||||
|
roccat_button_action_to_raw(const struct ratbag_button_action *action)
|
||||||
|
{
|
||||||
|
struct roccat_button_mapping *mapping;
|
||||||
|
|
||||||
|
ARRAY_FOR_EACH(roccat_button_mapping, mapping) {
|
||||||
|
if (ratbag_button_action_match(&mapping->action, action))
|
||||||
|
return mapping->raw;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint16_t
|
||||||
|
roccat_get_unaligned_u16(uint8_t *buf)
|
||||||
|
{
|
||||||
|
return (buf[1] << 8) | buf[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint16_t
|
||||||
|
roccat_compute_crc(uint8_t *buf, unsigned int len)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
uint16_t crc = 0;
|
||||||
|
|
||||||
|
if (len < 3)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for (i = 0; i < len - 2; i++) {
|
||||||
|
crc += buf[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return crc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
roccat_crc_is_valid(struct ratbag_device *device, uint8_t *buf, unsigned int len)
|
||||||
|
{
|
||||||
|
uint16_t crc;
|
||||||
|
uint16_t given_crc;
|
||||||
|
|
||||||
|
if (len < 3)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
crc = roccat_compute_crc(buf, len);
|
||||||
|
|
||||||
|
given_crc = roccat_get_unaligned_u16(&buf[len - 2]);
|
||||||
|
|
||||||
|
log_raw(device->ratbag,
|
||||||
|
"checksum computed: 0x%04x, checksum given: 0x%04x\n",
|
||||||
|
crc,
|
||||||
|
given_crc);
|
||||||
|
|
||||||
|
return crc == given_crc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
roccat_is_ready(struct ratbag_device *device)
|
||||||
|
{
|
||||||
|
uint8_t buf[3] = { 0 };
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = ratbag_hidraw_get_feature_report(device, ROCCAT_REPORT_ID_CONFIGURE_PROFILE,
|
||||||
|
buf, sizeof(buf));
|
||||||
|
if (rc < 0)
|
||||||
|
return rc;
|
||||||
|
if (rc != sizeof(buf))
|
||||||
|
return -EIO;
|
||||||
|
|
||||||
|
if (buf[1] == 0x03)
|
||||||
|
msleep(100);
|
||||||
|
|
||||||
|
if (buf[1] == 0x02)
|
||||||
|
return 2;
|
||||||
|
|
||||||
|
return buf[1] == 0x01;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
roccat_wait_ready(struct ratbag_device *device)
|
||||||
|
{
|
||||||
|
unsigned count = 0;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
msleep(10);
|
||||||
|
while (count < ROCCAT_MAX_RETRY_READY) {
|
||||||
|
rc = roccat_is_ready(device);
|
||||||
|
if (rc < 0)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
if (rc == 1)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (rc == 2)
|
||||||
|
return 2;
|
||||||
|
|
||||||
|
msleep(10);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -ETIMEDOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
roccat_current_profile(struct ratbag_device *device)
|
||||||
|
{
|
||||||
|
uint8_t buf[3];
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = ratbag_hidraw_get_feature_report(device, ROCCAT_REPORT_ID_PROFILE, buf,
|
||||||
|
sizeof(buf));
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if (ret != 3)
|
||||||
|
return -EIO;
|
||||||
|
|
||||||
|
return buf[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
roccat_set_current_profile(struct ratbag_device *device, unsigned int index)
|
||||||
|
{
|
||||||
|
uint8_t buf[] = {ROCCAT_REPORT_ID_PROFILE, 0x03, index};
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (index > ROCCAT_PROFILE_MAX)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
ret = ratbag_hidraw_set_feature_report(device, buf[0], buf,
|
||||||
|
sizeof(buf));
|
||||||
|
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if (ret != sizeof(buf))
|
||||||
|
return -EIO;
|
||||||
|
|
||||||
|
ret = roccat_wait_ready(device);
|
||||||
|
if (ret)
|
||||||
|
log_error(device->ratbag,
|
||||||
|
"Error while waiting for the device to be ready: %s (%d)\n",
|
||||||
|
strerror(-ret), ret);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
roccat_set_config_profile(struct ratbag_device *device, uint8_t profile, uint8_t type)
|
||||||
|
{
|
||||||
|
uint8_t buf[] = {ROCCAT_REPORT_ID_CONFIGURE_PROFILE, profile, type};
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (profile > ROCCAT_PROFILE_MAX)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
ret = ratbag_hidraw_set_feature_report(device, buf[0], buf,
|
||||||
|
sizeof(buf));
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if (ret != sizeof(buf))
|
||||||
|
return -EIO;
|
||||||
|
|
||||||
|
ret = roccat_wait_ready(device);
|
||||||
|
if (ret < 0)
|
||||||
|
log_error(device->ratbag,
|
||||||
|
"Error while waiting for the device to be ready: %s (%d)\n",
|
||||||
|
strerror(-ret), ret);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct ratbag_button_action *
|
||||||
|
roccat_button_to_action(struct ratbag_profile *profile,
|
||||||
|
unsigned int button_index)
|
||||||
|
{
|
||||||
|
struct ratbag_device *device = profile->device;
|
||||||
|
struct roccat_data *drv_data = ratbag_get_drv_data(device);
|
||||||
|
uint8_t data;
|
||||||
|
|
||||||
|
data = drv_data->profiles[profile->index][3 + button_index * 3];
|
||||||
|
return roccat_raw_to_button_action(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
roccat_write_profile(struct ratbag_profile *profile)
|
||||||
|
{
|
||||||
|
struct ratbag_device *device = profile->device;
|
||||||
|
unsigned int index = profile->index;
|
||||||
|
struct roccat_data *drv_data;
|
||||||
|
int rc;
|
||||||
|
uint8_t *buf;
|
||||||
|
uint16_t *crc;
|
||||||
|
|
||||||
|
assert(index <= ROCCAT_PROFILE_MAX);
|
||||||
|
|
||||||
|
drv_data = ratbag_get_drv_data(device);
|
||||||
|
buf = drv_data->profiles[index];
|
||||||
|
crc = (uint16_t *)&buf[ROCCAT_REPORT_SIZE_PROFILE - 2];
|
||||||
|
*crc = roccat_compute_crc(buf, ROCCAT_REPORT_SIZE_PROFILE);
|
||||||
|
|
||||||
|
roccat_set_config_profile(device, index, ROCCAT_CONFIG_KEY_MAPPING);
|
||||||
|
rc = ratbag_hidraw_set_feature_report(device, ROCCAT_REPORT_ID_KEY_MAPPING,
|
||||||
|
buf, ROCCAT_REPORT_SIZE_PROFILE);
|
||||||
|
|
||||||
|
if (rc < ROCCAT_REPORT_SIZE_PROFILE)
|
||||||
|
return -EIO;
|
||||||
|
|
||||||
|
log_raw(device->ratbag, "profile: %d written %s:%d\n",
|
||||||
|
buf[2],
|
||||||
|
__FILE__, __LINE__);
|
||||||
|
|
||||||
|
rc = roccat_wait_ready(device);
|
||||||
|
if (rc)
|
||||||
|
log_error(device->ratbag,
|
||||||
|
"Error while waiting for the device to be ready: %s (%d)\n",
|
||||||
|
strerror(-rc), rc);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
roccat_read_button(struct ratbag_button *button)
|
||||||
|
{
|
||||||
|
const struct ratbag_button_action *action;
|
||||||
|
struct ratbag_device *device;
|
||||||
|
struct roccat_macro *macro;
|
||||||
|
struct roccat_data *drv_data;
|
||||||
|
uint8_t *buf;
|
||||||
|
unsigned j, time;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
device = button->profile->device;
|
||||||
|
drv_data = ratbag_get_drv_data(device);
|
||||||
|
action = roccat_button_to_action(button->profile, button->index);
|
||||||
|
if (action)
|
||||||
|
ratbag_button_set_action(button, action);
|
||||||
|
button->type = roccat_raw_to_button_type(button->index);
|
||||||
|
// if (action == NULL)
|
||||||
|
// log_error(device->ratbag, "button: %d -> %d %s:%d\n",
|
||||||
|
// button->index, drv_data->profiles[button->profile->index][3 + button->index * 3],
|
||||||
|
// __FILE__, __LINE__);
|
||||||
|
|
||||||
|
ratbag_button_enable_action_type(button, RATBAG_BUTTON_ACTION_TYPE_BUTTON);
|
||||||
|
ratbag_button_enable_action_type(button, RATBAG_BUTTON_ACTION_TYPE_KEY);
|
||||||
|
ratbag_button_enable_action_type(button, RATBAG_BUTTON_ACTION_TYPE_SPECIAL);
|
||||||
|
ratbag_button_enable_action_type(button, RATBAG_BUTTON_ACTION_TYPE_MACRO);
|
||||||
|
|
||||||
|
if (action && action->type == RATBAG_BUTTON_ACTION_TYPE_MACRO) {
|
||||||
|
struct ratbag_button_macro *m = NULL;
|
||||||
|
|
||||||
|
roccat_set_config_profile(device,
|
||||||
|
button->profile->index,
|
||||||
|
0);
|
||||||
|
roccat_set_config_profile(device,
|
||||||
|
button->profile->index,
|
||||||
|
button->index);
|
||||||
|
macro = &drv_data->macros[button->profile->index][button->index];
|
||||||
|
buf = (uint8_t*)macro;
|
||||||
|
buf[0] = ROCCAT_REPORT_ID_MACRO;
|
||||||
|
rc = ratbag_hidraw_get_feature_report(device, ROCCAT_REPORT_ID_MACRO,
|
||||||
|
buf, ROCCAT_REPORT_SIZE_MACRO);
|
||||||
|
if (rc != ROCCAT_REPORT_SIZE_MACRO) {
|
||||||
|
log_error(device->ratbag,
|
||||||
|
"Unable to retrieve the macro for button %d of profile %d: %s (%d)\n",
|
||||||
|
button->index, button->profile->index,
|
||||||
|
rc < 0 ? strerror(-rc) : "not read enough", rc);
|
||||||
|
} else {
|
||||||
|
if (buf[0] != ROCCAT_REPORT_ID_MACRO) {
|
||||||
|
log_error(device->ratbag,
|
||||||
|
"Error while reading the macro of button %d of profile %d.\n",
|
||||||
|
button->index,
|
||||||
|
button->profile->index);
|
||||||
|
goto out_macro;
|
||||||
|
}
|
||||||
|
if (!roccat_crc_is_valid(device, buf, ROCCAT_REPORT_SIZE_MACRO)) {
|
||||||
|
log_error(device->ratbag,
|
||||||
|
"wrong checksum while reading the macro of button %d of profile %d.\n",
|
||||||
|
button->index,
|
||||||
|
button->profile->index);
|
||||||
|
goto out_macro;
|
||||||
|
}
|
||||||
|
|
||||||
|
m = ratbag_button_macro_new(macro->name);
|
||||||
|
log_raw(device->ratbag,
|
||||||
|
"macro on button %d of profile %d is named '%s', and contains %d events:\n",
|
||||||
|
button->index, button->profile->index,
|
||||||
|
macro->name, macro->length);
|
||||||
|
for (j = 0; j < macro->length; j++) {
|
||||||
|
unsigned int keycode = ratbag_hidraw_get_keycode_from_keyboard_usage(device,
|
||||||
|
macro->keys[j].keycode);
|
||||||
|
ratbag_button_macro_set_event(m,
|
||||||
|
j * 2,
|
||||||
|
macro->keys[j].flag & 0x01 ? RATBAG_MACRO_EVENT_KEY_PRESSED : RATBAG_MACRO_EVENT_KEY_RELEASED,
|
||||||
|
keycode);
|
||||||
|
if (macro->keys[j].time)
|
||||||
|
time = macro->keys[j].time;
|
||||||
|
else
|
||||||
|
time = macro->keys[j].flag & 0x01 ? 10 : 50;
|
||||||
|
ratbag_button_macro_set_event(m,
|
||||||
|
j * 2 + 1,
|
||||||
|
RATBAG_MACRO_EVENT_WAIT,
|
||||||
|
time);
|
||||||
|
|
||||||
|
log_raw(device->ratbag,
|
||||||
|
" - %s %s\n",
|
||||||
|
libevdev_event_code_get_name(EV_KEY, keycode),
|
||||||
|
macro->keys[j].flag & 0x80 ? "released" : "pressed");
|
||||||
|
}
|
||||||
|
ratbag_button_copy_macro(button, m);
|
||||||
|
}
|
||||||
|
out_macro:
|
||||||
|
msleep(10);
|
||||||
|
ratbag_button_macro_unref(m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
roccat_write_macro(struct ratbag_button *button,
|
||||||
|
const struct ratbag_button_action *action)
|
||||||
|
{
|
||||||
|
struct ratbag_device *device;
|
||||||
|
struct roccat_macro *macro;
|
||||||
|
struct roccat_data *drv_data;
|
||||||
|
uint8_t *buf;
|
||||||
|
unsigned i, count = 0;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if (action->type != RATBAG_BUTTON_ACTION_TYPE_MACRO)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
device = button->profile->device;
|
||||||
|
drv_data = ratbag_get_drv_data(device);
|
||||||
|
macro = &drv_data->macros[button->profile->index][button->index];
|
||||||
|
buf = (uint8_t*)macro;
|
||||||
|
|
||||||
|
memset(buf, 0, ROCCAT_REPORT_SIZE_MACRO);
|
||||||
|
|
||||||
|
for (i = 0; i < MAX_MACRO_EVENTS && count < ROCCAT_MAX_MACRO_LENGTH; i++) {
|
||||||
|
if (action->macro->events[i].type == RATBAG_MACRO_EVENT_INVALID)
|
||||||
|
return -EINVAL; /* should not happen, ever */
|
||||||
|
|
||||||
|
if (action->macro->events[i].type == RATBAG_MACRO_EVENT_NONE)
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* ignore the first wait */
|
||||||
|
if (action->macro->events[i].type == RATBAG_MACRO_EVENT_WAIT &&
|
||||||
|
!count)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (action->macro->events[i].type == RATBAG_MACRO_EVENT_KEY_PRESSED ||
|
||||||
|
action->macro->events[i].type == RATBAG_MACRO_EVENT_KEY_RELEASED) {
|
||||||
|
macro->keys[count].keycode = ratbag_hidraw_get_keyboard_usage_from_keycode(device, action->macro->events[i].event.key);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (action->macro->events[i].type) {
|
||||||
|
case RATBAG_MACRO_EVENT_KEY_PRESSED:
|
||||||
|
macro->keys[count].flag = 0x01;
|
||||||
|
break;
|
||||||
|
case RATBAG_MACRO_EVENT_KEY_RELEASED:
|
||||||
|
macro->keys[count].flag = 0x02;
|
||||||
|
break;
|
||||||
|
case RATBAG_MACRO_EVENT_WAIT:
|
||||||
|
macro->keys[--count].time = action->macro->events[i].event.timeout;
|
||||||
|
break;
|
||||||
|
case RATBAG_MACRO_EVENT_INVALID:
|
||||||
|
case RATBAG_MACRO_EVENT_NONE:
|
||||||
|
/* should not happen */
|
||||||
|
log_error(device->ratbag,
|
||||||
|
"something went wrong while writing a macro.\n");
|
||||||
|
}
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
macro->reportID = ROCCAT_REPORT_ID_MACRO;
|
||||||
|
macro->twentytwo = 0x22;
|
||||||
|
macro->height = 0x08;
|
||||||
|
macro->profile = button->profile->index;
|
||||||
|
macro->button_index = button->index;
|
||||||
|
macro->active = 0x01;
|
||||||
|
strcpy(macro->group, "g0");
|
||||||
|
strncpy(macro->name, action->macro->name, 23);
|
||||||
|
macro->length = count;
|
||||||
|
macro->checksum = roccat_compute_crc(buf, ROCCAT_REPORT_SIZE_MACRO);
|
||||||
|
|
||||||
|
rc = ratbag_hidraw_set_feature_report(device, ROCCAT_REPORT_ID_MACRO,
|
||||||
|
buf, ROCCAT_REPORT_SIZE_MACRO);
|
||||||
|
if (rc < 0)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
if (rc != ROCCAT_REPORT_SIZE_MACRO)
|
||||||
|
return -EIO;
|
||||||
|
|
||||||
|
rc = roccat_wait_ready(device);
|
||||||
|
if (rc)
|
||||||
|
log_error(device->ratbag,
|
||||||
|
"Error while waiting for the device to be ready: %s (%d)\n",
|
||||||
|
strerror(-rc), rc);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
roccat_write_button(struct ratbag_button *button,
|
||||||
|
const struct ratbag_button_action *action)
|
||||||
|
{
|
||||||
|
struct ratbag_profile *profile = button->profile;
|
||||||
|
struct ratbag_device *device = profile->device;
|
||||||
|
struct roccat_data *drv_data = ratbag_get_drv_data(device);
|
||||||
|
uint8_t rc, *data;
|
||||||
|
|
||||||
|
data = &drv_data->profiles[profile->index][3 + button->index * 3];
|
||||||
|
|
||||||
|
rc = roccat_button_action_to_raw(action);
|
||||||
|
if (!rc)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
*data = rc;
|
||||||
|
|
||||||
|
rc = roccat_write_profile(button->profile);
|
||||||
|
if (rc) {
|
||||||
|
log_error(device->ratbag,
|
||||||
|
"unable to write the profile to the device: '%s' (%d)\n",
|
||||||
|
strerror(-rc), rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = roccat_write_macro(button, action);
|
||||||
|
if (rc) {
|
||||||
|
log_error(device->ratbag,
|
||||||
|
"unable to write the macro to the device: '%s' (%d)\n",
|
||||||
|
strerror(-rc), rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
roccat_write_resolution_dpi(struct ratbag_resolution *resolution,
|
||||||
|
int dpi_x, int dpi_y)
|
||||||
|
{
|
||||||
|
struct ratbag_profile *profile = resolution->profile;
|
||||||
|
struct ratbag_device *device = profile->device;
|
||||||
|
struct roccat_data *drv_data = ratbag_get_drv_data(device);
|
||||||
|
struct roccat_settings_report *settings_report;
|
||||||
|
uint8_t *buf;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if (dpi_x < 100 || dpi_x > 5000 || dpi_x % 50)
|
||||||
|
return -EINVAL;
|
||||||
|
if (dpi_y < 100 || dpi_y > 5000 || dpi_y % 50)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
settings_report = &drv_data->settings[profile->index];
|
||||||
|
|
||||||
|
settings_report->xres[resolution->index] = dpi_x / 50;
|
||||||
|
settings_report->yres[resolution->index] = dpi_y / 50;
|
||||||
|
if (resolution->is_active)
|
||||||
|
settings_report->current_dpi = resolution->index;
|
||||||
|
|
||||||
|
buf = (uint8_t*)settings_report;
|
||||||
|
|
||||||
|
// No checksum for settings report on Kone Pure.
|
||||||
|
//settings_report->checksum = roccat_compute_crc(buf, ROCCAT_REPORT_SIZE_SETTINGS);
|
||||||
|
|
||||||
|
rc = ratbag_hidraw_set_feature_report(device, ROCCAT_REPORT_ID_SETTINGS,
|
||||||
|
buf, ROCCAT_REPORT_SIZE_SETTINGS);
|
||||||
|
|
||||||
|
if (rc < 0)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
if (rc != ROCCAT_REPORT_SIZE_SETTINGS)
|
||||||
|
return -EIO;
|
||||||
|
|
||||||
|
rc = roccat_wait_ready(device);
|
||||||
|
if (rc)
|
||||||
|
log_error(device->ratbag,
|
||||||
|
"Error while waiting for the device to be ready: %s (%d)\n",
|
||||||
|
strerror(-rc), rc);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
roccat_read_profile(struct ratbag_profile *profile)
|
||||||
|
{
|
||||||
|
struct ratbag_device *device = profile->device;
|
||||||
|
struct roccat_data *drv_data;
|
||||||
|
struct ratbag_resolution *resolution;
|
||||||
|
struct ratbag_button *button;
|
||||||
|
struct roccat_settings_report *setting_report;
|
||||||
|
uint8_t *buf;
|
||||||
|
unsigned int report_rate;
|
||||||
|
int dpi_x, dpi_y;
|
||||||
|
int rc;
|
||||||
|
unsigned int report_rates[] = { 125, 250, 500, 1000 };
|
||||||
|
|
||||||
|
assert(profile->index <= ROCCAT_PROFILE_MAX);
|
||||||
|
|
||||||
|
drv_data = ratbag_get_drv_data(device);
|
||||||
|
|
||||||
|
setting_report = &drv_data->settings[profile->index];
|
||||||
|
buf = (uint8_t*)setting_report;
|
||||||
|
roccat_set_config_profile(device, profile->index, ROCCAT_CONFIG_SETTINGS);
|
||||||
|
rc = ratbag_hidraw_get_feature_report(device, ROCCAT_REPORT_ID_SETTINGS,
|
||||||
|
buf, ROCCAT_REPORT_SIZE_SETTINGS);
|
||||||
|
|
||||||
|
if (rc < ROCCAT_REPORT_SIZE_SETTINGS)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* first retrieve the report rate, it is set per profile */
|
||||||
|
if (setting_report->report_rate < ARRAY_LENGTH(report_rates)) {
|
||||||
|
report_rate = report_rates[setting_report->report_rate];
|
||||||
|
} else {
|
||||||
|
log_error(device->ratbag,
|
||||||
|
"error while reading the report rate of the mouse (0x%02x)\n",
|
||||||
|
buf[26]);
|
||||||
|
report_rate = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ratbag_profile_set_report_rate_list(profile, report_rates,
|
||||||
|
ARRAY_LENGTH(report_rates));
|
||||||
|
ratbag_profile_set_report_rate(profile, report_rate);
|
||||||
|
|
||||||
|
ratbag_profile_for_each_resolution(profile, resolution) {
|
||||||
|
dpi_x = setting_report->xres[resolution->index] * 50;
|
||||||
|
dpi_y = setting_report->yres[resolution->index] * 50;
|
||||||
|
if (!(setting_report->dpi_mask & (1 << resolution->index))) {
|
||||||
|
/* the profile is disabled, overwrite it */
|
||||||
|
dpi_x = 0;
|
||||||
|
dpi_y = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ratbag_resolution_set_resolution(resolution, dpi_x, dpi_y);
|
||||||
|
ratbag_resolution_set_cap(resolution,
|
||||||
|
RATBAG_RESOLUTION_CAP_SEPARATE_XY_RESOLUTION);
|
||||||
|
resolution->is_active = (resolution->index == setting_report->current_dpi);
|
||||||
|
|
||||||
|
ratbag_resolution_set_dpi_list_from_range(resolution, 100, 5000);
|
||||||
|
}
|
||||||
|
|
||||||
|
buf = drv_data->profiles[profile->index];
|
||||||
|
roccat_set_config_profile(device, profile->index, ROCCAT_CONFIG_KEY_MAPPING);
|
||||||
|
rc = ratbag_hidraw_get_feature_report(device, ROCCAT_REPORT_ID_KEY_MAPPING,
|
||||||
|
buf, ROCCAT_REPORT_SIZE_PROFILE);
|
||||||
|
|
||||||
|
msleep(10);
|
||||||
|
|
||||||
|
if (rc < ROCCAT_REPORT_SIZE_PROFILE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Buttons were read from the buffer that was yet un-initialized with the device data.
|
||||||
|
ratbag_profile_for_each_button(profile, button)
|
||||||
|
roccat_read_button(button);
|
||||||
|
|
||||||
|
if (!roccat_crc_is_valid(device, buf, ROCCAT_REPORT_SIZE_PROFILE))
|
||||||
|
log_error(device->ratbag,
|
||||||
|
"Error while reading profile %d, continuing...\n",
|
||||||
|
profile->index);
|
||||||
|
|
||||||
|
log_raw(device->ratbag, "profile: %d %s:%d\n",
|
||||||
|
buf[2],
|
||||||
|
__FILE__, __LINE__);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
roccat_probe(struct ratbag_device *device)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
struct ratbag_profile *profile;
|
||||||
|
struct roccat_data *drv_data;
|
||||||
|
int active_idx;
|
||||||
|
|
||||||
|
rc = ratbag_open_hidraw(device);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
if (!ratbag_hidraw_has_report(device, ROCCAT_REPORT_ID_KEY_MAPPING)) {
|
||||||
|
ratbag_close_hidraw(device);
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
drv_data = zalloc(sizeof(*drv_data));
|
||||||
|
ratbag_set_drv_data(device, drv_data);
|
||||||
|
|
||||||
|
/* profiles are 0-indexed */
|
||||||
|
ratbag_device_init_profiles(device,
|
||||||
|
ROCCAT_PROFILE_MAX + 1,
|
||||||
|
ROCCAT_NUM_DPI,
|
||||||
|
ROCCAT_BUTTON_MAX + 1,
|
||||||
|
ROCCAT_LED_MAX);
|
||||||
|
|
||||||
|
ratbag_device_for_each_profile(device, profile)
|
||||||
|
roccat_read_profile(profile);
|
||||||
|
|
||||||
|
active_idx = roccat_current_profile(device);
|
||||||
|
if (active_idx < 0) {
|
||||||
|
log_error(device->ratbag,
|
||||||
|
"Can't talk to the mouse: '%s' (%d)\n",
|
||||||
|
strerror(-active_idx),
|
||||||
|
active_idx);
|
||||||
|
rc = -ENODEV;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
list_for_each(profile, &device->profiles, link) {
|
||||||
|
if (profile->index == (unsigned int)active_idx) {
|
||||||
|
profile->is_active = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log_raw(device->ratbag,
|
||||||
|
"'%s' is in profile %d\n",
|
||||||
|
ratbag_device_get_name(device),
|
||||||
|
profile->index);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err:
|
||||||
|
free(drv_data);
|
||||||
|
ratbag_set_drv_data(device, NULL);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
roccat_remove(struct ratbag_device *device)
|
||||||
|
{
|
||||||
|
ratbag_close_hidraw(device);
|
||||||
|
free(ratbag_get_drv_data(device));
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ratbag_driver roccat_driver = {
|
||||||
|
.name = "Roccat Kone Pure",
|
||||||
|
.id = "roccat",
|
||||||
|
.probe = roccat_probe,
|
||||||
|
.remove = roccat_remove,
|
||||||
|
.write_profile = roccat_write_profile,
|
||||||
|
.set_active_profile = roccat_set_current_profile,
|
||||||
|
.write_button = roccat_write_button,
|
||||||
|
.write_resolution_dpi = roccat_write_resolution_dpi,
|
||||||
|
};
|
||||||
@@ -306,6 +306,33 @@ hidpp_read_response(struct hidpp_device *dev, uint8_t *buf, size_t size)
|
|||||||
return rc >= 0 ? rc : -errno;
|
return rc >= 0 ? rc : -errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
hidpp_get_supported_report_types(struct hidpp_device *dev, struct hidpp_hid_report *reports, unsigned int num_reports)
|
||||||
|
{
|
||||||
|
if (!reports) {
|
||||||
|
hidpp_log_debug(dev, "hidpp: we don't have information about the hid reports, ignoring checks\n");
|
||||||
|
dev->supported_report_types = 0xffff;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* reset the bits we are gonna check */
|
||||||
|
dev->supported_report_types &= (0xff & ~HIDPP_REPORT_SHORT);
|
||||||
|
dev->supported_report_types &= (0xff & ~HIDPP_REPORT_LONG);
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < num_reports; i++)
|
||||||
|
if ((reports[i].usage_page & 0xff00) == 0xff00) /* vendor defined usage page (0xff00-0xffff) */
|
||||||
|
switch (reports[i].report_id) {
|
||||||
|
case REPORT_ID_SHORT:
|
||||||
|
hidpp_log_debug(dev, "hidpp: device supports short reports\n");
|
||||||
|
dev->supported_report_types |= HIDPP_REPORT_SHORT;
|
||||||
|
break;
|
||||||
|
case REPORT_ID_LONG:
|
||||||
|
hidpp_log_debug(dev, "hidpp: device supports long reports\n");
|
||||||
|
dev->supported_report_types |= HIDPP_REPORT_LONG;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
hidpp_log(struct hidpp_device *dev,
|
hidpp_log(struct hidpp_device *dev,
|
||||||
enum hidpp_log_priority priority,
|
enum hidpp_log_priority priority,
|
||||||
@@ -363,6 +390,7 @@ hidpp_device_init(struct hidpp_device *dev, int fd)
|
|||||||
{
|
{
|
||||||
dev->hidraw_fd = fd;
|
dev->hidraw_fd = fd;
|
||||||
hidpp_device_set_log_handler(dev, simple_log, HIDPP_LOG_PRIORITY_INFO, NULL);
|
hidpp_device_set_log_handler(dev, simple_log, HIDPP_LOG_PRIORITY_INFO, NULL);
|
||||||
|
dev->supported_report_types = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
@@ -95,13 +95,23 @@ typedef void (*hidpp_log_handler)(void *userdata,
|
|||||||
const char *format, va_list args)
|
const char *format, va_list args)
|
||||||
__attribute__ ((format (printf, 3, 0)));
|
__attribute__ ((format (printf, 3, 0)));
|
||||||
|
|
||||||
|
struct hidpp_hid_report {
|
||||||
|
unsigned int report_id;
|
||||||
|
unsigned int usage_page;
|
||||||
|
unsigned int usage;
|
||||||
|
};
|
||||||
|
|
||||||
struct hidpp_device {
|
struct hidpp_device {
|
||||||
int hidraw_fd;
|
int hidraw_fd;
|
||||||
void *userdata;
|
void *userdata;
|
||||||
hidpp_log_handler log_handler;
|
hidpp_log_handler log_handler;
|
||||||
enum hidpp_log_priority log_priority;
|
enum hidpp_log_priority log_priority;
|
||||||
|
unsigned supported_report_types;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define HIDPP_REPORT_SHORT (1 << 0)
|
||||||
|
#define HIDPP_REPORT_LONG (1 << 1)
|
||||||
|
|
||||||
void
|
void
|
||||||
hidpp_device_init(struct hidpp_device *dev, int fd);
|
hidpp_device_init(struct hidpp_device *dev, int fd);
|
||||||
void
|
void
|
||||||
@@ -140,6 +150,11 @@ hidpp_write_command(struct hidpp_device *dev, uint8_t *cmd, int size);
|
|||||||
int
|
int
|
||||||
hidpp_read_response(struct hidpp_device *dev, uint8_t *buf, size_t size);
|
hidpp_read_response(struct hidpp_device *dev, uint8_t *buf, size_t size);
|
||||||
|
|
||||||
|
void
|
||||||
|
hidpp_get_supported_report_types(struct hidpp_device *dev,
|
||||||
|
struct hidpp_hid_report *reports,
|
||||||
|
unsigned int num_reports);
|
||||||
|
|
||||||
void
|
void
|
||||||
hidpp_log(struct hidpp_device *dev,
|
hidpp_log(struct hidpp_device *dev,
|
||||||
enum hidpp_log_priority priority,
|
enum hidpp_log_priority priority,
|
||||||
|
|||||||
23
src/hidpp.i
Normal file
23
src/hidpp.i
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
/* wrapping libratbag functions from hidpp*.h using SWIG. */
|
||||||
|
|
||||||
|
%module hidpp
|
||||||
|
%{
|
||||||
|
/* the resulting C file should be built as a python extension */
|
||||||
|
#define SWIG_FILE_WITH_INIT
|
||||||
|
/* Includes the header in the wrapper code */
|
||||||
|
#include <shared.h>
|
||||||
|
#include <hidpp-generic.h>
|
||||||
|
#include <hidpp20.h>
|
||||||
|
%}
|
||||||
|
#define __attribute__(x)
|
||||||
|
#define _Static_assert(a,b)
|
||||||
|
|
||||||
|
|
||||||
|
/* Parse the header file to generate wrappers */
|
||||||
|
%include "stdint.i"
|
||||||
|
%include "cpointer.i"
|
||||||
|
%pointer_functions(int, intp);
|
||||||
|
%pointer_functions(uint8_t, uint8_tp);
|
||||||
|
%pointer_functions(uint16_t, uint16_tp);
|
||||||
|
%include "hidpp-generic.h"
|
||||||
|
%include "hidpp20.h"
|
||||||
@@ -833,6 +833,20 @@ hidpp10_get_current_profile(struct hidpp10_device *dev, uint8_t *current_profile
|
|||||||
"unable to find the profile at (%d,%d) in the directory\n",
|
"unable to find the profile at (%d,%d) in the directory\n",
|
||||||
page, offset);
|
page, offset);
|
||||||
break;
|
break;
|
||||||
|
case PROFILE_TYPE_FACTORY:
|
||||||
|
/* Factory profile is selected and profile switching is
|
||||||
|
* disabled. Let's switch to the first profile because the
|
||||||
|
* factory profile doesn't help anywone */
|
||||||
|
res = hidpp10_set_current_profile(dev, 0);
|
||||||
|
if (res == 0) {
|
||||||
|
hidpp_log_info(&dev->base, "switched from factory profile to 0\n");
|
||||||
|
*current_profile = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
hidpp_log_error(&dev->base,
|
||||||
|
"current profile is factory profile but switching to 0 failed.\n");
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
hidpp_log_error(&dev->base,
|
hidpp_log_error(&dev->base,
|
||||||
"Unexpected value: %02x\n",
|
"Unexpected value: %02x\n",
|
||||||
@@ -2737,8 +2751,7 @@ hidpp10_get_device_info(struct hidpp10_device *dev)
|
|||||||
|
|
||||||
hidpp10_get_optical_sensor_settings(dev, &reflect);
|
hidpp10_get_optical_sensor_settings(dev, &reflect);
|
||||||
|
|
||||||
hidpp10_get_current_profile(dev, ¤t_profile);
|
return hidpp10_get_current_profile(dev, ¤t_profile);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct hidpp10_device*
|
struct hidpp10_device*
|
||||||
|
|||||||
244
src/hidpp20.c
244
src/hidpp20.c
@@ -48,7 +48,6 @@ hidpp20_feature_get_name(uint16_t feature)
|
|||||||
{
|
{
|
||||||
static char numeric[8];
|
static char numeric[8];
|
||||||
const char *str;
|
const char *str;
|
||||||
#define CASE_RETURN_STRING(a) case a: return #a; break
|
|
||||||
|
|
||||||
switch(feature)
|
switch(feature)
|
||||||
{
|
{
|
||||||
@@ -99,11 +98,22 @@ hidpp20_sw_led_control_get_mode_string(const enum hidpp20_led_sw_ctrl_led_mode m
|
|||||||
str = numeric;
|
str = numeric;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#undef CASE_RETURN_STRING
|
|
||||||
|
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char*
|
||||||
|
hidpp20_get_quirk_string(enum hidpp20_quirk quirk)
|
||||||
|
{
|
||||||
|
switch (quirk) {
|
||||||
|
CASE_RETURN_STRING(HIDPP20_QUIRK_NONE);
|
||||||
|
CASE_RETURN_STRING(HIDPP20_QUIRK_G305);
|
||||||
|
CASE_RETURN_STRING(HIDPP20_QUIRK_G602);
|
||||||
|
}
|
||||||
|
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
hidpp20_request_command_allow_error(struct hidpp20_device *device, union hidpp20_message *msg,
|
hidpp20_request_command_allow_error(struct hidpp20_device *device, union hidpp20_message *msg,
|
||||||
bool allow_error)
|
bool allow_error)
|
||||||
@@ -123,6 +133,16 @@ hidpp20_request_command_allow_error(struct hidpp20_device *device, union hidpp20
|
|||||||
}
|
}
|
||||||
msg->msg.address |= DEVICE_SW_ID;
|
msg->msg.address |= DEVICE_SW_ID;
|
||||||
|
|
||||||
|
/* some mice don't support short reports */
|
||||||
|
if (msg->msg.report_id == REPORT_ID_SHORT && !(device->base.supported_report_types & HIDPP_REPORT_SHORT))
|
||||||
|
msg->msg.report_id = REPORT_ID_LONG;
|
||||||
|
|
||||||
|
/* sanity check */
|
||||||
|
if (msg->msg.report_id == REPORT_ID_LONG && !(device->base.supported_report_types & HIDPP_REPORT_LONG)) {
|
||||||
|
hidpp_log_error(&device->base, "hidpp20: trying to use unsupported report type\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
msg_len = msg->msg.report_id == REPORT_ID_SHORT ? SHORT_MESSAGE_LENGTH : LONG_MESSAGE_LENGTH;
|
msg_len = msg->msg.report_id == REPORT_ID_SHORT ? SHORT_MESSAGE_LENGTH : LONG_MESSAGE_LENGTH;
|
||||||
|
|
||||||
/* Send the message to the Device */
|
/* Send the message to the Device */
|
||||||
@@ -848,6 +868,8 @@ err:
|
|||||||
#define CMD_COLOR_LED_EFFECTS_GET_INFO 0x00
|
#define CMD_COLOR_LED_EFFECTS_GET_INFO 0x00
|
||||||
#define CMD_COLOR_LED_EFFECTS_GET_ZONE_INFO 0x10
|
#define CMD_COLOR_LED_EFFECTS_GET_ZONE_INFO 0x10
|
||||||
#define CMD_COLOR_LED_EFFECTS_GET_ZONE_EFFECT_INFO 0x20
|
#define CMD_COLOR_LED_EFFECTS_GET_ZONE_EFFECT_INFO 0x20
|
||||||
|
#define CMD_COLOR_LED_EFFECTS_SET_ZONE_EFFECT 0x30
|
||||||
|
#define CMD_COLOR_LED_EFFECTS_GET_ZONE_EFFECT 0xe0
|
||||||
|
|
||||||
int
|
int
|
||||||
hidpp20_color_led_effects_get_info(struct hidpp20_device *device,
|
hidpp20_color_led_effects_get_info(struct hidpp20_device *device,
|
||||||
@@ -873,6 +895,7 @@ hidpp20_color_led_effects_get_info(struct hidpp20_device *device,
|
|||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
*info = *(struct hidpp20_color_led_info *)msg.msg.parameters;
|
*info = *(struct hidpp20_color_led_info *)msg.msg.parameters;
|
||||||
|
device->led_ext_caps = info->ext_caps;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -992,6 +1015,80 @@ hidpp20_color_led_effect_get_zone_effect_info(struct hidpp20_device *device,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
hidpp20_color_led_effects_set_zone_effect(struct hidpp20_device *device,
|
||||||
|
uint8_t zone_index,
|
||||||
|
struct hidpp20_led led)
|
||||||
|
{
|
||||||
|
uint8_t feature_index;
|
||||||
|
union hidpp20_message msg = {
|
||||||
|
.msg.report_id = REPORT_ID_SHORT,
|
||||||
|
.msg.address = CMD_COLOR_LED_EFFECTS_SET_ZONE_EFFECT,
|
||||||
|
.msg.device_idx = device->index,
|
||||||
|
.msg.parameters[0] = zone_index,
|
||||||
|
.msg.parameters[12] = 1, /* write to RAM and flash */
|
||||||
|
};
|
||||||
|
int rc;
|
||||||
|
struct hidpp20_internal_led *internal_led = (struct hidpp20_internal_led*) &msg.msg.parameters[1];
|
||||||
|
|
||||||
|
hidpp20_onboard_profiles_write_led(internal_led, &led);
|
||||||
|
|
||||||
|
feature_index = hidpp_root_get_feature_idx(device,
|
||||||
|
HIDPP_PAGE_COLOR_LED_EFFECTS);
|
||||||
|
if (feature_index == 0)
|
||||||
|
return -ENOTSUP;
|
||||||
|
|
||||||
|
msg.msg.sub_id = feature_index;
|
||||||
|
|
||||||
|
rc = hidpp20_request_command(device, &msg);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
hidpp20_color_led_effects_get_zone_effect(struct hidpp20_device *device,
|
||||||
|
uint8_t zone_index,
|
||||||
|
struct hidpp20_led *led)
|
||||||
|
{
|
||||||
|
uint8_t feature_index;
|
||||||
|
union hidpp20_message msg = {
|
||||||
|
.msg.report_id = REPORT_ID_SHORT,
|
||||||
|
.msg.address = CMD_COLOR_LED_EFFECTS_GET_ZONE_EFFECT,
|
||||||
|
.msg.device_idx = device->index,
|
||||||
|
.msg.parameters[0] = zone_index,
|
||||||
|
};
|
||||||
|
struct hidpp20_internal_led *internal_led;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
/* hidpp20_color_led_effects_get_info() must be called first to set the capabilities */
|
||||||
|
if (!(device->led_ext_caps & HIDPP20_COLOR_LED_INFO_EXT_CAP_HAS_ZONE_EFFECT))
|
||||||
|
return -ENOTSUP;
|
||||||
|
|
||||||
|
feature_index = hidpp_root_get_feature_idx(device,
|
||||||
|
HIDPP_PAGE_COLOR_LED_EFFECTS);
|
||||||
|
if (feature_index == 0)
|
||||||
|
return -ENOTSUP;
|
||||||
|
|
||||||
|
msg.msg.sub_id = feature_index;
|
||||||
|
|
||||||
|
rc = hidpp20_request_command(device, &msg);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
if (msg.msg.parameters[0] != zone_index)
|
||||||
|
return -EPROTO;
|
||||||
|
|
||||||
|
internal_led = (struct hidpp20_internal_led*) &msg.msg.parameters[1];
|
||||||
|
|
||||||
|
hidpp20_onboard_profiles_read_led(led, *internal_led);
|
||||||
|
|
||||||
|
hidpp_log_debug(&device->base, "zone %u has effect %u\n", zone_index, led->mode);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
/* 0x8071: RGB Effects */
|
/* 0x8071: RGB Effects */
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
@@ -1073,8 +1170,8 @@ hidpp20_rgb_effects_get_cluster_info(struct hidpp20_device *device,
|
|||||||
info->effect_index = msg.msg.parameters[1];
|
info->effect_index = msg.msg.parameters[1];
|
||||||
|
|
||||||
info->location = get_unaligned_be_u16(&msg.msg.parameters[2]);
|
info->location = get_unaligned_be_u16(&msg.msg.parameters[2]);
|
||||||
info->num_effects = get_unaligned_be_u16(&msg.msg.parameters[4]);
|
info->num_effects = msg.msg.parameters[4];
|
||||||
info->persistency_caps = get_unaligned_be_u16(&msg.msg.parameters[6]);
|
info->persistency_caps = msg.msg.parameters[5];
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -1432,6 +1529,11 @@ hidpp20_adjustable_dpi_get_dpi_list(struct hidpp20_device *device,
|
|||||||
.msg.parameters[0] = sensor->index,
|
.msg.parameters[0] = sensor->index,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (device->quirk == HIDPP20_QUIRK_G602) {
|
||||||
|
msg.msg.parameters[0] = 1;
|
||||||
|
i = 0;
|
||||||
|
}
|
||||||
|
|
||||||
rc = hidpp20_request_command(device, &msg);
|
rc = hidpp20_request_command(device, &msg);
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
@@ -1443,6 +1545,9 @@ hidpp20_adjustable_dpi_get_dpi_list(struct hidpp20_device *device,
|
|||||||
get_unaligned_be_u16(&msg.msg.parameters[i]) != 0) {
|
get_unaligned_be_u16(&msg.msg.parameters[i]) != 0) {
|
||||||
uint16_t value = get_unaligned_be_u16(&msg.msg.parameters[i]);
|
uint16_t value = get_unaligned_be_u16(&msg.msg.parameters[i]);
|
||||||
|
|
||||||
|
if (device->quirk == HIDPP20_QUIRK_G602 && i == 2)
|
||||||
|
value += 0xe000;
|
||||||
|
|
||||||
if (value > 0xe000) {
|
if (value > 0xe000) {
|
||||||
sensor->dpi_steps = value - 0xe000;
|
sensor->dpi_steps = value - 0xe000;
|
||||||
} else {
|
} else {
|
||||||
@@ -1472,6 +1577,9 @@ hidpp20_adjustable_dpi_get_dpi(struct hidpp20_device *device,
|
|||||||
.msg.parameters[0] = sensor->index,
|
.msg.parameters[0] = sensor->index,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (device->quirk == HIDPP20_QUIRK_G602)
|
||||||
|
msg.msg.parameters[0] = 1;
|
||||||
|
|
||||||
rc = hidpp20_request_command(device, &msg);
|
rc = hidpp20_request_command(device, &msg);
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
@@ -1551,6 +1659,9 @@ int hidpp20_adjustable_dpi_set_sensor_dpi(struct hidpp20_device *device,
|
|||||||
.msg.parameters[0] = sensor->index,
|
.msg.parameters[0] = sensor->index,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (device->quirk == HIDPP20_QUIRK_G602)
|
||||||
|
msg.msg.parameters[0] = 1;
|
||||||
|
|
||||||
set_unaligned_be_u16(&msg.msg.parameters[1], dpi);
|
set_unaligned_be_u16(&msg.msg.parameters[1], dpi);
|
||||||
|
|
||||||
feature_index = hidpp_root_get_feature_idx(device,
|
feature_index = hidpp_root_get_feature_idx(device,
|
||||||
@@ -1578,6 +1689,8 @@ int hidpp20_adjustable_dpi_set_sensor_dpi(struct hidpp20_device *device,
|
|||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
#define CMD_ADJUSTABLE_REPORT_RATE_GET_REPORT_RATE_LIST 0x00
|
#define CMD_ADJUSTABLE_REPORT_RATE_GET_REPORT_RATE_LIST 0x00
|
||||||
|
#define CMD_ADJUSTABLE_REPORT_RATE_GET_REPORT_RATE 0x10
|
||||||
|
#define CMD_ADJUSTABLE_REPORT_RATE_SET_REPORT_RATE 0x20
|
||||||
|
|
||||||
int hidpp20_adjustable_report_rate_get_report_rate_list(struct hidpp20_device *device,
|
int hidpp20_adjustable_report_rate_get_report_rate_list(struct hidpp20_device *device,
|
||||||
uint8_t *bitflags_ms)
|
uint8_t *bitflags_ms)
|
||||||
@@ -1607,6 +1720,60 @@ int hidpp20_adjustable_report_rate_get_report_rate_list(struct hidpp20_device *d
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int hidpp20_adjustable_report_rate_get_report_rate(struct hidpp20_device *device,
|
||||||
|
uint8_t *rate_ms)
|
||||||
|
{
|
||||||
|
uint8_t feature_index;
|
||||||
|
int rc;
|
||||||
|
union hidpp20_message msg = {
|
||||||
|
.msg.report_id = REPORT_ID_SHORT,
|
||||||
|
.msg.device_idx = device->index,
|
||||||
|
.msg.address = CMD_ADJUSTABLE_REPORT_RATE_GET_REPORT_RATE,
|
||||||
|
.msg.parameters[0] = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
feature_index = hidpp_root_get_feature_idx(device,
|
||||||
|
HIDPP_PAGE_ADJUSTABLE_REPORT_RATE);
|
||||||
|
if (feature_index == 0)
|
||||||
|
return -ENOTSUP;
|
||||||
|
|
||||||
|
msg.msg.sub_id = feature_index;
|
||||||
|
|
||||||
|
rc = hidpp20_request_command(device, &msg);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
*rate_ms = msg.msg.parameters[0];
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int hidpp20_adjustable_report_rate_set_report_rate(struct hidpp20_device *device,
|
||||||
|
uint8_t rate_ms)
|
||||||
|
{
|
||||||
|
uint8_t feature_index;
|
||||||
|
int rc;
|
||||||
|
union hidpp20_message msg = {
|
||||||
|
.msg.report_id = REPORT_ID_SHORT,
|
||||||
|
.msg.device_idx = device->index,
|
||||||
|
.msg.address = CMD_ADJUSTABLE_REPORT_RATE_SET_REPORT_RATE,
|
||||||
|
.msg.parameters[0] = rate_ms,
|
||||||
|
};
|
||||||
|
|
||||||
|
feature_index = hidpp_root_get_feature_idx(device,
|
||||||
|
HIDPP_PAGE_ADJUSTABLE_REPORT_RATE);
|
||||||
|
if (feature_index == 0)
|
||||||
|
return -ENOTSUP;
|
||||||
|
|
||||||
|
msg.msg.sub_id = feature_index;
|
||||||
|
|
||||||
|
rc = hidpp20_request_command(device, &msg);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
/* 0x8100 - Onboard Profiles */
|
/* 0x8100 - Onboard Profiles */
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
@@ -1634,7 +1801,7 @@ int hidpp20_adjustable_report_rate_get_report_rate_list(struct hidpp20_device *d
|
|||||||
#define HIDPP20_ONBOARD_PROFILES_PROFILE_TYPE_G402 0x01
|
#define HIDPP20_ONBOARD_PROFILES_PROFILE_TYPE_G402 0x01
|
||||||
#define HIDPP20_ONBOARD_PROFILES_PROFILE_TYPE_G303 0x02
|
#define HIDPP20_ONBOARD_PROFILES_PROFILE_TYPE_G303 0x02
|
||||||
#define HIDPP20_ONBOARD_PROFILES_PROFILE_TYPE_G900 0x03
|
#define HIDPP20_ONBOARD_PROFILES_PROFILE_TYPE_G900 0x03
|
||||||
#define HIDPP20_ONBOARD_PROFILES_PROFILE_TYPE_G903_HERO 0x04
|
#define HIDPP20_ONBOARD_PROFILES_PROFILE_TYPE_G915 0x04
|
||||||
#define HIDPP20_ONBOARD_PROFILES_MACRO_TYPE_G402 0x01
|
#define HIDPP20_ONBOARD_PROFILES_MACRO_TYPE_G402 0x01
|
||||||
|
|
||||||
#define HIDPP20_USER_PROFILES_G402 0x0000
|
#define HIDPP20_USER_PROFILES_G402 0x0000
|
||||||
@@ -2054,7 +2221,7 @@ hidpp20_onboard_profiles_validate(struct hidpp20_device *device,
|
|||||||
if ((info->profile_format_id != HIDPP20_ONBOARD_PROFILES_PROFILE_TYPE_G402) &&
|
if ((info->profile_format_id != HIDPP20_ONBOARD_PROFILES_PROFILE_TYPE_G402) &&
|
||||||
(info->profile_format_id != HIDPP20_ONBOARD_PROFILES_PROFILE_TYPE_G303) &&
|
(info->profile_format_id != HIDPP20_ONBOARD_PROFILES_PROFILE_TYPE_G303) &&
|
||||||
(info->profile_format_id != HIDPP20_ONBOARD_PROFILES_PROFILE_TYPE_G900) &&
|
(info->profile_format_id != HIDPP20_ONBOARD_PROFILES_PROFILE_TYPE_G900) &&
|
||||||
(info->profile_format_id != HIDPP20_ONBOARD_PROFILES_PROFILE_TYPE_G903_HERO)) {
|
(info->profile_format_id != HIDPP20_ONBOARD_PROFILES_PROFILE_TYPE_G915)) {
|
||||||
hidpp_log_error(&device->base,
|
hidpp_log_error(&device->base,
|
||||||
"Profile layout not supported: 0x%02x.\n",
|
"Profile layout not supported: 0x%02x.\n",
|
||||||
info->profile_format_id);
|
info->profile_format_id);
|
||||||
@@ -2354,7 +2521,7 @@ hidpp20_onboard_profiles_write_dict(struct hidpp20_device *device,
|
|||||||
|
|
||||||
memset(data + buffer_index, 0xff, sector_size - buffer_index);
|
memset(data + buffer_index, 0xff, sector_size - buffer_index);
|
||||||
|
|
||||||
hidpp_log_buf_debug(&device->base,
|
hidpp_log_buf_raw(&device->base,
|
||||||
"dictionary: ",
|
"dictionary: ",
|
||||||
data,
|
data,
|
||||||
hidpp20_onboard_profiles_compute_dict_size(device,
|
hidpp20_onboard_profiles_compute_dict_size(device,
|
||||||
@@ -2365,6 +2532,9 @@ hidpp20_onboard_profiles_write_dict(struct hidpp20_device *device,
|
|||||||
sector_size,
|
sector_size,
|
||||||
data,
|
data,
|
||||||
true);
|
true);
|
||||||
|
if (rc)
|
||||||
|
hidpp_log_error(&device->base, "failed to write profile dictionary\n");
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2402,6 +2572,7 @@ hidpp20_buttons_to_cpu(struct hidpp20_device *device,
|
|||||||
break;
|
break;
|
||||||
case HIDPP20_BUTTON_SPECIAL:
|
case HIDPP20_BUTTON_SPECIAL:
|
||||||
button->special.special = b->special.special;
|
button->special.special = b->special.special;
|
||||||
|
button->special.profile = b->special.profile;
|
||||||
break;
|
break;
|
||||||
case HIDPP20_BUTTON_MACRO:
|
case HIDPP20_BUTTON_MACRO:
|
||||||
if (profile->macros[i]) {
|
if (profile->macros[i]) {
|
||||||
@@ -2461,6 +2632,7 @@ hidpp20_buttons_from_cpu(struct hidpp20_profile *profile,
|
|||||||
break;
|
break;
|
||||||
case HIDPP20_BUTTON_SPECIAL:
|
case HIDPP20_BUTTON_SPECIAL:
|
||||||
button->special.special = b->special.special;
|
button->special.special = b->special.special;
|
||||||
|
button->special.profile = b->special.profile;
|
||||||
break;
|
break;
|
||||||
case HIDPP20_BUTTON_DISABLED:
|
case HIDPP20_BUTTON_DISABLED:
|
||||||
break;
|
break;
|
||||||
@@ -2476,7 +2648,7 @@ hidpp20_buttons_from_cpu(struct hidpp20_profile *profile,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
hidpp20_onboard_profiles_read_led(struct hidpp20_led *led,
|
hidpp20_onboard_profiles_read_led(struct hidpp20_led *led,
|
||||||
struct hidpp20_internal_led internal_led)
|
struct hidpp20_internal_led internal_led)
|
||||||
{
|
{
|
||||||
@@ -2492,6 +2664,10 @@ hidpp20_onboard_profiles_read_led(struct hidpp20_led *led,
|
|||||||
if (brightness == 0)
|
if (brightness == 0)
|
||||||
brightness = 100;
|
brightness = 100;
|
||||||
break;
|
break;
|
||||||
|
case HIDPP20_LED_STARLIGHT:
|
||||||
|
led->color = internal_led.effect.starlight.color_sky;
|
||||||
|
led->extra_color = internal_led.effect.starlight.color_star;
|
||||||
|
break;
|
||||||
case HIDPP20_LED_BREATHING:
|
case HIDPP20_LED_BREATHING:
|
||||||
period = hidpp_be_u16_to_cpu(internal_led.effect.breath.period_or_speed);
|
period = hidpp_be_u16_to_cpu(internal_led.effect.breath.period_or_speed);
|
||||||
brightness = internal_led.effect.breath.intensity;
|
brightness = internal_led.effect.breath.intensity;
|
||||||
@@ -2499,11 +2675,18 @@ hidpp20_onboard_profiles_read_led(struct hidpp20_led *led,
|
|||||||
brightness = 100;
|
brightness = 100;
|
||||||
led->color = internal_led.effect.breath.color;
|
led->color = internal_led.effect.breath.color;
|
||||||
break;
|
break;
|
||||||
|
case HIDPP20_LED_RIPPLE:
|
||||||
|
period = hidpp_be_u16_to_cpu(internal_led.effect.breath.period_or_speed);
|
||||||
|
led->color = internal_led.effect.ripple.color;
|
||||||
|
break;
|
||||||
case HIDPP20_LED_ON:
|
case HIDPP20_LED_ON:
|
||||||
led->color = internal_led.effect.fixed.color;
|
led->color = internal_led.effect.fixed.color;
|
||||||
break;
|
break;
|
||||||
case HIDPP20_LED_OFF:
|
case HIDPP20_LED_OFF:
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
memcpy(led->original, &internal_led, sizeof(internal_led));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
led->period = period;
|
led->period = period;
|
||||||
@@ -2602,6 +2785,15 @@ hidpp20_onboard_profiles_initialize(struct hidpp20_device *device,
|
|||||||
HIDPP20_USER_PROFILES_G402,
|
HIDPP20_USER_PROFILES_G402,
|
||||||
profiles->sector_size,
|
profiles->sector_size,
|
||||||
data);
|
data);
|
||||||
|
|
||||||
|
if (rc && device->quirk == HIDPP20_QUIRK_G305) {
|
||||||
|
/* The G305 has a bug where it throws an ERR_INVALID_ARGUMENT
|
||||||
|
if the sector has not been written to yet. If this happens
|
||||||
|
we will read the ROM profiles.*/
|
||||||
|
read_userdata = false;
|
||||||
|
goto read_profiles;
|
||||||
|
}
|
||||||
|
|
||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
return rc; // ignore_clang_sa_mem_leak
|
return rc; // ignore_clang_sa_mem_leak
|
||||||
|
|
||||||
@@ -2635,6 +2827,7 @@ hidpp20_onboard_profiles_initialize(struct hidpp20_device *device,
|
|||||||
read_userdata = false;
|
read_userdata = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
read_profiles:
|
||||||
for (i = 0; i < profiles->num_profiles; i++) {
|
for (i = 0; i < profiles->num_profiles; i++) {
|
||||||
if (read_userdata) {
|
if (read_userdata) {
|
||||||
hidpp_log_debug(&device->base, "Parsing profile %u\n", i);
|
hidpp_log_debug(&device->base, "Parsing profile %u\n", i);
|
||||||
@@ -2669,7 +2862,7 @@ hidpp20_onboard_profiles_initialize(struct hidpp20_device *device,
|
|||||||
return profiles->num_profiles;
|
return profiles->num_profiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
hidpp20_onboard_profiles_write_led(struct hidpp20_internal_led *internal_led,
|
hidpp20_onboard_profiles_write_led(struct hidpp20_internal_led *internal_led,
|
||||||
struct hidpp20_led *led)
|
struct hidpp20_led *led)
|
||||||
{
|
{
|
||||||
@@ -2688,24 +2881,31 @@ hidpp20_onboard_profiles_write_led(struct hidpp20_internal_led *internal_led,
|
|||||||
else
|
else
|
||||||
internal_led->effect.cycle.intensity = 0;
|
internal_led->effect.cycle.intensity = 0;
|
||||||
break;
|
break;
|
||||||
|
case HIDPP20_LED_STARLIGHT:
|
||||||
|
internal_led->effect.starlight.color_sky = led->color;
|
||||||
|
internal_led->effect.starlight.color_star = led->extra_color;
|
||||||
|
break;
|
||||||
case HIDPP20_LED_BREATHING:
|
case HIDPP20_LED_BREATHING:
|
||||||
internal_led->effect.breath.color.red = led->color.red;
|
internal_led->effect.breath.color = led->color;
|
||||||
internal_led->effect.breath.color.blue = led->color.blue;
|
|
||||||
internal_led->effect.breath.color.green = led->color.green;
|
|
||||||
internal_led->effect.breath.period_or_speed = hidpp_cpu_to_be_u16(period);
|
internal_led->effect.breath.period_or_speed = hidpp_cpu_to_be_u16(period);
|
||||||
if (brightness < 100)
|
if (brightness < 100)
|
||||||
internal_led->effect.breath.intensity = brightness;
|
internal_led->effect.breath.intensity = brightness;
|
||||||
else
|
else
|
||||||
internal_led->effect.breath.intensity = 0;
|
internal_led->effect.breath.intensity = 0;
|
||||||
break;
|
break;
|
||||||
|
case HIDPP20_LED_RIPPLE:
|
||||||
|
internal_led->effect.ripple.color = led->color;
|
||||||
|
internal_led->effect.ripple.period = hidpp_cpu_to_be_u16(period);
|
||||||
|
break;
|
||||||
case HIDPP20_LED_ON:
|
case HIDPP20_LED_ON:
|
||||||
internal_led->effect.fixed.color.red = led->color.red;
|
internal_led->effect.fixed.color = led->color;
|
||||||
internal_led->effect.fixed.color.blue = led->color.blue;
|
|
||||||
internal_led->effect.fixed.color.green = led->color.green;
|
|
||||||
internal_led->effect.fixed.effect = 0;
|
internal_led->effect.fixed.effect = 0;
|
||||||
break;
|
break;
|
||||||
case HIDPP20_LED_OFF:
|
case HIDPP20_LED_OFF:
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
memcpy(internal_led, led->original, sizeof(*internal_led));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2753,8 +2953,10 @@ hidpp20_onboard_profiles_write_profile(struct hidpp20_device *device,
|
|||||||
memcpy(pdata->profile.name.txt, profile->name, sizeof(profile->name));
|
memcpy(pdata->profile.name.txt, profile->name, sizeof(profile->name));
|
||||||
|
|
||||||
rc = hidpp20_onboard_profiles_write_sector(device, sector, sector_size, data, true);
|
rc = hidpp20_onboard_profiles_write_sector(device, sector, sector_size, data, true);
|
||||||
if (rc < 0)
|
if (rc < 0) {
|
||||||
|
hidpp_log_error(&device->base, "failed to write profile\n");
|
||||||
return rc;
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -2837,7 +3039,7 @@ hidpp20_onboard_profiles_get_code_from_special(enum ratbag_button_action_special
|
|||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
struct hidpp20_device *
|
struct hidpp20_device *
|
||||||
hidpp20_device_new(const struct hidpp_device *base, unsigned int idx)
|
hidpp20_device_new(const struct hidpp_device *base, unsigned int idx, struct hidpp_hid_report *reports, unsigned int num_reports)
|
||||||
{
|
{
|
||||||
struct hidpp20_device *dev;
|
struct hidpp20_device *dev;
|
||||||
int rc;
|
int rc;
|
||||||
@@ -2850,6 +3052,14 @@ hidpp20_device_new(const struct hidpp_device *base, unsigned int idx)
|
|||||||
dev->proto_major = 1;
|
dev->proto_major = 1;
|
||||||
dev->proto_minor = 0;
|
dev->proto_minor = 0;
|
||||||
|
|
||||||
|
dev->led_ext_caps = 0;
|
||||||
|
|
||||||
|
hidpp_get_supported_report_types(&(dev->base), reports, num_reports);
|
||||||
|
|
||||||
|
if (!(dev->base.supported_report_types & HIDPP_REPORT_SHORT) &&
|
||||||
|
!(dev->base.supported_report_types & HIDPP_REPORT_LONG))
|
||||||
|
goto err;
|
||||||
|
|
||||||
rc = hidpp20_root_get_protocol_version(dev, &dev->proto_major, &dev->proto_minor);
|
rc = hidpp20_root_get_protocol_version(dev, &dev->proto_major, &dev->proto_minor);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
/* communication error, best to ignore the device */
|
/* communication error, best to ignore the device */
|
||||||
|
|||||||
@@ -51,6 +51,12 @@ struct hidpp20_feature {
|
|||||||
uint8_t type;
|
uint8_t type;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum hidpp20_quirk {
|
||||||
|
HIDPP20_QUIRK_NONE,
|
||||||
|
HIDPP20_QUIRK_G305,
|
||||||
|
HIDPP20_QUIRK_G602,
|
||||||
|
};
|
||||||
|
|
||||||
struct hidpp20_device {
|
struct hidpp20_device {
|
||||||
struct hidpp_device base;
|
struct hidpp_device base;
|
||||||
unsigned int index;
|
unsigned int index;
|
||||||
@@ -58,18 +64,25 @@ struct hidpp20_device {
|
|||||||
unsigned proto_minor;
|
unsigned proto_minor;
|
||||||
unsigned feature_count;
|
unsigned feature_count;
|
||||||
struct hidpp20_feature *feature_list;
|
struct hidpp20_feature *feature_list;
|
||||||
|
enum hidpp20_quirk quirk;
|
||||||
|
unsigned int led_ext_caps;
|
||||||
};
|
};
|
||||||
|
|
||||||
int hidpp20_request_command(struct hidpp20_device *dev, union hidpp20_message *msg);
|
int hidpp20_request_command(struct hidpp20_device *dev, union hidpp20_message *msg);
|
||||||
|
|
||||||
|
#define CASE_RETURN_STRING(a) case a: return #a; break
|
||||||
|
|
||||||
const char *hidpp20_feature_get_name(uint16_t feature);
|
const char *hidpp20_feature_get_name(uint16_t feature);
|
||||||
|
|
||||||
|
const char *hidpp20_get_quirk_string(enum hidpp20_quirk quirk);
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
/* generic hidpp20 device operations */
|
/* generic hidpp20 device operations */
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
struct hidpp20_device *
|
struct hidpp20_device *
|
||||||
hidpp20_device_new(const struct hidpp_device *base, unsigned int idx);
|
hidpp20_device_new(const struct hidpp_device *base, unsigned int idx,
|
||||||
|
struct hidpp_hid_report *reports, unsigned int num_reports);
|
||||||
|
|
||||||
void
|
void
|
||||||
hidpp20_device_destroy(struct hidpp20_device *device);
|
hidpp20_device_destroy(struct hidpp20_device *device);
|
||||||
@@ -420,6 +433,12 @@ int hidpp20_adjustable_dpi_set_sensor_dpi(struct hidpp20_device *device,
|
|||||||
int hidpp20_adjustable_report_rate_get_report_rate_list(struct hidpp20_device *device,
|
int hidpp20_adjustable_report_rate_get_report_rate_list(struct hidpp20_device *device,
|
||||||
uint8_t *bitflags_ms);
|
uint8_t *bitflags_ms);
|
||||||
|
|
||||||
|
int hidpp20_adjustable_report_rate_get_report_rate(struct hidpp20_device *device,
|
||||||
|
uint8_t *rate_ms);
|
||||||
|
|
||||||
|
int hidpp20_adjustable_report_rate_set_report_rate(struct hidpp20_device *device,
|
||||||
|
uint8_t rate_ms);
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
/* 0x8070v4 - Color LED effects */
|
/* 0x8070v4 - Color LED effects */
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
@@ -483,6 +502,18 @@ hidpp20_rgb_effects_get_effect_info(struct hidpp20_device *device,
|
|||||||
uint8_t effect_index,
|
uint8_t effect_index,
|
||||||
struct hidpp20_rgb_effect_info *info);
|
struct hidpp20_rgb_effect_info *info);
|
||||||
|
|
||||||
|
struct hidpp20_led;
|
||||||
|
|
||||||
|
int
|
||||||
|
hidpp20_color_led_effects_set_zone_effect(struct hidpp20_device *device,
|
||||||
|
uint8_t zone_index,
|
||||||
|
struct hidpp20_led led);
|
||||||
|
|
||||||
|
int
|
||||||
|
hidpp20_color_led_effects_get_zone_effect(struct hidpp20_device *device,
|
||||||
|
uint8_t zone_index,
|
||||||
|
struct hidpp20_led *led);
|
||||||
|
|
||||||
enum hidpp20_color_led_location {
|
enum hidpp20_color_led_location {
|
||||||
HIDPP20_COLOR_LED_LOCATION_UNDEFINED = 0,
|
HIDPP20_COLOR_LED_LOCATION_UNDEFINED = 0,
|
||||||
HIDPP20_COLOR_LED_LOCATION_PRIMARY,
|
HIDPP20_COLOR_LED_LOCATION_PRIMARY,
|
||||||
@@ -587,6 +618,8 @@ union hidpp20_button_binding {
|
|||||||
struct {
|
struct {
|
||||||
uint8_t type; /* HIDPP20_BUTTON_SPECIAL */
|
uint8_t type; /* HIDPP20_BUTTON_SPECIAL */
|
||||||
uint8_t special;
|
uint8_t special;
|
||||||
|
uint8_t reserved;
|
||||||
|
uint8_t profile;
|
||||||
} __attribute__((packed)) special;
|
} __attribute__((packed)) special;
|
||||||
struct {
|
struct {
|
||||||
uint8_t type; /* HIDPP20_BUTTON_MACRO */
|
uint8_t type; /* HIDPP20_BUTTON_MACRO */
|
||||||
@@ -686,7 +719,11 @@ enum hidpp20_led_mode {
|
|||||||
HIDPP20_LED_OFF = 0x00,
|
HIDPP20_LED_OFF = 0x00,
|
||||||
HIDPP20_LED_ON = 0x01,
|
HIDPP20_LED_ON = 0x01,
|
||||||
HIDPP20_LED_CYCLE = 0x03,
|
HIDPP20_LED_CYCLE = 0x03,
|
||||||
|
HIDPP20_LED_COLOR_WAVE = 0x04,
|
||||||
|
HIDPP20_LED_STARLIGHT = 0x05,
|
||||||
HIDPP20_LED_BREATHING = 0x0a,
|
HIDPP20_LED_BREATHING = 0x0a,
|
||||||
|
HIDPP20_LED_RIPPLE = 0x0b,
|
||||||
|
HIDPP20_LED_CUSTOM = 0x0c,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum hidpp20_led_waveform {
|
enum hidpp20_led_waveform {
|
||||||
@@ -711,27 +748,48 @@ struct hidpp20_internal_led {
|
|||||||
uint16_t period_or_speed; /* period in ms, speed is device dependent */
|
uint16_t period_or_speed; /* period in ms, speed is device dependent */
|
||||||
uint8_t intensity; /* 1 - 100 percent, 0 means 100 */
|
uint8_t intensity; /* 1 - 100 percent, 0 means 100 */
|
||||||
} __attribute__((packed)) cycle;
|
} __attribute__((packed)) cycle;
|
||||||
|
struct hidpp20_led_starlight {
|
||||||
|
struct hidpp20_color color_sky;
|
||||||
|
struct hidpp20_color color_star;
|
||||||
|
} __attribute__((packed)) starlight;
|
||||||
struct hidpp20_led_breath {
|
struct hidpp20_led_breath {
|
||||||
struct hidpp20_color color;
|
struct hidpp20_color color;
|
||||||
uint16_t period_or_speed; /* period in ms, speed is device dependent */
|
uint16_t period_or_speed; /* period in ms, speed is device dependent */
|
||||||
uint8_t waveform; /* enum hidpp20_led_waveform */
|
uint8_t waveform; /* enum hidpp20_led_waveform */
|
||||||
uint8_t intensity; /* 1 - 100 percent, 0 means 100 */
|
uint8_t intensity; /* 1 - 100 percent, 0 means 100 */
|
||||||
} __attribute__((packed)) breath;
|
} __attribute__((packed)) breath;
|
||||||
|
struct hidpp20_led_ripple {
|
||||||
|
struct hidpp20_color color;
|
||||||
|
uint8_t reserved;
|
||||||
|
uint16_t period;
|
||||||
|
} __attribute__((packed)) ripple;
|
||||||
|
struct hidpp20_led_custom {
|
||||||
|
uint8_t slot;
|
||||||
|
uint16_t init_frame;
|
||||||
|
uint16_t lenght;
|
||||||
|
uint16_t frame_period;
|
||||||
|
uint8_t intensity;
|
||||||
|
} __attribute__((packed)) custom;
|
||||||
uint8_t padding[10];
|
uint8_t padding[10];
|
||||||
} __attribute__((packed)) effect;
|
} __attribute__((packed)) effect;
|
||||||
};
|
};
|
||||||
_Static_assert(sizeof(struct hidpp20_led_fixed) == 4, "Invalid size");
|
_Static_assert(sizeof(struct hidpp20_led_fixed) == 4, "Invalid size");
|
||||||
_Static_assert(sizeof(struct hidpp20_led_cycle) == 8, "Invalid size");
|
_Static_assert(sizeof(struct hidpp20_led_cycle) == 8, "Invalid size");
|
||||||
|
_Static_assert(sizeof(struct hidpp20_led_starlight) == 6, "Invalid size");
|
||||||
_Static_assert(sizeof(struct hidpp20_led_breath) == 7, "Invalid size");
|
_Static_assert(sizeof(struct hidpp20_led_breath) == 7, "Invalid size");
|
||||||
_Static_assert(sizeof(struct hidpp20_internal_led) == 11, "Invalid size");
|
_Static_assert(sizeof(struct hidpp20_internal_led) == 11, "Invalid size");
|
||||||
|
_Static_assert(sizeof(struct hidpp20_led_ripple) == 6, "Invalid size");
|
||||||
|
_Static_assert(sizeof(struct hidpp20_led_custom) == 8, "Invalid size");
|
||||||
|
|
||||||
typedef uint8_t percent_t;
|
typedef uint8_t percent_t;
|
||||||
|
|
||||||
struct hidpp20_led {
|
struct hidpp20_led {
|
||||||
enum hidpp20_led_mode mode;
|
enum hidpp20_led_mode mode;
|
||||||
struct hidpp20_color color;
|
struct hidpp20_color color;
|
||||||
|
struct hidpp20_color extra_color;
|
||||||
uint16_t period;
|
uint16_t period;
|
||||||
percent_t brightness;
|
percent_t brightness;
|
||||||
|
uint8_t original[sizeof(struct hidpp20_internal_led)];
|
||||||
};
|
};
|
||||||
|
|
||||||
#define HIDPP20_MACRO_NOOP 0x01
|
#define HIDPP20_MACRO_NOOP 0x01
|
||||||
@@ -907,6 +965,14 @@ hidpp20_onboard_profiles_allocate_sector(struct hidpp20_profiles *profiles)
|
|||||||
return zalloc(profiles->sector_size);
|
return zalloc(profiles->sector_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
hidpp20_onboard_profiles_read_led(struct hidpp20_led *led,
|
||||||
|
struct hidpp20_internal_led internal_led);
|
||||||
|
|
||||||
|
void
|
||||||
|
hidpp20_onboard_profiles_write_led(struct hidpp20_internal_led *internal_led,
|
||||||
|
struct hidpp20_led *led);
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
/* 0x8110 - Mouse Button Spy */
|
/* 0x8110 - Mouse Button Spy */
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|||||||
@@ -33,6 +33,7 @@
|
|||||||
#include "libratbag.h"
|
#include "libratbag.h"
|
||||||
#include "libratbag-private.h"
|
#include "libratbag-private.h"
|
||||||
#include "libratbag-data.h"
|
#include "libratbag-data.h"
|
||||||
|
#include "hidpp20.h"
|
||||||
|
|
||||||
#define GROUP_DEVICE "Device"
|
#define GROUP_DEVICE "Device"
|
||||||
|
|
||||||
@@ -54,6 +55,7 @@ enum driver {
|
|||||||
|
|
||||||
struct data_hidpp20 {
|
struct data_hidpp20 {
|
||||||
int index;
|
int index;
|
||||||
|
enum hidpp20_quirk quirk;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct data_hidpp10 {
|
struct data_hidpp10 {
|
||||||
@@ -152,6 +154,7 @@ init_data_hidpp20(struct ratbag *ratbag,
|
|||||||
const char *group = "Driver/hidpp20";
|
const char *group = "Driver/hidpp20";
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
int num;
|
int num;
|
||||||
|
char *str;
|
||||||
|
|
||||||
data->hidpp20.index = -1;
|
data->hidpp20.index = -1;
|
||||||
|
|
||||||
@@ -160,6 +163,15 @@ init_data_hidpp20(struct ratbag *ratbag,
|
|||||||
data->hidpp20.index = num;
|
data->hidpp20.index = num;
|
||||||
if (error)
|
if (error)
|
||||||
g_error_free(error);
|
g_error_free(error);
|
||||||
|
|
||||||
|
str = g_key_file_get_string(keyfile, group, "Quirk", NULL);
|
||||||
|
data->hidpp20.quirk = HIDPP20_QUIRK_NONE;
|
||||||
|
if (str) {
|
||||||
|
if (streq(str, "G305"))
|
||||||
|
data->hidpp20.quirk = HIDPP20_QUIRK_G305;
|
||||||
|
else if(streq(str, "G602"))
|
||||||
|
data->hidpp20.quirk = HIDPP20_QUIRK_G602;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -334,6 +346,8 @@ parse_ledtypes(char **strv, enum ratbag_led_type *types, size_t ntypes)
|
|||||||
types[i] = RATBAG_LED_TYPE_SIDE;
|
types[i] = RATBAG_LED_TYPE_SIDE;
|
||||||
else if (streq(s, "wheel"))
|
else if (streq(s, "wheel"))
|
||||||
types[i] = RATBAG_LED_TYPE_WHEEL;
|
types[i] = RATBAG_LED_TYPE_WHEEL;
|
||||||
|
else if (streq(s, "switches"))
|
||||||
|
types[i] = RATBAG_LED_TYPE_SWITCHES;
|
||||||
else
|
else
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@@ -562,6 +576,14 @@ ratbag_device_data_hidpp20_get_index(const struct ratbag_device_data *data)
|
|||||||
return data->hidpp20.index;
|
return data->hidpp20.index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum hidpp20_quirk
|
||||||
|
ratbag_device_data_hidpp20_get_quirk(const struct ratbag_device_data *data)
|
||||||
|
{
|
||||||
|
assert(data->drivertype == HIDPP20);
|
||||||
|
|
||||||
|
return data->hidpp20.quirk;
|
||||||
|
}
|
||||||
|
|
||||||
/* SteelSeries */
|
/* SteelSeries */
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|||||||
@@ -80,6 +80,9 @@ ratbag_device_data_hidpp10_get_led_count(const struct ratbag_device_data *data);
|
|||||||
int
|
int
|
||||||
ratbag_device_data_hidpp20_get_index(const struct ratbag_device_data *data);
|
ratbag_device_data_hidpp20_get_index(const struct ratbag_device_data *data);
|
||||||
|
|
||||||
|
enum hidpp20_quirk
|
||||||
|
ratbag_device_data_hidpp20_get_quirk(const struct ratbag_device_data *data);
|
||||||
|
|
||||||
/* SteelSeries */
|
/* SteelSeries */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -293,6 +293,7 @@ enum ratbag_led_type {
|
|||||||
RATBAG_LED_TYPE_BATTERY,
|
RATBAG_LED_TYPE_BATTERY,
|
||||||
RATBAG_LED_TYPE_DPI,
|
RATBAG_LED_TYPE_DPI,
|
||||||
RATBAG_LED_TYPE_WHEEL,
|
RATBAG_LED_TYPE_WHEEL,
|
||||||
|
RATBAG_LED_TYPE_SWITCHES,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -295,6 +295,7 @@ struct ratbag_profile {
|
|||||||
unsigned int hz; /**< report rate in Hz */
|
unsigned int hz; /**< report rate in Hz */
|
||||||
unsigned int rates[8]; /**< report rates available */
|
unsigned int rates[8]; /**< report rates available */
|
||||||
size_t nrates; /**< number of entries in rates */
|
size_t nrates; /**< number of entries in rates */
|
||||||
|
bool rate_dirty;
|
||||||
|
|
||||||
unsigned int num_resolutions;
|
unsigned int num_resolutions;
|
||||||
|
|
||||||
@@ -585,14 +586,14 @@ ratbag_led_set_mode_capability(struct ratbag_led *led,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* list of all supported drivers */
|
/* list of all supported drivers */
|
||||||
struct ratbag_driver etekcity_driver;
|
extern struct ratbag_driver etekcity_driver;
|
||||||
struct ratbag_driver hidpp20_driver;
|
extern struct ratbag_driver hidpp20_driver;
|
||||||
struct ratbag_driver hidpp10_driver;
|
extern struct ratbag_driver hidpp10_driver;
|
||||||
struct ratbag_driver logitech_g300_driver;
|
extern struct ratbag_driver logitech_g300_driver;
|
||||||
struct ratbag_driver logitech_g600_driver;
|
extern struct ratbag_driver logitech_g600_driver;
|
||||||
struct ratbag_driver roccat_driver;
|
extern struct ratbag_driver roccat_driver;
|
||||||
struct ratbag_driver gskill_driver;
|
extern struct ratbag_driver gskill_driver;
|
||||||
struct ratbag_driver steelseries_driver;
|
extern struct ratbag_driver steelseries_driver;
|
||||||
|
|
||||||
struct ratbag_device*
|
struct ratbag_device*
|
||||||
ratbag_device_new(struct ratbag *ratbag, struct udev_device *udev_device,
|
ratbag_device_new(struct ratbag *ratbag, struct udev_device *udev_device,
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
#include "libratbag-util.h"
|
#include "libratbag-util.h"
|
||||||
#include "libratbag-test.h"
|
#include "libratbag-test.h"
|
||||||
|
|
||||||
struct ratbag_driver test_driver;
|
extern struct ratbag_driver test_driver;
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
ratbag_register_test_drivers(struct ratbag *ratbag)
|
ratbag_register_test_drivers(struct ratbag *ratbag)
|
||||||
|
|||||||
@@ -71,17 +71,29 @@ ratbag_default_log_func(struct ratbag *ratbag,
|
|||||||
const char *format, va_list args)
|
const char *format, va_list args)
|
||||||
{
|
{
|
||||||
const char *prefix;
|
const char *prefix;
|
||||||
|
FILE *out = stdout;
|
||||||
|
|
||||||
switch(priority) {
|
switch(priority) {
|
||||||
case RATBAG_LOG_PRIORITY_RAW: prefix = "raw"; break;
|
case RATBAG_LOG_PRIORITY_RAW:
|
||||||
case RATBAG_LOG_PRIORITY_DEBUG: prefix = "debug"; break;
|
prefix = "raw";
|
||||||
case RATBAG_LOG_PRIORITY_INFO: prefix = "info"; break;
|
break;
|
||||||
case RATBAG_LOG_PRIORITY_ERROR: prefix = "error"; break;
|
case RATBAG_LOG_PRIORITY_DEBUG:
|
||||||
default: prefix="<invalid priority>"; break;
|
prefix = "debug";
|
||||||
|
break;
|
||||||
|
case RATBAG_LOG_PRIORITY_INFO:
|
||||||
|
prefix = "info";
|
||||||
|
break;
|
||||||
|
case RATBAG_LOG_PRIORITY_ERROR:
|
||||||
|
prefix = "error";
|
||||||
|
out = stderr;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
prefix="<invalid priority>";
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(stderr, "ratbag %s: ", prefix);
|
fprintf(out, "ratbag %s: ", prefix);
|
||||||
vfprintf(stderr, format, args);
|
vfprintf(out, format, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -256,7 +268,7 @@ ratbag_sanity_check_device(struct ratbag_device *device)
|
|||||||
}
|
}
|
||||||
|
|
||||||
nres = ratbag_profile_get_num_resolutions(profile);
|
nres = ratbag_profile_get_num_resolutions(profile);
|
||||||
if (nres == 0 || nres > 16) {
|
if (nres > 16) {
|
||||||
log_bug_libratbag(ratbag,
|
log_bug_libratbag(ratbag,
|
||||||
"%s: invalid number of resolutions (%d)\n",
|
"%s: invalid number of resolutions (%d)\n",
|
||||||
device->name,
|
device->name,
|
||||||
@@ -322,7 +334,7 @@ out:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline bool
|
static inline bool
|
||||||
ratbag_test_driver(struct ratbag_device *device,
|
ratbag_try_driver(struct ratbag_device *device,
|
||||||
const struct input_id *dev_id,
|
const struct input_id *dev_id,
|
||||||
const char *driver_name,
|
const char *driver_name,
|
||||||
const struct ratbag_test_device *test_device)
|
const struct ratbag_test_device *test_device)
|
||||||
@@ -377,9 +389,9 @@ ratbag_driver_fallback_logitech(struct ratbag_device *device,
|
|||||||
if (dev_id->vendor != USB_VENDOR_ID_LOGITECH)
|
if (dev_id->vendor != USB_VENDOR_ID_LOGITECH)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
rc = ratbag_test_driver(device, dev_id, "hidpp20", NULL);
|
rc = ratbag_try_driver(device, dev_id, "hidpp20", NULL);
|
||||||
if (!rc)
|
if (!rc)
|
||||||
rc = ratbag_test_driver(device, dev_id, "hidpp10", NULL);
|
rc = ratbag_try_driver(device, dev_id, "hidpp10", NULL);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@@ -401,7 +413,7 @@ ratbag_assign_driver(struct ratbag_device *device,
|
|||||||
|
|
||||||
if (driver_name) {
|
if (driver_name) {
|
||||||
log_debug(device->ratbag, "device assigned driver %s\n", driver_name);
|
log_debug(device->ratbag, "device assigned driver %s\n", driver_name);
|
||||||
rc = ratbag_test_driver(device, dev_id, driver_name, test_device);
|
rc = ratbag_try_driver(device, dev_id, driver_name, test_device);
|
||||||
} else {
|
} else {
|
||||||
rc = ratbag_driver_fallback_logitech(device, dev_id);
|
rc = ratbag_driver_fallback_logitech(device, dev_id);
|
||||||
}
|
}
|
||||||
@@ -937,6 +949,8 @@ ratbag_device_commit(struct ratbag_device *device)
|
|||||||
list_for_each(profile, &device->profiles, link) {
|
list_for_each(profile, &device->profiles, link) {
|
||||||
profile->dirty = false;
|
profile->dirty = false;
|
||||||
|
|
||||||
|
profile->rate_dirty = false;
|
||||||
|
|
||||||
list_for_each(button, &profile->buttons, link)
|
list_for_each(button, &profile->buttons, link)
|
||||||
button->dirty = false;
|
button->dirty = false;
|
||||||
|
|
||||||
@@ -1105,6 +1119,7 @@ ratbag_profile_set_report_rate(struct ratbag_profile *profile,
|
|||||||
if (profile->hz != hz) {
|
if (profile->hz != hz) {
|
||||||
profile->hz = hz;
|
profile->hz = hz;
|
||||||
profile->dirty = true;
|
profile->dirty = true;
|
||||||
|
profile->rate_dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return RATBAG_SUCCESS;
|
return RATBAG_SUCCESS;
|
||||||
|
|||||||
@@ -52,6 +52,28 @@
|
|||||||
%typemap(freearg) (unsigned int *rates, size_t nrates) = (unsigned int *resolutions, size_t nres);
|
%typemap(freearg) (unsigned int *rates, size_t nrates) = (unsigned int *resolutions, size_t nres);
|
||||||
/* END OF custom typemap for handling ratbag_resolution_get_report_rate_list */
|
/* END OF custom typemap for handling ratbag_resolution_get_report_rate_list */
|
||||||
|
|
||||||
|
/* uintXX_t mapping: Python -> C */
|
||||||
|
%typemap(in) uint8_t {
|
||||||
|
$1 = (uint8_t) PyInt_AsLong($input);
|
||||||
|
}
|
||||||
|
%typemap(in) uint16_t {
|
||||||
|
$1 = (uint16_t) PyInt_AsLong($input);
|
||||||
|
}
|
||||||
|
%typemap(in) uint32_t {
|
||||||
|
$1 = (uint32_t) PyInt_AsLong($input);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* uintXX_t mapping: C -> Python */
|
||||||
|
%typemap(out) uint8_t {
|
||||||
|
$result = PyInt_FromLong((long) $1);
|
||||||
|
}
|
||||||
|
%typemap(out) uint16_t {
|
||||||
|
$result = PyInt_FromLong((long) $1);
|
||||||
|
}
|
||||||
|
%typemap(out) uint32_t {
|
||||||
|
$result = PyInt_FromLong((long) $1);
|
||||||
|
}
|
||||||
|
|
||||||
/* Parse the header file to generate wrappers */
|
/* Parse the header file to generate wrappers */
|
||||||
%include "libratbag.h"
|
%include "libratbag.h"
|
||||||
%include "libratbag-enums.h"
|
%include "libratbag-enums.h"
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ main(int argc, char **argv)
|
|||||||
error(1, errno, "Failed to open path %s", path);
|
error(1, errno, "Failed to open path %s", path);
|
||||||
|
|
||||||
hidpp_device_init(&base, fd);
|
hidpp_device_init(&base, fd);
|
||||||
dev = hidpp20_device_new(&base, 0xff);
|
dev = hidpp20_device_new(&base, 0xff, NULL, 0);
|
||||||
if (!dev)
|
if (!dev)
|
||||||
error(1, 0, "Failed to open %s as a HID++ 2.0 device", path);
|
error(1, 0, "Failed to open %s as a HID++ 2.0 device", path);
|
||||||
|
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ main(int argc, char **argv)
|
|||||||
error(1, errno, "Failed to open path %s", path);
|
error(1, errno, "Failed to open path %s", path);
|
||||||
|
|
||||||
hidpp_device_init(&base, fd);
|
hidpp_device_init(&base, fd);
|
||||||
dev = hidpp20_device_new(&base, 0xff);
|
dev = hidpp20_device_new(&base, 0xff, NULL, 0);
|
||||||
if (!dev)
|
if (!dev)
|
||||||
error(1, 0, "Failed to open %s as a HID++ 2.0 device", path);
|
error(1, 0, "Failed to open %s as a HID++ 2.0 device", path);
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
#
|
#
|
||||||
# vim: set expandtab shiftwidth=4 tabstop=4:
|
|
||||||
#
|
|
||||||
# Copyright 2017 Red Hat, Inc.
|
# Copyright 2017 Red Hat, Inc.
|
||||||
#
|
#
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining a
|
# Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
# vim: set expandtab shiftwidth=4 tabstop=4:
|
# Copyright 2017-2019 Red Hat, Inc.
|
||||||
#
|
|
||||||
# Copyright 2017 Red Hat, Inc.
|
|
||||||
#
|
#
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining a
|
# Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
# copy of this software and associated documentation files (the "Software"),
|
# copy of this software and associated documentation files (the "Software"),
|
||||||
@@ -137,7 +135,7 @@ class Ratbagd(object):
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self, apiversion):
|
||||||
os.environ['LIBRATBAG_DATA_DIR'] = LIBRATBAG_DATA_DIR
|
os.environ['LIBRATBAG_DATA_DIR'] = LIBRATBAG_DATA_DIR
|
||||||
self._ratbag = libratbag.ratbag_create_context(libratbag.interface, None)
|
self._ratbag = libratbag.ratbag_create_context(libratbag.interface, None)
|
||||||
self._devices = {}
|
self._devices = {}
|
||||||
@@ -251,13 +249,13 @@ class RatbagdDevice(metaclass=MetaRatbag):
|
|||||||
@property
|
@property
|
||||||
def model(self):
|
def model(self):
|
||||||
"""The unique identifier for this device model."""
|
"""The unique identifier for this device model."""
|
||||||
bus = libratbag.ratbag_device_get_bus(self._device)
|
bus = libratbag.ratbag_device_get_bustype(self._device)
|
||||||
if not bus:
|
if not bus:
|
||||||
return "unknown"
|
return "unknown"
|
||||||
vid = libratbag.ratbag_device_get_vendor_id(self._device)
|
vid = libratbag.ratbag_device_get_vendor_id(self._device)
|
||||||
pid = libratbag.ratbag_device_get_product_id(self._device)
|
pid = libratbag.ratbag_device_get_product_id(self._device)
|
||||||
version = libratbag.ratbag_device_get_product_version(self._device)
|
version = libratbag.ratbag_device_get_product_version(self._device)
|
||||||
return "{}:{04x}:{04x}:{d}".format(bus, vid, pid, version)
|
return "{}:{:04x}:{:04x}:{:d}".format(bus, vid, pid, version)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self):
|
||||||
@@ -324,7 +322,7 @@ class RatbagdProfile(metaclass=MetaRatbag):
|
|||||||
"""The capabilities of this profile as an array. Capabilities not
|
"""The capabilities of this profile as an array. Capabilities not
|
||||||
present on the profile are not in the list. Thus use e.g.
|
present on the profile are not in the list. Thus use e.g.
|
||||||
|
|
||||||
if RatbagdProfile.CAP_WRITABLE_NAME is in profile.capabilities:
|
if RatbagdProfile.CAP_WRITABLE_NAME in profile.capabilities:
|
||||||
do something
|
do something
|
||||||
"""
|
"""
|
||||||
return self._capabilities
|
return self._capabilities
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
#
|
#
|
||||||
# vim: set expandtab shiftwidth=4 tabstop=4:
|
|
||||||
#
|
|
||||||
# This file is part of libratbag.
|
# This file is part of libratbag.
|
||||||
#
|
#
|
||||||
# Copyright 2017 Red Hat, Inc.
|
# Copyright 2017 Red Hat, Inc.
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
#
|
#
|
||||||
# vim: set expandtab shiftwidth=4 tabstop=4:
|
|
||||||
#
|
|
||||||
# Copyright 2016 Red Hat, Inc.
|
# Copyright 2016 Red Hat, Inc.
|
||||||
#
|
#
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining a
|
# Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
#
|
#
|
||||||
# vim: set expandtab shiftwidth=4 tabstop=4:
|
|
||||||
#
|
|
||||||
# This file is part of libratbag.
|
# This file is part of libratbag.
|
||||||
#
|
#
|
||||||
# Copyright 2017 Red Hat, Inc.
|
# Copyright 2017 Red Hat, Inc.
|
||||||
@@ -374,6 +372,7 @@ class TestRatbagCtlDPI(TestRatbagCtl):
|
|||||||
{ "is_active": false,
|
{ "is_active": false,
|
||||||
"resolutions": [
|
"resolutions": [
|
||||||
{ "xres": 1000, "yres": 1100,
|
{ "xres": 1000, "yres": 1100,
|
||||||
|
"capabilities": [1],
|
||||||
"is_active": false },
|
"is_active": false },
|
||||||
{ "xres": 1300, "yres": 1400,
|
{ "xres": 1300, "yres": 1400,
|
||||||
"capabilities": [1],
|
"capabilities": [1],
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
# vim: set expandtab shiftwidth=4 tabstop=4:
|
# Copyright 2016-2019 Red Hat, Inc.
|
||||||
#
|
|
||||||
# Copyright 2016 Red Hat, Inc.
|
|
||||||
#
|
#
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining a
|
# Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
# copy of this software and associated documentation files (the "Software"),
|
# copy of this software and associated documentation files (the "Software"),
|
||||||
@@ -252,11 +250,13 @@ class Ratbagd(_RatbagdDBus):
|
|||||||
|
|
||||||
def __init__(self, api_version):
|
def __init__(self, api_version):
|
||||||
super().__init__("Manager", None)
|
super().__init__("Manager", None)
|
||||||
result = self._get_dbus_property("Devices") or []
|
result = self._get_dbus_property("Devices")
|
||||||
self._devices = [RatbagdDevice(objpath) for objpath in result]
|
if result is None and not self._proxy.get_cached_property_names():
|
||||||
self._proxy.connect("notify::g-name-owner", self._on_name_owner_changed)
|
raise RatbagdUnavailable("Make sure it is running and your user is in the required groups.")
|
||||||
if self.api_version != api_version:
|
if self.api_version != api_version:
|
||||||
raise RatbagdIncompatible(self.api_version or -1, api_version)
|
raise RatbagdIncompatible(self.api_version or -1, api_version)
|
||||||
|
self._devices = [RatbagdDevice(objpath) for objpath in result or []]
|
||||||
|
self._proxy.connect("notify::g-name-owner", self._on_name_owner_changed)
|
||||||
|
|
||||||
def _on_name_owner_changed(self, *kwargs):
|
def _on_name_owner_changed(self, *kwargs):
|
||||||
self.emit("daemon-disappeared")
|
self.emit("daemon-disappeared")
|
||||||
@@ -428,7 +428,7 @@ class RatbagdProfile(_RatbagdDBus):
|
|||||||
"""The capabilities of this profile as an array. Capabilities not
|
"""The capabilities of this profile as an array. Capabilities not
|
||||||
present on the profile are not in the list. Thus use e.g.
|
present on the profile are not in the list. Thus use e.g.
|
||||||
|
|
||||||
if RatbagdProfile.CAP_WRITABLE_NAME is in profile.capabilities:
|
if RatbagdProfile.CAP_WRITABLE_NAME in profile.capabilities:
|
||||||
do something
|
do something
|
||||||
"""
|
"""
|
||||||
return self._get_dbus_property("Capabilities") or []
|
return self._get_dbus_property("Capabilities") or []
|
||||||
@@ -520,7 +520,7 @@ class RatbagdProfile(_RatbagdDBus):
|
|||||||
|
|
||||||
@GObject.Property
|
@GObject.Property
|
||||||
def is_active(self):
|
def is_active(self):
|
||||||
"""Returns True if the profile is currenly active, false otherwise."""
|
"""Returns True if the profile is currently active, false otherwise."""
|
||||||
return self._active
|
return self._active
|
||||||
|
|
||||||
def set_active(self):
|
def set_active(self):
|
||||||
|
|||||||
@@ -74,6 +74,9 @@ led_type_to_str(enum ratbag_led_type type)
|
|||||||
case RATBAG_LED_TYPE_WHEEL:
|
case RATBAG_LED_TYPE_WHEEL:
|
||||||
str = "wheel";
|
str = "wheel";
|
||||||
break;
|
break;
|
||||||
|
case RATBAG_LED_TYPE_SWITCHES:
|
||||||
|
str = "switches";
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
assert(!"Invalid LED type");
|
assert(!"Invalid LED type");
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -88,4 +88,4 @@ str_to_special_action(const char *str);
|
|||||||
struct ratbag_device *
|
struct ratbag_device *
|
||||||
ratbag_cmd_open_device(struct ratbag *ratbag, const char *path);
|
ratbag_cmd_open_device(struct ratbag *ratbag, const char *path);
|
||||||
|
|
||||||
const struct ratbag_interface interface;
|
extern const struct ratbag_interface interface;
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
# vim: set expandtab shiftwidth=4 tabstop=4:
|
|
||||||
#
|
|
||||||
# This file is part of libratbag.
|
# This file is part of libratbag.
|
||||||
#
|
#
|
||||||
# Copyright 2017 Red Hat, Inc.
|
# Copyright 2017 Red Hat, Inc.
|
||||||
@@ -62,9 +60,9 @@ def start_ratbagd(verbosity=0):
|
|||||||
args = [os.path.join('@MESON_BUILD_ROOT@', "ratbagd.devel")]
|
args = [os.path.join('@MESON_BUILD_ROOT@', "ratbagd.devel")]
|
||||||
|
|
||||||
if verbosity >= 3:
|
if verbosity >= 3:
|
||||||
args.append('--verbose=raw')
|
|
||||||
elif verbosity >= 2:
|
|
||||||
args.append('--verbose')
|
args.append('--verbose')
|
||||||
|
elif verbosity >= 2:
|
||||||
|
args.append('--verbose=debug')
|
||||||
elif verbosity == 0:
|
elif verbosity == 0:
|
||||||
args.append('--quiet')
|
args.append('--quiet')
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user