mirror of
https://github.com/libratbag/libratbag.git
synced 2026-11-07 15:14:38 +01:00
Compare commits
56 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3d345570eb | ||
|
|
6000688c30 | ||
|
|
9b409822c3 | ||
|
|
363eab80f0 | ||
|
|
66fc7b545e | ||
|
|
bb4b673df8 | ||
|
|
e104eca02c | ||
|
|
01c362eadc | ||
|
|
fff3589a20 | ||
|
|
a4e1e1690d | ||
|
|
38dce69838 | ||
|
|
23ff4e753d | ||
|
|
f24cb6dc66 | ||
|
|
b738136154 | ||
|
|
447931d779 | ||
|
|
920b71d94c | ||
|
|
a786aaf390 | ||
|
|
d395db1a11 | ||
|
|
ad0b7e53d9 | ||
|
|
0ed621db8f | ||
|
|
5ae473dcd1 | ||
|
|
ac384137bd | ||
|
|
e43cf7ab08 | ||
|
|
acb65a1bc8 | ||
|
|
e5f4b49e36 | ||
|
|
31d0fa00d9 | ||
|
|
d28f330d43 | ||
|
|
a29adaf913 | ||
|
|
ea3e68cf7d | ||
|
|
158594ec20 | ||
|
|
6e51849ae5 | ||
|
|
29731aa578 | ||
|
|
4d0ef4f2c1 | ||
|
|
e7d03448cc | ||
|
|
2725a55770 | ||
|
|
e5be1a70eb | ||
|
|
26493aceaf | ||
|
|
c4f5bd5218 | ||
|
|
7c65b0b4a9 | ||
|
|
d81c68d94f | ||
|
|
a5a2ea1a70 | ||
|
|
507d10378a | ||
|
|
08f3f7daf2 | ||
|
|
9b848084fd | ||
|
|
e1ebf7ad1b | ||
|
|
38f46a9be8 | ||
|
|
d07b7582db | ||
|
|
af194a22f0 | ||
|
|
d8c7050f6f | ||
|
|
30e834b18b | ||
|
|
49770a22e7 | ||
|
|
de8cba13cf | ||
|
|
1fab318dd3 | ||
|
|
e2190964c2 | ||
|
|
8eddf99823 | ||
|
|
9fede0e68d |
@@ -6,7 +6,7 @@ way to access the various features exposed by these mice and abstracts away
|
||||
hardware-specific and kernel-specific quirks.
|
||||
|
||||
libratbag exports the devices over a DBus daemon called **ratbagd**, see the
|
||||
[ratbagd DBus Interface description](DBusInterface.md).
|
||||
[ratbagd DBus Interface description](https://libratbag.github.io/).
|
||||
|
||||
Compiling libratbag
|
||||
-------------------
|
||||
@@ -27,9 +27,9 @@ And to build or re-build after code-changes, run:
|
||||
Note: `builddir` is the build output directory and can be changed to any
|
||||
other directory name. To set configure-time options, use e.g.
|
||||
|
||||
mesonconf builddir -Denable-documentation=false
|
||||
meson configure builddir -Denable-documentation=false
|
||||
|
||||
Run `mesonconf builddir` to list the options.
|
||||
Run `meson configure builddir` to list the options.
|
||||
|
||||
Running ratbagd as DBus-activated systemd service
|
||||
-------------------------------------------------
|
||||
|
||||
@@ -124,13 +124,13 @@ scan_build_run: &scan_build_run
|
||||
- *fedora_install
|
||||
- run:
|
||||
name: Install clang and find
|
||||
command: dnf install -y clang-analyzer findutils
|
||||
command: dnf install -y clang-analyzer findutils python3-beautifulsoup4
|
||||
- checkout
|
||||
- *ninja_scan_build
|
||||
- *export_logs
|
||||
- run:
|
||||
name: Check scan-build results
|
||||
command: test ! -d ~/libratbag/build/meson-logs/scanbuild || test $(find ~/libratbag/build/meson-logs/scanbuild -maxdepth 0 ! -empty -exec echo "not empty" \; | wc -l) -eq 0 || (echo "Check scan-build results" && false)
|
||||
command: python3 ~/libratbag/tools/check_scan_build.py ~/libratbag/build/meson-logs/scanbuild
|
||||
|
||||
doc_build: &doc_build
|
||||
<<: *default_settings
|
||||
|
||||
7
data/devices/logitech-g102-g203.device
Normal file
7
data/devices/logitech-g102-g203.device
Normal file
@@ -0,0 +1,7 @@
|
||||
# G102 and G203 (USB)
|
||||
[Device]
|
||||
Name=Logitech Gaming Mouse G102/G103
|
||||
DeviceMatch=usb:046d:c084
|
||||
Svg=logitech-g102-g203.svg
|
||||
Driver=hidpp20
|
||||
LedTypes=logo;side;
|
||||
7
data/devices/logitech-g302.device
Normal file
7
data/devices/logitech-g302.device
Normal file
@@ -0,0 +1,7 @@
|
||||
# G302 over USB
|
||||
[Device]
|
||||
Name=Logitech Gaming Mouse G302
|
||||
DeviceMatch=usb:046d:c07f
|
||||
Svg=logitech-g303.svg
|
||||
Driver=hidpp20
|
||||
LedTypes=logo;side;
|
||||
6
data/devices/logitech-g600.device
Normal file
6
data/devices/logitech-g600.device
Normal file
@@ -0,0 +1,6 @@
|
||||
# WARNING: this file was automatically converted and has not yet been vetted
|
||||
[Device]
|
||||
Name=Logitech G600
|
||||
DeviceMatch=usb:046d:c24a
|
||||
Driver=logitech_g600
|
||||
Svg=logitech-g600.svg
|
||||
15
data/devices/steelseries-sensei-raw.device
Normal file
15
data/devices/steelseries-sensei-raw.device
Normal file
@@ -0,0 +1,15 @@
|
||||
[Device]
|
||||
Name=SteelSeries Sensei Raw
|
||||
DeviceMatch=usb:1038:1369
|
||||
Driver=steelseries
|
||||
Svg=steelseries-senseiraw.svg
|
||||
LedTypes=logo;dpi
|
||||
|
||||
[Driver/steelseries]
|
||||
DeviceVersion=1
|
||||
Buttons=8
|
||||
Leds=1
|
||||
DpiRange=90:5670@90
|
||||
MacroLength=1
|
||||
MonoLed=1
|
||||
ShortButton=1
|
||||
@@ -49,7 +49,7 @@ def check_layers(root):
|
||||
def check_elements(root, prefix, required=0):
|
||||
"""
|
||||
Checks for elements of the form 'prefixN' in the root tag. Any elements
|
||||
found must be consecutive or an error is printed, i.e. if there's a
|
||||
found must be consecutive or an warning is printed, i.e. if there's a
|
||||
'button8' there has to be a 'button7'.
|
||||
|
||||
If required is nonzero, an error is logged for any missing element with
|
||||
@@ -70,7 +70,7 @@ def check_elements(root, prefix, required=0):
|
||||
highest = idx
|
||||
previous = '{}{}'.format(prefix, idx - 1)
|
||||
if idx > 0 and previous not in element_ids:
|
||||
logger.error("Non-consecutive {}: {}".format(prefix, e))
|
||||
logger.warning("Non-consecutive {}: {}".format(prefix, e))
|
||||
|
||||
leader = '{}{}-leader'.format(prefix, idx)
|
||||
if leader not in element_ids:
|
||||
|
||||
1
data/gnome/logitech-g102-g203.svg
Symbolic link
1
data/gnome/logitech-g102-g203.svg
Symbolic link
@@ -0,0 +1 @@
|
||||
logitech-g303.svg
|
||||
1190
data/gnome/logitech-g600.svg
Normal file
1190
data/gnome/logitech-g600.svg
Normal file
File diff suppressed because it is too large
Load Diff
|
After Width: | Height: | Size: 95 KiB |
@@ -14,8 +14,8 @@
|
||||
viewBox="0 0 129.64583 129.64583"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
sodipodi:docname="G9.svg"
|
||||
inkscape:version="0.92.2 (5c3e80d, 2017-08-06)"
|
||||
sodipodi:docname="logitech-g9.svg"
|
||||
inkscape:version="0.92.3 (2405546, 2018-03-11)"
|
||||
enable-background="new">
|
||||
<defs
|
||||
id="defs2">
|
||||
@@ -38,16 +38,16 @@
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1.4142136"
|
||||
inkscape:cx="108.9024"
|
||||
inkscape:cy="270.58583"
|
||||
inkscape:zoom="8.0000004"
|
||||
inkscape:cx="264.58829"
|
||||
inkscape:cy="370.72481"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="LEDs"
|
||||
inkscape:current-layer="Device"
|
||||
inkscape:document-rotation="0"
|
||||
showgrid="false"
|
||||
showguides="false"
|
||||
showguides="true"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1136"
|
||||
inkscape:window-height="1016"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="27"
|
||||
inkscape:window-maximized="1"
|
||||
@@ -55,8 +55,8 @@
|
||||
inkscape:guide-bbox="true"
|
||||
units="px"
|
||||
inkscape:snap-global="false"
|
||||
inkscape:measure-start="200.26,379.645"
|
||||
inkscape:measure-end="199.294,334.274">
|
||||
inkscape:measure-start="296.875,398.125"
|
||||
inkscape:measure-end="288.375,379.75">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid78" />
|
||||
@@ -71,12 +71,12 @@
|
||||
id="guide81"
|
||||
inkscape:locked="false" />
|
||||
<sodipodi:guide
|
||||
position="51.756014,88.614617"
|
||||
position="-0.18708866,88.492936"
|
||||
orientation="0,1"
|
||||
id="guide83"
|
||||
inkscape:locked="false" />
|
||||
<sodipodi:guide
|
||||
position="57.778386,76.729167"
|
||||
position="13.758333,76.993746"
|
||||
orientation="0,1"
|
||||
id="guide85"
|
||||
inkscape:locked="false" />
|
||||
@@ -156,13 +156,13 @@
|
||||
<path
|
||||
style="fill:#d9dad7;fill-opacity:1;stroke:#babdb6;stroke-width:0.61647916;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 34.611402,214.21326 -0.467722,5.00462 16.18317,-1.07576 0.04677,-4.77076 z"
|
||||
id="button3"
|
||||
id="button9"
|
||||
inkscape:connector-curvature="0"
|
||||
inkscape:label="#path896" />
|
||||
<path
|
||||
style="fill:#d9dad7;fill-opacity:1;stroke:#babdb6;stroke-width:0.61647916;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 64.405272,212.43591 -14.066729,0.93544 0.02888,4.76741 13.98589,-0.84138 z"
|
||||
id="button4"
|
||||
id="button8"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccc"
|
||||
inkscape:label="#path898" />
|
||||
@@ -184,14 +184,14 @@
|
||||
<path
|
||||
style="fill:#d9dad7;fill-opacity:1;stroke:#babdb6;stroke-width:0.61647916;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 24.274755,248.26339 c -0.124726,-9.60388 -0.342996,-10.78877 0.748354,-17.86696 0.576857,0.0935 1.153713,0.18709 1.73057,0.28063 -0.826308,5.86211 -1.652616,11.72422 -2.478924,17.58633 z"
|
||||
id="button6"
|
||||
id="button3"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccc"
|
||||
inkscape:label="#path4606" />
|
||||
<path
|
||||
style="fill:#d9dad7;fill-opacity:1;stroke:#babdb6;stroke-width:0.61647916;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 27.104469,228.7594 c -0.561265,-0.0779 -1.122531,-0.15591 -1.683796,-0.23386 0.919852,-4.78635 2.120338,-8.77758 3.671614,-12.95589 -0.662606,4.39658 -1.325212,8.79317 -1.987818,13.18975 z"
|
||||
id="button5"
|
||||
id="button4"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccc"
|
||||
inkscape:label="#path4608" />
|
||||
@@ -207,6 +207,20 @@
|
||||
id="button1"
|
||||
inkscape:connector-curvature="0"
|
||||
inkscape:label="#path4612" />
|
||||
<path
|
||||
transform="translate(0,164.70833)"
|
||||
id="button6"
|
||||
d="m 62.980849,30.452818 a 0.06589785,0.06589785 0 0 0 -0.046,0.02066 l -1.13998,1.23145 a 0.06589785,0.06589785 0 0 0 0.002,0.09147 l 1.13947,1.139465 a 0.06589785,0.06589785 0 0 0 0.10697,-0.07338 l -0.50385,-1.113628 0.50488,-1.205093 a 0.06589785,0.06589785 0 0 0 -0.0636,-0.09095 z"
|
||||
style="display:inline;color:#000000;overflow:visible;opacity:1;vector-effect:none;fill:#888a85;fill-opacity:1;stroke:none;stroke-width:0.25282338;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal"
|
||||
inkscape:connector-curvature="0"
|
||||
inkscape:label="#path1016" />
|
||||
<path
|
||||
transform="translate(0,164.70833)"
|
||||
id="button7"
|
||||
d="m 75.28463,30.433444 a 0.06589785,0.06589785 0 0 1 0.046,0.02066 l 1.13998,1.23145 a 0.06589785,0.06589785 0 0 1 -0.002,0.09147 l -1.13947,1.139465 a 0.06589785,0.06589785 0 0 1 -0.10697,-0.07338 l 0.50385,-1.113628 -0.50488,-1.205093 a 0.06589785,0.06589785 0 0 1 0.0636,-0.09095 z"
|
||||
style="display:inline;color:#000000;overflow:visible;opacity:1;vector-effect:none;fill:#888a85;fill-opacity:1;stroke:none;stroke-width:0.25282338;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal"
|
||||
inkscape:connector-curvature="0"
|
||||
inkscape:label="#path1016-3" />
|
||||
</g>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
@@ -215,26 +229,26 @@
|
||||
transform="translate(0,-2.6458338)"
|
||||
style="display:inline">
|
||||
<g
|
||||
transform="matrix(0.26458333,0,0,0.26458333,40.502648,-13.272558)"
|
||||
transform="matrix(0.26458333,0,0,0.26458333,40.502648,-1.1017221)"
|
||||
style="display:inline"
|
||||
id="button2-path"
|
||||
inkscape:label="#g146">
|
||||
<path
|
||||
style="color:#000000;overflow:visible;opacity:1;vector-effect:none;fill:none;fill-opacity:1;stroke:#888a85;stroke-width:0.99999994;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal"
|
||||
d="m 336.91912,170.14213 -225.57514,0.36405"
|
||||
d="M 336.91912,169.83277 147.21994,169.67013 109.21898,124.50618"
|
||||
id="path51"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
sodipodi:nodetypes="ccc" />
|
||||
<rect
|
||||
style="color:#000000;overflow:visible;opacity:1;vector-effect:none;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal"
|
||||
id="rect53"
|
||||
width="6.999999"
|
||||
height="6.999999"
|
||||
x="107.41756"
|
||||
y="166.91161" />
|
||||
x="106.00334"
|
||||
y="120.59612" />
|
||||
<rect
|
||||
y="169.75269"
|
||||
x="336.91913"
|
||||
y="169.31075"
|
||||
x="336.56558"
|
||||
height="1"
|
||||
width="1"
|
||||
id="button2-leader"
|
||||
@@ -244,7 +258,7 @@
|
||||
<g
|
||||
transform="matrix(-0.26458333,0,0,-0.26458333,116.08398,94.455601)"
|
||||
style="display:inline"
|
||||
id="button3-path"
|
||||
id="button9-path"
|
||||
inkscape:label="#g146">
|
||||
<path
|
||||
style="color:#000000;overflow:visible;opacity:1;vector-effect:none;fill:none;fill-opacity:1;stroke:#888a85;stroke-width:0.99999994;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal"
|
||||
@@ -264,7 +278,7 @@
|
||||
x="438.04599"
|
||||
height="1"
|
||||
width="1"
|
||||
id="button3-leader"
|
||||
id="button9-leader"
|
||||
style="color:#000000;text-align:end;overflow:visible;vector-effect:none;fill:#888a85;fill-opacity:1;stroke:none;stroke-linecap:round"
|
||||
inkscape:label="#rect871" />
|
||||
</g>
|
||||
@@ -323,13 +337,13 @@
|
||||
inkscape:label="#rect871" />
|
||||
</g>
|
||||
<g
|
||||
transform="matrix(0.26458333,0,0,-0.26458333,13.573867,94.421678)"
|
||||
transform="matrix(0.26458333,0,0,0.26458333,13.573867,4.9859563)"
|
||||
style="display:inline"
|
||||
id="button4-path"
|
||||
id="button8-path"
|
||||
inkscape:label="#g146">
|
||||
<path
|
||||
style="color:#000000;overflow:visible;opacity:1;vector-effect:none;fill:none;fill-opacity:1;stroke:#888a85;stroke-width:0.99999994;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal"
|
||||
d="M 438.04598,191.7488 H 193.48839 l -29.95691,-26.43012"
|
||||
d="m 438.04598,191.7488 -249.80759,-0.5 -23.58191,-19.43012"
|
||||
id="path51-1-9-6-8-4"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccc" />
|
||||
@@ -338,21 +352,21 @@
|
||||
id="rect53-2-3-2-7-4"
|
||||
width="6.999999"
|
||||
height="6.999999"
|
||||
x="160.13437"
|
||||
y="161.68198" />
|
||||
x="161.75937"
|
||||
y="169.05698" />
|
||||
<rect
|
||||
y="191.3428"
|
||||
x="438.04599"
|
||||
height="1"
|
||||
width="1"
|
||||
id="button4-leader"
|
||||
id="button8-leader"
|
||||
style="color:#000000;text-align:start;overflow:visible;vector-effect:none;fill:#888a85;fill-opacity:1;stroke:none;stroke-linecap:round"
|
||||
inkscape:label="#rect871" />
|
||||
</g>
|
||||
<g
|
||||
transform="matrix(-0.26458333,0,0,-0.26458333,116.07548,106.30868)"
|
||||
style="display:inline"
|
||||
id="button5-path"
|
||||
id="button4-path"
|
||||
inkscape:label="#g146">
|
||||
<path
|
||||
style="color:#000000;overflow:visible;opacity:1;vector-effect:none;fill:none;fill-opacity:1;stroke:#888a85;stroke-width:0.99999994;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal"
|
||||
@@ -372,14 +386,14 @@
|
||||
x="438.04599"
|
||||
height="1"
|
||||
width="1"
|
||||
id="button5-leader"
|
||||
id="button4-leader"
|
||||
style="color:#000000;text-align:end;overflow:visible;vector-effect:none;fill:#888a85;fill-opacity:1;stroke:none;stroke-linecap:round"
|
||||
inkscape:label="#rect871" />
|
||||
</g>
|
||||
<g
|
||||
transform="matrix(-0.26458333,0,0,-0.26458333,116.05287,118.29899)"
|
||||
style="display:inline"
|
||||
id="button6-path"
|
||||
id="button3-path"
|
||||
inkscape:label="#g146">
|
||||
<path
|
||||
style="color:#000000;overflow:visible;opacity:1;vector-effect:none;fill:none;fill-opacity:1;stroke:#888a85;stroke-width:0.99999994;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal"
|
||||
@@ -399,8 +413,62 @@
|
||||
x="438.04599"
|
||||
height="1"
|
||||
width="1"
|
||||
id="button3-leader"
|
||||
style="color:#000000;text-align:end;overflow:visible;vector-effect:none;fill:#888a85;fill-opacity:1;stroke:none;stroke-linecap:round"
|
||||
inkscape:label="#rect871" />
|
||||
</g>
|
||||
<g
|
||||
transform="matrix(-0.29294531,0,0,0.26458333,70.05035,-34.688457)"
|
||||
style="display:inline"
|
||||
id="button6-path"
|
||||
inkscape:label="#g156">
|
||||
<path
|
||||
sodipodi:nodetypes="cc"
|
||||
style="color:#000000;overflow:visible;opacity:1;vector-effect:none;fill:none;fill-opacity:1;stroke:#888a85;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal"
|
||||
d="m 33.59277,251.21287 205.11339,-0.0974"
|
||||
id="path966-9-6"
|
||||
inkscape:connector-curvature="0" />
|
||||
<rect
|
||||
style="color:#000000;overflow:visible;opacity:1;vector-effect:none;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal"
|
||||
id="rect976-8-7"
|
||||
width="6.999999"
|
||||
height="6.999999"
|
||||
x="29.446411"
|
||||
y="247.53609" />
|
||||
<rect
|
||||
y="250.62447"
|
||||
x="238.5843"
|
||||
height="1"
|
||||
width="1"
|
||||
id="button6-leader"
|
||||
style="color:#000000;text-align:end;overflow:visible;vector-effect:none;fill:#888a85;fill-opacity:1;stroke:none;stroke-linecap:round"
|
||||
inkscape:label="#rect875" />
|
||||
</g>
|
||||
<g
|
||||
transform="matrix(0.26458333,0,0,0.26458333,40.372307,-13.288752)"
|
||||
style="display:inline"
|
||||
id="button7-path"
|
||||
inkscape:label="#g146">
|
||||
<path
|
||||
style="color:#000000;overflow:visible;opacity:1;vector-effect:none;fill:none;fill-opacity:1;stroke:#888a85;stroke-width:0.99999994;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal"
|
||||
d="m 336.91912,170.14213 -196.70014,0.23905"
|
||||
id="path51-1-6"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<rect
|
||||
style="color:#000000;overflow:visible;opacity:1;vector-effect:none;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal"
|
||||
id="rect53-0-7"
|
||||
width="6.999999"
|
||||
height="6.999999"
|
||||
x="137.97041"
|
||||
y="166.84467" />
|
||||
<rect
|
||||
y="169.75269"
|
||||
x="336.91913"
|
||||
height="1"
|
||||
width="1"
|
||||
id="button7-leader"
|
||||
style="color:#000000;text-align:start;overflow:visible;vector-effect:none;fill:#888a85;fill-opacity:1;stroke:none;stroke-linecap:round"
|
||||
inkscape:label="#rect871" />
|
||||
</g>
|
||||
</g>
|
||||
@@ -411,13 +479,13 @@
|
||||
transform="translate(0,-2.6458338)"
|
||||
style="display:inline">
|
||||
<g
|
||||
transform="matrix(0.26458333,0,0,-0.26458333,13.686363,102.7808)"
|
||||
transform="matrix(0.26458333,0,0,0.26458333,13.592814,20.269951)"
|
||||
style="display:inline"
|
||||
id="led0-path"
|
||||
inkscape:label="#g146">
|
||||
<path
|
||||
style="color:#000000;overflow:visible;opacity:1;vector-effect:none;fill:none;fill-opacity:1;stroke:#888a85;stroke-width:0.99999994;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal"
|
||||
d="M 438.04598,178.25732 H 151.75439 l -10.41041,-7.75114"
|
||||
d="m 438.04598,178.25732 -267.54159,0.25 -31.41041,-32.75114"
|
||||
id="path51-1-9-6-0"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccc" />
|
||||
@@ -426,8 +494,8 @@
|
||||
id="rect53-2-3-2-2"
|
||||
width="6.999999"
|
||||
height="6.999999"
|
||||
x="137.02765"
|
||||
y="165.93933" />
|
||||
x="135.77765"
|
||||
y="141.93933" />
|
||||
<rect
|
||||
y="177.79317"
|
||||
x="438.04599"
|
||||
|
||||
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 26 KiB |
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 739 KiB After Width: | Height: | Size: 15 KiB |
497
data/gnome/steelseries-senseiraw.svg
Normal file
497
data/gnome/steelseries-senseiraw.svg
Normal file
@@ -0,0 +1,497 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="490"
|
||||
height="490"
|
||||
viewBox="0 0 129.64583 129.64583"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
sodipodi:docname="steelseries-senseiraw.svg"
|
||||
inkscape:version="0.92.3 (2405546, 2018-03-11)">
|
||||
<defs
|
||||
id="defs2" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1.4986862"
|
||||
inkscape:cx="234.07051"
|
||||
inkscape:cy="291.38143"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="Device"
|
||||
inkscape:document-rotation="0"
|
||||
showgrid="false"
|
||||
showguides="false"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1149"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
showborder="true"
|
||||
inkscape:guide-bbox="true"
|
||||
units="px"
|
||||
inkscape:snap-global="false"
|
||||
inkscape:measure-start="0,0"
|
||||
inkscape:measure-end="0,0">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid78" />
|
||||
<sodipodi:guide
|
||||
position="58.722772,112.40709"
|
||||
orientation="0,1"
|
||||
id="guide79"
|
||||
inkscape:locked="false" />
|
||||
<sodipodi:guide
|
||||
position="39.611923,100.54373"
|
||||
orientation="0,1"
|
||||
id="guide81"
|
||||
inkscape:locked="false" />
|
||||
<sodipodi:guide
|
||||
position="51.756014,88.614617"
|
||||
orientation="0,1"
|
||||
id="guide83"
|
||||
inkscape:locked="false" />
|
||||
<sodipodi:guide
|
||||
position="57.778386,76.729167"
|
||||
orientation="0,1"
|
||||
id="guide85"
|
||||
inkscape:locked="false" />
|
||||
<sodipodi:guide
|
||||
position="45.047078,64.795712"
|
||||
orientation="0,1"
|
||||
inkscape:locked="false"
|
||||
id="guide87" />
|
||||
<sodipodi:guide
|
||||
position="57.646696,52.899321"
|
||||
orientation="0,1"
|
||||
id="guide89"
|
||||
inkscape:locked="false" />
|
||||
<sodipodi:guide
|
||||
position="64.732676,142.09384"
|
||||
orientation="1,0"
|
||||
id="guide913"
|
||||
inkscape:locked="false" />
|
||||
<sodipodi:guide
|
||||
position="-45.462545,31.805073"
|
||||
orientation="0,1"
|
||||
inkscape:locked="false"
|
||||
id="guide944" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
inkscape:label="Image"
|
||||
style="display:none"
|
||||
sodipodi:insensitive="true" />
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="Device"
|
||||
inkscape:label="Device"
|
||||
style="display:inline;opacity:1"
|
||||
transform="translate(0,-167.35416)">
|
||||
<path
|
||||
style="display:inline;fill:#d3d3ce;fill-opacity:1;fill-rule:evenodd;stroke:#babdb6;stroke-width:0.98636663;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 61.118815,173.57187 c -6.81302,0.0662 -11.972394,1.52136 -16.073435,3.37344 -2.88728,1.31189 -4.888218,3.54982 -6.680729,5.62239 -2.215885,3.43407 -3.375386,5.63618 -3.970698,8.86355 -0.919394,7.49385 -0.194949,14.47321 -0.225672,22.62187 -0.0441,2.92144 0.321327,3.9908 0.09533,6.28385 -0.132292,4.05143 -0.413412,7.82174 -0.79375,11.90625 l -0.859895,11.9724 -1.190625,16.27187 c -0.0248,0.94258 -1e-6,1.65364 0.198437,2.57969 0.171855,0.8399 0.352238,1.03153 0.463021,1.52135 0.595312,2.4033 0.529166,3.99631 1.785937,7.2099 2.116666,4.23333 3.604948,6.84609 6.746875,10.71562 3.858506,4.06797 6.928936,5.67685 11.575518,7.34219 4.293136,1.39044 7.919768,1.65835 12.633854,1.78594 0,0 8.340581,-0.39932 12.633718,-1.78976 4.646582,-1.66534 7.717012,-3.27422 11.575518,-7.34219 3.141927,-3.86953 4.630209,-6.48229 6.746875,-10.71562 1.256771,-3.21359 1.190625,-4.8066 1.785937,-7.2099 0.110783,-0.48982 0.291166,-0.68145 0.463021,-1.52135 0.198438,-0.92605 0.223237,-1.63711 0.198437,-2.57969 l -1.190625,-16.27187 -0.717876,-8.98999 c -0.380338,-4.08451 -0.803477,-10.83723 -0.935769,-14.88866 -0.225999,-2.29305 -0.28663,-3.36241 -0.33073,-6.28385 -0.03072,-8.14866 0.835741,-15.12802 -0.08365,-22.62187 -0.595312,-3.22737 -1.470774,-5.42948 -3.686659,-8.86355 -1.792511,-2.07257 -3.793449,-4.3105 -6.680729,-5.62239 -4.101041,-1.85208 -9.260416,-3.30724 -16.073436,-3.37344 -3.028432,-0.0919 -5.294794,0.0499 -7.4082,0.004 z"
|
||||
id="path926"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccccccccccccccccccccccccccccc" />
|
||||
<path
|
||||
id="path5205"
|
||||
style="display:inline;opacity:1;vector-effect:none;fill:#eeeeec;fill-opacity:1;fill-rule:evenodd;stroke:#babdb6;stroke-width:0.98636663;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:markers fill stroke"
|
||||
d="m 68.894015,173.48626 c 0.01741,1.97468 0.845255,8.1474 1.684943,11.60161 1.369264,5.63272 0.266853,23.47034 0.266853,23.47034 0,0 -2.042025,17.37272 -6.022897,17.27166 -3.980871,0.16348 -6.022896,-17.20924 -6.022896,-17.20924 0,0 -1.10241,-17.83762 0.266854,-23.47034 0.839687,-3.45421 1.667532,-9.62693 1.684942,-11.60161 z"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cscccscc" />
|
||||
<path
|
||||
style="display:inline;opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;stroke:#babdb6;stroke-width:0.98636663;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
d="m 64.695108,222.94948 c -0.606916,-0.009 -3.440676,-6.06643 -3.513997,-9.56014 -0.02982,-1.42071 0.176696,-1.66675 3.591511,-1.70532 3.503766,-0.0396 3.702586,0.22584 3.694867,1.62781 -0.01799,3.26716 -3.27008,9.64508 -3.772381,9.63765 z"
|
||||
id="button7"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="sssss"
|
||||
mask="none"
|
||||
clip-path="none" />
|
||||
<path
|
||||
style="display:inline;opacity:1;vector-effect:none;fill:#eeeeec;fill-opacity:1;stroke:#babdb6;stroke-width:0.98636663;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
d="m 95.121771,209.18914 c 0,0 -0.197205,17.71196 -1.241986,33.44373 -0.483924,7.28668 -1.491683,12.97597 -2.130552,18.3934 -0.45519,3.85988 0.58105,6.73694 2.373267,7.24471 1.728139,0.48961 3.747262,-3.87217 3.747262,-3.87217"
|
||||
id="path4742"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="csssc" />
|
||||
<path
|
||||
sodipodi:nodetypes="csssc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4744"
|
||||
d="m 34.385075,208.66134 c 0,0 0.197205,17.71196 1.241986,33.44373 0.483924,7.28668 1.491683,12.97597 2.130552,18.3934 0.45519,3.85988 -0.58105,6.73694 -2.373267,7.24471 -1.728139,0.48961 -3.747262,-3.87217 -3.747262,-3.87217"
|
||||
style="display:inline;opacity:1;vector-effect:none;fill:#eeeeec;fill-opacity:1;stroke:#babdb6;stroke-width:0.98636663;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
|
||||
<path
|
||||
style="display:inline;opacity:1;vector-effect:none;fill:none;fill-opacity:1;stroke:#babdb6;stroke-width:0.98636663;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
d="m 33.794256,226.79927 0.594666,-18.07871"
|
||||
id="path58"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="display:inline;opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;stroke:#babdb6;stroke-width:0.98636663;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
d="m 35.720073,242.99898 c 0,0 -1.305894,-0.86732 -1.520495,-1.08633 -0.214601,-0.21901 -0.406023,-15.1316 -0.406023,-15.1316 l 1.116802,0.0102"
|
||||
id="path56"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="czcc" />
|
||||
<path
|
||||
style="display:inline;opacity:1;vector-effect:none;fill:none;fill-opacity:1;stroke:#babdb6;stroke-width:0.98636663;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
d="m 95.452345,226.07744 -0.362533,-16.8175"
|
||||
id="path54"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="display:inline;opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;stroke:#babdb6;stroke-width:0.98636663;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
d="m 93.827188,242.82115 c 0,0 1.385456,-0.49501 1.574101,-0.65851 0.188645,-0.16351 0.05639,-16.17317 0.05639,-16.17317 l -0.703725,-0.17593"
|
||||
id="path52"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="czcc" />
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="display:inline;opacity:1;fill:none;fill-opacity:0.39215686;stroke:#babdb6;stroke-width:3.62082291;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="led0"
|
||||
sodipodi:cx="64.822914"
|
||||
sodipodi:cy="280.68228"
|
||||
sodipodi:rx="6.5174346"
|
||||
sodipodi:ry="6.5174413"
|
||||
d="m 69.431436,276.07375 a 6.5174346,6.5174413 0 0 1 10e-7,9.21706 6.5174346,6.5174413 0 0 1 -9.217045,0 6.5174346,6.5174413 0 0 1 -10e-7,-9.21705"
|
||||
sodipodi:start="5.4977871"
|
||||
sodipodi:end="3.9269907"
|
||||
sodipodi:open="true"
|
||||
sodipodi:arc-type="arc"
|
||||
inkscape:label="#led1" />
|
||||
<path
|
||||
style="display:inline;opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;stroke:#babdb6;stroke-width:0.98636663;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal"
|
||||
d="m 62.181167,187.21067 -0.0053,13.99772 c 0.798868,1.60491 0.79411,1.60258 2.56045,1.60804 1.9255,-0.003 1.931661,-0.005 2.733645,-1.59929 l -0.0049,-14.01641 c -0.79057,-1.56574 -0.793119,-1.57885 -2.72281,-1.60756 -1.766557,0.0242 -1.762015,0.025 -2.561099,1.6175 z"
|
||||
id="button2"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccccccc" />
|
||||
<rect
|
||||
id="button0"
|
||||
width="18.360525"
|
||||
height="26.481527"
|
||||
x="37.983463"
|
||||
y="180.65782"
|
||||
style="display:inline;fill:none;stroke-width:0.26458332"
|
||||
inkscape:label="#button0" />
|
||||
<rect
|
||||
id="button1"
|
||||
width="19.0667"
|
||||
height="26.834612"
|
||||
x="72.056366"
|
||||
y="179.95164"
|
||||
style="display:inline;fill:none;stroke-width:0.26458332"
|
||||
inkscape:label="#button1" />
|
||||
<rect
|
||||
id="button4"
|
||||
width="3.8839571"
|
||||
height="16.242002"
|
||||
x="32.334072"
|
||||
y="209.96404"
|
||||
style="display:inline;fill:none;stroke-width:0.26458332"
|
||||
inkscape:label="#button4" />
|
||||
<rect
|
||||
id="button3"
|
||||
width="4.0605006"
|
||||
height="15.006199"
|
||||
x="32.334072"
|
||||
y="227.2653"
|
||||
style="display:inline;fill:none;stroke-width:0.26458332"
|
||||
inkscape:label="#button3" />
|
||||
<rect
|
||||
id="button5"
|
||||
width="3.177783"
|
||||
height="14.653111"
|
||||
x="93.594673"
|
||||
y="210.67021"
|
||||
style="display:inline;fill:none;stroke-width:0.26458332"
|
||||
inkscape:label="#button5" />
|
||||
<rect
|
||||
id="button6"
|
||||
width="3.3543267"
|
||||
height="15.712373"
|
||||
x="93.594673"
|
||||
y="226.91222"
|
||||
style="display:inline;fill:none;stroke-width:0.26458332"
|
||||
inkscape:label="#button6" />
|
||||
</g>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="Buttons"
|
||||
inkscape:label="Buttons"
|
||||
transform="translate(0,-2.6458338)"
|
||||
style="display:inline">
|
||||
<g
|
||||
transform="matrix(-0.29294531,0,0,0.26458333,70.223399,-40.717196)"
|
||||
style="display:inline"
|
||||
id="button0-path"
|
||||
inkscape:label="#button0-path">
|
||||
<path
|
||||
sodipodi:nodetypes="cc"
|
||||
style="color:#000000;overflow:visible;opacity:1;vector-effect:none;fill:none;fill-opacity:1;stroke:#888a85;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal"
|
||||
d="m 81.663449,250.50576 157.960771,0.0352"
|
||||
id="path966"
|
||||
inkscape:connector-curvature="0" />
|
||||
<rect
|
||||
style="color:#000000;overflow:visible;opacity:1;vector-effect:none;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal"
|
||||
id="rect976"
|
||||
width="6.999999"
|
||||
height="6.999999"
|
||||
x="79.083046"
|
||||
y="247.00577" />
|
||||
<rect
|
||||
y="250.00575"
|
||||
x="238.62422"
|
||||
height="1"
|
||||
width="1"
|
||||
id="button0-leader"
|
||||
style="color:#000000;text-align:end;overflow:visible;vector-effect:none;fill:#888a85;fill-opacity:1;stroke:none;stroke-linecap:round"
|
||||
inkscape:label="#button0-leader" />
|
||||
</g>
|
||||
<g
|
||||
transform="matrix(0.26458333,0,0,0.26458333,40.529257,-19.549003)"
|
||||
style="display:inline"
|
||||
id="button1-path"
|
||||
inkscape:label="#button1-path">
|
||||
<path
|
||||
style="color:#000000;overflow:visible;opacity:1;vector-effect:none;fill:none;fill-opacity:1;stroke:#888a85;stroke-width:0.99999994;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal"
|
||||
d="m 336.91912,170.14213 -183.57514,0.36405"
|
||||
id="path51"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<rect
|
||||
style="color:#000000;overflow:visible;opacity:1;vector-effect:none;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal"
|
||||
id="rect53"
|
||||
width="6.999999"
|
||||
height="6.999999"
|
||||
x="149"
|
||||
y="167" />
|
||||
<rect
|
||||
y="169.75269"
|
||||
x="336.91913"
|
||||
height="1"
|
||||
width="1"
|
||||
id="button1-leader"
|
||||
style="color:#000000;text-align:start;overflow:visible;vector-effect:none;fill:#888a85;fill-opacity:1;stroke:none;stroke-linecap:round"
|
||||
inkscape:label="#button1-leader" />
|
||||
</g>
|
||||
<g
|
||||
transform="matrix(-0.2847136,0,0,0.26458333,87.395313,-3.7692874)"
|
||||
style="display:inline;opacity:1"
|
||||
id="button2-path"
|
||||
inkscape:label="#button2-path">
|
||||
<path
|
||||
sodipodi:nodetypes="ccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path964-6"
|
||||
d="m 79.210952,122.6933 62.691188,68.76371 165.40155,1e-5"
|
||||
style="color:#000000;overflow:visible;opacity:1;vector-effect:none;fill:none;fill-opacity:1;stroke:#888a85;stroke-width:0.99999994;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal" />
|
||||
<rect
|
||||
inkscape:label="#button2-leader"
|
||||
style="color:#000000;text-align:end;overflow:visible;vector-effect:none;fill:#888a85;fill-opacity:1;stroke:none;stroke-linecap:round"
|
||||
id="button2-leader"
|
||||
width="1"
|
||||
height="1"
|
||||
x="306.40533"
|
||||
y="190.93378" />
|
||||
<rect
|
||||
y="117.94263"
|
||||
x="76.303352"
|
||||
height="6.999999"
|
||||
width="6.999999"
|
||||
id="rect974-5"
|
||||
style="color:#000000;overflow:visible;opacity:1;vector-effect:none;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal" />
|
||||
</g>
|
||||
<g
|
||||
transform="matrix(0.26458333,0,0,0.26458333,13.523106,5.8698781)"
|
||||
style="display:inline"
|
||||
id="button7-path"
|
||||
inkscape:label="#button7-path">
|
||||
<path
|
||||
style="color:#000000;overflow:visible;opacity:1;vector-effect:none;fill:none;fill-opacity:1;stroke:#888a85;stroke-width:0.99999994;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal"
|
||||
d="M 438.5178,161.34199 H 204.22621 l -10.41041,7.75114"
|
||||
id="path51-1-9-6-0"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccc" />
|
||||
<rect
|
||||
style="color:#000000;overflow:visible;opacity:1;vector-effect:none;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal"
|
||||
id="rect53-2-3-2-2"
|
||||
width="6.999999"
|
||||
height="6.999999"
|
||||
x="189"
|
||||
y="167" />
|
||||
<rect
|
||||
y="160.86166"
|
||||
x="437.87918"
|
||||
height="1"
|
||||
width="1"
|
||||
id="button7-leader"
|
||||
style="color:#000000;text-align:start;overflow:visible;vector-effect:none;fill:#888a85;fill-opacity:1;stroke:none;stroke-linecap:round"
|
||||
inkscape:label="#button7-leader" />
|
||||
</g>
|
||||
<g
|
||||
inkscape:label="#button3-path"
|
||||
id="button3-path"
|
||||
style="display:inline"
|
||||
transform="matrix(-0.29294531,0,0,0.26458333,58.364063,-10.132593)">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path64"
|
||||
d="m 81.659897,250.49954 118.042313,0.0476"
|
||||
style="color:#000000;overflow:visible;opacity:1;vector-effect:none;fill:none;fill-opacity:1;stroke:#888a85;stroke-width:1.00572562;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<rect
|
||||
y="247.00577"
|
||||
x="79.083046"
|
||||
height="6.999999"
|
||||
width="6.999999"
|
||||
id="rect66"
|
||||
style="color:#000000;overflow:visible;opacity:1;vector-effect:none;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal" />
|
||||
<rect
|
||||
inkscape:label="#button3-leader"
|
||||
style="color:#000000;text-align:end;overflow:visible;vector-effect:none;fill:#888a85;fill-opacity:1;stroke:none;stroke-linecap:round"
|
||||
id="button3-leader"
|
||||
width="1"
|
||||
height="1"
|
||||
x="199.22597"
|
||||
y="250.00575" />
|
||||
</g>
|
||||
<g
|
||||
transform="matrix(-0.29294531,0,0,0.26458333,58.488898,4.7227855)"
|
||||
style="display:inline"
|
||||
id="button4-path"
|
||||
inkscape:label="#button4-path">
|
||||
<path
|
||||
sodipodi:nodetypes="cc"
|
||||
style="color:#000000;overflow:visible;opacity:1;vector-effect:none;fill:none;fill-opacity:1;stroke:#888a85;stroke-width:1.00572562;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal"
|
||||
d="m 81.659897,250.49954 118.042313,0.0476"
|
||||
id="path72"
|
||||
inkscape:connector-curvature="0" />
|
||||
<rect
|
||||
style="color:#000000;overflow:visible;opacity:1;vector-effect:none;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal"
|
||||
id="rect74"
|
||||
width="6.999999"
|
||||
height="6.999999"
|
||||
x="79.083046"
|
||||
y="247.00577" />
|
||||
<rect
|
||||
y="250.00575"
|
||||
x="199.15065"
|
||||
height="1"
|
||||
width="1"
|
||||
id="button4-leader"
|
||||
style="color:#000000;text-align:end;overflow:visible;vector-effect:none;fill:#888a85;fill-opacity:1;stroke:none;stroke-linecap:round"
|
||||
inkscape:label="#button4-leader" />
|
||||
</g>
|
||||
<g
|
||||
transform="matrix(0.29294531,0,0,0.26458333,71.117413,-9.779506)"
|
||||
style="display:inline"
|
||||
id="button5-path"
|
||||
inkscape:label="#button5-path">
|
||||
<path
|
||||
sodipodi:nodetypes="cc"
|
||||
style="color:#000000;overflow:visible;opacity:1;vector-effect:none;fill:none;fill-opacity:1;stroke:#888a85;stroke-width:1.00572562;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal"
|
||||
d="m 81.659897,250.49954 118.042313,0.0476"
|
||||
id="path80"
|
||||
inkscape:connector-curvature="0" />
|
||||
<rect
|
||||
style="color:#000000;overflow:visible;opacity:1;vector-effect:none;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal"
|
||||
id="rect82"
|
||||
width="6.999999"
|
||||
height="6.999999"
|
||||
x="79.083046"
|
||||
y="247.00577" />
|
||||
<rect
|
||||
y="250.00575"
|
||||
x="199.22597"
|
||||
height="1"
|
||||
width="1"
|
||||
id="button5-leader"
|
||||
style="color:#000000;text-align:start;overflow:visible;vector-effect:none;fill:#888a85;fill-opacity:1;stroke:none;stroke-linecap:round"
|
||||
inkscape:label="#button5-leader" />
|
||||
</g>
|
||||
<g
|
||||
inkscape:label="#button6-path"
|
||||
id="button6-path"
|
||||
style="display:inline"
|
||||
transform="matrix(0.29294531,0,0,0.26458333,70.992573,5.0758725)">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path88"
|
||||
d="m 81.659897,250.49954 118.042313,0.0476"
|
||||
style="color:#000000;overflow:visible;opacity:1;vector-effect:none;fill:none;fill-opacity:1;stroke:#888a85;stroke-width:1.00572562;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<rect
|
||||
y="247.00577"
|
||||
x="79.083046"
|
||||
height="6.999999"
|
||||
width="6.999999"
|
||||
id="rect90"
|
||||
style="color:#000000;overflow:visible;opacity:1;vector-effect:none;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal" />
|
||||
<rect
|
||||
inkscape:label="#button6-leader"
|
||||
style="color:#000000;text-align:start;overflow:visible;vector-effect:none;fill:#888a85;fill-opacity:1;stroke:none;stroke-linecap:round"
|
||||
id="button6-leader"
|
||||
width="1"
|
||||
height="1"
|
||||
x="199.15065"
|
||||
y="250.00575" />
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="LEDs"
|
||||
inkscape:label="LEDs"
|
||||
transform="translate(0,-2.6458338)"
|
||||
style="display:inline">
|
||||
<g
|
||||
transform="matrix(-0.29294531,0,0,0.26458333,70.145744,50.590488)"
|
||||
style="display:inline"
|
||||
id="led0-path"
|
||||
inkscape:label="#led0-path">
|
||||
<path
|
||||
sodipodi:nodetypes="cc"
|
||||
style="color:#000000;overflow:visible;opacity:1;vector-effect:none;fill:none;fill-opacity:1;stroke:#888a85;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal"
|
||||
d="m 19.28901,250.49471 219.01243,0.008"
|
||||
id="path966-0-2"
|
||||
inkscape:connector-curvature="0" />
|
||||
<rect
|
||||
style="color:#000000;overflow:visible;opacity:1;vector-effect:none;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal"
|
||||
id="rect976-2-1"
|
||||
width="6.999999"
|
||||
height="6.999999"
|
||||
x="16.834169"
|
||||
y="246.63705" />
|
||||
<rect
|
||||
y="249.97328"
|
||||
x="237.7849"
|
||||
height="1"
|
||||
width="1"
|
||||
id="led0-leader"
|
||||
style="color:#000000;text-align:end;overflow:visible;vector-effect:none;fill:#888a85;fill-opacity:1;stroke:none;stroke-linecap:round"
|
||||
inkscape:label="#rect875" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 25 KiB |
13
doc/dbus.rst
13
doc/dbus.rst
@@ -129,6 +129,19 @@ org.freedesktop.ratbag1.Device
|
||||
This is the case if the device has SVGs available but not
|
||||
for the given theme.
|
||||
|
||||
.. js:function:: GetSvgFd(s) → (h)
|
||||
|
||||
:param s: the theme name
|
||||
:returns: An open file descriptor to the SVG for the given theme
|
||||
|
||||
Returns an open file descriptor to the SVG for the given theme or an
|
||||
errno on error. The theme must be one of :js:attr:`Themes`.
|
||||
|
||||
The theme **'default'** is guaranteed to be available.
|
||||
ratbagd may return ENOENT if a file doesn't exist.
|
||||
This is the case if the device has SVGs available but not
|
||||
for the given theme.
|
||||
|
||||
.. js:function:: Resync()
|
||||
|
||||
:type: Signal
|
||||
|
||||
86
meson.build
86
meson.build
@@ -1,8 +1,8 @@
|
||||
project('libratbag', 'c', 'cpp',
|
||||
version : '0.9.902',
|
||||
version : '0.9.903',
|
||||
license : 'MIT/Expat',
|
||||
default_options : [ 'c_std=gnu99', 'warning_level=2' ],
|
||||
meson_version : '>= 0.38.0')
|
||||
meson_version : '>= 0.40.0')
|
||||
|
||||
libratbag_version = meson.project_version().split('.')
|
||||
|
||||
@@ -38,6 +38,7 @@ add_project_arguments(cppflags, language: 'cpp')
|
||||
# is generated at the end of this file
|
||||
config_h = configuration_data()
|
||||
config_h.set('_GNU_SOURCE', '1')
|
||||
config_h.set_quoted('RATBAG_VERSION', meson.project_version())
|
||||
config_h.set_quoted('FALLBACK_SVG_NAME', 'fallback.svg')
|
||||
libratbag_data_dir = join_paths(get_option('prefix'),
|
||||
get_option('datadir'),
|
||||
@@ -49,11 +50,20 @@ config_h.set_quoted('LIBRATBAG_DATA_DIR', libratbag_data_dir)
|
||||
pkgconfig = import('pkgconfig')
|
||||
dep_udev = dependency('libudev')
|
||||
dep_libevdev = dependency('libevdev')
|
||||
dep_libsystemd = dependency('libsystemd', version : '>=227')
|
||||
dep_systemd = dependency('systemd')
|
||||
dep_glib = dependency('glib-2.0')
|
||||
dep_lm = cc.find_library('m')
|
||||
|
||||
if get_option('logind-provider') == 'elogind'
|
||||
logind_dep = dependency('libelogind', version : '>=227')
|
||||
else
|
||||
logind_dep = dependency('libsystemd', version : '>=227')
|
||||
endif
|
||||
|
||||
enable_systemd = get_option('systemd')
|
||||
if enable_systemd
|
||||
dep_systemd = dependency('systemd')
|
||||
endif
|
||||
|
||||
#### libutil.a ####
|
||||
src_libutil = [
|
||||
'src/libratbag-util.c',
|
||||
@@ -131,6 +141,7 @@ src_libratbag = [
|
||||
'src/driver-hidpp20.c',
|
||||
'src/driver-hidpp10.c',
|
||||
'src/driver-logitech-g300.c',
|
||||
'src/driver-logitech-g600.c',
|
||||
'src/driver-roccat.c',
|
||||
'src/driver-gskill.c',
|
||||
'src/driver-steelseries.c',
|
||||
@@ -155,15 +166,6 @@ deps_libratbag = [
|
||||
dep_libhidpp,
|
||||
]
|
||||
|
||||
libratbag_version_h_config = configuration_data()
|
||||
libratbag_version_h_config.set_quoted('LIBRATBAG_VERSION', meson.project_version())
|
||||
|
||||
libratbag_version_h = configure_file(
|
||||
output : 'libratbag-version.h',
|
||||
configuration : libratbag_version_h_config,
|
||||
install: false,
|
||||
)
|
||||
|
||||
lib_libratbag = static_library('ratbag',
|
||||
src_libratbag,
|
||||
include_directories : include_directories('.'),
|
||||
@@ -244,6 +246,7 @@ man_lur_command = configure_file (
|
||||
data_files = files(
|
||||
'data/devices/etekcity-scroll-alpha.device',
|
||||
'data/devices/gskill-MX-780.device',
|
||||
'data/devices/logitech-g102-g203.device',
|
||||
'data/devices/logitech-g300.device',
|
||||
'data/devices/logitech-g303.device',
|
||||
'data/devices/logitech-g403.device',
|
||||
@@ -253,6 +256,7 @@ data_files = files(
|
||||
'data/devices/logitech-g502-Proteus-Spectrum-over-USB.device',
|
||||
'data/devices/logitech-g5-2007.device',
|
||||
'data/devices/logitech-g5.device',
|
||||
'data/devices/logitech-g600.device',
|
||||
'data/devices/logitech-g602.device',
|
||||
'data/devices/logitech-g700.device',
|
||||
'data/devices/logitech-g700s.device',
|
||||
@@ -275,6 +279,7 @@ data_files = files(
|
||||
'data/devices/steelseries-kinzu-v2.device',
|
||||
'data/devices/steelseries-rival-310.device',
|
||||
'data/devices/steelseries-sensei-310.device',
|
||||
'data/devices/steelseries-sensei-raw.device',
|
||||
)
|
||||
|
||||
install_data(data_files,
|
||||
@@ -289,12 +294,14 @@ test('data-parse-test', data_parse_test,
|
||||
|
||||
gnome_svg_files = files(
|
||||
'data/gnome/fallback.svg',
|
||||
'data/gnome/logitech-g102-g203.svg',
|
||||
'data/gnome/logitech-g300.svg',
|
||||
'data/gnome/logitech-g303.svg',
|
||||
'data/gnome/logitech-g403.svg',
|
||||
'data/gnome/logitech-g500.svg',
|
||||
'data/gnome/logitech-g500s.svg',
|
||||
'data/gnome/logitech-g502.svg',
|
||||
'data/gnome/logitech-g600.svg',
|
||||
'data/gnome/logitech-g700.svg',
|
||||
'data/gnome/logitech-g703.svg',
|
||||
'data/gnome/logitech-g9.svg',
|
||||
@@ -303,6 +310,7 @@ gnome_svg_files = files(
|
||||
'data/gnome/steelseries-kinzu-v2.svg',
|
||||
'data/gnome/steelseries-rival310.svg',
|
||||
'data/gnome/steelseries-sensei310.svg',
|
||||
'data/gnome/steelseries-senseiraw.svg',
|
||||
)
|
||||
install_data(gnome_svg_files,
|
||||
install_dir : join_paths(get_option('datadir'), 'libratbag', 'gnome'))
|
||||
@@ -311,7 +319,7 @@ test_svg_files = find_program('data/gnome/check-svg.py')
|
||||
test('check-svg', test_svg_files, args : gnome_svg_files)
|
||||
|
||||
#### tests ####
|
||||
enable_tests = get_option('enable-tests')
|
||||
enable_tests = get_option('tests')
|
||||
if enable_tests
|
||||
dep_check = dependency('check', version: '>= 0.9.10')
|
||||
|
||||
@@ -399,7 +407,7 @@ src_ratbagd = [
|
||||
|
||||
deps_ratbagd = [
|
||||
dep_udev,
|
||||
dep_libsystemd,
|
||||
logind_dep,
|
||||
dep_libratbag,
|
||||
]
|
||||
|
||||
@@ -430,35 +438,39 @@ configure_file(input : 'dbus/org.freedesktop.ratbag_devel1.conf.in',
|
||||
configuration : config_ratbagd_devel)
|
||||
|
||||
#### unit file ####
|
||||
unitdir = get_option('systemd-unit-dir')
|
||||
if unitdir == ''
|
||||
libdir = get_option('libdir')
|
||||
default_unitdir = dep_systemd.get_pkgconfig_variable('systemdsystemunitdir')
|
||||
# Fedora uses lib64 but systemd is in lib. Hack around this so it
|
||||
# works out of the box.
|
||||
intended_unitdir = join_paths(get_option('prefix'), get_option('libdir'), 'systemd')
|
||||
if get_option('prefix') == '/usr' and intended_unitdir != default_unitdir
|
||||
message('''
|
||||
systemd unitdir libdir mismatch detected, changing unitdir to
|
||||
@0@
|
||||
or specify with
|
||||
mesonconf -Dsystemd-unit-dir=<path>
|
||||
if enable_systemd
|
||||
unitdir = get_option('systemd-unit-dir')
|
||||
if unitdir == ''
|
||||
libdir = get_option('libdir')
|
||||
default_unitdir = dep_systemd.get_pkgconfig_variable('systemdsystemunitdir')
|
||||
# Fedora uses lib64 but systemd is in lib. Hack around this so it
|
||||
# works out of the box.
|
||||
intended_unitdir = join_paths(get_option('prefix'), get_option('libdir'), 'systemd')
|
||||
if get_option('prefix') == '/usr' and intended_unitdir != default_unitdir
|
||||
message('''
|
||||
systemd unitdir libdir mismatch detected, changing unitdir to
|
||||
@0@
|
||||
or specify with
|
||||
mesonconf -Dsystemd-unit-dir=<path>
|
||||
|
||||
See https://github.com/libratbag/libratbag/issues/188
|
||||
'''.format(default_unitdir))
|
||||
unitdir = default_unitdir
|
||||
else
|
||||
unitdir = intended_unitdir
|
||||
See https://github.com/libratbag/libratbag/issues/188
|
||||
'''.format(default_unitdir))
|
||||
unitdir = default_unitdir
|
||||
else
|
||||
unitdir = intended_unitdir
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
config_bindir = configuration_data()
|
||||
config_bindir.set('bindir', join_paths(get_option('prefix'), get_option('bindir')))
|
||||
|
||||
configure_file(input : 'ratbagd/ratbagd.service.in',
|
||||
output : 'ratbagd.service',
|
||||
configuration : config_bindir,
|
||||
install_dir : unitdir)
|
||||
if enable_systemd
|
||||
configure_file(input : 'ratbagd/ratbagd.service.in',
|
||||
output : 'ratbagd.service',
|
||||
configuration : config_bindir,
|
||||
install_dir : unitdir)
|
||||
endif
|
||||
|
||||
dbusdir = get_option('dbus-root-dir')
|
||||
if dbusdir == ''
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
option('udev-dir',
|
||||
type: 'string',
|
||||
value: '',
|
||||
description: 'udev base directory [default=$prefix/lib/udev]')
|
||||
type: 'string',
|
||||
value: '',
|
||||
description: 'udev base directory [default=$prefix/lib/udev]')
|
||||
|
||||
option('enable-tests',
|
||||
option('tests',
|
||||
type: 'boolean',
|
||||
value: true,
|
||||
description: 'Build the tests (default=yes)')
|
||||
@@ -27,3 +27,16 @@ option('dbus-group',
|
||||
type: 'string',
|
||||
value : '',
|
||||
description : 'The UNIX group that is granted access to the ratbagd D-Bus service. By default all users may access it.')
|
||||
|
||||
option('systemd',
|
||||
type : 'boolean',
|
||||
value : true,
|
||||
description : 'Build systemd unit files'
|
||||
)
|
||||
|
||||
option('logind-provider',
|
||||
type : 'combo',
|
||||
choices: [ 'elogind', 'systemd'],
|
||||
value : 'systemd',
|
||||
description : 'Which logind provider to use'
|
||||
)
|
||||
|
||||
@@ -58,6 +58,8 @@ static int ratbagd_button_get_type(sd_bus *bus,
|
||||
|
||||
t = ratbag_button_get_type(button->lib_button);
|
||||
|
||||
verify_unsigned_int(t);
|
||||
|
||||
return sd_bus_message_append(reply, "u", t);
|
||||
}
|
||||
|
||||
@@ -74,6 +76,8 @@ static int ratbagd_button_get_button(sd_bus *bus,
|
||||
|
||||
b = ratbag_button_get_button(button->lib_button);
|
||||
|
||||
verify_unsigned_int(b);
|
||||
|
||||
return sd_bus_message_append(reply, "u", b);
|
||||
}
|
||||
|
||||
@@ -128,8 +132,14 @@ static int ratbagd_button_get_special(sd_bus *bus,
|
||||
enum ratbag_button_action_special special;
|
||||
|
||||
special = ratbag_button_get_special(button->lib_button);
|
||||
if (special == RATBAG_BUTTON_ACTION_SPECIAL_INVALID)
|
||||
special = RATBAG_BUTTON_ACTION_SPECIAL_UNKNOWN;
|
||||
|
||||
return sd_bus_message_append(reply, "u", special);
|
||||
verify_unsigned_int(special);
|
||||
|
||||
CHECK_CALL(sd_bus_message_append(reply, "u", special));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ratbagd_button_set_special(sd_bus *bus,
|
||||
@@ -144,9 +154,7 @@ static int ratbagd_button_set_special(sd_bus *bus,
|
||||
enum ratbag_button_action_special special;
|
||||
int r;
|
||||
|
||||
r = sd_bus_message_read(m, "u", &special);
|
||||
if (r < 0)
|
||||
return r;
|
||||
CHECK_CALL(sd_bus_message_read(m, "u", &special));
|
||||
|
||||
r = ratbag_button_set_special(button->lib_button, special);
|
||||
|
||||
@@ -180,12 +188,9 @@ static int ratbagd_button_get_macro(sd_bus *bus,
|
||||
{
|
||||
struct ratbagd_button *button = userdata;
|
||||
_cleanup_(ratbag_button_macro_unrefp) struct ratbag_button_macro *macro = NULL;
|
||||
int r;
|
||||
unsigned int idx;
|
||||
|
||||
r = sd_bus_message_open_container(reply, 'a', "(uu)");
|
||||
if (r < 0)
|
||||
return r;
|
||||
CHECK_CALL(sd_bus_message_open_container(reply, 'a', "(uu)"));
|
||||
|
||||
macro = ratbag_button_get_macro(button->lib_button);
|
||||
if (!macro)
|
||||
@@ -213,13 +218,16 @@ static int ratbagd_button_get_macro(sd_bus *bus,
|
||||
abort();
|
||||
}
|
||||
|
||||
r = sd_bus_message_append(reply, "(uu)", type, value);
|
||||
if (r < 0)
|
||||
return r;
|
||||
verify_unsigned_int(type);
|
||||
verify_unsigned_int(value);
|
||||
|
||||
CHECK_CALL(sd_bus_message_append(reply, "(uu)", type, value));
|
||||
}
|
||||
|
||||
out:
|
||||
return sd_bus_message_close_container(reply);
|
||||
CHECK_CALL(sd_bus_message_close_container(reply));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ratbagd_button_set_macro(sd_bus *bus,
|
||||
@@ -235,9 +243,7 @@ static int ratbagd_button_set_macro(sd_bus *bus,
|
||||
int r, idx = 0;
|
||||
_cleanup_(ratbag_button_macro_unrefp) struct ratbag_button_macro *macro = NULL;
|
||||
|
||||
r = sd_bus_message_enter_container(m, 'a', "(uu)");
|
||||
if (r < 0)
|
||||
return r;
|
||||
CHECK_CALL(sd_bus_message_enter_container(m, 'a', "(uu)"));
|
||||
|
||||
macro = ratbag_button_macro_new("macro");
|
||||
while ((r = sd_bus_message_read(m, "(uu)", &type, &value)) > 0) {
|
||||
@@ -251,9 +257,7 @@ static int ratbagd_button_set_macro(sd_bus *bus,
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_message_exit_container(m);
|
||||
if (r < 0)
|
||||
return r;
|
||||
CHECK_CALL(sd_bus_message_exit_container(m));
|
||||
|
||||
r = ratbag_button_set_macro(button->lib_button, macro);
|
||||
if (r < 0) {
|
||||
@@ -295,7 +299,11 @@ static int ratbagd_button_get_action_type(sd_bus *bus,
|
||||
if (type == RATBAG_BUTTON_ACTION_TYPE_KEY)
|
||||
type = RATBAG_BUTTON_ACTION_TYPE_UNKNOWN;
|
||||
|
||||
return sd_bus_message_append(reply, "u", type);
|
||||
verify_unsigned_int(type);
|
||||
|
||||
CHECK_CALL(sd_bus_message_append(reply, "u", type));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ratbagd_button_get_action_types(sd_bus *bus,
|
||||
@@ -307,7 +315,6 @@ static int ratbagd_button_get_action_types(sd_bus *bus,
|
||||
sd_bus_error *error)
|
||||
{
|
||||
struct ratbagd_button *button = userdata;
|
||||
int r;
|
||||
enum ratbag_button_action_type types[] = {
|
||||
RATBAG_BUTTON_ACTION_TYPE_BUTTON,
|
||||
RATBAG_BUTTON_ACTION_TYPE_SPECIAL,
|
||||
@@ -316,20 +323,19 @@ static int ratbagd_button_get_action_types(sd_bus *bus,
|
||||
enum ratbag_button_action_type *t;
|
||||
|
||||
|
||||
r = sd_bus_message_open_container(reply, 'a', "u");
|
||||
if (r < 0)
|
||||
return r;
|
||||
CHECK_CALL(sd_bus_message_open_container(reply, 'a', "u"));
|
||||
|
||||
ARRAY_FOR_EACH(types, t) {
|
||||
if (!ratbag_button_has_action_type(button->lib_button, *t))
|
||||
continue;
|
||||
|
||||
r = sd_bus_message_append(reply, "u", *t);
|
||||
if (r < 0)
|
||||
return r;
|
||||
verify_unsigned_int(*t);
|
||||
CHECK_CALL(sd_bus_message_append(reply, "u", *t));
|
||||
}
|
||||
|
||||
return sd_bus_message_close_container(reply);
|
||||
CHECK_CALL(sd_bus_message_close_container(reply));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ratbagd_button_disable(sd_bus_message *m,
|
||||
@@ -339,9 +345,7 @@ static int ratbagd_button_disable(sd_bus_message *m,
|
||||
struct ratbagd_button *button = userdata;
|
||||
int r;
|
||||
|
||||
r = sd_bus_message_read(m, "");
|
||||
if (r < 0)
|
||||
return r;
|
||||
CHECK_CALL(sd_bus_message_read(m, ""));
|
||||
|
||||
r = ratbag_button_disable(button->lib_button);
|
||||
if (r < 0) {
|
||||
@@ -351,7 +355,9 @@ static int ratbagd_button_disable(sd_bus_message *m,
|
||||
return r;
|
||||
}
|
||||
|
||||
return sd_bus_reply_method_return(m, "u", 0);
|
||||
CHECK_CALL(sd_bus_reply_method_return(m, "u", 0));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const sd_bus_vtable ratbagd_button_vtable[] = {
|
||||
|
||||
@@ -130,7 +130,9 @@ static int ratbagd_device_get_device_name(sd_bus *bus,
|
||||
name = "";
|
||||
}
|
||||
|
||||
return sd_bus_message_append(reply, "s", name);
|
||||
CHECK_CALL(sd_bus_message_append(reply, "s", name));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ratbagd_device_get_svg(sd_bus *bus,
|
||||
@@ -151,7 +153,9 @@ static int ratbagd_device_get_svg(sd_bus *bus,
|
||||
svg = "";
|
||||
}
|
||||
|
||||
return sd_bus_message_append(reply, "s", svg);
|
||||
CHECK_CALL(sd_bus_message_append(reply, "s", svg));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ratbagd_device_get_theme_svg(sd_bus_message *m,
|
||||
@@ -162,17 +166,13 @@ static int ratbagd_device_get_theme_svg(sd_bus_message *m,
|
||||
char svg_path[PATH_MAX] = {0};
|
||||
const char *theme;
|
||||
const char *svg;
|
||||
int r;
|
||||
const char *datadir;
|
||||
|
||||
datadir = getenv("LIBRATBAG_DATA_DIR");
|
||||
if (!datadir)
|
||||
datadir = LIBRATBAG_DATA_DIR;
|
||||
|
||||
r = sd_bus_message_read(m, "s", &theme);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
CHECK_CALL(sd_bus_message_read(m, "s", &theme));
|
||||
|
||||
svg = ratbag_device_get_svg_name(device->lib_device);
|
||||
if (!svg) {
|
||||
@@ -183,7 +183,48 @@ static int ratbagd_device_get_theme_svg(sd_bus_message *m,
|
||||
|
||||
snprintf(svg_path, sizeof(svg_path), "%s/%s/%s", datadir, theme, svg);
|
||||
|
||||
return sd_bus_reply_method_return(m, "s", svg_path);
|
||||
CHECK_CALL(sd_bus_reply_method_return(m, "s", svg_path));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ratbagd_device_get_theme_svg_fd(sd_bus_message *m,
|
||||
void *userdata,
|
||||
sd_bus_error *error)
|
||||
{
|
||||
struct ratbagd_device *device = userdata;
|
||||
char svg_path[PATH_MAX] = {0};
|
||||
const char *theme;
|
||||
const char *svg;
|
||||
const char *datadir;
|
||||
_cleanup_close_ int fd = -1;
|
||||
|
||||
datadir = getenv("LIBRATBAG_DATA_DIR");
|
||||
if (!datadir)
|
||||
datadir = LIBRATBAG_DATA_DIR;
|
||||
|
||||
CHECK_CALL(sd_bus_message_read(m, "s", &theme));
|
||||
|
||||
svg = ratbag_device_get_svg_name(device->lib_device);
|
||||
if (!svg) {
|
||||
log_error("%s: failed to fetch SVG, using fallback\n",
|
||||
ratbagd_device_get_sysname(device));
|
||||
svg = FALLBACK_SVG_NAME;
|
||||
}
|
||||
|
||||
snprintf(svg_path, sizeof(svg_path), "%s/%s/%s", datadir, theme, svg);
|
||||
|
||||
fd = open(svg_path, O_RDONLY);
|
||||
if (fd == -1) {
|
||||
log_error("%s: failed to open SVG '%s' (%m)\n",
|
||||
ratbagd_device_get_sysname(device),
|
||||
svg_path);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
CHECK_CALL(sd_bus_reply_method_return(m, "h", fd));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ratbagd_device_get_profiles(sd_bus *bus,
|
||||
@@ -197,25 +238,22 @@ static int ratbagd_device_get_profiles(sd_bus *bus,
|
||||
struct ratbagd_device *device = userdata;
|
||||
struct ratbagd_profile *profile;
|
||||
unsigned int i;
|
||||
int r;
|
||||
|
||||
r = sd_bus_message_open_container(reply, 'a', "o");
|
||||
if (r < 0)
|
||||
return r;
|
||||
CHECK_CALL(sd_bus_message_open_container(reply, 'a', "o"));
|
||||
|
||||
for (i = 0; i < device->n_profiles; ++i) {
|
||||
profile = device->profiles[i];
|
||||
if (!profile)
|
||||
continue;
|
||||
|
||||
r = sd_bus_message_append(reply,
|
||||
"o",
|
||||
ratbagd_profile_get_path(profile));
|
||||
if (r < 0)
|
||||
return r;
|
||||
CHECK_CALL(sd_bus_message_append(reply,
|
||||
"o",
|
||||
ratbagd_profile_get_path(profile)));
|
||||
}
|
||||
|
||||
return sd_bus_message_close_container(reply);
|
||||
CHECK_CALL(sd_bus_message_close_container(reply));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ratbagd_device_commit(sd_bus_message *m,
|
||||
@@ -233,7 +271,9 @@ static int ratbagd_device_commit(sd_bus_message *m,
|
||||
return r;
|
||||
}
|
||||
|
||||
return sd_bus_reply_method_return(m, "u", 0);
|
||||
CHECK_CALL(sd_bus_reply_method_return(m, "u", 0));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -261,23 +301,20 @@ ratbagd_device_get_capabilities(sd_bus *bus,
|
||||
RATBAG_DEVICE_CAP_BUTTON_MACROS,
|
||||
RATBAG_DEVICE_CAP_LED,
|
||||
};
|
||||
int r;
|
||||
size_t i;
|
||||
|
||||
r = sd_bus_message_open_container(reply, 'a', "u");
|
||||
if (r < 0)
|
||||
return r;
|
||||
CHECK_CALL(sd_bus_message_open_container(reply, 'a', "u"));
|
||||
|
||||
for (i = 0; i < ELEMENTSOF(caps); i++) {
|
||||
cap = caps[i];
|
||||
if (ratbag_device_has_capability(lib_device, cap)) {
|
||||
r = sd_bus_message_append(reply, "u", cap);
|
||||
if (r < 0)
|
||||
return r;
|
||||
CHECK_CALL(sd_bus_message_append(reply, "u", cap));
|
||||
}
|
||||
}
|
||||
|
||||
return sd_bus_message_close_container(reply);
|
||||
CHECK_CALL(sd_bus_message_close_container(reply));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const sd_bus_vtable ratbagd_device_vtable[] = {
|
||||
@@ -288,6 +325,7 @@ const sd_bus_vtable ratbagd_device_vtable[] = {
|
||||
SD_BUS_PROPERTY("Svg", "s", ratbagd_device_get_svg, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("Profiles", "ao", ratbagd_device_get_profiles, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_METHOD("GetSvg", "s", "s", ratbagd_device_get_theme_svg, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("GetSvgFd", "s", "h", ratbagd_device_get_theme_svg_fd, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("Commit", "", "u", ratbagd_device_commit, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_SIGNAL("Resync", "", 0),
|
||||
SD_BUS_VTABLE_END,
|
||||
@@ -324,10 +362,10 @@ int ratbagd_device_new(struct ratbagd_device **out,
|
||||
device->n_profiles = ratbag_device_get_num_profiles(device->lib_device);
|
||||
device->profiles = zalloc(device->n_profiles * sizeof(*device->profiles));
|
||||
|
||||
log_verbose("%s: \"%s\", %d profiles\n",
|
||||
sysname,
|
||||
ratbag_device_get_name(lib_device),
|
||||
device->n_profiles);
|
||||
log_info("%s: \"%s\", %d profiles\n",
|
||||
sysname,
|
||||
ratbag_device_get_name(lib_device),
|
||||
device->n_profiles);
|
||||
|
||||
for (i = 0; i < device->n_profiles; ++i) {
|
||||
profile = ratbag_device_get_profile(device->lib_device, i);
|
||||
|
||||
@@ -50,20 +50,19 @@ static int ratbagd_led_get_modes(sd_bus *bus,
|
||||
{
|
||||
struct ratbagd_led *led = userdata;
|
||||
enum ratbag_led_mode mode = 0;
|
||||
int r;
|
||||
|
||||
r = sd_bus_message_open_container(reply, 'a', "u");
|
||||
if (r < 0)
|
||||
return r;
|
||||
CHECK_CALL(sd_bus_message_open_container(reply, 'a', "u"));
|
||||
|
||||
|
||||
while (mode <= RATBAG_LED_BREATHING) {
|
||||
if (ratbag_led_has_mode(led->lib_led, mode))
|
||||
sd_bus_message_append(reply, "u", mode);
|
||||
CHECK_CALL(sd_bus_message_append(reply, "u", mode));
|
||||
mode++;
|
||||
}
|
||||
|
||||
return sd_bus_message_close_container(reply);
|
||||
CHECK_CALL(sd_bus_message_close_container(reply));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ratbagd_led_get_mode(sd_bus *bus,
|
||||
@@ -78,7 +77,12 @@ static int ratbagd_led_get_mode(sd_bus *bus,
|
||||
enum ratbag_led_mode mode;
|
||||
|
||||
mode = ratbag_led_get_mode(led->lib_led);
|
||||
return sd_bus_message_append(reply, "u", mode);
|
||||
|
||||
verify_unsigned_int(mode);
|
||||
|
||||
CHECK_CALL(sd_bus_message_append(reply, "u", mode));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ratbagd_led_set_mode(sd_bus *bus,
|
||||
@@ -93,9 +97,7 @@ static int ratbagd_led_set_mode(sd_bus *bus,
|
||||
enum ratbag_led_mode mode;
|
||||
int r;
|
||||
|
||||
r = sd_bus_message_read(m, "u", &mode);
|
||||
if (r < 0)
|
||||
return r;
|
||||
CHECK_CALL(sd_bus_message_read(m, "u", &mode));
|
||||
|
||||
r = ratbag_led_set_mode(led->lib_led, mode);
|
||||
|
||||
@@ -124,7 +126,11 @@ static int ratbagd_led_get_type(sd_bus *bus,
|
||||
|
||||
type = ratbag_led_get_type(led->lib_led);
|
||||
|
||||
return sd_bus_message_append(reply, "u", type);
|
||||
verify_unsigned_int(type);
|
||||
|
||||
CHECK_CALL(sd_bus_message_append(reply, "u", type));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ratbagd_led_get_color(sd_bus *bus,
|
||||
@@ -139,7 +145,9 @@ static int ratbagd_led_get_color(sd_bus *bus,
|
||||
struct ratbag_color c;
|
||||
|
||||
c = ratbag_led_get_color(led->lib_led);
|
||||
return sd_bus_message_append(reply, "(uuu)", c.red, c.green, c.blue);
|
||||
CHECK_CALL(sd_bus_message_append(reply, "(uuu)", c.red, c.green, c.blue));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ratbagd_led_set_color(sd_bus *bus,
|
||||
@@ -154,9 +162,7 @@ static int ratbagd_led_set_color(sd_bus *bus,
|
||||
struct ratbag_color c;
|
||||
int r;
|
||||
|
||||
r = sd_bus_message_read(m, "(uuu)", &c.red, &c.green, &c.blue);
|
||||
if (r < 0)
|
||||
return r;
|
||||
CHECK_CALL(sd_bus_message_read(m, "(uuu)", &c.red, &c.green, &c.blue));
|
||||
|
||||
if (c.red > 255)
|
||||
c.red = 255;
|
||||
@@ -191,7 +197,12 @@ static int ratbagd_led_get_effect_duration(sd_bus *bus,
|
||||
int rate;
|
||||
|
||||
rate = ratbag_led_get_effect_duration(led->lib_led);
|
||||
return sd_bus_message_append(reply, "u", rate);
|
||||
|
||||
verify_unsigned_int(rate);
|
||||
|
||||
CHECK_CALL(sd_bus_message_append(reply, "u", rate));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ratbagd_led_set_effect_duration(sd_bus *bus,
|
||||
@@ -206,9 +217,7 @@ static int ratbagd_led_set_effect_duration(sd_bus *bus,
|
||||
unsigned int rate;
|
||||
int r;
|
||||
|
||||
r = sd_bus_message_read(m, "u", &rate);
|
||||
if (r < 0)
|
||||
return r;
|
||||
CHECK_CALL(sd_bus_message_read(m, "u", &rate));
|
||||
|
||||
if (rate > 10000)
|
||||
rate = 10000;
|
||||
@@ -239,7 +248,12 @@ static int ratbagd_led_get_brightness(sd_bus *bus,
|
||||
unsigned int brightness;
|
||||
|
||||
brightness = ratbag_led_get_brightness(led->lib_led);
|
||||
return sd_bus_message_append(reply, "u", brightness);
|
||||
|
||||
verify_unsigned_int(brightness);
|
||||
|
||||
CHECK_CALL(sd_bus_message_append(reply, "u", brightness));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ratbagd_led_set_brightness(sd_bus *bus,
|
||||
@@ -254,9 +268,7 @@ static int ratbagd_led_set_brightness(sd_bus *bus,
|
||||
unsigned int brightness;
|
||||
int r;
|
||||
|
||||
r = sd_bus_message_read(m, "u", &brightness);
|
||||
if (r < 0)
|
||||
return r;
|
||||
CHECK_CALL(sd_bus_message_read(m, "u", &brightness));
|
||||
|
||||
if (brightness > 255)
|
||||
brightness = 255;
|
||||
|
||||
@@ -102,25 +102,22 @@ static int ratbagd_profile_get_resolutions(sd_bus *bus,
|
||||
struct ratbagd_profile *profile = userdata;
|
||||
struct ratbagd_resolution *resolution;
|
||||
unsigned int i;
|
||||
int r;
|
||||
|
||||
r = sd_bus_message_open_container(reply, 'a', "o");
|
||||
if (r < 0)
|
||||
return r;
|
||||
CHECK_CALL(sd_bus_message_open_container(reply, 'a', "o"));
|
||||
|
||||
for (i = 0; i < profile->n_resolutions; ++i) {
|
||||
resolution = profile->resolutions[i];
|
||||
if (!resolution)
|
||||
continue;
|
||||
|
||||
r = sd_bus_message_append(reply,
|
||||
"o",
|
||||
ratbagd_resolution_get_path(resolution));
|
||||
if (r < 0)
|
||||
return r;
|
||||
CHECK_CALL(sd_bus_message_append(reply,
|
||||
"o",
|
||||
ratbagd_resolution_get_path(resolution)));
|
||||
}
|
||||
|
||||
return sd_bus_message_close_container(reply);
|
||||
CHECK_CALL(sd_bus_message_close_container(reply));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ratbagd_profile_get_buttons(sd_bus *bus,
|
||||
@@ -134,25 +131,22 @@ static int ratbagd_profile_get_buttons(sd_bus *bus,
|
||||
struct ratbagd_profile *profile = userdata;
|
||||
struct ratbagd_button *button;
|
||||
unsigned int i;
|
||||
int r;
|
||||
|
||||
r = sd_bus_message_open_container(reply, 'a', "o");
|
||||
if (r < 0)
|
||||
return r;
|
||||
CHECK_CALL(sd_bus_message_open_container(reply, 'a', "o"));
|
||||
|
||||
for (i = 0; i < profile->n_buttons; ++i) {
|
||||
button = profile->buttons[i];
|
||||
if (!button)
|
||||
continue;
|
||||
|
||||
r = sd_bus_message_append(reply,
|
||||
CHECK_CALL(sd_bus_message_append(reply,
|
||||
"o",
|
||||
ratbagd_button_get_path(button));
|
||||
if (r < 0)
|
||||
return r;
|
||||
ratbagd_button_get_path(button)));
|
||||
}
|
||||
|
||||
return sd_bus_message_close_container(reply);
|
||||
CHECK_CALL(sd_bus_message_close_container(reply));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ratbagd_profile_get_leds(sd_bus *bus,
|
||||
@@ -166,25 +160,22 @@ static int ratbagd_profile_get_leds(sd_bus *bus,
|
||||
struct ratbagd_profile *profile = userdata;
|
||||
struct ratbagd_led *led;
|
||||
unsigned int i;
|
||||
int r;
|
||||
|
||||
r = sd_bus_message_open_container(reply, 'a', "o");
|
||||
if (r < 0)
|
||||
return r;
|
||||
CHECK_CALL(sd_bus_message_open_container(reply, 'a', "o"));
|
||||
|
||||
for (i = 0; i < profile->n_leds; ++i) {
|
||||
led = profile->leds[i];
|
||||
if (!led)
|
||||
continue;
|
||||
|
||||
r = sd_bus_message_append(reply,
|
||||
"o",
|
||||
ratbagd_led_get_path(led));
|
||||
if (r < 0)
|
||||
return r;
|
||||
CHECK_CALL(sd_bus_message_append(reply,
|
||||
"o",
|
||||
ratbagd_led_get_path(led)));
|
||||
}
|
||||
|
||||
return sd_bus_message_close_container(reply);
|
||||
CHECK_CALL(sd_bus_message_close_container(reply));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ratbagd_profile_is_active(sd_bus *bus,
|
||||
@@ -198,9 +189,11 @@ static int ratbagd_profile_is_active(sd_bus *bus,
|
||||
struct ratbagd_profile *profile = userdata;
|
||||
int is_active;
|
||||
|
||||
is_active = !!ratbag_profile_is_active(profile->lib_profile);
|
||||
is_active = ratbag_profile_is_active(profile->lib_profile);
|
||||
|
||||
return sd_bus_message_append(reply, "b", is_active);
|
||||
CHECK_CALL(sd_bus_message_append(reply, "b", is_active));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ratbagd_profile_find_button(sd_bus *bus,
|
||||
@@ -286,9 +279,7 @@ static int ratbagd_profile_set_active(sd_bus_message *m,
|
||||
struct ratbagd_profile *profile = userdata;
|
||||
int r;
|
||||
|
||||
r = sd_bus_message_read(m, "");
|
||||
if (r < 0)
|
||||
return r;
|
||||
CHECK_CALL(sd_bus_message_read(m, ""));
|
||||
|
||||
r = ratbag_profile_set_active(profile->lib_profile);
|
||||
if (r < 0) {
|
||||
@@ -302,7 +293,9 @@ static int ratbagd_profile_set_active(sd_bus_message *m,
|
||||
profile->device,
|
||||
ratbagd_profile_active_signal_cb);
|
||||
|
||||
return sd_bus_reply_method_return(m, "u", 0);
|
||||
CHECK_CALL(sd_bus_reply_method_return(m, "u", 0));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -318,9 +311,7 @@ ratbagd_profile_set_enabled(sd_bus *bus,
|
||||
int enabled;
|
||||
int r;
|
||||
|
||||
r = sd_bus_message_read(m, "b", &enabled);
|
||||
if (r < 0)
|
||||
return r;
|
||||
CHECK_CALL(sd_bus_message_read(m, "b", &enabled));
|
||||
|
||||
r = ratbag_profile_set_enabled(profile->lib_profile, enabled);
|
||||
if (r == 0) {
|
||||
@@ -347,7 +338,9 @@ ratbagd_profile_is_enabled(sd_bus *bus,
|
||||
struct ratbagd_profile *profile = userdata;
|
||||
int enabled = ratbag_profile_is_enabled(profile->lib_profile) != 0;
|
||||
|
||||
return sd_bus_message_append(reply, "b", enabled);
|
||||
CHECK_CALL(sd_bus_message_append(reply, "b", enabled));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -363,9 +356,7 @@ ratbagd_profile_set_name(sd_bus *bus,
|
||||
char *name;
|
||||
int r;
|
||||
|
||||
r = sd_bus_message_read(m, "s", &name);
|
||||
if (r < 0)
|
||||
return r;
|
||||
CHECK_CALL(sd_bus_message_read(m, "s", &name));
|
||||
|
||||
r = ratbag_profile_set_name(profile->lib_profile, name);
|
||||
|
||||
@@ -392,7 +383,9 @@ ratbagd_profile_get_name(sd_bus *bus,
|
||||
struct ratbagd_profile *profile = userdata;
|
||||
const char *name = ratbag_profile_get_name(profile->lib_profile);
|
||||
|
||||
return sd_bus_message_append(reply, "s", name);
|
||||
CHECK_CALL(sd_bus_message_append(reply, "s", name));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -410,23 +403,20 @@ ratbagd_profile_get_capabilities(sd_bus *bus,
|
||||
enum ratbag_profile_capability caps[] = {
|
||||
RATBAG_PROFILE_CAP_WRITABLE_NAME,
|
||||
};
|
||||
int r;
|
||||
size_t i;
|
||||
|
||||
r = sd_bus_message_open_container(reply, 'a', "u");
|
||||
if (r < 0)
|
||||
return r;
|
||||
CHECK_CALL(sd_bus_message_open_container(reply, 'a', "u"));
|
||||
|
||||
for (i = 0; i < ELEMENTSOF(caps); i++) {
|
||||
cap = caps[i];
|
||||
if (ratbag_profile_has_capability(lib_profile, cap)) {
|
||||
r = sd_bus_message_append(reply, "u", cap);
|
||||
if (r < 0)
|
||||
return r;
|
||||
CHECK_CALL(sd_bus_message_append(reply, "u", cap));
|
||||
}
|
||||
}
|
||||
|
||||
return sd_bus_message_close_container(reply);
|
||||
CHECK_CALL(sd_bus_message_close_container(reply));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const sd_bus_vtable ratbagd_profile_vtable[] = {
|
||||
|
||||
@@ -167,7 +167,7 @@ ratbagd_resolution_is_active(sd_bus *bus,
|
||||
struct ratbag_resolution *lib_resolution = resolution->lib_resolution;
|
||||
int is_active;
|
||||
|
||||
is_active = !!ratbag_resolution_is_active(lib_resolution);
|
||||
is_active = ratbag_resolution_is_active(lib_resolution);
|
||||
|
||||
return sd_bus_message_append(reply, "b", is_active);
|
||||
}
|
||||
@@ -185,7 +185,7 @@ ratbagd_resolution_is_default(sd_bus *bus,
|
||||
struct ratbag_resolution *lib_resolution = resolution->lib_resolution;
|
||||
int is_default;
|
||||
|
||||
is_default = !!ratbag_resolution_is_default(lib_resolution);
|
||||
is_default = ratbag_resolution_is_default(lib_resolution);
|
||||
|
||||
return sd_bus_message_append(reply, "b", is_default);
|
||||
}
|
||||
@@ -214,6 +214,7 @@ ratbagd_resolution_get_resolutions(sd_bus *bus,
|
||||
assert(ndpis <= ARRAY_LENGTH(dpis));
|
||||
|
||||
for (unsigned int i = 0; i < ndpis; i++) {
|
||||
verify_unsigned_int(dpis[i]);
|
||||
r = sd_bus_message_append(reply, "u", dpis[i]);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@@ -238,6 +239,9 @@ ratbagd_resolution_get_resolution(sd_bus *bus,
|
||||
xres = ratbag_resolution_get_dpi_x(lib_resolution);
|
||||
yres = ratbag_resolution_get_dpi_y(lib_resolution);
|
||||
|
||||
verify_unsigned_int(xres);
|
||||
verify_unsigned_int(yres);
|
||||
|
||||
return sd_bus_message_append(reply, "(uu)", xres, yres);
|
||||
}
|
||||
|
||||
@@ -293,6 +297,7 @@ ratbagd_resolution_get_report_rate(sd_bus *bus,
|
||||
int rate;
|
||||
|
||||
rate = ratbag_resolution_get_report_rate(lib_resolution);
|
||||
verify_unsigned_int(rate);
|
||||
return sd_bus_message_append(reply, "u", rate);
|
||||
}
|
||||
|
||||
@@ -307,7 +312,7 @@ ratbagd_resolution_get_report_rates(sd_bus *bus,
|
||||
{
|
||||
struct ratbagd_resolution *resolution = userdata;
|
||||
struct ratbag_resolution *lib_resolution = resolution->lib_resolution;
|
||||
unsigned int rates[5];
|
||||
unsigned int rates[8];
|
||||
unsigned int nrates = ARRAY_LENGTH(rates);
|
||||
int r;
|
||||
|
||||
@@ -320,6 +325,7 @@ ratbagd_resolution_get_report_rates(sd_bus *bus,
|
||||
assert(nrates <= ARRAY_LENGTH(rates));
|
||||
|
||||
for (unsigned int i = 0; i < nrates; i++) {
|
||||
verify_unsigned_int(rates[i]);
|
||||
r = sd_bus_message_append(reply, "u", rates[i]);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -42,8 +42,12 @@
|
||||
|
||||
#include "ratbagd-test.h"
|
||||
|
||||
static bool verbose = false;
|
||||
static bool verbose_raw = false;
|
||||
enum log_level {
|
||||
LL_QUIET = 1,
|
||||
LL_INFO,
|
||||
LL_VERBOSE,
|
||||
LL_RAW,
|
||||
} log_level = LL_INFO;
|
||||
|
||||
static const char *SVG_THEMES[] = {
|
||||
"default",
|
||||
@@ -51,13 +55,23 @@ static const char *SVG_THEMES[] = {
|
||||
NULL
|
||||
};
|
||||
|
||||
void log_info(const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start(args, fmt);
|
||||
if (log_level >= LL_INFO)
|
||||
vprintf(fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void log_verbose(const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start(args, fmt);
|
||||
|
||||
if (verbose)
|
||||
if (log_level >= LL_VERBOSE)
|
||||
vprintf(fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
@@ -142,21 +156,18 @@ static int ratbagd_get_devices(sd_bus *bus,
|
||||
{
|
||||
struct ratbagd *ctx = userdata;
|
||||
struct ratbagd_device *device;
|
||||
int r;
|
||||
|
||||
r = sd_bus_message_open_container(reply, 'a', "o");
|
||||
if (r < 0)
|
||||
return r;
|
||||
CHECK_CALL(sd_bus_message_open_container(reply, 'a', "o"));
|
||||
|
||||
RATBAGD_DEVICE_FOREACH(device, ctx) {
|
||||
r = sd_bus_message_append(reply,
|
||||
"o",
|
||||
ratbagd_device_get_path(device));
|
||||
if (r < 0)
|
||||
return r;
|
||||
CHECK_CALL(sd_bus_message_append(reply,
|
||||
"o",
|
||||
ratbagd_device_get_path(device)));
|
||||
}
|
||||
|
||||
return sd_bus_message_close_container(reply);
|
||||
CHECK_CALL(sd_bus_message_close_container(reply));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ratbagd_get_themes(sd_bus *bus,
|
||||
@@ -169,23 +180,18 @@ static int ratbagd_get_themes(sd_bus *bus,
|
||||
{
|
||||
struct ratbagd *ctx = userdata;
|
||||
const char **theme;
|
||||
int r;
|
||||
|
||||
r = sd_bus_message_open_container(reply, 'a', "s");
|
||||
if (r < 0)
|
||||
return r;
|
||||
CHECK_CALL(sd_bus_message_open_container(reply, 'a', "s"));
|
||||
|
||||
theme = ctx->themes;
|
||||
while(*theme) {
|
||||
r = sd_bus_message_append(reply,
|
||||
"s",
|
||||
*theme);
|
||||
if (r < 0)
|
||||
return r;
|
||||
CHECK_CALL(sd_bus_message_append(reply, "s", *theme));
|
||||
theme++;
|
||||
}
|
||||
|
||||
return sd_bus_message_close_container(reply);
|
||||
CHECK_CALL(sd_bus_message_close_container(reply));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const sd_bus_vtable ratbagd_vtable[] = {
|
||||
@@ -384,10 +390,10 @@ static int ratbagd_new(struct ratbagd **out)
|
||||
if (!ctx->lib_ctx)
|
||||
return -ENOMEM;
|
||||
|
||||
if (verbose_raw)
|
||||
if (log_level >= LL_RAW)
|
||||
ratbag_log_set_priority(ctx->lib_ctx,
|
||||
RATBAG_LOG_PRIORITY_RAW);
|
||||
else if (verbose)
|
||||
else if (log_level >= LL_VERBOSE)
|
||||
ratbag_log_set_priority(ctx->lib_ctx,
|
||||
RATBAG_LOG_PRIORITY_DEBUG);
|
||||
|
||||
@@ -533,12 +539,17 @@ int main(int argc, char *argv[])
|
||||
#endif
|
||||
|
||||
if (argc > 1) {
|
||||
if (streq(argv[1], "--verbose=raw")) {
|
||||
verbose_raw = true;
|
||||
if (streq(argv[1], "--version")) {
|
||||
printf("%s\n", RATBAG_VERSION);
|
||||
return 0;
|
||||
} else if (streq(argv[1], "--quiet")) {
|
||||
log_level = LL_QUIET;
|
||||
} else if (streq(argv[1], "--verbose=raw")) {
|
||||
log_level = LL_RAW;
|
||||
} else if (streq(argv[1], "--verbose")) {
|
||||
verbose = true;
|
||||
log_level = LL_VERBOSE;
|
||||
} else {
|
||||
fprintf(stderr, "Usage: %s [--verbose[=raw]]\n",
|
||||
fprintf(stderr, "Usage: %s [--version | --quiet | --verbose[=raw]]\n",
|
||||
program_invocation_short_name);
|
||||
r = -EINVAL;
|
||||
goto exit;
|
||||
|
||||
@@ -54,9 +54,20 @@ struct ratbagd_resolution;
|
||||
struct ratbagd_button;
|
||||
struct ratbagd_led;
|
||||
|
||||
void log_info(const char *fmt, ...) _printf_(1, 2);
|
||||
void log_verbose(const char *fmt, ...) _printf_(1, 2);
|
||||
void log_error(const char *fmt, ...) _printf_(1, 2);
|
||||
|
||||
#define CHECK_CALL(_call) \
|
||||
do { \
|
||||
int _r = _call; \
|
||||
if (_r < 0) { \
|
||||
log_error("%s: '%s' failed with: %s\n", __func__, #_call, strerror(-_r)); \
|
||||
return _r; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
/*
|
||||
* Profiles
|
||||
*/
|
||||
@@ -176,6 +187,19 @@ struct ratbagd_device *ratbagd_device_next(struct ratbagd_device *device);
|
||||
(_device); \
|
||||
_device = (_safe), \
|
||||
_safe = (_safe) ? ratbagd_device_next(_safe) : NULL)
|
||||
|
||||
/* Verify that _val is not -1. This traps DBus API errors where we end up
|
||||
* sending a valid-looking index across and then fail on the other side.
|
||||
*
|
||||
* do {} while(0) so we can terminate with a ; without the compiler
|
||||
* complaining about an empty statement;
|
||||
* */
|
||||
#define verify_unsigned_int(_val) \
|
||||
do { if ((int)_val == -1) { \
|
||||
log_error("%s:%d - %s: expected unsigned int, got -1\n", __FILE__, __LINE__, __func__); \
|
||||
return -EINVAL; \
|
||||
} } while(0)
|
||||
|
||||
/*
|
||||
* Context
|
||||
*/
|
||||
|
||||
@@ -987,7 +987,7 @@ gskill_read_resolutions(struct ratbag_profile *profile,
|
||||
hz = GSKILL_MAX_POLLING_RATE / (report->polling_rate + 1);
|
||||
|
||||
for (i = 0; i < report->dpi_num; i++) {
|
||||
_cleanup_resolution_ struct ratbag_resolution *resolution;
|
||||
_cleanup_resolution_ struct ratbag_resolution *resolution = NULL;
|
||||
unsigned int rates[] = { 500, 1000 }; /* let's assume that is true */
|
||||
|
||||
dpi_x = report->dpi_levels[i].x * GSKILL_DPI_UNIT;
|
||||
@@ -1108,7 +1108,7 @@ gskill_update_resolutions(struct ratbag_profile *profile)
|
||||
* lost on exit
|
||||
*/
|
||||
for (i = 0; i < GSKILL_NUM_DPI; i++) {
|
||||
_cleanup_resolution_ struct ratbag_resolution *res;
|
||||
_cleanup_resolution_ struct ratbag_resolution *res = NULL;
|
||||
struct gskill_raw_dpi_level *level =
|
||||
&report->dpi_levels[report->dpi_num];
|
||||
|
||||
|
||||
@@ -407,8 +407,14 @@ hidpp10drv_read_profile(struct ratbag_profile *profile)
|
||||
if (rc)
|
||||
return;
|
||||
|
||||
ratbag_profile_set_cap(profile, RATBAG_PROFILE_CAP_WRITABLE_NAME);
|
||||
|
||||
profile->is_enabled = p.enabled;
|
||||
|
||||
if (profile->name)
|
||||
free(profile->name);
|
||||
profile->name = strdup_safe((char*)p.name);
|
||||
|
||||
rc = hidpp10_get_current_profile(hidpp10, &idx);
|
||||
if (rc == 0 && (unsigned int)idx == profile->index)
|
||||
profile->is_active = true;
|
||||
@@ -543,6 +549,7 @@ hidpp10drv_commit(struct ratbag_device *device)
|
||||
return rc;
|
||||
|
||||
p.enabled = profile->is_enabled;
|
||||
strncpy_safe((char*)p.name, profile->name, 24);
|
||||
|
||||
ratbag_profile_for_each_resolution(profile, resolution) {
|
||||
p.dpi_modes[resolution->index].xres = resolution->dpi_x;
|
||||
@@ -605,7 +612,7 @@ hidpp10drv_probe(struct ratbag_device *device)
|
||||
goto err;
|
||||
|
||||
drv_data = zalloc(sizeof(*drv_data));
|
||||
hidpp_device_init(&base, device->hidraw.fd);
|
||||
hidpp_device_init(&base, device->hidraw[0].fd);
|
||||
hidpp_device_set_log_handler(&base, hidpp10_log, HIDPP_LOG_PRIORITY_RAW, device);
|
||||
|
||||
typestr = ratbag_device_data_hidpp10_get_profile_type(device->data);
|
||||
|
||||
@@ -716,6 +716,9 @@ hidpp20drv_read_resolution_dpi(struct ratbag_profile *profile)
|
||||
struct ratbag_device *device = profile->device;
|
||||
struct ratbag *ratbag = device->ratbag;
|
||||
struct hidpp20drv_data *drv_data = ratbag_get_drv_data(device);
|
||||
struct ratbag_resolution *res;
|
||||
unsigned int default_dpi = 1000;
|
||||
unsigned int default_rate = 500;
|
||||
int rc;
|
||||
|
||||
if (drv_data->capabilities & HIDPP_CAP_RESOLUTION_2200) {
|
||||
@@ -734,8 +737,6 @@ hidpp20drv_read_resolution_dpi(struct ratbag_profile *profile)
|
||||
}
|
||||
|
||||
if (drv_data->capabilities & HIDPP_CAP_SWITCHABLE_RESOLUTION_2201) {
|
||||
struct ratbag_resolution *res;
|
||||
|
||||
rc = hidpp20drv_read_resolution_dpi_2201(device);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
@@ -756,13 +757,12 @@ hidpp20drv_read_resolution_dpi(struct ratbag_profile *profile)
|
||||
* they are from different sensors */
|
||||
res->is_active = true;
|
||||
}
|
||||
|
||||
return 0;
|
||||
} else {
|
||||
ratbag_profile_for_each_resolution(profile, res)
|
||||
ratbag_resolution_set_dpi_list(res, &default_dpi, 1);
|
||||
}
|
||||
|
||||
if (drv_data->capabilities & HIDPP_CAP_ADJUSTIBLE_REPORT_RATE_8060) {
|
||||
struct ratbag_resolution *res;
|
||||
|
||||
rc = hidpp20drv_read_report_rate_8060(device);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
@@ -771,6 +771,9 @@ hidpp20drv_read_resolution_dpi(struct ratbag_profile *profile)
|
||||
ratbag_resolution_set_report_rate_list(res,
|
||||
drv_data->report_rates,
|
||||
drv_data->num_report_rates);
|
||||
} else {
|
||||
ratbag_profile_for_each_resolution(profile, res)
|
||||
ratbag_resolution_set_report_rate_list(res, &default_rate, 1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -1049,7 +1052,7 @@ hidpp20drv_init_feature(struct ratbag_device *device, uint16_t feature)
|
||||
/* we read the profile once to get the correct number of
|
||||
* supported buttons. */
|
||||
if (!hidpp20drv_read_special_key_mouse(device))
|
||||
device->num_buttons = drv_data->num_controls;
|
||||
drv_data->num_buttons = drv_data->num_controls;
|
||||
break;
|
||||
}
|
||||
case HIDPP_PAGE_BATTERY_LEVEL_STATUS: {
|
||||
@@ -1074,7 +1077,7 @@ hidpp20drv_init_feature(struct ratbag_device *device, uint16_t feature)
|
||||
/* we read the profile once to get the correct number of
|
||||
* supported buttons. */
|
||||
if (!hidpp20drv_read_kbd_reprogrammable_key(device))
|
||||
device->num_buttons = drv_data->num_controls;
|
||||
drv_data->num_buttons = drv_data->num_controls;
|
||||
break;
|
||||
}
|
||||
case HIDPP_PAGE_ADJUSTABLE_REPORT_RATE: {
|
||||
@@ -1163,8 +1166,6 @@ hidpp20drv_commit(struct ratbag_device *device)
|
||||
if (!profile->dirty)
|
||||
continue;
|
||||
|
||||
drv_data->profiles->profiles[profile->index].enabled = profile->is_enabled;
|
||||
|
||||
ratbag_profile_for_each_resolution(profile, resolution) {
|
||||
if (resolution->is_active)
|
||||
dpi_index = resolution->index;
|
||||
@@ -1197,6 +1198,9 @@ hidpp20drv_commit(struct ratbag_device *device)
|
||||
}
|
||||
|
||||
if (drv_data->capabilities & HIDPP_CAP_ONBOARD_PROFILES_8100) {
|
||||
list_for_each(profile, &device->profiles, link)
|
||||
drv_data->profiles->profiles[profile->index].enabled = profile->is_enabled;
|
||||
|
||||
rc = hidpp20_onboard_profiles_commit(drv_data->dev,
|
||||
drv_data->profiles);
|
||||
if (rc)
|
||||
@@ -1306,7 +1310,7 @@ hidpp20drv_probe(struct ratbag_device *device)
|
||||
|
||||
drv_data = zalloc(sizeof(*drv_data));
|
||||
ratbag_set_drv_data(device, drv_data);
|
||||
hidpp_device_init(&base, device->hidraw.fd);
|
||||
hidpp_device_init(&base, device->hidraw[0].fd);
|
||||
hidpp_device_set_log_handler(&base, hidpp20_log, HIDPP_LOG_PRIORITY_RAW, device);
|
||||
|
||||
device_idx = ratbag_device_data_hidpp20_get_index(device->data);
|
||||
@@ -1335,7 +1339,7 @@ hidpp20drv_probe(struct ratbag_device *device)
|
||||
drv_data->num_profiles = 1;
|
||||
drv_data->num_resolutions = 1;
|
||||
drv_data->num_buttons = 8;
|
||||
drv_data->num_leds = 2;
|
||||
drv_data->num_leds = 0;
|
||||
|
||||
rc = hidpp20drv_20_probe(device);
|
||||
if (rc)
|
||||
|
||||
671
src/driver-logitech-g600.c
Normal file
671
src/driver-logitech-g600.c
Normal file
@@ -0,0 +1,671 @@
|
||||
/*
|
||||
* Copyright © 2018 Thomas Hindoe Paaboel Andersen.
|
||||
*
|
||||
* 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 LOGITECH_G600_NUM_PROFILES 3
|
||||
#define LOGITECH_G600_NUM_BUTTONS 20
|
||||
#define LOGITECH_G600_NUM_DPI 4
|
||||
#define LOGITECH_G600_NUM_LED 1
|
||||
#define LOGITECH_G600_DPI_MIN 200
|
||||
#define LOGITECH_G600_DPI_MAX 8200
|
||||
|
||||
#define LOGITECH_G600_REPORT_ID_GET_ACTIVE 0xF0
|
||||
#define LOGITECH_G600_REPORT_ID_SET_ACTIVE 0xF0
|
||||
#define LOGITECH_G600_REPORT_ID_PROFILE_0 0xF3
|
||||
#define LOGITECH_G600_REPORT_ID_PROFILE_1 0xF4
|
||||
#define LOGITECH_G600_REPORT_ID_PROFILE_2 0xF5
|
||||
|
||||
#define LOGITECH_G600_REPORT_SIZE_PROFILE 154
|
||||
|
||||
#define LOGITECH_G600_LED_SOLID 0x00
|
||||
#define LOGITECH_G600_LED_BREATHE 0x01
|
||||
#define LOGITECH_G600_LED_CYCLE 0x02
|
||||
|
||||
struct logitech_g600_button {
|
||||
uint8_t code;
|
||||
uint8_t modifier;
|
||||
uint8_t key;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct logitech_g600_profile_report {
|
||||
uint8_t id;
|
||||
uint8_t led_red;
|
||||
uint8_t led_green;
|
||||
uint8_t led_blue;
|
||||
uint8_t led_effect;
|
||||
uint8_t led_duration;
|
||||
uint8_t unknown1[5];
|
||||
uint8_t frequency; /* frequency = 1000 / (value + 1) */
|
||||
uint8_t dpi_shift; /* value is a linear range between 200->0x04, 8200->0xa4, so value * 50, 0x00 is disabled */
|
||||
uint8_t dpi_default; /* between 1 and 4*/
|
||||
uint8_t dpi[4]; /* value is a linear range between 200->0x04, 8200->0xa4, so value * 50, 0x00 is disabled */
|
||||
uint8_t unknown2[13];
|
||||
struct logitech_g600_button buttons[20];
|
||||
uint8_t g_shift_color[3]; /* can't assign it in LGS, but the 3rd profile has one that shows the feature :) */
|
||||
struct logitech_g600_button g_shift_buttons[20];
|
||||
} __attribute__((packed));
|
||||
|
||||
struct logitech_g600_active_profile_report {
|
||||
uint8_t id;
|
||||
uint8_t unknown1 :1;
|
||||
uint8_t resolution :2;
|
||||
uint8_t unknown2 :1;
|
||||
uint8_t profile :4;
|
||||
uint8_t unknown3;
|
||||
uint8_t unknown4;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct logitech_g600_profile_data {
|
||||
struct logitech_g600_profile_report report;
|
||||
};
|
||||
|
||||
struct logitech_g600_data {
|
||||
struct logitech_g600_profile_data profile_data[LOGITECH_G600_NUM_PROFILES];
|
||||
};
|
||||
|
||||
_Static_assert(sizeof(struct logitech_g600_profile_report) == LOGITECH_G600_REPORT_SIZE_PROFILE,
|
||||
"Size of logitech_g600_profile_report is wrong");
|
||||
|
||||
struct logitech_g600_button_type_mapping {
|
||||
uint8_t raw;
|
||||
enum ratbag_button_type type;
|
||||
};
|
||||
|
||||
static const struct logitech_g600_button_type_mapping logitech_g600_button_type_mapping[] = {
|
||||
{ 0, RATBAG_BUTTON_TYPE_LEFT },
|
||||
{ 1, RATBAG_BUTTON_TYPE_RIGHT },
|
||||
{ 2, RATBAG_BUTTON_TYPE_MIDDLE },
|
||||
{ 3, RATBAG_BUTTON_TYPE_WHEEL_LEFT },
|
||||
{ 4, RATBAG_BUTTON_TYPE_WHEEL_RIGHT },
|
||||
{ 5, RATBAG_BUTTON_TYPE_PINKIE },
|
||||
{ 6, RATBAG_BUTTON_TYPE_PROFILE_CYCLE_UP },
|
||||
{ 7, RATBAG_BUTTON_TYPE_RESOLUTION_CYCLE_UP },
|
||||
{ 8, RATBAG_BUTTON_TYPE_SIDE }, // 8 = G9 ... 19 = G20
|
||||
{ 9, RATBAG_BUTTON_TYPE_SIDE },
|
||||
{ 10, RATBAG_BUTTON_TYPE_SIDE },
|
||||
{ 11, RATBAG_BUTTON_TYPE_SIDE },
|
||||
{ 12, RATBAG_BUTTON_TYPE_SIDE },
|
||||
{ 13, RATBAG_BUTTON_TYPE_SIDE },
|
||||
{ 14, RATBAG_BUTTON_TYPE_SIDE },
|
||||
{ 15, RATBAG_BUTTON_TYPE_SIDE },
|
||||
{ 16, RATBAG_BUTTON_TYPE_SIDE },
|
||||
{ 17, RATBAG_BUTTON_TYPE_SIDE },
|
||||
{ 18, RATBAG_BUTTON_TYPE_SIDE },
|
||||
{ 19, RATBAG_BUTTON_TYPE_SIDE },
|
||||
};
|
||||
|
||||
static enum ratbag_button_type
|
||||
logitech_g600_raw_to_button_type(uint8_t data)
|
||||
{
|
||||
const struct logitech_g600_button_type_mapping *mapping;
|
||||
|
||||
ARRAY_FOR_EACH(logitech_g600_button_type_mapping, mapping) {
|
||||
if (mapping->raw == data)
|
||||
return mapping->type;
|
||||
}
|
||||
|
||||
return RATBAG_BUTTON_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
struct logitech_g600_button_mapping {
|
||||
uint8_t raw;
|
||||
struct ratbag_button_action action;
|
||||
};
|
||||
|
||||
static struct logitech_g600_button_mapping logitech_g600_button_mapping[] = {
|
||||
/* 0x00 is either key or unassigned. Must be handled separatly */
|
||||
{ 0x01, BUTTON_ACTION_BUTTON(1) },
|
||||
{ 0x02, BUTTON_ACTION_BUTTON(2) },
|
||||
{ 0x03, BUTTON_ACTION_BUTTON(3) },
|
||||
{ 0x04, BUTTON_ACTION_BUTTON(4) },
|
||||
{ 0x05, BUTTON_ACTION_BUTTON(5) },
|
||||
{ 0x11, BUTTON_ACTION_SPECIAL(RATBAG_BUTTON_ACTION_SPECIAL_RESOLUTION_UP) },
|
||||
{ 0x12, BUTTON_ACTION_SPECIAL(RATBAG_BUTTON_ACTION_SPECIAL_RESOLUTION_DOWN) },
|
||||
{ 0x13, BUTTON_ACTION_SPECIAL(RATBAG_BUTTON_ACTION_SPECIAL_RESOLUTION_CYCLE_UP) },
|
||||
{ 0x14, BUTTON_ACTION_SPECIAL(RATBAG_BUTTON_ACTION_SPECIAL_PROFILE_CYCLE_UP) },
|
||||
{ 0x15, BUTTON_ACTION_SPECIAL(RATBAG_BUTTON_ACTION_SPECIAL_RESOLUTION_ALTERNATE) },
|
||||
{ 0x17, BUTTON_ACTION_SPECIAL(RATBAG_BUTTON_ACTION_SPECIAL_SECOND_MODE) },
|
||||
};
|
||||
|
||||
static const struct ratbag_button_action*
|
||||
logitech_g600_raw_to_button_action(uint8_t data)
|
||||
{
|
||||
struct logitech_g600_button_mapping *mapping;
|
||||
|
||||
ARRAY_FOR_EACH(logitech_g600_button_mapping, mapping) {
|
||||
if (mapping->raw == data)
|
||||
return &mapping->action;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static uint8_t logitech_g600_modifier_to_raw(int modifier_flags)
|
||||
{
|
||||
uint8_t modifiers = 0x00;
|
||||
|
||||
if (modifier_flags & MODIFIER_LEFTCTRL)
|
||||
modifiers |= 0x01;
|
||||
if (modifier_flags & MODIFIER_LEFTSHIFT)
|
||||
modifiers |= 0x02;
|
||||
if (modifier_flags & MODIFIER_LEFTALT)
|
||||
modifiers |= 0x04;
|
||||
if (modifier_flags & MODIFIER_LEFTMETA)
|
||||
modifiers |= 0x08;
|
||||
if (modifier_flags & MODIFIER_RIGHTCTRL)
|
||||
modifiers |= 0x10;
|
||||
if (modifier_flags & MODIFIER_RIGHTSHIFT)
|
||||
modifiers |= 0x20;
|
||||
if (modifier_flags & MODIFIER_RIGHTALT)
|
||||
modifiers |= 0x40;
|
||||
if (modifier_flags & MODIFIER_RIGHTMETA)
|
||||
modifiers |= 0x80;
|
||||
|
||||
return modifiers;
|
||||
}
|
||||
|
||||
static int logitech_g600_raw_to_modifiers(uint8_t data)
|
||||
{
|
||||
int modifiers = 0;
|
||||
|
||||
if (data & 0x01)
|
||||
modifiers |= MODIFIER_LEFTCTRL;
|
||||
if (data & 0x02)
|
||||
modifiers |= MODIFIER_LEFTSHIFT;
|
||||
if (data & 0x04)
|
||||
modifiers |= MODIFIER_LEFTALT;
|
||||
if (data & 0x08)
|
||||
modifiers |= MODIFIER_LEFTMETA;
|
||||
if (data & 0x10)
|
||||
modifiers |= MODIFIER_RIGHTCTRL;
|
||||
if (data & 0x20)
|
||||
modifiers |= MODIFIER_RIGHTSHIFT;
|
||||
if (data & 0x40)
|
||||
modifiers |= MODIFIER_RIGHTALT;
|
||||
if (data & 0x80)
|
||||
modifiers |= MODIFIER_RIGHTMETA;
|
||||
|
||||
return modifiers;
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
logitech_g600_button_action_to_raw(const struct ratbag_button_action *action)
|
||||
{
|
||||
struct logitech_g600_button_mapping *mapping;
|
||||
|
||||
ARRAY_FOR_EACH(logitech_g600_button_mapping, mapping) {
|
||||
if (ratbag_button_action_match(&mapping->action, action))
|
||||
return mapping->raw;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
logitech_g600_get_active_profile_and_resolution(struct ratbag_device *device)
|
||||
{
|
||||
struct ratbag_profile *profile;
|
||||
struct logitech_g600_active_profile_report buf;
|
||||
int ret;
|
||||
|
||||
ret = ratbag_hidraw_raw_request(device, LOGITECH_G600_REPORT_ID_GET_ACTIVE,
|
||||
(uint8_t*)&buf, sizeof(buf),
|
||||
HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (ret != sizeof(buf))
|
||||
return -EIO;
|
||||
|
||||
list_for_each(profile, &device->profiles, link) {
|
||||
struct ratbag_resolution *resolution;
|
||||
|
||||
if (profile->index != buf.profile)
|
||||
continue;
|
||||
|
||||
profile->is_active = true;
|
||||
ratbag_profile_for_each_resolution(profile, resolution) {
|
||||
resolution->is_active = resolution->index == buf.resolution;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
logitech_g600_set_current_resolution(struct ratbag_device *device, unsigned int index)
|
||||
{
|
||||
uint8_t buf[] = {LOGITECH_G600_REPORT_ID_SET_ACTIVE, 0x40 | (index << 1), 0x00, 0x00};
|
||||
int ret;
|
||||
|
||||
log_debug(device->ratbag, "Setting active resolution to %d\n", index);
|
||||
|
||||
if (index >= LOGITECH_G600_NUM_DPI)
|
||||
return -EINVAL;
|
||||
|
||||
ret = ratbag_hidraw_raw_request(device, buf[0], buf, sizeof(buf),
|
||||
HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
|
||||
|
||||
return ret == sizeof(buf) ? 0 : ret;
|
||||
}
|
||||
|
||||
static int
|
||||
logitech_g600_set_active_profile(struct ratbag_device *device, unsigned int index)
|
||||
{
|
||||
struct ratbag_profile *profile;
|
||||
uint8_t buf[] = {LOGITECH_G600_REPORT_ID_SET_ACTIVE, 0x80 | (index << 4), 0x00, 0x00};
|
||||
int ret, active_resolution = 0;
|
||||
|
||||
if (index >= LOGITECH_G600_NUM_PROFILES)
|
||||
return -EINVAL;
|
||||
|
||||
ret = ratbag_hidraw_raw_request(device, buf[0], buf, sizeof(buf),
|
||||
HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
|
||||
|
||||
if (ret != sizeof(buf))
|
||||
return ret;
|
||||
|
||||
/* Update the active resolution. After profile change the default is used. */
|
||||
list_for_each(profile, &device->profiles, link) {
|
||||
struct ratbag_resolution *resolution;
|
||||
|
||||
if (profile->index != index)
|
||||
continue;
|
||||
|
||||
ratbag_profile_for_each_resolution(profile, resolution) {
|
||||
resolution->is_active = resolution->is_default;
|
||||
|
||||
if (resolution->is_active)
|
||||
active_resolution = resolution->index;
|
||||
}
|
||||
}
|
||||
|
||||
ret = logitech_g600_set_current_resolution(device, active_resolution);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
logitech_g600_read_button(struct ratbag_button *button)
|
||||
{
|
||||
const struct ratbag_button_action *action;
|
||||
struct ratbag_profile *profile = button->profile;
|
||||
struct ratbag_device *device = profile->device;
|
||||
struct logitech_g600_data *drv_data = device->drv_data;
|
||||
struct logitech_g600_profile_data *pdata;
|
||||
struct logitech_g600_profile_report *profile_report;
|
||||
struct logitech_g600_button *button_report;
|
||||
|
||||
pdata = &drv_data->profile_data[profile->index];
|
||||
profile_report = &pdata->report;
|
||||
button_report = &profile_report->buttons[button->index];
|
||||
|
||||
ratbag_button_enable_action_type(button, RATBAG_BUTTON_ACTION_TYPE_BUTTON);
|
||||
ratbag_button_enable_action_type(button, RATBAG_BUTTON_ACTION_TYPE_SPECIAL);
|
||||
ratbag_button_enable_action_type(button, RATBAG_BUTTON_ACTION_TYPE_KEY);
|
||||
ratbag_button_enable_action_type(button, RATBAG_BUTTON_ACTION_TYPE_MACRO);
|
||||
|
||||
button->type = logitech_g600_raw_to_button_type(button->index);
|
||||
|
||||
action = logitech_g600_raw_to_button_action(button_report->code);
|
||||
if (action) {
|
||||
ratbag_button_set_action(button, action);
|
||||
}
|
||||
else if (button_report->code == 0x00 && (button_report->modifier > 0x00 || button_report->key > 0x00))
|
||||
{
|
||||
unsigned int key, modifiers;
|
||||
int rc;
|
||||
|
||||
key = ratbag_hidraw_get_keycode_from_keyboard_usage(device,
|
||||
button_report->key);
|
||||
modifiers = logitech_g600_raw_to_modifiers(button_report->modifier);
|
||||
|
||||
rc = ratbag_button_macro_new_from_keycode(button, key, modifiers);
|
||||
if (rc < 0) {
|
||||
log_error(device->ratbag,
|
||||
"Error while reading button %d\n",
|
||||
button->index);
|
||||
button->action.type = RATBAG_BUTTON_ACTION_TYPE_NONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
logitech_g600_read_led(struct ratbag_led *led)
|
||||
{
|
||||
struct ratbag_profile *profile = led->profile;
|
||||
struct ratbag_device *device = profile->device;
|
||||
struct logitech_g600_data *drv_data = device->drv_data;
|
||||
struct logitech_g600_profile_data *pdata;
|
||||
struct logitech_g600_profile_report *report;
|
||||
|
||||
pdata = &drv_data->profile_data[profile->index];
|
||||
report = &pdata->report;
|
||||
|
||||
led->type = RATBAG_LED_TYPE_SIDE;
|
||||
led->colordepth = RATBAG_LED_COLORDEPTH_RGB_888;
|
||||
ratbag_led_set_mode_capability(led, RATBAG_LED_OFF);
|
||||
ratbag_led_set_mode_capability(led, RATBAG_LED_ON);
|
||||
ratbag_led_set_mode_capability(led, RATBAG_LED_BREATHING);
|
||||
ratbag_led_set_mode_capability(led, RATBAG_LED_CYCLE);
|
||||
|
||||
switch (report->led_effect) {
|
||||
case LOGITECH_G600_LED_SOLID:
|
||||
led->mode = RATBAG_LED_ON;
|
||||
break;
|
||||
case LOGITECH_G600_LED_BREATHE:
|
||||
led->mode = RATBAG_LED_BREATHING;
|
||||
led->ms = report->led_duration * 1000;
|
||||
break;
|
||||
case LOGITECH_G600_LED_CYCLE:
|
||||
led->mode = RATBAG_LED_CYCLE;
|
||||
led->ms = report->led_duration * 1000;
|
||||
break;
|
||||
}
|
||||
led->color.red = report->led_red;
|
||||
led->color.green = report->led_green;
|
||||
led->color.blue = report->led_blue;
|
||||
}
|
||||
|
||||
static void
|
||||
logitech_g600_read_profile(struct ratbag_profile *profile)
|
||||
{
|
||||
struct ratbag_device *device = profile->device;
|
||||
struct logitech_g600_data *drv_data = device->drv_data;
|
||||
struct logitech_g600_profile_data *pdata;
|
||||
struct logitech_g600_profile_report *report;
|
||||
struct ratbag_resolution *resolution;
|
||||
unsigned int report_rates[] = { 125, 142, 166, 200, 250, 333, 500, 1000 };
|
||||
uint8_t report_id;
|
||||
int rc;
|
||||
struct ratbag_button *button;
|
||||
struct ratbag_led *led;
|
||||
|
||||
assert(profile->index < LOGITECH_G600_NUM_PROFILES);
|
||||
|
||||
pdata = &drv_data->profile_data[profile->index];
|
||||
report = &pdata->report;
|
||||
|
||||
switch (profile->index) {
|
||||
case 0: report_id = LOGITECH_G600_REPORT_ID_PROFILE_0; break;
|
||||
case 1: report_id = LOGITECH_G600_REPORT_ID_PROFILE_1; break;
|
||||
case 2: report_id = LOGITECH_G600_REPORT_ID_PROFILE_2; break;
|
||||
}
|
||||
|
||||
rc = ratbag_hidraw_raw_request(device, report_id,
|
||||
(uint8_t*)report,
|
||||
sizeof(*report),
|
||||
HID_FEATURE_REPORT,
|
||||
HID_REQ_GET_REPORT);
|
||||
|
||||
if (rc < (int)sizeof(*report)) {
|
||||
log_error(device->ratbag,
|
||||
"Error while requesting profile: %d\n", rc);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
ratbag_profile_for_each_resolution(profile, resolution) {
|
||||
resolution->dpi_x = report->dpi[resolution->index] * 50;
|
||||
resolution->dpi_y = report->dpi[resolution->index] * 50;
|
||||
resolution->hz = 1000 / (report->frequency + 1);
|
||||
resolution->is_default = report->dpi_default - 1U == resolution->index;
|
||||
resolution->is_active = resolution->is_default;
|
||||
|
||||
ratbag_resolution_set_dpi_list_from_range(resolution,
|
||||
LOGITECH_G600_DPI_MIN,
|
||||
LOGITECH_G600_DPI_MAX);
|
||||
ratbag_resolution_set_report_rate_list(resolution, report_rates,
|
||||
ARRAY_LENGTH(report_rates));
|
||||
}
|
||||
|
||||
ratbag_profile_for_each_button(profile, button)
|
||||
logitech_g600_read_button(button);
|
||||
|
||||
ratbag_profile_for_each_led(profile, led)
|
||||
logitech_g600_read_led(led);
|
||||
|
||||
log_debug(device->ratbag, "Unknown data in profile %d\n", profile->index);
|
||||
log_buf_debug(device->ratbag, " profile->unknown1: ",
|
||||
report->unknown1, 5);
|
||||
log_buf_debug(device->ratbag, " profile->unknown2: ",
|
||||
report->unknown2, 13);
|
||||
}
|
||||
|
||||
static int
|
||||
logitech_g600_test_hidraw(struct ratbag_device *device)
|
||||
{
|
||||
return ratbag_hidraw_has_report(device, LOGITECH_G600_REPORT_ID_GET_ACTIVE);
|
||||
}
|
||||
|
||||
static int
|
||||
logitech_g600_probe(struct ratbag_device *device)
|
||||
{
|
||||
int rc;
|
||||
struct logitech_g600_data *drv_data = NULL;
|
||||
struct ratbag_profile *profile;
|
||||
|
||||
rc = ratbag_find_hidraw(device, logitech_g600_test_hidraw);
|
||||
if (rc)
|
||||
goto err;
|
||||
|
||||
drv_data = zalloc(sizeof(*drv_data));
|
||||
ratbag_set_drv_data(device, drv_data);
|
||||
|
||||
ratbag_device_init_profiles(device,
|
||||
LOGITECH_G600_NUM_PROFILES,
|
||||
LOGITECH_G600_NUM_DPI,
|
||||
LOGITECH_G600_NUM_BUTTONS,
|
||||
LOGITECH_G600_NUM_LED);
|
||||
|
||||
ratbag_device_for_each_profile(device, profile)
|
||||
logitech_g600_read_profile(profile);
|
||||
|
||||
ratbag_device_set_capability(device, RATBAG_DEVICE_CAP_RESOLUTION);
|
||||
ratbag_device_set_capability(device, RATBAG_DEVICE_CAP_SWITCHABLE_RESOLUTION);
|
||||
ratbag_device_set_capability(device, RATBAG_DEVICE_CAP_PROFILE);
|
||||
ratbag_device_set_capability(device, RATBAG_DEVICE_CAP_SWITCHABLE_PROFILE);
|
||||
ratbag_device_set_capability(device, RATBAG_DEVICE_CAP_BUTTON);
|
||||
ratbag_device_set_capability(device, RATBAG_DEVICE_CAP_BUTTON_KEY);
|
||||
ratbag_device_set_capability(device, RATBAG_DEVICE_CAP_BUTTON_MACROS);
|
||||
|
||||
rc = logitech_g600_get_active_profile_and_resolution(device);
|
||||
|
||||
if (rc < 0) {
|
||||
log_error(device->ratbag,
|
||||
"Can't talk to the mouse: '%s' (%d)\n",
|
||||
strerror(-rc),
|
||||
rc);
|
||||
rc = -ENODEV;
|
||||
goto err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
free(drv_data);
|
||||
ratbag_set_drv_data(device, NULL);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int
|
||||
logitech_g600_write_profile(struct ratbag_profile *profile)
|
||||
{
|
||||
struct ratbag_device *device = profile->device;
|
||||
struct logitech_g600_data *drv_data = device->drv_data;
|
||||
struct logitech_g600_profile_data *pdata;
|
||||
struct logitech_g600_profile_report *report;
|
||||
struct ratbag_resolution *resolution;
|
||||
struct ratbag_button *button;
|
||||
struct ratbag_led *led;
|
||||
|
||||
uint8_t *buf;
|
||||
int rc, active_resolution = 0;
|
||||
|
||||
pdata = &drv_data->profile_data[profile->index];
|
||||
report = &pdata->report;
|
||||
|
||||
ratbag_profile_for_each_resolution(profile, resolution) {
|
||||
report->dpi[resolution->index] = resolution->dpi_x / 50;
|
||||
|
||||
if (resolution->is_default)
|
||||
report->dpi_default = resolution->index + 1;
|
||||
|
||||
if (profile->is_active && resolution->is_active)
|
||||
active_resolution = resolution->index;
|
||||
|
||||
/* The same hz is used for all resolutions */
|
||||
if (resolution->index == 0)
|
||||
report->frequency = (1000 / resolution->hz) - 1;
|
||||
}
|
||||
|
||||
list_for_each(button, &profile->buttons, link) {
|
||||
struct ratbag_button_action *action = &button->action;
|
||||
struct logitech_g600_button *raw_button;
|
||||
|
||||
raw_button = &report->buttons[button->index];
|
||||
|
||||
raw_button->code = logitech_g600_button_action_to_raw(action);
|
||||
raw_button->modifier = 0x00;
|
||||
raw_button->key = 0x00;
|
||||
|
||||
if (action->type == RATBAG_BUTTON_ACTION_TYPE_MACRO) {
|
||||
unsigned int key, modifiers;
|
||||
|
||||
rc = ratbag_action_keycode_from_macro(action,
|
||||
&key,
|
||||
&modifiers);
|
||||
if (rc < 0) {
|
||||
log_error(device->ratbag,
|
||||
"Error while writing macro for button %d\n",
|
||||
button->index);
|
||||
}
|
||||
|
||||
raw_button->key = ratbag_hidraw_get_keyboard_usage_from_keycode(
|
||||
device, key);
|
||||
raw_button->modifier = logitech_g600_modifier_to_raw(modifiers);
|
||||
}
|
||||
}
|
||||
|
||||
list_for_each(led, &profile->leds, link) {
|
||||
report->led_red = led->color.red;
|
||||
report->led_green = led->color.green;
|
||||
report->led_blue = led->color.blue;
|
||||
|
||||
switch (led->mode) {
|
||||
case RATBAG_LED_ON:
|
||||
report->led_effect = LOGITECH_G600_LED_SOLID;
|
||||
break;
|
||||
case RATBAG_LED_OFF:
|
||||
report->led_effect = LOGITECH_G600_LED_SOLID;
|
||||
report->led_red = 0x00;
|
||||
report->led_green = 0x00;
|
||||
report->led_blue = 0x00;
|
||||
break;
|
||||
case RATBAG_LED_BREATHING:
|
||||
report->led_effect = LOGITECH_G600_LED_BREATHE;
|
||||
report->led_duration = led->ms / 1000;
|
||||
break;
|
||||
case RATBAG_LED_CYCLE:
|
||||
report->led_effect = LOGITECH_G600_LED_CYCLE;
|
||||
report->led_duration = led->ms / 1000;
|
||||
break;
|
||||
}
|
||||
|
||||
if (report->led_duration > 0x0f)
|
||||
report->led_duration = 0x0f;
|
||||
}
|
||||
|
||||
buf = (uint8_t*)report;
|
||||
|
||||
rc = ratbag_hidraw_raw_request(device, report->id,
|
||||
buf,
|
||||
sizeof(*report),
|
||||
HID_FEATURE_REPORT,
|
||||
HID_REQ_SET_REPORT);
|
||||
|
||||
if (rc < (int)sizeof(*report)) {
|
||||
log_error(device->ratbag,
|
||||
"Error while writing profile: %d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (profile->is_active) {
|
||||
rc = logitech_g600_set_current_resolution(device, active_resolution);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
logitech_g600_commit(struct ratbag_device *device)
|
||||
{
|
||||
struct ratbag_profile *profile;
|
||||
int rc = 0;
|
||||
|
||||
list_for_each(profile, &device->profiles, link) {
|
||||
if (!profile->dirty)
|
||||
continue;
|
||||
|
||||
log_debug(device->ratbag,
|
||||
"Profile %d changed, rewriting\n", profile->index);
|
||||
|
||||
rc = logitech_g600_write_profile(profile);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
logitech_g600_remove(struct ratbag_device *device)
|
||||
{
|
||||
ratbag_close_hidraw(device);
|
||||
free(ratbag_get_drv_data(device));
|
||||
}
|
||||
|
||||
struct ratbag_driver logitech_g600_driver = {
|
||||
.name = "Logitech G600",
|
||||
.id = "logitech_g600",
|
||||
.probe = logitech_g600_probe,
|
||||
.remove = logitech_g600_remove,
|
||||
.commit = logitech_g600_commit,
|
||||
.set_active_profile = logitech_g600_set_active_profile,
|
||||
};
|
||||
@@ -37,6 +37,8 @@
|
||||
|
||||
#define STEELSERIES_NUM_PROFILES 1
|
||||
#define STEELSERIES_NUM_DPI 2
|
||||
#define STEELSERIES_INPUT_ENDPOINT 0
|
||||
#define STEELSERIES_INPUT_HIDRAW 1
|
||||
|
||||
/* not sure these two are used for */
|
||||
#define STEELSERIES_REPORT_ID_1 0x01
|
||||
@@ -48,6 +50,7 @@
|
||||
|
||||
#define STEELSERIES_ID_DPI_SHORT 0x03
|
||||
#define STEELSERIES_ID_REPORT_RATE_SHORT 0x04
|
||||
#define STEELSERIES_ID_LED_INTENSITY_SHORT 0x05
|
||||
#define STEELSERIES_ID_LED_EFFECT_SHORT 0x07
|
||||
#define STEELSERIES_ID_LED_COLOR_SHORT 0x08
|
||||
#define STEELSERIES_ID_SAVE_SHORT 0x09
|
||||
@@ -57,14 +60,37 @@
|
||||
#define STEELSERIES_ID_REPORT_RATE 0x54
|
||||
#define STEELSERIES_ID_LED 0x5b
|
||||
#define STEELSERIES_ID_SAVE 0x59
|
||||
#define STEELSERIES_ID_FIRMWARE 0x90
|
||||
#define STEELSERIES_ID_SETTTINGS 0x92
|
||||
|
||||
#define STEELSERIES_BUTTON_OFF 0x00
|
||||
#define STEELSERIES_BUTTON_RES_CYCLE 0x30
|
||||
#define STEELSERIES_BUTTON_WHEEL_UP 0x31
|
||||
#define STEELSERIES_BUTTON_WHEEL_DOWN 0x32
|
||||
#define STEELSERIES_BUTTON_KEY 0x10
|
||||
#define STEELSERIES_BUTTON_KBD 0x51
|
||||
#define STEELSERIES_BUTTON_CONSUMER 0x61
|
||||
|
||||
struct steelseries_data {
|
||||
int firmware_major;
|
||||
int firmware_minor;
|
||||
};
|
||||
|
||||
struct steelseries_point {
|
||||
struct list link;
|
||||
|
||||
struct ratbag_color color; /* point color */
|
||||
uint8_t pos; /* relative position in the cycle */
|
||||
};
|
||||
|
||||
struct steelseries_led_cycle {
|
||||
uint8_t led_id; /* led id */
|
||||
uint16_t duration; /* cycle duration */
|
||||
bool repeat; /* if the cycle restarts automatically */
|
||||
uint8_t trigger_buttons; /* trigger button combination */
|
||||
struct list points; /* colors in the cycle */
|
||||
};
|
||||
|
||||
static int
|
||||
steelseries_test_hidraw(struct ratbag_device *device)
|
||||
{
|
||||
@@ -120,14 +146,88 @@ button_defaults_for_layout(struct ratbag_button *button, int button_count)
|
||||
ratbag_button_set_action(button, &button_actions[button->index]);
|
||||
}
|
||||
|
||||
static int
|
||||
steelseries_get_firmware_version(struct ratbag_device *device)
|
||||
{
|
||||
struct steelseries_data *drv_data = device->drv_data;
|
||||
int device_version = ratbag_device_data_steelseries_get_device_version(device->data);
|
||||
size_t buf_len = STEELSERIES_REPORT_SIZE;
|
||||
uint8_t buf[STEELSERIES_REPORT_SIZE] = {0};
|
||||
int ret;
|
||||
|
||||
if (device_version == 1)
|
||||
return 0;
|
||||
|
||||
buf[0] = STEELSERIES_ID_FIRMWARE;
|
||||
msleep(10);
|
||||
ret = ratbag_hidraw_output_report(device, buf, buf_len);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = ratbag_hidraw_read_input_report_index(device, buf, buf_len, STEELSERIES_INPUT_HIDRAW);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
drv_data->firmware_major = buf[1];
|
||||
drv_data->firmware_minor = buf[0];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
steelseries_read_settings(struct ratbag_device *device)
|
||||
{
|
||||
int device_version = ratbag_device_data_steelseries_get_device_version(device->data);
|
||||
struct ratbag_profile *profile = NULL;
|
||||
struct ratbag_resolution *resolution;
|
||||
struct ratbag_led *led;
|
||||
|
||||
size_t buf_len = STEELSERIES_REPORT_SIZE;
|
||||
uint8_t buf[STEELSERIES_REPORT_SIZE] = {0};
|
||||
int ret;
|
||||
unsigned int active_resolution;
|
||||
|
||||
if (device_version == 1)
|
||||
return 0;
|
||||
|
||||
buf[0] = STEELSERIES_ID_SETTTINGS;
|
||||
msleep(10);
|
||||
ret = ratbag_hidraw_output_report(device, buf, buf_len);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = ratbag_hidraw_read_input_report_index(device, buf, buf_len, STEELSERIES_INPUT_HIDRAW);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
active_resolution = buf[1] - 1;
|
||||
ratbag_device_for_each_profile(device, profile) {
|
||||
ratbag_profile_for_each_resolution(profile, resolution) {
|
||||
resolution->is_active = resolution->index == active_resolution;
|
||||
|
||||
resolution->dpi_x = 100 * (1 + buf[2 + resolution->index*2]);
|
||||
resolution->dpi_y = resolution->dpi_x;
|
||||
}
|
||||
|
||||
ratbag_profile_for_each_led(profile, led) {
|
||||
led->color.red = buf[6 + led->index * 3];
|
||||
led->color.green = buf[7 + led->index * 3];
|
||||
led->color.blue = buf[8 + led->index * 3];
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
steelseries_probe(struct ratbag_device *device)
|
||||
{
|
||||
struct steelseries_data *drv_data = NULL;
|
||||
struct ratbag_profile *profile = NULL;
|
||||
struct ratbag_resolution *resolution;
|
||||
struct ratbag_button *button;
|
||||
struct ratbag_led *led;
|
||||
int rc, button_count, led_count, device_version;
|
||||
int rc, button_count, led_count, device_version, mono_led, short_button;
|
||||
_cleanup_(dpi_list_freep) struct dpi_list *dpilist = NULL;
|
||||
_cleanup_(freep) struct dpi_range *dpirange = NULL;
|
||||
|
||||
@@ -137,11 +237,19 @@ steelseries_probe(struct ratbag_device *device)
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = ratbag_open_hidraw_index(device,
|
||||
STEELSERIES_INPUT_ENDPOINT,
|
||||
STEELSERIES_INPUT_HIDRAW);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
device_version = ratbag_device_data_steelseries_get_device_version(device->data);
|
||||
button_count = ratbag_device_data_steelseries_get_button_count(device->data);
|
||||
led_count = ratbag_device_data_steelseries_get_led_count(device->data);
|
||||
dpirange = ratbag_device_data_steelseries_get_dpi_range(device->data);
|
||||
dpilist = ratbag_device_data_steelseries_get_dpi_list(device->data);
|
||||
mono_led = ratbag_device_data_steelseries_get_mono_led(device->data);
|
||||
short_button = ratbag_device_data_steelseries_get_short_button(device->data);
|
||||
|
||||
ratbag_device_init_profiles(device,
|
||||
STEELSERIES_NUM_PROFILES,
|
||||
@@ -154,7 +262,9 @@ steelseries_probe(struct ratbag_device *device)
|
||||
/* set these caps manually as they are not assumed with only 1 profile */
|
||||
ratbag_device_set_capability(device, RATBAG_DEVICE_CAP_BUTTON);
|
||||
ratbag_device_set_capability(device, RATBAG_DEVICE_CAP_BUTTON_KEY);
|
||||
ratbag_device_set_capability(device, RATBAG_DEVICE_CAP_BUTTON_MACROS);
|
||||
if (short_button == 0) {
|
||||
ratbag_device_set_capability(device, RATBAG_DEVICE_CAP_BUTTON_MACROS);
|
||||
}
|
||||
}
|
||||
|
||||
ratbag_device_unset_capability(device, RATBAG_DEVICE_CAP_QUERY_CONFIGURATION);
|
||||
@@ -193,7 +303,9 @@ steelseries_probe(struct ratbag_device *device)
|
||||
ratbag_button_enable_action_type(button, RATBAG_BUTTON_ACTION_TYPE_BUTTON);
|
||||
ratbag_button_enable_action_type(button, RATBAG_BUTTON_ACTION_TYPE_SPECIAL);
|
||||
ratbag_button_enable_action_type(button, RATBAG_BUTTON_ACTION_TYPE_KEY);
|
||||
ratbag_button_enable_action_type(button, RATBAG_BUTTON_ACTION_TYPE_MACRO);
|
||||
if (short_button == 0) {
|
||||
ratbag_button_enable_action_type(button, RATBAG_BUTTON_ACTION_TYPE_MACRO);
|
||||
}
|
||||
|
||||
button_defaults_for_layout(button, button_count);
|
||||
}
|
||||
@@ -201,10 +313,15 @@ steelseries_probe(struct ratbag_device *device)
|
||||
ratbag_profile_for_each_led(profile, led) {
|
||||
led->type = led->index == 0 ? RATBAG_LED_TYPE_LOGO : RATBAG_LED_TYPE_WHEEL;
|
||||
led->mode = RATBAG_LED_ON;
|
||||
led->colordepth = RATBAG_LED_COLORDEPTH_RGB_888;
|
||||
led->color.red = 0;
|
||||
led->color.green = 0;
|
||||
led->color.blue = 255;
|
||||
if (mono_led) {
|
||||
led->colordepth = RATBAG_LED_COLORDEPTH_MONOCHROME;
|
||||
led->brightness = 255;
|
||||
} else {
|
||||
led->colordepth = RATBAG_LED_COLORDEPTH_RGB_888;
|
||||
led->color.red = 0;
|
||||
led->color.green = 0;
|
||||
led->color.blue = 255;
|
||||
}
|
||||
ratbag_led_set_mode_capability(led, RATBAG_LED_OFF);
|
||||
ratbag_led_set_mode_capability(led, RATBAG_LED_ON);
|
||||
ratbag_led_set_mode_capability(led, RATBAG_LED_BREATHING);
|
||||
@@ -213,6 +330,16 @@ steelseries_probe(struct ratbag_device *device)
|
||||
}
|
||||
}
|
||||
|
||||
drv_data = zalloc(sizeof(*drv_data));
|
||||
ratbag_set_drv_data(device, drv_data);
|
||||
|
||||
steelseries_get_firmware_version(device);
|
||||
log_debug(device->ratbag, "SteelSeries firmware version %d.%d\n",
|
||||
drv_data->firmware_major,
|
||||
drv_data->firmware_minor);
|
||||
|
||||
steelseries_read_settings(device);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -295,13 +422,20 @@ static int
|
||||
steelseries_write_buttons(struct ratbag_profile *profile)
|
||||
{
|
||||
struct ratbag_device *device = profile->device;
|
||||
uint8_t buf[STEELSERIES_REPORT_LONG_SIZE] = {0};
|
||||
struct ratbag_button *button;
|
||||
int ret;
|
||||
|
||||
if (ratbag_device_data_steelseries_get_macro_length(device->data) == 0)
|
||||
return 0;
|
||||
|
||||
int short_button = ratbag_device_data_steelseries_get_short_button(device->data);
|
||||
int button_size = (short_button == 0) ? 5 : 3;
|
||||
int report_size = (short_button == 0) ? STEELSERIES_REPORT_LONG_SIZE : STEELSERIES_REPORT_SIZE_SHORT;
|
||||
int max_modifiers = (short_button == 0) ? 3 : 0;
|
||||
|
||||
uint8_t buf[report_size];
|
||||
memset(buf, 0, report_size);
|
||||
|
||||
buf[0] = STEELSERIES_ID_BUTTONS;
|
||||
|
||||
ratbag_profile_for_each_button(profile, button) {
|
||||
@@ -310,8 +444,8 @@ steelseries_write_buttons(struct ratbag_profile *profile)
|
||||
unsigned int key, modifiers;
|
||||
int idx;
|
||||
|
||||
/* Each button takes up 5 bytes starting from index 2 */
|
||||
idx = 2 + button->index * 5;
|
||||
/* Each button takes up 3 or 5 bytes starting from index 2 */
|
||||
idx = 2 + button->index * button_size;
|
||||
|
||||
switch (action->type) {
|
||||
case RATBAG_BUTTON_ACTION_TYPE_BUTTON:
|
||||
@@ -322,34 +456,38 @@ steelseries_write_buttons(struct ratbag_profile *profile)
|
||||
ratbag_action_keycode_from_macro(action, &key, &modifiers);
|
||||
|
||||
/* There is only space for 3 modifiers */
|
||||
if (__builtin_popcount(modifiers > 3)) {
|
||||
log_debug(device->ratbag,
|
||||
"Too many modifiers in macro for button %d\n",
|
||||
button->index);
|
||||
if (__builtin_popcount(modifiers) > max_modifiers) {
|
||||
log_error(device->ratbag,
|
||||
"Too many modifiers in macro for button %d (maximum %d)\n",
|
||||
button->index, max_modifiers);
|
||||
break;
|
||||
}
|
||||
|
||||
code = ratbag_hidraw_get_keyboard_usage_from_keycode(
|
||||
device, key);
|
||||
if (code) {
|
||||
buf[idx] = STEELSERIES_BUTTON_KBD;
|
||||
if (short_button) {
|
||||
buf[idx] = STEELSERIES_BUTTON_KEY;
|
||||
} else {
|
||||
buf[idx] = STEELSERIES_BUTTON_KBD;
|
||||
|
||||
if (modifiers & MODIFIER_LEFTCTRL)
|
||||
buf[++idx] = 0xE0;
|
||||
if (modifiers & MODIFIER_LEFTSHIFT)
|
||||
buf[++idx] = 0xE1;
|
||||
if (modifiers & MODIFIER_LEFTALT)
|
||||
buf[++idx] = 0xE2;
|
||||
if (modifiers & MODIFIER_LEFTMETA)
|
||||
buf[++idx] = 0xE3;
|
||||
if (modifiers & MODIFIER_RIGHTCTRL)
|
||||
buf[++idx] = 0xE4;
|
||||
if (modifiers & MODIFIER_RIGHTSHIFT)
|
||||
buf[++idx] = 0xE5;
|
||||
if (modifiers & MODIFIER_RIGHTALT)
|
||||
buf[++idx] = 0xE6;
|
||||
if (modifiers & MODIFIER_RIGHTMETA)
|
||||
buf[++idx] = 0xE7;
|
||||
if (modifiers & MODIFIER_LEFTCTRL)
|
||||
buf[++idx] = 0xE0;
|
||||
if (modifiers & MODIFIER_LEFTSHIFT)
|
||||
buf[++idx] = 0xE1;
|
||||
if (modifiers & MODIFIER_LEFTALT)
|
||||
buf[++idx] = 0xE2;
|
||||
if (modifiers & MODIFIER_LEFTMETA)
|
||||
buf[++idx] = 0xE3;
|
||||
if (modifiers & MODIFIER_RIGHTCTRL)
|
||||
buf[++idx] = 0xE4;
|
||||
if (modifiers & MODIFIER_RIGHTSHIFT)
|
||||
buf[++idx] = 0xE5;
|
||||
if (modifiers & MODIFIER_RIGHTALT)
|
||||
buf[++idx] = 0xE6;
|
||||
if (modifiers & MODIFIER_RIGHTMETA)
|
||||
buf[++idx] = 0xE7;
|
||||
}
|
||||
|
||||
buf[idx + 1] = code;
|
||||
} else {
|
||||
@@ -421,11 +559,24 @@ steelseries_write_led_v1(struct ratbag_led *led)
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
buf[0] = STEELSERIES_ID_LED_COLOR_SHORT;
|
||||
buf[1] = led->index + 1;
|
||||
buf[2] = led->color.red;
|
||||
buf[3] = led->color.green;
|
||||
buf[4] = led->color.blue;
|
||||
int mono_led = ratbag_device_data_steelseries_get_mono_led(device->data);
|
||||
|
||||
if (mono_led) {
|
||||
buf[0] = STEELSERIES_ID_LED_INTENSITY_SHORT;
|
||||
buf[1] = led->index + 1;
|
||||
if (led->mode == RATBAG_LED_OFF || led->brightness == 0) {
|
||||
buf[2] = 1;
|
||||
} else {
|
||||
//split the brightness into roughly 3 equal intensities
|
||||
buf[2] = (led->brightness / 86) + 2;
|
||||
}
|
||||
} else {
|
||||
buf[0] = STEELSERIES_ID_LED_COLOR_SHORT;
|
||||
buf[1] = led->index + 1;
|
||||
buf[2] = led->color.red;
|
||||
buf[3] = led->color.green;
|
||||
buf[4] = led->color.blue;
|
||||
}
|
||||
|
||||
msleep(10);
|
||||
ret = ratbag_hidraw_output_report(device, buf, sizeof(buf));
|
||||
@@ -435,103 +586,134 @@ steelseries_write_led_v1(struct ratbag_led *led)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
create_cycle(struct steelseries_led_cycle *cycle)
|
||||
{
|
||||
cycle->led_id = 0x00;
|
||||
cycle->duration = 5000;
|
||||
cycle->repeat = true;
|
||||
cycle->trigger_buttons = 0x00;
|
||||
|
||||
list_init(&cycle->points);
|
||||
}
|
||||
|
||||
static void
|
||||
construct_cycle_buffer(struct steelseries_led_cycle *cycle, uint8_t *buf, uint8_t buf_size)
|
||||
{
|
||||
struct steelseries_point *point;
|
||||
uint16_t duration;
|
||||
uint8_t npoints = 0;
|
||||
uint16_t cycle_size = 0;
|
||||
|
||||
buf[0] = STEELSERIES_ID_LED;
|
||||
buf[2] = cycle->led_id;
|
||||
|
||||
if (!cycle->repeat)
|
||||
buf[19] = 0x01;
|
||||
|
||||
buf[23] = cycle->trigger_buttons;
|
||||
|
||||
list_for_each(point, &cycle->points, link) {
|
||||
if(npoints == 0){
|
||||
/* this is not a mistake,
|
||||
we need to write the first
|
||||
point to 28,29,30 */
|
||||
buf[28] = point->color.red;
|
||||
buf[29] = point->color.green;
|
||||
buf[30] = point->color.blue;
|
||||
}
|
||||
|
||||
cycle_size += point->pos;
|
||||
assert(cycle_size < 256);
|
||||
assert(34 + npoints*4 <= buf_size);
|
||||
|
||||
buf[31 + npoints*4] = point->color.red;
|
||||
buf[32 + npoints*4] = point->color.green;
|
||||
buf[33 + npoints*4] = point->color.blue;
|
||||
buf[34 + npoints*4] = point->pos;
|
||||
|
||||
npoints++;
|
||||
}
|
||||
|
||||
buf[27] = npoints;
|
||||
|
||||
/* this seems to be the minimum allowed */
|
||||
duration = max(buf[27] * 330, cycle->duration);
|
||||
|
||||
hidpp_set_unaligned_le_u16(&buf[3], duration);
|
||||
}
|
||||
|
||||
static int
|
||||
steelseries_write_led_v2(struct ratbag_led *led)
|
||||
{
|
||||
struct ratbag_device *device = led->profile->device;
|
||||
uint8_t buf[STEELSERIES_REPORT_SIZE] = {0};
|
||||
uint16_t duration, min_duration;
|
||||
int ret;
|
||||
|
||||
buf[0] = STEELSERIES_ID_LED;
|
||||
buf[2] = led->index;
|
||||
struct steelseries_led_cycle cycle;
|
||||
struct steelseries_point point[4];
|
||||
|
||||
/* not sure if these two are needed */
|
||||
buf[15] = 0x01;
|
||||
buf[17] = 0x01;
|
||||
const struct ratbag_color black = { 0x00 };
|
||||
const struct ratbag_color red = { 0xFF, 0x00, 0x00 };
|
||||
const struct ratbag_color green = { 0x00, 0xFF, 0x00 };
|
||||
const struct ratbag_color blue = { 0x00, 0x00, 0xFF };
|
||||
|
||||
create_cycle(&cycle);
|
||||
cycle.led_id = led->index;
|
||||
|
||||
switch(led->mode) {
|
||||
case RATBAG_LED_OFF:
|
||||
buf[19] = 0x01;
|
||||
buf[27] = 0x01;
|
||||
buf[28] = buf[31] = 0x00;
|
||||
buf[29] = buf[32] = 0x00;
|
||||
buf[30] = buf[33] = 0x00;
|
||||
/* not sure why the duration is set for the steady color or why
|
||||
it is different for the two LEDs */
|
||||
duration = led->index == 0 ? 10000 : 5000; /* 0x1027 or 0x8813 */
|
||||
point[0].color = black;
|
||||
point[0].pos = 0x00;
|
||||
|
||||
list_append(&cycle.points, &point[0].link);
|
||||
break;
|
||||
case RATBAG_LED_ON:
|
||||
buf[19] = 0x01;
|
||||
buf[27] = 0x01;
|
||||
buf[28] = buf[31] = led->color.red;
|
||||
buf[29] = buf[32] = led->color.green;
|
||||
buf[30] = buf[33] = led->color.blue;
|
||||
point[0].color = led->color;
|
||||
|
||||
/* not sure why the duration is set for the steady color or why
|
||||
it is different for the two LEDs */
|
||||
duration = led->index == 0 ? 10000 : 5000; /* 0x1027 or 0x8813 */
|
||||
list_append(&cycle.points, &point[0].link);
|
||||
break;
|
||||
case RATBAG_LED_CYCLE:
|
||||
buf[27] = 0x04; /* number of steps in cycle */
|
||||
case RATBAG_LED_CYCLE:
|
||||
point[0].color = red;
|
||||
point[0].pos = 0x00;
|
||||
|
||||
/* start color */
|
||||
buf[28] = buf[31] = 0xFF;
|
||||
buf[29] = buf[32] = 0x00;
|
||||
buf[30] = buf[33] = 0x00;
|
||||
point[1].color = green;
|
||||
point[1].pos = 0x55;
|
||||
|
||||
/* Cycle to green */
|
||||
buf[35] = 0x00;
|
||||
buf[36] = 0xFF;
|
||||
buf[37] = 0x00;
|
||||
buf[38] = 0x54; /* normalized time share of animation */
|
||||
point[2].color = blue;
|
||||
point[2].pos = 0x55;
|
||||
|
||||
/* Cycle to blue */
|
||||
buf[39] = 0x00;
|
||||
buf[40] = 0x00;
|
||||
buf[41] = 0xFF;
|
||||
buf[42] = 0x54; /* normalized time share of animation */
|
||||
point[3].color = red;
|
||||
point[3].pos = 0x55;
|
||||
|
||||
/* Cycle to red */
|
||||
buf[43] = 0xFF;
|
||||
buf[44] = 0x00;
|
||||
buf[45] = 0x00;
|
||||
buf[46] = 0x56; /* normalized time share of animation */
|
||||
list_append(&cycle.points, &point[0].link);
|
||||
list_append(&cycle.points, &point[1].link);
|
||||
list_append(&cycle.points, &point[2].link);
|
||||
list_append(&cycle.points, &point[3].link);
|
||||
|
||||
duration = led->ms;
|
||||
cycle.duration = led->ms;
|
||||
break;
|
||||
case RATBAG_LED_BREATHING:
|
||||
buf[27] = 0x03; /* number of steps in cycle */
|
||||
point[0].color = black;
|
||||
point[0].pos = 0x00;
|
||||
|
||||
/* start color */
|
||||
buf[28] = buf[31] = led->color.red;
|
||||
buf[29] = buf[32] = led->color.green;
|
||||
buf[30] = buf[33] = led->color.blue;
|
||||
point[1].color = led->color;
|
||||
point[1].pos = 0x7F;
|
||||
|
||||
/* Cycle to black */
|
||||
buf[35] = 0x00;
|
||||
buf[36] = 0x00;
|
||||
buf[37] = 0x00;
|
||||
buf[38] = 0x7F; /* normalized time share of animation */
|
||||
point[2].color = black;
|
||||
point[2].pos = 0x7F;
|
||||
|
||||
list_append(&cycle.points, &point[0].link);
|
||||
list_append(&cycle.points, &point[1].link);
|
||||
list_append(&cycle.points, &point[2].link);
|
||||
|
||||
/* Cycle to selected color */
|
||||
buf[39] = led->color.red;
|
||||
buf[40] = led->color.green;
|
||||
buf[41] = led->color.blue;
|
||||
buf[42] = 0x7F; /* normalized time share of animation */
|
||||
|
||||
duration = led->ms;
|
||||
cycle.duration = led->ms;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* this seems to be the minimum allowed */
|
||||
min_duration = buf[27] * 330;
|
||||
if (duration < min_duration)
|
||||
duration = min_duration;
|
||||
|
||||
hidpp_set_unaligned_le_u16(&buf[3], duration);
|
||||
construct_cycle_buffer(&cycle, buf, sizeof(buf));
|
||||
|
||||
msleep(10);
|
||||
ret = ratbag_hidraw_output_report(device, buf, sizeof(buf));
|
||||
@@ -658,7 +840,9 @@ steelseries_commit(struct ratbag_device *device)
|
||||
static void
|
||||
steelseries_remove(struct ratbag_device *device)
|
||||
{
|
||||
ratbag_close_hidraw(device);
|
||||
ratbag_close_hidraw_index(device, 0);
|
||||
ratbag_close_hidraw_index(device, 1);
|
||||
free(ratbag_get_drv_data(device));
|
||||
}
|
||||
|
||||
struct ratbag_driver steelseries_driver = {
|
||||
|
||||
@@ -190,7 +190,7 @@ test_read_profile(struct ratbag_profile *profile)
|
||||
r0 = &p0->resolutions[0];
|
||||
|
||||
for (i = 0; i < d->num_resolutions; i++) {
|
||||
_cleanup_resolution_ struct ratbag_resolution *res;
|
||||
_cleanup_resolution_ struct ratbag_resolution *res = NULL;
|
||||
size_t nrates = 0;
|
||||
|
||||
r = &p->resolutions[i];
|
||||
@@ -225,7 +225,7 @@ test_read_profile(struct ratbag_profile *profile)
|
||||
|
||||
/* special case triggered by the test suite when num_resolutions is 0 */
|
||||
if (d->num_resolutions) {
|
||||
_cleanup_resolution_ struct ratbag_resolution *res;
|
||||
_cleanup_resolution_ struct ratbag_resolution *res = NULL;
|
||||
|
||||
res = ratbag_profile_get_resolution(profile, 0);
|
||||
assert(res);
|
||||
|
||||
@@ -2362,7 +2362,7 @@ hidpp20_onboard_profiles_parse(struct hidpp20_device *device,
|
||||
profiles->sector_size,
|
||||
data);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
return rc; // ignore_clang_sa_mem_leak
|
||||
|
||||
crc_valid = hidpp20_onboard_profiles_is_sector_valid(device,
|
||||
profiles->sector_size,
|
||||
|
||||
@@ -195,7 +195,7 @@ lur_receiver_enumerate(struct lur_receiver *lur,
|
||||
dev->present = false;
|
||||
|
||||
for (i = 0; i < MAX_DEVICES; i++) {
|
||||
_cleanup_hidpp10_device_destroy_ struct hidpp10_device *d;
|
||||
_cleanup_hidpp10_device_destroy_ struct hidpp10_device *d = NULL;
|
||||
size_t name_size = 64;
|
||||
char name[name_size];
|
||||
uint8_t interval, type;
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <glib.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "libratbag.h"
|
||||
#include "libratbag-private.h"
|
||||
@@ -47,6 +48,7 @@ enum driver {
|
||||
ETEKCITY,
|
||||
GSKILL,
|
||||
LOGITECH_G300,
|
||||
LOGITECH_G600,
|
||||
STEELSERIES,
|
||||
};
|
||||
|
||||
@@ -71,6 +73,8 @@ struct data_steelseries {
|
||||
struct dpi_list *dpi_list;
|
||||
struct dpi_range *dpi_range;
|
||||
int macro_length;
|
||||
int mono_led;
|
||||
int short_button;
|
||||
};
|
||||
|
||||
struct ratbag_device_data {
|
||||
@@ -174,6 +178,8 @@ init_data_steelseries(struct ratbag *ratbag,
|
||||
data->steelseries.led_count = -1;
|
||||
data->steelseries.dpi_list = NULL;
|
||||
data->steelseries.dpi_range = NULL;
|
||||
data->steelseries.mono_led = 0;
|
||||
data->steelseries.short_button = 0;
|
||||
|
||||
num = g_key_file_get_integer(keyfile, group, "Buttons", &error);
|
||||
if (num != 0 || !error)
|
||||
@@ -210,6 +216,20 @@ init_data_steelseries(struct ratbag *ratbag,
|
||||
data->steelseries.macro_length = num;
|
||||
if (error)
|
||||
g_error_free(error);
|
||||
|
||||
error = NULL;
|
||||
num = g_key_file_get_integer(keyfile, group, "MonoLed", &error);
|
||||
if (num > 0 || !error)
|
||||
data->steelseries.mono_led = num;
|
||||
if (error)
|
||||
g_error_free(error);
|
||||
|
||||
error = NULL;
|
||||
num = g_key_file_get_integer(keyfile, group, "ShortButton", &error);
|
||||
if (num > 0 || !error)
|
||||
data->steelseries.short_button = num;
|
||||
if (error)
|
||||
g_error_free(error);
|
||||
}
|
||||
|
||||
static const struct driver_map {
|
||||
@@ -225,6 +245,7 @@ static const struct driver_map {
|
||||
{ ETEKCITY, "etekcity", NULL},
|
||||
{ GSKILL, "gskill", NULL },
|
||||
{ LOGITECH_G300, "logitech_g300", NULL},
|
||||
{ LOGITECH_G600, "logitech_g600", NULL},
|
||||
{ STEELSERIES, "steelseries", init_data_steelseries },
|
||||
};
|
||||
|
||||
@@ -388,7 +409,7 @@ file_data_matches(struct ratbag *ratbag,
|
||||
data->refcount = 1;
|
||||
data->name = g_key_file_get_string(keyfile, GROUP_DEVICE, "Name", NULL);
|
||||
if (!data->name) {
|
||||
return false;
|
||||
return false; // ignore_clang_sa_mem_leak
|
||||
}
|
||||
|
||||
data->driver = g_key_file_get_string(keyfile, GROUP_DEVICE, "Driver", NULL);
|
||||
@@ -599,3 +620,19 @@ ratbag_device_data_steelseries_get_macro_length(const struct ratbag_device_data
|
||||
|
||||
return data->steelseries.macro_length;
|
||||
}
|
||||
|
||||
int
|
||||
ratbag_device_data_steelseries_get_mono_led(const struct ratbag_device_data *data)
|
||||
{
|
||||
assert(data->drivertype == STEELSERIES);
|
||||
|
||||
return data->steelseries.mono_led;
|
||||
}
|
||||
|
||||
int
|
||||
ratbag_device_data_steelseries_get_short_button(const struct ratbag_device_data *data)
|
||||
{
|
||||
assert(data->drivertype == STEELSERIES);
|
||||
|
||||
return data->steelseries.short_button;
|
||||
}
|
||||
|
||||
@@ -110,3 +110,9 @@ ratbag_device_data_steelseries_get_dpi_range(const struct ratbag_device_data *da
|
||||
|
||||
int
|
||||
ratbag_device_data_steelseries_get_macro_length(const struct ratbag_device_data *data);
|
||||
|
||||
int
|
||||
ratbag_device_data_steelseries_get_mono_led(const struct ratbag_device_data *data);
|
||||
|
||||
int
|
||||
ratbag_device_data_steelseries_get_short_button(const struct ratbag_device_data *data);
|
||||
|
||||
@@ -1223,7 +1223,7 @@ static int
|
||||
ratbag_hidraw_parse_report_descriptor(struct ratbag_device *device)
|
||||
{
|
||||
int rc, desc_size = 0;
|
||||
struct ratbag_hidraw *hidraw = &device->hidraw;
|
||||
struct ratbag_hidraw *hidraw = &device->hidraw[0];
|
||||
struct hidraw_report_descriptor report_desc = {0};
|
||||
unsigned int i, j;
|
||||
unsigned int usage_page, usage;
|
||||
@@ -1291,7 +1291,7 @@ ratbag_hidraw_parse_report_descriptor(struct ratbag_device *device)
|
||||
}
|
||||
|
||||
static int
|
||||
ratbag_open_hidraw_node(struct ratbag_device *device, struct udev_device *hidraw_udev)
|
||||
ratbag_open_hidraw_node(struct ratbag_device *device, struct udev_device *hidraw_udev, int idx)
|
||||
{
|
||||
struct hidraw_devinfo info;
|
||||
struct ratbag_device *tmp_device;
|
||||
@@ -1300,15 +1300,17 @@ ratbag_open_hidraw_node(struct ratbag_device *device, struct udev_device *hidraw
|
||||
const char *sysname;
|
||||
size_t reports_size;
|
||||
|
||||
device->hidraw.fd = -1;
|
||||
assert(idx >= 0 && idx < MAX_HIDRAW);
|
||||
|
||||
device->hidraw[idx].fd = -1;
|
||||
|
||||
sysname = udev_device_get_sysname(hidraw_udev);
|
||||
if (!strneq("hidraw", sysname, 6))
|
||||
return -ENODEV;
|
||||
|
||||
list_for_each(tmp_device, &device->ratbag->devices, link) {
|
||||
if (tmp_device->hidraw.sysname &&
|
||||
streq(tmp_device->hidraw.sysname, sysname)) {
|
||||
if (tmp_device->hidraw[idx].sysname &&
|
||||
streq(tmp_device->hidraw[idx].sysname, sysname)) {
|
||||
return -ENODEV;
|
||||
}
|
||||
}
|
||||
@@ -1339,7 +1341,7 @@ ratbag_open_hidraw_node(struct ratbag_device *device, struct udev_device *hidraw
|
||||
device->name,
|
||||
udev_device_get_devnode(hidraw_udev));
|
||||
|
||||
device->hidraw.fd = fd;
|
||||
device->hidraw[idx].fd = fd;
|
||||
|
||||
/* parse first to count the number of reports */
|
||||
res = ratbag_hidraw_parse_report_descriptor(device);
|
||||
@@ -1348,19 +1350,19 @@ ratbag_open_hidraw_node(struct ratbag_device *device, struct udev_device *hidraw
|
||||
"Error while parsing the report descriptor: '%s' (%d)\n",
|
||||
strerror(-res),
|
||||
res);
|
||||
device->hidraw.fd = -1;
|
||||
device->hidraw[idx].fd = -1;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (device->hidraw.num_reports)
|
||||
reports_size = device->hidraw.num_reports * sizeof(struct ratbag_hid_report);
|
||||
if (device->hidraw[idx].num_reports)
|
||||
reports_size = device->hidraw[idx].num_reports * sizeof(struct ratbag_hid_report);
|
||||
else
|
||||
reports_size = sizeof(struct ratbag_hid_report);
|
||||
|
||||
device->hidraw.reports = zalloc(reports_size);
|
||||
device->hidraw[idx].reports = zalloc(reports_size);
|
||||
ratbag_hidraw_parse_report_descriptor(device);
|
||||
|
||||
device->hidraw.sysname = strdup_safe(sysname);
|
||||
device->hidraw[idx].sysname = strdup_safe(sysname);
|
||||
return 0;
|
||||
|
||||
err:
|
||||
@@ -1372,17 +1374,18 @@ err:
|
||||
static int
|
||||
ratbag_find_hidraw_node(struct ratbag_device *device,
|
||||
int (*match)(struct ratbag_device *device),
|
||||
int use_usb_parent)
|
||||
int use_usb_parent,
|
||||
int match_index, int hidraw_index)
|
||||
{
|
||||
struct ratbag *ratbag = device->ratbag;
|
||||
struct udev_enumerate *e;
|
||||
_cleanup_(udev_enumerate_unrefp) struct udev_enumerate *e = NULL;
|
||||
struct udev_list_entry *entry;
|
||||
const char *path;
|
||||
struct udev_device *hid_udev;
|
||||
struct udev_device *parent_udev;
|
||||
struct udev *udev = ratbag->udev;
|
||||
int rc = -ENODEV;
|
||||
int matched;
|
||||
int matched, endpoint_index = 0;
|
||||
|
||||
assert(match);
|
||||
|
||||
@@ -1414,29 +1417,30 @@ ratbag_find_hidraw_node(struct ratbag_device *device,
|
||||
if (!udev_device)
|
||||
continue;
|
||||
|
||||
rc = ratbag_open_hidraw_node(device, udev_device);
|
||||
if (match_index > 0 && match_index != endpoint_index++)
|
||||
continue;
|
||||
|
||||
rc = ratbag_open_hidraw_node(device, udev_device, hidraw_index);
|
||||
if (rc)
|
||||
goto skip;
|
||||
|
||||
|
||||
matched = match(device);
|
||||
rc = matched ? 0 : -ENODEV;
|
||||
if (matched == 1)
|
||||
goto out;
|
||||
return rc;
|
||||
|
||||
skip:
|
||||
ratbag_close_hidraw(device);
|
||||
ratbag_close_hidraw_index(device, hidraw_index);
|
||||
}
|
||||
|
||||
out:
|
||||
udev_enumerate_unref(e);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
ratbag_find_hidraw(struct ratbag_device *device, int (*match)(struct ratbag_device *device))
|
||||
{
|
||||
return ratbag_find_hidraw_node(device, match, true);
|
||||
return ratbag_find_hidraw_node(device, match, true, -1, 0);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -1448,7 +1452,13 @@ hidraw_match_all(struct ratbag_device *device)
|
||||
int
|
||||
ratbag_open_hidraw(struct ratbag_device *device)
|
||||
{
|
||||
return ratbag_find_hidraw_node(device, hidraw_match_all, false);
|
||||
return ratbag_find_hidraw_node(device, hidraw_match_all, false, -1, 0);
|
||||
}
|
||||
|
||||
int
|
||||
ratbag_open_hidraw_index(struct ratbag_device *device, int endpoint_index, int hidraw_index)
|
||||
{
|
||||
return ratbag_find_hidraw_node(device, hidraw_match_all, true, endpoint_index, hidraw_index);
|
||||
}
|
||||
|
||||
static struct ratbag_hid_report *
|
||||
@@ -1457,15 +1467,15 @@ ratbag_hidraw_get_report(struct ratbag_device *device, unsigned int report_id)
|
||||
unsigned i;
|
||||
|
||||
if (report_id == 0) {
|
||||
if (device->hidraw.reports[0].report_id == report_id)
|
||||
return &device->hidraw.reports[0];
|
||||
if (device->hidraw[0].reports[0].report_id == report_id)
|
||||
return &device->hidraw[0].reports[0];
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < device->hidraw.num_reports; i++) {
|
||||
if (device->hidraw.reports[i].report_id == report_id)
|
||||
return &device->hidraw.reports[i];
|
||||
for (i = 0; i < device->hidraw[0].num_reports; i++) {
|
||||
if (device->hidraw[0].reports[i].report_id == report_id)
|
||||
return &device->hidraw[0].reports[i];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
@@ -1507,20 +1517,28 @@ ratbag_hidraw_get_usage(struct ratbag_device *device, unsigned int report_id)
|
||||
void
|
||||
ratbag_close_hidraw(struct ratbag_device *device)
|
||||
{
|
||||
if (device->hidraw.fd < 0)
|
||||
ratbag_close_hidraw_index(device, 0);
|
||||
}
|
||||
|
||||
void
|
||||
ratbag_close_hidraw_index(struct ratbag_device *device, int idx)
|
||||
{
|
||||
assert(idx >= 0 && idx < MAX_HIDRAW);
|
||||
|
||||
if (device->hidraw[idx].fd < 0)
|
||||
return;
|
||||
|
||||
if (device->hidraw.sysname) {
|
||||
free(device->hidraw.sysname);
|
||||
device->hidraw.sysname = NULL;
|
||||
if (device->hidraw[idx].sysname) {
|
||||
free(device->hidraw[idx].sysname);
|
||||
device->hidraw[idx].sysname = NULL;
|
||||
}
|
||||
|
||||
ratbag_close_fd(device, device->hidraw.fd);
|
||||
device->hidraw.fd = -1;
|
||||
ratbag_close_fd(device, device->hidraw[idx].fd);
|
||||
device->hidraw[idx].fd = -1;
|
||||
|
||||
if (device->hidraw.reports) {
|
||||
free(device->hidraw.reports);
|
||||
device->hidraw.reports = NULL;
|
||||
if (device->hidraw[idx].reports) {
|
||||
free(device->hidraw[idx].reports);
|
||||
device->hidraw[idx].reports = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1531,7 +1549,7 @@ ratbag_hidraw_raw_request(struct ratbag_device *device, unsigned char reportnum,
|
||||
uint8_t tmp_buf[HID_MAX_BUFFER_SIZE];
|
||||
int rc;
|
||||
|
||||
if (len < 1 || len > HID_MAX_BUFFER_SIZE || !buf || device->hidraw.fd < 0)
|
||||
if (len < 1 || len > HID_MAX_BUFFER_SIZE || !buf || device->hidraw[0].fd < 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (rtype != HID_FEATURE_REPORT)
|
||||
@@ -1542,7 +1560,7 @@ ratbag_hidraw_raw_request(struct ratbag_device *device, unsigned char reportnum,
|
||||
memset(tmp_buf, 0, len);
|
||||
tmp_buf[0] = reportnum;
|
||||
|
||||
rc = ioctl(device->hidraw.fd, HIDIOCGFEATURE(len), tmp_buf);
|
||||
rc = ioctl(device->hidraw[0].fd, HIDIOCGFEATURE(len), tmp_buf);
|
||||
if (rc < 0)
|
||||
return -errno;
|
||||
|
||||
@@ -1554,7 +1572,7 @@ ratbag_hidraw_raw_request(struct ratbag_device *device, unsigned char reportnum,
|
||||
buf[0] = reportnum;
|
||||
|
||||
log_buf_raw(device->ratbag, "feature set: ", buf, len);
|
||||
rc = ioctl(device->hidraw.fd, HIDIOCSFEATURE(len), buf);
|
||||
rc = ioctl(device->hidraw[0].fd, HIDIOCSFEATURE(len), buf);
|
||||
if (rc < 0)
|
||||
return -errno;
|
||||
|
||||
@@ -1569,12 +1587,12 @@ ratbag_hidraw_output_report(struct ratbag_device *device, uint8_t *buf, size_t l
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (len < 1 || len > HID_MAX_BUFFER_SIZE || !buf || device->hidraw.fd < 0)
|
||||
if (len < 1 || len > HID_MAX_BUFFER_SIZE || !buf || device->hidraw[0].fd < 0)
|
||||
return -EINVAL;
|
||||
|
||||
log_buf_raw(device->ratbag, "output report: ", buf, len);
|
||||
|
||||
rc = write(device->hidraw.fd, buf, len);
|
||||
rc = write(device->hidraw[0].fd, buf, len);
|
||||
|
||||
if (rc < 0)
|
||||
return -errno;
|
||||
@@ -1587,14 +1605,22 @@ ratbag_hidraw_output_report(struct ratbag_device *device, uint8_t *buf, size_t l
|
||||
|
||||
int
|
||||
ratbag_hidraw_read_input_report(struct ratbag_device *device, uint8_t *buf, size_t len)
|
||||
{
|
||||
return ratbag_hidraw_read_input_report_index(device, buf, len, 0);
|
||||
}
|
||||
|
||||
int
|
||||
ratbag_hidraw_read_input_report_index(struct ratbag_device *device, uint8_t *buf, size_t len, int hidrawno)
|
||||
{
|
||||
int rc;
|
||||
struct pollfd fds;
|
||||
|
||||
if (len < 1 || !buf || device->hidraw.fd < 0)
|
||||
assert(hidrawno >= 0 && hidrawno < MAX_HIDRAW);
|
||||
|
||||
if (len < 1 || !buf || device->hidraw[hidrawno].fd < 0)
|
||||
return -EINVAL;
|
||||
|
||||
fds.fd = device->hidraw.fd;
|
||||
fds.fd = device->hidraw[hidrawno].fd;
|
||||
fds.events = POLLIN;
|
||||
|
||||
rc = poll(&fds, 1, 1000);
|
||||
@@ -1604,7 +1630,7 @@ ratbag_hidraw_read_input_report(struct ratbag_device *device, uint8_t *buf, size
|
||||
if (rc == 0)
|
||||
return -ETIMEDOUT;
|
||||
|
||||
rc = read(device->hidraw.fd, buf, len);
|
||||
rc = read(device->hidraw[hidrawno].fd, buf, len);
|
||||
|
||||
if (rc > 0)
|
||||
log_buf_raw(device->ratbag, "input report: ", buf, rc);
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#define HID_INPUT_REPORT 0
|
||||
#define HID_OUTPUT_REPORT 1
|
||||
#define HID_FEATURE_REPORT 2
|
||||
#define MAX_HIDRAW 2
|
||||
|
||||
struct ratbag_hid_report {
|
||||
unsigned int report_id;
|
||||
@@ -55,6 +56,18 @@ struct ratbag_hidraw {
|
||||
*/
|
||||
int ratbag_open_hidraw(struct ratbag_device *device);
|
||||
|
||||
/**
|
||||
* Open a hidraw device associated with the device by its enumeration order to
|
||||
* a specific internal hidraw index.
|
||||
*
|
||||
* @param device the ratbag device
|
||||
* @param enumeration index of the endpoint
|
||||
* @param interal index of hidraw array
|
||||
*
|
||||
* @return 0 on success or a negative errno on error
|
||||
*/
|
||||
int ratbag_open_hidraw_index(struct ratbag_device *device, int endpoint_index, int hidraw_index);
|
||||
|
||||
/**
|
||||
* Find and open the hidraw device associated with the device by using the
|
||||
* given matching function.
|
||||
@@ -75,6 +88,14 @@ ratbag_find_hidraw(struct ratbag_device *device,
|
||||
*/
|
||||
void ratbag_close_hidraw(struct ratbag_device *device);
|
||||
|
||||
/**
|
||||
* Close a hidraw device associated with the device by the internal index.
|
||||
*
|
||||
* @param device the ratbag device
|
||||
* @param interal index of hidraw array
|
||||
*/
|
||||
void ratbag_close_hidraw_index(struct ratbag_device *device, int idx);
|
||||
|
||||
/**
|
||||
* Send report request to device
|
||||
*
|
||||
@@ -115,6 +136,19 @@ int ratbag_hidraw_output_report(struct ratbag_device *device, uint8_t *buf, size
|
||||
*/
|
||||
int ratbag_hidraw_read_input_report(struct ratbag_device *device, uint8_t *buf, size_t len);
|
||||
|
||||
/**
|
||||
* Read an input report from the device from a specific hidraw index
|
||||
*
|
||||
* @param device the ratbag device
|
||||
* @param[out] buf resulting raw data
|
||||
* @param len length of buf
|
||||
* @param interal index of hidraw array
|
||||
*
|
||||
* @return count of data transfered, or a negative errno on error
|
||||
*/
|
||||
int ratbag_hidraw_read_input_report_index(struct ratbag_device *device, uint8_t *buf, size_t len, int hidrawno);
|
||||
|
||||
|
||||
/**
|
||||
* Tells if a given device has the specified report ID.
|
||||
*
|
||||
|
||||
@@ -129,7 +129,7 @@ struct ratbag_device {
|
||||
void *userdata;
|
||||
|
||||
struct udev_device *udev_device;
|
||||
struct ratbag_hidraw hidraw;
|
||||
struct ratbag_hidraw hidraw[MAX_HIDRAW];
|
||||
int refcount;
|
||||
struct input_id ids;
|
||||
struct ratbag_driver *driver;
|
||||
@@ -262,7 +262,7 @@ struct ratbag_resolution {
|
||||
unsigned int dpi_y; /**< y resolution in dpi */
|
||||
unsigned int hz; /**< report rate in Hz */
|
||||
|
||||
unsigned int rates[5];
|
||||
unsigned int rates[8];
|
||||
size_t nrates;
|
||||
|
||||
bool is_active;
|
||||
@@ -603,6 +603,7 @@ struct ratbag_driver etekcity_driver;
|
||||
struct ratbag_driver hidpp20_driver;
|
||||
struct ratbag_driver hidpp10_driver;
|
||||
struct ratbag_driver logitech_g300_driver;
|
||||
struct ratbag_driver logitech_g600_driver;
|
||||
struct ratbag_driver roccat_driver;
|
||||
struct ratbag_driver gskill_driver;
|
||||
struct ratbag_driver steelseries_driver;
|
||||
|
||||
@@ -583,6 +583,7 @@ ratbag_create_context(const struct ratbag_interface *interface,
|
||||
ratbag_register_driver(ratbag, &hidpp20_driver);
|
||||
ratbag_register_driver(ratbag, &hidpp10_driver);
|
||||
ratbag_register_driver(ratbag, &logitech_g300_driver);
|
||||
ratbag_register_driver(ratbag, &logitech_g600_driver);
|
||||
ratbag_register_driver(ratbag, &roccat_driver);
|
||||
ratbag_register_driver(ratbag, &gskill_driver);
|
||||
ratbag_register_driver(ratbag, &steelseries_driver);
|
||||
@@ -649,7 +650,7 @@ ratbag_create_led(struct ratbag_profile *profile, unsigned int index)
|
||||
return led;
|
||||
}
|
||||
|
||||
LIBRATBAG_EXPORT int
|
||||
LIBRATBAG_EXPORT bool
|
||||
ratbag_profile_has_capability(const struct ratbag_profile *profile,
|
||||
enum ratbag_profile_capability cap)
|
||||
{
|
||||
@@ -831,16 +832,16 @@ ratbag_profile_set_enabled(struct ratbag_profile *profile, bool enabled)
|
||||
return RATBAG_SUCCESS;
|
||||
}
|
||||
|
||||
LIBRATBAG_EXPORT int
|
||||
LIBRATBAG_EXPORT bool
|
||||
ratbag_profile_is_active(struct ratbag_profile *profile)
|
||||
{
|
||||
return profile->is_active;
|
||||
return !!profile->is_active;
|
||||
}
|
||||
|
||||
LIBRATBAG_EXPORT bool
|
||||
ratbag_profile_is_enabled(const struct ratbag_profile *profile)
|
||||
{
|
||||
return profile->is_enabled;
|
||||
return !!profile->is_enabled;
|
||||
}
|
||||
|
||||
LIBRATBAG_EXPORT unsigned int
|
||||
@@ -892,7 +893,7 @@ ratbag_device_unset_capability(struct ratbag_device *device,
|
||||
long_clear_bit(device->capabilities, cap);
|
||||
}
|
||||
|
||||
LIBRATBAG_EXPORT int
|
||||
LIBRATBAG_EXPORT bool
|
||||
ratbag_device_has_capability(const struct ratbag_device *device,
|
||||
enum ratbag_device_capability cap)
|
||||
{
|
||||
@@ -1001,7 +1002,7 @@ ratbag_device_commit(struct ratbag_device *device)
|
||||
|
||||
list_for_each(resolution, &profile->resolutions, link)
|
||||
resolution->dirty = false;
|
||||
|
||||
|
||||
}
|
||||
|
||||
return RATBAG_SUCCESS;
|
||||
@@ -1083,7 +1084,7 @@ ratbag_resolution_unref(struct ratbag_resolution *resolution)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
LIBRATBAG_EXPORT int
|
||||
LIBRATBAG_EXPORT bool
|
||||
ratbag_resolution_has_capability(struct ratbag_resolution *resolution,
|
||||
enum ratbag_resolution_capability cap)
|
||||
{
|
||||
@@ -1226,10 +1227,10 @@ ratbag_resolution_get_report_rate_list(struct ratbag_resolution *resolution,
|
||||
return resolution->nrates;
|
||||
}
|
||||
|
||||
LIBRATBAG_EXPORT int
|
||||
LIBRATBAG_EXPORT bool
|
||||
ratbag_resolution_is_active(const struct ratbag_resolution *resolution)
|
||||
{
|
||||
return resolution->is_active;
|
||||
return !!resolution->is_active;
|
||||
}
|
||||
|
||||
LIBRATBAG_EXPORT enum ratbag_error_code
|
||||
@@ -1248,10 +1249,10 @@ ratbag_resolution_set_active(struct ratbag_resolution *resolution)
|
||||
}
|
||||
|
||||
|
||||
LIBRATBAG_EXPORT int
|
||||
LIBRATBAG_EXPORT bool
|
||||
ratbag_resolution_is_default(const struct ratbag_resolution *resolution)
|
||||
{
|
||||
return resolution->is_default;
|
||||
return !!resolution->is_default;
|
||||
}
|
||||
|
||||
LIBRATBAG_EXPORT enum ratbag_error_code
|
||||
@@ -1314,7 +1315,7 @@ ratbag_button_get_action_type(struct ratbag_button *button)
|
||||
return button->action.type;
|
||||
}
|
||||
|
||||
LIBRATBAG_EXPORT int
|
||||
LIBRATBAG_EXPORT bool
|
||||
ratbag_button_has_action_type(struct ratbag_button *button,
|
||||
enum ratbag_button_action_type action_type)
|
||||
{
|
||||
@@ -1544,7 +1545,7 @@ ratbag_led_get_type(struct ratbag_led *led)
|
||||
return led->type;
|
||||
}
|
||||
|
||||
LIBRATBAG_EXPORT int
|
||||
LIBRATBAG_EXPORT bool
|
||||
ratbag_led_has_mode(struct ratbag_led *led,
|
||||
enum ratbag_led_mode mode)
|
||||
{
|
||||
@@ -1553,7 +1554,7 @@ ratbag_led_has_mode(struct ratbag_led *led,
|
||||
if (mode == RATBAG_LED_OFF)
|
||||
return 1;
|
||||
|
||||
return (led->modes & (1 << mode));
|
||||
return !!(led->modes & (1 << mode));
|
||||
}
|
||||
|
||||
LIBRATBAG_EXPORT struct ratbag_color
|
||||
@@ -1681,6 +1682,7 @@ ratbag_profile_set_name(struct ratbag_profile *profile,
|
||||
free(profile->name);
|
||||
|
||||
profile->name = name_copy;
|
||||
profile->dirty = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -452,7 +452,7 @@ ratbag_device_get_svg_name(const struct ratbag_device* device);
|
||||
* @retval 1 The device has the capability
|
||||
* @retval 0 The device does not have the capability
|
||||
*/
|
||||
int
|
||||
bool
|
||||
ratbag_device_has_capability(const struct ratbag_device *device,
|
||||
enum ratbag_device_capability cap);
|
||||
|
||||
@@ -540,7 +540,7 @@ ratbag_profile_unref(struct ratbag_profile *profile);
|
||||
*
|
||||
* @return non-zero if the capability is available, zero otherwise.
|
||||
*/
|
||||
int
|
||||
bool
|
||||
ratbag_profile_has_capability(const struct ratbag_profile *profile,
|
||||
enum ratbag_profile_capability cap);
|
||||
|
||||
@@ -655,7 +655,7 @@ ratbag_device_get_profile(struct ratbag_device *device, unsigned int index);
|
||||
*
|
||||
* @return non-zero if the profile is currently active, zero otherwise
|
||||
*/
|
||||
int
|
||||
bool
|
||||
ratbag_profile_is_active(struct ratbag_profile *profile);
|
||||
|
||||
/**
|
||||
@@ -771,7 +771,7 @@ ratbag_resolution_get_user_data(const struct ratbag_resolution *resolution);
|
||||
*
|
||||
* @return non-zero if the capability is available, zero otherwise.
|
||||
*/
|
||||
int
|
||||
bool
|
||||
ratbag_resolution_has_capability(struct ratbag_resolution *resolution,
|
||||
enum ratbag_resolution_capability cap);
|
||||
|
||||
@@ -988,7 +988,7 @@ ratbag_resolution_set_active(struct ratbag_resolution *resolution);
|
||||
* @return Non-zero if the resolution mode is the active one, zero
|
||||
* otherwise.
|
||||
*/
|
||||
int
|
||||
bool
|
||||
ratbag_resolution_is_active(const struct ratbag_resolution *resolution);
|
||||
|
||||
/**
|
||||
@@ -1023,7 +1023,7 @@ ratbag_resolution_set_default(struct ratbag_resolution *resolution);
|
||||
* @return Non-zero if the resolution mode is the default one, zero
|
||||
* otherwise.
|
||||
*/
|
||||
int
|
||||
bool
|
||||
ratbag_resolution_is_default(const struct ratbag_resolution *resolution);
|
||||
|
||||
/**
|
||||
@@ -1117,7 +1117,7 @@ ratbag_button_get_action_type(struct ratbag_button *button);
|
||||
*
|
||||
* @return non-zero if the action type is supported, zero otherwise.
|
||||
*/
|
||||
int
|
||||
bool
|
||||
ratbag_button_has_action_type(struct ratbag_button *button,
|
||||
enum ratbag_button_action_type action_type);
|
||||
|
||||
@@ -1218,7 +1218,7 @@ ratbag_led_get_type(struct ratbag_led *led);
|
||||
*
|
||||
* @see ratbag_led_set_mode
|
||||
*/
|
||||
int
|
||||
bool
|
||||
ratbag_led_has_mode(struct ratbag_led *led,
|
||||
enum ratbag_led_mode mode);
|
||||
|
||||
|
||||
@@ -135,6 +135,7 @@ static inline void reset_errno(int *saved_errno)
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev*, udev_unref);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev_device*, udev_device_unref);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev_enumerate*, udev_enumerate_unref);
|
||||
|
||||
/*
|
||||
* ELEMENTSOF() - number of array elements
|
||||
|
||||
99
tools/check_scan_build.py
Executable file
99
tools/check_scan_build.py
Executable file
@@ -0,0 +1,99 @@
|
||||
#!/bin/env python3
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
|
||||
import bs4
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
|
||||
class Bug(object):
|
||||
def __init__(self):
|
||||
self.line_number = None
|
||||
self.cfile = None
|
||||
self.sa_type = None
|
||||
self.sa_descr = None
|
||||
|
||||
|
||||
def main(argv):
|
||||
if len(argv) < 2:
|
||||
print(f'usage {argv[0]} PATH')
|
||||
sys.exit(1)
|
||||
|
||||
scanbuild_path = argv[1]
|
||||
|
||||
ignored = []
|
||||
bugs = []
|
||||
|
||||
line_re = re.compile(r'line (\d+), column (\d+)')
|
||||
|
||||
for root, dirs, files in os.walk(scanbuild_path):
|
||||
for filename in files:
|
||||
if not filename.startswith('report'):
|
||||
continue
|
||||
|
||||
with open(os.path.join(root, filename)) as f:
|
||||
soup = bs4.BeautifulSoup(f, 'html.parser')
|
||||
|
||||
# the first table is the summary
|
||||
summary = soup.table
|
||||
bug = Bug()
|
||||
|
||||
# iterate over the table
|
||||
for tr in summary('tr'):
|
||||
if 'File:' in tr.contents[0].string:
|
||||
bug.cfile = os.path.abspath(tr.contents[1].string)
|
||||
else:
|
||||
bug.sa_type = tr.contents[0].string.rstrip(':').lower()
|
||||
for s in tr.contents[1].strings:
|
||||
# retrieve the line number and the description
|
||||
m = line_re.match(s)
|
||||
if m is None:
|
||||
bug.sa_descr = s
|
||||
else:
|
||||
bug.line_number = int(m.group(1))
|
||||
|
||||
# retrieve the html line corresponding to the code
|
||||
code = soup.find('td', id=f'LN{bug.line_number}').parent
|
||||
|
||||
# fetching any comments in this line
|
||||
try:
|
||||
comments = code.find('span', class_='comment').string
|
||||
except AttributeError:
|
||||
# no comments on the line
|
||||
bugs.append(bug)
|
||||
else:
|
||||
if 'ignore_clang_sa_' in comments:
|
||||
ignored.append(bug)
|
||||
else:
|
||||
bugs.append(bug)
|
||||
|
||||
if len(ignored) > 0:
|
||||
print(f'{len(ignored)} bugs are ignored:')
|
||||
for b in ignored:
|
||||
print(f' {b.sa_type}: {b.sa_descr} at {b.cfile}:{b.line_number}')
|
||||
|
||||
if len(bugs) > 0:
|
||||
print()
|
||||
|
||||
if len(bugs) > 0:
|
||||
print(f'ERROR: {len(bugs)} bugs found:')
|
||||
for b in bugs:
|
||||
print(f' * {b.sa_type.upper()}: {b.sa_descr} at {b.cfile}:{b.line_number}')
|
||||
sys.exit(1)
|
||||
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main(sys.argv)
|
||||
@@ -31,6 +31,7 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include <liblur.h>
|
||||
#include <libratbag-util.h>
|
||||
|
||||
@@ -30,7 +30,7 @@ import sys
|
||||
|
||||
|
||||
def print_ratbagctl(ratbagctl_path, ratbagd_path, version_string):
|
||||
with open(ratbagctl_path, 'r') as ratbagctl, open(ratbagd_path, 'r') as ratbagd:
|
||||
with open(ratbagctl_path, 'r', encoding='utf-8') as ratbagctl, open(ratbagd_path, 'r', encoding='utf-8') as ratbagd:
|
||||
for l in ratbagctl.readlines():
|
||||
if l.startswith("from ratbagd import "):
|
||||
headers = True
|
||||
@@ -53,7 +53,7 @@ def main(argv):
|
||||
parser.add_argument("--version", action="store", default="git_master")
|
||||
ns = parser.parse_args(sys.argv[1:])
|
||||
if ns.output:
|
||||
ns.output_file = open(ns.output, 'w')
|
||||
ns.output_file = open(ns.output, 'w', encoding='utf-8')
|
||||
st = os.stat(ns.output)
|
||||
os.chmod(ns.output, st.st_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)
|
||||
sys.stdout = ns.output_file
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
import evdev
|
||||
import sys
|
||||
import argparse
|
||||
import re
|
||||
|
||||
from ratbagd import Ratbagd, RatbagdDevice, RatbagdProfile, RatbagdMacro, RatbagdResolution, RatbagdButton, RatbagdLed, RatbagdDBusUnavailable, RatbagError, RatbagErrorCode, RatbagErrorCapability # NOQA
|
||||
|
||||
@@ -266,8 +267,18 @@ def print_device(d, level):
|
||||
RatbagdDevice.CAP_LED: "led"}
|
||||
capabilities = [caps[c] for c in d.capabilities]
|
||||
|
||||
svg_name = 'unknown'
|
||||
try:
|
||||
with d.get_svg_fd('gnome') as fd:
|
||||
svg = fd.read()
|
||||
match = re.search('sodipodi:docname=".*"\n', svg)
|
||||
if match:
|
||||
svg_name = match.group(0).split('"')[1]
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
|
||||
print(" " * level + "{} - {}".format(d.id, d.name))
|
||||
print(" " * level + " SVG: {}".format(d.get_svg('gnome')))
|
||||
print(" " * level + " SVG: {}".format(svg_name))
|
||||
print(" " * level + " Capabilities: {}".format(", ".join(capabilities)))
|
||||
print(" " * level + " Number of Buttons: {}".format(len(p.buttons)))
|
||||
print(" " * level + " Number of Leds: {}".format(len(p.leds)))
|
||||
|
||||
@@ -232,6 +232,35 @@ class _RatbagdDBus(GObject.GObject):
|
||||
print(e.message, file=sys.stderr)
|
||||
raise
|
||||
|
||||
def _dbus_call_return_one_fd(self, method, type, *value):
|
||||
# Calls a method synchronously on the bus, using the given method name,
|
||||
# type signature and values.
|
||||
#
|
||||
# It the result is valid, it is returned. Invalid results raise the
|
||||
# appropriate RatbagError* or RatbagdDBus* exception, or GLib.Error if
|
||||
# it is an unexpected exception that probably shouldn't be passed up to
|
||||
# the UI.
|
||||
val = GLib.Variant("({})".format(type), value)
|
||||
try:
|
||||
res = self._proxy.call_with_unix_fd_list_sync(method, val,
|
||||
Gio.DBusCallFlags.NO_AUTO_START,
|
||||
2000, None, None)
|
||||
if res in EXCEPTION_TABLE:
|
||||
raise EXCEPTION_TABLE[res]
|
||||
# Result is a tuple of (GLib.Variant('(h)', (0,)), fd_list),
|
||||
# we return the first file descriptor in that list
|
||||
return res[1].get(0)
|
||||
except GLib.Error as e:
|
||||
if e.code == Gio.DBusError.FILE_NOT_FOUND:
|
||||
raise FileNotFoundError('Failed to open SVG file')
|
||||
elif e.code == Gio.IOErrorEnum.TIMED_OUT:
|
||||
raise RatbagdDBusTimeout(e.message)
|
||||
else:
|
||||
# Unrecognized error code; print the message to stderr and raise
|
||||
# the GLib.Error.
|
||||
print(e.message, file=sys.stderr)
|
||||
raise
|
||||
|
||||
def __eq__(self, other):
|
||||
return other and self._object_path == other._object_path
|
||||
|
||||
@@ -253,7 +282,7 @@ class Ratbagd(_RatbagdDBus):
|
||||
|
||||
def __init__(self):
|
||||
_RatbagdDBus.__init__(self, "Manager", None)
|
||||
result = self._get_dbus_property("Devices")
|
||||
result = self._get_dbus_property("Devices") or []
|
||||
self._devices = [RatbagdDevice(objpath) for objpath in result]
|
||||
|
||||
def _on_properties_changed(self, proxy, changed_props, invalidated_props):
|
||||
@@ -286,7 +315,7 @@ class Ratbagd(_RatbagdDBus):
|
||||
def themes(self):
|
||||
"""A list of theme names. The theme 'default' is guaranteed to be
|
||||
available."""
|
||||
return self._get_dbus_property("Themes")
|
||||
return self._get_dbus_property("Themes") or []
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
@@ -321,7 +350,7 @@ class RatbagdDevice(_RatbagdDBus):
|
||||
|
||||
# FIXME: if we start adding and removing objects from this list,
|
||||
# things will break!
|
||||
result = self._get_dbus_property("Profiles")
|
||||
result = self._get_dbus_property("Profiles") or []
|
||||
self._profiles = [RatbagdProfile(objpath) for objpath in result]
|
||||
for profile in self._profiles:
|
||||
profile.connect("notify::is-active", self._on_active_profile_changed)
|
||||
@@ -343,7 +372,7 @@ class RatbagdDevice(_RatbagdDBus):
|
||||
if RatbagdDevice.CAP_SWITCHABLE_RESOLUTION is in device.capabilities:
|
||||
do something
|
||||
"""
|
||||
return self._get_dbus_property("Capabilities")
|
||||
return self._get_dbus_property("Capabilities") or []
|
||||
|
||||
@GObject.Property
|
||||
def name(self):
|
||||
@@ -367,6 +396,19 @@ class RatbagdDevice(_RatbagdDBus):
|
||||
print("No active profile. Please report this bug to the libratbag developers", file=sys.stderr)
|
||||
return self._profiles[0]
|
||||
|
||||
def get_svg_fd(self, theme):
|
||||
"""Returns a File-like object to the SVG for the given theme, or
|
||||
raises FileNotFoundError if the file is not available.
|
||||
|
||||
The theme must be one of org.freedesktop.ratbag1.Manager.Themes. The
|
||||
theme 'default' is guaranteed to be available (but the file itself
|
||||
may not be).
|
||||
|
||||
@param theme The theme from which to retrieve the SVG, as str
|
||||
"""
|
||||
fd = self._dbus_call_return_one_fd("GetSvgFd", "s", theme)
|
||||
return os.fdopen(fd)
|
||||
|
||||
def get_svg(self, theme):
|
||||
"""Gets the full path to the SVG for the given theme, or the empty
|
||||
string if none is available.
|
||||
@@ -411,15 +453,15 @@ class RatbagdProfile(_RatbagdDBus):
|
||||
|
||||
# FIXME: if we start adding and removing objects from any of these
|
||||
# lists, things will break!
|
||||
result = self._get_dbus_property("Resolutions")
|
||||
result = self._get_dbus_property("Resolutions") or []
|
||||
self._resolutions = [RatbagdResolution(objpath) for objpath in result]
|
||||
self._subscribe_dirty(self._resolutions)
|
||||
|
||||
result = self._get_dbus_property("Buttons")
|
||||
result = self._get_dbus_property("Buttons") or []
|
||||
self._buttons = [RatbagdButton(objpath) for objpath in result]
|
||||
self._subscribe_dirty(self._buttons)
|
||||
|
||||
result = self._get_dbus_property("Leds")
|
||||
result = self._get_dbus_property("Leds") or []
|
||||
self._leds = [RatbagdLed(objpath) for objpath in result]
|
||||
self._subscribe_dirty(self._leds)
|
||||
|
||||
@@ -448,7 +490,7 @@ class RatbagdProfile(_RatbagdDBus):
|
||||
if RatbagdProfile.CAP_WRITABLE_NAME is in profile.capabilities:
|
||||
do something
|
||||
"""
|
||||
return self._get_dbus_property("Capabilities")
|
||||
return self._get_dbus_property("Capabilities") or []
|
||||
|
||||
@GObject.Property
|
||||
def name(self):
|
||||
@@ -565,7 +607,7 @@ class RatbagdResolution(_RatbagdDBus):
|
||||
if RatbagdResolution.CAP_SEPARATE_XY_RESOLUTION is in resolution.capabilities:
|
||||
do something
|
||||
"""
|
||||
return self._get_dbus_property("Capabilities")
|
||||
return self._get_dbus_property("Capabilities") or []
|
||||
|
||||
@GObject.Property
|
||||
def resolution(self):
|
||||
@@ -596,12 +638,12 @@ class RatbagdResolution(_RatbagdDBus):
|
||||
@GObject.Property
|
||||
def resolutions(self):
|
||||
"""The list of supported DPI values"""
|
||||
return self._get_dbus_property("Resolutions")
|
||||
return self._get_dbus_property("Resolutions") or []
|
||||
|
||||
@GObject.Property
|
||||
def report_rates(self):
|
||||
"""The list of supported report rates"""
|
||||
return self._get_dbus_property("ReportRates")
|
||||
return self._get_dbus_property("ReportRates") or []
|
||||
|
||||
@GObject.Property
|
||||
def is_active(self):
|
||||
|
||||
@@ -61,6 +61,8 @@ def start_ratbagd(verbosity=0):
|
||||
from gi.repository import Gio
|
||||
import time
|
||||
|
||||
os.makedirs(DBUS_CONF_DIR, exist_ok=True)
|
||||
|
||||
# first copy the policy for the ratbagd daemon to be allowed to run
|
||||
shutil.copy(os.path.join('@MESON_BUILD_ROOT@', DBUS_CONF_NAME),
|
||||
DBUS_CONF_PATH)
|
||||
@@ -73,6 +75,8 @@ def start_ratbagd(verbosity=0):
|
||||
args.append('--verbose=raw')
|
||||
elif verbosity >= 2:
|
||||
args.append('--verbose')
|
||||
elif verbosity == 0:
|
||||
args.append('--quiet')
|
||||
|
||||
ratbagd_process = subprocess.Popen(args, shell=False, stdout=sys.stdout, stderr=sys.stderr)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user