Compare commits
897 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
daf9580ca5 | ||
|
|
396b8bee87 | ||
|
|
c8c1c63531 | ||
|
|
704710814e | ||
|
|
f497dab1d8 | ||
|
|
67ee0fab14 | ||
|
|
d17868303e | ||
|
|
6d05b7df67 | ||
|
|
30c482aab2 | ||
|
|
bf127d4c68 | ||
|
|
9f9f6294c3 | ||
|
|
3bba3d9bcb | ||
|
|
6b65ed2198 | ||
|
|
8e9dd6f392 | ||
|
|
f3df391d71 | ||
|
|
16daac7311 | ||
|
|
653b834e01 | ||
|
|
8c32036e03 | ||
|
|
ba10000feb | ||
|
|
f07007b6e6 | ||
|
|
a002a58a5e | ||
|
|
57ca3086ae | ||
|
|
a46c30253d | ||
|
|
391a0e923e | ||
|
|
cac289119d | ||
|
|
2607114709 | ||
|
|
d171f953c7 | ||
|
|
734977f176 | ||
|
|
10a1cc9bbc | ||
|
|
367aa29dfe | ||
|
|
79711dfdad | ||
|
|
32a5ad377e | ||
|
|
5328c20a58 | ||
|
|
014212bbd9 | ||
|
|
3fcf13b58e | ||
|
|
55fd6c7a71 | ||
|
|
d6bbc33dda | ||
|
|
d24ea1e662 | ||
|
|
e4d4a7905a | ||
|
|
af729ec16b | ||
|
|
8ae35fa11b | ||
|
|
561f0ac866 | ||
|
|
12ac8b17f0 | ||
|
|
b568963b14 | ||
|
|
583a050945 | ||
|
|
fe5ed89995 | ||
|
|
9ceec4f9f7 | ||
|
|
e55c3812db | ||
|
|
d924218c7c | ||
|
|
8a3eb946fe | ||
|
|
c734cec88a | ||
|
|
109621f73e | ||
|
|
6e09afd61e | ||
|
|
943308ccaf | ||
|
|
253e8f6edc | ||
|
|
17d8bcacf6 | ||
|
|
6280268919 | ||
|
|
caa75d170d | ||
|
|
a7f44211df | ||
|
|
a3466f0e99 | ||
|
|
222dda17a6 | ||
|
|
29fb0f855f | ||
|
|
91dfc3477d | ||
|
|
42caf3bc94 | ||
|
|
7778da715e | ||
|
|
0c2e4121af | ||
|
|
107a649e08 | ||
|
|
a17613459b | ||
|
|
3392b5e276 | ||
|
|
13656b60f7 | ||
|
|
c2f93dc672 | ||
|
|
468e6108ca | ||
|
|
59e134149a | ||
|
|
29b2e64a1d | ||
|
|
4ce6a872ca | ||
|
|
8fa5a82376 | ||
|
|
0ef2dff374 | ||
|
|
208bb15149 | ||
|
|
549a6c47b8 | ||
|
|
400451efe1 | ||
|
|
2ee88948f3 | ||
|
|
ace60f76da | ||
|
|
451af331b9 | ||
|
|
b87a770970 | ||
|
|
e59ef319b0 | ||
|
|
8a1487f6f4 | ||
|
|
44d36d2bf0 | ||
|
|
635865efa5 | ||
|
|
38949013f7 | ||
|
|
e1879818b4 | ||
|
|
9b2614109f | ||
|
|
abe99fec6a | ||
|
|
21936db58b | ||
|
|
74f01f3de4 | ||
|
|
53ba4d975d | ||
|
|
97306ddd5a | ||
|
|
16e052d846 | ||
|
|
1586913fc7 | ||
|
|
cf9a3e48b7 | ||
|
|
ec835e2e82 | ||
|
|
b86211204c | ||
|
|
1d6995be72 | ||
|
|
536576fe8b | ||
|
|
b514f49b08 | ||
|
|
46a466ffe1 | ||
|
|
15f1667fa4 | ||
|
|
284c13b2fe | ||
|
|
e9bb4f98ae | ||
|
|
45b8d792cc | ||
|
|
b93dfcfda4 | ||
|
|
3ffdc8daa0 | ||
|
|
e38bc7a760 | ||
|
|
2dca516afa | ||
|
|
b489ac871d | ||
|
|
50fb898138 | ||
|
|
c676fcefb1 | ||
|
|
bb4dd2aae0 | ||
|
|
9b11340e91 | ||
|
|
3cd5a1f986 | ||
|
|
874d7eccb8 | ||
|
|
44c4b901e2 | ||
|
|
2371960a1d | ||
|
|
874aa8e63e | ||
|
|
1225f421c0 | ||
|
|
5f0f5d2843 | ||
|
|
1d464767e1 | ||
|
|
9551dddbb8 | ||
|
|
563c274705 | ||
|
|
71ed64a843 | ||
|
|
efb3efc828 | ||
|
|
982e6cc7fe | ||
|
|
44dc754e31 | ||
|
|
18887e4c86 | ||
|
|
46d5fae2e5 | ||
|
|
4b31945e1d | ||
|
|
7e685f5196 | ||
|
|
050db150f6 | ||
|
|
a3de0e1ff7 | ||
|
|
acc0066f08 | ||
|
|
eb9f98e58d | ||
|
|
6d996bf1aa | ||
|
|
34fbfe105c | ||
|
|
dfeac1bcbc | ||
|
|
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 | ||
|
|
1e62916e75 | ||
|
|
447c69f034 | ||
|
|
fc0ab95087 | ||
|
|
7fe4d6f097 | ||
|
|
fa57b417e9 | ||
|
|
1aec9c0f54 | ||
|
|
d1918a063c | ||
|
|
770dd62b1d | ||
|
|
b474e76ac2 | ||
|
|
6fa6e18408 | ||
|
|
8ee19efee9 | ||
|
|
45282e7bd9 | ||
|
|
54b04ffff8 | ||
|
|
1243d5bb13 | ||
|
|
627fc5054f | ||
|
|
a0830a8aaa | ||
|
|
02cbfc23b7 | ||
|
|
3da2630158 | ||
|
|
e02d0724a3 | ||
|
|
920fb3917f | ||
|
|
f36b2dbce9 | ||
|
|
ef7e6f6db5 | ||
|
|
3459fab8ec | ||
|
|
8063385d03 | ||
|
|
3dabcaa3a0 | ||
|
|
6c182b8e9b | ||
|
|
ae805a3568 | ||
|
|
d0001b8e0e | ||
|
|
cbcdc4b724 | ||
|
|
3bc3da967c | ||
|
|
b50ffef327 | ||
|
|
ec223eb2e6 | ||
|
|
573d3d399e | ||
|
|
0f5beb619e | ||
|
|
89aff23c11 | ||
|
|
fd27957b57 | ||
|
|
554ee88c86 | ||
|
|
868d71a08b | ||
|
|
9b3c33a2fe | ||
|
|
109cc69da9 | ||
|
|
113bd4859e | ||
|
|
2a2b7487d4 | ||
|
|
2b4022dcbf | ||
|
|
7555cf1607 | ||
|
|
9c75a7cc7e | ||
|
|
0337ae41ab | ||
|
|
ff39e67615 | ||
|
|
7ba5563eeb | ||
|
|
968b9383d3 | ||
|
|
be6c381751 | ||
|
|
27a0db37d8 | ||
|
|
5858816b53 | ||
|
|
a1376180b4 | ||
|
|
75d1400206 | ||
|
|
78475a6d15 | ||
|
|
63f93111fb | ||
|
|
1ea21ed6ce | ||
|
|
18a8fb9651 | ||
|
|
2e836a40d3 | ||
|
|
c09872e589 | ||
|
|
575b7bce98 | ||
|
|
3e04abde30 | ||
|
|
790c5e90bd | ||
|
|
85a358e07c | ||
|
|
3af0544421 | ||
|
|
f69b4d53f6 | ||
|
|
cb4be02a56 | ||
|
|
bacdab2596 | ||
|
|
ec7bb2f63a | ||
|
|
74a5551a8d | ||
|
|
3e0c803a37 | ||
|
|
55682c3a5d | ||
|
|
ae9e287b8d | ||
|
|
03c264cec1 | ||
|
|
410e01de61 | ||
|
|
d167dfd83b | ||
|
|
9b7d8f5f24 | ||
|
|
366fbc3fda | ||
|
|
f1d20f1f35 | ||
|
|
558f59b52c | ||
|
|
1a3ef63519 | ||
|
|
17380baae9 | ||
|
|
314c3e2f78 | ||
|
|
6ba5cc3319 | ||
|
|
1148d172b5 | ||
|
|
a930cdad87 | ||
|
|
b951d83a64 | ||
|
|
f56df6b1d0 | ||
|
|
1e35b2ace6 | ||
|
|
e75c20a249 | ||
|
|
c63ffdd3ef | ||
|
|
40658c6d0e | ||
|
|
251efd3b40 | ||
|
|
94320099b0 | ||
|
|
f592cabcd7 | ||
|
|
a58096fade | ||
|
|
b140bc2827 | ||
|
|
aeaa69b9e1 | ||
|
|
a535897ae7 | ||
|
|
1074a2b2e6 | ||
|
|
51c1be3806 | ||
|
|
b9e647ccb8 | ||
|
|
e063aa3d2a | ||
|
|
9a74e30c64 | ||
|
|
f26de4bb29 | ||
|
|
e9008eeaba | ||
|
|
d5dc8eccd6 | ||
|
|
13736d0ced | ||
|
|
a926afe8de | ||
|
|
af78dc4ec2 | ||
|
|
1c85d77d56 | ||
|
|
c8929b50fa | ||
|
|
e58e79cb8d | ||
|
|
049e12b2eb | ||
|
|
5c71f9552d | ||
|
|
c3be9e1af1 | ||
|
|
186d626c40 | ||
|
|
dfc433cb74 | ||
|
|
ab2dae47af | ||
|
|
ec442b960d | ||
|
|
670720b40f | ||
|
|
0787e35964 | ||
|
|
9f4df9582c | ||
|
|
d282590746 | ||
|
|
9e5047976b | ||
|
|
d69a2ec5ba | ||
|
|
4bfd5d9a13 | ||
|
|
091e651831 | ||
|
|
d52c2c0320 | ||
|
|
cd71ce67b1 | ||
|
|
43f501907e | ||
|
|
d26d5b83f1 | ||
|
|
c401414310 | ||
|
|
c34fe85780 | ||
|
|
a19a79d33a | ||
|
|
8edf6e7609 | ||
|
|
835a694c4b | ||
|
|
a47492e62c | ||
|
|
186a1deda8 | ||
|
|
132212652f | ||
|
|
5a40d93a30 | ||
|
|
f62940c1e5 | ||
|
|
0f808ed387 | ||
|
|
d8edf2d9e4 | ||
|
|
6827f5ed81 | ||
|
|
f3208b499b | ||
|
|
94e0842a06 | ||
|
|
e0de98ba01 | ||
|
|
1adb147f6d | ||
|
|
b1c4bba3b2 | ||
|
|
cdbdcd23e6 | ||
|
|
23d1290b22 | ||
|
|
5edcdfba5b | ||
|
|
6d105a002c | ||
|
|
3b1a41f154 | ||
|
|
0153efbf9c | ||
|
|
db34ab5255 | ||
|
|
52e10d029f | ||
|
|
1c94ef5c56 | ||
|
|
5efd83fc41 | ||
|
|
33966989db | ||
|
|
c56c76e07d | ||
|
|
8440a36f92 | ||
|
|
3e31b45db0 | ||
|
|
548a40dba6 | ||
|
|
c437882e96 | ||
|
|
4a61dc413b | ||
|
|
59df7defdb | ||
|
|
77fa6a1e65 | ||
|
|
0f8031c201 | ||
|
|
5842dccc2a | ||
|
|
0c5b1998a5 | ||
|
|
f52ebd0dba | ||
|
|
1857378a76 | ||
|
|
d2600583bb | ||
|
|
e2a4684f83 | ||
|
|
ed39cf3dee | ||
|
|
c4d3b1e606 | ||
|
|
be1fb30751 | ||
|
|
a2b3c32124 | ||
|
|
26e7237010 | ||
|
|
26a6215122 | ||
|
|
376adfdf2a | ||
|
|
d990e3f027 | ||
|
|
2473f66cb3 | ||
|
|
8e9bf7b48a | ||
|
|
7edae05b37 | ||
|
|
909749fc00 | ||
|
|
15b4b4a3ca | ||
|
|
cad05f1256 | ||
|
|
703e1f6f0d | ||
|
|
19451f9df7 | ||
|
|
3314b41202 | ||
|
|
f636fd8f53 | ||
|
|
77847f570c | ||
|
|
afaf3fa83d | ||
|
|
4c7f644599 | ||
|
|
692f7f008a | ||
|
|
0a62c3dfa8 | ||
|
|
7cd2cfed44 | ||
|
|
c31e11d385 | ||
|
|
efe6021e76 | ||
|
|
8d67389042 | ||
|
|
4037587f74 | ||
|
|
94daeb1444 | ||
|
|
937b30c415 | ||
|
|
6f0242f05b | ||
|
|
921837fd0f | ||
|
|
d06cdcc53c | ||
|
|
5828355426 | ||
|
|
50dc321b7b | ||
|
|
43f033db80 | ||
|
|
623c53f1e4 | ||
|
|
39762718b9 | ||
|
|
ae3804f7b4 | ||
|
|
0dd08dfb84 | ||
|
|
bb23f68d53 | ||
|
|
83345a17d2 | ||
|
|
b9f6554767 | ||
|
|
7eadd20879 | ||
|
|
3844a60837 | ||
|
|
6cdf8a901a | ||
|
|
c868c43179 | ||
|
|
01ca2a6de7 | ||
|
|
d64af72f74 | ||
|
|
c2fe745813 | ||
|
|
ddefbf95a3 | ||
|
|
a2b651985e | ||
|
|
788c261ce9 | ||
|
|
35070cc17e | ||
|
|
79be057e91 | ||
|
|
aa8f506dd0 | ||
|
|
c6486b1960 | ||
|
|
2f8e3a1610 | ||
|
|
432d32bedc | ||
|
|
8cb2d21ff5 | ||
|
|
1103c208a8 | ||
|
|
7e59f0f974 | ||
|
|
c647d6df99 | ||
|
|
97a927bb7d | ||
|
|
7c650aeeca | ||
|
|
3fd7cd0137 | ||
|
|
7e97936f0e | ||
|
|
643a4a89f4 | ||
|
|
cfd93cf332 | ||
|
|
340e5b7d86 | ||
|
|
be624fe943 | ||
|
|
cb102e115c | ||
|
|
952eb1cf0e | ||
|
|
709ffa37b2 | ||
|
|
f4f206f3e5 | ||
|
|
7036428066 | ||
|
|
18239f1aee | ||
|
|
fe8fde79f6 | ||
|
|
9f805a4ebe | ||
|
|
572f00cf2a | ||
|
|
330b4641ad | ||
|
|
c1c8b1eda2 | ||
|
|
aa251448d3 | ||
|
|
e27b1eb99f | ||
|
|
faaf93b194 | ||
|
|
58957667e1 | ||
|
|
0db7ba0c85 | ||
|
|
c42c15ad0e | ||
|
|
fc50e38ae2 | ||
|
|
b2d29a0285 | ||
|
|
87ecd6e252 | ||
|
|
2b49550b9b | ||
|
|
6ddba76c93 | ||
|
|
d9e7298aee | ||
|
|
49b7029506 | ||
|
|
468787601e | ||
|
|
804d8f7969 | ||
|
|
9b53119121 | ||
|
|
b773ac085b | ||
|
|
13419dcbb8 | ||
|
|
c9322fa983 | ||
|
|
6cfca9e34b | ||
|
|
282398493b | ||
|
|
022dc74354 | ||
|
|
cd6ffca413 | ||
|
|
b19a6ebcfc | ||
|
|
811281372b | ||
|
|
c361b8500f | ||
|
|
bcf302904d | ||
|
|
e0e4d5062a | ||
|
|
abd1a04fed | ||
|
|
ab1d7628f1 | ||
|
|
670cf90e11 | ||
|
|
f5210e1902 | ||
|
|
5bcafb5bee | ||
|
|
d8e132f550 | ||
|
|
7e9566b00f | ||
|
|
7c313a31fd | ||
|
|
861562e58a | ||
|
|
0a6b4b3778 | ||
|
|
b4f451285e | ||
|
|
5f0ebdead7 | ||
|
|
de3bb0e579 | ||
|
|
9dcd2c6c05 | ||
|
|
34196c9960 | ||
|
|
5399d15658 | ||
|
|
5f98d8d029 | ||
|
|
10903e2434 | ||
|
|
b7f53effa1 | ||
|
|
129551f3f4 | ||
|
|
4f62424e8a | ||
|
|
ae65ab3ae8 | ||
|
|
96067f18ca | ||
|
|
67e1c8667b | ||
|
|
ab67517584 | ||
|
|
9fe892f10f | ||
|
|
bf18e9b795 | ||
|
|
e95bb9601c | ||
|
|
a16ffa3946 | ||
|
|
8c97a12741 | ||
|
|
0982d6a4a9 | ||
|
|
3160d86050 | ||
|
|
6faa59c70d | ||
|
|
ced958f135 | ||
|
|
d5ccaed457 | ||
|
|
2c799eca30 | ||
|
|
98fb63e2e3 | ||
|
|
55bab29233 | ||
|
|
c0c77100ad | ||
|
|
aa50df8eaf | ||
|
|
c12ca6008a | ||
|
|
c6bc6b2576 | ||
|
|
f53bf7d4ad | ||
|
|
40bd189cc0 | ||
|
|
7097f1dea6 | ||
|
|
70f3da98db | ||
|
|
f281bd751e | ||
|
|
04b54d26e2 | ||
|
|
19cdf6d7e9 | ||
|
|
0018431f31 | ||
|
|
8380e1686b | ||
|
|
c14ffe36e3 | ||
|
|
a4dd9bcdf3 | ||
|
|
c1cabeeeeb | ||
|
|
ca69365a86 | ||
|
|
98fa9c168a | ||
|
|
0e26b6e2be | ||
|
|
760c3f3ff9 | ||
|
|
8aaa6894df | ||
|
|
636d254d41 | ||
|
|
f6e5dd6c2c | ||
|
|
5637755345 | ||
|
|
a9c4f46412 | ||
|
|
7aed3640c4 | ||
|
|
85f2ec3910 | ||
|
|
6274dea4ac | ||
|
|
a938521c9e | ||
|
|
9450d1402f | ||
|
|
8209ce56b6 | ||
|
|
a6d03fde18 | ||
|
|
5fff0ece5b | ||
|
|
d915fdfe45 | ||
|
|
7b861ada4c | ||
|
|
fa1799eef3 | ||
|
|
77cc2fa82d | ||
|
|
de4bd4a2d2 | ||
|
|
c61782f1a4 | ||
|
|
6503407007 | ||
|
|
09295d9d0e | ||
|
|
2c379d09c9 | ||
|
|
994ade7fff | ||
|
|
769289fe01 | ||
|
|
f05950f37c | ||
|
|
de16f1a4b1 | ||
|
|
d1db382607 | ||
|
|
82a0cd4ec4 | ||
|
|
ec85b6db3e | ||
|
|
a9f4049841 | ||
|
|
dab5d2c0b7 | ||
|
|
51d625244d | ||
|
|
7b1e7dc4e7 | ||
|
|
019d020535 | ||
|
|
89d071bb80 | ||
|
|
499ebc7d18 | ||
|
|
e522e0bb07 | ||
|
|
f55a314666 | ||
|
|
97ac0f81f2 | ||
|
|
8cfcab3363 | ||
|
|
6f72accbee | ||
|
|
e021937867 | ||
|
|
82d197462f | ||
|
|
78bdfe7a59 | ||
|
|
586fc7a97d | ||
|
|
2faa94920e | ||
|
|
01163d8f77 | ||
|
|
04990e4ea2 | ||
|
|
37c8dec45c | ||
|
|
df2a06690d | ||
|
|
2c4cdc6dc6 | ||
|
|
96c2f404d2 | ||
|
|
e33a515fd6 | ||
|
|
8fc58e259c | ||
|
|
caadd86091 | ||
|
|
e16aafe86c | ||
|
|
6a0ebe9e45 | ||
|
|
79f4b9c0d6 | ||
|
|
e6433abd09 | ||
|
|
96f3b7858b | ||
|
|
f5abc191d8 | ||
|
|
251b602323 | ||
|
|
fe3169182c | ||
|
|
642a5339bc | ||
|
|
c251053f03 | ||
|
|
4b97b00518 | ||
|
|
faa1a24c25 | ||
|
|
b78b5cd73e | ||
|
|
4eb5411bf1 | ||
|
|
22af1176d3 | ||
|
|
bb6d8a6ea4 | ||
|
|
935f68ae8f | ||
|
|
2fd939f514 | ||
|
|
dbc0672061 | ||
|
|
804f2eec76 | ||
|
|
73c24319d1 | ||
|
|
6b3fc6338e | ||
|
|
c6855df5fc | ||
|
|
9ed61fd072 | ||
|
|
1a764944e7 | ||
|
|
e311f89357 | ||
|
|
ecdba84977 | ||
|
|
c003eccb1e | ||
|
|
f36fdc0492 | ||
|
|
907b96d447 | ||
|
|
b4682e836c | ||
|
|
30e8fbedd8 | ||
|
|
fc1887c01f | ||
|
|
d51acfd730 | ||
|
|
35e38a5469 | ||
|
|
2ae3976868 | ||
|
|
5dcdc3c652 | ||
|
|
af68f6046c | ||
|
|
c0c4ba156a | ||
|
|
22135f31d5 | ||
|
|
0c7ca85f5b | ||
|
|
478c5bbb68 | ||
|
|
487e66e64d | ||
|
|
2b5b0b1772 | ||
|
|
13bb5b52e1 | ||
|
|
90d2a48cfb | ||
|
|
97a37d21e1 | ||
|
|
9cf6100e00 | ||
|
|
932cf905ef | ||
|
|
7da53c61cf | ||
|
|
714c0d5330 | ||
|
|
dc92abb5e5 | ||
|
|
b0c515b59d | ||
|
|
8e6c13832e | ||
|
|
e33f655f61 | ||
|
|
8e8b7b0611 | ||
|
|
d28f2f0123 | ||
|
|
a8eea870f5 | ||
|
|
7e12e45311 | ||
|
|
b31c1d5ff3 | ||
|
|
f6949458b7 | ||
|
|
15dd6b4f2b | ||
|
|
7afd59149c | ||
|
|
a47f506293 | ||
|
|
ad88f755a4 | ||
|
|
f243abb65c | ||
|
|
a4b177436d | ||
|
|
8367569236 | ||
|
|
5bbb2b28ea | ||
|
|
2b92ab6dd6 | ||
|
|
c05c3dcaa3 | ||
|
|
dd71c23a04 | ||
|
|
299c49c291 | ||
|
|
b1feabaf64 | ||
|
|
2722e008e0 | ||
|
|
178b08cd0a | ||
|
|
bf20845249 | ||
|
|
4dc15451b7 | ||
|
|
3a764b6aae | ||
|
|
190e78c79c | ||
|
|
eb01399f26 | ||
|
|
c815654c94 | ||
|
|
f1ce908b50 | ||
|
|
fb07204d9f | ||
|
|
1e5648b11d | ||
|
|
0902e3420f | ||
|
|
2750f8c49b | ||
|
|
57ffc9c5d3 | ||
|
|
a2b858008f | ||
|
|
28956126ec | ||
|
|
698d8ab365 | ||
|
|
44471d3c42 | ||
|
|
ad1fa22196 | ||
|
|
04ebd96bb7 | ||
|
|
09b5ae14b1 | ||
|
|
8aa127186c | ||
|
|
a962082173 | ||
|
|
5c0dbe4d5c | ||
|
|
5934816b11 | ||
|
|
28dd84713f | ||
|
|
11b31cf9bd | ||
|
|
dfd2d88953 | ||
|
|
6a097bd691 | ||
|
|
2776d1ce8e | ||
|
|
fa12517fb2 | ||
|
|
9624d1bdcd | ||
|
|
8f7bf150df | ||
|
|
f5270e1539 | ||
|
|
0834b210ca | ||
|
|
cc41adbbf9 | ||
|
|
8944353716 | ||
|
|
53ff42ea55 | ||
|
|
63a666025f | ||
|
|
25a92e61ef | ||
|
|
70a33ec78d | ||
|
|
d358d7433b | ||
|
|
08ce9773dd | ||
|
|
f745734d90 | ||
|
|
5443083b1d | ||
|
|
cc19496699 | ||
|
|
b595691c5e | ||
|
|
7d784a1a91 | ||
|
|
a664042f64 | ||
|
|
5bc4470a8c | ||
|
|
b8ed1ea3a4 | ||
|
|
f2ad49cf20 | ||
|
|
fd6a9e73ed | ||
|
|
db57a8e7b6 | ||
|
|
2a35bf009f | ||
|
|
42d49d74ab | ||
|
|
a9f34249fc | ||
|
|
1ce59bcc1f | ||
|
|
bb35821c45 | ||
|
|
bbec42c426 | ||
|
|
cb487a6d1a | ||
|
|
7fdcf62bf2 | ||
|
|
f82c1119bf | ||
|
|
f60f8a12ab | ||
|
|
fd348d456d | ||
|
|
0f73a97bc8 | ||
|
|
7783f50110 | ||
|
|
617cd628ea | ||
|
|
9601ba1323 | ||
|
|
b85fcd0cee | ||
|
|
3c879b7389 | ||
|
|
44e7bc1c23 | ||
|
|
0bcaeaeb33 | ||
|
|
da60f0748c | ||
|
|
5418392143 | ||
|
|
6c18b16a00 | ||
|
|
8e5ad717c4 | ||
|
|
1ff263f0a4 | ||
|
|
e9f0ca4385 | ||
|
|
079b67f111 | ||
|
|
a224ef6d0b | ||
|
|
0c0a6d39cb | ||
|
|
3439058a54 | ||
|
|
6414f7901f | ||
|
|
4d6390ea66 | ||
|
|
3f83d5057d | ||
|
|
67f1c00181 | ||
|
|
c4013ca4b0 | ||
|
|
25294d9a63 | ||
|
|
7d241642f9 | ||
|
|
d1e42ac56c | ||
|
|
45129b2bc8 | ||
|
|
0568b4c39d | ||
|
|
5b152a6c3f | ||
|
|
52d4e35192 | ||
|
|
a1a3750bc8 | ||
|
|
3cfda944d0 | ||
|
|
852fc2da2d | ||
|
|
adefb2921b | ||
|
|
27a141fd87 | ||
|
|
2b63ca4935 | ||
|
|
107d7e652f | ||
|
|
7e8d40b57a | ||
|
|
6c40b18229 | ||
|
|
9d51d70f70 | ||
|
|
96a9a0f6a4 | ||
|
|
31b513e6d7 | ||
|
|
d831d6e515 | ||
|
|
89de42ad8e | ||
|
|
01fcef9b9d | ||
|
|
2bcacfc1ac | ||
|
|
1e2edefd93 | ||
|
|
3aabba255d | ||
|
|
fc874c0249 | ||
|
|
e543723856 | ||
|
|
eb8e4bbfa8 | ||
|
|
a9dc630fae | ||
|
|
d874a2e5f1 | ||
|
|
a658b117a7 | ||
|
|
638b505ade | ||
|
|
ff3730f3fb | ||
|
|
00f488dc13 | ||
|
|
ca2f32ea58 | ||
|
|
0ebbccc6cf | ||
|
|
7c622ecc58 | ||
|
|
917308d24d | ||
|
|
97eee9e0c5 | ||
|
|
5cc234e27e | ||
|
|
2bbcc51a8b | ||
|
|
1824b977f7 | ||
|
|
99011fd3bf | ||
|
|
346631cd75 | ||
|
|
8517e103b0 | ||
|
|
815a81a610 | ||
|
|
20b9339620 | ||
|
|
2e93ac07f6 | ||
|
|
f385622ec6 | ||
|
|
de83186c3c | ||
|
|
fa0d57dd47 | ||
|
|
b164fa622f | ||
|
|
e4c654841b | ||
|
|
a411248c7c | ||
|
|
a066203b4a | ||
|
|
819c70fa9a | ||
|
|
9f9383e6ff | ||
|
|
70222b3033 | ||
|
|
5e2d7de6c2 | ||
|
|
aceef4d0d0 | ||
|
|
654956baa6 | ||
|
|
212ab08c15 | ||
|
|
18a0be561f | ||
|
|
0528981a0a | ||
|
|
eac1e91638 | ||
|
|
a8600faeb3 | ||
|
|
9c33eede5c | ||
|
|
6c285fa2a1 | ||
|
|
d6116e00bc | ||
|
|
c54b382775 | ||
|
|
184e2b646c | ||
|
|
8a8379c7eb | ||
|
|
8e8d827e00 | ||
|
|
2fad2e3ccd | ||
|
|
4c66d7f5ba | ||
|
|
124385fc31 | ||
|
|
5fe39f94ab | ||
|
|
e8d1645150 | ||
|
|
d1ea517f9a | ||
|
|
c6627d6266 | ||
|
|
2138ab05e5 | ||
|
|
ce3038fd8e | ||
|
|
555d00c9a8 | ||
|
|
12f013681a | ||
|
|
7a498310e2 | ||
|
|
9af58224fa | ||
|
|
61abdb57a7 | ||
|
|
e0cb0c70e1 | ||
|
|
420a05cabf | ||
|
|
262dd532e6 | ||
|
|
80ed6d1399 | ||
|
|
c04f1b57aa | ||
|
|
7aca92f2b3 | ||
|
|
e199278d6f | ||
|
|
f2a55bca55 | ||
|
|
bcd62aec6b | ||
|
|
c4e4330bd1 | ||
|
|
c70b53a162 | ||
|
|
3262def07c | ||
|
|
d049c13062 | ||
|
|
5ffed21e0e | ||
|
|
92ffda48ee | ||
|
|
91a4a325ae | ||
|
|
7cff5e58f0 | ||
|
|
17f0fc41d1 | ||
|
|
958e86f67e | ||
|
|
acb0118897 | ||
|
|
85a045c538 | ||
|
|
fbffe241e6 | ||
|
|
765fd1565a | ||
|
|
1a677c0b1d | ||
|
|
eeb8788413 | ||
|
|
c24ca68d63 | ||
|
|
e189dc3b1f | ||
|
|
ff8f391e91 | ||
|
|
0a9c2824ba | ||
|
|
dc37d3bf62 | ||
|
|
2780e6f3d7 | ||
|
|
260df58856 | ||
|
|
cba28a97a0 | ||
|
|
eca2203603 | ||
|
|
e926212554 | ||
|
|
65463b6efb | ||
|
|
9ac799bc95 | ||
|
|
7e4d757bdf | ||
|
|
1a8037cd6c | ||
|
|
dbc8a37b56 | ||
|
|
b1851ada93 | ||
|
|
c0799b0c1d | ||
|
|
e461710811 | ||
|
|
bea8e89cc7 | ||
|
|
17d66153b0 | ||
|
|
8ca0c11154 | ||
|
|
c4afc3d5c0 | ||
|
|
c22d51e439 | ||
|
|
aa052ae005 | ||
|
|
3f0b41ec3c |
3
.flake8
Normal file
@@ -0,0 +1,3 @@
|
||||
[flake8]
|
||||
ignore = E402,E501
|
||||
exclude = .git,__pycache__,build,data,piper/piper.py
|
||||
41
.gitignore
vendored
@@ -1,7 +1,5 @@
|
||||
*.o
|
||||
*.pc
|
||||
*.la
|
||||
*.lo
|
||||
*.swp
|
||||
*~
|
||||
*.sig
|
||||
@@ -10,43 +8,4 @@
|
||||
*.patch
|
||||
*.rej
|
||||
*.trs
|
||||
Makefile
|
||||
Makefile.in
|
||||
aclocal.m4
|
||||
autom4te.cache/
|
||||
config.guess
|
||||
config.h
|
||||
config.h.in
|
||||
config.log
|
||||
config.status
|
||||
config.sub
|
||||
configure
|
||||
depcomp
|
||||
install-sh
|
||||
libtool
|
||||
ltmain.sh
|
||||
missing
|
||||
stamp-h1
|
||||
.libs/
|
||||
.deps/
|
||||
src/libratbag-version.h
|
||||
doc/libratbag.doxygen
|
||||
doc/html
|
||||
tags
|
||||
test-driver
|
||||
compile
|
||||
m4
|
||||
symbols-leak-test
|
||||
symbols-leak-test.log
|
||||
test-build-cxx
|
||||
test-build-linker
|
||||
test-build-pedantic-c99
|
||||
test-build-std-gnuc90
|
||||
test-suite.log
|
||||
test-context
|
||||
test-device
|
||||
test-*.log
|
||||
ratbag-command
|
||||
hidpp10-dump-page
|
||||
hidpp20-dump-page
|
||||
lur-command
|
||||
|
||||
3
COPYING
@@ -1,4 +1,5 @@
|
||||
Copyright © 2015 Red Hat, Inc.
|
||||
Copyright © 2015-2017 Red Hat, Inc.
|
||||
Copyright © 2015 David Herrmann <dh.herrmann@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
SUBDIRS = src doc test tools hwdb data
|
||||
|
||||
ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
|
||||
|
||||
valgrind:
|
||||
(cd test; $(MAKE) valgrind)
|
||||
170
README.md
@@ -1,28 +1,110 @@
|
||||
/*!@mainpage
|
||||
|
||||
libratbag
|
||||
=========
|
||||
|
||||
libratbag is a configuration library for gaming mice. It provides a generic
|
||||
way to access the various features exposed by these mice and abstracts away
|
||||
hardware-specific and kernel-specific quirks.
|
||||
<img src="https://libratbag.github.io/_images/logo.svg" alt="" width="30%" align="right">
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
libratbag provides **ratbagd**, a DBus daemon to configure gaming mice.
|
||||
The daemon provides a generic way to access the various features exposed by
|
||||
these mice and abstracts away hardware-specific and kernel-specific quirks.
|
||||
|
||||
API documentation is available here:
|
||||
libratbag currently supports devices from Logitech, Etekcity, GSkill,
|
||||
Roccat, Steelseries. See [the device
|
||||
files](https://github.com/libratbag/libratbag/tree/master/data/devices) for
|
||||
a complete list of supported devices.
|
||||
|
||||
http://libratbag.github.io/libratbag/
|
||||
Users interact through a GUI like
|
||||
[Piper](https://github.com/libratbag/piper/). For developers, the
|
||||
`ratbagctl` tool is the prime tool for debugging.
|
||||
|
||||
Architecture
|
||||
------------
|
||||
Installing libratbag from system packages
|
||||
-----------------------------------------
|
||||
|
||||
libratbag has two main components, the front-end API and wrapper code, and
|
||||
the back-end HW-specific drivers:
|
||||
libratbag is packaged for some distributions, you can use your system's
|
||||
package manager to install it. See [the
|
||||
wiki](https://github.com/libratbag/libratbag/wiki/Installation) for details.
|
||||
|
||||
+-----+ +-----+ +-----------+ +----------+
|
||||
| app | -> | API | -> | hw-driver | -> | protocol | -> device
|
||||
+-----+ +-----+ +-----------+ +----------+
|
||||
Compiling libratbag
|
||||
-------------------
|
||||
|
||||
libratbag uses the [meson build system](http://mesonbuild.com) which in
|
||||
turn uses ninja to invoke the compiler. Run the following commands to clone
|
||||
libratbag and initialize the build:
|
||||
|
||||
git clone https://github.com/libratbag/libratbag.git
|
||||
cd libratbag
|
||||
meson builddir
|
||||
ninja -C builddir
|
||||
sudo ninja -C builddir install
|
||||
|
||||
The default prefix is `/usr/local`, i.e. it will not overwrite the system
|
||||
installation. For more information, see [the
|
||||
wiki](https://github.com/libratbag/libratbag/wiki/Installation).
|
||||
|
||||
And to build or re-build after code-changes, run:
|
||||
|
||||
ninja -C builddir
|
||||
sudo ninja -C builddir install
|
||||
|
||||
Note: `builddir` is the build output directory and can be changed to any
|
||||
other directory name. To set configure-time options, use e.g.
|
||||
|
||||
meson configure builddir -Ddocumentation=false
|
||||
|
||||
Run `meson configure builddir` to list the options.
|
||||
|
||||
Running ratbagd as DBus-activated systemd service
|
||||
-------------------------------------------------
|
||||
|
||||
To run ratbagd, simply run it as root `sudo ratbagd`. However,
|
||||
ratbagd is intended to run as dbus-activated systemd service and installs
|
||||
the following files:
|
||||
|
||||
/usr/share/dbus-1/system.d/org.freedesktop.ratbag1.conf
|
||||
/usr/share/dbus-1/system-services/org.freedesktop.ratbag1.conf
|
||||
/usr/share/systemd/system/ratbagd.service
|
||||
|
||||
These files are installed into the prefix by `ninja install`, see also the
|
||||
configure-time options `-Dsystemd-unit-dir` and `-Ddbus-root-dir`.
|
||||
Developers are encouraged to simply symlink to the files in the git
|
||||
repository.
|
||||
|
||||
For the files to take effect, you should run
|
||||
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl reload dbus.service
|
||||
|
||||
And finally, to enable the service:
|
||||
|
||||
sudo systemctl enable ratbagd.service
|
||||
|
||||
This places the required symlink into the systemd directory so that dbus
|
||||
activation is possible.
|
||||
|
||||
The DBus Interface
|
||||
-------------------
|
||||
|
||||
Full documentation of the DBus interface to interact with devices is
|
||||
available here: [ratbagd DBus Interface description](https://libratbag.github.io/).
|
||||
|
||||
libratbag Internal Architecture
|
||||
-------------------------------
|
||||
|
||||
libratbag has two main components, libratbag and ratbagd. Applications like
|
||||
Piper talk over DBus to ratbagd. ratbagd uses libratbag to access the actual
|
||||
devices.
|
||||
|
||||
+-------+ +------+ +---------+ +-----------+
|
||||
| Piper | -> | DBus | -> | ratbagd | -> | libratbag | -> device
|
||||
+-------+ +------+ +---------+ +-----------+
|
||||
|
||||
|
||||
Inside libratbag, we have the general frontend and API. Each device is
|
||||
handled by a HW-specific backend. That HW backend is responsible for the
|
||||
device-specific communication (usually some vendor-specific HID protocol).
|
||||
|
||||
+---------+ +-----+ +------------+ +----------+
|
||||
| ratbagd | -> | API | -> | hw backend | -> | protocol | -> device
|
||||
+---------+ +-----+ +------------+ +----------+
|
||||
|
||||
The API layer is HW agnostic. Depend on the HW, the protocol may be part of
|
||||
the driver implementation (e.g. etekcity) or a separate set of files
|
||||
@@ -31,36 +113,24 @@ implemented. The HW driver then only accesses the bits required for
|
||||
libratbag. This allows us to optionally export the protocol as separate
|
||||
library in the future, if other projects require it.
|
||||
|
||||
Adding Devices
|
||||
--------------
|
||||
Adding Devices to libratbag
|
||||
---------------------------
|
||||
|
||||
As of commit 3605bede4 libratbag now uses a hwdb entry to match the device
|
||||
with the drivers. To access a device through libratbag, the udev property
|
||||
RATBAG_DRIVER must be set for a device's event node. Check with
|
||||
libratbag relies on a device database to match a device with the drivers.
|
||||
See the [data/devices/](https://github.com/libratbag/libratbag/tree/master/data/devices)
|
||||
directory for the set of known devices. These files
|
||||
are usually installed into `$prefix/$datadir` (e.g. `/usr/share/libratbag/`).
|
||||
|
||||
sudo udevadm info /sys/class/input/eventX | grep RATBAG_DRIVER
|
||||
Adding a new device can be as simple as adding a new `.device` file. This is
|
||||
the case for many devices with a shared protocol (e.g. Logitech's HID++).
|
||||
See the
|
||||
[data/devices/device.example](https://github.com/libratbag/libratbag/tree/master/data/devices/device.example)
|
||||
file for guidance on what information must be set. Look for existing devices
|
||||
from the same vendor as guidance too.
|
||||
|
||||
If your device is not yet assigned the property, it is not in the hwdb. It
|
||||
may however be supported by one of our existing drivers. Try enabling it by
|
||||
adding the device vendor-id/product-id to the hwdb file in
|
||||
`hwdb/70-libratbag-mouse.hwdb`. For example, for a HID++ 1.0 device, edit
|
||||
the 70-libratbag-mouse.hwdb file and add an entry with `RATBAG_DRIVER=hidpp10`.
|
||||
For the other drivers, look for the id of the driver in driver-{drivername}.c
|
||||
file and do the same.
|
||||
|
||||
Once your device is added to the hwdb, install libratbag and trigger a hwdb
|
||||
update:
|
||||
|
||||
sudo udevadm hwdb --update
|
||||
sudo udevadm control --reload
|
||||
|
||||
Then unplug/replug your mouse. `RATBAG_DRIVER` should appear in the udev
|
||||
properties of your device with the value you previously set. If the property
|
||||
is not assigned, the hwdb entry does not correctly match your device or the
|
||||
installed udev rules/hwdb entries are not picked up by udev.
|
||||
|
||||
If the device doesn't work, you'll have to start reverse-engineering the
|
||||
device-specific protocol. Good luck :)
|
||||
If the device has a different protocol and doesn't work after adding the
|
||||
device file, you'll have to start reverse-engineering the device-specific
|
||||
protocol. Good luck :)
|
||||
|
||||
Source
|
||||
------
|
||||
@@ -70,20 +140,20 @@ Source
|
||||
Bugs
|
||||
----
|
||||
|
||||
Bugs can be reported in the issue tracker on our github repo:
|
||||
https://github.com/libratbag/libratbag/issues
|
||||
Bugs can be reported in [our issue tracker](https://github.com/libratbag/libratbag/issues)
|
||||
|
||||
Mailing list
|
||||
------------
|
||||
|
||||
libratbag discussions happen on the input-tools mailing list hosted on
|
||||
freedesktop.org: http://lists.freedesktop.org/archives/input-tools/
|
||||
libratbag discussions happen on the [input-tools mailing
|
||||
list](http://lists.freedesktop.org/archives/input-tools/) hosted on
|
||||
freedesktop.org
|
||||
|
||||
Device-specific notes
|
||||
---------------------
|
||||
|
||||
A number of device-specific notes and observations can be found in our
|
||||
"device-notes" repository: http://libratbag.github.io/device-notes/
|
||||
wiki: https://github.com/libratbag/libratbag/wiki/Devices
|
||||
|
||||
License
|
||||
-------
|
||||
@@ -99,6 +169,4 @@ libratbag is licensed under the MIT license.
|
||||
|
||||
See the COPYING file for the full license information.
|
||||
|
||||
[](https://semaphoreci.com/libratbag/libratbag)
|
||||
|
||||
*/
|
||||
[](https://circleci.com/gh/libratbag/libratbag)
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
test -n "$srcdir" || srcdir=`dirname "$0"`
|
||||
test -n "$srcdir" || srcdir=.
|
||||
(
|
||||
cd "$srcdir" &&
|
||||
autoreconf --force -v --install
|
||||
) || exit
|
||||
test -n "$NOCONFIGURE" || "$srcdir/configure" "$@"
|
||||
224
circle.yml
Normal file
@@ -0,0 +1,224 @@
|
||||
# vim: set expandtab shiftwidth=2 tabstop=8:
|
||||
libratbag_references:
|
||||
default_settings: &default_settings
|
||||
working_directory: ~/libratbag
|
||||
environment:
|
||||
LANG: C.UTF-8
|
||||
build_default: &build_default
|
||||
name: Build
|
||||
command: |
|
||||
rm -rf build
|
||||
meson build ${MESON_PARAMS}
|
||||
meson configure build
|
||||
ninja -v -C build ${NINJA_ARGS}
|
||||
environment:
|
||||
MESON_PARAMS: --prefix=/usr
|
||||
build_and_test: &build_and_test
|
||||
run:
|
||||
<<: *build_default
|
||||
name: Build and test
|
||||
environment:
|
||||
NINJA_ARGS: test
|
||||
build_with_docs: &build_with_docs
|
||||
run:
|
||||
<<: *build_default
|
||||
name: Build with documentation
|
||||
environment:
|
||||
MESON_PARAMS: -Ddocumentation=true
|
||||
install: &install
|
||||
run:
|
||||
name: Installing
|
||||
command: ninja -C build install
|
||||
check_install: &check_install
|
||||
run:
|
||||
name: Checking installation
|
||||
command: |
|
||||
PREFIX=/usr/local/
|
||||
diff -u <(cd data/devices; ls *.device) <(cd $PREFIX/share/libratbag/devices; ls *.device)
|
||||
check_uninstall: &check_uninstall
|
||||
run:
|
||||
name: Checking if any files are left after uninstall
|
||||
command: |
|
||||
PREFIX=/root/test_install
|
||||
# workaround until https://github.com/mesonbuild/meson/pull/2033 is merged
|
||||
# and a new release appears
|
||||
git clone https://github.com/whot/meson -b wip/remove-directories-on-uninstall
|
||||
./meson/meson.py build_install --prefix=$PREFIX
|
||||
ninja -C build_install install
|
||||
ninja -C build_install uninstall
|
||||
if [ -d $PREFIX ]
|
||||
then
|
||||
tree $PREFIX
|
||||
exit 1
|
||||
fi
|
||||
export_logs: &export_logs
|
||||
store_artifacts:
|
||||
path: ~/libratbag/build/meson-logs
|
||||
start_dbus: &start_dbus
|
||||
run:
|
||||
name: Start dbus daemon
|
||||
command: |
|
||||
mkdir /run/dbus
|
||||
/usr/bin/dbus-daemon --system --fork
|
||||
|
||||
fedora_prep_cache: &fedora_prep_cache
|
||||
<<: *default_settings
|
||||
steps:
|
||||
- run:
|
||||
name: Initializing Fedora dnf cache
|
||||
command: dnf install -y --downloadonly libsolv tree git gcc gcc-c++ meson check-devel libudev-devel libevdev-devel valgrind python3-gobject python3-evdev glib2-devel python3-lxml
|
||||
- persist_to_workspace:
|
||||
root: /var/cache/
|
||||
paths:
|
||||
- dnf/*
|
||||
|
||||
fedora_fetch_cache: &fedora_fetch_cache
|
||||
attach_workspace:
|
||||
at: /var/cache/
|
||||
|
||||
fedora_install: &fedora_install
|
||||
run:
|
||||
name: Install prerequisites
|
||||
command: |
|
||||
echo keepcache=1 >> /etc/dnf/dnf.conf
|
||||
dnf upgrade -y libsolv
|
||||
dnf install -y tree git gcc gcc-c++ meson check-devel libudev-devel libevdev-devel valgrind python3-gobject python3-evdev glib2-devel python3-lxml python3-devel swig
|
||||
|
||||
|
||||
fedora_settings: &fedora_settings
|
||||
<<: *default_settings
|
||||
steps:
|
||||
- *fedora_fetch_cache
|
||||
- *fedora_install
|
||||
- checkout
|
||||
- *start_dbus
|
||||
- *build_and_test
|
||||
- *install
|
||||
- *check_install
|
||||
- *check_uninstall
|
||||
- *export_logs
|
||||
|
||||
|
||||
ubuntu_settings: &ubuntu_settings
|
||||
<<: *default_settings
|
||||
steps:
|
||||
- run:
|
||||
name: Install prerequisites
|
||||
command: |
|
||||
apt-get update
|
||||
apt-get install -y software-properties-common
|
||||
add-apt-repository universe
|
||||
apt-get update
|
||||
apt-get install -y tree git gcc g++ pkg-config meson check libudev-dev libevdev-dev libsystemd-dev valgrind python3-gi python3-evdev libglib2.0-dev python3-lxml python3-dev swig systemd
|
||||
- checkout
|
||||
- *start_dbus
|
||||
- *build_and_test
|
||||
- *install
|
||||
- *check_install
|
||||
- *check_uninstall
|
||||
- *export_logs
|
||||
|
||||
doc_build: &doc_build
|
||||
<<: *default_settings
|
||||
steps:
|
||||
- *fedora_fetch_cache
|
||||
- *fedora_install
|
||||
- run:
|
||||
name: Install documentation build-deps
|
||||
command: dnf install -y python3-sphinx python3-sphinx_rtd_theme
|
||||
- checkout
|
||||
- *build_with_docs
|
||||
- *export_logs
|
||||
- store_artifacts:
|
||||
path: ~/libratbag/build/doc/html
|
||||
- persist_to_workspace:
|
||||
root: build
|
||||
paths:
|
||||
- doc/html/*
|
||||
|
||||
docs_deploy: &docs_deploy
|
||||
<<: *default_settings
|
||||
steps:
|
||||
- *fedora_fetch_cache
|
||||
- run:
|
||||
name: Install prerequisites
|
||||
command: dnf install -y git tree
|
||||
- checkout
|
||||
- attach_workspace:
|
||||
at: build
|
||||
- run:
|
||||
name: Setup the deploy SSH key
|
||||
command: |
|
||||
ssh-add -L | tail -n1 > ~/.ssh/deploy.pub
|
||||
cat <<EOF > ~/.ssh/config
|
||||
Host github.com
|
||||
IdentityFile /root/.ssh/deploy.pub
|
||||
IdentitiesOnly yes
|
||||
EOF
|
||||
- run:
|
||||
name: Clone doc repository
|
||||
command: |
|
||||
cd ~
|
||||
git clone ssh://git@github.com/${CIRCLE_PROJECT_REPONAME}/${CIRCLE_PROJECT_REPONAME}.github.io
|
||||
- run:
|
||||
name: Copy the doc, commit and push
|
||||
command: |
|
||||
set +e
|
||||
cd ~/${CIRCLE_PROJECT_REPONAME}.github.io
|
||||
\cp -r ~/${CIRCLE_PROJECT_REPONAME}/build/doc/html/* .
|
||||
if ! git diff-index --quiet HEAD --; then
|
||||
git config --global user.email "libratbag@librabtag.github.io"
|
||||
git config --global user.name "The libratbag crew"
|
||||
git add .
|
||||
git commit -m "update docs from ${CIRCLE_SHA1}"
|
||||
git push
|
||||
fi
|
||||
|
||||
version: 2
|
||||
jobs:
|
||||
fedora_rawhide:
|
||||
<<: *fedora_settings
|
||||
docker:
|
||||
- image: fedora:rawhide
|
||||
fedora_cache:
|
||||
<<: *fedora_prep_cache
|
||||
docker:
|
||||
- image: fedora:28
|
||||
fedora_latest:
|
||||
<<: *fedora_settings
|
||||
docker:
|
||||
- image: fedora:28
|
||||
ubuntu_17_10:
|
||||
<<: *ubuntu_settings
|
||||
docker:
|
||||
- image: ubuntu:artful
|
||||
doc_build:
|
||||
<<: *doc_build
|
||||
docker:
|
||||
- image: fedora:28
|
||||
doc_deploy:
|
||||
<<: *docs_deploy
|
||||
docker:
|
||||
- image: fedora:28
|
||||
|
||||
|
||||
workflows:
|
||||
version: 2
|
||||
compile_and_test:
|
||||
jobs:
|
||||
# - fedora_rawhide
|
||||
- fedora_cache
|
||||
- ubuntu_17_10
|
||||
- fedora_latest:
|
||||
requires:
|
||||
- fedora_cache
|
||||
- doc_build:
|
||||
requires:
|
||||
- fedora_cache
|
||||
- doc_deploy:
|
||||
requires:
|
||||
- fedora_cache
|
||||
- doc_build
|
||||
filters:
|
||||
branches:
|
||||
only: master
|
||||
164
configure.ac
@@ -1,164 +0,0 @@
|
||||
AC_PREREQ([2.64])
|
||||
|
||||
m4_define([libratbag_major_version], [0])
|
||||
m4_define([libratbag_minor_version], [5])
|
||||
m4_define([libratbag_micro_version], [0])
|
||||
m4_define([libratbag_version],
|
||||
[libratbag_major_version.libratbag_minor_version.libratbag_micro_version])
|
||||
|
||||
AC_INIT([libratbag],
|
||||
[libratbag_version],
|
||||
[],
|
||||
[libratbag],
|
||||
[])
|
||||
|
||||
AC_SUBST([LIBRATBAG_VERSION_MAJOR], [libratbag_major_version])
|
||||
AC_SUBST([LIBRATBAG_VERSION_MINOR], [libratbag_minor_version])
|
||||
AC_SUBST([LIBRATBAG_VERSION_MICRO], [libratbag_micro_version])
|
||||
AC_SUBST([LIBRATBAG_VERSION], [libratbag_version])
|
||||
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
|
||||
AM_INIT_AUTOMAKE([1.11 foreign no-dist-gzip dist-xz])
|
||||
|
||||
# Before making a release, the LIBRATBAG_LT_VERSION and LIBLUR_LT_VERSION
|
||||
# strings should be modified.
|
||||
# The strings are of the form C:R:A.
|
||||
# a) If binary compatibility has been broken (eg removed or changed interfaces)
|
||||
# change to C+1:0:0.
|
||||
# b) If interfaces have been changed or added, but binary compatibility has
|
||||
# been preserved, change to C+1:0:A+1
|
||||
# c) If the interface is the same as the previous version, change to C:R+1:A
|
||||
LIBRATBAG_LT_VERSION=3:1:0
|
||||
LIBLUR_LT_VERSION=3:1:0
|
||||
AC_SUBST(LIBRATBAG_LT_VERSION)
|
||||
AC_SUBST(LIBLUR_LT_VERSION)
|
||||
|
||||
AM_SILENT_RULES([yes])
|
||||
AC_USE_SYSTEM_EXTENSIONS
|
||||
|
||||
# Check for programs
|
||||
AC_PROG_CC_C99
|
||||
AC_PROG_CXX # Only used by build C++ test
|
||||
AC_PROG_GREP
|
||||
|
||||
# Initialize libtool
|
||||
LT_PREREQ([2.2])
|
||||
LT_INIT
|
||||
|
||||
PKG_PROG_PKG_CONFIG()
|
||||
PKG_CHECK_MODULES(LIBUDEV, [libudev])
|
||||
PKG_CHECK_MODULES(LIBEVDEV, [libevdev])
|
||||
|
||||
if test "x$GCC" = "xyes"; then
|
||||
GCC_CXXFLAGS="-Wall -Wextra -Wno-unused-parameter -g -fvisibility=hidden"
|
||||
GCC_CFLAGS="$GCC_CXXFLAGS -Wmissing-prototypes -Wstrict-prototypes"
|
||||
fi
|
||||
AC_SUBST(GCC_CFLAGS)
|
||||
AC_SUBST(GCC_CXXFLAGS)
|
||||
|
||||
AC_ARG_WITH(udev-base-dir, AS_HELP_STRING([--with-udev-base-dir=DIR], [where udev base directory is]))
|
||||
if test -n "$with_udev_base_dir" ; then
|
||||
UDEV_BASE_DIR="$with_udev_base_dir"
|
||||
else
|
||||
UDEV_BASE_DIR="$prefix/lib/udev"
|
||||
fi
|
||||
AC_SUBST(UDEV_BASE_DIR)
|
||||
|
||||
AC_ARG_ENABLE([documentation],
|
||||
[AC_HELP_STRING([--enable-documentation],
|
||||
[Enable building the documentation (default=auto)])],
|
||||
[build_documentation="$enableval"],
|
||||
[build_documentation="auto"])
|
||||
|
||||
if test "x$build_documentation" = "xyes" -o "x$build_documentation" = "xauto"; then
|
||||
AC_PATH_PROG(DOXYGEN, doxygen)
|
||||
if test "x$DOXYGEN" = "x"; then
|
||||
if test "x$build_documentation" = "xyes"; then
|
||||
AC_MSG_ERROR([Documentation build requested but doxygen not found. Install doxygen or disable the documentation using --disable-documentation])
|
||||
fi
|
||||
else
|
||||
AC_MSG_CHECKING([for compatible doxygen version])
|
||||
doxygen_version=`$DOXYGEN --version`
|
||||
AS_VERSION_COMPARE([$doxygen_version], [1.6.0],
|
||||
[AC_MSG_RESULT([no])
|
||||
DOXYGEN=""],
|
||||
[AC_MSG_RESULT([yes])],
|
||||
[AC_MSG_RESULT([yes])])
|
||||
if test "x$DOXYGEN" = "x" -a "x$build_documentation" = "xyes"; then
|
||||
AC_MSG_ERROR([Doxygen $doxygen_version too old. Doxygen 1.6+ required for documentation build. Install required doxygen version or disable the documentation using --disable-documentation])
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_PATH_PROG(DOT, dot)
|
||||
if test "x$DOT" = "x"; then
|
||||
if test "x$build_documentation" = "xyes"; then
|
||||
AC_MSG_ERROR([Documentation build requested but graphviz's dot not found. Install graphviz or disable the documentation using --disable-documentation])
|
||||
fi
|
||||
else
|
||||
AC_MSG_CHECKING([for compatible dot version])
|
||||
dot_version=`$DOT -V 2>&1|$GREP -oP '(?<=version\W)@<:@0-9.@:>@*(?=\W(.*))'`
|
||||
AS_VERSION_COMPARE([$dot_version], [2.26.0],
|
||||
[AC_MSG_RESULT([no])
|
||||
DOT=""],
|
||||
[AC_MSG_RESULT([yes])],
|
||||
[AC_MSG_RESULT([yes])])
|
||||
if test "x$DOT" = "x" -a "x$build_documentation" = "xyes"; then
|
||||
AC_MSG_ERROR([Graphviz dot $dot_version too old. Graphviz 2.26+ required for documentation build. Install required graphviz version or disable the documentation using --disable-documentation])
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "x$DOXYGEN" != "x" -a "x$DOT" != "x"; then
|
||||
build_documentation="yes"
|
||||
else
|
||||
build_documentation="no"
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE(tests,
|
||||
AS_HELP_STRING([--enable-tests], [Build the tests (default=auto)]),
|
||||
[build_tests="$enableval"],
|
||||
[build_tests="auto"])
|
||||
|
||||
PKG_CHECK_MODULES(CHECK, [check >= 0.9.10], [HAVE_CHECK="yes"], [HAVE_CHECK="no"])
|
||||
|
||||
if test "x$build_tests" = "xauto"; then
|
||||
build_tests="$HAVE_CHECK"
|
||||
fi
|
||||
if test "x$build_tests" = "xyes"; then
|
||||
if test "x$HAVE_CHECK" = "xno"; then
|
||||
AC_MSG_ERROR([Cannot build tests, check is missing])
|
||||
fi
|
||||
|
||||
AC_PATH_PROG(VALGRIND, [valgrind])
|
||||
fi
|
||||
|
||||
AC_DEFINE(BUILD_TESTS, [1], ["Build the test suite])
|
||||
AM_CONDITIONAL(HAVE_VALGRIND, [test "x$VALGRIND" != "x"])
|
||||
AM_CONDITIONAL(BUILD_TESTS, [test "x$build_tests" = "xyes"])
|
||||
AM_CONDITIONAL(BUILD_DOCS, [test "x$build_documentation" = "xyes"])
|
||||
|
||||
AC_CONFIG_FILES([Makefile
|
||||
data/Makefile
|
||||
doc/Makefile
|
||||
doc/libratbag.doxygen
|
||||
hwdb/Makefile
|
||||
src/Makefile
|
||||
src/libratbag.pc
|
||||
src/libratbag-version.h
|
||||
src/liblur.pc
|
||||
test/Makefile
|
||||
tools/Makefile])
|
||||
AC_CONFIG_FILES([test/symbols-leak-test],
|
||||
[chmod +x test/symbols-leak-test])
|
||||
AC_OUTPUT
|
||||
|
||||
AC_MSG_RESULT([
|
||||
Prefix ${prefix}
|
||||
udev base directory: ${UDEV_BASE_DIR}
|
||||
|
||||
Build documentation ${build_documentation}
|
||||
Build tests ${build_tests}
|
||||
Tests use valgrind ${VALGRIND}
|
||||
])
|
||||
@@ -1,2 +0,0 @@
|
||||
libratbagdatadir = $(datadir)/libratbag
|
||||
dist_libratbagdata_DATA = $(shell find $(top_srcdir)/data -name "*.svg" -printf "%P\n")
|
||||
@@ -1,20 +1,11 @@
|
||||
libratbag data files
|
||||
====================
|
||||
|
||||
These SVG files should approximate the device to make it immediately
|
||||
recognizable. Detail work not required, the graphic is an illustration only.
|
||||
This directory contains the SVG files for each theme. In general, device SVGs
|
||||
should approximate the device to make it immediately recognizable. Detail work
|
||||
not required, the graphic is an illustration only.
|
||||
|
||||
Requirements
|
||||
------------
|
||||
|
||||
- Canvas size: 750x750 pixels
|
||||
- Two layers in the final SVG: a lower layer named "Device" with the device
|
||||
itself, "Leaders" with the buttons and leader-lines
|
||||
- The device should be approximately centered on the canvas and occupy a
|
||||
meaningful portion of the canvas without making it look cramped
|
||||
- Button labels must be in 12pt Sans, starting with Button0
|
||||
- Wheel buttons may be labeled separately if required (look at the Etekcity
|
||||
for an example)
|
||||
For theme-specific requirements, consult the README in the subdirectories.
|
||||
|
||||
Technique
|
||||
---------
|
||||
|
||||
219
data/devices/data-parse-test.py
Executable file
@@ -0,0 +1,219 @@
|
||||
#!/usr/bin/env python3
|
||||
# vim: set expandtab shiftwidth=4 tabstop=4:
|
||||
#
|
||||
# Copyright © 2017 Red Hat, Inc.
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a
|
||||
# copy of this software and associated documentation files (the "Software"),
|
||||
# to deal in the Software without restriction, including without limitation
|
||||
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
# and/or sell copies of the Software, and to permit persons to whom the
|
||||
# Software is furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice (including the next
|
||||
# paragraph) shall be included in all copies or substantial portions of the
|
||||
# Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
# DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
# Device data verification script
|
||||
#
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import configparser
|
||||
|
||||
def assertIn(element, l):
|
||||
if element not in l:
|
||||
raise AssertionError('{} must be in {}'.format(element, l))
|
||||
|
||||
|
||||
def assertNotIn(element, l):
|
||||
if element in l:
|
||||
raise AssertionError('{} must not be in {}'.format(element, l))
|
||||
|
||||
|
||||
def check_match_str(string):
|
||||
bustypes = ['usb', 'bluetooth']
|
||||
|
||||
matches = string.split(';')
|
||||
for match in matches:
|
||||
if not match: # empty string if trailing ;
|
||||
continue
|
||||
|
||||
parts = match.split(':')
|
||||
assert(len(parts) == 3)
|
||||
assertIn(parts[0], bustypes)
|
||||
vid = parts[1]
|
||||
assert(vid == '{:04x}'.format(int(vid, 16)))
|
||||
pid = parts[2]
|
||||
assert(pid == '{:04x}'.format(int(pid, 16)))
|
||||
|
||||
|
||||
def check_ledtypes_str(string):
|
||||
permitted_types = ['logo', 'side', 'battery', 'dpi']
|
||||
|
||||
types = string.split(';')
|
||||
for t in types:
|
||||
if not t: # emtpy string if trailing ;
|
||||
continue
|
||||
|
||||
assertIn(t, permitted_types)
|
||||
|
||||
|
||||
def check_section_device(section):
|
||||
required_keys = ['Name', 'Driver', 'DeviceMatch']
|
||||
permitted_keys = required_keys + ['LedTypes']
|
||||
|
||||
for key in section.keys():
|
||||
assertIn(key, permitted_keys)
|
||||
|
||||
for r in required_keys:
|
||||
assertIn(r, section)
|
||||
|
||||
try:
|
||||
check_ledtypes_str(section['LedTypes'])
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
check_match_str(section['DeviceMatch'])
|
||||
|
||||
|
||||
def check_dpi_range_str(string):
|
||||
import re
|
||||
|
||||
m = re.search('^([0-9]+):([0-9]+)@([0-9\.]+)$', string)
|
||||
assert(m is not None)
|
||||
min = int(m.group(1))
|
||||
max = int(m.group(2))
|
||||
steps = float(m.group(3))
|
||||
|
||||
assert(min >= 0 and min <= 400)
|
||||
assert(max >= 2000 and max <= 12000)
|
||||
assert(steps > 0 and steps <= 100)
|
||||
|
||||
if int(steps) == steps:
|
||||
steps = int(steps)
|
||||
|
||||
assert(string == '{}:{}@{}'.format(min, max, steps))
|
||||
|
||||
|
||||
def check_dpi_list_str(string):
|
||||
entries = string.split(';')
|
||||
# Remove possible empty last entry if trailing with a ;
|
||||
if not entries[len(entries) - 1]:
|
||||
entries = entries[:-1]
|
||||
|
||||
for idx, entry in enumerate(entries):
|
||||
dpi = int(entry)
|
||||
assert(dpi >= 0 and dpi <= 12000)
|
||||
if idx > 0:
|
||||
prev = entries[idx - 1]
|
||||
prev_dpi = int(prev)
|
||||
assert(dpi > prev_dpi)
|
||||
|
||||
|
||||
def check_profile_type_str(string):
|
||||
types = ['G9', 'G500', 'G700']
|
||||
assertIn(string, types)
|
||||
|
||||
|
||||
def check_section_hidpp10(section):
|
||||
permitted = ['Profiles', 'ProfileType', 'DpiRange', 'DpiList', 'DeviceIndex', 'Leds']
|
||||
for key in section.keys():
|
||||
assertIn(key, permitted)
|
||||
|
||||
try:
|
||||
nprofiles = int(section['Profiles'])
|
||||
# 10 is arbitrarily chosen
|
||||
assert(nprofiles > 0 and nprofiles < 10)
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
try:
|
||||
index = int(section['DeviceIndex'])
|
||||
# 10 is arbitrarily chosen
|
||||
assert(index > 0 and index < 10)
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
try:
|
||||
check_dpi_range_str(section['DpiRange'])
|
||||
assertNotIn('DpiList', section.keys())
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
try:
|
||||
check_dpi_list_str(section['DpiList'])
|
||||
assertNotIn('DpiRange', section.keys())
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
try:
|
||||
check_profile_type_str(section['ProfileType'])
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
try:
|
||||
leds = int(section['Leds'])
|
||||
# 10 is arbitrarily chosen
|
||||
assert(leds > 0 and leds < 10)
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
|
||||
def check_section_hidpp20(section):
|
||||
permitted = ['DeviceIndex']
|
||||
for key in section.keys():
|
||||
assertIn(key, permitted)
|
||||
|
||||
try:
|
||||
index = int(section['DeviceIndex'])
|
||||
# 10 is arbitrarily chosen
|
||||
assert(index > 0 and index < 10)
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
|
||||
def check_section_driver(driver, section):
|
||||
if driver == 'hidpp10':
|
||||
check_section_hidpp10(section)
|
||||
elif driver == 'hidpp20':
|
||||
check_section_hidpp20(section)
|
||||
else:
|
||||
assert('Unsupported driver section {}'.format(driver))
|
||||
|
||||
|
||||
def parse_data_file(path):
|
||||
print('Parsing file {}'.format(path))
|
||||
data = configparser.ConfigParser(strict=True)
|
||||
# Don't convert to lowercase
|
||||
data.optionxform = lambda option: option
|
||||
data.read(path)
|
||||
|
||||
assertIn('Device', data.sections())
|
||||
check_section_device(data['Device'])
|
||||
|
||||
driver = data['Device']['Driver']
|
||||
driver_section = 'Driver/{}'.format(driver)
|
||||
|
||||
permitted_sections = ['Device', driver_section]
|
||||
for s in data.sections():
|
||||
assertIn(s, permitted_sections)
|
||||
|
||||
if data.has_section(driver_section):
|
||||
check_section_driver(driver, data[driver_section])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(description="Device data-file checker")
|
||||
parser.add_argument('file', nargs='+')
|
||||
args = parser.parse_args()
|
||||
for path in args.file:
|
||||
parse_data_file(path)
|
||||
54
data/devices/device.example
Normal file
@@ -0,0 +1,54 @@
|
||||
# Example description file for a libratbag device
|
||||
#
|
||||
# Make sure the file has a recognizable name with a '.device' suffix
|
||||
|
||||
[Device]
|
||||
# The kernel name of the device. This name is not used by libratbag, it is
|
||||
# used by debugging tools.
|
||||
Name=Logitech Example Device
|
||||
|
||||
# DeviceMatch is a triplet of bus:vid:pid, where bus is 'usb' or bluetooth'
|
||||
# and pid/vid are lowercase 4-digit hexadecimal numbers with preceding
|
||||
# zeroes.
|
||||
DeviceMatch=usb:12ab:00f2
|
||||
|
||||
# The libratbag driver backend
|
||||
Driver=hidpp10
|
||||
|
||||
# The types of the LEDs, in the indexed order they appear in, separated by a
|
||||
# semicolon.
|
||||
# Allowed values: logo, side, battery, dpi
|
||||
LedTypes=logo;side
|
||||
|
||||
# Only one group of driver-specific properties is permitted and it must be
|
||||
# [Driver/<drivername>]. It is a bug do have any other [Driver/foo] group in
|
||||
# a device file, but this example file lists all.
|
||||
|
||||
[Driver/hidpp10]
|
||||
# The number of profiles, must be greater than 0
|
||||
Profiles=1
|
||||
|
||||
# The type of the profile
|
||||
ProfileType=G9
|
||||
|
||||
# The range of available resolutions in the form min:max@step
|
||||
# Mutually exclusive with DpiList
|
||||
DpiRange=50:5700@50
|
||||
|
||||
# The list of available resolutions, separated by semicolons.
|
||||
# Mutually exclusive with DpiRange
|
||||
# Where possible, DpiRange should be preferred
|
||||
DpiList=50;200;400;800
|
||||
|
||||
# The HID++ 1.0 device index
|
||||
# Should be unset unless required
|
||||
# DeviceIndex=1
|
||||
|
||||
# The number of LEDs
|
||||
Leds=1
|
||||
|
||||
|
||||
[Driver/hidpp20]
|
||||
# The HID++ 2.0 device index
|
||||
# Should be unset unless required
|
||||
# DeviceIndex=1
|
||||
4
data/devices/etekcity-scroll-alpha.device
Normal file
@@ -0,0 +1,4 @@
|
||||
[Device]
|
||||
Name=Etekcity Scroll Alpha
|
||||
DeviceMatch=usb:1ea7:4011
|
||||
Driver=etekcity
|
||||
5
data/devices/gskill-MX-780.device
Normal file
@@ -0,0 +1,5 @@
|
||||
# G.Skill MX-780
|
||||
[Device]
|
||||
Name=G.Skill MX-780
|
||||
DeviceMatch=usb:28da:3101
|
||||
Driver=gskill
|
||||
5
data/devices/logitech-M325.device
Normal file
@@ -0,0 +1,5 @@
|
||||
# Logitech M325 over unifying
|
||||
[Device]
|
||||
Name=Logitech M325
|
||||
DeviceMatch=usb:046d:400a
|
||||
Driver=hidpp20
|
||||
5
data/devices/logitech-M570.device
Normal file
@@ -0,0 +1,5 @@
|
||||
# Logitech M570
|
||||
[Device]
|
||||
Name=Logitech M570
|
||||
DeviceMatch=usb:046d:1028
|
||||
Driver=hidpp10
|
||||
5
data/devices/logitech-M705.device
Normal file
@@ -0,0 +1,5 @@
|
||||
# Logitech M705
|
||||
[Device]
|
||||
Name=Logitech M705
|
||||
DeviceMatch=usb:046d:101b
|
||||
Driver=hidpp10
|
||||
4
data/devices/logitech-MX-Anywhere2.device
Normal file
@@ -0,0 +1,4 @@
|
||||
[Device]
|
||||
Name=Logitech MX Anywhere 2
|
||||
DeviceMatch=usb:046d:404a;bluetooth:046d:b013
|
||||
Driver=hidpp20
|
||||
4
data/devices/logitech-MX-Anywhere2S.device
Normal file
@@ -0,0 +1,4 @@
|
||||
[Device]
|
||||
Name=Logitech MX Anywhere 2S
|
||||
DeviceMatch=usb:046d:406a
|
||||
Driver=hidpp20
|
||||
5
data/devices/logitech-MX-Master-2S.device
Normal file
@@ -0,0 +1,5 @@
|
||||
# Logitech MX Master 2S
|
||||
[Device]
|
||||
Name=Logitech MX Master 2S
|
||||
DeviceMatch=bluetooth:046d:b019;usb:046d:4069
|
||||
Driver=hidpp20
|
||||
5
data/devices/logitech-MX-Master.device
Normal file
@@ -0,0 +1,5 @@
|
||||
# Logitech MX Master
|
||||
[Device]
|
||||
Name=Logitech MX Master
|
||||
DeviceMatch=usb:046d:4041;bluetooth:046d:b012;usb:046d:4060
|
||||
Driver=hidpp20
|
||||
5
data/devices/logitech-T650.device
Normal file
@@ -0,0 +1,5 @@
|
||||
# Logitech T650 over unifying
|
||||
[Device]
|
||||
Name=Logitech T650
|
||||
DeviceMatch=usb:046d:4101
|
||||
Driver=hidpp20
|
||||
5
data/devices/logitech-Wireless-Touchpad.device
Normal file
@@ -0,0 +1,5 @@
|
||||
# Logitech Wireless Touchpad (Unifying)
|
||||
[Device]
|
||||
Name=Logitech Wireless Touchpad
|
||||
DeviceMatch=usb:046d:4011
|
||||
Driver=hidpp20
|
||||
8
data/devices/logitech-g-pro-wireless.device
Normal file
@@ -0,0 +1,8 @@
|
||||
[Device]
|
||||
Name=Logitech G Pro Wireless
|
||||
DeviceMatch=usb:046d:c539;usb:046d:c088
|
||||
LedTypes=logo;battery;dpi;
|
||||
Driver=hidpp20
|
||||
|
||||
[Driver/hidpp20]
|
||||
DeviceIndex=1
|
||||
5
data/devices/logitech-g-pro.device
Normal file
@@ -0,0 +1,5 @@
|
||||
[Device]
|
||||
Name=Logitech Gaming Mouse G Pro
|
||||
DeviceMatch=usb:046d:c085
|
||||
Driver=hidpp20
|
||||
LedTypes=logo;side
|
||||
6
data/devices/logitech-g102-g203.device
Normal file
@@ -0,0 +1,6 @@
|
||||
# G102 and G203 (USB)
|
||||
[Device]
|
||||
Name=Logitech Gaming Mouse G102/G103
|
||||
DeviceMatch=usb:046d:c084
|
||||
Driver=hidpp20
|
||||
LedTypes=logo;side;
|
||||
5
data/devices/logitech-g300.device
Normal file
@@ -0,0 +1,5 @@
|
||||
# WARNING: this file was automatically converted and has not yet been vetted
|
||||
[Device]
|
||||
Name=Logitech G300
|
||||
DeviceMatch=usb:046d:c246
|
||||
Driver=logitech_g300
|
||||
6
data/devices/logitech-g302.device
Normal file
@@ -0,0 +1,6 @@
|
||||
# G302 over USB
|
||||
[Device]
|
||||
Name=Logitech Gaming Mouse G302
|
||||
DeviceMatch=usb:046d:c07f
|
||||
Driver=hidpp20
|
||||
LedTypes=logo;side;
|
||||
6
data/devices/logitech-g303.device
Normal file
@@ -0,0 +1,6 @@
|
||||
# G303 over USB
|
||||
[Device]
|
||||
Name=Logitech Gaming Mouse G303
|
||||
DeviceMatch=usb:046d:c080
|
||||
Driver=hidpp20
|
||||
LedTypes=logo;side;
|
||||
5
data/devices/logitech-g402.device
Normal file
@@ -0,0 +1,5 @@
|
||||
# Logitech G402 Gaming Mouse USB
|
||||
[Device]
|
||||
Name=Logitech G402 Gaming Mouse
|
||||
DeviceMatch=usb:046d:c07e
|
||||
Driver=hidpp20
|
||||
5
data/devices/logitech-g403.device
Normal file
@@ -0,0 +1,5 @@
|
||||
# Logitech G403
|
||||
[Device]
|
||||
Name=Logitech G403
|
||||
DeviceMatch=usb:046d:c082;usb:046d:c083
|
||||
Driver=hidpp20
|
||||
9
data/devices/logitech-g5-2007.device
Normal file
@@ -0,0 +1,9 @@
|
||||
# Name=Logitech G5 2007
|
||||
[Device]
|
||||
Name=Logitech G5
|
||||
DeviceMatch=usb:046d:c049
|
||||
Driver=hidpp10
|
||||
|
||||
[Driver/hidpp10]
|
||||
DpiList=400;800;1600;2000
|
||||
Profiles=1
|
||||
7
data/devices/logitech-g5.device
Normal file
@@ -0,0 +1,7 @@
|
||||
[Device]
|
||||
Name=G5
|
||||
DeviceMatch=usb:046d:c041
|
||||
Driver=hidpp10
|
||||
|
||||
[Driver/hidpp10]
|
||||
DpiList=400;800;1600;2000
|
||||
9
data/devices/logitech-g500.device
Normal file
@@ -0,0 +1,9 @@
|
||||
[Device]
|
||||
Name=Logitech G500
|
||||
DeviceMatch=usb:046d:c068
|
||||
Driver=hidpp10
|
||||
|
||||
[Driver/hidpp10]
|
||||
DpiRange=0:5700@23.53
|
||||
ProfileType=G500
|
||||
Profiles=1
|
||||
9
data/devices/logitech-g500s.device
Normal file
@@ -0,0 +1,9 @@
|
||||
[Device]
|
||||
Name=Logitech G500s
|
||||
DeviceMatch=usb:046d:c24e
|
||||
Driver=hidpp10
|
||||
|
||||
[Driver/hidpp10]
|
||||
DpiRange=0:8200@50
|
||||
ProfileType=G500
|
||||
Profiles=1
|
||||
5
data/devices/logitech-g502-HERO-over-USB.device
Normal file
@@ -0,0 +1,5 @@
|
||||
# Logitech G502 HERO over USB
|
||||
[Device]
|
||||
Name=Logitech G502 HERO
|
||||
DeviceMatch=usb:046d:c08b
|
||||
Driver=hidpp20
|
||||
5
data/devices/logitech-g502-Proteus-Core-over-USB.device
Normal file
@@ -0,0 +1,5 @@
|
||||
# Logitech G502 Proteus Core over USB
|
||||
[Device]
|
||||
Name=Logitech G502 Proteus Core
|
||||
DeviceMatch=usb:046d:c07d
|
||||
Driver=hidpp20
|
||||
@@ -0,0 +1,5 @@
|
||||
# Logitech G502 Proteus Spectrum over USB
|
||||
[Device]
|
||||
Name=Logitech G502 Proteus Spectrum
|
||||
DeviceMatch=usb:046d:c332
|
||||
Driver=hidpp20
|
||||
5
data/devices/logitech-g600.device
Normal file
@@ -0,0 +1,5 @@
|
||||
# WARNING: this file was automatically converted and has not yet been vetted
|
||||
[Device]
|
||||
Name=Logitech G600
|
||||
DeviceMatch=usb:046d:c24a
|
||||
Driver=logitech_g600
|
||||
8
data/devices/logitech-g602.device
Normal file
@@ -0,0 +1,8 @@
|
||||
# Logitech G602 over wireless USB
|
||||
[Device]
|
||||
Name=Logitech G602
|
||||
DeviceMatch=usb:046d:c537
|
||||
Driver=hidpp20
|
||||
|
||||
[Driver/hidpp20]
|
||||
DeviceIndex=1
|
||||
5
data/devices/logitech-g603.device
Normal file
@@ -0,0 +1,5 @@
|
||||
# Logitech G603
|
||||
[Device]
|
||||
Name=Logitech G603
|
||||
DeviceMatch=bluetooth:046d:b01c
|
||||
Driver=hidpp20
|
||||
9
data/devices/logitech-g7.device
Normal file
@@ -0,0 +1,9 @@
|
||||
# Logitech G7
|
||||
# http://support.logitech.com/en_us/product/g7-laser-cordless-mouse/specs
|
||||
[Device]
|
||||
Name=Logitech G7
|
||||
DeviceMatch=usb:046d:c51a
|
||||
Driver=hidpp10
|
||||
|
||||
[Driver/hidpp10]
|
||||
Profiles=1
|
||||
12
data/devices/logitech-g700-wireless.device
Normal file
@@ -0,0 +1,12 @@
|
||||
# Logitech G700 over wireless USB
|
||||
# http://support.logitech.com/en_us/product/wireless-gaming-mouse-g700/specs
|
||||
[Device]
|
||||
Name=Logitech G700
|
||||
DeviceMatch=usb:046d:c531
|
||||
Driver=hidpp10
|
||||
|
||||
[Driver/hidpp10]
|
||||
DpiRange=0:5700@23.53
|
||||
ProfileType=G700
|
||||
DeviceIndex=1
|
||||
Profiles=5
|
||||
11
data/devices/logitech-g700.device
Normal file
@@ -0,0 +1,11 @@
|
||||
# Logitech G700 over USB
|
||||
# http://support.logitech.com/en_us/product/wireless-gaming-mouse-g700/specs
|
||||
[Device]
|
||||
Name=Logitech G700
|
||||
DeviceMatch=usb:046d:c06b
|
||||
Driver=hidpp10
|
||||
|
||||
[Driver/hidpp10]
|
||||
DpiRange=0:5700@23.53
|
||||
ProfileType=G700
|
||||
Profiles=5
|
||||
12
data/devices/logitech-g700s-wireless.device
Normal file
@@ -0,0 +1,12 @@
|
||||
# Logitech G700s over wireless USB
|
||||
# http://support.logitech.com/en_us/product/g700s-rechargable-wireless-gaming-mouse/specs
|
||||
[Device]
|
||||
Name=Logitech G700s
|
||||
DeviceMatch=usb:046d:c531
|
||||
Driver=hidpp10
|
||||
|
||||
[Driver/hidpp10]
|
||||
DpiRange=0:8200@50
|
||||
ProfileType=G700
|
||||
DeviceIndex=1
|
||||
Profiles=5
|
||||
11
data/devices/logitech-g700s.device
Normal file
@@ -0,0 +1,11 @@
|
||||
# Logitech G700s over USB
|
||||
# http://support.logitech.com/en_us/product/g700s-rechargable-wireless-gaming-mouse/specs
|
||||
[Device]
|
||||
Name=Logitech G700s
|
||||
DeviceMatch=usb:046d:c07c
|
||||
Driver=hidpp10
|
||||
|
||||
[Driver/hidpp10]
|
||||
DpiRange=0:8200@50
|
||||
ProfileType=G700
|
||||
Profiles=5
|
||||
5
data/devices/logitech-g703.device
Normal file
@@ -0,0 +1,5 @@
|
||||
[Device]
|
||||
Name=Logitech G703
|
||||
DeviceMatch=usb:046d:c087
|
||||
Driver=hidpp20
|
||||
|
||||
13
data/devices/logitech-g9.device
Normal file
@@ -0,0 +1,13 @@
|
||||
# Logitech G9
|
||||
# http://support.logitech.com/en_us/product/g9-laser-mouse/specs
|
||||
[Device]
|
||||
Name=Logitech G9
|
||||
DeviceMatch=usb:046d:c048
|
||||
LedTypes=dpi
|
||||
Driver=hidpp10
|
||||
|
||||
[Driver/hidpp10]
|
||||
DpiList=200;400;600;800;1000;1200;1400;1600;1800;2000;2200;2400;2600;2800;3000;3200
|
||||
ProfileType=G9
|
||||
Profiles=5
|
||||
Leds=1
|
||||
8
data/devices/logitech-g900-wireless.device
Normal file
@@ -0,0 +1,8 @@
|
||||
# Logitech G900, G903, G603 and G403 over wireless USB
|
||||
[Device]
|
||||
Name=Logitech G900, G903, G603, G403
|
||||
DeviceMatch=usb:046d:c539
|
||||
Driver=hidpp20
|
||||
|
||||
[Driver/hidpp20]
|
||||
DeviceIndex=1
|
||||
5
data/devices/logitech-g900.device
Normal file
@@ -0,0 +1,5 @@
|
||||
# Logitech G900 over USB
|
||||
[Device]
|
||||
Name=Logitech G900
|
||||
DeviceMatch=usb:046d:c081
|
||||
Driver=hidpp20
|
||||
5
data/devices/logitech-g903.device
Normal file
@@ -0,0 +1,5 @@
|
||||
# Logitech G903 over USB
|
||||
[Device]
|
||||
Name=Logitech G903
|
||||
DeviceMatch=usb:046d:c086
|
||||
Driver=hidpp20
|
||||
11
data/devices/logitech-g9x-[Call-of-Duty-MW3-Edition].device
Normal file
@@ -0,0 +1,11 @@
|
||||
# Logitech G9x [Call of Duty MW3 Edition]
|
||||
# http://support.logitech.com/en_us/product/laser-mouse-g9x/specs
|
||||
[Device]
|
||||
Name=Logitech G9x [Call of Duty MW3 Edition]
|
||||
DeviceMatch=usb:046d:c249
|
||||
Driver=hidpp10
|
||||
|
||||
[Driver/hidpp10]
|
||||
DpiRange=0:5700@23.53
|
||||
ProfileType=G500
|
||||
Profiles=5
|
||||
11
data/devices/logitech-g9x-[Original].device
Normal file
@@ -0,0 +1,11 @@
|
||||
# Logitech G9x [Original]
|
||||
# http://support.logitech.com/en_us/product/g9x-laser-mouse/specs
|
||||
[Device]
|
||||
Name=G9x [Original]
|
||||
DeviceMatch=usb:046d:c066
|
||||
Driver=hidpp10
|
||||
|
||||
[Driver/hidpp10]
|
||||
DpiRange=0:5700@23.53
|
||||
ProfileType=G500
|
||||
Profiles=5
|
||||
8
data/devices/logitech-gpowerplay-wireless.device
Normal file
@@ -0,0 +1,8 @@
|
||||
# Logitech G PowerPlay mouse pad + wireless USB receiver.
|
||||
[Device]
|
||||
Name=Logitech G PowerPlay mouse pad.
|
||||
DeviceMatch=usb:046d:c53a
|
||||
Driver=hidpp20
|
||||
|
||||
[Driver/hidpp20]
|
||||
DeviceIndex=1
|
||||
4
data/devices/roccat-kone-xtd.device
Normal file
@@ -0,0 +1,4 @@
|
||||
[Device]
|
||||
Name=Roccat Kone XTD
|
||||
DeviceMatch=usb:1e7d:2e22
|
||||
Driver=roccat
|
||||
11
data/devices/steelseries-kinzu-v2.device
Normal file
@@ -0,0 +1,11 @@
|
||||
[Device]
|
||||
Name=SteelSeries Kinzu V2
|
||||
DeviceMatch=usb:1038:1378
|
||||
Driver=steelseries
|
||||
|
||||
[Driver/steelseries]
|
||||
DeviceVersion=1
|
||||
Buttons=3
|
||||
Leds=0
|
||||
DpiList=400;800;1600;3200
|
||||
MacroLength=0
|
||||
11
data/devices/steelseries-rival-310.device
Normal file
@@ -0,0 +1,11 @@
|
||||
[Device]
|
||||
Name=SteelSeries Rival 310
|
||||
DeviceMatch=usb:1038:1720
|
||||
Driver=steelseries
|
||||
|
||||
[Driver/steelseries]
|
||||
DeviceVersion=2
|
||||
Buttons=6
|
||||
Leds=2
|
||||
DpiRange=100:12000@100
|
||||
MacroLength=1
|
||||
11
data/devices/steelseries-rival-600.device
Normal file
@@ -0,0 +1,11 @@
|
||||
[Device]
|
||||
Name=SteelSeries Rival 600
|
||||
DeviceMatch=usb:1038:1724
|
||||
Driver=steelseries
|
||||
|
||||
[Driver/steelseries]
|
||||
DeviceVersion=3
|
||||
Buttons=7
|
||||
Leds=8
|
||||
DpiRange=100:12000@100
|
||||
MacroLength=1
|
||||
11
data/devices/steelseries-rival.device
Normal file
@@ -0,0 +1,11 @@
|
||||
[Device]
|
||||
Name=SteelSeries Rival
|
||||
DeviceMatch=usb:1038:1384
|
||||
Driver=steelseries
|
||||
|
||||
[Driver/steelseries]
|
||||
DeviceVersion=1
|
||||
Buttons=6
|
||||
Leds=2
|
||||
DpiRange=50:6500@50
|
||||
MacroLength=1
|
||||
11
data/devices/steelseries-sensei-310.device
Normal file
@@ -0,0 +1,11 @@
|
||||
[Device]
|
||||
Name=SteelSeries Sensei 310
|
||||
DeviceMatch=usb:1038:1722
|
||||
Driver=steelseries
|
||||
|
||||
[Driver/steelseries]
|
||||
DeviceVersion=2
|
||||
Buttons=8
|
||||
Leds=2
|
||||
DpiRange=100:12000@100
|
||||
MacroLength=1
|
||||
14
data/devices/steelseries-sensei-raw.device
Normal file
@@ -0,0 +1,14 @@
|
||||
[Device]
|
||||
Name=SteelSeries Sensei Raw
|
||||
DeviceMatch=usb:1038:1369
|
||||
Driver=steelseries
|
||||
LedTypes=logo;dpi
|
||||
|
||||
[Driver/steelseries]
|
||||
DeviceVersion=1
|
||||
Buttons=8
|
||||
Leds=1
|
||||
DpiRange=90:5670@90
|
||||
MacroLength=1
|
||||
MonoLed=1
|
||||
ShortButton=1
|
||||
@@ -1,482 +0,0 @@
|
||||
<?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:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="750"
|
||||
height="750"
|
||||
viewBox="0 0 750.00005 750"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.4 r9939"
|
||||
sodipodi:docname="etekcity.svg">
|
||||
<defs
|
||||
id="defs4">
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient4449">
|
||||
<stop
|
||||
style="stop-color:#a6a6a6;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop4451" />
|
||||
<stop
|
||||
style="stop-color:#484848;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop4453" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient4336">
|
||||
<stop
|
||||
style="stop-color:#898989;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop4338" />
|
||||
<stop
|
||||
style="stop-color:#898989;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop4340" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4449"
|
||||
id="linearGradient3237"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1.344964,0,0,1.344964,-138.13637,564.60502)"
|
||||
x1="31.968746"
|
||||
y1="18.546629"
|
||||
x2="31.968746"
|
||||
y2="29.577879" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4336"
|
||||
id="linearGradient3889"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.79176032,0,0,0.79176032,-529.7793,277.79557)"
|
||||
x1="97.085503"
|
||||
y1="74.08123"
|
||||
x2="95.471596"
|
||||
y2="200.83122" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4449"
|
||||
id="linearGradient3891"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1.344964,0,0,1.344964,-441.46063,314.40367)"
|
||||
x1="31.968746"
|
||||
y1="18.546629"
|
||||
x2="31.968746"
|
||||
y2="29.577879" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4336"
|
||||
id="linearGradient3921"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.79176032,0,0,0.79176032,-529.7793,277.79557)"
|
||||
x1="97.085503"
|
||||
y1="74.08123"
|
||||
x2="95.471596"
|
||||
y2="200.83122" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4449"
|
||||
id="linearGradient3923"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1.344964,0,0,1.344964,-441.46063,314.40367)"
|
||||
x1="31.968746"
|
||||
y1="18.546629"
|
||||
x2="31.968746"
|
||||
y2="29.577879" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="0.96038311"
|
||||
inkscape:cx="377.27056"
|
||||
inkscape:cy="338.13614"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer4"
|
||||
showgrid="false"
|
||||
showguides="true"
|
||||
inkscape:guide-bbox="true"
|
||||
fit-margin-top="50"
|
||||
fit-margin-left="50"
|
||||
fit-margin-right="50"
|
||||
fit-margin-bottom="50"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1099"
|
||||
inkscape:window-x="1920"
|
||||
inkscape:window-y="28"
|
||||
inkscape:window-maximized="1" />
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<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="layer5"
|
||||
inkscape:label="Device"
|
||||
transform="translate(647.36582,-57.672087)"
|
||||
style="display:inline">
|
||||
<g
|
||||
id="g3893"
|
||||
transform="translate(121.82639,-21.866275)">
|
||||
<g
|
||||
transform="matrix(0.79176032,0,0,0.79176032,-628.41671,192.05523)"
|
||||
style="fill:#000000;fill-opacity:1;stroke:none;display:inline"
|
||||
id="g4271">
|
||||
<path
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none"
|
||||
d="m 421.23361,409.14757 c 4.4349,4.09496 9.16721,10.86185 32.57742,27.27412 4.08118,24.47294 2.40765,48.35999 1.01015,67.42768 -1.3975,19.06769 -9.52288,85.7367 -30.55711,85.7367 l -41.92133,-6.18719 8.9651,-171.72593 32.38801,-150.26019 27.05315,-2.27284 -2.70689,27.21098 -26.19294,53.47495 z"
|
||||
id="path4249"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cczcccccccc" />
|
||||
<use
|
||||
style="fill:#000000;fill-opacity:1;stroke:none"
|
||||
x="0"
|
||||
y="0"
|
||||
xlink:href="#path4249"
|
||||
id="use4266"
|
||||
transform="matrix(-1,0,0,1,580.95786,0)"
|
||||
width="1469.2054"
|
||||
height="1013.322" />
|
||||
</g>
|
||||
<path
|
||||
sodipodi:nodetypes="cccccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4251"
|
||||
d="m -268.43146,403.53037 c -1.07689,19.01234 -1.64984,38.40264 -3.69907,56.68573 -2.36798,4.75208 -4.96718,7.8857 -7.59809,10.79728 l -13.59657,0 5.59859,-67.18309 z"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4253"
|
||||
d="m -281.12826,473.7127 -0.29993,6.19844 7.09822,5.79854 -2.19945,30.1924 -8.99773,9.59758 -0.29993,28.99271 -2.3994,3.59909 -14.59632,0 0,-84.47873 z"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline" />
|
||||
<use
|
||||
height="1013.322"
|
||||
width="1469.2054"
|
||||
transform="matrix(-1,0,0,1,-698.21665,-85.740335)"
|
||||
id="use4275"
|
||||
xlink:href="#path4251"
|
||||
y="0"
|
||||
x="0"
|
||||
style="display:inline" />
|
||||
<ellipse
|
||||
sodipodi:ry="36.875"
|
||||
sodipodi:rx="57.5"
|
||||
sodipodi:cy="231.07376"
|
||||
sodipodi:cx="290.47894"
|
||||
d="m 347.97894,231.07376 c 0,20.3655 -25.74362,36.875 -57.5,36.875 -31.75637,0 -57.5,-16.5095 -57.5,-36.875 0,-20.3655 25.74363,-36.875 57.5,-36.875 31.75638,0 57.5,16.5095 57.5,36.875 z"
|
||||
ry="36.875"
|
||||
rx="57.5"
|
||||
cy="231.07376"
|
||||
cx="290.47894"
|
||||
id="path4243"
|
||||
style="fill:#000000;fill-opacity:1;stroke:#ff0000;stroke-width:1.26300848;stroke-opacity:1;display:inline"
|
||||
transform="matrix(0.79176032,0,0,0.79176032,-628.41671,124.43258)" />
|
||||
<use
|
||||
height="1013.322"
|
||||
width="1469.2054"
|
||||
transform="matrix(-1,0,0,1,-698.21665,-85.740335)"
|
||||
id="use4277"
|
||||
xlink:href="#path4253"
|
||||
y="0"
|
||||
x="0"
|
||||
style="display:inline" />
|
||||
<path
|
||||
sodipodi:nodetypes="cccccscccccccccccccccccscccccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3441"
|
||||
d="m -401.08313,328.79009 0.26444,-40.70143 c -39.18883,7.37119 -44.1411,4.0242 -51.69484,0.84743 -19.57977,14.34842 -45.06471,30.13362 -73.61979,38.63234 -2.47282,19.58198 -2.71663,46.75085 -2.09075,66.56663 19.0204,10.56139 17.6053,33.92046 19.25741,48.34377 1.65211,14.4233 7.20626,94.24576 7.20626,94.24576 l -2.59797,21.72393 23.30745,43.04888 c -0.16213,7.00604 -0.46719,14.87323 -3.03251,37.40758 -7.15647,2.04323 -13.81042,1.56652 -20.02442,-1.10259 0.0912,10.91499 -0.68305,21.82736 0.56908,32.68021 11.24444,13.4205 16.39645,27.09393 56.20571,56.18715 l 6.498,11.63207 c 13.0739,7.46592 23.16933,11.65186 42.40866,14.95221 19.23933,-3.30035 29.33476,-7.48629 42.40866,-14.95221 l 6.498,-11.63207 c 39.80926,-29.09322 44.96127,-42.76665 56.2057,-56.18715 1.25213,-10.85285 0.47635,-21.76522 0.56754,-32.68021 -6.214,2.66911 -12.86641,3.14582 -20.02288,1.10259 -2.56532,-22.53435 -2.87037,-30.40154 -3.0325,-37.40758 l 23.3059,-43.04888 -2.59642,-21.72393 c 0,0 5.55415,-79.82246 7.20625,-94.24576 1.65211,-14.42331 0.23546,-37.78238 19.25586,-48.34377 0.62589,-19.81578 0.38362,-46.98465 -2.08919,-66.56663 -28.55509,-8.49872 -54.04157,-24.28392 -73.62134,-38.63234 -7.55373,3.17677 -12.50447,6.52376 -51.69329,-0.84743 l 0.26444,40.70143 z"
|
||||
style="fill:#282828;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4289"
|
||||
d="m -398.45459,328.52925 0,117.85034"
|
||||
style="fill:none;stroke:#ff0000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline" />
|
||||
<path
|
||||
sodipodi:nodetypes="cccccccccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4247"
|
||||
d="m -390.51793,495.35976 13.14911,20.077 24.31724,0 -19.22802,-64.1898 -26.14665,-13.56354 -26.14819,13.56354 -19.22802,64.1898 24.31879,0 13.14909,-20.077 z"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline" />
|
||||
<rect
|
||||
ry="3.2500002"
|
||||
rx="3.2500002"
|
||||
y="334.18024"
|
||||
x="-410.93967"
|
||||
height="59.523411"
|
||||
width="25.025282"
|
||||
id="rect4245"
|
||||
style="fill:#000000;fill-opacity:1;stroke:#ff0000;stroke-width:1;stroke-opacity:1;display:inline" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4311"
|
||||
d="m -408.76059,297.49061 c -14.10207,2.39851 -28.95919,4.88556 -42.94836,0.51186 -20.52977,14.9081 -42.9383,27.51676 -67.08004,35.5287 -1.79569,18.70085 -2.21232,37.56904 -1.4629,56.27529 14.36611,10.46486 18.14376,29.44442 18.67596,46.17572 1.42879,19.10333 3.31403,38.21183 4.78767,57.33922 l 94.06329,0.0603 0,-99.67829 -5.64129,0 c -1.42556,0 -2.57322,-1.14766 -2.57322,-2.57323 l 0,-54.37631 c 0,-1.42556 1.14766,-2.57322 2.57322,-2.57322 l 2.21136,0 c -2.89117,-5.43908 -2.75569,-17.98166 -2.75569,-23.06002 0,-6.57742 0.14421,-9.08623 0.15,-13.63002 z"
|
||||
style="fill:url(#linearGradient3921);fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline" />
|
||||
<use
|
||||
height="1013.322"
|
||||
width="1469.2054"
|
||||
transform="matrix(-1,0,0,1,-796.64968,2.010815e-6)"
|
||||
id="use4348"
|
||||
xlink:href="#path4311"
|
||||
y="0"
|
||||
x="0"
|
||||
style="display:inline" />
|
||||
<circle
|
||||
sodipodi:ry="13.13577"
|
||||
sodipodi:rx="13.13577"
|
||||
sodipodi:cy="194.21156"
|
||||
sodipodi:cx="165.89903"
|
||||
d="m 179.0348,194.21156 c 0,7.25469 -5.88108,13.13577 -13.13577,13.13577 -7.25468,0 -13.13577,-5.88108 -13.13577,-13.13577 0,-7.25468 5.88109,-13.13577 13.13577,-13.13577 7.25469,0 13.13577,5.88109 13.13577,13.13577 z"
|
||||
r="13.13577"
|
||||
cy="194.21156"
|
||||
cx="165.89903"
|
||||
id="path4352"
|
||||
style="fill:#898989;fill-opacity:1;stroke:none;display:inline"
|
||||
transform="matrix(0.79176032,0,0,0.79176032,-529.7793,210.17291)" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4357"
|
||||
d="m -420.59834,454.5406 c -5.60675,18.71514 -11.21351,37.43027 -16.82027,56.1454 5.1217,0 10.2434,0 15.3651,0 4.38485,-6.69216 8.76766,-13.38566 13.15375,-20.077 6.98254,0 13.96508,0 20.94762,0 4.38609,6.69134 8.76889,13.38484 13.15374,20.077 5.12118,0 10.24237,0 15.36355,0 -5.60676,-18.71565 -11.21352,-37.43129 -16.82027,-56.14694 -7.39028,-3.83406 -14.78056,-7.66812 -22.17083,-11.50218 -7.39079,3.83457 -14.78159,7.66915 -22.17239,11.50372 z"
|
||||
style="fill:#898989;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="use4396"
|
||||
d="m -521.43644,406.56488 c -1.77374,0.0227 -3.15566,0.4222 -3.55518,1.76754 l 0.11752,2.1727 c 1.24058,16.62081 0.75876,33.65011 3.93561,49.99997 1.98359,2.87617 3.63732,8.09685 7.96709,7.20935 1.8046,-0.22471 4.69928,1.07511 6.16243,-0.0881 -0.0876,-1.12531 -0.18047,-2.37689 -0.26598,-3.46086 -1.38363,-12.51596 -2.3414,-25.11574 -3.33096,-37.70913 -0.77697,-6.57243 -2.15369,-13.39954 -5.30263,-19.41823 -1.9185,-0.16721 -4.00601,-0.49523 -5.7279,-0.4732 z"
|
||||
style="fill:#898989;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="use4398"
|
||||
d="m -506.09917,476.83515 c -1.97837,0.009 -3.95674,0.0188 -5.93511,0.0279 0.85216,4.85149 -4.04309,7.59388 -6.85213,10.37484 -0.6345,6.02214 1.09923,12.03757 0.98197,18.13626 0.3064,4.54843 -0.35793,10.2138 4.18921,12.95425 3.89072,2.9778 6.76537,7.60716 5.65521,12.64652 0.43285,7.84497 -0.8119,15.99277 0.9062,23.38167 1.01515,0.57035 2.08809,0.77358 3.18869,0.80413 l 2.20518,-18.43626 c 0,0 -2.26899,-32.57611 -4.33922,-59.88925 z"
|
||||
style="fill:#898989;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4404"
|
||||
d="m -271.77677,406.75044 c -3.09643,0.0485 -6.19285,0.0969 -9.28928,0.14537 -3.15953,5.97283 -4.55856,12.75131 -5.34747,19.29452 l -3.45931,41.48855 c 3.94759,0.0294 9.07538,1.78551 11.24547,-2.81911 5.80456,-6.57393 3.74439,-15.87475 4.98871,-23.78837 0.76732,-11.43639 1.23856,-22.86533 1.86188,-34.32096 z"
|
||||
style="fill:#898989;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4406"
|
||||
d="m -288.21508,476.67123 c -0.84134,0.006 -1.68687,0.0599 -2.53457,0.11907 -2.07117,27.32261 -4.3423,59.9341 -4.3423,59.9341 l 2.20826,18.47337 c 1.29581,-0.023 2.52331,-0.3133 3.58612,-1.2263 1.08603,-9.86486 -0.19804,-20.31797 0.95414,-30.09153 3.59307,-4.65204 10.46727,-8.17451 9.15627,-15.08365 0.31411,-7.28513 1.50719,-14.93066 1.3129,-22.00692 -3.27092,-2.21915 -7.90201,-5.21182 -6.84904,-9.77793 -1.14795,-0.27038 -2.31544,-0.34912 -3.49178,-0.34021 z"
|
||||
style="fill:#898989;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4441"
|
||||
d="m -398.42702,334.8881 -2.54284,4.40528 -2.54281,4.40266 2.90008,0 0,9.31229 2.18557,-1.2609 2.18556,1.2609 0,-9.31229 2.90008,0 -2.54283,-4.40266 -2.54281,-4.40528 z"
|
||||
style="fill:url(#linearGradient3923);fill-opacity:1;stroke:none;display:inline" />
|
||||
<use
|
||||
height="1013.322"
|
||||
width="1469.2054"
|
||||
transform="matrix(1,0,0,-1,-9.1690072e-7,727.78645)"
|
||||
id="use4460"
|
||||
xlink:href="#path4441"
|
||||
y="0"
|
||||
x="0"
|
||||
style="display:inline" />
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer4"
|
||||
inkscape:label="Leaders"
|
||||
transform="translate(647.36582,-57.672087)"
|
||||
style="display:inline">
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline"
|
||||
d="M -346.88483,324.11711 -381.86206,206.36042"
|
||||
id="path4211"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline"
|
||||
d="M -204.64408,314.78985 -143.68094,209.1986"
|
||||
id="path4215"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline"
|
||||
d="m -480.19795,353.09245 84.92794,58.46775"
|
||||
id="path4227"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline"
|
||||
d="m -481.9468,416.63443 92.50633,61.96547"
|
||||
id="path4229"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline"
|
||||
d="m -277.50576,447.94085 91.11706,-91.11705 75.50256,0"
|
||||
id="path4546"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccc" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline"
|
||||
d="m -110.92083,419.10931 -48.8358,0"
|
||||
id="path4221"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline"
|
||||
d="m -110.81855,476.81202 -50.8131,0"
|
||||
id="path4225"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4556"
|
||||
d="m -95.10276,585.08945 -2.54284,4.40528 -2.54281,4.40265 2.90008,0 0,9.3123 2.18557,-1.2609 2.18556,1.2609 0,-9.3123 2.90008,0 -2.54283,-4.40265 -2.54281,-4.40528 z"
|
||||
style="fill:url(#linearGradient3237);fill-opacity:1;stroke:none;display:inline" />
|
||||
<use
|
||||
style="display:inline"
|
||||
height="1013.322"
|
||||
width="1469.2054"
|
||||
transform="matrix(1.0000001,0,0,-1.0000001,303.3243,982.46676)"
|
||||
id="use4558"
|
||||
xlink:href="#path4441"
|
||||
y="0"
|
||||
x="0" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:31.67041588px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:end;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;display:inline;font-family:Sans;-inkscape-font-specification:'Sans, Normal'"
|
||||
x="-368.79688"
|
||||
y="175.47208"
|
||||
id="text4473"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
x="-368.79688"
|
||||
y="175.47208"
|
||||
id="tspan4217"
|
||||
style="font-size:32.00000381px">Button0</tspan></text>
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text4477"
|
||||
y="205.6097"
|
||||
x="-141.6575"
|
||||
style="font-size:31.67041206px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;display:inline;font-family:Sans"
|
||||
xml:space="preserve"><tspan
|
||||
y="205.6097"
|
||||
x="-141.6575"
|
||||
id="tspan4479"
|
||||
sodipodi:role="line"
|
||||
style="font-size:32.00000381px">Button1</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:32.00000381px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;display:inline;font-family:Sans;-inkscape-font-specification:'Sans, Normal'"
|
||||
x="-252.41873"
|
||||
y="147.92294"
|
||||
id="text4481"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4483"
|
||||
x="-252.41873"
|
||||
y="147.92294">Button2</tspan></text>
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text4485"
|
||||
y="361.82675"
|
||||
x="-492.72778"
|
||||
style="font-size:31.67041588px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:end;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;display:inline;font-family:Sans;-inkscape-font-specification:'Sans, Normal'"
|
||||
xml:space="preserve"><tspan
|
||||
y="361.82675"
|
||||
x="-492.72778"
|
||||
id="tspan4487"
|
||||
sodipodi:role="line"
|
||||
style="font-size:32.00000381px">Button3</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:31.67041588px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:end;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;display:inline;font-family:Sans;-inkscape-font-specification:'Sans, Normal'"
|
||||
x="-492.44421"
|
||||
y="414.9819"
|
||||
id="text4489"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4491"
|
||||
x="-492.44421"
|
||||
y="414.9819"
|
||||
style="font-size:32.00000381px">Button4</tspan></text>
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text4493"
|
||||
y="356.69751"
|
||||
x="-110.46946"
|
||||
style="font-size:31.67041206px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;display:inline;font-family:Sans"
|
||||
xml:space="preserve"><tspan
|
||||
y="356.69751"
|
||||
x="-110.46946"
|
||||
id="tspan4495"
|
||||
sodipodi:role="line"
|
||||
style="font-size:32.00000381px">Button5</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:31.67041206px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;display:inline;font-family:Sans"
|
||||
x="-110.46946"
|
||||
y="416.97623"
|
||||
id="text4497"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4499"
|
||||
x="-110.46946"
|
||||
y="416.97623"
|
||||
style="font-size:32.00000381px">Button6</tspan></text>
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text4501"
|
||||
y="476.83734"
|
||||
x="-110.46946"
|
||||
style="font-size:31.67041206px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;display:inline;font-family:Sans"
|
||||
xml:space="preserve"><tspan
|
||||
y="476.83734"
|
||||
x="-110.46946"
|
||||
id="tspan4503"
|
||||
sodipodi:role="line"
|
||||
style="font-size:32.00000381px">Button7</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:31.67041206px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;display:inline;font-family:Sans"
|
||||
x="-77.532547"
|
||||
y="605.11292"
|
||||
id="text4505"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4507"
|
||||
x="-77.532547"
|
||||
y="605.11292"
|
||||
style="font-size:32.00000381px">Button8</tspan></text>
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text4509"
|
||||
y="650.02606"
|
||||
x="-77.532547"
|
||||
style="font-size:31.67041206px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;display:inline;font-family:Sans"
|
||||
xml:space="preserve"><tspan
|
||||
y="650.02606"
|
||||
x="-77.532547"
|
||||
id="tspan4511"
|
||||
sodipodi:role="line"
|
||||
style="font-size:32.00000381px">Button9</tspan></text>
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline"
|
||||
d="m -276.93036,342.77164 25.64997,0 0,-188.87707"
|
||||
id="path4213"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 62 KiB |
@@ -1,778 +0,0 @@
|
||||
<?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:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="750"
|
||||
height="750"
|
||||
viewBox="0 0 750.00004 749.99998"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.91 r13725"
|
||||
sodipodi:docname="logitech-g502.svg">
|
||||
<defs
|
||||
id="defs4">
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient4372">
|
||||
<stop
|
||||
style="stop-color:#3d444c;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop4374" />
|
||||
<stop
|
||||
style="stop-color:#8f9aaa;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop4376" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient4327">
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop4329" />
|
||||
<stop
|
||||
style="stop-color:#969696;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop4331" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient4319">
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop4321" />
|
||||
<stop
|
||||
style="stop-color:#969696;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop4323" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient4219">
|
||||
<stop
|
||||
style="stop-color:#c3c3c3;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop4221" />
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop4223" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient4197">
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop4199" />
|
||||
<stop
|
||||
id="stop4205"
|
||||
offset="0.23127364"
|
||||
style="stop-color:#242424;stop-opacity:1;" />
|
||||
<stop
|
||||
style="stop-color:#242424;stop-opacity:1;"
|
||||
offset="0.7880435"
|
||||
id="stop4207" />
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop4201" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient4178">
|
||||
<stop
|
||||
id="stop4180"
|
||||
offset="0"
|
||||
style="stop-color:#000000;stop-opacity:1;" />
|
||||
<stop
|
||||
style="stop-color:#3b3b3b;stop-opacity:1;"
|
||||
offset="0.46853611"
|
||||
id="stop4182" />
|
||||
<stop
|
||||
style="stop-color:#777777;stop-opacity:1;"
|
||||
offset="0.84132797"
|
||||
id="stop4184" />
|
||||
<stop
|
||||
id="stop4186"
|
||||
offset="1"
|
||||
style="stop-color:#000000;stop-opacity:1;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient4168">
|
||||
<stop
|
||||
id="stop4170"
|
||||
offset="0"
|
||||
style="stop-color:#000000;stop-opacity:1;" />
|
||||
<stop
|
||||
style="stop-color:#3b3b3b;stop-opacity:1;"
|
||||
offset="0.646918"
|
||||
id="stop4172" />
|
||||
<stop
|
||||
style="stop-color:#777777;stop-opacity:1;"
|
||||
offset="0.76408035"
|
||||
id="stop4174" />
|
||||
<stop
|
||||
id="stop4176"
|
||||
offset="1"
|
||||
style="stop-color:#000000;stop-opacity:1;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient4150">
|
||||
<stop
|
||||
id="stop4152"
|
||||
offset="0"
|
||||
style="stop-color:#000000;stop-opacity:1;" />
|
||||
<stop
|
||||
style="stop-color:#3b3b3b;stop-opacity:1;"
|
||||
offset="0.54100561"
|
||||
id="stop4154" />
|
||||
<stop
|
||||
style="stop-color:#777777;stop-opacity:1;"
|
||||
offset="0.84132797"
|
||||
id="stop4156" />
|
||||
<stop
|
||||
id="stop4158"
|
||||
offset="1"
|
||||
style="stop-color:#000000;stop-opacity:1;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient4140">
|
||||
<stop
|
||||
id="stop4142"
|
||||
offset="0"
|
||||
style="stop-color:#000000;stop-opacity:1;" />
|
||||
<stop
|
||||
style="stop-color:#3b3b3b;stop-opacity:1;"
|
||||
offset="0.5890528"
|
||||
id="stop4144" />
|
||||
<stop
|
||||
style="stop-color:#777777;stop-opacity:1;"
|
||||
offset="0.69403088"
|
||||
id="stop4146" />
|
||||
<stop
|
||||
id="stop4148"
|
||||
offset="1"
|
||||
style="stop-color:#000000;stop-opacity:1;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient4047">
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop4049" />
|
||||
<stop
|
||||
id="stop4055"
|
||||
offset="0.5"
|
||||
style="stop-color:#000000;stop-opacity:0.49803922;" />
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop4051" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient4039">
|
||||
<stop
|
||||
style="stop-color:#636363;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop4041" />
|
||||
<stop
|
||||
id="stop4063"
|
||||
offset="0.19902708"
|
||||
style="stop-color:#595959;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop4061"
|
||||
offset="0.39056408"
|
||||
style="stop-color:#4f4f4f;stop-opacity:1;" />
|
||||
<stop
|
||||
style="stop-color:#a3a3a3;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop4043" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient4449">
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop4451" />
|
||||
<stop
|
||||
id="stop4059"
|
||||
offset="0.24691147"
|
||||
style="stop-color:#3b3b3b;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop4057"
|
||||
offset="0.84132797"
|
||||
style="stop-color:#777777;stop-opacity:1;" />
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop4453" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4449"
|
||||
id="linearGradient4562"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0,-1.698701,1.698701,0,-120.19569,737.44997)"
|
||||
x1="31.968746"
|
||||
y1="18.546629"
|
||||
x2="31.968746"
|
||||
y2="29.577879" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4449"
|
||||
id="linearGradient4623"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0,-1.6987012,-1.6987012,0,-45.565631,793.48827)"
|
||||
x1="31.968746"
|
||||
y1="18.546629"
|
||||
x2="31.968746"
|
||||
y2="29.577879" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4319"
|
||||
id="linearGradient4325"
|
||||
x1="-258.85849"
|
||||
y1="636.73883"
|
||||
x2="-210.58292"
|
||||
y2="669.61383"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4327"
|
||||
id="linearGradient4333"
|
||||
x1="-258.85849"
|
||||
y1="636.73883"
|
||||
x2="-210.58292"
|
||||
y2="669.61383"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4372"
|
||||
id="linearGradient4378"
|
||||
x1="476.00003"
|
||||
y1="513.00006"
|
||||
x2="559.50006"
|
||||
y2="463.50003"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1.4142136"
|
||||
inkscape:cx="359.25033"
|
||||
inkscape:cy="331.87231"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer4"
|
||||
showgrid="false"
|
||||
showguides="false"
|
||||
inkscape:guide-bbox="true"
|
||||
fit-margin-top="50"
|
||||
fit-margin-left="50"
|
||||
fit-margin-right="50"
|
||||
fit-margin-bottom="50"
|
||||
inkscape:window-width="2048"
|
||||
inkscape:window-height="1088"
|
||||
inkscape:window-x="2560"
|
||||
inkscape:window-y="27"
|
||||
inkscape:window-maximized="1" />
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<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></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Device"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(522.78594,-165.96284)"
|
||||
style="display:inline"
|
||||
sodipodi:insensitive="true">
|
||||
<g
|
||||
id="g4390"
|
||||
transform="translate(46.66905,-6.3639614)">
|
||||
<path
|
||||
sodipodi:nodetypes="zccccccscsscssssssssz"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4435"
|
||||
d="m -226.16095,683.58782 c -6.01535,-13.02364 -13,-16.5 -13,-16.5 l -11.25,-3.375 -116.45795,-88.57547 11.4905,-82.02437 7.62132,1.97703 6.89061,-13.15685 c -18.38478,2.65165 -27.23986,-1.01777 -28.47729,-2.60876 -1.23744,-1.59099 0.17677,-3.18198 0.17677,-3.18198 0,0 7.43505,-10.39747 47.55294,-23.33452 117.72759,-37.96429 194.75285,-32.63933 310.328127,14.65494 101.699787,41.61632 127.995243,117.50993 130.641353,159.47011 0,0 -2.38649,0.17677 -5.74524,5.03813 -3.35876,4.86136 6.0104,17.05896 3.53553,28.72622 -2.47487,11.66726 -28.637827,53.29817 -45.166448,48.70198 -16.528622,-4.5962 -39.067651,-6.98268 -55.154331,-3.00521 -16.08667977,3.97748 -95.017477,43.75224 -100.144001,46.66905 -5.126525,2.91682 -19.26866,10.42983 -25.36746,10.87177 -6.09879,0.44194 -18.29639,-4.06586 -45.25483,-14.05375 -26.95845,-9.98788 -54.09367,-22.98097 -61.25313,-32.88046 -7.15946,-9.8995 -4.95112,-20.38922 -10.96647,-33.41286 z"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4362"
|
||||
transform="translate(-522.78594,165.96281)"
|
||||
d="m 564.2793,394.82812 c -3.92575,-0.10626 -7.28936,3.75042 -13.08985,11.8711 -8.83883,12.37437 -39.24401,61.16451 -77.07422,75.30664 -37.83021,14.14214 -97.93406,2.12147 -130.10742,-1.41406 -32.07532,-3.52476 -80.61133,-16.61719 -80.61133,-16.61719 l -30.16601,4.00391 39.14453,29.77148 11.25,3.375 c 0,0 6.98465,3.47636 13,16.5 6.01535,13.02364 3.80734,23.51261 10.9668,33.41211 7.15946,9.89949 34.2935,22.89298 61.25195,32.88086 26.95844,9.98789 39.15707,14.49663 45.25586,14.05469 6.0988,-0.44194 20.24066,-7.95623 25.36719,-10.87305 5.12652,-2.91681 84.05785,-42.69049 100.14453,-46.66797 16.08668,-3.97747 38.62567,-1.59229 55.15429,3.00391 16.52863,4.59619 42.69115,-37.03392 45.16602,-48.70117 0.81145,-3.82542 0.34164,-7.70307 -0.52734,-11.36524 -4.70923,-11.20032 -11.76875,-25.18057 -21.7461,-38.13281 -23.82425,-30.92783 -38.18467,-40.65753 -46.3164,-47.02149 -2.79529,-2.18761 -5.00616,-3.33105 -7.0625,-3.38672 z"
|
||||
style="fill:url(#linearGradient4378);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
<g
|
||||
id="g4356">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#2e2d2b;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 130.91406,379.34375 c -0.46995,0.14042 -0.93877,0.27563 -1.41015,0.42187 0,10e-6 -1.6703,5.53928 -1.51758,6.25196 l 51.97265,21.91992 23.86524,-17.50195 2.72461,-3.55664 c -0.22885,-0.14243 -0.45999,-0.27609 -0.68945,-0.41602 -27.39877,-3.31358 -52.27682,-5.25289 -75.04493,-6.2793 l 0.0996,-0.83984 z"
|
||||
transform="translate(-522.78594,165.96281)"
|
||||
id="path4417" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#13130f;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 128.01367,386.0293 4.48633,9.0957 66,39.375 -18.53906,-26.56445 -0.002,0.002 -51.94531,-21.9082 z"
|
||||
transform="translate(-522.78594,165.96281)"
|
||||
id="path4422" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#7c7a79;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 203.82422,390.61328 c 0,0 -0.57509,0.25215 -0.60156,0.26367 l -23.26172,17.0586 18.38281,26.33984 -1.14844,-4.50586 0.79492,-17.32422 5.83399,-21.83203 z"
|
||||
transform="translate(-522.78594,165.96281)"
|
||||
id="path4427" />
|
||||
</g>
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4216"
|
||||
transform="translate(-522.78594,165.96281)"
|
||||
d="M 411.19922,269.32812 C 389.02158,276.55183 382.23256,283.7763 371.75,291 l 25.375,6.25 c 18.2282,-19.41084 23.88453,-20.47312 31.20117,-23.95898 -5.76229,-1.45746 -11.46778,-2.78139 -17.12695,-3.9629 z"
|
||||
style="fill:#3d4144;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4220"
|
||||
d="m -170.91095,464.08782 -8.5,16.125 35.75,3.25 1.625,-16.25 z"
|
||||
style="fill:#3c4247;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
<path
|
||||
sodipodi:nodetypes="cssccccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4226"
|
||||
transform="translate(-522.78594,165.96281)"
|
||||
d="m 411.17969,269.33398 c -24.50302,-5.11518 -48.18402,-7.65405 -72.22657,-7.57031 -42.56105,0.14824 -86.27544,8.47266 -137.78124,25.08203 -40.11789,12.93705 -47.55274,23.33399 -47.55274,23.33399 0,0 -0.48629,0.56241 -0.63476,1.3457 l 0.10351,0.0684 c 65.05383,-30.40559 116.42376,-36.77027 218.33008,-20.63869 11.09267,-7.17661 17.60011,-14.39959 39.76172,-21.62112 z"
|
||||
style="fill:#363c41;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4263"
|
||||
transform="translate(-522.78594,165.96281)"
|
||||
d="m 296.87305,518.20312 c 5.68645,12.75421 3.66653,23.08278 10.71875,32.83399 7.15946,9.89949 34.2935,22.89298 61.25195,32.88086 26.95844,9.98789 39.15707,14.49663 45.25586,14.05469 5.82656,-0.42222 18.90685,-7.25764 24.54101,-10.41407 -0.55038,-0.0177 -1.10725,-0.03 -1.64062,-0.0586 -7,-0.375 -17.75,-3.625 -26.375,-6.5 -8.625,-2.875 -67.14947,-20.67049 -76.375,-33.125 -7.10507,-9.59187 -5.33684,-16.54135 -8.83008,-19.27148 -2.49111,-1.94692 -8.34261,-3.73063 -12.5039,-5.15625 -3.08671,-1.05747 -11.18273,-3.67568 -16.04297,-5.24415 z"
|
||||
style="fill:#10f5fa;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
<g
|
||||
id="g4348">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#a6a09b;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 244.0293,281.64062 c -11.87933,0.21005 -21.28719,4.70945 -25.45899,14.41407 l -7.76367,15.2207 c 4.63005,-8.00151 13.38623,-11.7657 24.20703,-11.95703 13.84985,-0.24489 31.05521,5.35529 47.24414,15.31641 4.24517,-2.44738 6.87171,-7.03619 7.65625,-8.34375 0.83684,-1.39473 3.09281,-4.54246 4.70703,-7.20118 -17.13681,-11.29215 -35.78244,-17.71107 -50.59179,-17.44922 z m -33.22266,29.63477 c -0.45292,0.78273 -0.88022,1.59229 -1.25195,2.45703 l 1.25195,-2.45703 z"
|
||||
transform="translate(-522.78594,165.96281)"
|
||||
id="path4228" />
|
||||
<path
|
||||
style="fill:#0c0d08;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 210.77539,311.25976 -1.12305,2.28126 c -0.45554,2.37144 2.75076,4.2831 5.21875,3.9746 2.82843,-0.35354 20.06602,-2.56346 32.97071,-2.74023 12.9047,-0.17678 22.09591,1.76761 29.34375,1.41406 1.88682,-0.092 3.57816,-0.69332 5.07226,-1.55468 -16.18893,-9.96112 -33.39429,-15.5613 -47.24414,-15.31641 -10.8208,0.19133 -19.60823,3.93989 -24.23828,11.9414 z"
|
||||
id="path4247"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccssscsc"
|
||||
transform="translate(-522.78594,165.96281)" />
|
||||
</g>
|
||||
<path
|
||||
sodipodi:nodetypes="ccccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4258"
|
||||
d="m -179.35432,480.17165 -2.95971,5.51668 39.24443,5.56847 -0.88388,-7.86656 z"
|
||||
style="fill:#111419;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
<path
|
||||
sodipodi:nodetypes="ccccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4260"
|
||||
d="m -143.07496,491.2041 -1.00352,-7.90761 2.03293,-16.10721 1.45082,6.56663 z"
|
||||
style="fill:#282d32;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
<g
|
||||
id="g4352">
|
||||
<path
|
||||
style="fill:#2f333a;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m -313.91094,553.83781 -2.375,3.5 -3.875,14.125 93.375,-1.625 c -21.95804,-4.72268 -46.10785,-9.6343 -87.125,-16 z"
|
||||
id="path4262"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<path
|
||||
sodipodi:nodetypes="cccccc"
|
||||
style="fill:#585958;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m -320.16094,571.44718 -3.125,23.01563 3.25,7.125 99.5,-15.375 -6.29687,-16.40625 z"
|
||||
id="path4264"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
<g
|
||||
id="g4335">
|
||||
<path
|
||||
style="fill:url(#linearGradient4333);fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient4325);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m -295.16094,608.46281 6.625,27.125 27.125,5.875 c 0,0 38.75,14.5 45.75,29.125 l 5.5,0.875 2.375,-4.625 c 0,0 -13.875,-23.75 -49.625,-33.375 l -1,-1.25 2.25,-11.25 z"
|
||||
id="path4288"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccccccccc" />
|
||||
<path
|
||||
style="fill:#1f2021;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 235.18359,469.82617 272.125,497.75 l 35,6.875 C 300.125,490 261.375,475.5 261.375,475.5 Z"
|
||||
transform="translate(-522.78594,165.96281)"
|
||||
id="path4290"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
</g>
|
||||
<g
|
||||
id="g4297">
|
||||
<path
|
||||
style="fill:#5e5d5c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m -271.28594,618.46281 4,7 85.38128,13.44194 9.61872,-8.44194 z"
|
||||
id="path4266"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<path
|
||||
style="fill:#242422;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m -181.07659,638.77695 c 0,0 22.18548,12.55115 -5.48008,8.04334 -27.66555,-4.5078 -67.97064,-12.55114 -67.97064,-12.55114 l -12.72792,-8.75045 z"
|
||||
id="path4268"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:#5e6570;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m -172.41453,630.38006 -9.45755,8.3085 9.28077,8.3969 9.54594,-5.3033 z"
|
||||
id="path4270"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<path
|
||||
style="fill:#181719;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m -271.48416,618.56636 2.19822,-8.60355 103.25,9.875 6,18.125 -2.625,3.875 -9.60983,-10.91789 z"
|
||||
id="path4280"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccccc" />
|
||||
</g>
|
||||
<g
|
||||
id="g4305">
|
||||
<path
|
||||
style="fill:#676763;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m -164.98991,632.50138 6.18718,9.72272 75.041708,8.22011 8.131734,-6.54073 1.155328,-4.55469 4.153795,-8.23574 -93.255535,-9.12988 z"
|
||||
id="path4272"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccccccc" />
|
||||
<path
|
||||
style="fill:#2f343b;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m -70.32599,631.08717 5.48008,5.39169 -5.74524,12.90469 -5.204655,-5.54257 c 0.08832,-4.98178 3.353501,-8.62593 5.469815,-12.75381 z"
|
||||
id="path4274"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<path
|
||||
style="fill:#202328;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m -83.58424,650.17905 3.8007,4.06586 -77.87014,-6.89429 -1.15104,-5.14215 z"
|
||||
id="path4276"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<path
|
||||
sodipodi:nodetypes="ccccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4278"
|
||||
d="m -70.59115,649.38355 -9.1397,4.91406 -3.894905,-4.1034 7.819685,-6.37912 z"
|
||||
style="fill:#97a6b5;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
</g>
|
||||
<path
|
||||
sodipodi:nodetypes="ccccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4292"
|
||||
d="m -153.03036,495.18342 44.96255,6.76837 1.76776,125.51145 -32.51219,-3.18198 z"
|
||||
style="fill:#676769;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
<path
|
||||
style="fill:#181719;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m -164.98991,632.50138 89.360622,11.4021 1.155328,-4.55469 4.153795,-8.23574 -93.255535,-9.12988 z"
|
||||
id="path4303"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccccc" />
|
||||
<g
|
||||
id="g4282">
|
||||
<path
|
||||
style="fill:#9b9994;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m -283.96063,605.18939 1.59099,4.06586 144.42656,16.26346 -6.01041,-45.07806 z"
|
||||
id="path4244"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#2cbfff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 312.64258,435.04297 -5.01172,0.64453 8.00195,8.8418 5.88281,0.41015 -8.87304,-9.89648 z"
|
||||
transform="translate(-522.78594,165.96281)"
|
||||
id="path4246" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#2cbfff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 331.68945,432.58984 -4.78515,0.61524 11.86718,12.93945 6.72461,0.4707 -13.80664,-14.02539 z"
|
||||
transform="translate(-522.78594,165.96281)"
|
||||
id="path4248" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#2cbfff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 351.97266,429.97852 -6.13282,0.78906 16.58594,17.0293 7.58399,0.52929 -18.03711,-18.34765 z"
|
||||
transform="translate(-522.78594,165.96281)"
|
||||
id="path4250" />
|
||||
</g>
|
||||
<g
|
||||
id="g4339">
|
||||
<path
|
||||
style="fill:#4c5053;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m -386.31433,498.06271 -5.65686,48.08326 c 45.99186,2.07336 100.55399,7.85718 167.23075,21.21321 l 1.06066,3.0052 c 23.24045,-1.15617 46.44002,-2.32824 77.95852,-0.26516 l 3.35876,3.62392 -10.6066,-78.48885 c -119.63944,-15.8417 -179.55343,-5.16228 -233.34523,2.82842 z"
|
||||
id="path3608"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccccccc" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#413d44;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 344.67578,403.00977 c -16.50546,-0.0586 -30.99426,0.6673 -45.49414,1.38867 l 6.64258,15.02929 74.77539,-10.96093 -0.94727,-1.53907 -2.58789,-2.79101 c -11.81943,-0.77366 -22.46808,-1.09174 -32.38867,-1.12695 z"
|
||||
transform="translate(-522.78594,165.96281)"
|
||||
id="path4412" />
|
||||
<path
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m -296.22345,497.71282 4.375,6.6875 6.875,-6.8125 z"
|
||||
id="path4242"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
<g
|
||||
style="stroke:none"
|
||||
id="g4344">
|
||||
<path
|
||||
style="fill:#6d747e;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 428.32422,273.29297 c -7.29616,3.47575 -12.94858,4.55152 -31.06055,23.8125 0.0479,0.0864 0.0803,0.17102 0.13086,0.25781 6.62912,19.7106 10.60547,165.375 10.60547,165.375 0,0 41.19295,7.2655 67.125,1.38672 22.33947,-5.06434 38.625,-29.625 51.125,-42.625 12.5,-13 24.89365,-35.29164 33.5,-37.875 6.89763,-2.07046 15.8234,4.4109 29.125,12.375 33.4418,20.02269 42.89394,39.55603 52.79297,65.09375 0.30214,-0.10531 0.47265,-0.12305 0.47265,-0.12305 C 639.49453,419.01054 613.19977,343.11632 511.5,301.5 481.65769,289.2883 454.39027,279.88532 428.32422,273.29297 Z"
|
||||
transform="translate(-522.78594,165.96281)"
|
||||
id="path4234"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccssssccsc" />
|
||||
<ellipse
|
||||
style="opacity:1;fill:#2cbfff;fill-opacity:1;stroke:none;stroke-width:1.5;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path4261"
|
||||
cx="-58.535938"
|
||||
cy="561.08783"
|
||||
rx="32.25"
|
||||
ry="29.875" />
|
||||
</g>
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4218"
|
||||
d="m -205.53595,454.96282 -11.375,19 21.5,-0.875 10.875,-18.875 z"
|
||||
style="fill:#202124;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
<path
|
||||
sodipodi:nodetypes="ccccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4254"
|
||||
d="m -222.88428,483.39024 6.01577,-9.47808 21.47301,-0.86336 1.23744,11.49049 z"
|
||||
style="fill:#121518;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
<path
|
||||
sodipodi:nodetypes="ccccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4256"
|
||||
d="m -195.50442,473.05324 10.88157,-18.79455 2.39721,10.39322 -12.00029,19.91863 z"
|
||||
style="fill:#1a1e22;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer4"
|
||||
inkscape:label="Leaders"
|
||||
transform="translate(647.36582,-57.672066)"
|
||||
style="display:inline">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4556"
|
||||
d="m -94.323676,683.09816 5.56391,3.21163 5.56059,3.21159 0,-3.66282 11.76151,0 -1.59253,-2.7604 1.59253,-2.76039 -11.76151,0 0,-3.66282 -5.56059,3.21162 -5.56391,3.21159 z"
|
||||
style="display:inline;fill:url(#linearGradient4562);fill-opacity:1;stroke:none" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="use4558"
|
||||
d="m -71.437651,739.13645 -5.56391,3.21162 -5.56059,3.21159 0,-3.66282 -11.76152,0 1.59254,-2.76039 -1.59254,-2.76039 11.76152,0 0,-3.66282 5.56059,3.21161 5.56391,3.2116 z"
|
||||
style="fill:url(#linearGradient4623);fill-opacity:1;stroke:none" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:40.00000381px;line-height:125%;font-family:Sans;-inkscape-font-specification:'Sans, Normal';text-align:end;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:end;display:inline;fill:#000000;fill-opacity:1;stroke:none"
|
||||
x="-507.44232"
|
||||
y="412.75952"
|
||||
id="text4489"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4491"
|
||||
x="-507.44232"
|
||||
y="412.75952"
|
||||
style="font-size:32px">Button0</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;display:inline;fill:#000000;fill-opacity:1;stroke:none"
|
||||
x="-60.689339"
|
||||
y="696.94501"
|
||||
id="text4505"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4507"
|
||||
x="-60.689339"
|
||||
y="696.94501"
|
||||
style="font-size:32px">Button10</tspan></text>
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text4509"
|
||||
y="753.67065"
|
||||
x="-60.689339"
|
||||
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;display:inline;fill:#000000;fill-opacity:1;stroke:none"
|
||||
xml:space="preserve"><tspan
|
||||
y="753.67065"
|
||||
x="-60.689339"
|
||||
id="tspan4511"
|
||||
sodipodi:role="line"
|
||||
style="font-size:32px">Button9</tspan></text>
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text4440"
|
||||
y="467.91382"
|
||||
x="-507.44232"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:40.00000381px;line-height:125%;font-family:Sans;-inkscape-font-specification:'Sans, Normal';text-align:end;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:end;display:inline;fill:#000000;fill-opacity:1;stroke:none"
|
||||
xml:space="preserve"><tspan
|
||||
style="font-size:32px"
|
||||
y="467.91382"
|
||||
x="-507.44232"
|
||||
id="tspan4442"
|
||||
sodipodi:role="line">Button7</tspan></text>
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4448"
|
||||
d="m -501.44135,408.77695 79.19595,0"
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m -290.72353,319.68149 38.18376,-118.08684"
|
||||
id="path4450"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text4452"
|
||||
y="209.51634"
|
||||
x="-419.71732"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:40.00000381px;line-height:125%;font-family:Sans;-inkscape-font-specification:'Sans, Normal';text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;display:inline;fill:#000000;fill-opacity:1;stroke:none"
|
||||
xml:space="preserve"><tspan
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:32px;font-family:Sans;-inkscape-font-specification:Sans"
|
||||
y="209.51634"
|
||||
x="-419.71732"
|
||||
id="tspan4454"
|
||||
sodipodi:role="line">Button2</tspan></text>
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4456"
|
||||
d="M -355.77735,340.18759 -422.9525,219.97943"
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4466"
|
||||
d="m -302.74434,651.31459 94.0452,-113.8442"
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:40.00000381px;line-height:125%;font-family:Sans;-inkscape-font-specification:'Sans, Normal';text-align:end;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:end;display:inline;fill:#000000;fill-opacity:1;stroke:none"
|
||||
x="-507.44232"
|
||||
y="516.70416"
|
||||
id="text4468"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4470"
|
||||
x="-507.44232"
|
||||
y="516.70416"
|
||||
style="font-size:32px">Button6</tspan></text>
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text4472"
|
||||
y="566.90875"
|
||||
x="-455.11642"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:40.00000381px;line-height:125%;font-family:Sans;-inkscape-font-specification:'Sans, Normal';text-align:end;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:end;display:inline;fill:#000000;fill-opacity:1;stroke:none"
|
||||
xml:space="preserve"><tspan
|
||||
style="font-size:32px"
|
||||
y="566.90875"
|
||||
x="-455.11642"
|
||||
id="tspan4474"
|
||||
sodipodi:role="line">Button4</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:40.00000381px;line-height:125%;font-family:Sans;-inkscape-font-specification:'Sans, Normal';text-align:end;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:end;display:inline;fill:#000000;fill-opacity:1;stroke:none"
|
||||
x="-456.53064"
|
||||
y="616.40625"
|
||||
id="text4476"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4478"
|
||||
x="-456.53064"
|
||||
y="616.40625"
|
||||
style="font-size:32px">Button5</tspan></text>
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text4480"
|
||||
y="662.36816"
|
||||
x="-310.86664"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:40.00000381px;line-height:125%;font-family:Sans;-inkscape-font-specification:'Sans, Normal';text-align:end;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:end;display:inline;fill:#000000;fill-opacity:1;stroke:none"
|
||||
xml:space="preserve"><tspan
|
||||
style="font-size:32px"
|
||||
y="662.36816"
|
||||
x="-310.86664"
|
||||
id="tspan4482"
|
||||
sodipodi:role="line">Button3</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:40.00000381px;line-height:125%;font-family:Sans;-inkscape-font-specification:'Sans, Normal';text-align:left;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;display:inline;fill:#000000;fill-opacity:1;stroke:none"
|
||||
x="-252.13301"
|
||||
y="200.32396"
|
||||
id="text4484"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4486"
|
||||
x="-252.13301"
|
||||
y="200.32396"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:32px;font-family:Sans;-inkscape-font-specification:Sans">Button1</tspan></text>
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text4488"
|
||||
y="247.93217"
|
||||
x="-103.82285"
|
||||
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;display:inline;fill:#000000;fill-opacity:1;stroke:none"
|
||||
xml:space="preserve"><tspan
|
||||
style="font-size:32px"
|
||||
y="247.93217"
|
||||
x="-103.82285"
|
||||
id="tspan4490"
|
||||
sodipodi:role="line">Button8</tspan></text>
|
||||
<path
|
||||
sodipodi:nodetypes="cc"
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m -502.14846,464.63839 60.10407,-12.72792"
|
||||
id="path4492"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4494"
|
||||
d="m -496.4916,512.72165 126.57211,-43.84061"
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
sodipodi:nodetypes="cc"
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m -445.57991,562.92624 140.71425,-43.84062"
|
||||
id="path4496"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4498"
|
||||
d="m -439.21595,608.88818 100.40916,-61.51829"
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
sodipodi:nodetypes="cc"
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M -232.03365,357.15816 -108.28996,250.38503"
|
||||
id="path4500"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 36 KiB |
@@ -1,352 +0,0 @@
|
||||
<?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:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="750"
|
||||
height="750"
|
||||
viewBox="0 0 750.00004 749.99998"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.4 r9939"
|
||||
sodipodi:docname="logitech-mx_master.svg">
|
||||
<defs
|
||||
id="defs4">
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient5204">
|
||||
<stop
|
||||
style="stop-color:#868686;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop5206" />
|
||||
<stop
|
||||
style="stop-color:#868686;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop5208" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient5128">
|
||||
<stop
|
||||
style="stop-color:#3a3a3a;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop5130" />
|
||||
<stop
|
||||
style="stop-color:#aaaaaa;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop5132" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient5128"
|
||||
id="linearGradient3078"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
spreadMethod="reflect"
|
||||
x1="230.63638"
|
||||
y1="432.30179"
|
||||
x2="238.061"
|
||||
y2="447.85815" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient5204"
|
||||
id="linearGradient3080"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="196.63423"
|
||||
y1="468.17209"
|
||||
x2="170.13423"
|
||||
y2="402.67206" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1"
|
||||
inkscape:cx="417.6511"
|
||||
inkscape:cy="345.62267"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer4"
|
||||
showgrid="false"
|
||||
showguides="true"
|
||||
inkscape:guide-bbox="true"
|
||||
fit-margin-top="50"
|
||||
fit-margin-left="50"
|
||||
fit-margin-right="50"
|
||||
fit-margin-bottom="50"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1099"
|
||||
inkscape:window-x="1920"
|
||||
inkscape:window-y="28"
|
||||
inkscape:window-maximized="1" />
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<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:label="Device"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(522.78594,-165.96284)"
|
||||
style="display:inline">
|
||||
<g
|
||||
id="g3058"
|
||||
transform="matrix(0.70142923,0,0,0.70142923,-172.43767,286.8878)">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path5084"
|
||||
transform="translate(-522.78594,-97.359255)"
|
||||
d="m 921.14258,351.92188 c -10.71472,0.3561 17.48242,40.65039 17.48242,40.65039 l -0.99805,38.58007 c -0.0632,-0.10181 -0.1163,-0.2052 -0.18164,-0.30664 -0.41273,0.4635 -0.8827,0.9276 -1.47656,1.39063 C 883.92622,472.81347 836.5,478.32226 756.5,516.32227 c -80,37.99997 -316.69239,159.29807 -343.5,147.5 -0.19217,-0.0846 -0.3462,-0.18445 -0.50195,-0.28321 -0.14711,0.0864 -0.35538,0.19871 -0.49805,0.28321 -0.0138,-0.0118 -0.0272,-0.0234 -0.041,-0.0352 l -0.0273,0.0156 c 20.65212,21.99316 41.34778,28.42752 134.68945,6.01954 l 67.87891,0 c 0,0 31.685,6.41255 73,41.25 56.21397,47.40048 70.15272,37.94645 213.83008,7.3789 120.72766,-25.68496 98.22343,-76.56575 107.07816,-168.1289 5.6329,-58.24749 15.6725,-114.94915 -35.90824,-161 -31.61176,-28.22275 -46.12465,-37.57431 -51.35742,-37.40039 z"
|
||||
style="fill:#433737;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.42566061px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
<path
|
||||
sodipodi:nodetypes="scccccccccsccccssss"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path5077"
|
||||
transform="translate(-522.78594,-97.359255)"
|
||||
d="m 766.6582,304.5 c -179.15881,0.002 -367.84961,155.86523 -367.84961,155.86523 -21.93235,32.98189 -41.23548,69.54864 -57.98242,109.60157 7.5036,28.04106 30.67382,59.21512 71.17383,93.85547 59.9519,-35.50497 512.63903,-236.02476 512.5,-244 95.7156,51.99999 -269.006,189 -269,189 -12.27104,5.04673 -14.55606,11.0677 -7.5,18 l 2.06445,1.76953 0.002,0 11.89062,10.1875 c -0.62249,0.15805 -1.26128,0.30706 -1.87305,0.48242 -47.26127,13.54738 -84.55325,23.64795 -114.41015,30.79101 L 615,669.82227 l 63.40625,-16.95508 38.59961,33.06445 c 38.18376,34.64823 37.84255,32.06806 141.42187,14.14258 C 964.16532,681.77523 962.3307,680.80807 974.39258,545.2168 984.45817,432.06647 1011.3318,377.81074 858.42773,320.35742 828.82733,309.23515 797.88772,304.49969 766.6582,304.5 z"
|
||||
style="fill:#3d3d3d;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.42566061px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path5079"
|
||||
transform="translate(-522.78594,-97.359255)"
|
||||
d="m 924.5,419.82227 c 0.13868,7.95534 -450.25292,207.4789 -512.00586,243.71484 0.15695,0.0995 0.31224,0.19994 0.50586,0.28516 26.80761,11.79809 263.5,-109.50001 343.5,-147.5 80,-38.00001 127.42622,-43.50878 179.46875,-84.08594 0.5964,-0.46501 1.06842,-0.93101 1.48242,-1.39649 -2.56726,-3.98332 -6.80221,-7.67699 -12.95117,-11.01757 z"
|
||||
style="fill:#826c5e;fill-opacity:1;fill-rule:evenodd;stroke:none" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path5101"
|
||||
transform="translate(-522.78594,-97.359255)"
|
||||
d="m 633.2832,328.9668 c -128.50884,43.87332 -234.47461,131.39843 -234.47461,131.39843 -21.86064,32.87406 -41.10756,69.31169 -57.8164,109.21094 l 0.008,-0.004 61.25,-46.25 c -0.31467,-30.27892 8.67871,-33.61166 108.5,-91 105.67745,-60.75512 109.87649,-54.6167 115.74609,-80.49805 1.83541,-8.09301 4.52898,-16.4514 6.78711,-22.85742 z"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.42566061px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path5107"
|
||||
transform="translate(-522.78594,-97.359255)"
|
||||
d="m 640.70703,428.57422 c -3.04651,0.0756 -6.31444,0.73835 -9.96875,2.0918 -19.09188,7.07104 -141.89935,74.20682 -175.71484,98.99414 -48.59449,35.62053 -48.4375,14.14257 -48.4375,14.14257 l -4.24219,-20.85937 c 0,0 -0.0901,0.0489 -0.0937,0.0508 9.1e-4,0.11168 -10e-4,0.2157 0,0.32813 l -61.25,46.25 -0.008,0.004 c -0.0548,0.13093 -0.11124,0.25961 -0.16602,0.39063 7.5036,28.04104 30.67382,59.21512 71.17383,93.85547 0.14966,-0.0886 0.33959,-0.19447 0.49414,-0.28516 0.0169,-0.01 0.0397,-0.0213 0.0566,-0.0312 1.02546,-0.60112 2.16407,-1.25057 3.39844,-1.93945 0.2066,-0.11531 0.43415,-0.23971 0.64648,-0.35743 1.08032,-0.59888 2.2254,-1.22479 3.45118,-1.88476 0.32998,-0.17769 0.67334,-0.36095 1.01367,-0.54297 1.22538,-0.65535 2.51457,-1.33647 3.87109,-2.04687 0.32591,-0.17069 0.65104,-0.34183 0.98438,-0.51563 0.98003,-0.51099 2.03888,-1.05627 3.08203,-1.59375 1.50441,-0.77516 3.19823,-1.63034 4.83007,-2.45898 2.6812,-1.36148 5.48308,-2.77245 8.49219,-4.27149 1.45002,-0.72234 2.95192,-1.46789 4.47461,-2.2207 3.14575,-1.55527 6.43566,-3.16851 9.87696,-4.84766 1.7505,-0.85415 3.50304,-1.70917 5.32617,-2.59375 3.69907,-1.79476 7.57491,-3.665 11.55664,-5.57812 1.62203,-0.77935 3.19102,-1.53607 4.85742,-2.33399 4.85137,-2.32297 9.91021,-4.73306 15.11328,-7.20312 1.05862,-0.50256 2.06054,-0.98002 3.13281,-1.48828 6.27234,-2.97314 12.74159,-6.02841 19.44532,-9.18164 0.19493,-0.0917 0.37504,-0.1777 0.57031,-0.26954 0.88374,-0.4156 1.84183,-0.86083 2.73242,-1.27929 8.89106,-4.17765 18.33343,-8.58591 27.83008,-13.01563 9.48674,-4.42512 19.20352,-8.94432 29.15625,-13.5625 5.63004,-2.6124 11.17539,-5.18811 16.91992,-7.84765 11.03955,-5.11098 22.24511,-10.28776 33.57227,-15.51563 4.59686,-2.12162 9.06381,-4.18813 13.6875,-6.32031 31.79772,-14.66333 64.04275,-29.4992 94.89648,-43.72656 0.64347,-0.29672 1.23671,-0.57103 1.87891,-0.86719 -0.0661,-2.523 -0.5325,-5.27289 -1.4043,-8.3125 -2.95973,-10.3194 -36.14133,-35.93502 -56.06055,-50.55859 C 663.08118,438.83704 654.18972,428.94451 642,428.57812 c -0.42664,-0.0128 -0.85775,-0.0147 -1.29297,-0.004 z"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.42566061px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
<rect
|
||||
transform="matrix(0.89707316,-0.44188205,0.39545007,0.91848747,0,0)"
|
||||
ry="4.5092516"
|
||||
rx="4.7671914"
|
||||
y="299.94894"
|
||||
x="-63.730179"
|
||||
height="22.140448"
|
||||
width="42.955582"
|
||||
id="rect5118"
|
||||
style="fill:#000000;fill-opacity:1;stroke:#ffffff;stroke-width:1.4265933;stroke-opacity:1" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path5120"
|
||||
d="m 275.08906,417.33778 4.375,22.875 80.75,-60.625 z"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.42566061px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
<path
|
||||
sodipodi:nodetypes="cssc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path5122"
|
||||
d="m 281.58906,443.33778 91.75,-68.625 c 10.87423,-8.13345 34.03844,-10.26653 -9.25,21.375 -37.38734,27.32814 -82.5,47.25 -82.5,47.25 z"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.42566061px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
<path
|
||||
sodipodi:nodetypes="ccccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path5124"
|
||||
d="m 197.58906,448.96278 c 6.125,13 10.625,29.125 10.625,29.125 0,0 57.34269,-25.16319 68.25,-30.75 -0.13843,-9.48681 -3.52264,-22.72856 -8.375,-27.875 -27.125,3.75 -70.5,29.5 -70.5,29.5 z"
|
||||
style="fill:url(#linearGradient3078);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.42566073;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
|
||||
<path
|
||||
sodipodi:nodetypes="ccsccczc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path5138"
|
||||
d="m 3.47828,341.26173 c 0,0 6.886406,9.46214 7.95495,30.22881 -9.7125082,0.38797 -22.45064,-1.59098 -48.96714,10.78339 -26.5165,12.37437 -35.70889,37.29989 -35.70889,37.29989 l -6.84404,-0.46967 -8.1731,-22.75242 c 0,0 5.196794,-22.7334 30.485095,-40.41753 C -32.486544,338.25007 3.47828,341.26173 3.47828,341.26173 z"
|
||||
style="fill:#797979;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.42566061px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path5140"
|
||||
transform="translate(-522.78594,-97.359255)"
|
||||
d="m 527.89648,441.94336 c -11.21543,-6.8e-4 -35.91089,1.15173 -54.02148,10.37891 -20.66776,10.53002 -34.76604,36.66892 -38.41016,44.00195 l 7.17383,19.9707 c 2.6388,-7.65898 11.92913,-28.82418 37.36133,-42.34765 27.46537,-14.60461 48.83613,-10.8705 53.86328,-9.67383 -1.11415,-11.22385 -3.86953,-18.48609 -5.74414,-22.32617 -0.0929,-1.7e-4 -0.12786,-0.004 -0.22266,-0.004 z"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none" />
|
||||
<path
|
||||
sodipodi:nodetypes="sccs"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path5145"
|
||||
transform="translate(-522.78594,-97.359255)"
|
||||
d="m 485.25195,479.63281 c -26.5165,12.37437 -35.70886,37.34486 -35.70886,37.34486 9.75656,-6.29912 84.5483,-48.37571 84.5483,-48.37571 -6.04962,0.7682 -22.32294,-1.34352 -48.83944,11.03085 z"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path5151"
|
||||
d="m -6.1035156,230.91992 c -19.3024674,3.60682 -35.0488854,16.31894 -52.6556354,24.21599 -51.094769,27.0536 -101.437299,55.94388 -149.051399,88.65901 -9.95415,5.51243 -22.54214,11.99271 -33.83984,6.61914 -6.38959,-3.90926 -7.96324,-11.94005 -8.66992,-18.82617 -15.28799,12.40039 -32.51253,23.07504 -46.6875,36.30469 11.43671,32.54466 37.53518,57.07166 61.90234,80.5625 1.79409,1.58773 4.14015,-3.28155 6.15485,-2.80815 C -144.1825,402.09598 -56.798635,363.92186 29.448769,323.50255 46.66114,315.61589 63.86767,307.71041 80.912109,299.46484 75.326356,287.31278 62.865961,280.7519 53.502952,271.87742 35.5688,257.98999 18.22755,242.94827 -1.484375,231.63672 c -1.4916064,-0.46547 -3.0527704,-0.75113 -4.6191406,-0.7168 z"
|
||||
style="fill:#868686;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline"
|
||||
transform="translate(124.57988,108.29077)" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path5162"
|
||||
d="m -28.414062,137.02148 c -76.907488,29.50803 -148.819988,71.80459 -213.308758,122.89206 -13.55128,17.43946 -23.11685,37.54603 -33.88323,56.82187 -3.7754,7.32186 -7.34192,14.58222 -10.84707,22.04584 11.21464,-8.37958 22.86793,-16.47415 33.20898,-25.8125 -0.25698,-17.631 11.68533,-33.06792 26.42383,-41.59375 31.52229,-22.08766 66.11652,-39.23093 99.04413,-59.05073 30.395219,-17.37588 61.961588,-32.92482 91.295711,-52.0313 6.692064,-6.28955 7.910236,-15.49613 9.814453,-23.93359 l -0.935164,0.35421 -0.812882,0.30789 z"
|
||||
style="fill:#868686;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline"
|
||||
transform="translate(124.57988,108.29077)" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path5173"
|
||||
d="m 152.77364,310.2307 c 1.1582,6.05599 2.3164,12.11198 3.4746,18.16797 21.37631,-16.04948 42.75261,-32.09896 64.12891,-48.14843 -22.5345,9.99349 -45.06901,19.98697 -67.60351,29.98046 z"
|
||||
style="fill:#868686;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline"
|
||||
transform="translate(124.57988,108.29077)" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path5187"
|
||||
d="m 261.2834,263.28539 c -12.21657,2.16029 -20.42211,12.86093 -30.56476,19.12846 -18.40968,13.8199 -38.36778,28.59535 -55.81414,41.82076 29.28272,-15.22709 58.48771,-31.62916 82.88671,-54.0625 1.70896,-1.96865 4.73868,-4.48833 4.69532,-6.85547 -0.39767,-0.0641 -0.80252,-0.0596 -1.20313,-0.0312 z"
|
||||
style="fill:#868686;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline"
|
||||
transform="translate(124.57988,108.29077)" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path5192"
|
||||
d="m 42.546875,449.04102 c 19.339052,15.73498 36.723013,34.10436 57.603515,47.67578 20.60808,9.36671 43.55773,2.08926 64.83959,-0.49809 35.57938,-6.15258 71.49952,-11.18454 106.39931,-20.59787 15.04923,-4.60526 29.72058,-14.93837 34.46618,-30.81811 9.43121,-25.52623 9.54274,-53.05503 12.87313,-79.81517 -0.62149,-4.24546 3.55982,-14.72991 -0.52003,-14.51534 -91.88723,32.85626 -183.77446,65.71253 -275.661695,98.5688 z"
|
||||
style="fill:url(#linearGradient3080);fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline"
|
||||
transform="translate(124.57988,108.29077)" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="rect5212"
|
||||
d="m -27.103516,182.32422 c -10.397754,4.71799 -21.409505,9.91406 -30.929687,15.4375 2.508683,3.97971 3.88786,8.5168 5.707031,12.72266 10.007293,-5.84796 21.032198,-9.89858 31.039063,-15.81641 -1.598593,-4.02995 -3.118058,-9.77197 -5.816407,-12.34375 z"
|
||||
style="fill:#868686;fill-opacity:1;stroke:none;display:inline"
|
||||
transform="translate(124.57988,108.29077)" />
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer4"
|
||||
inkscape:label="Leaders"
|
||||
transform="translate(647.36582,-57.672066)"
|
||||
style="display:inline">
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:40.00000381px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:end;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;display:inline;font-family:Sans;-inkscape-font-specification:'Sans, Normal'"
|
||||
x="-502.6427"
|
||||
y="633.16559"
|
||||
id="text4473"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4475"
|
||||
x="-502.6427"
|
||||
y="633.16559"
|
||||
style="font-size:32px">Button0</tspan></text>
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text4477"
|
||||
y="337.89117"
|
||||
x="-491.6427"
|
||||
style="font-size:40.00000381px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:end;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;display:inline;font-family:Sans;-inkscape-font-specification:'Sans, Normal'"
|
||||
xml:space="preserve"><tspan
|
||||
y="337.89117"
|
||||
x="-491.6427"
|
||||
id="tspan4479"
|
||||
sodipodi:role="line"
|
||||
style="font-size:32px">Button1</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:40.00000381px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:end;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;display:inline;font-family:Sans;-inkscape-font-specification:'Sans, Normal'"
|
||||
x="-484.6427"
|
||||
y="453.61685"
|
||||
id="text4481"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4483"
|
||||
x="-484.6427"
|
||||
y="453.61685"
|
||||
style="font-size:32px">Button2</tspan></text>
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text4485"
|
||||
y="235.48463"
|
||||
x="-59.791931"
|
||||
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;display:inline;font-family:Sans"
|
||||
xml:space="preserve"><tspan
|
||||
y="235.48463"
|
||||
x="-59.791931"
|
||||
id="tspan4487"
|
||||
sodipodi:role="line"
|
||||
style="font-size:32px">Button3</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;display:inline;font-family:Sans"
|
||||
x="-265.79193"
|
||||
y="177.2103"
|
||||
id="text4489"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4491"
|
||||
x="-265.79193"
|
||||
y="177.2103"
|
||||
style="font-size:32px">Button4</tspan></text>
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text4493"
|
||||
y="713.93604"
|
||||
x="-229.79195"
|
||||
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;display:inline;font-family:Sans"
|
||||
xml:space="preserve"><tspan
|
||||
y="713.93604"
|
||||
x="-229.79195"
|
||||
id="tspan4495"
|
||||
sodipodi:role="line"
|
||||
style="font-size:32px">Button5</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;display:inline;font-family:Sans"
|
||||
x="-499.79196"
|
||||
y="209.66159"
|
||||
id="text4497"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4499"
|
||||
x="-499.79196"
|
||||
y="209.66159"
|
||||
style="font-size:32px">Button6</tspan></text>
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m -484.36582,336.67204 121,88"
|
||||
id="path3082"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m -480.36582,448.67204 148,-7"
|
||||
id="path3084"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m -492.36582,626.67204 130,-108"
|
||||
id="path3086"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m -375.36582,214.67204 133,180"
|
||||
id="path3088"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m -167.36582,192.67204 81,275"
|
||||
id="path3092"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 34.63418,254.67204 -67,189"
|
||||
id="path3094"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m -152.36582,675.67204 85,-87"
|
||||
id="path3096"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 21 KiB |
182
data/logo.svg
Normal file
@@ -0,0 +1,182 @@
|
||||
<?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="180.65305mm"
|
||||
height="180.65305mm"
|
||||
viewBox="0 0 180.65305 180.65305"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
inkscape:version="0.92.4 5da689c313, 2019-01-14"
|
||||
sodipodi:docname="logo.svg">
|
||||
<defs
|
||||
id="defs2" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1"
|
||||
inkscape:cx="-156.7648"
|
||||
inkscape:cy="473.25323"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:current-layer="layer2"
|
||||
showgrid="false"
|
||||
inkscape:measure-start="0,0"
|
||||
inkscape:measure-end="0,0"
|
||||
inkscape:window-width="2560"
|
||||
inkscape:window-height="1376"
|
||||
inkscape:window-x="2560"
|
||||
inkscape:window-y="27"
|
||||
inkscape:window-maximized="1"
|
||||
showguides="true"
|
||||
inkscape:guide-bbox="true"
|
||||
inkscape:snap-to-guides="true">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid1058"
|
||||
originx="-15.590431"
|
||||
originy="-49.255695" />
|
||||
</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="layer4"
|
||||
inkscape:label="rat right"
|
||||
style="display:inline;opacity:1"
|
||||
transform="translate(-15.59043,-80.129979)">
|
||||
<path
|
||||
sodipodi:nodetypes="sssssssssssssssccssscss"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path1039"
|
||||
d="m 181.70318,102.59719 c -3.2499,1.24415 -5.70487,5.21773 -6.1731,8.64054 -0.46127,3.37194 1.06674,8.17528 5.17162,8.92716 1.88245,0.3448 5.75552,3.71382 1.56778,2.91866 -4.41092,-0.83753 -9.60561,-1.81767 -12.03434,-5.88833 -2.51189,-4.21004 -6.0824,-2.70094 -9.60946,-1.97697 -3.61649,0.74233 -3.34262,3.70961 -0.59483,4.79149 1.76651,0.69552 -4.7698,1.02182 -6.46586,-0.31589 -0.99074,-0.7814 -4.3093,0.86964 -6.03067,0.70651 -4.14705,-0.39301 -8.0988,0.0723 -12.42874,-0.59505 -2.75134,-0.42408 -6.23873,1.52773 -5.40472,-2.94355 0.41316,-2.21506 -1.53788,-7.95327 -0.25583,-12.08908 1.43935,-4.64326 2.78762,-6.554728 6.29989,-9.291599 2.96282,-2.308725 9.62529,-5.456849 13.27656,-6.171955 5.94327,-1.163997 13.69394,2.401773 15.47361,3.054918 2.51726,0.923848 7.67473,-3.278929 11.1961,-3.200515 2.07518,-1.437388 4.50939,-5.479552 6.03783,0.452639 3.26133,0.136438 5.00967,-0.06864 9.09359,2.312711 2.76398,1.611684 4.87236,1.538272 5.34391,2.873448 0.62005,1.755647 -2.69292,5.296383 -3.28547,5.288623 -0.8492,-0.0111 -0.81394,0.0819 -2.0197,0.17649 -0.32445,1.41613 -2.05245,1.97075 -5.1013,1.61048 -1.43172,-0.16918 -2.7495,0.21878 -4.05687,0.71927 z"
|
||||
style="display:inline;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path1045"
|
||||
d="m 119.43296,119.1374 c -3.19754,-3.4816 -3.91548,-3.31073 -5.87228,-7.17694 -1.51881,-4.76902 -1.2579,-3.59102 -4.44899,-11.00554 2.31432,2.99141 3.84563,6.48437 5.56001,9.87162 2.19923,4.34517 4.03074,4.88595 7.22829,8.36756"
|
||||
style="display:inline;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
sodipodi:nodetypes="cccsc" />
|
||||
<path
|
||||
transform="translate(-4.1666665e-8,1.0416667e-6)"
|
||||
style="display:inline;fill:#ffffff;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1"
|
||||
d="m 183.59605,92.870943 c 0.70159,-0.65481 2.47893,-0.65481 2.89988,-0.187088 0.42095,0.467721 -1.82412,1.028987 -2.89988,0.187088 z"
|
||||
id="path833"
|
||||
inkscape:connector-curvature="0">
|
||||
<animate
|
||||
values="orange;red;orange"
|
||||
dur="7s"
|
||||
repeatCount="indefinite"
|
||||
attributeName="fill" />
|
||||
</path>
|
||||
</g>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer2"
|
||||
inkscape:label="rat left"
|
||||
style="display:inline;opacity:1"
|
||||
transform="translate(-15.59043,-80.129979)">
|
||||
<path
|
||||
sodipodi:nodetypes="ccsccccccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path1298"
|
||||
d="m 86.198873,115.45536 c -0.640498,-1.90396 -0.324058,-5.87792 -2.548937,-9.26118 1.761266,-3.58236 5.461967,-1.0306 3.345989,-4.71668 -1.27974,-2.229332 -5.394303,-0.5453 -6.437336,0.67341 -2.968786,0.40847 -6.280299,-3.592034 -8.586349,-4.613758 -3.902419,-1.141693 -9.722226,-2.223874 -12.939723,-3.303186 -2.646277,1.694635 -1.446947,6.207524 -1.598912,7.088294 1.30852,3.28167 1.243822,1.80143 2.493275,5.51481 2.008262,2.23089 4.855928,4.59155 5.686271,9.4289 7.349678,-0.38854 9.558907,-0.59389 20.585722,-0.81061 z"
|
||||
style="display:inline;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
<path
|
||||
sodipodi:nodetypes="ccccsc"
|
||||
style="display:inline;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 108.49567,117.83325 c -0.24901,-4.72058 -0.43574,-9.98729 -1.82782,-14.09082 -4.0267,-10.295998 -4.72401,-12.496029 -0.0129,-13.556767 -2.07044,-0.256651 -5.41881,-0.421857 -5.48281,2.489527 0.517,3.746632 1.94024,7.284981 3.15986,10.88015 1.56453,4.61189 1.00424,9.35889 1.25325,14.07947"
|
||||
id="path955"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
transform="translate(-4.1666665e-8,1.0416667e-6)"
|
||||
style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 71.938542,102.84868 c -0.902446,-0.17526 -1.969377,-1.68007 -1.548427,-2.12186 0.867434,-0.27642 1.714682,0.92977 1.548427,2.12186 z"
|
||||
id="path833-3"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccc">
|
||||
<animate
|
||||
values="green;yellow;green"
|
||||
dur="3s"
|
||||
repeatCount="indefinite"
|
||||
attributeName="fill" />
|
||||
</path>
|
||||
</g>
|
||||
<g
|
||||
inkscape:label="sack"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
style="display:inline"
|
||||
transform="translate(-15.59043,-80.129979)">
|
||||
<rect
|
||||
ry="0.44884709"
|
||||
y="172.18915"
|
||||
x="1150"
|
||||
height="4.8108511"
|
||||
width="6.0803819"
|
||||
id="rect1075"
|
||||
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:3.16499996;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<g
|
||||
style="display:inline;opacity:1"
|
||||
id="g1316"
|
||||
transform="translate(-11.599497,6.3500003)">
|
||||
<path
|
||||
sodipodi:nodetypes="cccccczzcczc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path815"
|
||||
d="m 71.911001,151.04073 c -13.545552,17.75365 -48.518606,24.46129 -42.445015,52.8882 4.987974,25.22201 13.988429,29.44417 56.008367,27.90906 47.288497,0.24745 47.307997,0.7217 90.436597,0.28592 14.07598,2.60143 28.63685,-20.8018 23.94043,-35.61574 -4.77259,-20.1552 -28.81931,-24.18426 -36.25354,-41.43822 -7.52218,-23.58108 1.99039,-35.03297 22.19568,-25.38895 20.20529,9.64403 26.03755,-15.82001 -11.10418,-15.33498 -37.14173,0.48503 -66.18409,-5.57956 -84.958574,-4.07459 -15.461428,0.81842 -41.712504,-2.86861 -44.765236,21.70932 2.422297,6.71408 19.985082,-12.15526 27.605897,-5.44801 7.620815,6.70724 20.413185,4.32379 -0.660426,24.50799 z"
|
||||
style="display:inline;fill:none;fill-opacity:1;stroke:#000000;stroke-width:3.16499996;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
sodipodi:nodetypes="ccccc"
|
||||
style="display:inline;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1.16499996;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 79.716618,142.54753 c 0,0 63.912362,8.07113 81.488252,0.7006 0,0 -0.56974,-7.74657 1.60362,-10.91212 -17.57589,7.37053 -79.821755,-0.0115 -79.821755,-0.0115 3.474504,7.01583 -3.270117,10.22298 -3.270117,10.22298 z"
|
||||
id="path842"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer6"
|
||||
inkscape:label="rat bottom"
|
||||
style="display:inline;opacity:1"
|
||||
transform="translate(-15.59043,-80.129979)">
|
||||
<path
|
||||
sodipodi:nodetypes="cccccccccccccccccccccccccccccccccccccccccsccccccccccccccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path1212"
|
||||
d="m 122.70428,243.35492 c 6.05524,1.14081 7.22067,1.31431 10.02264,2.72758 0,0.38071 -0.19945,0.89381 -1.01365,1.66697 -0.8142,0.77314 -2.6542,0.92241 -3.94953,1.25266 -0.67325,0.3643 -1.36184,1.00187 -1.50199,1.72727 3.97782,-1.45575 2.82486,-1.28103 2.75389,0.45072 0.20024,0.42037 1.54248,-1.05607 1.70256,-1.07661 1.00124,-0.41482 0.93822,0.001 1.55056,0.0319 0.20389,0.64546 -0.30382,1.34832 -0.26341,1.72391 0.84425,0.0769 1.57036,-1.33585 1.5884,-2.00591 0.34832,-0.5087 0.57096,-0.30966 1.0296,0 0.83149,0.862 0.93498,0.50569 1.95428,1.01599 2.24374,0.45044 -0.93235,-2.10713 -1.49797,-2.41992 -0.0737,-0.0369 1.39328,-2.39745 1.58909,-2.64425 2.32503,-0.403 4.75988,-1.00269 6.10414,-1.57594 v -1.2e-4 c 5.97825,1.84348 14.60207,1.47181 21.66926,1.7325 8.87347,0.60502 6.80866,4.81981 -11.94665,7.57383 29.43774,3.60709 24.29174,-11.42807 13.49975,-11.41332 -4.45874,0.0577 -12.7835,-0.12064 -21.26078,-1.9791 -1.35135,-2.33359 -1.8837,-5.9598 -1.12611,-9.63435 -2.49031,-11.667 -8.91489,-30.75707 -16.82134,-42.62455 -2.9074,-3.93147 -6.12061,-11.52979 -7.33913,-14.68828 7.81948,-5.62697 0.38705,-8.64346 -3.43515,-4.04735 -4.2835,-4.24158 -9.25924,-6.58986 -17.436457,-7.91069 -4.46939,6.75139 7.201157,21.8355 7.201157,21.8355 0.27261,11.69368 -1.47411,14.8979 -4.3435,23.39568 0.0471,0.3928 -0.49786,0.52092 -0.68357,0.83384 -0.19254,0.21312 -0.924097,1.82103 -1.179137,2.01487 -0.12771,0.23832 -0.38006,0.38366 -0.60384,0.59827 -0.23775,0.19619 -0.40433,0.49501 -0.42142,0.8292 -0.13385,0.31584 -0.17018,0.488 -0.19925,0.87639 -0.15645,0.29381 0.11002,0.40231 0.35386,0.34986 0.27783,-0.0135 0.56968,0.0505 0.82065,-0.10012 0.38688,-0.0135 0.824117,-0.32301 0.901337,-0.70099 0.0571,-0.34113 0.16568,-0.80155 0.62396,-0.6509 0.27636,0.006 0.58137,-0.16307 0.77806,0.15023 0.27193,0.12771 0.77421,0.23993 0.87876,-0.14883 0.16039,-0.42589 0.57357,-0.67322 0.67434,-1.12667 0.14254,-0.12321 0.37352,-0.19611 0.30974,-0.28545 0.26187,-0.26516 0.52474,-0.58479 0.89076,-0.74525 3.05534,-1.07719 3.51973,-4.67744 3.86462,-4.59812 0.67734,0.15577 -0.84342,6.82001 3.73079,20.85428 -1.4046,15.75023 6.7093,18.67126 6.7093,18.67126 0.17258,1.22487 -3.10226,1.32242 -3.80222,1.80721 -0.96512,0.31347 -2.42142,0.5571 -3.36241,0.16943 -0.41052,-0.20344 -1.14128,-0.10911 -0.6235,0.34889 -0.6851,0.62634 -1.75451,0.42589 -2.61368,0.63307 -0.84134,0.12395 -1.06409,1.07707 -0.0627,0.80147 -0.42125,1.18238 1.04775,0.72998 1.68923,0.70002 0.53648,-0.0399 0.30954,0.7577 0.96774,0.39958 0.92805,-0.19058 1.83353,-0.32154 2.75115,-0.51031 0.98245,-0.0454 1.60905,0.10657 2.586,0.18597 0.728,0.16342 2.43322,-0.53193 2.89833,-1.06277 0.62324,-0.55427 1.57699,-1.41676 2.07353,-2.11063 0.49656,-0.69386 0.66544,-0.53528 1.31986,-1.29795 z"
|
||||
style="display:inline;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.39657527px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
<path
|
||||
sodipodi:nodetypes="ccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path850"
|
||||
d="m 109.46587,169.42014 c -0.90244,-0.17526 -1.96937,-1.68007 -1.54842,-2.12186 0.86743,-0.27642 1.71468,0.92977 1.54842,2.12186 z"
|
||||
style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1">
|
||||
<animate
|
||||
values="red;blue;red"
|
||||
dur="5s"
|
||||
repeatCount="indefinite"
|
||||
attributeName="fill" />
|
||||
</path>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 12 KiB |
@@ -1,557 +0,0 @@
|
||||
<?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="750"
|
||||
height="750"
|
||||
viewBox="0 0 750.00004 749.99998"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.4 r9939"
|
||||
sodipodi:docname="roccat-kone-xtd.svg">
|
||||
<defs
|
||||
id="defs4" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1.3581868"
|
||||
inkscape:cx="337.88759"
|
||||
inkscape:cy="511.56243"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer4"
|
||||
showgrid="false"
|
||||
showguides="true"
|
||||
inkscape:guide-bbox="true"
|
||||
fit-margin-top="50"
|
||||
fit-margin-left="50"
|
||||
fit-margin-right="50"
|
||||
fit-margin-bottom="50"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1099"
|
||||
inkscape:window-x="1920"
|
||||
inkscape:window-y="28"
|
||||
inkscape:window-maximized="1" />
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<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:label="Device"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(522.78594,-165.96284)"
|
||||
style="display:inline">
|
||||
<g
|
||||
id="g3136"
|
||||
transform="matrix(0.68876596,0,0,0.68876596,-231.95789,223.11559)">
|
||||
<path
|
||||
sodipodi:nodetypes="csc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4770"
|
||||
d="m -6.8766439,519.77381 c -32.5046101,10.85914 -64.2932331,9.07935 -55.9542041,-23.77308 18.883288,-74.39257 -57.845532,2.41084 -29.233145,-133.3763"
|
||||
style="fill:none;stroke:#000000;stroke-width:29.49614906;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
|
||||
<path
|
||||
sodipodi:nodetypes="ccsssssccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3661"
|
||||
d="m -33.934887,422.04568 10.14038,-25.10953 C 52.122953,323.19727 160.74504,269.07207 269.83981,256.48052 c 114.24665,-13.18617 232.89306,-1.04277 284.3675,72.85307 67.68352,97.16539 16.07476,170.11753 -8.69176,195.56454 -20.05502,20.60604 -39.26023,38.76732 -57.46217,50.70193 -38.08063,24.96863 -99.02413,29.12078 -118.30443,27.5239 -56.28478,-4.66179 -227.65266,41.307 -235.6432,46.83891 L 32.219046,607.9527 C 4.8894737,559.61921 -21.751345,509.50644 -33.934887,422.04568 z"
|
||||
style="fill:#293843;fill-opacity:1;fill-rule:evenodd;stroke:none" />
|
||||
<path
|
||||
id="path4463"
|
||||
d="m 520.63342,372.91486 c -22.02158,0.11026 -45.15654,9.22867 -63.99943,19.07328 -68.64532,35.8642 -269.2094,153.12888 -338.02986,180.28255 l -87.122352,34.37512 c 0.245863,0.43536 0.49112,0.87206 0.737105,1.30711 l 39.216027,16.16965 c 44.83999,-15.41316 98.86516,-40.41176 154.72423,-67.21674 90.48008,-43.41854 177.45369,-92.45774 236.96271,-121.89569 60.39622,-29.87684 105.87888,-24.18751 112.83284,44.85426 6.15884,-13.91293 10.75607,-30.17964 11.63778,-48.45529 -13.44827,-44.58801 -39.32739,-58.63259 -66.95905,-58.49425 z"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
sodipodi:nodetypes="ccccccccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4468"
|
||||
d="m 460.17444,405.06363 c -25.33816,12.5814 -164.20311,89.16529 -247.36725,132.94909 -31.24494,16.55348 -62.91668,32.44366 -95.5461,46.08015 l 3.13236,9.65662 c 54.85379,-22.99389 108.07344,-49.78006 161.39646,-76.09146 64.31558,-32.64428 127.12882,-68.2385 192.32459,-99.13545 18.32983,-7.64259 38.30614,-12.8303 58.27155,-10.58417 14.47996,1.85097 28.06901,9.59531 37.24885,20.96153 6.66994,-53.74538 -76.10417,-40.33748 -109.46046,-23.83631 z"
|
||||
style="fill:#00ff3a;fill-opacity:1;fill-rule:evenodd;stroke:none" />
|
||||
<path
|
||||
sodipodi:nodetypes="cccccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4545"
|
||||
d="m 270.88842,559.80819 26.12051,4.09732 62.14289,-30.90074 c 11.97455,-20.17142 5.93562,-23.53024 5.29239,-31.92505 l -91.50713,47.4608 c -3.16993,2.58552 -6.42443,5.13123 -2.04866,11.26767 z"
|
||||
style="fill:#202427;fill-opacity:1;fill-rule:evenodd;stroke:none" />
|
||||
<path
|
||||
sodipodi:nodetypes="ccccccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4547"
|
||||
d="m 392.10122,486.05615 c 1.23298,4.69552 4.04803,7.598 -1.19506,19.63307 l -9.73117,17.58438 80.75159,-31.4129 c 5.77716,-10.78358 11.4074,-21.61616 11.4384,-34.31516 -2.7867,-11.40006 -8.20083,-9.22506 -13.65779,-6.82888 z"
|
||||
style="fill:#202427;fill-opacity:1;fill-rule:evenodd;stroke:none" />
|
||||
<path
|
||||
sodipodi:nodetypes="ccccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4549"
|
||||
d="M 20.837165,461.33753 26.414193,480.9345 62.94875,466.25238 55.307676,431.63187 z"
|
||||
style="fill:#202427;fill-opacity:1;fill-rule:evenodd;stroke:none" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4551"
|
||||
d="m 178.69842,365.35554 12.29201,31.24217 56.50906,-25.09617 -12.46274,-27.48628 z"
|
||||
style="fill:#202427;fill-opacity:1;fill-rule:evenodd;stroke:none" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4553"
|
||||
d="m 261.4987,335.64987 11.95056,26.63267 49.85089,-20.31594 12.80416,-3.41445 -6.82888,-14.16994 -12.97489,-3.41445 z"
|
||||
style="fill:#202427;fill-opacity:1;fill-rule:evenodd;stroke:none" />
|
||||
<path
|
||||
d="m 204.43745,364.0435 2.09895,5.60714 5.81901,-2.56255 0.64062,1.71134 -5.81901,2.56254 2.09895,5.60714 -1.75511,0.77292 -2.09894,-5.60715 -5.81902,2.56255 -0.64059,-1.71135 5.81898,-2.56254 -2.09892,-5.60714 1.75508,-0.7729 z"
|
||||
id="path4560"
|
||||
inkscape:connector-curvature="0"
|
||||
style="font-size:medium;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:tb-rl;fill:#838d96;fill-opacity:1;stroke:none;font-family:sans-serif" />
|
||||
<path
|
||||
style="font-size:medium;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;fill:#838d96;fill-opacity:1;stroke:none;font-family:sans-serif"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4567"
|
||||
d="m 305.42303,329.94388 4.03768,8.95391 -2.72436,1.22853 -4.03769,-8.95391 2.72437,-1.22853 z" />
|
||||
<path
|
||||
d="m 46.989112,448.7916 2.557622,11.39542 -2.682847,1.56354 -2.557622,-11.39545 2.682847,-1.56351 z"
|
||||
id="path4569"
|
||||
inkscape:connector-curvature="0"
|
||||
style="font-size:medium;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;fill:#838d96;fill-opacity:1;stroke:none;font-family:sans-serif" />
|
||||
<path
|
||||
style="font-size:medium;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;fill:#838d96;fill-opacity:1;stroke:none;font-family:sans-serif"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4577"
|
||||
d="m 42.643233,451.50777 2.557622,11.39545 -2.682847,1.56351 -2.557622,-11.39545 2.682847,-1.56351 z" />
|
||||
<path
|
||||
d="m 38.478433,454.34466 2.557622,11.39543 -2.682847,1.56354 -2.557622,-11.39545 2.682847,-1.56352 z"
|
||||
id="path4579"
|
||||
inkscape:connector-curvature="0"
|
||||
style="font-size:medium;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;fill:#838d96;fill-opacity:1;stroke:none;font-family:sans-serif" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4581"
|
||||
d="m 119.43841,465.4441 5.37199,3.74229 1.87114,-8.26926 z"
|
||||
style="fill:#838d96;fill-opacity:1;fill-rule:evenodd;stroke:none" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4583"
|
||||
d="m 99.218,376.23286 -2.29366,6.51884 6.33774,-3.25942 z"
|
||||
style="fill:#838d96;fill-opacity:1;fill-rule:evenodd;stroke:none" />
|
||||
<path
|
||||
id="path4585"
|
||||
d="m 370.13999,299.12951 c -0.43414,-0.004 -0.88599,0.004 -1.35658,0.0243 -114.61991,18.29248 -262.7613,57.8235 -362.6396132,162.97056 l -0.2413441,18.34924 -23.0804397,18.75305 c 0.295394,0.96107 0.592605,1.91666 0.892085,2.8672 L 6.8682998,485.78508 11.938416,498.5815 c 3.022522,1.91455 4.542353,4.99753 13.03731,2.65575 0,0 35.049508,-13.87527 66.878294,-31.62836 25.86269,-14.4254 169.13513,-92.29377 297.45122,-135.68783 3.53168,-1.85807 6.92052,-3.82383 2.89753,-11.3479 l -11.34789,-17.38339 c -1.68431,-3.27833 -4.20267,-6.0005 -10.71489,-6.06024 z m 0.85055,7.18994 c 0.76127,-0.0183 1.49621,0.14715 2.1413,0.68389 2.28062,2.60105 3.95393,5.73706 5.90572,8.6044 2.36789,3.85426 5.13602,7.51375 7.31692,11.43239 -2.00889,0.76437 -4.02217,1.5172 -6.0383,2.2622 -74.38121,26.47497 -146.51346,58.91354 -216.93155,94.53357 -23.7859,11.80119 -47.13201,24.45131 -70.49007,37.07193 -21.87976,12.03816 -44.368571,22.99172 -67.494965,32.39674 -2.178032,0.79387 -4.91012,2.49014 -7.139522,0.97798 -2.462342,-3.62775 -3.065109,-8.18739 -5.10326,-12.05744 -0.191754,-5.72806 0.125694,-11.45575 0.125574,-17.18406 19.24401,-19.99827 40.662677,-37.85032 63.501803,-53.60899 56.88977,-39.14613 121.81546,-65.28367 188.25625,-83.14833 34.45174,-9.02055 69.30996,-16.66573 104.56505,-21.77335 0.46215,-0.10291 0.9283,-0.17995 1.38505,-0.19093 z"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
sodipodi:nodetypes="czsccscc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4590"
|
||||
d="m 69.56866,436.43193 c 2.34022,-18.39325 11.0874,-31.41629 35.56456,-46.25604 24.47717,-14.83973 51.02774,-12.17822 62.53237,-11.10613 4.19739,0.39116 6.14741,2.1271 9.65751,8.20888 l 9.65751,18.10785 c -9.72905,-3.24303 -45.31306,0.55135 -63.36379,8.82104 -23.93977,10.96767 -32.63451,13.417 -49.78556,44.90031 z"
|
||||
style="fill:#202427;fill-opacity:1;fill-rule:evenodd;stroke:none" />
|
||||
<text
|
||||
transform="matrix(0.81792144,-0.30782972,0,1.2226113,0,0)"
|
||||
sodipodi:linespacing="125%"
|
||||
id="text4751"
|
||||
y="544.12469"
|
||||
x="541.47949"
|
||||
style="font-size:19.26995659px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;fill:#838d96;fill-opacity:1;stroke:none;font-family:sans-serif;-inkscape-font-specification:sans-serif Bold"
|
||||
xml:space="preserve"><tspan
|
||||
y="544.12469"
|
||||
x="541.47949"
|
||||
id="tspan4753"
|
||||
sodipodi:role="line">></tspan></text>
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4759"
|
||||
d="m 300.25264,556.5858 10.24335,-10.8622 0.29876,2.6035 -4.75887,5.05767 6.35939,-0.96032 0.72556,2.19804 z"
|
||||
style="fill:#838d96;fill-opacity:1;fill-rule:evenodd;stroke:none" />
|
||||
<path
|
||||
id="path4761"
|
||||
d="m 175.51398,404.23374 c -14.95857,0.0867 -38.3591,3.7713 -51.89715,9.97357 -23.8618,10.93194 -32.57995,13.40905 -49.62048,44.60172 l 112.98222,-53.41898 -0.0122,-0.008 c -2.4337,-0.80767 -6.47543,-1.17722 -11.45245,-1.14838 z"
|
||||
style="fill:#151d23;fill-opacity:1;fill-rule:evenodd;stroke:none"
|
||||
inkscape:connector-curvature="0" />
|
||||
<ellipse
|
||||
sodipodi:ry="11.985341"
|
||||
sodipodi:rx="11.98534"
|
||||
sodipodi:cy="294.12094"
|
||||
sodipodi:cx="-12.758862"
|
||||
d="m -0.77352142,294.12094 c 0,6.61932 -5.36601958,11.98534 -11.98534058,11.98534 -6.61932,0 -11.98534,-5.36602 -11.98534,-11.98534 0,-6.61932 5.36602,-11.98534 11.98534,-11.98534 6.619321,0 11.98534058,5.36602 11.98534058,11.98534 z"
|
||||
ry="11.985341"
|
||||
rx="11.98534"
|
||||
cy="294.12094"
|
||||
cx="-12.758862"
|
||||
id="path4352"
|
||||
style="fill:#898989;fill-opacity:1;stroke:none;display:inline"
|
||||
transform="translate(124.57988,108.29077)" />
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer4"
|
||||
inkscape:label="Leaders"
|
||||
transform="translate(647.36582,-57.672066)"
|
||||
style="display:inline">
|
||||
<g
|
||||
style="display:inline"
|
||||
id="g4230"
|
||||
transform="translate(-312.22243,78.703789)">
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text4473"
|
||||
y="547.70569"
|
||||
x="-157.20392"
|
||||
style="font-size:40.00000381px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:end;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;display:inline;font-family:Sans;-inkscape-font-specification:'Sans, Normal'"
|
||||
xml:space="preserve"><tspan
|
||||
id="tspan4217"
|
||||
y="547.70569"
|
||||
x="-157.20392"
|
||||
sodipodi:role="line"
|
||||
style="font-size:32px">Button0</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:40.00000381px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:end;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;display:inline;font-family:Sans;-inkscape-font-specification:'Sans, Normal'"
|
||||
x="-157.20392"
|
||||
y="591.14594"
|
||||
id="text4212"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
x="-157.20392"
|
||||
y="591.14594"
|
||||
id="tspan4214"
|
||||
style="font-size:32px">Button12</tspan></text>
|
||||
</g>
|
||||
<g
|
||||
style="display:inline"
|
||||
id="g4224"
|
||||
transform="translate(-177.72019,47.152301)">
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:40.00000381px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:end;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;display:inline;font-family:Sans;-inkscape-font-specification:'Sans, Normal'"
|
||||
x="6.9855804"
|
||||
y="647.10291"
|
||||
id="text4216"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
x="6.9855804"
|
||||
y="647.10291"
|
||||
id="tspan4218"
|
||||
style="font-size:32px">Button3</tspan></text>
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text4220"
|
||||
y="690.54315"
|
||||
x="6.9855804"
|
||||
style="font-size:40.00000381px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:end;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;display:inline;font-family:Sans;-inkscape-font-specification:'Sans, Normal'"
|
||||
xml:space="preserve"><tspan
|
||||
id="tspan4222"
|
||||
y="690.54315"
|
||||
x="6.9855804"
|
||||
sodipodi:role="line"
|
||||
style="font-size:32px">Button15</tspan></text>
|
||||
</g>
|
||||
<g
|
||||
style="display:inline"
|
||||
id="g4250"
|
||||
transform="translate(-353.6901,52.306237)">
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text4238"
|
||||
y="645.63037"
|
||||
x="270.96399"
|
||||
style="font-size:40.00000381px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;display:inline;font-family:Sans;-inkscape-font-specification:'Sans, Normal'"
|
||||
xml:space="preserve"><tspan
|
||||
id="tspan4240"
|
||||
y="645.63037"
|
||||
x="270.96399"
|
||||
sodipodi:role="line"
|
||||
style="font-size:32px">Button4</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:40.00000381px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;display:inline;font-family:Sans;-inkscape-font-specification:'Sans, Normal'"
|
||||
x="270.96399"
|
||||
y="689.07062"
|
||||
id="text4242"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
x="270.96399"
|
||||
y="689.07062"
|
||||
id="tspan4244"
|
||||
style="font-size:32px">Button16</tspan></text>
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 426.30366,602.00857 72.8913,-163.45321"
|
||||
id="path3163"
|
||||
inkscape:connector-curvature="0"
|
||||
transform="translate(-293.67572,5.365799)" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 629.51576,602.74485 586.81177,393.64254"
|
||||
id="path3165"
|
||||
inkscape:connector-curvature="0"
|
||||
transform="translate(-293.67572,5.365799)" />
|
||||
</g>
|
||||
<g
|
||||
style="display:inline"
|
||||
id="g4256"
|
||||
transform="translate(-311.42639,-501.45091)">
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:40.00000381px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;display:inline;font-family:Sans;-inkscape-font-specification:'Sans, Normal'"
|
||||
x="195.12758"
|
||||
y="642.68524"
|
||||
id="text4258"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
x="195.12758"
|
||||
y="642.68524"
|
||||
id="tspan4260"
|
||||
style="font-size:32.00000171px">Button10</tspan></text>
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text4262"
|
||||
y="686.12549"
|
||||
x="195.12758"
|
||||
style="font-size:40.00000381px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;display:inline;font-family:Sans;-inkscape-font-specification:'Sans, Normal'"
|
||||
xml:space="preserve"><tspan
|
||||
id="tspan4264"
|
||||
y="686.12549"
|
||||
x="195.12758"
|
||||
sodipodi:role="line"
|
||||
style="font-size:32.00000171px">Button22</tspan></text>
|
||||
</g>
|
||||
<g
|
||||
style="display:inline"
|
||||
transform="translate(-539.74217,-541.2965)"
|
||||
id="g4266">
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text4268"
|
||||
y="642.68524"
|
||||
x="195.12758"
|
||||
style="font-size:40.00000381px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;display:inline;font-family:Sans;-inkscape-font-specification:'Sans, Normal'"
|
||||
xml:space="preserve"><tspan
|
||||
id="tspan4270"
|
||||
y="642.68524"
|
||||
x="195.12758"
|
||||
sodipodi:role="line"
|
||||
style="font-size:32px">Button9</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:40.00000381px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;display:inline;font-family:Sans;-inkscape-font-specification:'Sans, Normal'"
|
||||
x="195.12758"
|
||||
y="686.12549"
|
||||
id="text4272"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
x="195.12758"
|
||||
y="686.12549"
|
||||
id="tspan4274"
|
||||
style="font-size:32px">Button21</tspan></text>
|
||||
</g>
|
||||
<g
|
||||
style="display:inline"
|
||||
transform="translate(-209.20512,184.48383)"
|
||||
id="g4276">
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:40.00000381px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:end;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;display:inline;font-family:Sans;-inkscape-font-specification:'Sans, Normal'"
|
||||
x="-157.20392"
|
||||
y="547.70569"
|
||||
id="text4278"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
x="-157.20392"
|
||||
y="547.70569"
|
||||
id="tspan4280"
|
||||
style="font-size:32px">Button5</tspan></text>
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text4282"
|
||||
y="591.14594"
|
||||
x="-157.20392"
|
||||
style="font-size:40.00000381px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:end;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;display:inline;font-family:Sans;-inkscape-font-specification:'Sans, Normal'"
|
||||
xml:space="preserve"><tspan
|
||||
id="tspan4284"
|
||||
y="591.14594"
|
||||
x="-157.20392"
|
||||
sodipodi:role="line"
|
||||
style="font-size:32px">Button17</tspan></text>
|
||||
</g>
|
||||
<g
|
||||
style="display:inline"
|
||||
id="g4286"
|
||||
transform="translate(-330.93429,-54.814789)">
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text4288"
|
||||
y="547.70569"
|
||||
x="-157.20392"
|
||||
style="font-size:40.00000381px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:end;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;display:inline;font-family:Sans;-inkscape-font-specification:'Sans, Normal'"
|
||||
xml:space="preserve"><tspan
|
||||
id="tspan4290"
|
||||
y="547.70569"
|
||||
x="-157.20392"
|
||||
sodipodi:role="line"
|
||||
style="font-size:32px">Button11</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:40.00000381px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:end;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;display:inline;font-family:Sans;-inkscape-font-specification:'Sans, Normal'"
|
||||
x="-157.20392"
|
||||
y="591.14594"
|
||||
id="text4292"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
x="-157.20392"
|
||||
y="591.14594"
|
||||
id="tspan4294"
|
||||
style="font-size:32px">Button23</tspan></text>
|
||||
</g>
|
||||
<g
|
||||
style="display:inline"
|
||||
transform="translate(-333.46977,-188.98667)"
|
||||
id="g4338">
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:40.00000381px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:end;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;display:inline;font-family:Sans;-inkscape-font-specification:'Sans, Normal'"
|
||||
x="-157.20392"
|
||||
y="547.70569"
|
||||
id="text4340"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
x="-157.20392"
|
||||
y="547.70569"
|
||||
id="tspan4342"
|
||||
style="font-size:32px">Button1</tspan></text>
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text4344"
|
||||
y="591.14594"
|
||||
x="-157.20392"
|
||||
style="font-size:40.00000381px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:end;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;display:inline;font-family:Sans;-inkscape-font-specification:'Sans, Normal'"
|
||||
xml:space="preserve"><tspan
|
||||
id="tspan4346"
|
||||
y="591.14594"
|
||||
x="-157.20392"
|
||||
sodipodi:role="line"
|
||||
style="font-size:32px">Button13</tspan></text>
|
||||
</g>
|
||||
<g
|
||||
style="display:inline"
|
||||
id="g4348"
|
||||
transform="translate(-264.96175,-314.68951)">
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text4350"
|
||||
y="547.70569"
|
||||
x="-157.20392"
|
||||
style="font-size:40.00000381px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:end;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;display:inline;font-family:Sans;-inkscape-font-specification:'Sans, Normal'"
|
||||
xml:space="preserve"><tspan
|
||||
id="tspan4352"
|
||||
y="547.70569"
|
||||
x="-157.20392"
|
||||
sodipodi:role="line"
|
||||
style="font-size:32px">Button2</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:40.00000381px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:end;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;display:inline;font-family:Sans;-inkscape-font-specification:'Sans, Normal'"
|
||||
x="-157.20392"
|
||||
y="591.14594"
|
||||
id="text4354"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
x="-157.20392"
|
||||
y="591.14594"
|
||||
id="tspan4356"
|
||||
style="font-size:32px">Button14</tspan></text>
|
||||
</g>
|
||||
<g
|
||||
style="display:inline"
|
||||
transform="translate(-220.77251,-418.68304)"
|
||||
id="g4358">
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:40.00000381px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:end;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;display:inline;font-family:Sans;-inkscape-font-specification:'Sans, Normal'"
|
||||
x="-157.20392"
|
||||
y="547.70569"
|
||||
id="text4360"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
x="-157.20392"
|
||||
y="547.70569"
|
||||
id="tspan4362"
|
||||
style="font-size:32px">Button6</tspan></text>
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text4364"
|
||||
y="591.14594"
|
||||
x="-157.20392"
|
||||
style="font-size:40.00000381px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:end;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;display:inline;font-family:Sans;-inkscape-font-specification:'Sans, Normal'"
|
||||
xml:space="preserve"><tspan
|
||||
id="tspan4366"
|
||||
y="591.14594"
|
||||
x="-157.20392"
|
||||
sodipodi:role="line"
|
||||
style="font-size:32px">Button18</tspan></text>
|
||||
</g>
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 250.33375,638.82236 373.2918,377.44447"
|
||||
id="path3167"
|
||||
inkscape:connector-curvature="0"
|
||||
transform="translate(-647.36582,57.672036)" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 187.75032,550.46927 313.65347,442.97301"
|
||||
id="path3171"
|
||||
inkscape:connector-curvature="0"
|
||||
transform="translate(-647.36582,57.672036)" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 170.0797,442.23674 318.07112,378.91702"
|
||||
id="path3173"
|
||||
inkscape:connector-curvature="0"
|
||||
transform="translate(-647.36582,57.672036)" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 590.49315,144.78134 502.14006,287.61883"
|
||||
id="path3175"
|
||||
inkscape:connector-curvature="0"
|
||||
transform="translate(-647.36582,57.672036)" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 403.47911,102.07734 437.34779,309.7071"
|
||||
id="path3177"
|
||||
inkscape:connector-curvature="0"
|
||||
transform="translate(-647.36582,57.672036)" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 257.69651,135.20975 98.66095,183.33266"
|
||||
id="path3179"
|
||||
inkscape:connector-curvature="0"
|
||||
transform="translate(-647.36582,57.672036)" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 207.62976,229.45305 365.19277,333.26793"
|
||||
id="path3181"
|
||||
inkscape:connector-curvature="0"
|
||||
transform="translate(-647.36582,57.672036)" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 162.71694,318.54241 133.26591,29.45103"
|
||||
id="path3183"
|
||||
inkscape:connector-curvature="0"
|
||||
transform="translate(-647.36582,57.672036)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 29 KiB |
19
dbus/org.freedesktop.ratbag1.conf.in
Normal file
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0"?> <!--*-nxml-*-->
|
||||
<!DOCTYPE busconfig PUBLIC
|
||||
"-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
|
||||
"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
|
||||
|
||||
<busconfig>
|
||||
|
||||
<policy user="root">
|
||||
<allow own="org.freedesktop.ratbag1"/>
|
||||
<allow send_destination="org.freedesktop.ratbag1"/>
|
||||
<allow receive_sender="org.freedesktop.ratbag1"/>
|
||||
</policy>
|
||||
|
||||
<policy @access@>
|
||||
<allow send_destination="org.freedesktop.ratbag1"/>
|
||||
<allow receive_sender="org.freedesktop.ratbag1"/>
|
||||
</policy>
|
||||
|
||||
</busconfig>
|
||||
5
dbus/org.freedesktop.ratbag1.service.in
Normal file
@@ -0,0 +1,5 @@
|
||||
[D-BUS Service]
|
||||
Name=org.freedesktop.ratbag1
|
||||
Exec=@bindir@/ratbagd
|
||||
User=root
|
||||
SystemdService=ratbagd.service
|
||||
26
dbus/org.freedesktop.ratbag_devel1.conf.in
Normal file
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0"?> <!--*-nxml-*-->
|
||||
<!DOCTYPE busconfig PUBLIC
|
||||
"-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
|
||||
"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
|
||||
|
||||
<!--
|
||||
WARNING: this file is for testing of libratbag during development.
|
||||
If you don't know why this file is in your dbus configuration
|
||||
folder, remove it.
|
||||
-->
|
||||
|
||||
<busconfig>
|
||||
|
||||
<policy user="root">
|
||||
<allow own="org.freedesktop.ratbag_devel1_@ratbagd_sha@"/>
|
||||
<allow send_destination="org.freedesktop.ratbag_devel1_@ratbagd_sha@"/>
|
||||
<allow receive_sender="org.freedesktop.ratbag_devel1_@ratbagd_sha@"/>
|
||||
</policy>
|
||||
|
||||
<!-- allow everyone to talk to the daemon -->
|
||||
<policy context="default">
|
||||
<allow send_destination="org.freedesktop.ratbag_devel1_@ratbagd_sha@"/>
|
||||
<allow receive_sender="org.freedesktop.ratbag_devel1_@ratbagd_sha@"/>
|
||||
</policy>
|
||||
|
||||
</busconfig>
|
||||
@@ -1,38 +0,0 @@
|
||||
if BUILD_DOCS
|
||||
|
||||
noinst_DATA = html/index.html
|
||||
|
||||
header_files = \
|
||||
$(top_srcdir)/src/libratbag.h \
|
||||
$(top_srcdir)/README.md
|
||||
|
||||
style_files = \
|
||||
style/header.html \
|
||||
style/footer.html \
|
||||
style/customdoxygen.css \
|
||||
style/bootstrap.css
|
||||
|
||||
html/index.html: libratbag.doxygen $(header_files) $(diagram_files) $(style_files)
|
||||
$(AM_V_GEN)(cat $<; \
|
||||
echo "INPUT = $(header_files)"; \
|
||||
) | $(DOXYGEN) -
|
||||
|
||||
clean-local:
|
||||
$(AM_V_at)rm -rf html
|
||||
|
||||
doc_src= $(shell find html -type f -printf "html/%P\n" 2>/dev/null)
|
||||
EXTRA_DIST = $(builddir)/html/index.html \
|
||||
$(doc_src) \
|
||||
$(diagram_files) \
|
||||
$(header_files) \
|
||||
$(style_files)
|
||||
endif
|
||||
|
||||
# make sure doc was built before running dist
|
||||
dist-hook:
|
||||
@test -f $(distdir)/html/index.html || (\
|
||||
echo "******************************************************" && \
|
||||
echo "Couldn't find documentation files, refusing make dist." && \
|
||||
echo "Install doxygen to build documentation for tarball." && \
|
||||
echo "******************************************************" && \
|
||||
test )
|
||||
157
doc/conf.py.in
Normal file
@@ -0,0 +1,157 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# @PACKAGE_NAME@ documentation build configuration file, created by
|
||||
# sphinx-quickstart on Wed Oct 11 13:45:08 2017.
|
||||
#
|
||||
# This file is execfile()d with the current directory set to its
|
||||
# containing dir.
|
||||
#
|
||||
# Note that not all possible configuration values are present in this
|
||||
# autogenerated file.
|
||||
#
|
||||
# All configuration values have a default; values that are commented out
|
||||
# serve to show the default.
|
||||
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
|
||||
import os
|
||||
import sys
|
||||
sys.path.insert(0, os.path.abspath('..'))
|
||||
|
||||
# -- General configuration ------------------------------------------------
|
||||
|
||||
# If your documentation needs a minimal Sphinx version, state it here.
|
||||
#
|
||||
# needs_sphinx = '1.0'
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||
# ones.
|
||||
extensions = []
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['_templates']
|
||||
|
||||
# The suffix(es) of source filenames.
|
||||
# You can specify multiple suffix as a list of string:
|
||||
#
|
||||
# source_suffix = ['.rst', '.md']
|
||||
source_suffix = '.rst'
|
||||
|
||||
# The master toctree document.
|
||||
master_doc = 'index'
|
||||
|
||||
# General information about the project.
|
||||
project = '@PACKAGE_NAME@'
|
||||
copyright = '2017, The ratbaggers'
|
||||
author = 'The ratbaggers'
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = ''
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = ''
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
#
|
||||
# This is also used if you do content translation via gettext catalogs.
|
||||
# Usually you set "language" from the command line for these cases.
|
||||
language = None
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
# This patterns also effect to html_static_path and html_extra_path
|
||||
exclude_patterns = []
|
||||
|
||||
# The name of the Pygments (syntax highlighting) style to use.
|
||||
pygments_style = 'sphinx'
|
||||
|
||||
# If true, `todo` and `todoList` produce output, else they produce nothing.
|
||||
todo_include_todos = False
|
||||
|
||||
|
||||
# -- Options for HTML output ----------------------------------------------
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
#
|
||||
# html_theme = 'alabaster'
|
||||
html_theme = 'sphinx_rtd_theme'
|
||||
|
||||
# Theme options are theme-specific and customize the look and feel of a theme
|
||||
# further. For a list of options available for each theme, see the
|
||||
# documentation.
|
||||
#
|
||||
# html_theme_options = {}
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
html_static_path = ['_static']
|
||||
|
||||
|
||||
# -- Options for HTMLHelp output ------------------------------------------
|
||||
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = '@PACKAGE_NAME@doc'
|
||||
|
||||
|
||||
# -- Options for LaTeX output ---------------------------------------------
|
||||
|
||||
latex_elements = {
|
||||
# The paper size ('letterpaper' or 'a4paper').
|
||||
#
|
||||
# 'papersize': 'letterpaper',
|
||||
|
||||
# The font size ('10pt', '11pt' or '12pt').
|
||||
#
|
||||
# 'pointsize': '10pt',
|
||||
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
#
|
||||
# 'preamble': '',
|
||||
|
||||
# Latex figure (float) alignment
|
||||
#
|
||||
# 'figure_align': 'htbp',
|
||||
}
|
||||
|
||||
# Grouping the document tree into LaTeX files. List of tuples
|
||||
# (source start file, target name, title,
|
||||
# author, documentclass [howto, manual, or own class]).
|
||||
latex_documents = [
|
||||
(master_doc, '@PACKAGE_NAME@.tex', '@PACKAGE_NAME@ Documentation',
|
||||
'The ratbaggers', 'manual'),
|
||||
]
|
||||
|
||||
|
||||
# -- Options for manual page output ---------------------------------------
|
||||
|
||||
# One entry per manual page. List of tuples
|
||||
# (source start file, name, description, authors, manual section).
|
||||
man_pages = [
|
||||
(master_doc, '@PACKAGE_NAME@', '@PACKAGE_NAME@ Documentation',
|
||||
[author], 1)
|
||||
]
|
||||
|
||||
|
||||
# -- Options for Texinfo output -------------------------------------------
|
||||
|
||||
# Grouping the document tree into Texinfo files. List of tuples
|
||||
# (source start file, target name, title, author,
|
||||
# dir menu entry, description, category)
|
||||
texinfo_documents = [
|
||||
(master_doc, '@PACKAGE_NAME@', '@PACKAGE_NAME@ Documentation',
|
||||
author, '@PACKAGE_NAME@', 'One line description of project.',
|
||||
'Miscellaneous'),
|
||||
]
|
||||
|
||||
|
||||
|
||||
557
doc/dbus.rst
Normal file
@@ -0,0 +1,557 @@
|
||||
********
|
||||
DBus API
|
||||
********
|
||||
|
||||
Note: **the DBus interface is subject to change**
|
||||
|
||||
Interfaces:
|
||||
|
||||
* :ref:`manager`
|
||||
* :ref:`device`
|
||||
* :ref:`profile`
|
||||
* :ref:`resolution`
|
||||
* :ref:`button`
|
||||
* :ref:`led`
|
||||
|
||||
Changing settings on a device is a three-step process:
|
||||
|
||||
#. Change the various properties to the desired value
|
||||
#. Invoke :func:`org.freedesktop.ratbag1.Device.Commit() <Commit>`
|
||||
#. Optional: if an error occured writing the new data to the device,
|
||||
a :func:`org.freedesktop.ratbag1.Resync <Resync>` signal is emitted on the device and
|
||||
all properties are updated accordingly.
|
||||
|
||||
The time it takes to write settings to a device varies greatly, any caller
|
||||
must be prepared to receive a :func:`org.freedesktop.ratbag1.Device.Resync
|
||||
<Resync>` signal several seconds after
|
||||
:func:`org.freedesktop.ratbag1.Device.Commit() <Commit>`.
|
||||
|
||||
Notes on the DBus API
|
||||
---------------------
|
||||
|
||||
For easier debugging, objects paths are constructed from the device. e.g.
|
||||
``/org/freedesktop/ratbag/button/event5/p0/b10`` is the button interface for
|
||||
button 10 on profile 0 on event5. The naming is subject to change. Do not
|
||||
rely on a constructed object path in your application.
|
||||
|
||||
Types
|
||||
.....
|
||||
|
||||
Types used by these interfaces:
|
||||
|
||||
+----------+-----------------------------------+
|
||||
| Type | Description |
|
||||
+==========+===================================+
|
||||
| ``b`` | Bool |
|
||||
+----------+-----------------------------------+
|
||||
| ``o`` | Object path |
|
||||
+----------+-----------------------------------+
|
||||
| ``s`` | String |
|
||||
+----------+-----------------------------------+
|
||||
| ``u`` | Unsigned 32-bit integer |
|
||||
+----------+-----------------------------------+
|
||||
|``(uuu)`` | A triplet of 32-bit integers |
|
||||
+----------+-----------------------------------+
|
||||
| ``ao`` | Array of object paths |
|
||||
+----------+-----------------------------------+
|
||||
| ``as`` | Array of strings |
|
||||
+----------+-----------------------------------+
|
||||
| ``au`` | Array of 32-bit integers |
|
||||
+----------+-----------------------------------+
|
||||
| ``a(uu)``| Array of 2 32-bit integer tuples |
|
||||
+----------+-----------------------------------+
|
||||
|
||||
For details on each type, see the `DBus Specification
|
||||
<https://dbus.freedesktop.org/doc/dbus-specification.html>`_.
|
||||
|
||||
Flags
|
||||
.....
|
||||
|
||||
Properties marked as **constant** do not change for the lifetime of the
|
||||
object. Properties marked as **mutable** may change, and a
|
||||
``org.freedesktop.DBus.Properties.PropertyChanged`` signal is sent for those
|
||||
unless otherwise specified.
|
||||
|
||||
.. _manager:
|
||||
|
||||
org.freedesktop.ratbag1.Manager
|
||||
-------------------------------
|
||||
|
||||
The **org.freedesktop.ratbag1.Manager** interface is the entry point to
|
||||
interact with ratbagd.
|
||||
|
||||
.. attribute:: Devices
|
||||
|
||||
:type: ao
|
||||
:flags: read-only, mutable
|
||||
|
||||
An array of read-only object paths referencing the available
|
||||
devices. The devices implement the :ref:`device` interface.
|
||||
|
||||
.. _device:
|
||||
|
||||
org.freedesktop.ratbag1.Device
|
||||
-------------------------------
|
||||
|
||||
The **org.freedesktop.ratbag1.Device** interface describes a single device
|
||||
known to ratbagd.
|
||||
|
||||
.. attribute:: Model
|
||||
|
||||
:type: s
|
||||
:flags: read-only, constant
|
||||
|
||||
An ID identifying the physical device model. This string is
|
||||
guaranteed to be unique for a specific model and always identical
|
||||
for devices of that model.
|
||||
|
||||
This is a string of one of the following formats:
|
||||
|
||||
- ``usb:1234:abcd:0``
|
||||
- ``bluetooth:5678:ef01:0``
|
||||
- ``unknown``
|
||||
|
||||
In the future, other formats may get added. Clients must ignore
|
||||
unknown string formats.
|
||||
|
||||
For a string starting with ``usb:``, the format is the bus type (USB)
|
||||
followed by a 4-digit lowercase hex USB vendor ID, followed by a
|
||||
4-digit lowercase hex USB product ID, followed by an decimal version
|
||||
number of unspecified length. These four elements are separated by a
|
||||
colon (``:``).
|
||||
|
||||
For a string starting with ``bluetooth:``, the format is the bus type
|
||||
(Bluetooth) followed by a 4-digit lowercase hex Bluetooth vendor ID,
|
||||
followed by a 4-digit lowercase hex Bluetooth product ID, followed
|
||||
by an decimal version number of unspecified length. These four
|
||||
elements are separated by a colon (``:``).
|
||||
|
||||
For the string ``unknown``, the model of the device cannot be
|
||||
determined. This is usually a bug in libratbag.
|
||||
|
||||
For a ``Model`` of type ``usb`` and ``bluetooth``, the version
|
||||
number is reserved for use by libratbag. Device with identical
|
||||
vendor and product IDs but different versions must be considered
|
||||
different devices. For example, the version may increase when a
|
||||
manufacturer re-uses USB Ids.
|
||||
|
||||
Vendor or product IDs of 0 are valid IDs (e.g. used used by test
|
||||
devices).
|
||||
|
||||
.. attribute:: Name
|
||||
|
||||
:type: s
|
||||
:flags: read-only, constant
|
||||
|
||||
The device's name, suitable for presentation to the user.
|
||||
|
||||
.. attribute:: Profiles
|
||||
|
||||
:type: ao
|
||||
:flags: read-only, mutable
|
||||
|
||||
This property is mutable if the device supports adding and removing
|
||||
profiles.
|
||||
|
||||
Provides the list of profile paths for all profiles on this device, see
|
||||
:ref:`profile`
|
||||
|
||||
.. function:: Commit() → ()
|
||||
|
||||
Commits the changes to the device. This call always succeeds,
|
||||
the data is written to the device asynchronously. Where an error
|
||||
occurs, the :func:`Resync` signal is emitted and all properties are
|
||||
updated to the current state.
|
||||
|
||||
.. function:: Resync()
|
||||
|
||||
:type: Signal
|
||||
|
||||
Emitted when an internal error occurs, usually on writing values to
|
||||
the device after :func:`Commit()`. Upon receiving this
|
||||
signal, clients are expected to resync their property values with
|
||||
ratbagd.
|
||||
|
||||
|
||||
.. _profile:
|
||||
|
||||
org.freedesktop.ratbag1.Profile
|
||||
-------------------------------
|
||||
|
||||
.. attribute:: Index
|
||||
|
||||
:type: u
|
||||
:flags: read-only, constant
|
||||
|
||||
The zero-based index of this profile
|
||||
|
||||
.. attribute:: Name
|
||||
|
||||
:type: s
|
||||
:flags: read-write, mutable
|
||||
|
||||
The name of this profile. If the name is the empty string, the
|
||||
profile name cannot be changed.
|
||||
|
||||
.. attribute:: Enabled
|
||||
|
||||
:type: b
|
||||
:flags: read-write, mutable
|
||||
|
||||
True if this is the profile is enabled, false otherwise.
|
||||
|
||||
Note that a disabled profile might not have correct bindings, so it's
|
||||
a good thing to rebind everything before calling
|
||||
:func:`Commit`.
|
||||
|
||||
.. attribute:: IsActive
|
||||
|
||||
:type: b
|
||||
:flags: read-only, mutable
|
||||
|
||||
True if this is the currently active profile, false otherwise.
|
||||
|
||||
Profiles can only be set to active, but never to not active - at least one
|
||||
profile must be active at all times. This property is read-only, use the
|
||||
:func:`SetActive` method to activate a profile.
|
||||
|
||||
.. attribute:: Resolutions
|
||||
|
||||
:type: ao
|
||||
:flags: read-only, mutable
|
||||
|
||||
This property is mutable if the device supports adding and removing
|
||||
resolutions.
|
||||
|
||||
Provides the object paths of all resolutions in this profile, see
|
||||
:ref:`resolution`.
|
||||
|
||||
.. attribute:: Buttons
|
||||
|
||||
:type: ao
|
||||
:flags: read-only, constant
|
||||
|
||||
Provides the object paths of all buttons in this profile, see
|
||||
:ref:`button`.
|
||||
|
||||
.. attribute:: Leds
|
||||
|
||||
:type: ao
|
||||
:flags: read-only, constant
|
||||
|
||||
Provides the object paths of all LEDs in this profile, see
|
||||
:ref:`led`.
|
||||
|
||||
.. attribute:: ReportRate
|
||||
|
||||
:type: u
|
||||
:flags: read-write, mutable
|
||||
|
||||
uint for the report rate in Hz assigned to this profile. This rate
|
||||
must be one of those listed in :attr:`ReportRates`.
|
||||
|
||||
.. attribute:: ReportRates
|
||||
|
||||
:type: au
|
||||
:flags: read-write, constant
|
||||
|
||||
A list of permitted report rates. Values in this list may be used
|
||||
in the :attr:`ReportRate` property. This list is always sorted
|
||||
ascending, the lowest report rate is the first item in the list.
|
||||
|
||||
This list may be empty if the device does not support reading and/or
|
||||
writing to resolutions.
|
||||
|
||||
.. function:: SetActive() → ()
|
||||
|
||||
Set this profile to be the active profile
|
||||
|
||||
.. _resolution:
|
||||
|
||||
org.freedesktop.ratbag1.Resolution
|
||||
----------------------------------
|
||||
|
||||
.. attribute:: Index
|
||||
|
||||
:type: u
|
||||
:flags: read-only, constant
|
||||
|
||||
Index of the resolution
|
||||
|
||||
.. attribute:: IsActive
|
||||
|
||||
:type: b
|
||||
:flags: read-only, mutable
|
||||
|
||||
True if this is the currently active resolution, false otherwise.
|
||||
|
||||
Resolutions can only be set to active, but never to not
|
||||
active - at least one resoultion must be active at all
|
||||
times. This property is read-only, use the
|
||||
:func:`SetActive` method to set a resolution as the
|
||||
active resolution.
|
||||
|
||||
.. attribute:: IsDefault
|
||||
|
||||
:type: b
|
||||
:flags: read-only, mutable
|
||||
|
||||
True if this is the currently default resolution, false
|
||||
otherwise. If the device does not have the default
|
||||
resolution capability, this property is always false.
|
||||
|
||||
Resolutions can only be set to default, but never to not
|
||||
default - at least one resolution must be default at all
|
||||
times. This property is read-only, use the
|
||||
:func:`SetDefault` method to set a resolution as
|
||||
the default resolution.
|
||||
|
||||
.. attribute:: Resolution
|
||||
|
||||
:type: v
|
||||
:flags: read-write, mutable
|
||||
|
||||
The resolution for this entry in dpi.
|
||||
|
||||
If the variant is a single unsigned integer (``u``), the value is
|
||||
the resolution for both the x- and the y- axis.
|
||||
|
||||
If the variant is a unsigned integer tuple (``(uu)``), the value is
|
||||
the resolution for the x- and y- axis separately.
|
||||
|
||||
A client must leave the type intact, assigning a single ``u`` to a
|
||||
resolution object previously exporting ``(uu)`` is invalid.
|
||||
|
||||
The value for the resolution must be equal to one of the values in
|
||||
:attr:`Resolutions`.
|
||||
|
||||
.. attribute:: Resolutions
|
||||
|
||||
:type: au
|
||||
:flags: read-only, constant
|
||||
|
||||
A list of permitted resolutions. Values in this list may be used in
|
||||
the :attr:`Resolution` property. This list is always sorted
|
||||
ascending, the lowest resolution is the first item in the list.
|
||||
|
||||
This list may be empty if the device does not support reading and/or
|
||||
writing to resolutions.
|
||||
|
||||
.. function:: SetDefault() → ()
|
||||
|
||||
Set this resolution to be the default
|
||||
|
||||
.. function:: SetActive() → ()
|
||||
|
||||
Set this resolution to be the active one
|
||||
|
||||
.. _button:
|
||||
|
||||
org.freedesktop.ratbag1.Button
|
||||
------------------------------
|
||||
|
||||
.. attribute:: Index
|
||||
|
||||
:type: u
|
||||
:flags: read-only, constant
|
||||
|
||||
Index of the button
|
||||
|
||||
.. attribute:: Mapping
|
||||
|
||||
:type: (uv)
|
||||
:flags: read-write, mutable
|
||||
|
||||
The current button mapping. The first element is the ``ActionType``
|
||||
for this button and must be one of those in :attr:`ActionTypes`.
|
||||
|
||||
If the ActionType is *Button*, the variant is an unsigned integer
|
||||
(``u``) denoting the button number to map to.
|
||||
|
||||
If the ActionType is *Special*, the variant is an unsigned integer
|
||||
(``u``) denoting the special value to map to.
|
||||
|
||||
If the ActionType is *Macro*, the variant is an array of integer
|
||||
tuples (``a(uu)``) where each tuple is ``(type, keycode)`` and the
|
||||
type is one of the following:
|
||||
|
||||
+---------+--------------------------------------+
|
||||
| Value | Description |
|
||||
+=========+======================================+
|
||||
| 0 | Key release event |
|
||||
+---------+--------------------------------------+
|
||||
| 1 | Key press event |
|
||||
+---------+--------------------------------------+
|
||||
|
||||
If the ActionType is *Unknown*, the variant is an unsigned integer
|
||||
(``u``) of value 0.
|
||||
|
||||
.. attribute:: ActionTypes
|
||||
|
||||
:type: au
|
||||
:flags: read-only, constant
|
||||
|
||||
+---------+---------+--------------------------------------+
|
||||
| Value | Name | Description |
|
||||
+=========+=========+======================================+
|
||||
| 0 | None | No mapping configured |
|
||||
+---------+---------+--------------------------------------+
|
||||
| 1 | Button | Mapping to a logical button number |
|
||||
+---------+---------+--------------------------------------+
|
||||
| 2 | Special | Mapping to a special function |
|
||||
+---------+---------+--------------------------------------+
|
||||
| 3 | Macro | Mapping to a macro key sequence |
|
||||
+---------+---------+--------------------------------------+
|
||||
| 1000 | Unknown | An unknown or unreadable mapping type|
|
||||
+---------+---------+--------------------------------------+
|
||||
|
||||
See :ref:`button_special` for a list of supported special
|
||||
functions.
|
||||
|
||||
Clients must ignore :attr:`ActionTypes` unknown to them.
|
||||
|
||||
.. function:: Disable() → ()
|
||||
|
||||
Disable this button
|
||||
|
||||
.. _led:
|
||||
|
||||
org.freedesktop.ratbag1.Led
|
||||
---------------------------
|
||||
|
||||
.. attribute:: Index
|
||||
|
||||
:type: u
|
||||
:flags: read-only, constant
|
||||
|
||||
Index of the LED
|
||||
|
||||
.. attribute:: Mode
|
||||
|
||||
:type: u
|
||||
:flags: read-write, mutable
|
||||
|
||||
Enum describing the current mode, see :attr:`Modes`.
|
||||
|
||||
.. attribute:: Modes
|
||||
|
||||
:type: au
|
||||
:flags: read-only, constant
|
||||
|
||||
A list of modes supported by this LED.
|
||||
|
||||
+-------+-------------------------------------+
|
||||
| Value | Definition |
|
||||
+=======+=====================================+
|
||||
| 0 | LED is off |
|
||||
+-------+-------------------------------------+
|
||||
| 1 | LED is on with constant brightness |
|
||||
+-------+-------------------------------------+
|
||||
| 2 | LED cycles through a set of colors. |
|
||||
| | This mode ignores the :attr:`Color` |
|
||||
| | values. |
|
||||
+-------+-------------------------------------+
|
||||
| 3 | LED uses a breathing-style animation|
|
||||
+-------+-------------------------------------+
|
||||
|
||||
In the future, extra values may get added. Clients must ignore
|
||||
unknown Modes.
|
||||
|
||||
.. attribute:: Color
|
||||
|
||||
:type: (uuu)
|
||||
:flags: read-write, mutable
|
||||
|
||||
32-bit unsigned int triplet (RGB) of the LED's color. Only the least
|
||||
significant bits are valid, the :attr:`ColorDepth` property defines
|
||||
the number of bits for each color. When writing to this property,
|
||||
all bits outside the color depth must be 0.
|
||||
|
||||
.. attribute:: ColorDepth
|
||||
|
||||
:type: u
|
||||
:flags: read-only, constant
|
||||
|
||||
An enum specifying the color depth of this LED. Permitted values are:
|
||||
|
||||
+-------+-------------------------------+
|
||||
| Value | Definition |
|
||||
+=======+===============================+
|
||||
| 0 | 0 bits per color (monochrome) |
|
||||
+-------+-------------------------------+
|
||||
| 1 | 8 bits per color |
|
||||
+-------+-------------------------------+
|
||||
| 2 | 1 bit per color |
|
||||
+-------+-------------------------------+
|
||||
|
||||
In the future, extra values may get added. Clients must ignore
|
||||
unknown ``ColorDepths`` and not manipulate the LED color where
|
||||
the ``ColorDepth`` is unknown.
|
||||
|
||||
.. attribute:: EffectDuration
|
||||
|
||||
:type: u
|
||||
:flags: read-write, mutable
|
||||
|
||||
The effect duration in ms, possible values are in the range 0 - 10000
|
||||
|
||||
.. attribute:: Brightness
|
||||
|
||||
:type: u
|
||||
:flags: read-write, mutable
|
||||
|
||||
The brightness of the LED, normalized to the range 0-255, inclusive.
|
||||
Where the LED supports less than 8-bit of brightness, libratbag maps
|
||||
the value to a device-supported value in an implementation-defined
|
||||
manner.
|
||||
|
||||
|
||||
.. _button_special:
|
||||
|
||||
Special button functions
|
||||
------------------------
|
||||
|
||||
All special button function values are based on the value
|
||||
``0x40000000`` (``1 << 30``).
|
||||
|
||||
+------------+------------+---------------------------------------------------+
|
||||
| Offset | Value |Description |
|
||||
+============+============+===================================================+
|
||||
| 0 | 0x40000000 | Unknown |
|
||||
+------------+------------+---------------------------------------------------+
|
||||
| 1 | 0x40000001 | Doublelick |
|
||||
+------------+------------+---------------------------------------------------+
|
||||
| 2 | 0x40000002 | Wheel left |
|
||||
+------------+------------+---------------------------------------------------+
|
||||
| 3 | 0x40000003 | Wheel right |
|
||||
+------------+------------+---------------------------------------------------+
|
||||
| 4 | 0x40000004 | Wheel up |
|
||||
+------------+------------+---------------------------------------------------+
|
||||
| 5 | 0x40000005 | Wheel down |
|
||||
+------------+------------+---------------------------------------------------+
|
||||
| 6 | 0x40000006 | Ratchet mode switch |
|
||||
+------------+------------+---------------------------------------------------+
|
||||
| 7 | 0x40000007 | Resolution cycle up |
|
||||
+------------+------------+---------------------------------------------------+
|
||||
| 8 | 0x40000008 | Resolution cycle down |
|
||||
+------------+------------+---------------------------------------------------+
|
||||
| 9 | 0x40000009 | Resolution up |
|
||||
+------------+------------+---------------------------------------------------+
|
||||
| 10 | 0x4000000a | Resolution down |
|
||||
+------------+------------+---------------------------------------------------+
|
||||
| 11 | 0x4000000b | Resolution alternate |
|
||||
+------------+------------+---------------------------------------------------+
|
||||
| 12 | 0x4000000c | Resolution default |
|
||||
+------------+------------+---------------------------------------------------+
|
||||
| 13 | 0x4000000d | Profile cycle up |
|
||||
+------------+------------+---------------------------------------------------+
|
||||
| 14 | 0x4000000e | Profile cycle down |
|
||||
+------------+------------+---------------------------------------------------+
|
||||
| 15 | 0x4000000f | Profile up |
|
||||
+------------+------------+---------------------------------------------------+
|
||||
| 16 | 0x40000010 | Profile down |
|
||||
+------------+------------+---------------------------------------------------+
|
||||
| 17 | 0x40000011 | Second mode |
|
||||
+------------+------------+---------------------------------------------------+
|
||||
| 18 | 0x40000012 | Battery level |
|
||||
+------------+------------+---------------------------------------------------+
|
||||
53
doc/doxygen-enums-to-rst.xsl
Normal file
@@ -0,0 +1,53 @@
|
||||
<!-- XSLT script to combine the generated output into a single file.
|
||||
If you have xsltproc you could use:
|
||||
xsltproc combine.xslt index.xml >all.xml
|
||||
-->
|
||||
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
|
||||
<xsl:output method="text" indent="yes"/>
|
||||
<xsl:strip-space elements="detaileddescription briefdescription"/>
|
||||
|
||||
<xsl:template match="/">
|
||||
<xsl:text>
|
||||
************
|
||||
Enumerations
|
||||
************
|
||||
|
||||
This document contains the enums used by libratbag's DBus interface.
|
||||
|
||||
</xsl:text>
|
||||
<xsl:apply-templates select="//memberdef"/>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="memberdef">
|
||||
|
||||
<xsl:value-of select="name"/>
|
||||
---------------------------------------
|
||||
|
||||
<xsl:text>
</xsl:text>
|
||||
<xsl:if test="briefdescription != ''">
|
||||
<xsl:value-of select="briefdescription"/>
|
||||
</xsl:if>
|
||||
<xsl:if test="detaileddescription != ''">
|
||||
<xsl:value-of select="detaileddescription"/>
|
||||
</xsl:if>
|
||||
|
||||
.. cpp:enum:: <xsl:value-of select="name"/>
|
||||
|
||||
<xsl:text>

</xsl:text>
|
||||
<xsl:apply-templates select="./enumvalue"/>
|
||||
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="enumvalue">
|
||||
.. cpp:enumerator:: <xsl:value-of select="name"/><xsl:text> </xsl:text><xsl:value-of select="initializer"/>
|
||||
<xsl:text>

</xsl:text>
|
||||
<xsl:if test="briefdescription != ''">
|
||||
<xsl:text> </xsl:text><xsl:value-of select="briefdescription"/>
|
||||
</xsl:if>
|
||||
<xsl:if test="detaileddescription != ''">
|
||||
<xsl:text> </xsl:text><xsl:value-of select="detaileddescription"/>
|
||||
</xsl:if>
|
||||
<xsl:text>

</xsl:text>
|
||||
</xsl:template>
|
||||
</xsl:stylesheet>
|
||||
|
||||
22
doc/index.rst
Normal file
@@ -0,0 +1,22 @@
|
||||
.. libratbag documentation master file, created by
|
||||
sphinx-quickstart on Wed Oct 11 13:45:08 2017.
|
||||
You can adapt this file completely to your liking, but it should at least
|
||||
contain the root `toctree` directive.
|
||||
|
||||
**********************
|
||||
The libratbag DBus API
|
||||
**********************
|
||||
|
||||
.. image:: ../../data/logo.svg
|
||||
:width: 400
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:caption: Contents:
|
||||
|
||||
The DBus Interfaces <dbus.rst>
|
||||
|
||||
This document describes the DBus API that is the public interface for
|
||||
libratbag.
|
||||
|
||||
Note: **the DBus interface is subject to change**
|
||||
@@ -8,19 +8,8 @@ EXTRACT_ALL = YES
|
||||
EXTRACT_STATIC = YES
|
||||
MAX_INITIALIZER_LINES = 0
|
||||
QUIET = YES
|
||||
INPUT = @top_srcdir@/src/libratbag.h \
|
||||
@top_srcdir@/README.txt
|
||||
GENERATE_HTML = YES
|
||||
HTML_TIMESTAMP = YES
|
||||
USE_MATHJAX = YES
|
||||
# Keep this list in sync with meson.build
|
||||
INPUT = @top_srcdir@/src/libratbag-enums.h
|
||||
GENERATE_HTML = NO
|
||||
GENERATE_XML = YES
|
||||
GENERATE_LATEX = NO
|
||||
MACRO_EXPANSION = YES
|
||||
EXPAND_ONLY_PREDEF = YES
|
||||
PREDEFINED = LIBRATBAG_ATTRIBUTE_PRINTF(f, \
|
||||
a)= \
|
||||
LIBRATBAG_ATTRIBUTE_DEPRECATED
|
||||
|
||||
HTML_HEADER = @top_srcdir@/doc/style/header.html
|
||||
HTML_FOOTER = @top_srcdir@/doc/style/footer.html
|
||||
HTML_EXTRA_STYLESHEET = @top_srcdir@/doc/style/customdoxygen.css \
|
||||
@top_srcdir@/doc/style/bootstrap.css
|
||||
|
||||
42
doc/meson.build
Normal file
@@ -0,0 +1,42 @@
|
||||
if get_option('documentation')
|
||||
|
||||
cmd_sphinx = find_program('sphinx-build-3', 'sphinx-build3')
|
||||
|
||||
doc_config = configuration_data()
|
||||
doc_config.set('PACKAGE_NAME', meson.project_name())
|
||||
doc_config.set('PACKAGE_VERSION', meson.project_version())
|
||||
doc_config.set('top_srcdir', meson.source_root())
|
||||
|
||||
# Sphinx really really wants a _static directory in its source tree. Let's
|
||||
# make it happy
|
||||
run_command('mkdir', '-p', join_paths(meson.build_root(), 'doc', '_static'))
|
||||
|
||||
# Effectively a noop copy. We *must* generate enums.rst so that will end up
|
||||
# in the build directory. sphinx doesn't allow for multiple source
|
||||
# directories, so any .rst and the conf.py must be copied over to the
|
||||
# build directory too
|
||||
src_rsts = ['index.rst', 'dbus.rst']
|
||||
dst_rsts = []
|
||||
foreach rst : src_rsts
|
||||
f = configure_file(input : rst,
|
||||
output : rst,
|
||||
configuration : doc_config,
|
||||
install : false)
|
||||
dst_rsts += f
|
||||
endforeach
|
||||
|
||||
sphinx_conf = configure_file(input : 'conf.py.in',
|
||||
output : 'conf.py',
|
||||
configuration : doc_config,
|
||||
install : false)
|
||||
|
||||
custom_target('sphinx',
|
||||
input : [ sphinx_conf, dst_rsts ],
|
||||
output : 'html',
|
||||
command : [ cmd_sphinx, '-b', 'html', '-q', '-n',
|
||||
join_paths(meson.build_root(), 'doc'),
|
||||
join_paths(meson.build_root(), 'doc', 'html') ],
|
||||
build_by_default : true,
|
||||
install : false)
|
||||
|
||||
endif
|
||||
@@ -1,229 +0,0 @@
|
||||
These licenses apply to the doxygen documentation HTML style only. They do
|
||||
not apply or affect libratbag itself.
|
||||
|
||||
Apache: https://github.com/Velron/doxygen-bootstrapped/
|
||||
MIT: https://bootswatch.com/paper/bootstrap.css
|
||||
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright {yyyy} {name of copyright owner}
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2011-2015 Twitter, Inc
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to
|
||||
deal in the Software without restriction, including without limitation the
|
||||
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
sell copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice 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.
|
||||
7500
doc/style/bootstrap.css
vendored
@@ -1,255 +0,0 @@
|
||||
h1, .h1, h2, .h2, h3, .h3{
|
||||
font-weight: 200 !important;
|
||||
}
|
||||
|
||||
#navrow1, #navrow2, #navrow3, #navrow4, #navrow5{
|
||||
border-bottom: 1px solid #EEEEEE;
|
||||
}
|
||||
|
||||
.adjust-right {
|
||||
margin-left: 30px !important;
|
||||
font-size: 1.15em !important;
|
||||
}
|
||||
.navbar{
|
||||
border: 0px solid #222 !important;
|
||||
}
|
||||
|
||||
|
||||
/* Sticky footer styles
|
||||
-------------------------------------------------- */
|
||||
html,
|
||||
body {
|
||||
height: 100%;
|
||||
/* The html and body elements cannot have any padding or margin. */
|
||||
}
|
||||
|
||||
/* Wrapper for page content to push down footer */
|
||||
#wrap {
|
||||
min-height: 100%;
|
||||
height: auto;
|
||||
/* Negative indent footer by its height */
|
||||
margin: 0 auto -60px;
|
||||
/* Pad bottom by footer height */
|
||||
padding: 0 0 60px;
|
||||
}
|
||||
|
||||
/* Set the fixed height of the footer here */
|
||||
#footer {
|
||||
font-size: 0.9em;
|
||||
padding: 8px 0px;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
.footer-row {
|
||||
line-height: 44px;
|
||||
}
|
||||
|
||||
#footer > .container {
|
||||
padding-left: 15px;
|
||||
padding-right: 15px;
|
||||
}
|
||||
|
||||
.footer-follow-icon {
|
||||
margin-left: 3px;
|
||||
text-decoration: none !important;
|
||||
}
|
||||
|
||||
.footer-follow-icon img {
|
||||
width: 20px;
|
||||
}
|
||||
|
||||
.footer-link {
|
||||
padding-top: 5px;
|
||||
display: inline-block;
|
||||
color: #999999;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.footer-copyright {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
||||
@media (min-width: 992px) {
|
||||
.footer-row {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.footer-icons {
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
@media (max-width: 991px) {
|
||||
.footer-row {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.footer-icons {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
/* DOXYGEN Code Styles
|
||||
----------------------------------- */
|
||||
|
||||
|
||||
a.qindex {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
a.qindexHL {
|
||||
font-weight: bold;
|
||||
background-color: #9CAFD4;
|
||||
color: #ffffff;
|
||||
border: 1px double #869DCA;
|
||||
}
|
||||
|
||||
.contents a.qindexHL:visited {
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
a.code, a.code:visited, a.line, a.line:visited {
|
||||
color: #4665A2;
|
||||
}
|
||||
|
||||
a.codeRef, a.codeRef:visited, a.lineRef, a.lineRef:visited {
|
||||
color: #4665A2;
|
||||
}
|
||||
|
||||
/* @end */
|
||||
|
||||
dl.el {
|
||||
margin-left: -1cm;
|
||||
}
|
||||
|
||||
pre.fragment {
|
||||
border: 1px solid #C4CFE5;
|
||||
background-color: #FBFCFD;
|
||||
padding: 4px 6px;
|
||||
margin: 4px 8px 4px 2px;
|
||||
overflow: auto;
|
||||
word-wrap: break-word;
|
||||
font-size: 9pt;
|
||||
line-height: 125%;
|
||||
font-family: monospace, fixed;
|
||||
font-size: 105%;
|
||||
}
|
||||
|
||||
div.fragment {
|
||||
padding: 4px 6px;
|
||||
margin: 4px 8px 4px 2px;
|
||||
border: 1px solid #C4CFE5;
|
||||
}
|
||||
|
||||
div.line {
|
||||
font-family: monospace, fixed;
|
||||
font-size: 13px;
|
||||
min-height: 13px;
|
||||
line-height: 1.0;
|
||||
text-wrap: unrestricted;
|
||||
white-space: -moz-pre-wrap; /* Moz */
|
||||
white-space: -pre-wrap; /* Opera 4-6 */
|
||||
white-space: -o-pre-wrap; /* Opera 7 */
|
||||
white-space: pre-wrap; /* CSS3 */
|
||||
word-wrap: break-word; /* IE 5.5+ */
|
||||
text-indent: -53px;
|
||||
padding-left: 53px;
|
||||
padding-bottom: 0px;
|
||||
margin: 0px;
|
||||
-webkit-transition-property: background-color, box-shadow;
|
||||
-webkit-transition-duration: 0.5s;
|
||||
-moz-transition-property: background-color, box-shadow;
|
||||
-moz-transition-duration: 0.5s;
|
||||
-ms-transition-property: background-color, box-shadow;
|
||||
-ms-transition-duration: 0.5s;
|
||||
-o-transition-property: background-color, box-shadow;
|
||||
-o-transition-duration: 0.5s;
|
||||
transition-property: background-color, box-shadow;
|
||||
transition-duration: 0.5s;
|
||||
}
|
||||
|
||||
div.line.glow {
|
||||
background-color: cyan;
|
||||
box-shadow: 0 0 10px cyan;
|
||||
}
|
||||
|
||||
|
||||
span.lineno {
|
||||
padding-right: 4px;
|
||||
text-align: right;
|
||||
border-right: 2px solid #0F0;
|
||||
background-color: #E8E8E8;
|
||||
white-space: pre;
|
||||
}
|
||||
span.lineno a {
|
||||
background-color: #D8D8D8;
|
||||
}
|
||||
|
||||
span.lineno a:hover {
|
||||
background-color: #C8C8C8;
|
||||
}
|
||||
|
||||
div.groupHeader {
|
||||
margin-left: 16px;
|
||||
margin-top: 12px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
div.groupText {
|
||||
margin-left: 16px;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/* @group Code Colorization */
|
||||
|
||||
span.keyword {
|
||||
color: #008000
|
||||
}
|
||||
|
||||
span.keywordtype {
|
||||
color: #604020
|
||||
}
|
||||
|
||||
span.keywordflow {
|
||||
color: #e08000
|
||||
}
|
||||
|
||||
span.comment {
|
||||
color: #800000
|
||||
}
|
||||
|
||||
span.preprocessor {
|
||||
color: #806020
|
||||
}
|
||||
|
||||
span.stringliteral {
|
||||
color: #002080
|
||||
}
|
||||
|
||||
span.charliteral {
|
||||
color: #008080
|
||||
}
|
||||
|
||||
span.vhdldigit {
|
||||
color: #ff00ff
|
||||
}
|
||||
|
||||
span.vhdlchar {
|
||||
color: #000000
|
||||
}
|
||||
|
||||
span.vhdlkeyword {
|
||||
color: #700070
|
||||
}
|
||||
|
||||
span.vhdllogic {
|
||||
color: #ff0000
|
||||
}
|
||||
|
||||
blockquote {
|
||||
background-color: #F7F8FB;
|
||||
border-left: 2px solid #9CAFD4;
|
||||
margin: 0 24px 0 4px;
|
||||
padding: 0 12px 0 16px;
|
||||
}
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
<!-- HTML footer for doxygen 1.8.8-->
|
||||
<!-- start footer part -->
|
||||
<!--BEGIN GENERATE_TREEVIEW-->
|
||||
<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
|
||||
<ul>
|
||||
$navpath
|
||||
<li class="footer">$generatedby
|
||||
<a href="http://www.doxygen.org/index.html">
|
||||
<img class="footer" src="$relpath^doxygen.png" alt="doxygen"/></a> $doxygenversion </li>
|
||||
</ul>
|
||||
</div>
|
||||
<!--END GENERATE_TREEVIEW-->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--BEGIN !GENERATE_TREEVIEW-->
|
||||
<hr class="footer"/><address class="footer"><small>
|
||||
$generatedby  <a href="http://www.doxygen.org/index.html">
|
||||
<img class="footer" src="$relpath^doxygen.png" alt="doxygen"/>
|
||||
</a> $doxygenversion
|
||||
</small></address>
|
||||
<!--END !GENERATE_TREEVIEW-->
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,42 +0,0 @@
|
||||
<!-- HTML header for doxygen 1.8.8-->
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<!-- For Mobile Devices -->
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
|
||||
<meta name="generator" content="Doxygen $doxygenversion"/>
|
||||
|
||||
<script type="text/javascript" src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
|
||||
|
||||
<!--BEGIN PROJECT_NAME--><title>$projectname: $title</title><!--END PROJECT_NAME-->
|
||||
<!--BEGIN !PROJECT_NAME--><title>$title</title><!--END !PROJECT_NAME-->
|
||||
<!--<link href="$relpath^tabs.css" rel="stylesheet" type="text/css"/>-->
|
||||
<script type="text/javascript" src="$relpath^dynsections.js"></script>
|
||||
$treeview
|
||||
$search
|
||||
$mathjax
|
||||
<link href="$relpath^$stylesheet" rel="stylesheet" type="text/css" />
|
||||
$extrastylesheet
|
||||
|
||||
<link href="bootstrap.css" rel="stylesheet" type="text/css" />
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/js/bootstrap.min.js"></script>
|
||||
<script type="text/javascript" src="doxy-boot.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar navbar-default" role="navigation">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<a class="navbar-brand">$projectname $projectnumber</a>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
|
||||
<div class="content" id="content">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 panel panel-default" style="padding-bottom: 15px;">
|
||||
<div style="margin-bottom: 15px;">
|
||||
<!-- end header part -->
|
||||
@@ -1,189 +0,0 @@
|
||||
# Database for libratbag to select the correct driver to use for gaming mice.
|
||||
#
|
||||
# The lookup keys are composed in:
|
||||
# 70-libratbag-mouse.rules
|
||||
#
|
||||
# Match string format:
|
||||
# mouse:<subsystem>:v<vid>p<pid>:name:<name>:
|
||||
#
|
||||
# Supported subsystems: usb, bluetooth
|
||||
# vid/pid as 4-digit hex lowercase vendor/product
|
||||
#
|
||||
# if vid/pid is unavailable, use
|
||||
# mouse:*:name:<name>:
|
||||
# if name is unavailable, use
|
||||
# mouse:<subsystem>:v<vid>p<pid>:*
|
||||
#
|
||||
# For example, the following 5 matches all match the same mouse:
|
||||
# mouse:usb:v17efp6019:name:Lenovo Optical USB Mouse:
|
||||
# mouse:usb:*:name:Lenovo Optical USB Mouse:
|
||||
# mouse:usb:v17efp6019:*
|
||||
# mouse:*:name:Lenovo Optical USB Mouse:
|
||||
#
|
||||
# To add local entries, create a new file
|
||||
# /etc/udev/hwdb.d/71-libratbat-mouse-local.hwdb
|
||||
# and add your rules there. To load the new rules execute (as root):
|
||||
# udevadm hwdb --update
|
||||
# udevadm trigger /dev/input/eventXX
|
||||
# where /dev/input/eventXX is the mouse in question. If in
|
||||
# doubt, simply use /dev/input/event* to reload all input rules.
|
||||
#
|
||||
# If your changes are generally applicable, preferably send them as a pull
|
||||
# request to
|
||||
# https://github.com/libratbag/libratbag
|
||||
# or create a bug report on https://github.com/libratbag/libratbag/issues and
|
||||
# include your new rules, a description of the device, and the output of
|
||||
# udevadm info /dev/input/eventXX
|
||||
# (or /dev/input/event*).
|
||||
#
|
||||
# Allowed properties are:
|
||||
# RATBAG_DRIVER
|
||||
# RATBAG_SVG
|
||||
|
||||
# Sort by brand, driver
|
||||
|
||||
|
||||
##########################################
|
||||
# Etekcity
|
||||
##########################################
|
||||
|
||||
mouse:usb:v1ea7p4011:name:*:
|
||||
RATBAG_DRIVER=etekcity
|
||||
RATBAG_SVG=etekcity.svg
|
||||
|
||||
##########################################
|
||||
# Logitech
|
||||
##########################################
|
||||
|
||||
# M705
|
||||
mouse:usb:v046dp101b:name:*:
|
||||
RATBAG_DRIVER=hidpp10
|
||||
|
||||
# M570
|
||||
mouse:usb:v046dp1028:name:*:
|
||||
RATBAG_DRIVER=hidpp10
|
||||
|
||||
# G5
|
||||
mouse:usb:v046dpc041:name:*:
|
||||
RATBAG_DRIVER=hidpp10
|
||||
RATBAG_HIDPP10_DPI_LIST=400;800;1600;2000
|
||||
|
||||
# G5 2007
|
||||
mouse:usb:v046dpc049:name:*:
|
||||
RATBAG_DRIVER=hidpp10
|
||||
RATBAG_HIDPP10_DPI_LIST=400;800;1600;2000
|
||||
|
||||
# G7
|
||||
mouse:usb:v046dpc51a:name:*:
|
||||
RATBAG_DRIVER=hidpp10
|
||||
|
||||
# G9
|
||||
mouse:usb:v046dpc048:name:*:
|
||||
RATBAG_DRIVER=hidpp10
|
||||
RATBAG_HIDPP10_DPI_LIST=0;200;400;600;800;1000;1200;1400;1600;1800;2000;2200;2400;2600;2800;3000;3200
|
||||
RATBAG_HIDPP10_PROFILE=G9
|
||||
|
||||
# G9x [Original]
|
||||
mouse:usb:v046dpc066:name:*:
|
||||
RATBAG_DRIVER=hidpp10
|
||||
RATBAG_HIDPP10_DPI=0:5700@23.53
|
||||
RATBAG_HIDPP10_PROFILE=G500
|
||||
|
||||
# G9x [Call of Duty MW3 Edition]
|
||||
mouse:usb:v046dpc249:name:*:
|
||||
RATBAG_DRIVER=hidpp10
|
||||
RATBAG_HIDPP10_DPI=0:5700@23.53
|
||||
RATBAG_HIDPP10_PROFILE=G500
|
||||
|
||||
# G500
|
||||
mouse:usb:v046dpc068:name:*:
|
||||
RATBAG_DRIVER=hidpp10
|
||||
RATBAG_HIDPP10_DPI=0:5700@23.53
|
||||
RATBAG_HIDPP10_PROFILE=G500
|
||||
|
||||
# G500s
|
||||
mouse:usb:v046dpc24e:name:*:
|
||||
RATBAG_DRIVER=hidpp10
|
||||
RATBAG_SVG=logitech-g500s.svg
|
||||
RATBAG_HIDPP10_DPI=0:8200@50
|
||||
RATBAG_HIDPP10_PROFILE=G500
|
||||
|
||||
# G502 Proteus Core over USB
|
||||
mouse:usb:v046dpc07d:name:*:
|
||||
RATBAG_DRIVER=hidpp20
|
||||
RATBAG_SVG=logitech-g502.svg
|
||||
|
||||
# G502 Proteus Spectrum over USB
|
||||
mouse:usb:v046dpc332:name:*:
|
||||
RATBAG_DRIVER=hidpp20
|
||||
RATBAG_SVG=logitech-g502.svg
|
||||
|
||||
# G700 over USB
|
||||
mouse:usb:v046dpc06b:name:*:
|
||||
RATBAG_DRIVER=hidpp10
|
||||
RATBAG_SVG=logitech-g700.svg
|
||||
RATBAG_HIDPP10_DPI=0:5700@23.53
|
||||
RATBAG_HIDPP10_PROFILE=G700
|
||||
|
||||
# G700 over wireless USB
|
||||
mouse:usb:v046dpc531:name:*:
|
||||
RATBAG_DRIVER=hidpp10
|
||||
RATBAG_HIDPP10_DPI=0:5700@23.53
|
||||
RATBAG_HIDPP10_PROFILE=G700
|
||||
RATBAG_HIDPP10_INDEX=1
|
||||
|
||||
# G700s over USB
|
||||
mouse:usb:v046dpc07c:name:*:
|
||||
RATBAG_DRIVER=hidpp10
|
||||
RATBAG_SVG=logitech-g700.svg
|
||||
RATBAG_HIDPP10_DPI=0:8200@50
|
||||
RATBAG_HIDPP10_PROFILE=G700
|
||||
|
||||
# G700s over wireless USB
|
||||
mouse:usb:v046dpc531:name:*:
|
||||
RATBAG_DRIVER=hidpp10
|
||||
RATBAG_SVG=logitech-g700.svg
|
||||
RATBAG_HIDPP10_DPI=0:8200@50
|
||||
RATBAG_HIDPP10_PROFILE=G700
|
||||
RATBAG_HIDPP10_INDEX=1
|
||||
|
||||
# MX Master over unifying
|
||||
mouse:usb:v046dp4041:name:*:
|
||||
# MX Master over bluetooth
|
||||
mouse:bluetooth:v046dpb012:name:*:
|
||||
RATBAG_DRIVER=hidpp20
|
||||
RATBAG_SVG=logitech-mx_master.svg
|
||||
|
||||
# T650 over unifying
|
||||
mouse:usb:v046dp4101:name:*:
|
||||
RATBAG_DRIVER=hidpp20
|
||||
|
||||
# M325 over unifying
|
||||
mouse:usb:v046dp400a:name:*:
|
||||
RATBAG_DRIVER=hidpp20
|
||||
|
||||
# G303 over USB
|
||||
mouse:usb:v046dpc080:name:*:
|
||||
RATBAG_DRIVER=hidpp20
|
||||
|
||||
# Wireless Touchpad (Unifying)
|
||||
mouse:usb:v046dp4011:name:*:
|
||||
RATBAG_DRIVER=hidpp20
|
||||
|
||||
# G602 over wireless USB
|
||||
mouse:usb:v046dpc537:name:*:
|
||||
RATBAG_HIDPP20_INDEX=1
|
||||
|
||||
# G900 over wireless USB
|
||||
mouse:usb:v046dpc539:name:*:
|
||||
RATBAG_DRIVER=hidpp20
|
||||
RATBAG_HIDPP20_INDEX=1
|
||||
|
||||
|
||||
##########################################
|
||||
# Roccat
|
||||
##########################################
|
||||
|
||||
mouse:usb:v1e7dp2e22:name:*:
|
||||
RATBAG_DRIVER=roccat
|
||||
RATBAG_SVG=roccat-kone-xtd.svg
|
||||
@@ -1,24 +0,0 @@
|
||||
# do not edit this file, it will be overwritten on update
|
||||
|
||||
ACTION=="remove", GOTO="mouse_end"
|
||||
KERNEL!="event*", GOTO="mouse_end"
|
||||
ENV{ID_INPUT}=="", GOTO="mouse_end"
|
||||
|
||||
# mouse:<subsystem>:v<vid>p<pid>:name:<name>:*
|
||||
KERNELS=="input*", ENV{ID_BUS}=="usb", \
|
||||
IMPORT{builtin}="hwdb 'mouse:$env{ID_BUS}:v$attr{id/vendor}p$attr{id/product}:name:$attr{name}:'", \
|
||||
GOTO="mouse_end"
|
||||
KERNELS=="input*", ENV{ID_BUS}=="bluetooth", \
|
||||
IMPORT{builtin}="hwdb 'mouse:$env{ID_BUS}:v$attr{id/vendor}p$attr{id/product}:name:$attr{name}:'", \
|
||||
GOTO="mouse_end"
|
||||
KERNELS=="input*", ENV{DEVPATH}=="/devices/virtual/misc/uhid/0003:*", \
|
||||
IMPORT{builtin}="hwdb 'mouse:usb:v$attr{id/vendor}p$attr{id/product}:name:$attr{name}:'", \
|
||||
GOTO="mouse_end"
|
||||
KERNELS=="input*", ENV{DEVPATH}=="/devices/virtual/misc/uhid/0005:*", \
|
||||
IMPORT{builtin}="hwdb 'mouse:bluetooth:v$attr{id/vendor}p$attr{id/product}:name:$attr{name}:'", \
|
||||
GOTO="mouse_end"
|
||||
DRIVERS=="psmouse", SUBSYSTEMS=="serio", \
|
||||
IMPORT{builtin}="hwdb 'mouse:ps2::name:$attr{device/name}:'", \
|
||||
GOTO="mouse_end"
|
||||
|
||||
LABEL="mouse_end"
|
||||
@@ -1,9 +0,0 @@
|
||||
udevrulesdir = $(UDEV_BASE_DIR)/rules.d
|
||||
udevrules_DATA = 70-libratbag-mouse.rules
|
||||
|
||||
hwdbdir = $(UDEV_BASE_DIR)/hwdb.d
|
||||
hwdb_DATA = 70-libratbag-mouse.hwdb
|
||||
|
||||
EXTRA_DIST = \
|
||||
$(udevrules_DATA) \
|
||||
$(hwdb_DATA)
|
||||
607
meson.build
Normal file
@@ -0,0 +1,607 @@
|
||||
project('libratbag', 'c', 'cpp',
|
||||
version : '0.9.905',
|
||||
license : 'MIT/Expat',
|
||||
default_options : [ 'c_std=gnu99', 'warning_level=2' ],
|
||||
meson_version : '>= 0.40.0')
|
||||
|
||||
libratbag_version = meson.project_version().split('.')
|
||||
|
||||
git = find_program('git')
|
||||
r = run_command('tools/ratbag-git-sha.sh')
|
||||
ratbagd_sha = r.stdout().strip()
|
||||
|
||||
# We use libtool-version numbers because it's easier to understand.
|
||||
# Before making a release, the libratbag_so_* and liblur_so_*
|
||||
# numbers should be modified. The components are of the form C:R:A.
|
||||
# a) If binary compatibility has been broken (eg removed or changed interfaces)
|
||||
# change to C+1:0:0.
|
||||
# b) If interfaces have been changed or added, but binary compatibility has
|
||||
# been preserved, change to C+1:0:A+1
|
||||
# c) If the interface is the same as the previous version, change to C:R+1:A
|
||||
liblur_so_c=3
|
||||
liblur_so_r=3
|
||||
liblur_so_a=0
|
||||
|
||||
# convert to sonames
|
||||
liblur_so_version = '@0@.@1@.@2@'.format((liblur_so_c-liblur_so_a),
|
||||
liblur_so_a, liblur_so_r)
|
||||
|
||||
# Compiler setup
|
||||
cc = meson.get_compiler('c')
|
||||
cpp = meson.get_compiler('cpp')
|
||||
cppflags = ['-Wno-unused-parameter', '-fvisibility=hidden']
|
||||
cflags = cppflags + ['-Wmissing-prototypes', '-Wstrict-prototypes']
|
||||
add_project_arguments(cflags, language: 'c')
|
||||
add_project_arguments(cppflags, language: 'cpp')
|
||||
|
||||
# Initialize config.h, to be added to in the various options below, config.h
|
||||
# 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'),
|
||||
'libratbag')
|
||||
libratbag_data_dir_devel = join_paths(meson.source_root(), 'data')
|
||||
config_h.set_quoted('LIBRATBAG_DATA_DIR', libratbag_data_dir)
|
||||
|
||||
# Coverity breaks because it doesn't define _Float128 correctly, you'll end
|
||||
# up with a bunch of messages in the form:
|
||||
# "/usr/include/stdlib.h", line 133: error #20: identifier "_Float128" is
|
||||
# undefined
|
||||
# extern _Float128 strtof128 (const char *__restrict __nptr,
|
||||
# ^
|
||||
# We don't use float128 ourselves, it gets pulled in from math.h or
|
||||
# something, so let's just define it as uint128 and move on.
|
||||
# Unfortunately we can't detect the coverity build at meson configure
|
||||
# time, we only know it fails at runtime. So make this an option instead, to
|
||||
# be removed when coverity fixes this again.
|
||||
if get_option('coverity')
|
||||
config_h.set('_Float128', '__uint128_t')
|
||||
config_h.set('_Float32', 'int')
|
||||
config_h.set('_Float32x', 'int')
|
||||
config_h.set('_Float64', 'long')
|
||||
config_h.set('_Float64x', 'long')
|
||||
endif
|
||||
|
||||
# dependencies
|
||||
pkgconfig = import('pkgconfig')
|
||||
dep_udev = dependency('libudev')
|
||||
dep_libevdev = dependency('libevdev')
|
||||
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',
|
||||
'src/libratbag-util.h'
|
||||
]
|
||||
|
||||
deps_libutil = [
|
||||
dep_udev,
|
||||
]
|
||||
|
||||
lib_libutil = static_library('util',
|
||||
src_libutil,
|
||||
dependencies : deps_libutil
|
||||
)
|
||||
dep_libutil = declare_dependency(link_with: lib_libutil)
|
||||
|
||||
### libhidpp.a ####
|
||||
src_libhidpp = [
|
||||
'src/hidpp-generic.h',
|
||||
'src/hidpp-generic.c',
|
||||
'src/hidpp10.h',
|
||||
'src/hidpp10.c',
|
||||
'src/hidpp20.h',
|
||||
'src/hidpp20.c',
|
||||
'src/usb-ids.h'
|
||||
]
|
||||
|
||||
deps_libhidpp = [ dep_lm ]
|
||||
|
||||
lib_libhidpp = static_library('hidpp',
|
||||
src_libhidpp,
|
||||
dependencies : deps_libhidpp)
|
||||
dep_libhidpp = declare_dependency(link_with: lib_libhidpp)
|
||||
|
||||
### liblur.a ####
|
||||
install_headers('src/liblur.h')
|
||||
|
||||
src_liblur = [
|
||||
'src/liblur.c',
|
||||
'src/liblur.h'
|
||||
]
|
||||
|
||||
deps_liblur = [
|
||||
dep_libutil,
|
||||
dep_libhidpp,
|
||||
]
|
||||
|
||||
lur_mapfile = 'src/liblur.sym'
|
||||
lur_version_flag = '-Wl,--version-script,@0@/@1@'.format(meson.current_source_dir(), lur_mapfile)
|
||||
lib_liblur = shared_library('lur',
|
||||
src_liblur,
|
||||
include_directories : include_directories('.'),
|
||||
dependencies : deps_liblur,
|
||||
version : liblur_so_version,
|
||||
link_args : lur_version_flag,
|
||||
link_depends : lur_mapfile,
|
||||
install : true,
|
||||
)
|
||||
|
||||
dep_liblur = declare_dependency(link_with: lib_liblur)
|
||||
|
||||
pkgconfig.generate (
|
||||
filebase: 'liblur',
|
||||
name: 'Liblur',
|
||||
description: 'Logitech Unifying Receiver configuration library',
|
||||
version: meson.project_version(),
|
||||
libraries: lib_liblur
|
||||
)
|
||||
|
||||
#### libratbag.so ####
|
||||
src_libratbag = [
|
||||
'src/libratbag-enums.h',
|
||||
'src/libratbag.h',
|
||||
'src/driver-etekcity.c',
|
||||
'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',
|
||||
'src/driver-test.c',
|
||||
'src/libratbag.c',
|
||||
'src/libratbag.h',
|
||||
'src/libratbag-data.c',
|
||||
'src/libratbag-data.h',
|
||||
'src/libratbag-hidraw.c',
|
||||
'src/libratbag-hidraw.h',
|
||||
'src/libratbag-private.h',
|
||||
'src/libratbag-test.c',
|
||||
'src/libratbag-test.h',
|
||||
'src/usb-ids.h'
|
||||
]
|
||||
|
||||
deps_libratbag = [
|
||||
dep_udev,
|
||||
dep_libevdev,
|
||||
dep_glib,
|
||||
dep_libutil,
|
||||
dep_libhidpp,
|
||||
]
|
||||
|
||||
lib_libratbag = static_library('ratbag',
|
||||
src_libratbag,
|
||||
include_directories : include_directories('.'),
|
||||
dependencies : deps_libratbag,
|
||||
)
|
||||
|
||||
dep_libratbag = declare_dependency(
|
||||
link_with : lib_libratbag,
|
||||
dependencies : deps_libratbag
|
||||
)
|
||||
|
||||
#### libshared.a ####
|
||||
src_libshared = [
|
||||
'tools/shared.c',
|
||||
'tools/shared.h'
|
||||
]
|
||||
|
||||
deps_libshared = [
|
||||
dep_udev,
|
||||
dep_libevdev,
|
||||
]
|
||||
lib_libshared = static_library('shared',
|
||||
src_libshared,
|
||||
dependencies : deps_libshared,
|
||||
include_directories : include_directories('src')
|
||||
)
|
||||
dep_libshared = declare_dependency(link_with: lib_libshared)
|
||||
|
||||
#### hidpp10-dump-page ####
|
||||
src_hidpp10_dump_page = [ 'tools/hidpp10-dump-page.c' ]
|
||||
executable('hidpp10-dump-page',
|
||||
src_hidpp10_dump_page,
|
||||
dependencies : [ dep_libhidpp ],
|
||||
include_directories : include_directories('src'),
|
||||
install : false,
|
||||
)
|
||||
|
||||
#### hidpp20-dump-page ####
|
||||
src_hidpp20_dump_page = [ 'tools/hidpp20-dump-page.c' ]
|
||||
executable('hidpp20-dump-page',
|
||||
src_hidpp20_dump_page,
|
||||
dependencies : [ dep_libhidpp ],
|
||||
include_directories : include_directories('src'),
|
||||
install : false,
|
||||
)
|
||||
|
||||
#### hidpp20-reset ####
|
||||
src_hidpp20_reset = [ 'tools/hidpp20-reset.c' ]
|
||||
executable('hidpp20-reset',
|
||||
src_hidpp20_reset,
|
||||
dependencies : [ dep_libhidpp ],
|
||||
include_directories : include_directories('src'),
|
||||
install : false,
|
||||
)
|
||||
|
||||
#### lur-command ####
|
||||
src_lur_command = [ 'tools/lur-command.c' ]
|
||||
executable('lur-command',
|
||||
src_lur_command,
|
||||
dependencies : [ dep_libshared, dep_liblur ],
|
||||
include_directories : include_directories('src'),
|
||||
install : true,
|
||||
)
|
||||
|
||||
man_config = configuration_data()
|
||||
|
||||
man_config.set('version', meson.project_version())
|
||||
|
||||
man_lur_command = configure_file (
|
||||
input: 'tools/lur-command.man',
|
||||
output: 'lur-command.1',
|
||||
configuration: man_config,
|
||||
install : true,
|
||||
install_dir : join_paths(get_option('mandir'), 'man1')
|
||||
)
|
||||
|
||||
#### data files ####
|
||||
# list ordered by git ls-files data/devices/*.device
|
||||
data_files = files(
|
||||
'data/devices/etekcity-scroll-alpha.device',
|
||||
'data/devices/gskill-MX-780.device',
|
||||
'data/devices/logitech-M325.device',
|
||||
'data/devices/logitech-M570.device',
|
||||
'data/devices/logitech-M705.device',
|
||||
'data/devices/logitech-MX-Master.device',
|
||||
'data/devices/logitech-MX-Master-2S.device',
|
||||
'data/devices/logitech-T650.device',
|
||||
'data/devices/logitech-Wireless-Touchpad.device',
|
||||
'data/devices/logitech-g-pro-wireless.device',
|
||||
'data/devices/logitech-g-pro.device',
|
||||
'data/devices/logitech-g102-g203.device',
|
||||
'data/devices/logitech-g300.device',
|
||||
'data/devices/logitech-g302.device',
|
||||
'data/devices/logitech-g303.device',
|
||||
'data/devices/logitech-g402.device',
|
||||
'data/devices/logitech-g403.device',
|
||||
'data/devices/logitech-g5-2007.device',
|
||||
'data/devices/logitech-g5.device',
|
||||
'data/devices/logitech-g500.device',
|
||||
'data/devices/logitech-g500s.device',
|
||||
'data/devices/logitech-g502-HERO-over-USB.device',
|
||||
'data/devices/logitech-g502-Proteus-Core-over-USB.device',
|
||||
'data/devices/logitech-g502-Proteus-Spectrum-over-USB.device',
|
||||
'data/devices/logitech-g600.device',
|
||||
'data/devices/logitech-g602.device',
|
||||
'data/devices/logitech-g603.device',
|
||||
'data/devices/logitech-g7.device',
|
||||
'data/devices/logitech-g700-wireless.device',
|
||||
'data/devices/logitech-g700.device',
|
||||
'data/devices/logitech-g700s-wireless.device',
|
||||
'data/devices/logitech-g700s.device',
|
||||
'data/devices/logitech-g703.device',
|
||||
'data/devices/logitech-g9.device',
|
||||
'data/devices/logitech-g900-wireless.device',
|
||||
'data/devices/logitech-g900.device',
|
||||
'data/devices/logitech-g903.device',
|
||||
'data/devices/logitech-g9x-[Call-of-Duty-MW3-Edition].device',
|
||||
'data/devices/logitech-g9x-[Original].device',
|
||||
'data/devices/logitech-gpowerplay-wireless.device',
|
||||
'data/devices/logitech-MX-Anywhere2.device',
|
||||
'data/devices/logitech-MX-Anywhere2S.device',
|
||||
'data/devices/roccat-kone-xtd.device',
|
||||
'data/devices/steelseries-kinzu-v2.device',
|
||||
'data/devices/steelseries-rival-310.device',
|
||||
'data/devices/steelseries-rival-600.device',
|
||||
'data/devices/steelseries-rival.device',
|
||||
'data/devices/steelseries-sensei-310.device',
|
||||
'data/devices/steelseries-sensei-raw.device',
|
||||
)
|
||||
|
||||
install_data(data_files,
|
||||
install_dir : join_paths(get_option('datadir'), 'libratbag', 'devices'))
|
||||
|
||||
data_parse_test = find_program(join_paths(meson.source_root(), 'data/devices/data-parse-test.py'))
|
||||
test('data-parse-test', data_parse_test, args: data_files)
|
||||
|
||||
#### tests ####
|
||||
enable_tests = get_option('tests')
|
||||
if enable_tests
|
||||
dep_check = dependency('check', version: '>= 0.9.10')
|
||||
|
||||
config_h.set('BUILD_TESTS', '1')
|
||||
|
||||
test_context = executable('test-context',
|
||||
['test/test-context.c'],
|
||||
dependencies : [ dep_libratbag, dep_check ],
|
||||
include_directories : include_directories('src'),
|
||||
install : false)
|
||||
test_device = executable('test-device',
|
||||
['test/test-device.c'],
|
||||
dependencies : [ dep_libratbag, dep_check ],
|
||||
include_directories : include_directories('src'),
|
||||
install : false)
|
||||
test_util = executable('test-util',
|
||||
['test/test-util.c'],
|
||||
dependencies : [ dep_libratbag, dep_check ],
|
||||
include_directories : include_directories('src'),
|
||||
install : false)
|
||||
test_iconv_helper = executable('test-iconv-helper',
|
||||
['test/test-iconv-helper.c'],
|
||||
dependencies : [ dep_libratbag,
|
||||
dep_check,
|
||||
dep_libutil],
|
||||
include_directories : include_directories('src'),
|
||||
install : false)
|
||||
test('test-context', test_context)
|
||||
test('test-device', test_device)
|
||||
test('test-util', test_util)
|
||||
test('test-iconv-helper', test_iconv_helper)
|
||||
|
||||
valgrind = find_program('valgrind')
|
||||
valgrind_suppressions_file = join_paths(meson.source_root(), 'test', 'valgrind.suppressions')
|
||||
add_test_setup('valgrind',
|
||||
exe_wrapper : [
|
||||
valgrind,
|
||||
'--leak-check=full',
|
||||
'--quiet',
|
||||
'--error-exitcode=3',
|
||||
'--suppressions=' + valgrind_suppressions_file ],
|
||||
timeout_multiplier: 5)
|
||||
|
||||
executable('test-build-cxx',
|
||||
['test/build-cxx.cc'],
|
||||
dependencies : [ dep_libratbag ],
|
||||
include_directories : include_directories('src'),
|
||||
cpp_args : ['-Wall', '-Wextra', '-Wno-unused-parameter'],
|
||||
install : false)
|
||||
executable('test-build-linker',
|
||||
['test/build-pedantic.c'],
|
||||
dependencies : [ dep_libratbag ],
|
||||
include_directories : include_directories('src'),
|
||||
install : false)
|
||||
executable('test-build-gnuc90',
|
||||
['test/build-pedantic.c'],
|
||||
dependencies : [ dep_libratbag ],
|
||||
include_directories : include_directories('src'),
|
||||
c_args : ['-std=gnu90', '-Werror'],
|
||||
install : false)
|
||||
executable('test-build-pedantic',
|
||||
['test/build-pedantic.c'],
|
||||
dependencies : [ dep_libratbag ],
|
||||
include_directories : include_directories('src'),
|
||||
c_args : ['-std=c99', '-pedantic', '-Werror'],
|
||||
install : false)
|
||||
endif
|
||||
|
||||
#### ratbagd ####
|
||||
src_ratbagd = [
|
||||
'src/shared-macro.h',
|
||||
'src/shared-rbtree.h',
|
||||
'src/shared-rbtree.c',
|
||||
'ratbagd/ratbagd.h',
|
||||
'ratbagd/ratbagd.c',
|
||||
'ratbagd/ratbagd-led.c',
|
||||
'ratbagd/ratbagd-button.c',
|
||||
'ratbagd/ratbagd-device.c',
|
||||
'ratbagd/ratbagd-profile.c',
|
||||
'ratbagd/ratbagd-resolution.c',
|
||||
'ratbagd/ratbagd-test.c',
|
||||
'src/libratbag-util.h',
|
||||
'src/libratbag-util.c',
|
||||
]
|
||||
|
||||
deps_ratbagd = [
|
||||
dep_udev,
|
||||
logind_dep,
|
||||
dep_libratbag,
|
||||
]
|
||||
|
||||
executable('ratbagd',
|
||||
src_ratbagd,
|
||||
dependencies : deps_ratbagd,
|
||||
include_directories : include_directories('src'),
|
||||
install : true,
|
||||
)
|
||||
|
||||
install_man('ratbagd/ratbagd.8')
|
||||
|
||||
#### ratbagd_devel ####
|
||||
|
||||
executable('ratbagd.devel',
|
||||
src_ratbagd,
|
||||
dependencies : deps_ratbagd,
|
||||
include_directories : include_directories('src'),
|
||||
install : false,
|
||||
c_args : ['-DRATBAG_DBUS_INTERFACE="ratbag_devel1_@0@"'.format(ratbagd_sha),
|
||||
'-DDISABLE_COREDUMP=1'],
|
||||
)
|
||||
|
||||
config_ratbagd_devel = configuration_data()
|
||||
config_ratbagd_devel.set('ratbagd_sha', ratbagd_sha)
|
||||
configure_file(input : 'dbus/org.freedesktop.ratbag_devel1.conf.in',
|
||||
output : 'org.freedesktop.ratbag_devel1.conf',
|
||||
configuration : config_ratbagd_devel)
|
||||
|
||||
#### unit file ####
|
||||
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
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
config_bindir = configuration_data()
|
||||
config_bindir.set('bindir', join_paths(get_option('prefix'), get_option('bindir')))
|
||||
|
||||
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 == ''
|
||||
dbusdir = join_paths(get_option('datadir'), 'dbus-1')
|
||||
endif
|
||||
|
||||
configure_file(input : 'dbus/org.freedesktop.ratbag1.service.in',
|
||||
output : 'org.freedesktop.ratbag1.service',
|
||||
configuration : config_bindir,
|
||||
install_dir : join_paths(dbusdir, 'system-services'))
|
||||
|
||||
dbusgroup = get_option('dbus-group')
|
||||
if dbusgroup == ''
|
||||
# grant everybody access by default
|
||||
access = 'context="default"'
|
||||
else
|
||||
# grant access to members of the specified group only
|
||||
access = 'group="@0@"'.format(dbusgroup)
|
||||
endif
|
||||
|
||||
config_dbusaccess = configuration_data()
|
||||
config_dbusaccess.set('access', access)
|
||||
|
||||
configure_file(input : 'dbus/org.freedesktop.ratbag1.conf.in',
|
||||
output : 'org.freedesktop.ratbag1.conf',
|
||||
configuration : config_dbusaccess,
|
||||
install_dir : join_paths(dbusdir, 'system.d'))
|
||||
|
||||
#### tools ####
|
||||
|
||||
if meson.version().version_compare('<0.48.0')
|
||||
python = import('python3')
|
||||
py3 = python.find_python()
|
||||
else
|
||||
pymod = import('python')
|
||||
py3 = pymod.find_installation()
|
||||
endif
|
||||
|
||||
# ratbagctl calls ratbagd over DBus
|
||||
custom_target('ratbagctl',
|
||||
output : 'ratbagctl',
|
||||
input : ['tools/ratbagctl.in', 'tools/ratbagd.py'],
|
||||
build_by_default : true,
|
||||
command : [py3, join_paths(meson.source_root(), 'tools', 'merge_ratbagd.py'),
|
||||
'@INPUT@',
|
||||
'--output', '@OUTPUT@',
|
||||
'--version', meson.project_version()],
|
||||
install: true,
|
||||
install_dir: get_option('bindir'))
|
||||
|
||||
man_ratbagctl = configure_file (
|
||||
input: 'tools/ratbagctl.1',
|
||||
output: 'ratbagctl.1',
|
||||
configuration: man_config,
|
||||
install : true,
|
||||
install_dir : join_paths(get_option('mandir'), 'man1')
|
||||
)
|
||||
|
||||
config_ratbagctl_devel = configuration_data()
|
||||
config_ratbagctl_devel.set('ratbagd_sha', ratbagd_sha)
|
||||
config_ratbagctl_devel.set('MESON_BUILD_ROOT', meson.build_root())
|
||||
config_ratbagctl_devel.set('LIBRATBAG_DATA_DIR', libratbag_data_dir_devel)
|
||||
|
||||
configure_file(input : 'tools/toolbox.py',
|
||||
output : 'toolbox.py',
|
||||
configuration : config_ratbagctl_devel)
|
||||
# ratbagctl.devel starts a custom ratbagd and interacts with that over DBus
|
||||
configure_file(input : 'tools/ratbagctl.devel.in',
|
||||
output : 'ratbagctl.devel',
|
||||
configuration : config_ratbagctl_devel)
|
||||
# ratbagctl.test starts a custom ratbagd and interacts with that over DBus
|
||||
configure_file(input : 'tools/ratbagctl.test.in',
|
||||
output : 'ratbagctl.test',
|
||||
configuration : config_ratbagctl_devel)
|
||||
|
||||
env_test = environment()
|
||||
env_test.set('LIBRATBAG_DATA_DIR', libratbag_data_dir_devel)
|
||||
ratbagctl_test = find_program(join_paths(meson.build_root(), 'ratbagctl.test'))
|
||||
test('ratbagctl-test', ratbagctl_test, args: ['-v'], env : env_test)
|
||||
|
||||
# ratbag-command uses Swig bindings to call libratbag directly
|
||||
swig = find_program('swig')
|
||||
swig_gen = generator(
|
||||
swig,
|
||||
output: ['@BASENAME@.c'],
|
||||
arguments: ['-python', '-py3', '-o', './@OUTPUT@',
|
||||
'-outdir', '.',
|
||||
'-I' + join_paths(meson.source_root(), 'src'),
|
||||
'-I' + join_paths(meson.source_root(), 'tools'),
|
||||
'@INPUT@'],
|
||||
)
|
||||
|
||||
wrapper_deps = [
|
||||
dependency('python3'),
|
||||
dep_libratbag,
|
||||
dep_libshared,
|
||||
]
|
||||
|
||||
i_source = join_paths(meson.source_root(), 'src', 'libratbag.i')
|
||||
c_source = swig_gen.process(i_source)
|
||||
shared_library(
|
||||
'libratbag',
|
||||
c_source,
|
||||
name_prefix: '_',
|
||||
c_args : ['-Wno-missing-prototypes', '-Wno-format-nonliteral'],
|
||||
extra_files: [ i_source ] + src_libratbag ,
|
||||
dependencies: deps_libratbag + wrapper_deps,
|
||||
include_directories : include_directories('src', 'tools'),
|
||||
install: false,
|
||||
)
|
||||
|
||||
# ratbagc is the layer that maps ratbagctl to the swig bindings
|
||||
ratbagc_py_conf = configuration_data()
|
||||
ratbagc_py_conf.set('LIBRATBAG_DATA_DIR', libratbag_data_dir_devel)
|
||||
ratbagc_py = configure_file(input: 'tools/ratbagc.py.in',
|
||||
output: 'ratbagc.py',
|
||||
configuration: ratbagc_py_conf)
|
||||
custom_target('ratbag-command',
|
||||
output : 'ratbag-command',
|
||||
input : ['tools/ratbagctl.in', ratbagc_py],
|
||||
build_by_default : true,
|
||||
command : [py3, join_paths(meson.source_root(), 'tools', 'merge_ratbagd.py'),
|
||||
'@INPUT@',
|
||||
'--output', '@OUTPUT@',
|
||||
'--version', meson.project_version()],
|
||||
install: false)
|
||||
|
||||
#### output files ####
|
||||
configure_file(output: 'config.h', install: false, configuration: config_h)
|
||||
|
||||
subdir('doc')
|
||||
45
meson_options.txt
Normal file
@@ -0,0 +1,45 @@
|
||||
option('udev-dir',
|
||||
type: 'string',
|
||||
value: '',
|
||||
description: 'udev base directory [default=$prefix/lib/udev]')
|
||||
|
||||
option('tests',
|
||||
type: 'boolean',
|
||||
value: true,
|
||||
description: 'Build the tests (default=yes)')
|
||||
|
||||
option('systemd-unit-dir',
|
||||
type : 'string',
|
||||
value : '',
|
||||
description : 'systemd unit directory [default=$libdir/systemd/system]')
|
||||
|
||||
option('dbus-root-dir',
|
||||
type : 'string',
|
||||
value : '',
|
||||
description : 'dbus service directory [default=$datadir/dbus-1]')
|
||||
|
||||
option('documentation',
|
||||
type: 'boolean',
|
||||
value: false,
|
||||
description: 'Enable documentation build (default=no)')
|
||||
|
||||
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')
|
||||
|
||||
option('coverity',
|
||||
type: 'boolean',
|
||||
value: false,
|
||||
description: 'Enable coverity build fixes, see meson.build for details [default=false]')
|
||||
12
ratbagd/.gitignore
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
*.a
|
||||
*.log
|
||||
*.o
|
||||
*.stamp
|
||||
*.swp
|
||||
*.trs
|
||||
*~
|
||||
.dirstamp
|
||||
.libs/
|
||||
/*.tar.xz
|
||||
tags
|
||||
__pycache__
|
||||
14
ratbagd/org.freedesktop.ratbag1.conf
Normal file
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0"?> <!--*-nxml-*-->
|
||||
<!DOCTYPE busconfig PUBLIC
|
||||
"-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
|
||||
"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
|
||||
|
||||
<busconfig>
|
||||
|
||||
<policy user="root">
|
||||
<allow own="org.freedesktop.ratbag1"/>
|
||||
<allow send_destination="org.freedesktop.ratbag1"/>
|
||||
<allow receive_sender="org.freedesktop.ratbag1"/>
|
||||
</policy>
|
||||
|
||||
</busconfig>
|
||||
481
ratbagd/ratbagd-button.c
Normal file
@@ -0,0 +1,481 @@
|
||||
/***
|
||||
This file is part of ratbagd.
|
||||
|
||||
Copyright 2016 Red Hat, Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice (including the next
|
||||
paragraph) shall be included in all copies or substantial portions of the
|
||||
Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
***/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <libratbag.h>
|
||||
#include <libudev.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <systemd/sd-bus.h>
|
||||
#include <systemd/sd-event.h>
|
||||
#include <linux/input.h>
|
||||
#include "ratbagd.h"
|
||||
#include "shared-macro.h"
|
||||
#include "libratbag-util.h"
|
||||
|
||||
struct ratbagd_button {
|
||||
struct ratbagd_device *device;
|
||||
struct ratbag_button *lib_button;
|
||||
unsigned int index;
|
||||
char *path;
|
||||
};
|
||||
|
||||
static int ratbagd_button_get_button(sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
const char *property,
|
||||
sd_bus_message *reply,
|
||||
void *userdata,
|
||||
sd_bus_error *error)
|
||||
{
|
||||
struct ratbagd_button *button = userdata;
|
||||
unsigned int b;
|
||||
|
||||
b = ratbag_button_get_button(button->lib_button);
|
||||
|
||||
verify_unsigned_int(b);
|
||||
|
||||
return sd_bus_message_append(reply, "(uv)",
|
||||
RATBAG_BUTTON_ACTION_TYPE_BUTTON,
|
||||
"u", b);
|
||||
}
|
||||
|
||||
static int ratbagd_button_set_button(sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
const char *property,
|
||||
sd_bus_message *m,
|
||||
void *userdata,
|
||||
sd_bus_error *error)
|
||||
{
|
||||
struct ratbagd_button *button = userdata;
|
||||
unsigned int map;
|
||||
int r;
|
||||
|
||||
r = sd_bus_message_read(m, "v", "u", &map);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (map == 0 || map > 30)
|
||||
return 0;
|
||||
|
||||
r = ratbag_button_set_button(button->lib_button, map);
|
||||
|
||||
if (r == 0) {
|
||||
sd_bus *bus = sd_bus_message_get_bus(m);
|
||||
sd_bus_emit_properties_changed(bus,
|
||||
button->path,
|
||||
RATBAGD_NAME_ROOT ".Button",
|
||||
"ButtonMapping",
|
||||
NULL);
|
||||
|
||||
sd_bus_emit_properties_changed(bus,
|
||||
button->path,
|
||||
RATBAGD_NAME_ROOT ".Button",
|
||||
"ActionType",
|
||||
NULL);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ratbagd_button_get_special(sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
const char *property,
|
||||
sd_bus_message *reply,
|
||||
void *userdata,
|
||||
sd_bus_error *error)
|
||||
{
|
||||
struct ratbagd_button *button = userdata;
|
||||
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;
|
||||
|
||||
verify_unsigned_int(special);
|
||||
|
||||
CHECK_CALL(sd_bus_message_append(reply, "(uv)",
|
||||
RATBAG_BUTTON_ACTION_TYPE_SPECIAL,
|
||||
"u",
|
||||
special));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ratbagd_button_set_special(sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
const char *property,
|
||||
sd_bus_message *m,
|
||||
void *userdata,
|
||||
sd_bus_error *error)
|
||||
{
|
||||
struct ratbagd_button *button = userdata;
|
||||
enum ratbag_button_action_special special;
|
||||
int r;
|
||||
|
||||
CHECK_CALL(sd_bus_message_read(m, "v", "u", &special));
|
||||
|
||||
r = ratbag_button_set_special(button->lib_button, special);
|
||||
|
||||
if (r == 0) {
|
||||
sd_bus *bus = sd_bus_message_get_bus(m);
|
||||
sd_bus_emit_properties_changed(bus,
|
||||
button->path,
|
||||
RATBAGD_NAME_ROOT ".Button",
|
||||
"SpecialMapping",
|
||||
NULL);
|
||||
|
||||
sd_bus_emit_properties_changed(bus,
|
||||
button->path,
|
||||
RATBAGD_NAME_ROOT ".Button",
|
||||
"ActionType",
|
||||
NULL);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(struct ratbag_button_macro *, ratbag_button_macro_unref);
|
||||
|
||||
static int ratbagd_button_get_macro(sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
const char *property,
|
||||
sd_bus_message *reply,
|
||||
void *userdata,
|
||||
sd_bus_error *error)
|
||||
{
|
||||
struct ratbagd_button *button = userdata;
|
||||
_cleanup_(ratbag_button_macro_unrefp) struct ratbag_button_macro *macro = NULL;
|
||||
unsigned int idx;
|
||||
|
||||
CHECK_CALL(sd_bus_message_open_container(reply, SD_BUS_TYPE_STRUCT, "uv"));
|
||||
CHECK_CALL(sd_bus_message_append(reply, "u", RATBAG_BUTTON_ACTION_TYPE_MACRO));
|
||||
CHECK_CALL(sd_bus_message_open_container(reply, 'v', "a(uu)"));
|
||||
CHECK_CALL(sd_bus_message_open_container(reply, 'a', "(uu)"));
|
||||
|
||||
macro = ratbag_button_get_macro(button->lib_button);
|
||||
if (!macro)
|
||||
goto out;
|
||||
|
||||
for (idx = 0; idx < ratbag_button_macro_get_num_events(macro); idx++) {
|
||||
enum ratbag_macro_event_type type;
|
||||
int value;
|
||||
|
||||
type = ratbag_button_macro_get_event_type(macro, idx);
|
||||
switch (type) {
|
||||
case RATBAG_MACRO_EVENT_INVALID:
|
||||
abort();
|
||||
break;
|
||||
case RATBAG_MACRO_EVENT_NONE:
|
||||
goto out;
|
||||
case RATBAG_MACRO_EVENT_KEY_PRESSED:
|
||||
case RATBAG_MACRO_EVENT_KEY_RELEASED:
|
||||
value = ratbag_button_macro_get_event_key(macro, idx);
|
||||
break;
|
||||
case RATBAG_MACRO_EVENT_WAIT:
|
||||
value = ratbag_button_macro_get_event_timeout(macro, idx);
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
|
||||
verify_unsigned_int(type);
|
||||
verify_unsigned_int(value);
|
||||
|
||||
CHECK_CALL(sd_bus_message_append(reply, "(uu)", type, value));
|
||||
}
|
||||
|
||||
out:
|
||||
CHECK_CALL(sd_bus_message_close_container(reply)); /* a(uu) */
|
||||
CHECK_CALL(sd_bus_message_close_container(reply)); /* v */
|
||||
CHECK_CALL(sd_bus_message_close_container(reply)); /* ) */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ratbagd_button_set_macro(sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
const char *property,
|
||||
sd_bus_message *m,
|
||||
void *userdata,
|
||||
sd_bus_error *error)
|
||||
{
|
||||
struct ratbagd_button *button = userdata;
|
||||
unsigned int type, value;
|
||||
int r, idx = 0;
|
||||
_cleanup_(ratbag_button_macro_unrefp) struct ratbag_button_macro *macro = NULL;
|
||||
|
||||
CHECK_CALL(sd_bus_message_enter_container(m, 'v', "a(uu)"));
|
||||
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) {
|
||||
r = ratbag_button_macro_set_event(macro, idx++, type, value);
|
||||
if (r < 0) {
|
||||
r = ratbagd_device_resync(button->device, bus);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
}
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
CHECK_CALL(sd_bus_message_exit_container(m)); /* (uu) */
|
||||
CHECK_CALL(sd_bus_message_exit_container(m)); /* a(uu) */
|
||||
|
||||
r = ratbag_button_set_macro(button->lib_button, macro);
|
||||
if (r < 0) {
|
||||
r = ratbagd_device_resync(button->device, bus);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (r == 0) {
|
||||
sd_bus *bus = sd_bus_message_get_bus(m);
|
||||
sd_bus_emit_properties_changed(bus,
|
||||
button->path,
|
||||
RATBAGD_NAME_ROOT ".Button",
|
||||
"Macro",
|
||||
NULL);
|
||||
|
||||
sd_bus_emit_properties_changed(bus,
|
||||
button->path,
|
||||
RATBAGD_NAME_ROOT ".Button",
|
||||
"ActionType",
|
||||
NULL);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ratbagd_button_get_mapping(sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
const char *property,
|
||||
sd_bus_message *reply,
|
||||
void *userdata,
|
||||
sd_bus_error *error)
|
||||
{
|
||||
struct ratbagd_button *button = userdata;
|
||||
enum ratbag_button_action_type type;
|
||||
|
||||
type = ratbag_button_get_action_type(button->lib_button);
|
||||
if (type == RATBAG_BUTTON_ACTION_TYPE_KEY)
|
||||
type = RATBAG_BUTTON_ACTION_TYPE_UNKNOWN;
|
||||
verify_unsigned_int(type);
|
||||
|
||||
switch (type) {
|
||||
case RATBAG_BUTTON_ACTION_TYPE_BUTTON:
|
||||
return ratbagd_button_get_button(bus, path, interface, property,
|
||||
reply, userdata, error);
|
||||
case RATBAG_BUTTON_ACTION_TYPE_SPECIAL:
|
||||
return ratbagd_button_get_special(bus, path, interface, property,
|
||||
reply, userdata, error);
|
||||
case RATBAG_BUTTON_ACTION_TYPE_MACRO:
|
||||
return ratbagd_button_get_macro(bus, path, interface, property,
|
||||
reply, userdata, error);
|
||||
default:
|
||||
return sd_bus_message_append(reply, "(uv)",
|
||||
RATBAG_BUTTON_ACTION_TYPE_UNKNOWN,
|
||||
"u", 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ratbagd_button_set_mapping(sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
const char *property,
|
||||
sd_bus_message *m,
|
||||
void *userdata,
|
||||
sd_bus_error *error)
|
||||
{
|
||||
enum ratbag_button_action_type type;
|
||||
|
||||
CHECK_CALL(sd_bus_message_enter_container(m, SD_BUS_TYPE_STRUCT, "uv"));
|
||||
CHECK_CALL(sd_bus_message_read(m, "u", &type));
|
||||
|
||||
switch (type) {
|
||||
case RATBAG_BUTTON_ACTION_TYPE_BUTTON:
|
||||
CHECK_CALL(ratbagd_button_set_button(bus, path, interface, property,
|
||||
m, userdata, error));
|
||||
break;
|
||||
case RATBAG_BUTTON_ACTION_TYPE_SPECIAL:
|
||||
CHECK_CALL(ratbagd_button_set_special(bus, path, interface, property,
|
||||
m, userdata, error));
|
||||
break;
|
||||
case RATBAG_BUTTON_ACTION_TYPE_MACRO:
|
||||
CHECK_CALL(ratbagd_button_set_macro(bus, path, interface, property,
|
||||
m, userdata, error));
|
||||
break;
|
||||
default:
|
||||
/* FIXME */
|
||||
return 1;
|
||||
}
|
||||
|
||||
CHECK_CALL(sd_bus_message_exit_container(m));
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
static int ratbagd_button_get_action_types(sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
const char *property,
|
||||
sd_bus_message *reply,
|
||||
void *userdata,
|
||||
sd_bus_error *error)
|
||||
{
|
||||
struct ratbagd_button *button = userdata;
|
||||
enum ratbag_button_action_type types[] = {
|
||||
RATBAG_BUTTON_ACTION_TYPE_BUTTON,
|
||||
RATBAG_BUTTON_ACTION_TYPE_SPECIAL,
|
||||
RATBAG_BUTTON_ACTION_TYPE_MACRO
|
||||
};
|
||||
enum ratbag_button_action_type *t;
|
||||
|
||||
|
||||
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;
|
||||
|
||||
verify_unsigned_int(*t);
|
||||
CHECK_CALL(sd_bus_message_append(reply, "u", *t));
|
||||
}
|
||||
|
||||
CHECK_CALL(sd_bus_message_close_container(reply));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ratbagd_button_disable(sd_bus_message *m,
|
||||
void *userdata,
|
||||
sd_bus_error *error)
|
||||
{
|
||||
struct ratbagd_button *button = userdata;
|
||||
int r;
|
||||
|
||||
CHECK_CALL(sd_bus_message_read(m, ""));
|
||||
|
||||
r = ratbag_button_disable(button->lib_button);
|
||||
if (r < 0) {
|
||||
sd_bus *bus = sd_bus_message_get_bus(m);
|
||||
r = ratbagd_device_resync(button->device, bus);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
CHECK_CALL(sd_bus_reply_method_return(m, "u", 0));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const sd_bus_vtable ratbagd_button_vtable[] = {
|
||||
SD_BUS_VTABLE_START(0),
|
||||
SD_BUS_PROPERTY("Index", "u", NULL, offsetof(struct ratbagd_button, index), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_WRITABLE_PROPERTY("Mapping", "(uv)",
|
||||
ratbagd_button_get_mapping,
|
||||
ratbagd_button_set_mapping,
|
||||
0, SD_BUS_VTABLE_UNPRIVILEGED | SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||
SD_BUS_PROPERTY("ActionTypes", "au", ratbagd_button_get_action_types, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_METHOD("Disable", "", "u", ratbagd_button_disable, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_VTABLE_END,
|
||||
};
|
||||
|
||||
int ratbagd_button_new(struct ratbagd_button **out,
|
||||
struct ratbagd_device *device,
|
||||
struct ratbagd_profile *profile,
|
||||
struct ratbag_button *lib_button,
|
||||
unsigned int index)
|
||||
{
|
||||
_cleanup_(ratbagd_button_freep) struct ratbagd_button *button = NULL;
|
||||
char profile_buffer[DECIMAL_TOKEN_MAX(unsigned int) + 1],
|
||||
button_buffer[DECIMAL_TOKEN_MAX(unsigned int) + 1];
|
||||
int r;
|
||||
|
||||
assert(out);
|
||||
assert(lib_button);
|
||||
|
||||
button = zalloc(sizeof(*button));
|
||||
button->device = device;
|
||||
button->lib_button = lib_button;
|
||||
button->index = index;
|
||||
|
||||
sprintf(profile_buffer, "p%u", ratbagd_profile_get_index(profile));
|
||||
sprintf(button_buffer, "b%u", index);
|
||||
r = sd_bus_path_encode_many(&button->path,
|
||||
RATBAGD_OBJ_ROOT "/button/%/%/%",
|
||||
ratbagd_device_get_sysname(device),
|
||||
profile_buffer,
|
||||
button_buffer);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*out = button;
|
||||
button = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *ratbagd_button_get_path(struct ratbagd_button *button)
|
||||
{
|
||||
assert(button);
|
||||
return button->path;
|
||||
}
|
||||
|
||||
struct ratbagd_button *ratbagd_button_free(struct ratbagd_button *button)
|
||||
{
|
||||
if (!button)
|
||||
return NULL;
|
||||
|
||||
button->path = mfree(button->path);
|
||||
button->lib_button = ratbag_button_unref(button->lib_button);
|
||||
|
||||
return mfree(button);
|
||||
}
|
||||
|
||||
int ratbagd_button_resync(sd_bus *bus,
|
||||
struct ratbagd_button *button)
|
||||
{
|
||||
return sd_bus_emit_properties_changed(bus,
|
||||
button->path,
|
||||
RATBAGD_NAME_ROOT ".Button",
|
||||
"ButtonMapping",
|
||||
"SpecialMapping",
|
||||
"Macro",
|
||||
"ActionType",
|
||||
NULL);
|
||||
}
|
||||
506
ratbagd/ratbagd-device.c
Normal file
@@ -0,0 +1,506 @@
|
||||
/***
|
||||
This file is part of ratbagd.
|
||||
|
||||
Copyright 2015 David Herrmann <dh.herrmann@gmail.com>
|
||||
|
||||
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 <limits.h>
|
||||
#include <libratbag.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <systemd/sd-bus.h>
|
||||
#include <systemd/sd-event.h>
|
||||
#include "ratbagd.h"
|
||||
#include "shared-macro.h"
|
||||
#include "shared-rbtree.h"
|
||||
|
||||
#include "libratbag-util.h"
|
||||
|
||||
struct ratbagd_device {
|
||||
struct ratbagd *ctx;
|
||||
RBNode node;
|
||||
char *sysname;
|
||||
char *path;
|
||||
struct ratbag_device *lib_device;
|
||||
|
||||
sd_bus_slot *profile_vtable_slot;
|
||||
sd_bus_slot *profile_enum_slot;
|
||||
unsigned int n_profiles;
|
||||
struct ratbagd_profile **profiles;
|
||||
};
|
||||
|
||||
#define ratbagd_device_from_node(_ptr) \
|
||||
rbnode_of((_ptr), struct ratbagd_device, node)
|
||||
|
||||
static int ratbagd_device_find_profile(sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
void *userdata,
|
||||
void **found,
|
||||
sd_bus_error *error)
|
||||
{
|
||||
_cleanup_(freep) char *name = NULL;
|
||||
struct ratbagd_device *device = userdata;
|
||||
unsigned int index = 0;
|
||||
int r;
|
||||
|
||||
r = sd_bus_path_decode_many(path,
|
||||
RATBAGD_OBJ_ROOT "/profile/%/p%",
|
||||
NULL,
|
||||
&name);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
r = safe_atou(name, &index);
|
||||
if (r < 0)
|
||||
return 0;
|
||||
|
||||
if (index >= device->n_profiles || !device->profiles[index])
|
||||
return 0;
|
||||
|
||||
*found = device->profiles[index];
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int ratbagd_device_list_profiles(sd_bus *bus,
|
||||
const char *path,
|
||||
void *userdata,
|
||||
char ***paths,
|
||||
sd_bus_error *error)
|
||||
{
|
||||
struct ratbagd_device *device = userdata;
|
||||
struct ratbagd_profile *profile;
|
||||
char **profiles;
|
||||
unsigned int i;
|
||||
|
||||
profiles = zalloc((device->n_profiles + 1) * sizeof(char *));
|
||||
|
||||
for (i = 0; i < device->n_profiles; ++i) {
|
||||
profile = device->profiles[i];
|
||||
if (!profile)
|
||||
continue;
|
||||
|
||||
profiles[i] = strdup_safe(ratbagd_profile_get_path(profile));
|
||||
}
|
||||
|
||||
profiles[i] = NULL;
|
||||
*paths = profiles;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int ratbagd_device_get_device_name(sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
const char *property,
|
||||
sd_bus_message *reply,
|
||||
void *userdata,
|
||||
sd_bus_error *error)
|
||||
{
|
||||
struct ratbagd_device *device = userdata;
|
||||
const char *name;
|
||||
|
||||
name = ratbag_device_get_name(device->lib_device);
|
||||
if (!name) {
|
||||
log_error("%s: failed to fetch name\n",
|
||||
ratbagd_device_get_sysname(device));
|
||||
name = "";
|
||||
}
|
||||
|
||||
CHECK_CALL(sd_bus_message_append(reply, "s", name));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ratbagd_device_get_profiles(sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
const char *property,
|
||||
sd_bus_message *reply,
|
||||
void *userdata,
|
||||
sd_bus_error *error)
|
||||
{
|
||||
struct ratbagd_device *device = userdata;
|
||||
struct ratbagd_profile *profile;
|
||||
unsigned int i;
|
||||
|
||||
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;
|
||||
|
||||
CHECK_CALL(sd_bus_message_append(reply,
|
||||
"o",
|
||||
ratbagd_profile_get_path(profile)));
|
||||
}
|
||||
|
||||
CHECK_CALL(sd_bus_message_close_container(reply));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ratbagd_device_commit_pending(void *data)
|
||||
{
|
||||
struct ratbagd_device *device = data;
|
||||
int r;
|
||||
|
||||
r = ratbag_device_commit(device->lib_device);
|
||||
if (r < 0)
|
||||
ratbagd_device_resync(device, device->ctx->bus);
|
||||
}
|
||||
|
||||
static int ratbagd_device_commit(sd_bus_message *m,
|
||||
void *userdata,
|
||||
sd_bus_error *error)
|
||||
{
|
||||
struct ratbagd_device *device = userdata;
|
||||
|
||||
ratbagd_schedule_task(device->ctx,
|
||||
ratbagd_device_commit_pending,
|
||||
device);
|
||||
|
||||
CHECK_CALL(sd_bus_reply_method_return(m, "u", 0));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ratbag_device_get_model(sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
const char *property,
|
||||
sd_bus_message *reply,
|
||||
void *userdata,
|
||||
sd_bus_error *error)
|
||||
{
|
||||
struct ratbagd_device *device = userdata;
|
||||
struct ratbag_device *lib_device = device->lib_device;
|
||||
const char *bustype = ratbag_device_get_bustype(lib_device);
|
||||
uint32_t vid = ratbag_device_get_vendor_id(lib_device),
|
||||
pid = ratbag_device_get_product_id(lib_device),
|
||||
version = ratbag_device_get_product_version(lib_device);
|
||||
char model[64];
|
||||
|
||||
if (!bustype)
|
||||
return sd_bus_message_append(reply, "s", "unknown");
|
||||
|
||||
snprintf(model, sizeof(model), "%s:%04x:%04x:%d",
|
||||
bustype, vid, pid, version);
|
||||
|
||||
return sd_bus_message_append(reply, "s", model);
|
||||
}
|
||||
|
||||
const sd_bus_vtable ratbagd_device_vtable[] = {
|
||||
SD_BUS_VTABLE_START(0),
|
||||
SD_BUS_PROPERTY("Model", "s", ratbag_device_get_model, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("Name", "s", ratbagd_device_get_device_name, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("Profiles", "ao", ratbagd_device_get_profiles, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_METHOD("Commit", "", "u", ratbagd_device_commit, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_SIGNAL("Resync", "", 0),
|
||||
SD_BUS_VTABLE_END,
|
||||
};
|
||||
|
||||
int ratbagd_device_new(struct ratbagd_device **out,
|
||||
struct ratbagd *ctx,
|
||||
const char *sysname,
|
||||
struct ratbag_device *lib_device)
|
||||
{
|
||||
_cleanup_(ratbagd_device_freep) struct ratbagd_device *device = NULL;
|
||||
struct ratbag_profile *profile;
|
||||
unsigned int i;
|
||||
int r;
|
||||
|
||||
assert(out);
|
||||
assert(ctx);
|
||||
assert(sysname);
|
||||
|
||||
device = zalloc(sizeof(*device));
|
||||
device->ctx = ctx;
|
||||
rbnode_init(&device->node);
|
||||
device->lib_device = ratbag_device_ref(lib_device);
|
||||
|
||||
device->sysname = strdup_safe(sysname);
|
||||
|
||||
r = sd_bus_path_encode(RATBAGD_OBJ_ROOT "/device",
|
||||
device->sysname,
|
||||
&device->path);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
||||
device->n_profiles = ratbag_device_get_num_profiles(device->lib_device);
|
||||
device->profiles = zalloc(device->n_profiles * sizeof(*device->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);
|
||||
if (!profile)
|
||||
continue;
|
||||
|
||||
r = ratbagd_profile_new(&device->profiles[i],
|
||||
device,
|
||||
profile,
|
||||
i);
|
||||
if (r < 0) {
|
||||
errno = -r;
|
||||
log_error("%s: failed to allocate profile: %m\n",
|
||||
device->sysname);
|
||||
}
|
||||
}
|
||||
|
||||
*out = device;
|
||||
device = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct ratbagd_device *ratbagd_device_free(struct ratbagd_device *device)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (!device)
|
||||
return NULL;
|
||||
|
||||
assert(!ratbagd_device_linked(device));
|
||||
|
||||
for (i = 0; i < device->n_profiles; ++i)
|
||||
device->profiles[i] = ratbagd_profile_free(device->profiles[i]);
|
||||
|
||||
device->profiles = mfree(device->profiles);
|
||||
device->lib_device = ratbag_device_unref(device->lib_device);
|
||||
device->path = mfree(device->path);
|
||||
device->sysname = mfree(device->sysname);
|
||||
|
||||
assert(!device->lib_device); /* ratbag yields !NULL if still pinned */
|
||||
|
||||
return mfree(device);
|
||||
}
|
||||
|
||||
const char *ratbagd_device_get_sysname(struct ratbagd_device *device)
|
||||
{
|
||||
assert(device);
|
||||
return device->sysname;
|
||||
}
|
||||
|
||||
const char *ratbagd_device_get_path(struct ratbagd_device *device)
|
||||
{
|
||||
assert(device);
|
||||
return device->path;
|
||||
}
|
||||
|
||||
unsigned int ratbagd_device_get_num_buttons(struct ratbagd_device *device)
|
||||
{
|
||||
assert(device);
|
||||
return ratbag_device_get_num_buttons(device->lib_device);
|
||||
}
|
||||
|
||||
unsigned int ratbagd_device_get_num_leds(struct ratbagd_device *device)
|
||||
{
|
||||
assert(device);
|
||||
return ratbag_device_get_num_leds(device->lib_device);
|
||||
}
|
||||
|
||||
int ratbagd_device_resync(struct ratbagd_device *device, sd_bus *bus)
|
||||
{
|
||||
assert(device);
|
||||
assert(bus);
|
||||
|
||||
ratbagd_for_each_profile_signal(bus, device,
|
||||
ratbagd_profile_resync);
|
||||
|
||||
return sd_bus_emit_signal(bus,
|
||||
device->path,
|
||||
RATBAGD_NAME_ROOT ".Device",
|
||||
"Resync",
|
||||
NULL);
|
||||
}
|
||||
|
||||
bool ratbagd_device_linked(struct ratbagd_device *device)
|
||||
{
|
||||
return device && rbnode_linked(&device->node);
|
||||
}
|
||||
|
||||
void ratbagd_device_link(struct ratbagd_device *device)
|
||||
{
|
||||
_cleanup_(freep) char *prefix = NULL;
|
||||
struct ratbagd_device *iter;
|
||||
RBNode **node, *parent;
|
||||
int r, v;
|
||||
unsigned int i;
|
||||
|
||||
assert(device);
|
||||
assert(!ratbagd_device_linked(device));
|
||||
|
||||
/* find place to link it to */
|
||||
parent = NULL;
|
||||
node = &device->ctx->device_map.root;
|
||||
while (*node) {
|
||||
parent = *node;
|
||||
iter = ratbagd_device_from_node(parent);
|
||||
v = strcmp(device->sysname, iter->sysname);
|
||||
|
||||
/* if there's a duplicate, the caller screwed up */
|
||||
assert(v != 0);
|
||||
|
||||
if (v < 0)
|
||||
node = &parent->left;
|
||||
else /* if (v > 0) */
|
||||
node = &parent->right;
|
||||
}
|
||||
|
||||
/* link into context */
|
||||
rbtree_add(&device->ctx->device_map, parent, node, &device->node);
|
||||
++device->ctx->n_devices;
|
||||
|
||||
/* register profile interfaces */
|
||||
r = sd_bus_path_encode_many(&prefix,
|
||||
RATBAGD_OBJ_ROOT "/profile/%",
|
||||
device->sysname);
|
||||
if (r >= 0) {
|
||||
r = sd_bus_add_fallback_vtable(device->ctx->bus,
|
||||
&device->profile_vtable_slot,
|
||||
prefix,
|
||||
RATBAGD_NAME_ROOT ".Profile",
|
||||
ratbagd_profile_vtable,
|
||||
ratbagd_device_find_profile,
|
||||
device);
|
||||
if (r >= 0)
|
||||
r = sd_bus_add_node_enumerator(device->ctx->bus,
|
||||
&device->profile_enum_slot,
|
||||
prefix,
|
||||
ratbagd_device_list_profiles,
|
||||
device);
|
||||
}
|
||||
if (r < 0) {
|
||||
errno = -r;
|
||||
log_error("%s: failed to register profile interfaces: %m\n",
|
||||
device->sysname);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < device->n_profiles; i++) {
|
||||
r = ratbagd_profile_register_resolutions(device->ctx->bus,
|
||||
device,
|
||||
device->profiles[i]);
|
||||
if (r < 0) {
|
||||
log_error("%s: failed to register resolutions: %m\n",
|
||||
device->sysname);
|
||||
}
|
||||
|
||||
r = ratbagd_profile_register_buttons(device->ctx->bus,
|
||||
device,
|
||||
device->profiles[i]);
|
||||
if (r < 0) {
|
||||
log_error("%s: failed to register buttons: %m\n",
|
||||
device->sysname);
|
||||
}
|
||||
|
||||
r = ratbagd_profile_register_leds(device->ctx->bus,
|
||||
device,
|
||||
device->profiles[i]);
|
||||
if (r < 0) {
|
||||
log_error("%s: failed to register leds: %m\n",
|
||||
device->sysname);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ratbagd_device_unlink(struct ratbagd_device *device)
|
||||
{
|
||||
if (!ratbagd_device_linked(device))
|
||||
return;
|
||||
|
||||
device->profile_enum_slot = sd_bus_slot_unref(device->profile_enum_slot);
|
||||
device->profile_vtable_slot = sd_bus_slot_unref(device->profile_vtable_slot);
|
||||
|
||||
/* unlink from context */
|
||||
--device->ctx->n_devices;
|
||||
rbtree_remove(&device->ctx->device_map, &device->node);
|
||||
rbnode_init(&device->node);
|
||||
}
|
||||
|
||||
struct ratbagd_device *ratbagd_device_lookup(struct ratbagd *ctx,
|
||||
const char *name)
|
||||
{
|
||||
struct ratbagd_device *device;
|
||||
RBNode *node;
|
||||
int v;
|
||||
|
||||
assert(ctx);
|
||||
assert(name);
|
||||
|
||||
node = ctx->device_map.root;
|
||||
while (node) {
|
||||
device = ratbagd_device_from_node(node);
|
||||
v = strcmp(name, device->sysname);
|
||||
if (!v)
|
||||
return device;
|
||||
else if (v < 0)
|
||||
node = node->left;
|
||||
else /* if (v > 0) */
|
||||
node = node->right;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct ratbagd_device *ratbagd_device_first(struct ratbagd *ctx)
|
||||
{
|
||||
struct RBNode *node;
|
||||
|
||||
assert(ctx);
|
||||
|
||||
node = rbtree_first(&ctx->device_map);
|
||||
return node ? ratbagd_device_from_node(node) : NULL;
|
||||
}
|
||||
|
||||
struct ratbagd_device *ratbagd_device_next(struct ratbagd_device *device)
|
||||
{
|
||||
struct RBNode *node;
|
||||
|
||||
assert(device);
|
||||
|
||||
node = rbnode_next(&device->node);
|
||||
return node ? ratbagd_device_from_node(node) : NULL;
|
||||
}
|
||||
|
||||
int ratbagd_for_each_profile_signal(sd_bus *bus,
|
||||
struct ratbagd_device *device,
|
||||
int (*func)(sd_bus *bus,
|
||||
struct ratbagd_profile *profile))
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
for (size_t i = 0; rc == 0 && i < device->n_profiles; i++)
|
||||
rc = func(bus, device->profiles[i]);
|
||||
|
||||
return rc;
|
||||
}
|
||||
353
ratbagd/ratbagd-led.c
Normal file
@@ -0,0 +1,353 @@
|
||||
/***
|
||||
This file is part of ratbagd.
|
||||
|
||||
Copyright 2017 Jente Hidskes <hjdskes@gmail.com>.
|
||||
|
||||
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 <libratbag.h>
|
||||
#include <systemd/sd-bus.h>
|
||||
#include "ratbagd.h"
|
||||
#include "shared-macro.h"
|
||||
#include "libratbag-util.h"
|
||||
|
||||
struct ratbagd_led {
|
||||
struct ratbag_led *lib_led;
|
||||
unsigned int index;
|
||||
char *path;
|
||||
enum ratbag_led_colordepth colordepth;
|
||||
};
|
||||
|
||||
static int ratbagd_led_get_modes(sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
const char *property,
|
||||
sd_bus_message *reply,
|
||||
void *userdata,
|
||||
sd_bus_error *error)
|
||||
{
|
||||
struct ratbagd_led *led = userdata;
|
||||
enum ratbag_led_mode mode = 0;
|
||||
|
||||
CHECK_CALL(sd_bus_message_open_container(reply, 'a', "u"));
|
||||
|
||||
|
||||
while (mode <= RATBAG_LED_BREATHING) {
|
||||
if (ratbag_led_has_mode(led->lib_led, mode))
|
||||
CHECK_CALL(sd_bus_message_append(reply, "u", mode));
|
||||
mode++;
|
||||
}
|
||||
|
||||
CHECK_CALL(sd_bus_message_close_container(reply));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ratbagd_led_get_mode(sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
const char *property,
|
||||
sd_bus_message *reply,
|
||||
void *userdata,
|
||||
sd_bus_error *error)
|
||||
{
|
||||
struct ratbagd_led *led = userdata;
|
||||
enum ratbag_led_mode mode;
|
||||
|
||||
mode = ratbag_led_get_mode(led->lib_led);
|
||||
|
||||
verify_unsigned_int(mode);
|
||||
|
||||
CHECK_CALL(sd_bus_message_append(reply, "u", mode));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ratbagd_led_set_mode(sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
const char *property,
|
||||
sd_bus_message *m,
|
||||
void *userdata,
|
||||
sd_bus_error *error)
|
||||
{
|
||||
struct ratbagd_led *led = userdata;
|
||||
enum ratbag_led_mode mode;
|
||||
int r;
|
||||
|
||||
CHECK_CALL(sd_bus_message_read(m, "u", &mode));
|
||||
|
||||
r = ratbag_led_set_mode(led->lib_led, mode);
|
||||
|
||||
if (r == 0) {
|
||||
sd_bus *bus = sd_bus_message_get_bus(m);
|
||||
sd_bus_emit_properties_changed(bus,
|
||||
led->path,
|
||||
RATBAGD_NAME_ROOT ".Led",
|
||||
"Mode",
|
||||
NULL);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ratbagd_led_get_color(sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
const char *property,
|
||||
sd_bus_message *reply,
|
||||
void *userdata,
|
||||
sd_bus_error *error)
|
||||
{
|
||||
struct ratbagd_led *led = userdata;
|
||||
struct ratbag_color c;
|
||||
|
||||
c = ratbag_led_get_color(led->lib_led);
|
||||
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,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
const char *property,
|
||||
sd_bus_message *m,
|
||||
void *userdata,
|
||||
sd_bus_error *error)
|
||||
{
|
||||
struct ratbagd_led *led = userdata;
|
||||
struct ratbag_color c;
|
||||
int r;
|
||||
|
||||
CHECK_CALL(sd_bus_message_read(m, "(uuu)", &c.red, &c.green, &c.blue));
|
||||
|
||||
if (c.red > 255)
|
||||
c.red = 255;
|
||||
if (c.green > 255)
|
||||
c.green = 255;
|
||||
if (c.blue > 255)
|
||||
c.blue = 255;
|
||||
|
||||
r = ratbag_led_set_color(led->lib_led, c);
|
||||
|
||||
if (r == 0) {
|
||||
sd_bus *bus = sd_bus_message_get_bus(m);
|
||||
sd_bus_emit_properties_changed(bus,
|
||||
led->path,
|
||||
RATBAGD_NAME_ROOT ".Led",
|
||||
"Color",
|
||||
NULL);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ratbagd_led_get_effect_duration(sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
const char *property,
|
||||
sd_bus_message *reply,
|
||||
void *userdata,
|
||||
sd_bus_error *error)
|
||||
{
|
||||
struct ratbagd_led *led = userdata;
|
||||
int rate;
|
||||
|
||||
rate = ratbag_led_get_effect_duration(led->lib_led);
|
||||
|
||||
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,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
const char *property,
|
||||
sd_bus_message *m,
|
||||
void *userdata,
|
||||
sd_bus_error *error)
|
||||
{
|
||||
struct ratbagd_led *led = userdata;
|
||||
unsigned int rate;
|
||||
int r;
|
||||
|
||||
CHECK_CALL(sd_bus_message_read(m, "u", &rate));
|
||||
|
||||
if (rate > 10000)
|
||||
rate = 10000;
|
||||
|
||||
r = ratbag_led_set_effect_duration(led->lib_led, rate);
|
||||
|
||||
if (r == 0) {
|
||||
sd_bus *bus = sd_bus_message_get_bus(m);
|
||||
sd_bus_emit_properties_changed(bus,
|
||||
led->path,
|
||||
RATBAGD_NAME_ROOT ".Led",
|
||||
"EffectDuration",
|
||||
NULL);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ratbagd_led_get_brightness(sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
const char *property,
|
||||
sd_bus_message *reply,
|
||||
void *userdata,
|
||||
sd_bus_error *error)
|
||||
{
|
||||
struct ratbagd_led *led = userdata;
|
||||
unsigned int brightness;
|
||||
|
||||
brightness = ratbag_led_get_brightness(led->lib_led);
|
||||
|
||||
verify_unsigned_int(brightness);
|
||||
|
||||
CHECK_CALL(sd_bus_message_append(reply, "u", brightness));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ratbagd_led_set_brightness(sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
const char *property,
|
||||
sd_bus_message *m,
|
||||
void *userdata,
|
||||
sd_bus_error *error)
|
||||
{
|
||||
struct ratbagd_led *led = userdata;
|
||||
unsigned int brightness;
|
||||
int r;
|
||||
|
||||
CHECK_CALL(sd_bus_message_read(m, "u", &brightness));
|
||||
|
||||
if (brightness > 255)
|
||||
brightness = 255;
|
||||
|
||||
r = ratbag_led_set_brightness(led->lib_led, brightness);
|
||||
|
||||
if (r == 0) {
|
||||
sd_bus *bus = sd_bus_message_get_bus(m);
|
||||
sd_bus_emit_properties_changed(bus,
|
||||
led->path,
|
||||
RATBAGD_NAME_ROOT ".Led",
|
||||
"Brightness",
|
||||
NULL);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const sd_bus_vtable ratbagd_led_vtable[] = {
|
||||
SD_BUS_VTABLE_START(0),
|
||||
SD_BUS_PROPERTY("Index", "u", NULL, offsetof(struct ratbagd_led, index), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("Modes", "au", ratbagd_led_get_modes, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_WRITABLE_PROPERTY("Mode", "u",
|
||||
ratbagd_led_get_mode,
|
||||
ratbagd_led_set_mode, 0,
|
||||
SD_BUS_VTABLE_UNPRIVILEGED|SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||
SD_BUS_WRITABLE_PROPERTY("Color", "(uuu)",
|
||||
ratbagd_led_get_color, ratbagd_led_set_color, 0,
|
||||
SD_BUS_VTABLE_UNPRIVILEGED|SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||
SD_BUS_PROPERTY("ColorDepth", "u", NULL, offsetof(struct ratbagd_led, colordepth), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_WRITABLE_PROPERTY("EffectDuration", "u",
|
||||
ratbagd_led_get_effect_duration, ratbagd_led_set_effect_duration, 0,
|
||||
SD_BUS_VTABLE_UNPRIVILEGED|SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||
SD_BUS_WRITABLE_PROPERTY("Brightness", "u",
|
||||
ratbagd_led_get_brightness, ratbagd_led_set_brightness, 0,
|
||||
SD_BUS_VTABLE_UNPRIVILEGED|SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||
SD_BUS_VTABLE_END,
|
||||
};
|
||||
|
||||
int ratbagd_led_new(struct ratbagd_led **out,
|
||||
struct ratbagd_device *device,
|
||||
struct ratbagd_profile *profile,
|
||||
struct ratbag_led *lib_led,
|
||||
unsigned int index)
|
||||
{
|
||||
_cleanup_(ratbagd_led_freep) struct ratbagd_led *led = NULL;
|
||||
char profile_buffer[DECIMAL_TOKEN_MAX(unsigned int) + 1],
|
||||
led_buffer[DECIMAL_TOKEN_MAX(unsigned int) + 1];
|
||||
int r;
|
||||
|
||||
assert(out);
|
||||
assert(lib_led);
|
||||
|
||||
led = zalloc(sizeof(*led));
|
||||
led->lib_led = lib_led;
|
||||
led->index = index;
|
||||
led->colordepth = ratbag_led_get_colordepth(lib_led);
|
||||
|
||||
sprintf(profile_buffer, "p%u", ratbagd_profile_get_index(profile));
|
||||
sprintf(led_buffer, "l%u", index);
|
||||
r = sd_bus_path_encode_many(&led->path,
|
||||
RATBAGD_OBJ_ROOT "/led/%/%/%",
|
||||
ratbagd_device_get_sysname(device),
|
||||
profile_buffer,
|
||||
led_buffer);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*out = led;
|
||||
led = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *ratbagd_led_get_path(struct ratbagd_led *led)
|
||||
{
|
||||
assert(led);
|
||||
return led->path;
|
||||
}
|
||||
|
||||
struct ratbagd_led *ratbagd_led_free(struct ratbagd_led *led)
|
||||
{
|
||||
if (!led)
|
||||
return NULL;
|
||||
|
||||
led->path = mfree(led->path);
|
||||
led->lib_led = ratbag_led_unref(led->lib_led);
|
||||
|
||||
return mfree(led);
|
||||
}
|
||||
|
||||
int ratbagd_led_resync(sd_bus *bus,
|
||||
struct ratbagd_led *led)
|
||||
{
|
||||
return sd_bus_emit_properties_changed(bus,
|
||||
led->path,
|
||||
RATBAGD_NAME_ROOT ".Led",
|
||||
"Mode",
|
||||
"Color",
|
||||
"EffectDuration",
|
||||
"Brightness",
|
||||
NULL);
|
||||
}
|
||||
938
ratbagd/ratbagd-profile.c
Normal file
@@ -0,0 +1,938 @@
|
||||
/***
|
||||
This file is part of ratbagd.
|
||||
|
||||
Copyright 2015 David Herrmann <dh.herrmann@gmail.com>
|
||||
|
||||
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 <libratbag.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <systemd/sd-bus.h>
|
||||
#include <systemd/sd-event.h>
|
||||
#include "ratbagd.h"
|
||||
#include "libratbag-util.h"
|
||||
#include "shared-macro.h"
|
||||
#include "libratbag-util.h"
|
||||
|
||||
struct ratbagd_profile {
|
||||
struct ratbagd_device *device;
|
||||
struct ratbag_profile *lib_profile;
|
||||
unsigned int index;
|
||||
char *path;
|
||||
|
||||
sd_bus_slot *resolution_vtable_slot;
|
||||
sd_bus_slot *resolution_enum_slot;
|
||||
unsigned int n_resolutions;
|
||||
struct ratbagd_resolution **resolutions;
|
||||
|
||||
sd_bus_slot *button_vtable_slot;
|
||||
sd_bus_slot *button_enum_slot;
|
||||
unsigned int n_buttons;
|
||||
struct ratbagd_button **buttons;
|
||||
|
||||
sd_bus_slot *led_vtable_slot;
|
||||
sd_bus_slot *led_enum_slot;
|
||||
unsigned int n_leds;
|
||||
struct ratbagd_led **leds;
|
||||
};
|
||||
|
||||
static int ratbagd_profile_find_resolution(sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
void *userdata,
|
||||
void **found,
|
||||
sd_bus_error *error)
|
||||
{
|
||||
_cleanup_(freep) char *name = NULL;
|
||||
struct ratbagd_profile *profile = userdata;
|
||||
unsigned int index = 0;
|
||||
int r;
|
||||
|
||||
r = sd_bus_path_decode_many(path,
|
||||
RATBAGD_OBJ_ROOT "/resolution/%/p%/r%",
|
||||
NULL,
|
||||
NULL,
|
||||
&name);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
r = safe_atou(name, &index);
|
||||
if (r < 0)
|
||||
return 0;
|
||||
|
||||
if (index >= profile->n_resolutions || !profile->resolutions[index])
|
||||
return 0;
|
||||
|
||||
*found = profile->resolutions[index];
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int ratbagd_profile_get_resolutions(sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
const char *property,
|
||||
sd_bus_message *reply,
|
||||
void *userdata,
|
||||
sd_bus_error *error)
|
||||
{
|
||||
struct ratbagd_profile *profile = userdata;
|
||||
struct ratbagd_resolution *resolution;
|
||||
unsigned int i;
|
||||
|
||||
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;
|
||||
|
||||
CHECK_CALL(sd_bus_message_append(reply,
|
||||
"o",
|
||||
ratbagd_resolution_get_path(resolution)));
|
||||
}
|
||||
|
||||
CHECK_CALL(sd_bus_message_close_container(reply));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ratbagd_profile_get_buttons(sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
const char *property,
|
||||
sd_bus_message *reply,
|
||||
void *userdata,
|
||||
sd_bus_error *error)
|
||||
{
|
||||
struct ratbagd_profile *profile = userdata;
|
||||
struct ratbagd_button *button;
|
||||
unsigned int i;
|
||||
|
||||
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;
|
||||
|
||||
CHECK_CALL(sd_bus_message_append(reply,
|
||||
"o",
|
||||
ratbagd_button_get_path(button)));
|
||||
}
|
||||
|
||||
CHECK_CALL(sd_bus_message_close_container(reply));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ratbagd_profile_get_leds(sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
const char *property,
|
||||
sd_bus_message *reply,
|
||||
void *userdata,
|
||||
sd_bus_error *error)
|
||||
{
|
||||
struct ratbagd_profile *profile = userdata;
|
||||
struct ratbagd_led *led;
|
||||
unsigned int i;
|
||||
|
||||
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;
|
||||
|
||||
CHECK_CALL(sd_bus_message_append(reply,
|
||||
"o",
|
||||
ratbagd_led_get_path(led)));
|
||||
}
|
||||
|
||||
CHECK_CALL(sd_bus_message_close_container(reply));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ratbagd_profile_is_active(sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
const char *property,
|
||||
sd_bus_message *reply,
|
||||
void *userdata,
|
||||
sd_bus_error *error)
|
||||
{
|
||||
struct ratbagd_profile *profile = userdata;
|
||||
int is_active;
|
||||
|
||||
is_active = ratbag_profile_is_active(profile->lib_profile);
|
||||
|
||||
CHECK_CALL(sd_bus_message_append(reply, "b", is_active));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ratbagd_profile_find_button(sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
void *userdata,
|
||||
void **found,
|
||||
sd_bus_error *error)
|
||||
{
|
||||
_cleanup_(freep) char *name = NULL;
|
||||
struct ratbagd_profile *profile = userdata;
|
||||
unsigned int index = 0;
|
||||
int r;
|
||||
|
||||
r = sd_bus_path_decode_many(path,
|
||||
RATBAGD_OBJ_ROOT "/button/%/p%/b%",
|
||||
NULL,
|
||||
NULL,
|
||||
&name);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
r = safe_atou(name, &index);
|
||||
if (r < 0)
|
||||
return 0;
|
||||
|
||||
if (index >= profile->n_buttons || !profile->buttons[index])
|
||||
return 0;
|
||||
|
||||
*found = profile->buttons[index];
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int ratbagd_profile_find_led(sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
void *userdata,
|
||||
void **found,
|
||||
sd_bus_error *error)
|
||||
{
|
||||
_cleanup_(freep) char *name = NULL;
|
||||
struct ratbagd_profile *profile = userdata;
|
||||
unsigned int index = 0;
|
||||
int r;
|
||||
|
||||
r = sd_bus_path_decode_many(path,
|
||||
RATBAGD_OBJ_ROOT "/led/%/p%/l%",
|
||||
NULL,
|
||||
NULL,
|
||||
&name);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
r = safe_atou(name, &index);
|
||||
if (r < 0)
|
||||
return 0;
|
||||
|
||||
if (index >= profile->n_leds || !profile->leds[index])
|
||||
return 0;
|
||||
|
||||
*found = profile->leds[index];
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int ratbagd_profile_active_signal_cb(sd_bus *bus,
|
||||
struct ratbagd_profile *profile)
|
||||
{
|
||||
/* FIXME: we should cache is active and only send the signal for
|
||||
* those profiles where it changed */
|
||||
(void) sd_bus_emit_properties_changed(bus,
|
||||
profile->path,
|
||||
RATBAGD_NAME_ROOT ".Profile",
|
||||
"IsActive",
|
||||
NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ratbagd_profile_set_active(sd_bus_message *m,
|
||||
void *userdata,
|
||||
sd_bus_error *error)
|
||||
{
|
||||
struct ratbagd_profile *profile = userdata;
|
||||
int r;
|
||||
|
||||
CHECK_CALL(sd_bus_message_read(m, ""));
|
||||
|
||||
r = ratbag_profile_set_active(profile->lib_profile);
|
||||
if (r < 0) {
|
||||
sd_bus *bus = sd_bus_message_get_bus(m);
|
||||
r = ratbagd_device_resync(profile->device, bus);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
ratbagd_for_each_profile_signal(sd_bus_message_get_bus(m),
|
||||
profile->device,
|
||||
ratbagd_profile_active_signal_cb);
|
||||
|
||||
CHECK_CALL(sd_bus_reply_method_return(m, "u", 0));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ratbagd_profile_set_enabled(sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
const char *property,
|
||||
sd_bus_message *m,
|
||||
void *userdata,
|
||||
sd_bus_error *error)
|
||||
{
|
||||
struct ratbagd_profile *profile = userdata;
|
||||
int enabled;
|
||||
int r;
|
||||
|
||||
CHECK_CALL(sd_bus_message_read(m, "b", &enabled));
|
||||
|
||||
r = ratbag_profile_set_enabled(profile->lib_profile, enabled);
|
||||
if (r == 0) {
|
||||
sd_bus *bus = sd_bus_message_get_bus(m);
|
||||
sd_bus_emit_properties_changed(bus,
|
||||
profile->path,
|
||||
RATBAGD_NAME_ROOT ".Profile",
|
||||
"Enabled",
|
||||
NULL);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ratbagd_profile_is_enabled(sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
const char *property,
|
||||
sd_bus_message *reply,
|
||||
void *userdata,
|
||||
sd_bus_error *error)
|
||||
{
|
||||
struct ratbagd_profile *profile = userdata;
|
||||
int enabled = ratbag_profile_is_enabled(profile->lib_profile) != 0;
|
||||
|
||||
CHECK_CALL(sd_bus_message_append(reply, "b", enabled));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ratbagd_profile_set_name(sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
const char *property,
|
||||
sd_bus_message *m,
|
||||
void *userdata,
|
||||
sd_bus_error *error)
|
||||
{
|
||||
struct ratbagd_profile *profile = userdata;
|
||||
char *name;
|
||||
int r;
|
||||
|
||||
CHECK_CALL(sd_bus_message_read(m, "s", &name));
|
||||
|
||||
r = ratbag_profile_set_name(profile->lib_profile, name);
|
||||
|
||||
if (r == 0) {
|
||||
sd_bus_emit_properties_changed(bus,
|
||||
profile->path,
|
||||
RATBAGD_NAME_ROOT ".Profile",
|
||||
"Name",
|
||||
NULL);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ratbagd_profile_get_name(sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
const char *property,
|
||||
sd_bus_message *reply,
|
||||
void *userdata,
|
||||
sd_bus_error *error)
|
||||
{
|
||||
struct ratbagd_profile *profile = userdata;
|
||||
const char *name = ratbag_profile_get_name(profile->lib_profile);
|
||||
_cleanup_free_ char *asciiname;
|
||||
|
||||
if (!name)
|
||||
asciiname = strdup("");
|
||||
else
|
||||
/* This should really be a UTF8 check and it should really be in
|
||||
* libratbag, but for now this will do to at least not kick us off
|
||||
* the bus. https://github.com/libratbag/libratbag/issues/617
|
||||
*/
|
||||
asciiname = strdup_ascii_only(name);
|
||||
|
||||
CHECK_CALL(sd_bus_message_append(reply, "s", asciiname));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ratbagd_profile_get_capabilities(sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
const char *property,
|
||||
sd_bus_message *reply,
|
||||
void *userdata,
|
||||
sd_bus_error *error)
|
||||
{
|
||||
struct ratbagd_profile *profile = userdata;
|
||||
struct ratbag_profile *lib_profile = profile->lib_profile;
|
||||
enum ratbag_profile_capability cap;
|
||||
enum ratbag_profile_capability caps[] = {
|
||||
RATBAG_PROFILE_CAP_SET_DEFAULT,
|
||||
RATBAG_PROFILE_CAP_DISABLE,
|
||||
};
|
||||
size_t i;
|
||||
|
||||
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)) {
|
||||
CHECK_CALL(sd_bus_message_append(reply, "u", cap));
|
||||
}
|
||||
}
|
||||
|
||||
CHECK_CALL(sd_bus_message_close_container(reply));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ratbagd_profile_get_report_rate(sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
const char *property,
|
||||
sd_bus_message *reply,
|
||||
void *userdata,
|
||||
sd_bus_error *error)
|
||||
{
|
||||
struct ratbagd_profile *profile = userdata;
|
||||
struct ratbag_profile *lib_profile = profile->lib_profile;
|
||||
int rate;
|
||||
|
||||
rate = ratbag_profile_get_report_rate(lib_profile);
|
||||
verify_unsigned_int(rate);
|
||||
return sd_bus_message_append(reply, "u", rate);
|
||||
}
|
||||
|
||||
static int
|
||||
ratbagd_profile_get_report_rates(sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
const char *property,
|
||||
sd_bus_message *reply,
|
||||
void *userdata,
|
||||
sd_bus_error *error)
|
||||
{
|
||||
struct ratbagd_profile *profile = userdata;
|
||||
struct ratbag_profile *lib_profile = profile->lib_profile;
|
||||
unsigned int rates[8];
|
||||
unsigned int nrates = ARRAY_LENGTH(rates);
|
||||
int r;
|
||||
|
||||
r = sd_bus_message_open_container(reply, 'a', "u");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
nrates = ratbag_profile_get_report_rate_list(lib_profile,
|
||||
rates, nrates);
|
||||
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;
|
||||
}
|
||||
|
||||
return sd_bus_message_close_container(reply);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
ratbagd_profile_set_report_rate(sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
const char *property,
|
||||
sd_bus_message *m,
|
||||
void *userdata,
|
||||
sd_bus_error *error)
|
||||
{
|
||||
struct ratbagd_profile *profile = userdata;
|
||||
unsigned int rate;
|
||||
int r;
|
||||
|
||||
r = sd_bus_message_read(m, "u", &rate);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* basic sanity check */
|
||||
if (rate > 5000)
|
||||
rate = 5000;
|
||||
else if (rate % 100)
|
||||
rate = rate - (rate % 100);
|
||||
|
||||
r = ratbag_profile_set_report_rate(profile->lib_profile, rate);
|
||||
if (r == 0) {
|
||||
sd_bus *bus = sd_bus_message_get_bus(m);
|
||||
sd_bus_emit_properties_changed(bus,
|
||||
profile->path,
|
||||
RATBAGD_NAME_ROOT ".Profile",
|
||||
"ReportRate",
|
||||
NULL);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const sd_bus_vtable ratbagd_profile_vtable[] = {
|
||||
SD_BUS_VTABLE_START(0),
|
||||
SD_BUS_WRITABLE_PROPERTY("Name", "s",
|
||||
ratbagd_profile_get_name,
|
||||
ratbagd_profile_set_name, 0,
|
||||
SD_BUS_VTABLE_UNPRIVILEGED|SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||
SD_BUS_WRITABLE_PROPERTY("Enabled", "b",
|
||||
ratbagd_profile_is_enabled,
|
||||
ratbagd_profile_set_enabled, 0,
|
||||
SD_BUS_VTABLE_UNPRIVILEGED|SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||
SD_BUS_PROPERTY("Index", "u", NULL, offsetof(struct ratbagd_profile, index), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("Capabilities", "au", ratbagd_profile_get_capabilities, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("Resolutions", "ao", ratbagd_profile_get_resolutions, 0, 0),
|
||||
SD_BUS_PROPERTY("Buttons", "ao", ratbagd_profile_get_buttons, 0, 0),
|
||||
SD_BUS_PROPERTY("Leds", "ao", ratbagd_profile_get_leds, 0, 0),
|
||||
SD_BUS_PROPERTY("IsActive", "b", ratbagd_profile_is_active, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||
SD_BUS_WRITABLE_PROPERTY("ReportRate", "u",
|
||||
ratbagd_profile_get_report_rate,
|
||||
ratbagd_profile_set_report_rate, 0,
|
||||
SD_BUS_VTABLE_UNPRIVILEGED|SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||
SD_BUS_PROPERTY("ReportRates", "au", ratbagd_profile_get_report_rates, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_METHOD("SetActive", "", "u", ratbagd_profile_set_active, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_VTABLE_END,
|
||||
};
|
||||
|
||||
int ratbagd_profile_new(struct ratbagd_profile **out,
|
||||
struct ratbagd_device *device,
|
||||
struct ratbag_profile *lib_profile,
|
||||
unsigned int index)
|
||||
{
|
||||
_cleanup_(ratbagd_profile_freep) struct ratbagd_profile *profile = NULL;
|
||||
struct ratbag_resolution *resolution;
|
||||
struct ratbag_button *button;
|
||||
struct ratbag_led *led;
|
||||
char index_buffer[DECIMAL_TOKEN_MAX(unsigned int) + 1];
|
||||
unsigned int i;
|
||||
int r;
|
||||
|
||||
assert(out);
|
||||
assert(lib_profile);
|
||||
|
||||
profile = zalloc(sizeof(*profile));
|
||||
|
||||
profile->device = device;
|
||||
profile->lib_profile = lib_profile;
|
||||
profile->index = index;
|
||||
|
||||
sprintf(index_buffer, "p%u", index);
|
||||
r = sd_bus_path_encode_many(&profile->path,
|
||||
RATBAGD_OBJ_ROOT "/profile/%/%",
|
||||
ratbagd_device_get_sysname(device),
|
||||
index_buffer);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
profile->n_resolutions = ratbag_profile_get_num_resolutions(profile->lib_profile);
|
||||
profile->resolutions = zalloc(profile->n_resolutions * sizeof(*profile->resolutions));
|
||||
|
||||
profile->n_buttons = ratbagd_device_get_num_buttons(device);
|
||||
profile->buttons = zalloc(profile->n_buttons * sizeof(*profile->buttons));
|
||||
|
||||
profile->n_leds = ratbagd_device_get_num_leds(device);
|
||||
profile->leds = zalloc(profile->n_leds * sizeof(*profile->leds));
|
||||
|
||||
for (i = 0; i < profile->n_resolutions; ++i) {
|
||||
resolution = ratbag_profile_get_resolution(profile->lib_profile, i);
|
||||
if (!resolution)
|
||||
continue;
|
||||
|
||||
r = ratbagd_resolution_new(&profile->resolutions[i],
|
||||
device,
|
||||
profile,
|
||||
resolution,
|
||||
i);
|
||||
if (r < 0) {
|
||||
errno = -r;
|
||||
log_error("%s: failed to allocate resolution: %m\n",
|
||||
ratbagd_device_get_sysname(device));
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < profile->n_buttons; ++i) {
|
||||
button = ratbag_profile_get_button(profile->lib_profile, i);
|
||||
if (!button)
|
||||
continue;
|
||||
|
||||
r = ratbagd_button_new(&profile->buttons[i],
|
||||
device,
|
||||
profile,
|
||||
button,
|
||||
i);
|
||||
if (r < 0) {
|
||||
errno = -r;
|
||||
log_error("%s: failed to allocate button: %m\n",
|
||||
ratbagd_device_get_sysname(device));
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < profile->n_leds; ++i) {
|
||||
led = ratbag_profile_get_led(profile->lib_profile, i);
|
||||
if (!led)
|
||||
continue;
|
||||
|
||||
r = ratbagd_led_new(&profile->leds[i],
|
||||
device,
|
||||
profile,
|
||||
led,
|
||||
i);
|
||||
if (r < 0) {
|
||||
errno = -r;
|
||||
log_error("%s: failed to allocate led: %m\n",
|
||||
ratbagd_device_get_sysname(device));
|
||||
}
|
||||
}
|
||||
|
||||
*out = profile;
|
||||
profile = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct ratbagd_profile *ratbagd_profile_free(struct ratbagd_profile *profile)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (!profile)
|
||||
return NULL;
|
||||
|
||||
profile->resolution_vtable_slot = sd_bus_slot_unref(profile->resolution_vtable_slot);
|
||||
profile->resolution_enum_slot = sd_bus_slot_unref(profile->resolution_enum_slot);
|
||||
profile->button_vtable_slot = sd_bus_slot_unref(profile->button_vtable_slot);
|
||||
profile->button_enum_slot = sd_bus_slot_unref(profile->button_enum_slot);
|
||||
profile->led_vtable_slot = sd_bus_slot_unref(profile->led_vtable_slot);
|
||||
profile->led_enum_slot = sd_bus_slot_unref(profile->led_enum_slot);
|
||||
|
||||
for (i = 0; i< profile->n_leds; ++i)
|
||||
ratbagd_led_free(profile->leds[i]);
|
||||
for (i = 0; i< profile->n_buttons; ++i)
|
||||
ratbagd_button_free(profile->buttons[i]);
|
||||
for (i = 0; i< profile->n_resolutions; ++i)
|
||||
ratbagd_resolution_free(profile->resolutions[i]);
|
||||
|
||||
mfree(profile->leds);
|
||||
mfree(profile->buttons);
|
||||
mfree(profile->resolutions);
|
||||
|
||||
profile->path = mfree(profile->path);
|
||||
profile->lib_profile = ratbag_profile_unref(profile->lib_profile);
|
||||
|
||||
return mfree(profile);
|
||||
}
|
||||
|
||||
const char *ratbagd_profile_get_path(struct ratbagd_profile *profile)
|
||||
{
|
||||
assert(profile);
|
||||
return profile->path;
|
||||
}
|
||||
|
||||
unsigned int ratbagd_profile_get_index(struct ratbagd_profile *profile)
|
||||
{
|
||||
assert(profile);
|
||||
return profile->index;
|
||||
}
|
||||
|
||||
static int ratbagd_profile_list_resolutions(sd_bus *bus,
|
||||
const char *path,
|
||||
void *userdata,
|
||||
char ***paths,
|
||||
sd_bus_error *error)
|
||||
{
|
||||
struct ratbagd_profile *profile = userdata;
|
||||
struct ratbagd_resolution *resolution;
|
||||
char **resolutions;
|
||||
unsigned int i;
|
||||
|
||||
resolutions = zalloc((profile->n_resolutions + 1) * sizeof(char *));
|
||||
|
||||
for (i = 0; i < profile->n_resolutions; ++i) {
|
||||
resolution = profile->resolutions[i];
|
||||
if (!resolution)
|
||||
continue;
|
||||
|
||||
resolutions[i] = strdup_safe(ratbagd_resolution_get_path(resolution));
|
||||
}
|
||||
|
||||
resolutions[i] = NULL;
|
||||
*paths = resolutions;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int ratbagd_profile_register_resolutions(struct sd_bus *bus,
|
||||
struct ratbagd_device *device,
|
||||
struct ratbagd_profile *profile)
|
||||
{
|
||||
_cleanup_(freep) char *prefix = NULL;
|
||||
char index_buffer[DECIMAL_TOKEN_MAX(unsigned int) + 1];
|
||||
int r;
|
||||
|
||||
sprintf(index_buffer, "p%u", profile->index);
|
||||
|
||||
/* register resolution interfaces */
|
||||
r = sd_bus_path_encode_many(&prefix,
|
||||
RATBAGD_OBJ_ROOT "/resolution/%/%",
|
||||
ratbagd_device_get_sysname(device),
|
||||
index_buffer);
|
||||
|
||||
if (r >= 0) {
|
||||
r = sd_bus_add_fallback_vtable(bus,
|
||||
&profile->resolution_vtable_slot,
|
||||
prefix,
|
||||
RATBAGD_NAME_ROOT ".Resolution",
|
||||
ratbagd_resolution_vtable,
|
||||
ratbagd_profile_find_resolution,
|
||||
profile);
|
||||
if (r >= 0)
|
||||
r = sd_bus_add_node_enumerator(bus,
|
||||
&profile->resolution_enum_slot,
|
||||
prefix,
|
||||
ratbagd_profile_list_resolutions,
|
||||
profile);
|
||||
}
|
||||
if (r < 0) {
|
||||
errno = -r;
|
||||
log_error("%s: failed to register resolutions: %m\n",
|
||||
ratbagd_device_get_sysname(device));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ratbagd_profile_list_buttons(sd_bus *bus,
|
||||
const char *path,
|
||||
void *userdata,
|
||||
char ***paths,
|
||||
sd_bus_error *error)
|
||||
{
|
||||
struct ratbagd_profile *profile = userdata;
|
||||
struct ratbagd_button *button;
|
||||
char **buttons;
|
||||
unsigned int i;
|
||||
|
||||
buttons = zalloc((profile->n_buttons + 1) * sizeof(char *));
|
||||
|
||||
for (i = 0; i < profile->n_buttons; ++i) {
|
||||
button = profile->buttons[i];
|
||||
if (!button)
|
||||
continue;
|
||||
|
||||
buttons[i] = strdup_safe(ratbagd_button_get_path(button));
|
||||
}
|
||||
|
||||
buttons[i] = NULL;
|
||||
*paths = buttons;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ratbagd_profile_register_buttons(struct sd_bus *bus,
|
||||
struct ratbagd_device *device,
|
||||
struct ratbagd_profile *profile)
|
||||
{
|
||||
_cleanup_(freep) char *prefix = NULL;
|
||||
char index_buffer[DECIMAL_TOKEN_MAX(unsigned int) + 1];
|
||||
int r;
|
||||
|
||||
sprintf(index_buffer, "p%u", profile->index);
|
||||
|
||||
/* register button interfaces */
|
||||
r = sd_bus_path_encode_many(&prefix,
|
||||
RATBAGD_OBJ_ROOT "/button/%/%",
|
||||
ratbagd_device_get_sysname(device),
|
||||
index_buffer);
|
||||
|
||||
if (r >= 0) {
|
||||
r = sd_bus_add_fallback_vtable(bus,
|
||||
&profile->button_vtable_slot,
|
||||
prefix,
|
||||
RATBAGD_NAME_ROOT ".Button",
|
||||
ratbagd_button_vtable,
|
||||
ratbagd_profile_find_button,
|
||||
profile);
|
||||
if (r >= 0)
|
||||
r = sd_bus_add_node_enumerator(bus,
|
||||
&profile->button_enum_slot,
|
||||
prefix,
|
||||
ratbagd_profile_list_buttons,
|
||||
profile);
|
||||
}
|
||||
if (r < 0) {
|
||||
errno = -r;
|
||||
log_error("%s: failed to register buttons: %m\n",
|
||||
ratbagd_device_get_sysname(device));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ratbagd_profile_list_leds(sd_bus *bus,
|
||||
const char *path,
|
||||
void *userdata,
|
||||
char ***paths,
|
||||
sd_bus_error *error)
|
||||
{
|
||||
struct ratbagd_profile *profile = userdata;
|
||||
struct ratbagd_led *led;
|
||||
char **leds;
|
||||
unsigned int i;
|
||||
|
||||
leds = zalloc((profile->n_leds + 1) * sizeof(char *));
|
||||
|
||||
for (i = 0; i < profile->n_leds; ++i) {
|
||||
led = profile->leds[i];
|
||||
if (!led)
|
||||
continue;
|
||||
|
||||
leds[i] = strdup_safe(ratbagd_led_get_path(led));
|
||||
}
|
||||
|
||||
leds[i] = NULL;
|
||||
*paths = leds;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ratbagd_profile_register_leds(struct sd_bus *bus,
|
||||
struct ratbagd_device *device,
|
||||
struct ratbagd_profile *profile)
|
||||
{
|
||||
_cleanup_(freep) char *prefix = NULL;
|
||||
char index_buffer[DECIMAL_TOKEN_MAX(unsigned int) + 1];
|
||||
int r;
|
||||
|
||||
sprintf(index_buffer, "p%u", profile->index);
|
||||
|
||||
/* register led interfaces */
|
||||
r = sd_bus_path_encode_many(&prefix,
|
||||
RATBAGD_OBJ_ROOT "/led/%/%",
|
||||
ratbagd_device_get_sysname(device),
|
||||
index_buffer);
|
||||
|
||||
if (r >= 0) {
|
||||
r = sd_bus_add_fallback_vtable(bus,
|
||||
&profile->led_vtable_slot,
|
||||
prefix,
|
||||
RATBAGD_NAME_ROOT ".Led",
|
||||
ratbagd_led_vtable,
|
||||
ratbagd_profile_find_led,
|
||||
profile);
|
||||
if (r >= 0)
|
||||
r = sd_bus_add_node_enumerator(bus,
|
||||
&profile->led_enum_slot,
|
||||
prefix,
|
||||
ratbagd_profile_list_leds,
|
||||
profile);
|
||||
}
|
||||
if (r < 0) {
|
||||
errno = -r;
|
||||
log_error("%s: failed to register leds: %m\n",
|
||||
ratbagd_device_get_sysname(device));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ratbagd_for_each_resolution_signal(sd_bus *bus,
|
||||
struct ratbagd_profile *profile,
|
||||
int (*func)(sd_bus *bus,
|
||||
struct ratbagd_resolution *resolution))
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
for (size_t i = 0; rc == 0 && i < profile->n_resolutions; i++)
|
||||
rc = func(bus, profile->resolutions[i]);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int ratbagd_for_each_button_signal(sd_bus *bus,
|
||||
struct ratbagd_profile *profile,
|
||||
int (*func)(sd_bus *bus,
|
||||
struct ratbagd_button *button))
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
for (size_t i = 0; rc == 0 && i < profile->n_buttons; i++)
|
||||
rc = func(bus, profile->buttons[i]);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int ratbagd_for_each_led_signal(sd_bus *bus,
|
||||
struct ratbagd_profile *profile,
|
||||
int (*func)(sd_bus *bus,
|
||||
struct ratbagd_led *button))
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
for (size_t i = 0; rc == 0 && i < profile->n_leds; i++)
|
||||
rc = func(bus, profile->leds[i]);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
int ratbagd_profile_resync(sd_bus *bus,
|
||||
struct ratbagd_profile *profile)
|
||||
{
|
||||
ratbagd_for_each_resolution_signal(bus, profile, ratbagd_resolution_resync);
|
||||
ratbagd_for_each_button_signal(bus, profile, ratbagd_button_resync);
|
||||
ratbagd_for_each_led_signal(bus, profile, ratbagd_led_resync);
|
||||
|
||||
return sd_bus_emit_properties_changed(bus,
|
||||
profile->path,
|
||||
RATBAGD_NAME_ROOT ".Profile",
|
||||
"Resolutions",
|
||||
"Buttons",
|
||||
"Leds",
|
||||
"IsActive",
|
||||
NULL);
|
||||
}
|
||||
335
ratbagd/ratbagd-resolution.c
Normal file
@@ -0,0 +1,335 @@
|
||||
/***
|
||||
This file is part of ratbagd.
|
||||
|
||||
Copyright 2016 Red Hat, Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice (including the next
|
||||
paragraph) shall be included in all copies or substantial portions of the
|
||||
Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
***/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <libratbag.h>
|
||||
#include <libudev.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <systemd/sd-bus.h>
|
||||
#include <systemd/sd-event.h>
|
||||
#include "ratbagd.h"
|
||||
#include "shared-macro.h"
|
||||
#include "libratbag-util.h"
|
||||
|
||||
struct ratbagd_resolution {
|
||||
struct ratbagd_device *device;
|
||||
struct ratbagd_profile *profile;
|
||||
struct ratbag_resolution *lib_resolution;
|
||||
unsigned int index;
|
||||
char *path;
|
||||
};
|
||||
|
||||
int ratbagd_resolution_resync(sd_bus *bus,
|
||||
struct ratbagd_resolution *resolution)
|
||||
{
|
||||
return sd_bus_emit_properties_changed(bus,
|
||||
resolution->path,
|
||||
RATBAGD_NAME_ROOT ".Resolution",
|
||||
"IsDefault",
|
||||
"Resolution",
|
||||
"ReportRate",
|
||||
"IsActive",
|
||||
NULL);
|
||||
}
|
||||
|
||||
static int ratbagd_resolution_active_signal_cb(sd_bus *bus,
|
||||
struct ratbagd_resolution *resolution)
|
||||
{
|
||||
/* FIXME: we should cache is_active and only send the signal for
|
||||
* those resolutions where it changed */
|
||||
|
||||
(void) sd_bus_emit_properties_changed(bus,
|
||||
resolution->path,
|
||||
RATBAGD_NAME_ROOT ".Resolution",
|
||||
"IsActive",
|
||||
NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ratbagd_resolution_set_active(sd_bus_message *m,
|
||||
void *userdata,
|
||||
sd_bus_error *error)
|
||||
{
|
||||
struct ratbagd_resolution *resolution = userdata;
|
||||
int r;
|
||||
|
||||
r = ratbag_resolution_set_active(resolution->lib_resolution);
|
||||
if (r < 0) {
|
||||
sd_bus *bus = sd_bus_message_get_bus(m);
|
||||
r = ratbagd_device_resync(resolution->device, bus);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
ratbagd_for_each_resolution_signal(sd_bus_message_get_bus(m),
|
||||
resolution->profile,
|
||||
ratbagd_resolution_active_signal_cb);
|
||||
|
||||
return sd_bus_reply_method_return(m, "u", 0);
|
||||
}
|
||||
|
||||
static int ratbagd_resolution_default_signal_cb(sd_bus *bus,
|
||||
struct ratbagd_resolution *resolution)
|
||||
{
|
||||
/* FIXME: we should cache is default and only send the signal for
|
||||
* those resolutions where it changed */
|
||||
|
||||
(void) sd_bus_emit_properties_changed(bus,
|
||||
resolution->path,
|
||||
RATBAGD_NAME_ROOT ".Resolution",
|
||||
"IsDefault",
|
||||
NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ratbagd_resolution_set_default(sd_bus_message *m,
|
||||
void *userdata,
|
||||
sd_bus_error *error)
|
||||
{
|
||||
struct ratbagd_resolution *resolution = userdata;
|
||||
int r;
|
||||
|
||||
r = ratbag_resolution_set_default(resolution->lib_resolution);
|
||||
if (r < 0) {
|
||||
sd_bus *bus = sd_bus_message_get_bus(m);
|
||||
r = ratbagd_device_resync(resolution->device, bus);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
ratbagd_for_each_resolution_signal(sd_bus_message_get_bus(m),
|
||||
resolution->profile,
|
||||
ratbagd_resolution_default_signal_cb);
|
||||
|
||||
return sd_bus_reply_method_return(m, "u", 0);
|
||||
}
|
||||
|
||||
static int
|
||||
ratbagd_resolution_is_active(sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
const char *property,
|
||||
sd_bus_message *reply,
|
||||
void *userdata,
|
||||
sd_bus_error *error)
|
||||
{
|
||||
struct ratbagd_resolution *resolution = userdata;
|
||||
struct ratbag_resolution *lib_resolution = resolution->lib_resolution;
|
||||
int is_active;
|
||||
|
||||
is_active = ratbag_resolution_is_active(lib_resolution);
|
||||
|
||||
return sd_bus_message_append(reply, "b", is_active);
|
||||
}
|
||||
|
||||
static int
|
||||
ratbagd_resolution_is_default(sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
const char *property,
|
||||
sd_bus_message *reply,
|
||||
void *userdata,
|
||||
sd_bus_error *error)
|
||||
{
|
||||
struct ratbagd_resolution *resolution = userdata;
|
||||
struct ratbag_resolution *lib_resolution = resolution->lib_resolution;
|
||||
int is_default;
|
||||
|
||||
is_default = ratbag_resolution_is_default(lib_resolution);
|
||||
|
||||
return sd_bus_message_append(reply, "b", is_default);
|
||||
}
|
||||
|
||||
static int
|
||||
ratbagd_resolution_get_resolutions(sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
const char *property,
|
||||
sd_bus_message *reply,
|
||||
void *userdata,
|
||||
sd_bus_error *error)
|
||||
{
|
||||
struct ratbagd_resolution *resolution = userdata;
|
||||
struct ratbag_resolution *lib_resolution = resolution->lib_resolution;
|
||||
unsigned int dpis[300];
|
||||
unsigned int ndpis = ARRAY_LENGTH(dpis);
|
||||
int r;
|
||||
|
||||
r = sd_bus_message_open_container(reply, 'a', "u");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
ndpis = ratbag_resolution_get_dpi_list(lib_resolution,
|
||||
dpis, ndpis);
|
||||
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;
|
||||
}
|
||||
|
||||
return sd_bus_message_close_container(reply);
|
||||
}
|
||||
|
||||
static int
|
||||
ratbagd_resolution_get_resolution(sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
const char *property,
|
||||
sd_bus_message *reply,
|
||||
void *userdata,
|
||||
sd_bus_error *error)
|
||||
{
|
||||
struct ratbagd_resolution *resolution = userdata;
|
||||
struct ratbag_resolution *lib_resolution = resolution->lib_resolution;
|
||||
int xres, yres;
|
||||
|
||||
|
||||
xres = ratbag_resolution_get_dpi_x(lib_resolution);
|
||||
yres = ratbag_resolution_get_dpi_y(lib_resolution);
|
||||
|
||||
verify_unsigned_int(xres);
|
||||
verify_unsigned_int(yres);
|
||||
|
||||
if (ratbag_resolution_has_capability(lib_resolution,
|
||||
RATBAG_RESOLUTION_CAP_SEPARATE_XY_RESOLUTION))
|
||||
return sd_bus_message_append(reply, "v", "(uu)", xres, yres);
|
||||
else
|
||||
return sd_bus_message_append(reply, "v", "u", xres);
|
||||
}
|
||||
|
||||
static int
|
||||
ratbagd_resolution_set_resolution(sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
const char *property,
|
||||
sd_bus_message *m,
|
||||
void *userdata,
|
||||
sd_bus_error *error)
|
||||
{
|
||||
struct ratbagd_resolution *resolution = userdata;
|
||||
struct ratbag_resolution *lib_resolution = resolution->lib_resolution;
|
||||
const enum ratbag_resolution_capability cap = RATBAG_RESOLUTION_CAP_SEPARATE_XY_RESOLUTION;
|
||||
int xres, yres;
|
||||
int r;
|
||||
|
||||
if (ratbag_resolution_has_capability(lib_resolution, cap)) {
|
||||
CHECK_CALL(sd_bus_message_read(m, "v", "(uu)", &xres, &yres));
|
||||
r = ratbag_resolution_set_dpi_xy(resolution->lib_resolution,
|
||||
xres, yres);
|
||||
} else {
|
||||
CHECK_CALL(sd_bus_message_read(m, "v", "u", &xres));
|
||||
r = ratbag_resolution_set_dpi(resolution->lib_resolution, xres);
|
||||
}
|
||||
|
||||
if (r == 0) {
|
||||
sd_bus *bus = sd_bus_message_get_bus(m);
|
||||
sd_bus_emit_properties_changed(bus,
|
||||
resolution->path,
|
||||
RATBAGD_NAME_ROOT ".Resolution",
|
||||
"Resolution",
|
||||
NULL);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const sd_bus_vtable ratbagd_resolution_vtable[] = {
|
||||
SD_BUS_VTABLE_START(0),
|
||||
SD_BUS_PROPERTY("Index", "u", NULL, offsetof(struct ratbagd_resolution, index), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("IsActive", "b", ratbagd_resolution_is_active, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||
SD_BUS_PROPERTY("IsDefault", "b", ratbagd_resolution_is_default, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||
SD_BUS_WRITABLE_PROPERTY("Resolution", "v",
|
||||
ratbagd_resolution_get_resolution,
|
||||
ratbagd_resolution_set_resolution, 0,
|
||||
SD_BUS_VTABLE_UNPRIVILEGED|SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||
SD_BUS_PROPERTY("Resolutions", "au", ratbagd_resolution_get_resolutions, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_METHOD("SetActive", "", "u", ratbagd_resolution_set_active, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("SetDefault", "", "u", ratbagd_resolution_set_default, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_VTABLE_END,
|
||||
};
|
||||
|
||||
int ratbagd_resolution_new(struct ratbagd_resolution **out,
|
||||
struct ratbagd_device *device,
|
||||
struct ratbagd_profile *profile,
|
||||
struct ratbag_resolution *lib_resolution,
|
||||
unsigned int index)
|
||||
{
|
||||
_cleanup_(ratbagd_resolution_freep) struct ratbagd_resolution *resolution = NULL;
|
||||
char profile_buffer[DECIMAL_TOKEN_MAX(unsigned int) + 1],
|
||||
resolution_buffer[DECIMAL_TOKEN_MAX(unsigned int) + 1];
|
||||
int r;
|
||||
|
||||
assert(out);
|
||||
assert(lib_resolution);
|
||||
|
||||
resolution = calloc(1, sizeof(*resolution));
|
||||
if (!resolution)
|
||||
return -ENOMEM;
|
||||
|
||||
resolution->device = device;
|
||||
resolution->profile = profile;
|
||||
resolution->lib_resolution = lib_resolution;
|
||||
resolution->index = index;
|
||||
|
||||
sprintf(profile_buffer, "p%u", ratbagd_profile_get_index(profile));
|
||||
sprintf(resolution_buffer, "r%u", index);
|
||||
r = sd_bus_path_encode_many(&resolution->path,
|
||||
RATBAGD_OBJ_ROOT "/resolution/%/%/%",
|
||||
ratbagd_device_get_sysname(device),
|
||||
profile_buffer,
|
||||
resolution_buffer);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*out = resolution;
|
||||
resolution = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *ratbagd_resolution_get_path(struct ratbagd_resolution *resolution)
|
||||
{
|
||||
assert(resolution);
|
||||
return resolution->path;
|
||||
}
|
||||
|
||||
struct ratbagd_resolution *ratbagd_resolution_free(struct ratbagd_resolution *resolution)
|
||||
{
|
||||
if (!resolution)
|
||||
return NULL;
|
||||
|
||||
resolution->path = mfree(resolution->path);
|
||||
resolution->lib_resolution = ratbag_resolution_unref(resolution->lib_resolution);
|
||||
|
||||
return mfree(resolution);
|
||||
}
|
||||
229
ratbagd/ratbagd-test.c
Normal file
@@ -0,0 +1,229 @@
|
||||
/*
|
||||
* Copyright © 2017 Red Hat, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "ratbagd-test.h"
|
||||
|
||||
#ifdef RATBAG_DEVELOPER_EDITION
|
||||
|
||||
#include <linux/input.h>
|
||||
#include <systemd/sd-bus.h>
|
||||
#include <systemd/sd-event.h>
|
||||
|
||||
#include "libratbag-test.h"
|
||||
|
||||
/* A pre-setup sane device. Use for sanity testing by toggling the various
|
||||
* error conditions.
|
||||
*/
|
||||
static const struct ratbag_test_device ratbagd_test_device_descr = {
|
||||
.num_profiles = 4,
|
||||
.num_resolutions = 3,
|
||||
.num_buttons = 4,
|
||||
.num_leds = 3,
|
||||
.profiles = {
|
||||
{
|
||||
.name = NULL,
|
||||
.buttons = {
|
||||
{ .button_type = RATBAG_BUTTON_TYPE_LEFT,
|
||||
.action_type = RATBAG_BUTTON_ACTION_TYPE_BUTTON,
|
||||
.button = 0 },
|
||||
{ .button_type = RATBAG_BUTTON_TYPE_MIDDLE,
|
||||
.action_type = RATBAG_BUTTON_ACTION_TYPE_KEY,
|
||||
.key = KEY_3 },
|
||||
{ .button_type = RATBAG_BUTTON_TYPE_RIGHT,
|
||||
.action_type = RATBAG_BUTTON_ACTION_TYPE_SPECIAL,
|
||||
.special = RATBAG_BUTTON_ACTION_SPECIAL_PROFILE_CYCLE_UP },
|
||||
{ .action_type = RATBAG_BUTTON_ACTION_TYPE_MACRO,
|
||||
.macro = {
|
||||
{ .type = RATBAG_MACRO_EVENT_KEY_PRESSED,
|
||||
.value = KEY_B },
|
||||
{ .type = RATBAG_MACRO_EVENT_KEY_RELEASED,
|
||||
.value = KEY_B },
|
||||
{ .type = RATBAG_MACRO_EVENT_WAIT,
|
||||
.value = 300 },
|
||||
},
|
||||
}
|
||||
},
|
||||
.resolutions = {
|
||||
{ .xres = 100, .yres = 200,
|
||||
.dpi_min = 50, .dpi_max = 5000},
|
||||
{ .xres = 200, .yres = 300, .active = true, .dflt = true },
|
||||
{ .xres = 300, .yres = 400 },
|
||||
},
|
||||
.active = true,
|
||||
.dflt = false,
|
||||
.hz = 1000,
|
||||
.report_rates = {500, 1000},
|
||||
|
||||
.leds = {
|
||||
{
|
||||
.mode = RATBAG_LED_OFF,
|
||||
.color = { .red = 255, .green = 0, .blue = 0 },
|
||||
.ms = 1000,
|
||||
.brightness = 20,
|
||||
.type = RATBAG_LED_TYPE_LOGO,
|
||||
},
|
||||
{
|
||||
.mode = RATBAG_LED_ON,
|
||||
.color = { .red = 255, .green = 0, .blue = 0 },
|
||||
.ms = 1000,
|
||||
.brightness = 20,
|
||||
.type = RATBAG_LED_TYPE_SIDE,
|
||||
},
|
||||
{
|
||||
.mode = RATBAG_LED_CYCLE,
|
||||
.color = { .red = 255, .green = 255, .blue = 0 },
|
||||
.ms = 333,
|
||||
.brightness = 40,
|
||||
.type = RATBAG_LED_TYPE_SIDE,
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
.buttons = {
|
||||
{ .action_type = RATBAG_BUTTON_ACTION_TYPE_KEY,
|
||||
.key = 4 },
|
||||
{ .action_type = RATBAG_BUTTON_ACTION_TYPE_KEY,
|
||||
.key = 5 },
|
||||
{ .action_type = RATBAG_BUTTON_ACTION_TYPE_KEY,
|
||||
.key = 6 },
|
||||
{ .action_type = RATBAG_BUTTON_ACTION_TYPE_KEY,
|
||||
.key = 7 },
|
||||
},
|
||||
.resolutions = {
|
||||
{ .xres = 1100, .yres = 1200, .caps = RATBAG_RESOLUTION_CAP_SEPARATE_XY_RESOLUTION },
|
||||
{ .xres = 1200, .yres = 1300, .dflt = true, .caps = RATBAG_RESOLUTION_CAP_SEPARATE_XY_RESOLUTION },
|
||||
{ .xres = 1300, .yres = 1400, .active = true, .caps = RATBAG_RESOLUTION_CAP_SEPARATE_XY_RESOLUTION },
|
||||
},
|
||||
.hz = 2000,
|
||||
.active = false,
|
||||
.dflt = true,
|
||||
.name = "test profile 2",
|
||||
},
|
||||
{
|
||||
.buttons = {
|
||||
{ .button_type = RATBAG_BUTTON_TYPE_LEFT,
|
||||
.action_type = RATBAG_BUTTON_ACTION_TYPE_SPECIAL,
|
||||
.special = RATBAG_BUTTON_ACTION_SPECIAL_PROFILE_CYCLE_UP },
|
||||
{ .action_type = RATBAG_BUTTON_ACTION_TYPE_MACRO,
|
||||
.macro = {
|
||||
{ .type = RATBAG_MACRO_EVENT_KEY_PRESSED,
|
||||
.value = KEY_A },
|
||||
{ .type = RATBAG_MACRO_EVENT_KEY_RELEASED,
|
||||
.value = KEY_A },
|
||||
{ .type = RATBAG_MACRO_EVENT_WAIT,
|
||||
.value = 150 },
|
||||
}
|
||||
},
|
||||
{ .action_type = RATBAG_BUTTON_ACTION_TYPE_BUTTON,
|
||||
.button = 2 },
|
||||
{ .action_type = RATBAG_BUTTON_ACTION_TYPE_BUTTON,
|
||||
.button = 3 },
|
||||
},
|
||||
.resolutions = {
|
||||
{ .xres = 2100, .yres = 2200, .active = true, .caps = RATBAG_RESOLUTION_CAP_SEPARATE_XY_RESOLUTION },
|
||||
{ .xres = 2200, .yres = 2300, .dflt = true, .caps = RATBAG_RESOLUTION_CAP_SEPARATE_XY_RESOLUTION },
|
||||
{ .xres = 2300, .yres = 2400, .caps = RATBAG_RESOLUTION_CAP_SEPARATE_XY_RESOLUTION },
|
||||
},
|
||||
.hz = 3000,
|
||||
.leds = {
|
||||
{
|
||||
.mode = RATBAG_LED_ON,
|
||||
.color = { .red = 255, .green = 0, .blue = 0 },
|
||||
.ms = 1000,
|
||||
.brightness = 20
|
||||
},
|
||||
{
|
||||
.mode = RATBAG_LED_CYCLE,
|
||||
.color = { .red = 255, .green = 255, .blue = 0 },
|
||||
.ms = 333,
|
||||
.brightness = 40
|
||||
}
|
||||
},
|
||||
.active = false,
|
||||
.dflt = false,
|
||||
},
|
||||
{
|
||||
.disabled = true,
|
||||
},
|
||||
},
|
||||
.destroyed = NULL,
|
||||
.destroyed_data = NULL,
|
||||
};
|
||||
|
||||
|
||||
int ratbagd_reset_test_device(sd_bus_message *m,
|
||||
void *userdata,
|
||||
sd_bus_error *error)
|
||||
{
|
||||
static struct ratbagd_device *ratbagd_test_device = NULL;
|
||||
struct ratbagd *ctx = userdata;
|
||||
struct ratbag_device *device;
|
||||
int r;
|
||||
|
||||
if (ratbagd_test_device) {
|
||||
ratbagd_device_unlink(ratbagd_test_device);
|
||||
ratbagd_device_free(ratbagd_test_device);
|
||||
|
||||
(void) sd_bus_emit_properties_changed(ctx->bus,
|
||||
RATBAGD_OBJ_ROOT,
|
||||
RATBAGD_NAME_ROOT ".Manager",
|
||||
"Devices",
|
||||
NULL);
|
||||
}
|
||||
|
||||
device = ratbag_device_new_test_device(ctx->lib_ctx, &ratbagd_test_device_descr);
|
||||
|
||||
r = ratbagd_device_new(&ratbagd_test_device, ctx, "test_device", device);
|
||||
|
||||
/* the ratbagd_device takes its own reference, drop ours */
|
||||
ratbag_device_unref(device);
|
||||
|
||||
if (r < 0) {
|
||||
log_error("Cannot track test device\n");
|
||||
return r;
|
||||
}
|
||||
|
||||
ratbagd_device_link(ratbagd_test_device);
|
||||
if (m) {
|
||||
sd_bus_reply_method_return(m, "u", r);
|
||||
(void) sd_bus_emit_properties_changed(ctx->bus,
|
||||
RATBAGD_OBJ_ROOT,
|
||||
RATBAGD_NAME_ROOT ".Manager",
|
||||
"Devices",
|
||||
NULL);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void ratbagd_init_test_device(struct ratbagd *ctx)
|
||||
{
|
||||
#ifdef RATBAG_DEVELOPER_EDITION
|
||||
setenv("RATBAG_TEST", "1", 0);
|
||||
|
||||
ratbagd_reset_test_device(NULL, ctx, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2013 Jonas Ådahl
|
||||
* Copyright © 2017 Red Hat, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
@@ -21,12 +21,15 @@
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef LIBRATBAG_VERSION_H
|
||||
#define LIBRATBAG_VERSION_H
|
||||
#pragma once
|
||||
|
||||
#define LIBRATBAG_VERSION_MAJOR @LIBRATBAG_VERSION_MAJOR@
|
||||
#define LIBRATBAG_VERSION_MINOR @LIBRATBAG_VERSION_MINOR@
|
||||
#define LIBRATBAG_VERSION_MICRO @LIBRATBAG_VERSION_MICRO@
|
||||
#define LIBRATBAG_VERSION "@LIBRATBAG_VERSION@"
|
||||
#include "libratbag-test.h"
|
||||
#include "ratbagd.h"
|
||||
|
||||
#endif
|
||||
void ratbagd_init_test_device(struct ratbagd *ctx);
|
||||
|
||||
#ifdef RATBAG_DEVELOPER_EDITION
|
||||
int ratbagd_reset_test_device(sd_bus_message *m,
|
||||
void *userdata,
|
||||
sd_bus_error *error);
|
||||
#endif /* RATBAG_DEVELOPER_EDITION */
|
||||
19
ratbagd/ratbagd.8
Normal file
@@ -0,0 +1,19 @@
|
||||
.TH ratbagd 8 "Apr 13, 2016" ratbagd
|
||||
.SH NAME
|
||||
ratbagd \- system daemon to introspect and modify configurable mice
|
||||
.SH SYNOPSIS
|
||||
.B ratbagd
|
||||
.RB [ \-\-verbose ]
|
||||
.SH DESCRIPTION
|
||||
.B ratbagd
|
||||
starts the daemon. It shouldn't be invoked directly;
|
||||
.B ratbagd
|
||||
is normally started through DBus activation.
|
||||
.SH SEE ALSO
|
||||
.BR ratbagctl (1)
|
||||
.SH AUTHORS
|
||||
.B ratbagd
|
||||
was written by David Herrmann, Peter Hutterer and Benjamin Tissoires.
|
||||
.PP
|
||||
This manual page was written by Stephen Kitt <skitt@debian.org> for
|
||||
the Debian GNU/Linux system (but may be used by others).
|
||||
607
ratbagd/ratbagd.c
Normal file
@@ -0,0 +1,607 @@
|
||||
/***
|
||||
This file is part of ratbagd.
|
||||
|
||||
Copyright 2015 David Herrmann <dh.herrmann@gmail.com>
|
||||
|
||||
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 <linux/input-event-codes.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <libratbag.h>
|
||||
#include <libudev.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/resource.h>
|
||||
#include <systemd/sd-bus.h>
|
||||
#include <systemd/sd-event.h>
|
||||
#include "ratbagd.h"
|
||||
#include "shared-macro.h"
|
||||
#include "libratbag-util.h"
|
||||
|
||||
#include "ratbagd-test.h"
|
||||
|
||||
enum log_level {
|
||||
LL_QUIET = 1,
|
||||
LL_INFO,
|
||||
LL_VERBOSE,
|
||||
LL_RAW,
|
||||
} log_level = LL_INFO;
|
||||
|
||||
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 (log_level >= LL_VERBOSE)
|
||||
vprintf(fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void log_error(const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start(args, fmt);
|
||||
fprintf(stderr, "%s error: ", program_invocation_short_name);
|
||||
vfprintf(stderr, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
static int ratbagd_find_device(sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
void *userdata,
|
||||
void **found,
|
||||
sd_bus_error *error)
|
||||
{
|
||||
_cleanup_(freep) char *name = NULL;
|
||||
struct ratbagd *ctx = userdata;
|
||||
struct ratbagd_device *device;
|
||||
int r;
|
||||
|
||||
r = sd_bus_path_decode_many(path,
|
||||
RATBAGD_OBJ_ROOT "/device/%",
|
||||
&name);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
device = ratbagd_device_lookup(ctx, name);
|
||||
if (!device)
|
||||
return 0;
|
||||
|
||||
*found = device;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int ratbagd_list_devices(sd_bus *bus,
|
||||
const char *path,
|
||||
void *userdata,
|
||||
char ***paths,
|
||||
sd_bus_error *error)
|
||||
{
|
||||
struct ratbagd *ctx = userdata;
|
||||
struct ratbagd_device *device;
|
||||
char **devices, **pos;
|
||||
|
||||
devices = calloc(ctx->n_devices + 1, sizeof(char *));
|
||||
if (!devices)
|
||||
return -ENOMEM;
|
||||
|
||||
pos = devices;
|
||||
|
||||
RATBAGD_DEVICE_FOREACH(device, ctx) {
|
||||
*pos = strdup(ratbagd_device_get_path(device));
|
||||
if (!*pos)
|
||||
goto error;
|
||||
++pos;
|
||||
}
|
||||
|
||||
*pos = NULL;
|
||||
*paths = devices;
|
||||
return 1;
|
||||
|
||||
error:
|
||||
for (pos = devices; *pos; ++pos)
|
||||
free(*pos);
|
||||
free(devices);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
static int ratbagd_get_devices(sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
const char *property,
|
||||
sd_bus_message *reply,
|
||||
void *userdata,
|
||||
sd_bus_error *error)
|
||||
{
|
||||
struct ratbagd *ctx = userdata;
|
||||
struct ratbagd_device *device;
|
||||
|
||||
CHECK_CALL(sd_bus_message_open_container(reply, 'a', "o"));
|
||||
|
||||
RATBAGD_DEVICE_FOREACH(device, ctx) {
|
||||
CHECK_CALL(sd_bus_message_append(reply,
|
||||
"o",
|
||||
ratbagd_device_get_path(device)));
|
||||
}
|
||||
|
||||
CHECK_CALL(sd_bus_message_close_container(reply));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const sd_bus_vtable ratbagd_vtable[] = {
|
||||
SD_BUS_VTABLE_START(0),
|
||||
SD_BUS_PROPERTY("Devices", "ao", ratbagd_get_devices, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||
#ifdef RATBAG_DEVELOPER_EDITION
|
||||
SD_BUS_METHOD("ResetTestDevice", "", "u", ratbagd_reset_test_device, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
#endif /* RATBAG_DEVELOPER_EDITION */
|
||||
SD_BUS_VTABLE_END,
|
||||
};
|
||||
|
||||
static void ratbagd_process_device(struct ratbagd *ctx,
|
||||
struct udev_device *udevice)
|
||||
{
|
||||
struct ratbag_device *lib_device;
|
||||
struct ratbagd_device *device;
|
||||
const char *sysname;
|
||||
int r;
|
||||
|
||||
/*
|
||||
* TODO: libratbag should provide some mechanism to allow
|
||||
* device-grouping, just like libinput does. If multiple input
|
||||
* devices belong to the same virtual device, we should not add
|
||||
* it multiple times. Instead, libratbag should group them and
|
||||
* provide *us* a unique sysname that identifies the group, rather
|
||||
* than taking a random input-device as tag.
|
||||
*/
|
||||
|
||||
sysname = udev_device_get_sysname(udevice);
|
||||
if (!sysname || !startswith(sysname, "hidraw"))
|
||||
return;
|
||||
|
||||
device = ratbagd_device_lookup(ctx, sysname);
|
||||
|
||||
if (streq_ptr("remove", udev_device_get_action(udevice))) {
|
||||
/* device was removed, unlink it and destroy our context */
|
||||
if (device) {
|
||||
ratbagd_device_unlink(device);
|
||||
ratbagd_device_free(device);
|
||||
|
||||
(void) sd_bus_emit_properties_changed(ctx->bus,
|
||||
RATBAGD_OBJ_ROOT,
|
||||
RATBAGD_NAME_ROOT ".Manager",
|
||||
"Devices",
|
||||
NULL);
|
||||
}
|
||||
} else if (device) {
|
||||
/* device already known, refresh our view of the device */
|
||||
} else {
|
||||
enum ratbag_error_code error;
|
||||
|
||||
/* device unknown, create new one and link it */
|
||||
error = ratbag_device_new_from_udev_device(ctx->lib_ctx,
|
||||
udevice,
|
||||
&lib_device);
|
||||
if (error != RATBAG_SUCCESS)
|
||||
return; /* unsupported device */
|
||||
|
||||
r = ratbagd_device_new(&device, ctx, sysname, lib_device);
|
||||
|
||||
/* the ratbagd_device takes its own reference, drop ours */
|
||||
ratbag_device_unref(lib_device);
|
||||
|
||||
if (r < 0) {
|
||||
log_error("%s: cannot track device\n", sysname);
|
||||
return;
|
||||
}
|
||||
|
||||
ratbagd_device_link(device);
|
||||
(void) sd_bus_emit_properties_changed(ctx->bus,
|
||||
RATBAGD_OBJ_ROOT,
|
||||
RATBAGD_NAME_ROOT ".Manager",
|
||||
"Devices",
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static int ratbagd_monitor_event(sd_event_source *source,
|
||||
int fd,
|
||||
uint32_t mask,
|
||||
void *userdata)
|
||||
{
|
||||
struct ratbagd *ctx = userdata;
|
||||
struct udev_device *udevice;
|
||||
|
||||
udevice = udev_monitor_receive_device(ctx->monitor);
|
||||
if (!udevice)
|
||||
return 0;
|
||||
|
||||
ratbagd_process_device(ctx, udevice);
|
||||
udev_device_unref(udevice);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ratbagd_lib_open_restricted(const char *path,
|
||||
int flags,
|
||||
void *userdata)
|
||||
{
|
||||
return open(path, flags, 0);
|
||||
}
|
||||
|
||||
static void ratbagd_lib_close_restricted(int fd, void *userdata)
|
||||
{
|
||||
safe_close(fd);
|
||||
}
|
||||
|
||||
static const struct ratbag_interface ratbagd_lib_interface = {
|
||||
.open_restricted = ratbagd_lib_open_restricted,
|
||||
.close_restricted = ratbagd_lib_close_restricted,
|
||||
};
|
||||
|
||||
static struct ratbagd *ratbagd_free(struct ratbagd *ctx)
|
||||
{
|
||||
struct ratbagd_device *device, *tmp;
|
||||
|
||||
if (!ctx)
|
||||
return NULL;
|
||||
|
||||
RATBAGD_DEVICE_FOREACH_SAFE(device, tmp, ctx) {
|
||||
ratbagd_device_unlink(device);
|
||||
ratbagd_device_free(device);
|
||||
}
|
||||
|
||||
ctx->bus = sd_bus_flush_close_unref(ctx->bus);
|
||||
ctx->monitor_source = sd_event_source_unref(ctx->monitor_source);
|
||||
ctx->monitor = udev_monitor_unref(ctx->monitor);
|
||||
ctx->lib_ctx = ratbag_unref(ctx->lib_ctx);
|
||||
ctx->event = sd_event_unref(ctx->event);
|
||||
|
||||
assert(!ctx->device_map.root);
|
||||
assert(!ctx->lib_ctx); /* ratbag returns non-NULL if still pinned */
|
||||
|
||||
return mfree(ctx);
|
||||
}
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(struct ratbagd *, ratbagd_free);
|
||||
|
||||
static int ratbagd_init_monitor(struct ratbagd *ctx)
|
||||
{
|
||||
struct udev *udev;
|
||||
int r;
|
||||
|
||||
udev = udev_new();
|
||||
if (!udev)
|
||||
return -ENOMEM;
|
||||
|
||||
ctx->monitor = udev_monitor_new_from_netlink(udev, "udev");
|
||||
|
||||
/* we don't need the context to stay around; drop it */
|
||||
udev_unref(udev);
|
||||
|
||||
if (!ctx->monitor)
|
||||
return -ENOMEM;
|
||||
|
||||
r = udev_monitor_filter_add_match_subsystem_devtype(ctx->monitor,
|
||||
"hidraw",
|
||||
NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = udev_monitor_enable_receiving(ctx->monitor);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_event_add_io(ctx->event,
|
||||
&ctx->monitor_source,
|
||||
udev_monitor_get_fd(ctx->monitor),
|
||||
EPOLLIN,
|
||||
ratbagd_monitor_event,
|
||||
ctx);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ratbagd_new(struct ratbagd **out)
|
||||
{
|
||||
_cleanup_(ratbagd_freep) struct ratbagd *ctx = NULL;
|
||||
int r;
|
||||
|
||||
ctx = zalloc(sizeof(*ctx));
|
||||
|
||||
r = sd_event_default(&ctx->event);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_event_set_watchdog(ctx->event, true);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
ctx->lib_ctx = ratbag_create_context(&ratbagd_lib_interface, ctx);
|
||||
if (!ctx->lib_ctx)
|
||||
return -ENOMEM;
|
||||
|
||||
if (log_level >= LL_RAW)
|
||||
ratbag_log_set_priority(ctx->lib_ctx,
|
||||
RATBAG_LOG_PRIORITY_RAW);
|
||||
else if (log_level >= LL_VERBOSE)
|
||||
ratbag_log_set_priority(ctx->lib_ctx,
|
||||
RATBAG_LOG_PRIORITY_DEBUG);
|
||||
|
||||
r = ratbagd_init_monitor(ctx);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_open_system(&ctx->bus);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_add_object_vtable(ctx->bus,
|
||||
NULL,
|
||||
RATBAGD_OBJ_ROOT,
|
||||
RATBAGD_NAME_ROOT ".Manager",
|
||||
ratbagd_vtable,
|
||||
ctx);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_add_fallback_vtable(ctx->bus,
|
||||
NULL,
|
||||
RATBAGD_OBJ_ROOT "/device",
|
||||
RATBAGD_NAME_ROOT ".Device",
|
||||
ratbagd_device_vtable,
|
||||
ratbagd_find_device,
|
||||
ctx);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_add_node_enumerator(ctx->bus,
|
||||
NULL,
|
||||
RATBAGD_OBJ_ROOT "/device",
|
||||
ratbagd_list_devices,
|
||||
ctx);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_request_name(ctx->bus, RATBAGD_NAME_ROOT, 0);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_attach_event(ctx->bus, ctx->event, 0);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*out = ctx;
|
||||
ctx = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ratbagd_run_enumerate(struct ratbagd *ctx)
|
||||
{
|
||||
struct udev_list_entry *list, *iter;
|
||||
struct udev_enumerate *e;
|
||||
struct udev *udev;
|
||||
int r;
|
||||
|
||||
udev = udev_monitor_get_udev(ctx->monitor);
|
||||
|
||||
e = udev_enumerate_new(udev);
|
||||
if (!e)
|
||||
return -ENOMEM;
|
||||
|
||||
r = udev_enumerate_add_match_subsystem(e, "hidraw");
|
||||
if (r < 0)
|
||||
goto exit;
|
||||
|
||||
r = udev_enumerate_add_match_is_initialized(e);
|
||||
if (r < 0)
|
||||
goto exit;
|
||||
|
||||
r = udev_enumerate_scan_devices(e);
|
||||
if (r < 0)
|
||||
goto exit;
|
||||
|
||||
list = udev_enumerate_get_list_entry(e);
|
||||
udev_list_entry_foreach(iter, list) {
|
||||
struct udev_device *udevice;
|
||||
const char *p;
|
||||
|
||||
p = udev_list_entry_get_name(iter);
|
||||
udevice = udev_device_new_from_syspath(udev, p);
|
||||
if (udevice)
|
||||
ratbagd_process_device(ctx, udevice);
|
||||
udev_device_unref(udevice);
|
||||
}
|
||||
|
||||
r = 0;
|
||||
|
||||
exit:
|
||||
udev_enumerate_unref(e);
|
||||
return r;
|
||||
}
|
||||
|
||||
static int on_timeout_cb(sd_event_source *s, uint64_t usec, void *userdata)
|
||||
{
|
||||
log_info("Exiting after idle\n");
|
||||
sd_event_exit(sd_event_source_get_event(s), 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int before_idle_cb(sd_event_source *s, void *userdata)
|
||||
{
|
||||
struct ratbagd *ctx = userdata;
|
||||
uint64_t usec;
|
||||
|
||||
sd_event_now(sd_event_source_get_event(s), CLOCK_MONOTONIC, &usec);
|
||||
#define min2us(us_) (us_ * 1000000 * 60)
|
||||
usec += min2us(20);
|
||||
sd_event_source_set_time(ctx->timeout_source, usec);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sighandler(sd_event_source *source,
|
||||
const struct signalfd_siginfo *si,
|
||||
void *userdata)
|
||||
{
|
||||
sd_event *event = sd_event_source_get_event(source);
|
||||
sd_event_exit(event, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ratbagd_run(struct ratbagd *ctx)
|
||||
{
|
||||
int r;
|
||||
|
||||
r = ratbagd_run_enumerate(ctx);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
sigset_t sigset;
|
||||
sigemptyset(&sigset);
|
||||
sigaddset(&sigset, SIGINT);
|
||||
sigprocmask(SIG_BLOCK, &sigset, NULL);
|
||||
sd_event_add_signal(ctx->event, NULL, SIGINT, sighandler, NULL);
|
||||
|
||||
/* exit-on-idle: we set up a timer to simply exit. Since we don't
|
||||
* store anything, it doesn't matter and we can just restart next
|
||||
* time someone wants us.
|
||||
*
|
||||
* since we don't want to monitor every single dbus call, we just
|
||||
* set up a post source that gets called before we go idle. That
|
||||
* resets the timer, so as long as something is happening, ratbagd
|
||||
* won't exit.
|
||||
*/
|
||||
sd_event_add_time(ctx->event,
|
||||
&ctx->timeout_source,
|
||||
CLOCK_MONOTONIC,
|
||||
-1, /* infinite, see before_idle_cb */
|
||||
min2us(1), /* accuracy doesn't matter */
|
||||
on_timeout_cb,
|
||||
ctx);
|
||||
sd_event_add_post(ctx->event, NULL, before_idle_cb, ctx);
|
||||
|
||||
return sd_event_loop(ctx->event);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct ratbagd *ctx = NULL;
|
||||
int r;
|
||||
|
||||
#if DISABLE_COREDUMP
|
||||
const struct rlimit corelimit = { 0, 0 };
|
||||
|
||||
setrlimit(RLIMIT_CORE, &corelimit);
|
||||
#endif
|
||||
|
||||
if (argc > 1) {
|
||||
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")) {
|
||||
log_level = LL_VERBOSE;
|
||||
} else {
|
||||
fprintf(stderr, "Usage: %s [--version | --quiet | --verbose[=raw]]\n",
|
||||
program_invocation_short_name);
|
||||
r = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
r = ratbagd_new(&ctx);
|
||||
if (r < 0)
|
||||
goto exit;
|
||||
|
||||
ratbagd_init_test_device(ctx);
|
||||
|
||||
r = ratbagd_run(ctx);
|
||||
|
||||
exit:
|
||||
ratbagd_free(ctx);
|
||||
|
||||
if (r < 0) {
|
||||
if (r == -EEXIST) {
|
||||
log_error("Bus name is taken, another instance of ratbagd is already running.\n");
|
||||
} else {
|
||||
errno = -r;
|
||||
log_error("Failed to start ratbagd: %m\n");
|
||||
}
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
struct ratbagd_callback
|
||||
{
|
||||
ratbagd_callback_t callback;
|
||||
void *userdata;
|
||||
};
|
||||
|
||||
static int ratbagd_callback_handler(sd_event_source *s, void *userdata)
|
||||
{
|
||||
struct ratbagd_callback *cb = userdata;
|
||||
|
||||
cb->callback(cb->userdata);
|
||||
|
||||
sd_event_source_set_enabled(s, SD_EVENT_OFF);
|
||||
sd_event_source_unref(s);
|
||||
free(cb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ratbagd_schedule_task(struct ratbagd *ctx,
|
||||
ratbagd_callback_t callback,
|
||||
void *userdata)
|
||||
{
|
||||
struct ratbagd_callback *cb = zalloc(sizeof *cb);
|
||||
sd_event_source *source;
|
||||
|
||||
cb->callback = callback;
|
||||
cb->userdata = userdata;
|
||||
|
||||
sd_event_add_post(ctx->event, &source, ratbagd_callback_handler, cb);
|
||||
}
|
||||
237
ratbagd/ratbagd.h
Normal file
@@ -0,0 +1,237 @@
|
||||
#pragma once
|
||||
|
||||
/***
|
||||
This file is part of ratbagd.
|
||||
|
||||
Copyright 2015 David Herrmann <dh.herrmann@gmail.com>
|
||||
|
||||
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 <libratbag.h>
|
||||
#include <libudev.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <systemd/sd-bus.h>
|
||||
#include <systemd/sd-event.h>
|
||||
#include "shared-macro.h"
|
||||
#include "shared-rbtree.h"
|
||||
|
||||
#ifndef RATBAG_DBUS_INTERFACE
|
||||
#define RATBAG_DBUS_INTERFACE "ratbag1"
|
||||
#else
|
||||
#define RATBAG_DEVELOPER_EDITION
|
||||
#endif
|
||||
|
||||
#define RATBAGD_OBJ_ROOT "/org/freedesktop/" RATBAG_DBUS_INTERFACE
|
||||
#define RATBAGD_NAME_ROOT "org.freedesktop." RATBAG_DBUS_INTERFACE
|
||||
|
||||
struct ratbagd;
|
||||
struct ratbagd_device;
|
||||
struct ratbagd_profile;
|
||||
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
|
||||
*/
|
||||
|
||||
extern const sd_bus_vtable ratbagd_profile_vtable[];
|
||||
|
||||
int ratbagd_profile_new(struct ratbagd_profile **out,
|
||||
struct ratbagd_device *device,
|
||||
struct ratbag_profile *lib_profile,
|
||||
unsigned int index);
|
||||
struct ratbagd_profile *ratbagd_profile_free(struct ratbagd_profile *profile);
|
||||
const char *ratbagd_profile_get_path(struct ratbagd_profile *profile);
|
||||
bool ratbagd_profile_is_default(struct ratbagd_profile *profile);
|
||||
unsigned int ratbagd_profile_get_index(struct ratbagd_profile *profile);
|
||||
int ratbagd_profile_register_resolutions(struct sd_bus *bus,
|
||||
struct ratbagd_device *device,
|
||||
struct ratbagd_profile *profile);
|
||||
int ratbagd_profile_register_buttons(struct sd_bus *bus,
|
||||
struct ratbagd_device *device,
|
||||
struct ratbagd_profile *profile);
|
||||
int ratbagd_profile_register_leds(struct sd_bus *bus,
|
||||
struct ratbagd_device *device,
|
||||
struct ratbagd_profile *profile);
|
||||
|
||||
int ratbagd_for_each_profile_signal(sd_bus *bus,
|
||||
struct ratbagd_device *device,
|
||||
int (*func)(sd_bus *bus,
|
||||
struct ratbagd_profile *profile));
|
||||
int ratbagd_for_each_resolution_signal(sd_bus *bus,
|
||||
struct ratbagd_profile *profile,
|
||||
int (*func)(sd_bus *bus,
|
||||
struct ratbagd_resolution *resolution));
|
||||
int ratbagd_for_each_button_signal(sd_bus *bus,
|
||||
struct ratbagd_profile *profile,
|
||||
int (*func)(sd_bus *bus,
|
||||
struct ratbagd_button *button));
|
||||
int ratbagd_for_each_led_signal(sd_bus *bus,
|
||||
struct ratbagd_profile *profile,
|
||||
int (*func)(sd_bus *bus,
|
||||
struct ratbagd_led *led));
|
||||
int ratbagd_profile_resync(sd_bus *bus, struct ratbagd_profile *profile);
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(struct ratbagd_profile *, ratbagd_profile_free);
|
||||
|
||||
/*
|
||||
* Resolutions
|
||||
*/
|
||||
extern const sd_bus_vtable ratbagd_resolution_vtable[];
|
||||
|
||||
int ratbagd_resolution_new(struct ratbagd_resolution **out,
|
||||
struct ratbagd_device *device,
|
||||
struct ratbagd_profile *profile,
|
||||
struct ratbag_resolution *lib_resolution,
|
||||
unsigned int index);
|
||||
struct ratbagd_resolution *ratbagd_resolution_free(struct ratbagd_resolution *resolution);
|
||||
const char *ratbagd_resolution_get_path(struct ratbagd_resolution *resolution);
|
||||
int ratbagd_resolution_resync(sd_bus *bus, struct ratbagd_resolution *resolution);
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(struct ratbagd_resolution *, ratbagd_resolution_free);
|
||||
|
||||
/*
|
||||
* Buttons
|
||||
*/
|
||||
extern const sd_bus_vtable ratbagd_button_vtable[];
|
||||
|
||||
int ratbagd_button_new(struct ratbagd_button **out,
|
||||
struct ratbagd_device *device,
|
||||
struct ratbagd_profile *profile,
|
||||
struct ratbag_button *lib_button,
|
||||
unsigned int index);
|
||||
struct ratbagd_button *ratbagd_button_free(struct ratbagd_button *button);
|
||||
const char *ratbagd_button_get_path(struct ratbagd_button *button);
|
||||
int ratbagd_button_resync(sd_bus *bus, struct ratbagd_button *button);
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(struct ratbagd_button *, ratbagd_button_free);
|
||||
|
||||
/*
|
||||
* Leds
|
||||
*/
|
||||
extern const sd_bus_vtable ratbagd_led_vtable[];
|
||||
|
||||
int ratbagd_led_new(struct ratbagd_led **out,
|
||||
struct ratbagd_device *device,
|
||||
struct ratbagd_profile *profile,
|
||||
struct ratbag_led *lib_led,
|
||||
unsigned int index);
|
||||
struct ratbagd_led *ratbagd_led_free(struct ratbagd_led *led);
|
||||
const char *ratbagd_led_get_path(struct ratbagd_led *led);
|
||||
int ratbagd_led_resync(sd_bus *bus, struct ratbagd_led *led);
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(struct ratbagd_led *, ratbagd_led_free);
|
||||
|
||||
/*
|
||||
* Devices
|
||||
*/
|
||||
|
||||
extern const sd_bus_vtable ratbagd_device_vtable[];
|
||||
|
||||
int ratbagd_device_new(struct ratbagd_device **out,
|
||||
struct ratbagd *ctx,
|
||||
const char *sysname,
|
||||
struct ratbag_device *lib_device);
|
||||
struct ratbagd_device *ratbagd_device_free(struct ratbagd_device *device);
|
||||
const char *ratbagd_device_get_sysname(struct ratbagd_device *device);
|
||||
const char *ratbagd_device_get_path(struct ratbagd_device *device);
|
||||
unsigned int ratbagd_device_get_num_buttons(struct ratbagd_device *device);
|
||||
unsigned int ratbagd_device_get_num_leds(struct ratbagd_device *device);
|
||||
int ratbagd_device_resync(struct ratbagd_device *device, sd_bus *bus);
|
||||
|
||||
bool ratbagd_device_linked(struct ratbagd_device *device);
|
||||
void ratbagd_device_link(struct ratbagd_device *device);
|
||||
void ratbagd_device_unlink(struct ratbagd_device *device);
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(struct ratbagd_device *, ratbagd_device_free);
|
||||
|
||||
struct ratbagd_device *ratbagd_device_lookup(struct ratbagd *ctx,
|
||||
const char *name);
|
||||
struct ratbagd_device *ratbagd_device_first(struct ratbagd *ctx);
|
||||
struct ratbagd_device *ratbagd_device_next(struct ratbagd_device *device);
|
||||
|
||||
#define RATBAGD_DEVICE_FOREACH(_device, _ctx) \
|
||||
for ((_device) = ratbagd_device_first(_ctx); \
|
||||
(_device); \
|
||||
(_device) = ratbagd_device_next(_device))
|
||||
|
||||
#define RATBAGD_DEVICE_FOREACH_SAFE(_device, _safe, _ctx) \
|
||||
for (_device = ratbagd_device_first(_ctx), \
|
||||
_safe = (_device) ? ratbagd_device_next(_device) : NULL; \
|
||||
(_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
|
||||
*/
|
||||
|
||||
struct ratbagd {
|
||||
sd_event *event;
|
||||
struct ratbag *lib_ctx;
|
||||
struct udev_monitor *monitor;
|
||||
sd_event_source *timeout_source;
|
||||
sd_event_source *monitor_source;
|
||||
sd_bus *bus;
|
||||
|
||||
RBTree device_map;
|
||||
size_t n_devices;
|
||||
|
||||
const char **themes; /* NULL-terminated */
|
||||
};
|
||||
|
||||
typedef void (*ratbagd_callback_t)(void *userdata);
|
||||
|
||||
void ratbagd_schedule_task(struct ratbagd *ctx,
|
||||
ratbagd_callback_t callback,
|
||||
void *userdata);
|
||||